tinymce.js 1.1 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799238002380123802238032380423805238062380723808238092381023811238122381323814238152381623817238182381923820238212382223823238242382523826238272382823829238302383123832238332383423835238362383723838238392384023841238422384323844238452384623847238482384923850238512385223853238542385523856238572385823859238602386123862238632386423865238662386723868238692387023871238722387323874238752387623877238782387923880238812388223883238842388523886238872388823889238902389123892238932389423895238962389723898238992390023901239022390323904239052390623907239082390923910239112391223913239142391523916239172391823919239202392123922239232392423925239262392723928239292393023931239322393323934239352393623937239382393923940239412394223943239442394523946239472394823949239502395123952239532395423955239562395723958239592396023961239622396323964239652396623967239682396923970239712397223973239742397523976239772397823979239802398123982239832398423985239862398723988239892399023991239922399323994239952399623997239982399924000240012400224003240042400524006240072400824009240102401124012240132401424015240162401724018240192402024021240222402324024240252402624027240282402924030240312403224033240342403524036240372403824039240402404124042240432404424045240462404724048240492405024051240522405324054240552405624057240582405924060240612406224063240642406524066240672406824069240702407124072240732407424075240762407724078240792408024081240822408324084240852408624087240882408924090240912409224093240942409524096240972409824099241002410124102241032410424105241062410724108241092411024111241122411324114241152411624117241182411924120241212412224123241242412524126241272412824129241302413124132241332413424135241362413724138241392414024141241422414324144241452414624147241482414924150241512415224153241542415524156241572415824159241602416124162241632416424165241662416724168241692417024171241722417324174241752417624177241782417924180241812418224183241842418524186241872418824189241902419124192241932419424195241962419724198241992420024201242022420324204242052420624207242082420924210242112421224213242142421524216242172421824219242202422124222242232422424225242262422724228242292423024231242322423324234242352423624237242382423924240242412424224243242442424524246242472424824249242502425124252242532425424255242562425724258242592426024261242622426324264242652426624267242682426924270242712427224273242742427524276242772427824279242802428124282242832428424285242862428724288242892429024291242922429324294242952429624297242982429924300243012430224303243042430524306243072430824309243102431124312243132431424315243162431724318243192432024321243222432324324243252432624327243282432924330243312433224333243342433524336243372433824339243402434124342243432434424345243462434724348243492435024351243522435324354243552435624357243582435924360243612436224363243642436524366243672436824369243702437124372243732437424375243762437724378243792438024381243822438324384243852438624387243882438924390243912439224393243942439524396243972439824399244002440124402244032440424405244062440724408244092441024411244122441324414244152441624417244182441924420244212442224423244242442524426244272442824429244302443124432244332443424435244362443724438244392444024441244422444324444244452444624447244482444924450244512445224453244542445524456244572445824459244602446124462244632446424465244662446724468244692447024471244722447324474244752447624477244782447924480244812448224483244842448524486244872448824489244902449124492244932449424495244962449724498244992450024501245022450324504245052450624507245082450924510245112451224513245142451524516245172451824519245202452124522245232452424525245262452724528245292453024531245322453324534245352453624537245382453924540245412454224543245442454524546245472454824549245502455124552245532455424555245562455724558245592456024561245622456324564245652456624567245682456924570245712457224573245742457524576245772457824579245802458124582245832458424585245862458724588245892459024591245922459324594245952459624597245982459924600246012460224603246042460524606246072460824609246102461124612246132461424615246162461724618246192462024621246222462324624246252462624627246282462924630246312463224633246342463524636246372463824639246402464124642246432464424645246462464724648246492465024651246522465324654246552465624657246582465924660246612466224663246642466524666246672466824669246702467124672246732467424675246762467724678246792468024681246822468324684246852468624687246882468924690246912469224693246942469524696246972469824699247002470124702247032470424705247062470724708247092471024711247122471324714247152471624717247182471924720247212472224723247242472524726247272472824729247302473124732247332473424735247362473724738247392474024741247422474324744247452474624747247482474924750247512475224753247542475524756247572475824759247602476124762247632476424765247662476724768247692477024771247722477324774247752477624777247782477924780247812478224783247842478524786247872478824789247902479124792247932479424795247962479724798247992480024801248022480324804248052480624807248082480924810248112481224813248142481524816248172481824819248202482124822248232482424825248262482724828248292483024831248322483324834248352483624837248382483924840248412484224843248442484524846248472484824849248502485124852248532485424855248562485724858248592486024861248622486324864248652486624867248682486924870248712487224873248742487524876248772487824879248802488124882248832488424885248862488724888248892489024891248922489324894248952489624897248982489924900249012490224903249042490524906249072490824909249102491124912249132491424915249162491724918249192492024921249222492324924249252492624927249282492924930249312493224933249342493524936249372493824939249402494124942249432494424945249462494724948249492495024951249522495324954249552495624957249582495924960249612496224963249642496524966249672496824969249702497124972249732497424975249762497724978249792498024981249822498324984249852498624987249882498924990249912499224993249942499524996249972499824999250002500125002250032500425005250062500725008250092501025011250122501325014250152501625017250182501925020250212502225023250242502525026250272502825029250302503125032250332503425035250362503725038250392504025041250422504325044250452504625047250482504925050250512505225053250542505525056250572505825059250602506125062250632506425065250662506725068250692507025071250722507325074250752507625077250782507925080250812508225083250842508525086250872508825089250902509125092250932509425095250962509725098250992510025101251022510325104251052510625107251082510925110251112511225113251142511525116251172511825119251202512125122251232512425125251262512725128251292513025131251322513325134251352513625137251382513925140251412514225143251442514525146251472514825149251502515125152251532515425155251562515725158251592516025161251622516325164251652516625167251682516925170251712517225173251742517525176251772517825179251802518125182251832518425185251862518725188251892519025191251922519325194251952519625197251982519925200252012520225203252042520525206252072520825209252102521125212252132521425215252162521725218252192522025221252222522325224252252522625227252282522925230252312523225233252342523525236252372523825239252402524125242252432524425245252462524725248252492525025251252522525325254252552525625257252582525925260252612526225263252642526525266252672526825269252702527125272252732527425275252762527725278252792528025281252822528325284252852528625287252882528925290252912529225293252942529525296252972529825299253002530125302253032530425305253062530725308253092531025311253122531325314253152531625317253182531925320253212532225323253242532525326253272532825329253302533125332253332533425335253362533725338253392534025341253422534325344253452534625347253482534925350253512535225353253542535525356253572535825359253602536125362253632536425365253662536725368253692537025371253722537325374253752537625377253782537925380253812538225383253842538525386253872538825389253902539125392253932539425395253962539725398253992540025401254022540325404254052540625407254082540925410254112541225413254142541525416254172541825419254202542125422254232542425425254262542725428254292543025431254322543325434254352543625437254382543925440254412544225443254442544525446254472544825449254502545125452254532545425455254562545725458254592546025461254622546325464254652546625467254682546925470254712547225473254742547525476254772547825479254802548125482254832548425485254862548725488254892549025491254922549325494254952549625497254982549925500255012550225503255042550525506255072550825509255102551125512255132551425515255162551725518255192552025521255222552325524255252552625527255282552925530255312553225533255342553525536255372553825539255402554125542255432554425545255462554725548255492555025551255522555325554255552555625557255582555925560255612556225563255642556525566255672556825569255702557125572255732557425575255762557725578255792558025581255822558325584255852558625587255882558925590255912559225593255942559525596255972559825599256002560125602256032560425605256062560725608256092561025611256122561325614256152561625617256182561925620256212562225623256242562525626256272562825629256302563125632256332563425635256362563725638256392564025641256422564325644256452564625647256482564925650256512565225653256542565525656256572565825659256602566125662256632566425665256662566725668256692567025671256722567325674256752567625677256782567925680256812568225683256842568525686256872568825689256902569125692256932569425695256962569725698256992570025701257022570325704257052570625707257082570925710257112571225713257142571525716257172571825719257202572125722257232572425725257262572725728257292573025731257322573325734257352573625737257382573925740257412574225743257442574525746257472574825749257502575125752257532575425755257562575725758257592576025761257622576325764257652576625767257682576925770257712577225773257742577525776257772577825779257802578125782257832578425785257862578725788257892579025791257922579325794257952579625797257982579925800258012580225803258042580525806258072580825809258102581125812258132581425815258162581725818258192582025821258222582325824258252582625827258282582925830258312583225833258342583525836258372583825839258402584125842258432584425845258462584725848258492585025851258522585325854258552585625857258582585925860258612586225863258642586525866258672586825869258702587125872258732587425875258762587725878258792588025881258822588325884258852588625887258882588925890258912589225893258942589525896258972589825899259002590125902259032590425905259062590725908259092591025911259122591325914259152591625917259182591925920259212592225923259242592525926259272592825929259302593125932259332593425935259362593725938259392594025941259422594325944259452594625947259482594925950259512595225953259542595525956259572595825959259602596125962259632596425965259662596725968259692597025971259722597325974259752597625977259782597925980259812598225983259842598525986259872598825989259902599125992259932599425995259962599725998259992600026001260022600326004260052600626007260082600926010260112601226013260142601526016260172601826019260202602126022260232602426025260262602726028260292603026031260322603326034260352603626037260382603926040260412604226043260442604526046260472604826049260502605126052260532605426055260562605726058260592606026061260622606326064260652606626067260682606926070260712607226073260742607526076260772607826079260802608126082260832608426085260862608726088260892609026091260922609326094260952609626097260982609926100261012610226103261042610526106261072610826109261102611126112261132611426115261162611726118261192612026121261222612326124261252612626127261282612926130261312613226133261342613526136261372613826139261402614126142261432614426145261462614726148261492615026151261522615326154261552615626157261582615926160261612616226163261642616526166261672616826169261702617126172261732617426175261762617726178261792618026181261822618326184261852618626187261882618926190261912619226193261942619526196261972619826199262002620126202262032620426205262062620726208262092621026211262122621326214262152621626217262182621926220262212622226223262242622526226262272622826229262302623126232262332623426235262362623726238262392624026241262422624326244262452624626247262482624926250262512625226253262542625526256262572625826259262602626126262262632626426265262662626726268262692627026271262722627326274262752627626277262782627926280262812628226283262842628526286262872628826289262902629126292262932629426295262962629726298262992630026301263022630326304263052630626307263082630926310263112631226313263142631526316263172631826319263202632126322263232632426325263262632726328263292633026331263322633326334263352633626337263382633926340263412634226343263442634526346263472634826349263502635126352263532635426355263562635726358263592636026361263622636326364263652636626367263682636926370263712637226373263742637526376263772637826379263802638126382263832638426385263862638726388263892639026391263922639326394263952639626397263982639926400264012640226403264042640526406264072640826409264102641126412264132641426415264162641726418264192642026421264222642326424264252642626427264282642926430264312643226433264342643526436264372643826439264402644126442264432644426445264462644726448264492645026451264522645326454264552645626457264582645926460264612646226463264642646526466264672646826469264702647126472264732647426475264762647726478264792648026481264822648326484264852648626487264882648926490264912649226493264942649526496264972649826499265002650126502265032650426505265062650726508265092651026511265122651326514265152651626517265182651926520265212652226523265242652526526265272652826529265302653126532265332653426535265362653726538265392654026541265422654326544265452654626547265482654926550265512655226553265542655526556265572655826559265602656126562265632656426565265662656726568265692657026571265722657326574265752657626577265782657926580265812658226583265842658526586265872658826589265902659126592265932659426595265962659726598265992660026601266022660326604266052660626607266082660926610266112661226613266142661526616266172661826619266202662126622266232662426625266262662726628266292663026631266322663326634266352663626637266382663926640266412664226643266442664526646266472664826649266502665126652266532665426655266562665726658266592666026661266622666326664266652666626667266682666926670266712667226673266742667526676266772667826679266802668126682266832668426685266862668726688266892669026691266922669326694266952669626697266982669926700267012670226703267042670526706267072670826709267102671126712267132671426715267162671726718267192672026721267222672326724267252672626727267282672926730267312673226733267342673526736267372673826739267402674126742267432674426745267462674726748267492675026751267522675326754267552675626757267582675926760267612676226763267642676526766267672676826769267702677126772267732677426775267762677726778267792678026781267822678326784267852678626787267882678926790267912679226793267942679526796267972679826799268002680126802268032680426805268062680726808268092681026811268122681326814268152681626817268182681926820268212682226823268242682526826268272682826829268302683126832268332683426835268362683726838268392684026841268422684326844268452684626847268482684926850268512685226853268542685526856268572685826859268602686126862268632686426865268662686726868268692687026871268722687326874268752687626877268782687926880268812688226883268842688526886268872688826889268902689126892268932689426895268962689726898268992690026901269022690326904269052690626907269082690926910269112691226913269142691526916269172691826919269202692126922269232692426925269262692726928269292693026931269322693326934269352693626937269382693926940269412694226943269442694526946269472694826949269502695126952269532695426955269562695726958269592696026961269622696326964269652696626967269682696926970269712697226973269742697526976269772697826979269802698126982269832698426985269862698726988269892699026991269922699326994269952699626997269982699927000270012700227003270042700527006270072700827009270102701127012270132701427015270162701727018270192702027021270222702327024270252702627027270282702927030270312703227033270342703527036270372703827039270402704127042270432704427045270462704727048270492705027051270522705327054270552705627057270582705927060270612706227063270642706527066270672706827069270702707127072270732707427075270762707727078270792708027081270822708327084270852708627087270882708927090270912709227093270942709527096270972709827099271002710127102271032710427105271062710727108271092711027111271122711327114271152711627117271182711927120271212712227123271242712527126271272712827129271302713127132271332713427135271362713727138271392714027141271422714327144271452714627147271482714927150271512715227153271542715527156271572715827159271602716127162271632716427165271662716727168271692717027171271722717327174271752717627177271782717927180271812718227183271842718527186271872718827189271902719127192271932719427195271962719727198271992720027201272022720327204272052720627207272082720927210272112721227213272142721527216272172721827219272202722127222272232722427225272262722727228272292723027231272322723327234272352723627237272382723927240272412724227243272442724527246272472724827249272502725127252272532725427255272562725727258272592726027261272622726327264272652726627267272682726927270272712727227273272742727527276272772727827279272802728127282272832728427285272862728727288272892729027291272922729327294272952729627297272982729927300273012730227303273042730527306273072730827309273102731127312273132731427315273162731727318273192732027321273222732327324273252732627327273282732927330273312733227333273342733527336273372733827339273402734127342273432734427345273462734727348273492735027351273522735327354273552735627357273582735927360273612736227363273642736527366273672736827369273702737127372273732737427375273762737727378273792738027381273822738327384273852738627387273882738927390273912739227393273942739527396273972739827399274002740127402274032740427405274062740727408274092741027411274122741327414274152741627417274182741927420274212742227423274242742527426274272742827429274302743127432274332743427435274362743727438274392744027441274422744327444274452744627447274482744927450274512745227453274542745527456274572745827459274602746127462274632746427465274662746727468274692747027471274722747327474274752747627477274782747927480274812748227483274842748527486274872748827489274902749127492274932749427495274962749727498274992750027501275022750327504275052750627507275082750927510275112751227513275142751527516275172751827519275202752127522275232752427525275262752727528275292753027531275322753327534275352753627537275382753927540275412754227543275442754527546275472754827549275502755127552275532755427555275562755727558275592756027561275622756327564275652756627567275682756927570275712757227573275742757527576275772757827579275802758127582275832758427585275862758727588275892759027591275922759327594275952759627597275982759927600276012760227603276042760527606276072760827609276102761127612276132761427615276162761727618276192762027621276222762327624276252762627627276282762927630276312763227633276342763527636276372763827639276402764127642276432764427645276462764727648276492765027651276522765327654276552765627657276582765927660276612766227663276642766527666276672766827669276702767127672276732767427675276762767727678276792768027681276822768327684276852768627687276882768927690276912769227693276942769527696276972769827699277002770127702277032770427705277062770727708277092771027711277122771327714277152771627717277182771927720277212772227723277242772527726277272772827729277302773127732277332773427735277362773727738277392774027741277422774327744277452774627747277482774927750277512775227753277542775527756277572775827759277602776127762277632776427765277662776727768277692777027771277722777327774277752777627777277782777927780277812778227783277842778527786277872778827789277902779127792277932779427795277962779727798277992780027801278022780327804278052780627807278082780927810278112781227813278142781527816278172781827819278202782127822278232782427825278262782727828278292783027831278322783327834278352783627837278382783927840278412784227843278442784527846278472784827849278502785127852278532785427855278562785727858278592786027861278622786327864278652786627867278682786927870278712787227873278742787527876278772787827879278802788127882278832788427885278862788727888278892789027891278922789327894278952789627897278982789927900279012790227903279042790527906279072790827909279102791127912279132791427915279162791727918279192792027921279222792327924279252792627927279282792927930279312793227933279342793527936279372793827939279402794127942279432794427945279462794727948279492795027951279522795327954279552795627957279582795927960279612796227963279642796527966279672796827969279702797127972279732797427975279762797727978279792798027981279822798327984279852798627987279882798927990279912799227993279942799527996279972799827999280002800128002280032800428005280062800728008280092801028011280122801328014280152801628017280182801928020280212802228023280242802528026280272802828029280302803128032280332803428035280362803728038280392804028041280422804328044280452804628047280482804928050280512805228053280542805528056280572805828059280602806128062280632806428065280662806728068280692807028071280722807328074280752807628077280782807928080280812808228083280842808528086280872808828089280902809128092280932809428095280962809728098280992810028101281022810328104281052810628107281082810928110281112811228113281142811528116281172811828119281202812128122281232812428125281262812728128281292813028131281322813328134281352813628137281382813928140281412814228143281442814528146281472814828149281502815128152281532815428155281562815728158281592816028161281622816328164281652816628167281682816928170281712817228173281742817528176281772817828179281802818128182281832818428185281862818728188281892819028191281922819328194281952819628197281982819928200282012820228203282042820528206282072820828209282102821128212282132821428215282162821728218282192822028221282222822328224282252822628227282282822928230282312823228233282342823528236282372823828239282402824128242282432824428245282462824728248282492825028251282522825328254282552825628257282582825928260282612826228263282642826528266282672826828269282702827128272282732827428275282762827728278282792828028281282822828328284282852828628287282882828928290282912829228293282942829528296282972829828299283002830128302283032830428305283062830728308283092831028311283122831328314283152831628317283182831928320283212832228323283242832528326283272832828329283302833128332283332833428335283362833728338283392834028341283422834328344283452834628347283482834928350283512835228353283542835528356283572835828359283602836128362283632836428365283662836728368283692837028371283722837328374283752837628377283782837928380283812838228383283842838528386283872838828389283902839128392283932839428395283962839728398283992840028401284022840328404284052840628407284082840928410284112841228413284142841528416284172841828419284202842128422284232842428425284262842728428284292843028431284322843328434284352843628437284382843928440284412844228443284442844528446284472844828449284502845128452284532845428455284562845728458284592846028461284622846328464284652846628467284682846928470284712847228473284742847528476284772847828479284802848128482284832848428485284862848728488284892849028491284922849328494284952849628497284982849928500285012850228503285042850528506285072850828509285102851128512285132851428515285162851728518285192852028521285222852328524285252852628527285282852928530285312853228533285342853528536285372853828539285402854128542285432854428545285462854728548285492855028551285522855328554285552855628557285582855928560285612856228563285642856528566285672856828569285702857128572285732857428575285762857728578285792858028581285822858328584285852858628587285882858928590285912859228593285942859528596285972859828599286002860128602286032860428605286062860728608286092861028611286122861328614286152861628617286182861928620286212862228623286242862528626286272862828629286302863128632286332863428635286362863728638286392864028641286422864328644286452864628647286482864928650286512865228653286542865528656286572865828659286602866128662286632866428665286662866728668286692867028671286722867328674286752867628677286782867928680286812868228683286842868528686286872868828689286902869128692286932869428695286962869728698286992870028701287022870328704287052870628707287082870928710287112871228713287142871528716287172871828719287202872128722287232872428725287262872728728287292873028731287322873328734287352873628737287382873928740287412874228743287442874528746287472874828749287502875128752287532875428755287562875728758287592876028761287622876328764287652876628767287682876928770287712877228773287742877528776287772877828779287802878128782287832878428785287862878728788287892879028791287922879328794287952879628797287982879928800288012880228803288042880528806288072880828809288102881128812288132881428815288162881728818288192882028821288222882328824288252882628827288282882928830288312883228833288342883528836288372883828839288402884128842288432884428845288462884728848288492885028851288522885328854288552885628857288582885928860288612886228863288642886528866288672886828869288702887128872288732887428875288762887728878288792888028881288822888328884288852888628887288882888928890288912889228893288942889528896288972889828899289002890128902289032890428905289062890728908289092891028911289122891328914289152891628917289182891928920289212892228923289242892528926289272892828929289302893128932289332893428935289362893728938289392894028941289422894328944289452894628947289482894928950289512895228953289542895528956289572895828959289602896128962289632896428965289662896728968289692897028971289722897328974289752897628977289782897928980289812898228983289842898528986289872898828989289902899128992289932899428995289962899728998289992900029001290022900329004290052900629007290082900929010290112901229013290142901529016290172901829019290202902129022290232902429025290262902729028290292903029031290322903329034290352903629037290382903929040290412904229043290442904529046290472904829049290502905129052290532905429055290562905729058290592906029061290622906329064290652906629067290682906929070290712907229073290742907529076290772907829079290802908129082290832908429085290862908729088290892909029091290922909329094290952909629097290982909929100291012910229103291042910529106291072910829109291102911129112291132911429115291162911729118291192912029121291222912329124291252912629127291282912929130291312913229133291342913529136291372913829139291402914129142291432914429145291462914729148291492915029151291522915329154291552915629157291582915929160291612916229163291642916529166291672916829169291702917129172291732917429175291762917729178291792918029181291822918329184291852918629187291882918929190291912919229193291942919529196291972919829199292002920129202292032920429205292062920729208292092921029211292122921329214292152921629217292182921929220292212922229223292242922529226292272922829229292302923129232292332923429235292362923729238292392924029241292422924329244292452924629247292482924929250292512925229253292542925529256292572925829259292602926129262292632926429265292662926729268292692927029271292722927329274292752927629277292782927929280292812928229283292842928529286292872928829289292902929129292292932929429295292962929729298292992930029301293022930329304293052930629307293082930929310293112931229313293142931529316293172931829319293202932129322293232932429325293262932729328293292933029331293322933329334293352933629337293382933929340293412934229343293442934529346293472934829349293502935129352293532935429355293562935729358293592936029361293622936329364293652936629367293682936929370293712937229373293742937529376293772937829379293802938129382293832938429385293862938729388293892939029391293922939329394293952939629397293982939929400294012940229403294042940529406294072940829409294102941129412294132941429415294162941729418294192942029421294222942329424294252942629427294282942929430294312943229433294342943529436294372943829439294402944129442294432944429445294462944729448294492945029451294522945329454294552945629457294582945929460294612946229463294642946529466294672946829469294702947129472294732947429475294762947729478294792948029481294822948329484294852948629487294882948929490294912949229493294942949529496294972949829499295002950129502295032950429505295062950729508295092951029511295122951329514295152951629517295182951929520295212952229523295242952529526295272952829529295302953129532295332953429535295362953729538295392954029541295422954329544295452954629547295482954929550295512955229553295542955529556295572955829559295602956129562295632956429565295662956729568295692957029571295722957329574295752957629577295782957929580295812958229583295842958529586295872958829589295902959129592295932959429595295962959729598295992960029601296022960329604296052960629607296082960929610296112961229613296142961529616296172961829619296202962129622296232962429625296262962729628296292963029631296322963329634296352963629637296382963929640296412964229643296442964529646296472964829649296502965129652296532965429655296562965729658296592966029661296622966329664296652966629667296682966929670296712967229673296742967529676296772967829679296802968129682296832968429685296862968729688296892969029691296922969329694296952969629697296982969929700297012970229703297042970529706297072970829709297102971129712297132971429715297162971729718297192972029721297222972329724297252972629727297282972929730297312973229733297342973529736297372973829739297402974129742297432974429745297462974729748297492975029751297522975329754297552975629757297582975929760297612976229763297642976529766297672976829769297702977129772297732977429775297762977729778297792978029781297822978329784297852978629787297882978929790297912979229793297942979529796297972979829799298002980129802298032980429805298062980729808298092981029811298122981329814298152981629817298182981929820298212982229823298242982529826298272982829829298302983129832298332983429835298362983729838298392984029841298422984329844298452984629847298482984929850298512985229853298542985529856298572985829859298602986129862298632986429865298662986729868298692987029871298722987329874298752987629877298782987929880298812988229883298842988529886298872988829889298902989129892298932989429895298962989729898298992990029901299022990329904299052990629907299082990929910299112991229913299142991529916299172991829919299202992129922299232992429925299262992729928299292993029931299322993329934299352993629937299382993929940299412994229943299442994529946299472994829949299502995129952299532995429955299562995729958299592996029961299622996329964299652996629967299682996929970299712997229973299742997529976299772997829979299802998129982299832998429985299862998729988299892999029991299922999329994299952999629997299982999930000300013000230003300043000530006300073000830009300103001130012300133001430015300163001730018300193002030021300223002330024300253002630027300283002930030300313003230033300343003530036300373003830039300403004130042300433004430045300463004730048300493005030051300523005330054300553005630057300583005930060300613006230063300643006530066300673006830069300703007130072300733007430075300763007730078300793008030081300823008330084300853008630087300883008930090300913009230093300943009530096300973009830099301003010130102301033010430105301063010730108301093011030111301123011330114301153011630117301183011930120301213012230123301243012530126301273012830129301303013130132301333013430135301363013730138301393014030141301423014330144301453014630147301483014930150301513015230153301543015530156301573015830159301603016130162301633016430165301663016730168301693017030171301723017330174301753017630177301783017930180301813018230183301843018530186301873018830189301903019130192301933019430195301963019730198301993020030201302023020330204302053020630207302083020930210302113021230213302143021530216302173021830219302203022130222302233022430225302263022730228302293023030231302323023330234302353023630237302383023930240302413024230243302443024530246302473024830249302503025130252302533025430255302563025730258302593026030261302623026330264302653026630267302683026930270302713027230273302743027530276302773027830279302803028130282302833028430285302863028730288302893029030291302923029330294302953029630297302983029930300303013030230303303043030530306303073030830309303103031130312303133031430315303163031730318303193032030321303223032330324303253032630327303283032930330303313033230333303343033530336303373033830339303403034130342303433034430345303463034730348303493035030351303523035330354303553035630357303583035930360303613036230363303643036530366303673036830369303703037130372303733037430375303763037730378303793038030381303823038330384303853038630387303883038930390303913039230393303943039530396303973039830399304003040130402304033040430405304063040730408304093041030411304123041330414304153041630417304183041930420304213042230423304243042530426304273042830429304303043130432304333043430435304363043730438304393044030441304423044330444304453044630447304483044930450304513045230453304543045530456304573045830459304603046130462304633046430465304663046730468304693047030471304723047330474304753047630477304783047930480304813048230483304843048530486304873048830489304903049130492304933049430495304963049730498304993050030501305023050330504305053050630507305083050930510305113051230513305143051530516305173051830519305203052130522305233052430525305263052730528305293053030531305323053330534305353053630537305383053930540305413054230543305443054530546305473054830549305503055130552305533055430555305563055730558305593056030561305623056330564305653056630567305683056930570305713057230573305743057530576305773057830579305803058130582305833058430585305863058730588305893059030591305923059330594305953059630597305983059930600306013060230603306043060530606306073060830609306103061130612306133061430615306163061730618306193062030621306223062330624306253062630627306283062930630306313063230633306343063530636306373063830639306403064130642306433064430645306463064730648306493065030651306523065330654306553065630657306583065930660306613066230663306643066530666306673066830669306703067130672306733067430675306763067730678306793068030681306823068330684306853068630687306883068930690306913069230693306943069530696306973069830699307003070130702307033070430705307063070730708307093071030711307123071330714307153071630717307183071930720307213072230723307243072530726307273072830729307303073130732307333073430735307363073730738307393074030741307423074330744307453074630747307483074930750307513075230753307543075530756307573075830759307603076130762307633076430765307663076730768307693077030771307723077330774307753077630777307783077930780307813078230783307843078530786307873078830789307903079130792307933079430795307963079730798307993080030801308023080330804308053080630807308083080930810308113081230813308143081530816308173081830819308203082130822308233082430825308263082730828308293083030831308323083330834308353083630837308383083930840308413084230843308443084530846308473084830849308503085130852308533085430855308563085730858308593086030861308623086330864308653086630867308683086930870308713087230873308743087530876308773087830879308803088130882308833088430885308863088730888308893089030891308923089330894308953089630897308983089930900309013090230903309043090530906309073090830909309103091130912309133091430915309163091730918309193092030921309223092330924309253092630927309283092930930309313093230933309343093530936309373093830939309403094130942309433094430945309463094730948309493095030951309523095330954309553095630957309583095930960309613096230963309643096530966309673096830969309703097130972309733097430975309763097730978309793098030981309823098330984309853098630987309883098930990309913099230993309943099530996309973099830999310003100131002310033100431005310063100731008310093101031011310123101331014310153101631017310183101931020310213102231023310243102531026310273102831029310303103131032310333103431035310363103731038310393104031041310423104331044310453104631047310483104931050310513105231053310543105531056310573105831059310603106131062310633106431065310663106731068310693107031071310723107331074310753107631077310783107931080310813108231083310843108531086310873108831089310903109131092310933109431095310963109731098310993110031101311023110331104311053110631107311083110931110311113111231113311143111531116311173111831119311203112131122311233112431125311263112731128311293113031131311323113331134311353113631137311383113931140311413114231143311443114531146311473114831149311503115131152311533115431155311563115731158311593116031161311623116331164311653116631167311683116931170311713117231173311743117531176311773117831179311803118131182311833118431185311863118731188311893119031191311923119331194311953119631197311983119931200312013120231203312043120531206312073120831209312103121131212312133121431215312163121731218312193122031221312223122331224312253122631227312283122931230312313123231233312343123531236312373123831239312403124131242312433124431245312463124731248312493125031251312523125331254312553125631257312583125931260312613126231263312643126531266312673126831269312703127131272312733127431275312763127731278312793128031281312823128331284312853128631287312883128931290312913129231293312943129531296312973129831299313003130131302313033130431305313063130731308313093131031311313123131331314313153131631317313183131931320313213132231323313243132531326313273132831329313303133131332313333133431335313363133731338313393134031341313423134331344313453134631347313483134931350313513135231353313543135531356313573135831359313603136131362313633136431365313663136731368313693137031371313723137331374313753137631377313783137931380313813138231383313843138531386313873138831389313903139131392313933139431395313963139731398313993140031401314023140331404314053140631407314083140931410314113141231413314143141531416314173141831419314203142131422314233142431425314263142731428314293143031431314323143331434314353143631437314383143931440314413144231443314443144531446314473144831449314503145131452314533145431455314563145731458314593146031461314623146331464314653146631467314683146931470314713147231473314743147531476314773147831479314803148131482314833148431485314863148731488314893149031491314923149331494314953149631497314983149931500315013150231503315043150531506315073150831509315103151131512315133151431515315163151731518315193152031521315223152331524315253152631527315283152931530315313153231533315343153531536315373153831539315403154131542315433154431545315463154731548315493155031551315523155331554315553155631557315583155931560315613156231563315643156531566315673156831569315703157131572315733157431575315763157731578315793158031581315823158331584315853158631587315883158931590315913159231593315943159531596315973159831599316003160131602316033160431605316063160731608316093161031611316123161331614316153161631617316183161931620316213162231623316243162531626316273162831629316303163131632316333163431635316363163731638316393164031641316423164331644316453164631647316483164931650316513165231653316543165531656316573165831659316603166131662316633166431665316663166731668316693167031671316723167331674316753167631677316783167931680316813168231683316843168531686316873168831689316903169131692316933169431695316963169731698316993170031701317023170331704317053170631707317083170931710317113171231713317143171531716317173171831719317203172131722317233172431725317263172731728317293173031731317323173331734317353173631737317383173931740317413174231743317443174531746317473174831749317503175131752317533175431755317563175731758317593176031761317623176331764317653176631767317683176931770317713177231773317743177531776317773177831779317803178131782317833178431785317863178731788317893179031791317923179331794317953179631797317983179931800318013180231803318043180531806318073180831809318103181131812318133181431815318163181731818318193182031821318223182331824318253182631827318283182931830318313183231833318343183531836318373183831839318403184131842318433184431845318463184731848318493185031851318523185331854318553185631857318583185931860318613186231863318643186531866318673186831869318703187131872318733187431875318763187731878318793188031881318823188331884318853188631887318883188931890318913189231893318943189531896318973189831899319003190131902319033190431905319063190731908319093191031911319123191331914319153191631917319183191931920319213192231923319243192531926319273192831929319303193131932319333193431935319363193731938319393194031941319423194331944319453194631947319483194931950319513195231953319543195531956319573195831959319603196131962319633196431965319663196731968319693197031971319723197331974319753197631977319783197931980319813198231983319843198531986319873198831989319903199131992319933199431995319963199731998319993200032001320023200332004320053200632007320083200932010320113201232013320143201532016320173201832019320203202132022320233202432025320263202732028320293203032031320323203332034320353203632037320383203932040320413204232043320443204532046320473204832049320503205132052320533205432055320563205732058320593206032061320623206332064320653206632067320683206932070320713207232073320743207532076320773207832079320803208132082320833208432085320863208732088320893209032091320923209332094320953209632097320983209932100321013210232103321043210532106321073210832109321103211132112321133211432115321163211732118321193212032121321223212332124321253212632127321283212932130321313213232133321343213532136321373213832139321403214132142321433214432145321463214732148321493215032151321523215332154321553215632157321583215932160321613216232163321643216532166321673216832169321703217132172321733217432175321763217732178321793218032181321823218332184321853218632187321883218932190321913219232193321943219532196321973219832199322003220132202322033220432205322063220732208322093221032211322123221332214322153221632217322183221932220322213222232223322243222532226322273222832229322303223132232322333223432235322363223732238322393224032241322423224332244322453224632247322483224932250322513225232253322543225532256322573225832259322603226132262322633226432265322663226732268322693227032271322723227332274322753227632277322783227932280322813228232283322843228532286322873228832289322903229132292322933229432295322963229732298322993230032301323023230332304323053230632307323083230932310323113231232313323143231532316323173231832319323203232132322323233232432325323263232732328323293233032331323323233332334323353233632337323383233932340323413234232343323443234532346323473234832349323503235132352323533235432355323563235732358323593236032361323623236332364323653236632367323683236932370323713237232373323743237532376323773237832379323803238132382323833238432385323863238732388323893239032391323923239332394323953239632397323983239932400324013240232403324043240532406324073240832409324103241132412324133241432415324163241732418324193242032421324223242332424324253242632427324283242932430324313243232433324343243532436324373243832439324403244132442324433244432445324463244732448324493245032451324523245332454324553245632457324583245932460324613246232463324643246532466324673246832469324703247132472324733247432475324763247732478324793248032481324823248332484324853248632487324883248932490324913249232493324943249532496324973249832499325003250132502325033250432505325063250732508325093251032511325123251332514325153251632517325183251932520325213252232523325243252532526325273252832529325303253132532325333253432535325363253732538325393254032541325423254332544325453254632547325483254932550325513255232553325543255532556325573255832559325603256132562325633256432565325663256732568325693257032571325723257332574325753257632577325783257932580325813258232583325843258532586325873258832589325903259132592325933259432595325963259732598325993260032601326023260332604326053260632607326083260932610326113261232613326143261532616326173261832619326203262132622326233262432625326263262732628326293263032631326323263332634326353263632637326383263932640326413264232643326443264532646326473264832649326503265132652326533265432655326563265732658326593266032661326623266332664326653266632667326683266932670326713267232673326743267532676326773267832679326803268132682326833268432685326863268732688326893269032691326923269332694326953269632697326983269932700327013270232703327043270532706327073270832709327103271132712327133271432715327163271732718327193272032721327223272332724327253272632727327283272932730327313273232733327343273532736327373273832739327403274132742327433274432745327463274732748327493275032751327523275332754327553275632757327583275932760327613276232763327643276532766327673276832769327703277132772327733277432775327763277732778327793278032781327823278332784327853278632787327883278932790327913279232793327943279532796327973279832799328003280132802328033280432805328063280732808328093281032811328123281332814328153281632817328183281932820328213282232823328243282532826328273282832829328303283132832328333283432835328363283732838328393284032841328423284332844328453284632847328483284932850328513285232853328543285532856328573285832859328603286132862328633286432865328663286732868328693287032871328723287332874328753287632877328783287932880328813288232883328843288532886328873288832889328903289132892328933289432895328963289732898328993290032901329023290332904329053290632907329083290932910329113291232913329143291532916329173291832919329203292132922329233292432925329263292732928329293293032931329323293332934329353293632937329383293932940329413294232943329443294532946329473294832949329503295132952329533295432955329563295732958329593296032961329623296332964329653296632967329683296932970329713297232973329743297532976329773297832979329803298132982329833298432985329863298732988329893299032991329923299332994329953299632997329983299933000330013300233003330043300533006330073300833009330103301133012330133301433015330163301733018330193302033021330223302333024330253302633027330283302933030330313303233033330343303533036330373303833039330403304133042330433304433045330463304733048330493305033051330523305333054330553305633057330583305933060330613306233063330643306533066330673306833069330703307133072330733307433075330763307733078330793308033081330823308333084330853308633087330883308933090330913309233093330943309533096330973309833099331003310133102331033310433105331063310733108331093311033111331123311333114331153311633117331183311933120331213312233123331243312533126331273312833129331303313133132331333313433135331363313733138331393314033141331423314333144331453314633147331483314933150331513315233153331543315533156331573315833159331603316133162331633316433165331663316733168331693317033171331723317333174331753317633177331783317933180331813318233183331843318533186331873318833189331903319133192331933319433195331963319733198331993320033201332023320333204332053320633207332083320933210332113321233213332143321533216332173321833219332203322133222332233322433225332263322733228332293323033231332323323333234332353323633237332383323933240332413324233243332443324533246332473324833249332503325133252332533325433255332563325733258332593326033261332623326333264332653326633267332683326933270332713327233273332743327533276332773327833279332803328133282332833328433285332863328733288332893329033291332923329333294332953329633297332983329933300333013330233303333043330533306333073330833309333103331133312333133331433315333163331733318333193332033321333223332333324333253332633327333283332933330333313333233333333343333533336333373333833339333403334133342333433334433345333463334733348333493335033351333523335333354333553335633357333583335933360333613336233363333643336533366333673336833369333703337133372333733337433375333763337733378333793338033381333823338333384333853338633387333883338933390333913339233393333943339533396333973339833399334003340133402334033340433405334063340733408334093341033411334123341333414334153341633417334183341933420334213342233423334243342533426334273342833429334303343133432334333343433435334363343733438334393344033441334423344333444334453344633447334483344933450334513345233453334543345533456334573345833459334603346133462334633346433465334663346733468334693347033471334723347333474334753347633477334783347933480334813348233483334843348533486334873348833489334903349133492334933349433495334963349733498334993350033501335023350333504335053350633507335083350933510335113351233513335143351533516335173351833519335203352133522335233352433525335263352733528335293353033531335323353333534335353353633537335383353933540335413354233543335443354533546335473354833549335503355133552335533355433555335563355733558335593356033561335623356333564335653356633567335683356933570335713357233573335743357533576335773357833579335803358133582335833358433585335863358733588335893359033591335923359333594335953359633597335983359933600336013360233603336043360533606336073360833609336103361133612336133361433615336163361733618336193362033621336223362333624336253362633627336283362933630336313363233633336343363533636336373363833639336403364133642336433364433645336463364733648336493365033651336523365333654336553365633657336583365933660336613366233663336643366533666336673366833669336703367133672336733367433675336763367733678336793368033681336823368333684336853368633687336883368933690336913369233693336943369533696336973369833699337003370133702337033370433705337063370733708337093371033711337123371333714337153371633717337183371933720337213372233723337243372533726337273372833729337303373133732337333373433735337363373733738337393374033741337423374333744337453374633747337483374933750337513375233753337543375533756337573375833759337603376133762337633376433765337663376733768337693377033771337723377333774337753377633777337783377933780337813378233783337843378533786337873378833789337903379133792337933379433795337963379733798337993380033801338023380333804338053380633807338083380933810338113381233813338143381533816338173381833819338203382133822338233382433825338263382733828338293383033831338323383333834338353383633837338383383933840338413384233843338443384533846338473384833849338503385133852338533385433855338563385733858338593386033861338623386333864338653386633867338683386933870338713387233873338743387533876338773387833879338803388133882338833388433885338863388733888338893389033891338923389333894338953389633897338983389933900339013390233903339043390533906339073390833909339103391133912339133391433915339163391733918339193392033921339223392333924339253392633927339283392933930339313393233933339343393533936339373393833939339403394133942339433394433945339463394733948339493395033951339523395333954339553395633957339583395933960339613396233963339643396533966339673396833969339703397133972339733397433975339763397733978339793398033981339823398333984339853398633987339883398933990339913399233993339943399533996339973399833999340003400134002340033400434005340063400734008340093401034011340123401334014340153401634017340183401934020340213402234023340243402534026340273402834029340303403134032340333403434035340363403734038340393404034041340423404334044340453404634047340483404934050340513405234053340543405534056340573405834059340603406134062340633406434065340663406734068340693407034071340723407334074340753407634077340783407934080340813408234083340843408534086340873408834089340903409134092340933409434095340963409734098340993410034101341023410334104341053410634107341083410934110341113411234113341143411534116341173411834119341203412134122341233412434125341263412734128341293413034131341323413334134341353413634137341383413934140341413414234143341443414534146341473414834149341503415134152341533415434155341563415734158341593416034161341623416334164341653416634167341683416934170341713417234173341743417534176341773417834179341803418134182341833418434185341863418734188341893419034191341923419334194341953419634197341983419934200342013420234203342043420534206342073420834209342103421134212342133421434215342163421734218342193422034221342223422334224342253422634227342283422934230342313423234233342343423534236342373423834239342403424134242342433424434245342463424734248342493425034251342523425334254342553425634257342583425934260342613426234263342643426534266342673426834269342703427134272342733427434275342763427734278342793428034281342823428334284342853428634287342883428934290342913429234293342943429534296342973429834299343003430134302343033430434305343063430734308343093431034311343123431334314343153431634317343183431934320343213432234323343243432534326343273432834329343303433134332343333433434335343363433734338343393434034341343423434334344343453434634347343483434934350343513435234353343543435534356343573435834359343603436134362343633436434365343663436734368343693437034371343723437334374343753437634377343783437934380343813438234383343843438534386343873438834389343903439134392343933439434395343963439734398343993440034401344023440334404344053440634407344083440934410344113441234413344143441534416344173441834419344203442134422344233442434425344263442734428344293443034431344323443334434344353443634437344383443934440344413444234443344443444534446344473444834449344503445134452344533445434455344563445734458344593446034461344623446334464344653446634467344683446934470344713447234473344743447534476344773447834479344803448134482344833448434485344863448734488344893449034491344923449334494344953449634497344983449934500345013450234503345043450534506345073450834509345103451134512345133451434515345163451734518345193452034521345223452334524345253452634527345283452934530345313453234533345343453534536345373453834539345403454134542345433454434545345463454734548345493455034551345523455334554345553455634557345583455934560345613456234563345643456534566345673456834569345703457134572345733457434575345763457734578345793458034581345823458334584345853458634587345883458934590345913459234593345943459534596345973459834599346003460134602346033460434605346063460734608346093461034611346123461334614346153461634617346183461934620346213462234623346243462534626346273462834629346303463134632346333463434635346363463734638346393464034641346423464334644346453464634647346483464934650346513465234653346543465534656346573465834659346603466134662346633466434665346663466734668346693467034671346723467334674346753467634677346783467934680346813468234683346843468534686346873468834689346903469134692346933469434695346963469734698346993470034701347023470334704347053470634707347083470934710347113471234713347143471534716347173471834719347203472134722347233472434725347263472734728347293473034731347323473334734347353473634737347383473934740347413474234743347443474534746347473474834749347503475134752347533475434755347563475734758347593476034761347623476334764347653476634767347683476934770347713477234773347743477534776347773477834779347803478134782347833478434785347863478734788347893479034791347923479334794347953479634797347983479934800348013480234803348043480534806348073480834809348103481134812348133481434815348163481734818348193482034821348223482334824348253482634827348283482934830348313483234833348343483534836348373483834839348403484134842348433484434845348463484734848348493485034851348523485334854348553485634857348583485934860348613486234863348643486534866348673486834869348703487134872348733487434875348763487734878348793488034881348823488334884348853488634887348883488934890348913489234893348943489534896348973489834899349003490134902349033490434905349063490734908349093491034911349123491334914349153491634917349183491934920349213492234923349243492534926349273492834929349303493134932349333493434935349363493734938349393494034941349423494334944349453494634947349483494934950349513495234953349543495534956349573495834959349603496134962349633496434965349663496734968349693497034971349723497334974349753497634977349783497934980349813498234983349843498534986349873498834989349903499134992349933499434995349963499734998349993500035001350023500335004350053500635007350083500935010350113501235013350143501535016350173501835019350203502135022350233502435025350263502735028350293503035031350323503335034350353503635037350383503935040350413504235043350443504535046350473504835049350503505135052350533505435055350563505735058350593506035061350623506335064350653506635067350683506935070350713507235073350743507535076350773507835079350803508135082350833508435085350863508735088350893509035091350923509335094350953509635097350983509935100351013510235103351043510535106351073510835109351103511135112351133511435115351163511735118351193512035121351223512335124351253512635127351283512935130351313513235133351343513535136351373513835139351403514135142351433514435145351463514735148351493515035151351523515335154351553515635157351583515935160351613516235163351643516535166351673516835169351703517135172351733517435175351763517735178351793518035181351823518335184351853518635187351883518935190351913519235193351943519535196351973519835199352003520135202352033520435205352063520735208352093521035211352123521335214352153521635217352183521935220352213522235223352243522535226352273522835229352303523135232352333523435235352363523735238352393524035241352423524335244352453524635247352483524935250352513525235253352543525535256352573525835259352603526135262352633526435265352663526735268352693527035271352723527335274352753527635277352783527935280352813528235283352843528535286352873528835289352903529135292352933529435295352963529735298352993530035301353023530335304353053530635307353083530935310353113531235313353143531535316353173531835319353203532135322353233532435325353263532735328353293533035331353323533335334353353533635337353383533935340353413534235343353443534535346353473534835349353503535135352353533535435355353563535735358353593536035361353623536335364353653536635367353683536935370353713537235373353743537535376353773537835379353803538135382353833538435385353863538735388353893539035391353923539335394353953539635397353983539935400354013540235403354043540535406354073540835409354103541135412354133541435415354163541735418354193542035421354223542335424354253542635427354283542935430354313543235433354343543535436354373543835439354403544135442354433544435445354463544735448354493545035451354523545335454354553545635457354583545935460354613546235463354643546535466354673546835469354703547135472354733547435475354763547735478354793548035481354823548335484354853548635487354883548935490354913549235493354943549535496354973549835499355003550135502355033550435505355063550735508355093551035511355123551335514355153551635517355183551935520355213552235523355243552535526355273552835529355303553135532355333553435535355363553735538355393554035541355423554335544355453554635547355483554935550355513555235553355543555535556355573555835559355603556135562355633556435565355663556735568355693557035571355723557335574355753557635577355783557935580355813558235583355843558535586355873558835589355903559135592355933559435595355963559735598355993560035601356023560335604356053560635607356083560935610356113561235613356143561535616356173561835619356203562135622356233562435625356263562735628356293563035631356323563335634356353563635637356383563935640356413564235643356443564535646356473564835649356503565135652356533565435655356563565735658356593566035661356623566335664356653566635667356683566935670356713567235673356743567535676356773567835679356803568135682356833568435685356863568735688356893569035691356923569335694356953569635697356983569935700357013570235703357043570535706357073570835709357103571135712357133571435715357163571735718357193572035721357223572335724357253572635727357283572935730357313573235733357343573535736357373573835739357403574135742357433574435745357463574735748357493575035751357523575335754357553575635757357583575935760357613576235763357643576535766357673576835769357703577135772357733577435775357763577735778357793578035781357823578335784357853578635787357883578935790357913579235793357943579535796357973579835799358003580135802358033580435805358063580735808358093581035811358123581335814358153581635817358183581935820358213582235823358243582535826358273582835829358303583135832358333583435835358363583735838358393584035841358423584335844358453584635847358483584935850358513585235853358543585535856358573585835859358603586135862358633586435865358663586735868358693587035871358723587335874358753587635877358783587935880358813588235883358843588535886358873588835889358903589135892358933589435895358963589735898358993590035901359023590335904359053590635907359083590935910359113591235913359143591535916359173591835919359203592135922359233592435925359263592735928359293593035931359323593335934359353593635937359383593935940359413594235943359443594535946359473594835949359503595135952359533595435955359563595735958359593596035961359623596335964359653596635967359683596935970359713597235973359743597535976359773597835979359803598135982359833598435985359863598735988359893599035991359923599335994359953599635997359983599936000360013600236003360043600536006360073600836009360103601136012360133601436015360163601736018360193602036021360223602336024360253602636027360283602936030360313603236033360343603536036360373603836039360403604136042360433604436045360463604736048360493605036051360523605336054360553605636057360583605936060360613606236063360643606536066360673606836069360703607136072360733607436075360763607736078360793608036081360823608336084360853608636087360883608936090360913609236093360943609536096360973609836099361003610136102361033610436105361063610736108361093611036111361123611336114361153611636117361183611936120361213612236123361243612536126361273612836129361303613136132361333613436135361363613736138361393614036141361423614336144361453614636147361483614936150361513615236153361543615536156361573615836159361603616136162361633616436165361663616736168361693617036171361723617336174361753617636177361783617936180361813618236183361843618536186361873618836189361903619136192361933619436195361963619736198361993620036201362023620336204362053620636207362083620936210362113621236213362143621536216362173621836219362203622136222362233622436225362263622736228362293623036231362323623336234362353623636237362383623936240362413624236243362443624536246362473624836249362503625136252362533625436255362563625736258362593626036261362623626336264362653626636267362683626936270362713627236273362743627536276362773627836279362803628136282362833628436285362863628736288362893629036291362923629336294362953629636297362983629936300363013630236303363043630536306363073630836309363103631136312363133631436315363163631736318363193632036321363223632336324363253632636327363283632936330363313633236333363343633536336363373633836339363403634136342363433634436345363463634736348363493635036351363523635336354363553635636357363583635936360363613636236363363643636536366363673636836369363703637136372363733637436375363763637736378363793638036381363823638336384363853638636387363883638936390363913639236393363943639536396363973639836399364003640136402364033640436405364063640736408364093641036411364123641336414364153641636417364183641936420364213642236423364243642536426364273642836429364303643136432364333643436435364363643736438364393644036441364423644336444364453644636447364483644936450364513645236453364543645536456364573645836459364603646136462364633646436465364663646736468364693647036471364723647336474364753647636477364783647936480364813648236483364843648536486364873648836489364903649136492364933649436495364963649736498364993650036501365023650336504365053650636507365083650936510365113651236513365143651536516365173651836519365203652136522365233652436525365263652736528365293653036531365323653336534365353653636537365383653936540365413654236543365443654536546365473654836549365503655136552365533655436555365563655736558365593656036561365623656336564365653656636567365683656936570365713657236573365743657536576365773657836579365803658136582365833658436585365863658736588365893659036591365923659336594365953659636597365983659936600366013660236603366043660536606366073660836609366103661136612366133661436615366163661736618366193662036621366223662336624366253662636627366283662936630366313663236633366343663536636366373663836639366403664136642366433664436645366463664736648366493665036651366523665336654366553665636657366583665936660366613666236663366643666536666366673666836669366703667136672366733667436675366763667736678366793668036681366823668336684366853668636687366883668936690366913669236693366943669536696366973669836699367003670136702367033670436705367063670736708367093671036711367123671336714367153671636717367183671936720367213672236723367243672536726367273672836729367303673136732367333673436735367363673736738367393674036741367423674336744367453674636747367483674936750367513675236753367543675536756367573675836759367603676136762367633676436765367663676736768367693677036771367723677336774367753677636777367783677936780367813678236783367843678536786367873678836789367903679136792367933679436795367963679736798367993680036801368023680336804368053680636807368083680936810368113681236813368143681536816368173681836819368203682136822368233682436825368263682736828368293683036831368323683336834368353683636837368383683936840368413684236843368443684536846368473684836849368503685136852368533685436855368563685736858368593686036861368623686336864368653686636867368683686936870368713687236873368743687536876368773687836879368803688136882368833688436885368863688736888368893689036891368923689336894368953689636897368983689936900369013690236903369043690536906369073690836909369103691136912369133691436915369163691736918369193692036921369223692336924369253692636927369283692936930369313693236933369343693536936369373693836939369403694136942369433694436945369463694736948369493695036951369523695336954369553695636957369583695936960369613696236963369643696536966369673696836969369703697136972369733697436975369763697736978369793698036981369823698336984369853698636987369883698936990369913699236993369943699536996369973699836999370003700137002370033700437005370063700737008370093701037011370123701337014370153701637017370183701937020370213702237023370243702537026370273702837029370303703137032370333703437035370363703737038370393704037041370423704337044370453704637047370483704937050370513705237053370543705537056370573705837059370603706137062370633706437065370663706737068370693707037071370723707337074370753707637077370783707937080370813708237083370843708537086370873708837089370903709137092370933709437095370963709737098370993710037101371023710337104371053710637107371083710937110371113711237113371143711537116371173711837119371203712137122371233712437125371263712737128371293713037131371323713337134371353713637137371383713937140371413714237143371443714537146371473714837149371503715137152371533715437155371563715737158371593716037161371623716337164371653716637167371683716937170371713717237173371743717537176371773717837179371803718137182371833718437185371863718737188371893719037191371923719337194371953719637197371983719937200372013720237203372043720537206372073720837209372103721137212372133721437215372163721737218372193722037221372223722337224372253722637227372283722937230372313723237233372343723537236372373723837239372403724137242372433724437245372463724737248372493725037251372523725337254372553725637257372583725937260372613726237263372643726537266372673726837269372703727137272372733727437275372763727737278372793728037281372823728337284372853728637287372883728937290372913729237293372943729537296372973729837299373003730137302373033730437305373063730737308373093731037311373123731337314373153731637317373183731937320373213732237323373243732537326373273732837329373303733137332373333733437335373363733737338373393734037341373423734337344373453734637347373483734937350373513735237353373543735537356373573735837359373603736137362373633736437365373663736737368373693737037371373723737337374373753737637377373783737937380373813738237383373843738537386373873738837389373903739137392373933739437395373963739737398373993740037401374023740337404374053740637407374083740937410374113741237413374143741537416374173741837419374203742137422374233742437425374263742737428374293743037431374323743337434374353743637437374383743937440374413744237443374443744537446374473744837449374503745137452374533745437455374563745737458374593746037461374623746337464374653746637467374683746937470374713747237473374743747537476374773747837479374803748137482374833748437485374863748737488374893749037491374923749337494374953749637497374983749937500375013750237503375043750537506375073750837509375103751137512375133751437515375163751737518375193752037521375223752337524375253752637527375283752937530375313753237533375343753537536375373753837539375403754137542375433754437545375463754737548375493755037551375523755337554375553755637557375583755937560375613756237563375643756537566375673756837569375703757137572375733757437575375763757737578375793758037581375823758337584375853758637587375883758937590375913759237593375943759537596375973759837599376003760137602376033760437605376063760737608376093761037611376123761337614376153761637617376183761937620376213762237623376243762537626376273762837629376303763137632376333763437635376363763737638376393764037641376423764337644376453764637647376483764937650376513765237653376543765537656376573765837659376603766137662376633766437665376663766737668376693767037671376723767337674376753767637677376783767937680376813768237683376843768537686376873768837689376903769137692376933769437695376963769737698376993770037701377023770337704377053770637707377083770937710377113771237713377143771537716377173771837719377203772137722377233772437725377263772737728377293773037731377323773337734377353773637737377383773937740377413774237743377443774537746377473774837749377503775137752377533775437755377563775737758377593776037761377623776337764377653776637767377683776937770377713777237773377743777537776377773777837779377803778137782377833778437785377863778737788377893779037791377923779337794377953779637797377983779937800378013780237803378043780537806378073780837809378103781137812378133781437815378163781737818378193782037821378223782337824378253782637827378283782937830378313783237833378343783537836378373783837839378403784137842378433784437845378463784737848378493785037851378523785337854378553785637857378583785937860378613786237863378643786537866378673786837869378703787137872378733787437875378763787737878378793788037881378823788337884378853788637887378883788937890378913789237893378943789537896378973789837899379003790137902379033790437905379063790737908379093791037911379123791337914379153791637917379183791937920379213792237923379243792537926379273792837929379303793137932379333793437935379363793737938379393794037941379423794337944379453794637947379483794937950379513795237953379543795537956379573795837959379603796137962379633796437965379663796737968379693797037971379723797337974379753797637977379783797937980379813798237983379843798537986379873798837989379903799137992379933799437995379963799737998379993800038001380023800338004380053800638007380083800938010380113801238013380143801538016380173801838019380203802138022380233802438025380263802738028380293803038031380323803338034380353803638037380383803938040380413804238043380443804538046380473804838049380503805138052380533805438055380563805738058380593806038061380623806338064380653806638067380683806938070380713807238073380743807538076380773807838079380803808138082380833808438085380863808738088380893809038091380923809338094380953809638097380983809938100381013810238103381043810538106381073810838109381103811138112381133811438115381163811738118381193812038121381223812338124381253812638127381283812938130381313813238133381343813538136381373813838139381403814138142381433814438145381463814738148381493815038151381523815338154381553815638157381583815938160381613816238163381643816538166381673816838169381703817138172381733817438175381763817738178381793818038181381823818338184381853818638187381883818938190381913819238193381943819538196381973819838199382003820138202382033820438205382063820738208382093821038211382123821338214382153821638217382183821938220382213822238223382243822538226382273822838229382303823138232382333823438235382363823738238382393824038241382423824338244382453824638247382483824938250382513825238253382543825538256382573825838259382603826138262382633826438265382663826738268382693827038271382723827338274382753827638277382783827938280382813828238283382843828538286382873828838289382903829138292382933829438295382963829738298382993830038301383023830338304383053830638307383083830938310383113831238313383143831538316383173831838319383203832138322383233832438325383263832738328383293833038331383323833338334383353833638337383383833938340383413834238343383443834538346383473834838349383503835138352383533835438355383563835738358383593836038361383623836338364383653836638367383683836938370383713837238373383743837538376383773837838379383803838138382383833838438385383863838738388383893839038391383923839338394383953839638397383983839938400384013840238403384043840538406384073840838409384103841138412384133841438415384163841738418384193842038421384223842338424384253842638427384283842938430384313843238433384343843538436384373843838439384403844138442384433844438445384463844738448384493845038451384523845338454384553845638457384583845938460384613846238463384643846538466384673846838469384703847138472384733847438475384763847738478384793848038481384823848338484384853848638487384883848938490384913849238493384943849538496384973849838499385003850138502385033850438505385063850738508385093851038511385123851338514385153851638517385183851938520385213852238523385243852538526385273852838529385303853138532385333853438535385363853738538385393854038541385423854338544385453854638547385483854938550385513855238553385543855538556385573855838559385603856138562385633856438565385663856738568385693857038571385723857338574385753857638577385783857938580385813858238583
  1. /**
  2. * TinyMCE version 6.7.0 (2023-08-30)
  3. */
  4. (function () {
  5. "use strict";
  6. var typeOf$1 = function (x) {
  7. if (x === null) {
  8. return "null";
  9. }
  10. if (x === undefined) {
  11. return "undefined";
  12. }
  13. var t = typeof x;
  14. if (
  15. t === "object" &&
  16. (Array.prototype.isPrototypeOf(x) ||
  17. (x.constructor && x.constructor.name === "Array"))
  18. ) {
  19. return "array";
  20. }
  21. if (
  22. t === "object" &&
  23. (String.prototype.isPrototypeOf(x) ||
  24. (x.constructor && x.constructor.name === "String"))
  25. ) {
  26. return "string";
  27. }
  28. return t;
  29. };
  30. var isEquatableType = function (x) {
  31. return (
  32. [
  33. "undefined",
  34. "boolean",
  35. "number",
  36. "string",
  37. "function",
  38. "xml",
  39. "null",
  40. ].indexOf(x) !== -1
  41. );
  42. };
  43. var sort$1 = function (xs, compareFn) {
  44. var clone = Array.prototype.slice.call(xs);
  45. return clone.sort(compareFn);
  46. };
  47. var contramap = function (eqa, f) {
  48. return eq$2(function (x, y) {
  49. return eqa.eq(f(x), f(y));
  50. });
  51. };
  52. var eq$2 = function (f) {
  53. return { eq: f };
  54. };
  55. var tripleEq = eq$2(function (x, y) {
  56. return x === y;
  57. });
  58. var eqString = tripleEq;
  59. var eqArray = function (eqa) {
  60. return eq$2(function (x, y) {
  61. if (x.length !== y.length) {
  62. return false;
  63. }
  64. var len = x.length;
  65. for (var i = 0; i < len; i++) {
  66. if (!eqa.eq(x[i], y[i])) {
  67. return false;
  68. }
  69. }
  70. return true;
  71. });
  72. };
  73. var eqSortedArray = function (eqa, compareFn) {
  74. return contramap(eqArray(eqa), function (xs) {
  75. return sort$1(xs, compareFn);
  76. });
  77. };
  78. var eqRecord = function (eqa) {
  79. return eq$2(function (x, y) {
  80. var kx = Object.keys(x);
  81. var ky = Object.keys(y);
  82. if (!eqSortedArray(eqString).eq(kx, ky)) {
  83. return false;
  84. }
  85. var len = kx.length;
  86. for (var i = 0; i < len; i++) {
  87. var q = kx[i];
  88. if (!eqa.eq(x[q], y[q])) {
  89. return false;
  90. }
  91. }
  92. return true;
  93. });
  94. };
  95. var eqAny = eq$2(function (x, y) {
  96. if (x === y) {
  97. return true;
  98. }
  99. var tx = typeOf$1(x);
  100. var ty = typeOf$1(y);
  101. if (tx !== ty) {
  102. return false;
  103. }
  104. if (isEquatableType(tx)) {
  105. return x === y;
  106. } else if (tx === "array") {
  107. return eqArray(eqAny).eq(x, y);
  108. } else if (tx === "object") {
  109. return eqRecord(eqAny).eq(x, y);
  110. }
  111. return false;
  112. });
  113. const getPrototypeOf$2 = Object.getPrototypeOf;
  114. const hasProto = (v, constructor, predicate) => {
  115. var _a;
  116. if (predicate(v, constructor.prototype)) {
  117. return true;
  118. } else {
  119. return (
  120. ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) ===
  121. constructor.name
  122. );
  123. }
  124. };
  125. const typeOf = (x) => {
  126. const t = typeof x;
  127. if (x === null) {
  128. return "null";
  129. } else if (t === "object" && Array.isArray(x)) {
  130. return "array";
  131. } else if (
  132. t === "object" &&
  133. hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))
  134. ) {
  135. return "string";
  136. } else {
  137. return t;
  138. }
  139. };
  140. const isType$1 = (type) => (value) => typeOf(value) === type;
  141. const isSimpleType = (type) => (value) => typeof value === type;
  142. const eq$1 = (t) => (a) => t === a;
  143. const is$4 = (value, constructor) =>
  144. isObject(value) &&
  145. hasProto(value, constructor, (o, proto) => getPrototypeOf$2(o) === proto);
  146. const isString = isType$1("string");
  147. const isObject = isType$1("object");
  148. const isPlainObject = (value) => is$4(value, Object);
  149. const isArray$1 = isType$1("array");
  150. const isNull = eq$1(null);
  151. const isBoolean = isSimpleType("boolean");
  152. const isUndefined = eq$1(undefined);
  153. const isNullable = (a) => a === null || a === undefined;
  154. const isNonNullable = (a) => !isNullable(a);
  155. const isFunction = isSimpleType("function");
  156. const isNumber = isSimpleType("number");
  157. const isArrayOf = (value, pred) => {
  158. if (isArray$1(value)) {
  159. for (let i = 0, len = value.length; i < len; ++i) {
  160. if (!pred(value[i])) {
  161. return false;
  162. }
  163. }
  164. return true;
  165. }
  166. return false;
  167. };
  168. const noop = () => {};
  169. const compose = (fa, fb) => {
  170. return (...args) => {
  171. return fa(fb.apply(null, args));
  172. };
  173. };
  174. const compose1 = (fbc, fab) => (a) => fbc(fab(a));
  175. const constant = (value) => {
  176. return () => {
  177. return value;
  178. };
  179. };
  180. const identity = (x) => {
  181. return x;
  182. };
  183. const tripleEquals = (a, b) => {
  184. return a === b;
  185. };
  186. function curry(fn, ...initialArgs) {
  187. return (...restArgs) => {
  188. const all = initialArgs.concat(restArgs);
  189. return fn.apply(null, all);
  190. };
  191. }
  192. const not = (f) => (t) => !f(t);
  193. const die = (msg) => {
  194. return () => {
  195. throw new Error(msg);
  196. };
  197. };
  198. const apply$1 = (f) => {
  199. return f();
  200. };
  201. const call = (f) => {
  202. f();
  203. };
  204. const never = constant(false);
  205. const always = constant(true);
  206. class Optional {
  207. constructor(tag, value) {
  208. this.tag = tag;
  209. this.value = value;
  210. }
  211. static some(value) {
  212. return new Optional(true, value);
  213. }
  214. static none() {
  215. return Optional.singletonNone;
  216. }
  217. fold(onNone, onSome) {
  218. if (this.tag) {
  219. return onSome(this.value);
  220. } else {
  221. return onNone();
  222. }
  223. }
  224. isSome() {
  225. return this.tag;
  226. }
  227. isNone() {
  228. return !this.tag;
  229. }
  230. map(mapper) {
  231. if (this.tag) {
  232. return Optional.some(mapper(this.value));
  233. } else {
  234. return Optional.none();
  235. }
  236. }
  237. bind(binder) {
  238. if (this.tag) {
  239. return binder(this.value);
  240. } else {
  241. return Optional.none();
  242. }
  243. }
  244. exists(predicate) {
  245. return this.tag && predicate(this.value);
  246. }
  247. forall(predicate) {
  248. return !this.tag || predicate(this.value);
  249. }
  250. filter(predicate) {
  251. if (!this.tag || predicate(this.value)) {
  252. return this;
  253. } else {
  254. return Optional.none();
  255. }
  256. }
  257. getOr(replacement) {
  258. return this.tag ? this.value : replacement;
  259. }
  260. or(replacement) {
  261. return this.tag ? this : replacement;
  262. }
  263. getOrThunk(thunk) {
  264. return this.tag ? this.value : thunk();
  265. }
  266. orThunk(thunk) {
  267. return this.tag ? this : thunk();
  268. }
  269. getOrDie(message) {
  270. if (!this.tag) {
  271. throw new Error(
  272. message !== null && message !== void 0
  273. ? message
  274. : "Called getOrDie on None"
  275. );
  276. } else {
  277. return this.value;
  278. }
  279. }
  280. static from(value) {
  281. return isNonNullable(value) ? Optional.some(value) : Optional.none();
  282. }
  283. getOrNull() {
  284. return this.tag ? this.value : null;
  285. }
  286. getOrUndefined() {
  287. return this.value;
  288. }
  289. each(worker) {
  290. if (this.tag) {
  291. worker(this.value);
  292. }
  293. }
  294. toArray() {
  295. return this.tag ? [this.value] : [];
  296. }
  297. toString() {
  298. return this.tag ? `some(${this.value})` : "none()";
  299. }
  300. }
  301. Optional.singletonNone = new Optional(false);
  302. const nativeSlice = Array.prototype.slice;
  303. const nativeIndexOf = Array.prototype.indexOf;
  304. const nativePush = Array.prototype.push;
  305. const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
  306. const indexOf$1 = (xs, x) => {
  307. const r = rawIndexOf(xs, x);
  308. return r === -1 ? Optional.none() : Optional.some(r);
  309. };
  310. const contains$2 = (xs, x) => rawIndexOf(xs, x) > -1;
  311. const exists = (xs, pred) => {
  312. for (let i = 0, len = xs.length; i < len; i++) {
  313. const x = xs[i];
  314. if (pred(x, i)) {
  315. return true;
  316. }
  317. }
  318. return false;
  319. };
  320. const map$3 = (xs, f) => {
  321. const len = xs.length;
  322. const r = new Array(len);
  323. for (let i = 0; i < len; i++) {
  324. const x = xs[i];
  325. r[i] = f(x, i);
  326. }
  327. return r;
  328. };
  329. const each$e = (xs, f) => {
  330. for (let i = 0, len = xs.length; i < len; i++) {
  331. const x = xs[i];
  332. f(x, i);
  333. }
  334. };
  335. const eachr = (xs, f) => {
  336. for (let i = xs.length - 1; i >= 0; i--) {
  337. const x = xs[i];
  338. f(x, i);
  339. }
  340. };
  341. const partition$2 = (xs, pred) => {
  342. const pass = [];
  343. const fail = [];
  344. for (let i = 0, len = xs.length; i < len; i++) {
  345. const x = xs[i];
  346. const arr = pred(x, i) ? pass : fail;
  347. arr.push(x);
  348. }
  349. return {
  350. pass,
  351. fail,
  352. };
  353. };
  354. const filter$5 = (xs, pred) => {
  355. const r = [];
  356. for (let i = 0, len = xs.length; i < len; i++) {
  357. const x = xs[i];
  358. if (pred(x, i)) {
  359. r.push(x);
  360. }
  361. }
  362. return r;
  363. };
  364. const foldr = (xs, f, acc) => {
  365. eachr(xs, (x, i) => {
  366. acc = f(acc, x, i);
  367. });
  368. return acc;
  369. };
  370. const foldl = (xs, f, acc) => {
  371. each$e(xs, (x, i) => {
  372. acc = f(acc, x, i);
  373. });
  374. return acc;
  375. };
  376. const findUntil$1 = (xs, pred, until) => {
  377. for (let i = 0, len = xs.length; i < len; i++) {
  378. const x = xs[i];
  379. if (pred(x, i)) {
  380. return Optional.some(x);
  381. } else if (until(x, i)) {
  382. break;
  383. }
  384. }
  385. return Optional.none();
  386. };
  387. const find$2 = (xs, pred) => {
  388. return findUntil$1(xs, pred, never);
  389. };
  390. const findIndex$2 = (xs, pred) => {
  391. for (let i = 0, len = xs.length; i < len; i++) {
  392. const x = xs[i];
  393. if (pred(x, i)) {
  394. return Optional.some(i);
  395. }
  396. }
  397. return Optional.none();
  398. };
  399. const flatten = (xs) => {
  400. const r = [];
  401. for (let i = 0, len = xs.length; i < len; ++i) {
  402. if (!isArray$1(xs[i])) {
  403. throw new Error(
  404. "Arr.flatten item " + i + " was not an array, input: " + xs
  405. );
  406. }
  407. nativePush.apply(r, xs[i]);
  408. }
  409. return r;
  410. };
  411. const bind$3 = (xs, f) => flatten(map$3(xs, f));
  412. const forall = (xs, pred) => {
  413. for (let i = 0, len = xs.length; i < len; ++i) {
  414. const x = xs[i];
  415. if (pred(x, i) !== true) {
  416. return false;
  417. }
  418. }
  419. return true;
  420. };
  421. const reverse = (xs) => {
  422. const r = nativeSlice.call(xs, 0);
  423. r.reverse();
  424. return r;
  425. };
  426. const difference = (a1, a2) => filter$5(a1, (x) => !contains$2(a2, x));
  427. const mapToObject = (xs, f) => {
  428. const r = {};
  429. for (let i = 0, len = xs.length; i < len; i++) {
  430. const x = xs[i];
  431. r[String(x)] = f(x, i);
  432. }
  433. return r;
  434. };
  435. const sort = (xs, comparator) => {
  436. const copy = nativeSlice.call(xs, 0);
  437. copy.sort(comparator);
  438. return copy;
  439. };
  440. const get$b = (xs, i) =>
  441. i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
  442. const head = (xs) => get$b(xs, 0);
  443. const last$3 = (xs) => get$b(xs, xs.length - 1);
  444. const from = isFunction(Array.from) ? Array.from : (x) => nativeSlice.call(x);
  445. const findMap = (arr, f) => {
  446. for (let i = 0; i < arr.length; i++) {
  447. const r = f(arr[i], i);
  448. if (r.isSome()) {
  449. return r;
  450. }
  451. }
  452. return Optional.none();
  453. };
  454. const unique$1 = (xs, comparator) => {
  455. const r = [];
  456. const isDuplicated = isFunction(comparator)
  457. ? (x) => exists(r, (i) => comparator(i, x))
  458. : (x) => contains$2(r, x);
  459. for (let i = 0, len = xs.length; i < len; i++) {
  460. const x = xs[i];
  461. if (!isDuplicated(x)) {
  462. r.push(x);
  463. }
  464. }
  465. return r;
  466. };
  467. const keys = Object.keys;
  468. const hasOwnProperty$2 = Object.hasOwnProperty;
  469. const each$d = (obj, f) => {
  470. const props = keys(obj);
  471. for (let k = 0, len = props.length; k < len; k++) {
  472. const i = props[k];
  473. const x = obj[i];
  474. f(x, i);
  475. }
  476. };
  477. const map$2 = (obj, f) => {
  478. return tupleMap(obj, (x, i) => ({
  479. k: i,
  480. v: f(x, i),
  481. }));
  482. };
  483. const tupleMap = (obj, f) => {
  484. const r = {};
  485. each$d(obj, (x, i) => {
  486. const tuple = f(x, i);
  487. r[tuple.k] = tuple.v;
  488. });
  489. return r;
  490. };
  491. const objAcc = (r) => (x, i) => {
  492. r[i] = x;
  493. };
  494. const internalFilter = (obj, pred, onTrue, onFalse) => {
  495. each$d(obj, (x, i) => {
  496. (pred(x, i) ? onTrue : onFalse)(x, i);
  497. });
  498. };
  499. const bifilter = (obj, pred) => {
  500. const t = {};
  501. const f = {};
  502. internalFilter(obj, pred, objAcc(t), objAcc(f));
  503. return {
  504. t,
  505. f,
  506. };
  507. };
  508. const filter$4 = (obj, pred) => {
  509. const t = {};
  510. internalFilter(obj, pred, objAcc(t), noop);
  511. return t;
  512. };
  513. const mapToArray = (obj, f) => {
  514. const r = [];
  515. each$d(obj, (value, name) => {
  516. r.push(f(value, name));
  517. });
  518. return r;
  519. };
  520. const values = (obj) => {
  521. return mapToArray(obj, identity);
  522. };
  523. const get$a = (obj, key) => {
  524. return has$2(obj, key) ? Optional.from(obj[key]) : Optional.none();
  525. };
  526. const has$2 = (obj, key) => hasOwnProperty$2.call(obj, key);
  527. const hasNonNullableKey = (obj, key) =>
  528. has$2(obj, key) && obj[key] !== undefined && obj[key] !== null;
  529. const equal$1 = (a1, a2, eq = eqAny) => eqRecord(eq).eq(a1, a2);
  530. const stringArray = (a) => {
  531. const all = {};
  532. each$e(a, (key) => {
  533. all[key] = {};
  534. });
  535. return keys(all);
  536. };
  537. const isArrayLike = (o) => o.length !== undefined;
  538. const isArray = Array.isArray;
  539. const toArray$1 = (obj) => {
  540. if (!isArray(obj)) {
  541. const array = [];
  542. for (let i = 0, l = obj.length; i < l; i++) {
  543. array[i] = obj[i];
  544. }
  545. return array;
  546. } else {
  547. return obj;
  548. }
  549. };
  550. const each$c = (o, cb, s) => {
  551. if (!o) {
  552. return false;
  553. }
  554. s = s || o;
  555. if (isArrayLike(o)) {
  556. for (let n = 0, l = o.length; n < l; n++) {
  557. if (cb.call(s, o[n], n, o) === false) {
  558. return false;
  559. }
  560. }
  561. } else {
  562. for (const n in o) {
  563. if (has$2(o, n)) {
  564. if (cb.call(s, o[n], n, o) === false) {
  565. return false;
  566. }
  567. }
  568. }
  569. }
  570. return true;
  571. };
  572. const map$1 = (array, callback) => {
  573. const out = [];
  574. each$c(array, (item, index) => {
  575. out.push(callback(item, index, array));
  576. });
  577. return out;
  578. };
  579. const filter$3 = (a, f) => {
  580. const o = [];
  581. each$c(a, (v, index) => {
  582. if (!f || f(v, index, a)) {
  583. o.push(v);
  584. }
  585. });
  586. return o;
  587. };
  588. const indexOf = (a, v) => {
  589. if (a) {
  590. for (let i = 0, l = a.length; i < l; i++) {
  591. if (a[i] === v) {
  592. return i;
  593. }
  594. }
  595. }
  596. return -1;
  597. };
  598. const reduce = (collection, iteratee, accumulator, thisArg) => {
  599. let acc = isUndefined(accumulator) ? collection[0] : accumulator;
  600. for (let i = 0; i < collection.length; i++) {
  601. acc = iteratee.call(thisArg, acc, collection[i], i);
  602. }
  603. return acc;
  604. };
  605. const findIndex$1 = (array, predicate, thisArg) => {
  606. for (let i = 0, l = array.length; i < l; i++) {
  607. if (predicate.call(thisArg, array[i], i, array)) {
  608. return i;
  609. }
  610. }
  611. return -1;
  612. };
  613. const last$2 = (collection) => collection[collection.length - 1];
  614. const cached = (f) => {
  615. let called = false;
  616. let r;
  617. return (...args) => {
  618. if (!called) {
  619. called = true;
  620. r = f.apply(null, args);
  621. }
  622. return r;
  623. };
  624. };
  625. const DeviceType = (os, browser, userAgent, mediaMatch) => {
  626. const isiPad = os.isiOS() && /ipad/i.test(userAgent) === true;
  627. const isiPhone = os.isiOS() && !isiPad;
  628. const isMobile = os.isiOS() || os.isAndroid();
  629. const isTouch = isMobile || mediaMatch("(pointer:coarse)");
  630. const isTablet =
  631. isiPad ||
  632. (!isiPhone && isMobile && mediaMatch("(min-device-width:768px)"));
  633. const isPhone = isiPhone || (isMobile && !isTablet);
  634. const iOSwebview =
  635. browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false;
  636. const isDesktop = !isPhone && !isTablet && !iOSwebview;
  637. return {
  638. isiPad: constant(isiPad),
  639. isiPhone: constant(isiPhone),
  640. isTablet: constant(isTablet),
  641. isPhone: constant(isPhone),
  642. isTouch: constant(isTouch),
  643. isAndroid: os.isAndroid,
  644. isiOS: os.isiOS,
  645. isWebView: constant(iOSwebview),
  646. isDesktop: constant(isDesktop),
  647. };
  648. };
  649. const firstMatch = (regexes, s) => {
  650. for (let i = 0; i < regexes.length; i++) {
  651. const x = regexes[i];
  652. if (x.test(s)) {
  653. return x;
  654. }
  655. }
  656. return undefined;
  657. };
  658. const find$1 = (regexes, agent) => {
  659. const r = firstMatch(regexes, agent);
  660. if (!r) {
  661. return {
  662. major: 0,
  663. minor: 0,
  664. };
  665. }
  666. const group = (i) => {
  667. return Number(agent.replace(r, "$" + i));
  668. };
  669. return nu$3(group(1), group(2));
  670. };
  671. const detect$5 = (versionRegexes, agent) => {
  672. const cleanedAgent = String(agent).toLowerCase();
  673. if (versionRegexes.length === 0) {
  674. return unknown$2();
  675. }
  676. return find$1(versionRegexes, cleanedAgent);
  677. };
  678. const unknown$2 = () => {
  679. return nu$3(0, 0);
  680. };
  681. const nu$3 = (major, minor) => {
  682. return {
  683. major,
  684. minor,
  685. };
  686. };
  687. const Version = {
  688. nu: nu$3,
  689. detect: detect$5,
  690. unknown: unknown$2,
  691. };
  692. const detectBrowser$1 = (browsers, userAgentData) => {
  693. return findMap(userAgentData.brands, (uaBrand) => {
  694. const lcBrand = uaBrand.brand.toLowerCase();
  695. return find$2(browsers, (browser) => {
  696. var _a;
  697. return (
  698. lcBrand ===
  699. ((_a = browser.brand) === null || _a === void 0
  700. ? void 0
  701. : _a.toLowerCase())
  702. );
  703. }).map((info) => ({
  704. current: info.name,
  705. version: Version.nu(parseInt(uaBrand.version, 10), 0),
  706. }));
  707. });
  708. };
  709. const detect$4 = (candidates, userAgent) => {
  710. const agent = String(userAgent).toLowerCase();
  711. return find$2(candidates, (candidate) => {
  712. return candidate.search(agent);
  713. });
  714. };
  715. const detectBrowser = (browsers, userAgent) => {
  716. return detect$4(browsers, userAgent).map((browser) => {
  717. const version = Version.detect(browser.versionRegexes, userAgent);
  718. return {
  719. current: browser.name,
  720. version,
  721. };
  722. });
  723. };
  724. const detectOs = (oses, userAgent) => {
  725. return detect$4(oses, userAgent).map((os) => {
  726. const version = Version.detect(os.versionRegexes, userAgent);
  727. return {
  728. current: os.name,
  729. version,
  730. };
  731. });
  732. };
  733. const removeFromStart = (str, numChars) => {
  734. return str.substring(numChars);
  735. };
  736. const checkRange = (str, substr, start) =>
  737. substr === "" ||
  738. (str.length >= substr.length &&
  739. str.substr(start, start + substr.length) === substr);
  740. const removeLeading = (str, prefix) => {
  741. return startsWith(str, prefix) ? removeFromStart(str, prefix.length) : str;
  742. };
  743. const contains$1 = (str, substr, start = 0, end) => {
  744. const idx = str.indexOf(substr, start);
  745. if (idx !== -1) {
  746. return isUndefined(end) ? true : idx + substr.length <= end;
  747. } else {
  748. return false;
  749. }
  750. };
  751. const startsWith = (str, prefix) => {
  752. return checkRange(str, prefix, 0);
  753. };
  754. const endsWith = (str, suffix) => {
  755. return checkRange(str, suffix, str.length - suffix.length);
  756. };
  757. const blank = (r) => (s) => s.replace(r, "");
  758. const trim$3 = blank(/^\s+|\s+$/g);
  759. const lTrim = blank(/^\s+/g);
  760. const rTrim = blank(/\s+$/g);
  761. const isNotEmpty = (s) => s.length > 0;
  762. const isEmpty$3 = (s) => !isNotEmpty(s);
  763. const repeat = (s, count) => (count <= 0 ? "" : new Array(count + 1).join(s));
  764. const toInt = (value, radix = 10) => {
  765. const num = parseInt(value, radix);
  766. return isNaN(num) ? Optional.none() : Optional.some(num);
  767. };
  768. const normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/;
  769. const checkContains = (target) => {
  770. return (uastring) => {
  771. return contains$1(uastring, target);
  772. };
  773. };
  774. const browsers = [
  775. {
  776. name: "Edge",
  777. versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],
  778. search: (uastring) => {
  779. return (
  780. contains$1(uastring, "edge/") &&
  781. contains$1(uastring, "chrome") &&
  782. contains$1(uastring, "safari") &&
  783. contains$1(uastring, "applewebkit")
  784. );
  785. },
  786. },
  787. {
  788. name: "Chromium",
  789. brand: "Chromium",
  790. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/, normalVersionRegex],
  791. search: (uastring) => {
  792. return (
  793. contains$1(uastring, "chrome") && !contains$1(uastring, "chromeframe")
  794. );
  795. },
  796. },
  797. {
  798. name: "IE",
  799. versionRegexes: [
  800. /.*?msie\ ?([0-9]+)\.([0-9]+).*/,
  801. /.*?rv:([0-9]+)\.([0-9]+).*/,
  802. ],
  803. search: (uastring) => {
  804. return contains$1(uastring, "msie") || contains$1(uastring, "trident");
  805. },
  806. },
  807. {
  808. name: "Opera",
  809. versionRegexes: [normalVersionRegex, /.*?opera\/([0-9]+)\.([0-9]+).*/],
  810. search: checkContains("opera"),
  811. },
  812. {
  813. name: "Firefox",
  814. versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],
  815. search: checkContains("firefox"),
  816. },
  817. {
  818. name: "Safari",
  819. versionRegexes: [normalVersionRegex, /.*?cpu os ([0-9]+)_([0-9]+).*/],
  820. search: (uastring) => {
  821. return (
  822. (contains$1(uastring, "safari") || contains$1(uastring, "mobile/")) &&
  823. contains$1(uastring, "applewebkit")
  824. );
  825. },
  826. },
  827. ];
  828. const oses = [
  829. {
  830. name: "Windows",
  831. search: checkContains("win"),
  832. versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/],
  833. },
  834. {
  835. name: "iOS",
  836. search: (uastring) => {
  837. return contains$1(uastring, "iphone") || contains$1(uastring, "ipad");
  838. },
  839. versionRegexes: [
  840. /.*?version\/\ ?([0-9]+)\.([0-9]+).*/,
  841. /.*cpu os ([0-9]+)_([0-9]+).*/,
  842. /.*cpu iphone os ([0-9]+)_([0-9]+).*/,
  843. ],
  844. },
  845. {
  846. name: "Android",
  847. search: checkContains("android"),
  848. versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/],
  849. },
  850. {
  851. name: "macOS",
  852. search: checkContains("mac os x"),
  853. versionRegexes: [/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/],
  854. },
  855. {
  856. name: "Linux",
  857. search: checkContains("linux"),
  858. versionRegexes: [],
  859. },
  860. {
  861. name: "Solaris",
  862. search: checkContains("sunos"),
  863. versionRegexes: [],
  864. },
  865. {
  866. name: "FreeBSD",
  867. search: checkContains("freebsd"),
  868. versionRegexes: [],
  869. },
  870. {
  871. name: "ChromeOS",
  872. search: checkContains("cros"),
  873. versionRegexes: [/.*?chrome\/([0-9]+)\.([0-9]+).*/],
  874. },
  875. ];
  876. const PlatformInfo = {
  877. browsers: constant(browsers),
  878. oses: constant(oses),
  879. };
  880. const edge = "Edge";
  881. const chromium = "Chromium";
  882. const ie = "IE";
  883. const opera = "Opera";
  884. const firefox = "Firefox";
  885. const safari = "Safari";
  886. const unknown$1 = () => {
  887. return nu$2({
  888. current: undefined,
  889. version: Version.unknown(),
  890. });
  891. };
  892. const nu$2 = (info) => {
  893. const current = info.current;
  894. const version = info.version;
  895. const isBrowser = (name) => () => current === name;
  896. return {
  897. current,
  898. version,
  899. isEdge: isBrowser(edge),
  900. isChromium: isBrowser(chromium),
  901. isIE: isBrowser(ie),
  902. isOpera: isBrowser(opera),
  903. isFirefox: isBrowser(firefox),
  904. isSafari: isBrowser(safari),
  905. };
  906. };
  907. const Browser = {
  908. unknown: unknown$1,
  909. nu: nu$2,
  910. edge: constant(edge),
  911. chromium: constant(chromium),
  912. ie: constant(ie),
  913. opera: constant(opera),
  914. firefox: constant(firefox),
  915. safari: constant(safari),
  916. };
  917. const windows = "Windows";
  918. const ios = "iOS";
  919. const android = "Android";
  920. const linux = "Linux";
  921. const macos = "macOS";
  922. const solaris = "Solaris";
  923. const freebsd = "FreeBSD";
  924. const chromeos = "ChromeOS";
  925. const unknown = () => {
  926. return nu$1({
  927. current: undefined,
  928. version: Version.unknown(),
  929. });
  930. };
  931. const nu$1 = (info) => {
  932. const current = info.current;
  933. const version = info.version;
  934. const isOS = (name) => () => current === name;
  935. return {
  936. current,
  937. version,
  938. isWindows: isOS(windows),
  939. isiOS: isOS(ios),
  940. isAndroid: isOS(android),
  941. isMacOS: isOS(macos),
  942. isLinux: isOS(linux),
  943. isSolaris: isOS(solaris),
  944. isFreeBSD: isOS(freebsd),
  945. isChromeOS: isOS(chromeos),
  946. };
  947. };
  948. const OperatingSystem = {
  949. unknown,
  950. nu: nu$1,
  951. windows: constant(windows),
  952. ios: constant(ios),
  953. android: constant(android),
  954. linux: constant(linux),
  955. macos: constant(macos),
  956. solaris: constant(solaris),
  957. freebsd: constant(freebsd),
  958. chromeos: constant(chromeos),
  959. };
  960. const detect$3 = (userAgent, userAgentDataOpt, mediaMatch) => {
  961. const browsers = PlatformInfo.browsers();
  962. const oses = PlatformInfo.oses();
  963. const browser = userAgentDataOpt
  964. .bind((userAgentData) => detectBrowser$1(browsers, userAgentData))
  965. .orThunk(() => detectBrowser(browsers, userAgent))
  966. .fold(Browser.unknown, Browser.nu);
  967. const os = detectOs(oses, userAgent).fold(
  968. OperatingSystem.unknown,
  969. OperatingSystem.nu
  970. );
  971. const deviceType = DeviceType(os, browser, userAgent, mediaMatch);
  972. return {
  973. browser,
  974. os,
  975. deviceType,
  976. };
  977. };
  978. const PlatformDetection = { detect: detect$3 };
  979. const mediaMatch = (query) => window.matchMedia(query).matches;
  980. let platform$4 = cached(() =>
  981. PlatformDetection.detect(
  982. navigator.userAgent,
  983. Optional.from(navigator.userAgentData),
  984. mediaMatch
  985. )
  986. );
  987. const detect$2 = () => platform$4();
  988. const userAgent = navigator.userAgent;
  989. const platform$3 = detect$2();
  990. const browser$3 = platform$3.browser;
  991. const os$1 = platform$3.os;
  992. const deviceType = platform$3.deviceType;
  993. const windowsPhone = userAgent.indexOf("Windows Phone") !== -1;
  994. const Env = {
  995. transparentSrc:
  996. "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
  997. documentMode: browser$3.isIE() ? document.documentMode || 7 : 10,
  998. cacheSuffix: null,
  999. container: null,
  1000. canHaveCSP: !browser$3.isIE(),
  1001. windowsPhone,
  1002. browser: {
  1003. current: browser$3.current,
  1004. version: browser$3.version,
  1005. isChromium: browser$3.isChromium,
  1006. isEdge: browser$3.isEdge,
  1007. isFirefox: browser$3.isFirefox,
  1008. isIE: browser$3.isIE,
  1009. isOpera: browser$3.isOpera,
  1010. isSafari: browser$3.isSafari,
  1011. },
  1012. os: {
  1013. current: os$1.current,
  1014. version: os$1.version,
  1015. isAndroid: os$1.isAndroid,
  1016. isChromeOS: os$1.isChromeOS,
  1017. isFreeBSD: os$1.isFreeBSD,
  1018. isiOS: os$1.isiOS,
  1019. isLinux: os$1.isLinux,
  1020. isMacOS: os$1.isMacOS,
  1021. isSolaris: os$1.isSolaris,
  1022. isWindows: os$1.isWindows,
  1023. },
  1024. deviceType: {
  1025. isDesktop: deviceType.isDesktop,
  1026. isiPad: deviceType.isiPad,
  1027. isiPhone: deviceType.isiPhone,
  1028. isPhone: deviceType.isPhone,
  1029. isTablet: deviceType.isTablet,
  1030. isTouch: deviceType.isTouch,
  1031. isWebView: deviceType.isWebView,
  1032. },
  1033. };
  1034. const whiteSpaceRegExp$1 = /^\s*|\s*$/g;
  1035. const trim$2 = (str) => {
  1036. return isNullable(str) ? "" : ("" + str).replace(whiteSpaceRegExp$1, "");
  1037. };
  1038. const is$3 = (obj, type) => {
  1039. if (!type) {
  1040. return obj !== undefined;
  1041. }
  1042. if (type === "array" && isArray(obj)) {
  1043. return true;
  1044. }
  1045. return typeof obj === type;
  1046. };
  1047. const makeMap$4 = (items, delim, map = {}) => {
  1048. const resolvedItems = isString(items)
  1049. ? items.split(delim || ",")
  1050. : items || [];
  1051. let i = resolvedItems.length;
  1052. while (i--) {
  1053. map[resolvedItems[i]] = {};
  1054. }
  1055. return map;
  1056. };
  1057. const hasOwnProperty$1 = has$2;
  1058. const extend$3 = (obj, ...exts) => {
  1059. for (let i = 0; i < exts.length; i++) {
  1060. const ext = exts[i];
  1061. for (const name in ext) {
  1062. if (has$2(ext, name)) {
  1063. const value = ext[name];
  1064. if (value !== undefined) {
  1065. obj[name] = value;
  1066. }
  1067. }
  1068. }
  1069. }
  1070. return obj;
  1071. };
  1072. const walk$4 = function (o, f, n, s) {
  1073. s = s || this;
  1074. if (o) {
  1075. if (n) {
  1076. o = o[n];
  1077. }
  1078. each$c(o, (o, i) => {
  1079. if (f.call(s, o, i, n) === false) {
  1080. return false;
  1081. } else {
  1082. walk$4(o, f, n, s);
  1083. return true;
  1084. }
  1085. });
  1086. }
  1087. };
  1088. const resolve$3 = (n, o = window) => {
  1089. const path = n.split(".");
  1090. for (let i = 0, l = path.length; i < l; i++) {
  1091. o = o[path[i]];
  1092. if (!o) {
  1093. break;
  1094. }
  1095. }
  1096. return o;
  1097. };
  1098. const explode$3 = (s, d) => {
  1099. if (isArray$1(s)) {
  1100. return s;
  1101. } else if (s === "") {
  1102. return [];
  1103. } else {
  1104. return map$1(s.split(d || ","), trim$2);
  1105. }
  1106. };
  1107. const _addCacheSuffix = (url) => {
  1108. const cacheSuffix = Env.cacheSuffix;
  1109. if (cacheSuffix) {
  1110. url += (url.indexOf("?") === -1 ? "?" : "&") + cacheSuffix;
  1111. }
  1112. return url;
  1113. };
  1114. const Tools = {
  1115. trim: trim$2,
  1116. isArray: isArray,
  1117. is: is$3,
  1118. toArray: toArray$1,
  1119. makeMap: makeMap$4,
  1120. each: each$c,
  1121. map: map$1,
  1122. grep: filter$3,
  1123. inArray: indexOf,
  1124. hasOwn: hasOwnProperty$1,
  1125. extend: extend$3,
  1126. walk: walk$4,
  1127. resolve: resolve$3,
  1128. explode: explode$3,
  1129. _addCacheSuffix,
  1130. };
  1131. const is$2 = (lhs, rhs, comparator = tripleEquals) =>
  1132. lhs.exists((left) => comparator(left, rhs));
  1133. const equals = (lhs, rhs, comparator = tripleEquals) =>
  1134. lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
  1135. const cat = (arr) => {
  1136. const r = [];
  1137. const push = (x) => {
  1138. r.push(x);
  1139. };
  1140. for (let i = 0; i < arr.length; i++) {
  1141. arr[i].each(push);
  1142. }
  1143. return r;
  1144. };
  1145. const lift2 = (oa, ob, f) =>
  1146. oa.isSome() && ob.isSome()
  1147. ? Optional.some(f(oa.getOrDie(), ob.getOrDie()))
  1148. : Optional.none();
  1149. const lift3 = (oa, ob, oc, f) =>
  1150. oa.isSome() && ob.isSome() && oc.isSome()
  1151. ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie()))
  1152. : Optional.none();
  1153. const someIf = (b, a) => (b ? Optional.some(a) : Optional.none());
  1154. const Global =
  1155. typeof window !== "undefined" ? window : Function("return this;")();
  1156. const path = (parts, scope) => {
  1157. let o = scope !== undefined && scope !== null ? scope : Global;
  1158. for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
  1159. o = o[parts[i]];
  1160. }
  1161. return o;
  1162. };
  1163. const resolve$2 = (p, scope) => {
  1164. const parts = p.split(".");
  1165. return path(parts, scope);
  1166. };
  1167. const unsafe = (name, scope) => {
  1168. return resolve$2(name, scope);
  1169. };
  1170. const getOrDie = (name, scope) => {
  1171. const actual = unsafe(name, scope);
  1172. if (actual === undefined || actual === null) {
  1173. throw new Error(name + " not available on this browser");
  1174. }
  1175. return actual;
  1176. };
  1177. const getPrototypeOf$1 = Object.getPrototypeOf;
  1178. const sandHTMLElement = (scope) => {
  1179. return getOrDie("HTMLElement", scope);
  1180. };
  1181. const isPrototypeOf = (x) => {
  1182. const scope = resolve$2("ownerDocument.defaultView", x);
  1183. return (
  1184. isObject(x) &&
  1185. (sandHTMLElement(scope).prototype.isPrototypeOf(x) ||
  1186. /^HTML\w*Element$/.test(getPrototypeOf$1(x).constructor.name))
  1187. );
  1188. };
  1189. const COMMENT = 8;
  1190. const DOCUMENT = 9;
  1191. const DOCUMENT_FRAGMENT = 11;
  1192. const ELEMENT = 1;
  1193. const TEXT = 3;
  1194. const name = (element) => {
  1195. const r = element.dom.nodeName;
  1196. return r.toLowerCase();
  1197. };
  1198. const type$1 = (element) => element.dom.nodeType;
  1199. const isType = (t) => (element) => type$1(element) === t;
  1200. const isComment$1 = (element) =>
  1201. type$1(element) === COMMENT || name(element) === "#comment";
  1202. const isHTMLElement = (element) =>
  1203. isElement$7(element) && isPrototypeOf(element.dom);
  1204. const isElement$7 = isType(ELEMENT);
  1205. const isText$b = isType(TEXT);
  1206. const isDocument$2 = isType(DOCUMENT);
  1207. const isDocumentFragment$1 = isType(DOCUMENT_FRAGMENT);
  1208. const isTag = (tag) => (e) => isElement$7(e) && name(e) === tag;
  1209. const rawSet = (dom, key, value) => {
  1210. if (isString(value) || isBoolean(value) || isNumber(value)) {
  1211. dom.setAttribute(key, value + "");
  1212. } else {
  1213. console.error(
  1214. "Invalid call to Attribute.set. Key ",
  1215. key,
  1216. ":: Value ",
  1217. value,
  1218. ":: Element ",
  1219. dom
  1220. );
  1221. throw new Error("Attribute value was not simple");
  1222. }
  1223. };
  1224. const set$3 = (element, key, value) => {
  1225. rawSet(element.dom, key, value);
  1226. };
  1227. const setAll$1 = (element, attrs) => {
  1228. const dom = element.dom;
  1229. each$d(attrs, (v, k) => {
  1230. rawSet(dom, k, v);
  1231. });
  1232. };
  1233. const get$9 = (element, key) => {
  1234. const v = element.dom.getAttribute(key);
  1235. return v === null ? undefined : v;
  1236. };
  1237. const getOpt = (element, key) => Optional.from(get$9(element, key));
  1238. const has$1 = (element, key) => {
  1239. const dom = element.dom;
  1240. return dom && dom.hasAttribute ? dom.hasAttribute(key) : false;
  1241. };
  1242. const remove$a = (element, key) => {
  1243. element.dom.removeAttribute(key);
  1244. };
  1245. const hasNone = (element) => {
  1246. const attrs = element.dom.attributes;
  1247. return attrs === undefined || attrs === null || attrs.length === 0;
  1248. };
  1249. const clone$4 = (element) =>
  1250. foldl(
  1251. element.dom.attributes,
  1252. (acc, attr) => {
  1253. acc[attr.name] = attr.value;
  1254. return acc;
  1255. },
  1256. {}
  1257. );
  1258. const read$4 = (element, attr) => {
  1259. const value = get$9(element, attr);
  1260. return value === undefined || value === "" ? [] : value.split(" ");
  1261. };
  1262. const add$4 = (element, attr, id) => {
  1263. const old = read$4(element, attr);
  1264. const nu = old.concat([id]);
  1265. set$3(element, attr, nu.join(" "));
  1266. return true;
  1267. };
  1268. const remove$9 = (element, attr, id) => {
  1269. const nu = filter$5(read$4(element, attr), (v) => v !== id);
  1270. if (nu.length > 0) {
  1271. set$3(element, attr, nu.join(" "));
  1272. } else {
  1273. remove$a(element, attr);
  1274. }
  1275. return false;
  1276. };
  1277. const supports = (element) => element.dom.classList !== undefined;
  1278. const get$8 = (element) => read$4(element, "class");
  1279. const add$3 = (element, clazz) => add$4(element, "class", clazz);
  1280. const remove$8 = (element, clazz) => remove$9(element, "class", clazz);
  1281. const toggle$2 = (element, clazz) => {
  1282. if (contains$2(get$8(element), clazz)) {
  1283. return remove$8(element, clazz);
  1284. } else {
  1285. return add$3(element, clazz);
  1286. }
  1287. };
  1288. const add$2 = (element, clazz) => {
  1289. if (supports(element)) {
  1290. element.dom.classList.add(clazz);
  1291. } else {
  1292. add$3(element, clazz);
  1293. }
  1294. };
  1295. const cleanClass = (element) => {
  1296. const classList = supports(element)
  1297. ? element.dom.classList
  1298. : get$8(element);
  1299. if (classList.length === 0) {
  1300. remove$a(element, "class");
  1301. }
  1302. };
  1303. const remove$7 = (element, clazz) => {
  1304. if (supports(element)) {
  1305. const classList = element.dom.classList;
  1306. classList.remove(clazz);
  1307. } else {
  1308. remove$8(element, clazz);
  1309. }
  1310. cleanClass(element);
  1311. };
  1312. const toggle$1 = (element, clazz) => {
  1313. const result = supports(element)
  1314. ? element.dom.classList.toggle(clazz)
  1315. : toggle$2(element, clazz);
  1316. cleanClass(element);
  1317. return result;
  1318. };
  1319. const has = (element, clazz) =>
  1320. supports(element) && element.dom.classList.contains(clazz);
  1321. const fromHtml$1 = (html, scope) => {
  1322. const doc = scope || document;
  1323. const div = doc.createElement("div");
  1324. div.innerHTML = html;
  1325. if (!div.hasChildNodes() || div.childNodes.length > 1) {
  1326. const message = "HTML does not have a single root node";
  1327. console.error(message, html);
  1328. throw new Error(message);
  1329. }
  1330. return fromDom$2(div.childNodes[0]);
  1331. };
  1332. const fromTag = (tag, scope) => {
  1333. const doc = scope || document;
  1334. const node = doc.createElement(tag);
  1335. return fromDom$2(node);
  1336. };
  1337. const fromText = (text, scope) => {
  1338. const doc = scope || document;
  1339. const node = doc.createTextNode(text);
  1340. return fromDom$2(node);
  1341. };
  1342. const fromDom$2 = (node) => {
  1343. if (node === null || node === undefined) {
  1344. throw new Error("Node cannot be null or undefined");
  1345. }
  1346. return { dom: node };
  1347. };
  1348. const fromPoint$2 = (docElm, x, y) =>
  1349. Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$2);
  1350. const SugarElement = {
  1351. fromHtml: fromHtml$1,
  1352. fromTag,
  1353. fromText,
  1354. fromDom: fromDom$2,
  1355. fromPoint: fromPoint$2,
  1356. };
  1357. const toArray = (target, f) => {
  1358. const r = [];
  1359. const recurse = (e) => {
  1360. r.push(e);
  1361. return f(e);
  1362. };
  1363. let cur = f(target);
  1364. do {
  1365. cur = cur.bind(recurse);
  1366. } while (cur.isSome());
  1367. return r;
  1368. };
  1369. const is$1 = (element, selector) => {
  1370. const dom = element.dom;
  1371. if (dom.nodeType !== ELEMENT) {
  1372. return false;
  1373. } else {
  1374. const elem = dom;
  1375. if (elem.matches !== undefined) {
  1376. return elem.matches(selector);
  1377. } else if (elem.msMatchesSelector !== undefined) {
  1378. return elem.msMatchesSelector(selector);
  1379. } else if (elem.webkitMatchesSelector !== undefined) {
  1380. return elem.webkitMatchesSelector(selector);
  1381. } else if (elem.mozMatchesSelector !== undefined) {
  1382. return elem.mozMatchesSelector(selector);
  1383. } else {
  1384. throw new Error("Browser lacks native selectors");
  1385. }
  1386. }
  1387. };
  1388. const bypassSelector = (dom) =>
  1389. (dom.nodeType !== ELEMENT &&
  1390. dom.nodeType !== DOCUMENT &&
  1391. dom.nodeType !== DOCUMENT_FRAGMENT) ||
  1392. dom.childElementCount === 0;
  1393. const all = (selector, scope) => {
  1394. const base = scope === undefined ? document : scope.dom;
  1395. return bypassSelector(base)
  1396. ? []
  1397. : map$3(base.querySelectorAll(selector), SugarElement.fromDom);
  1398. };
  1399. const one = (selector, scope) => {
  1400. const base = scope === undefined ? document : scope.dom;
  1401. return bypassSelector(base)
  1402. ? Optional.none()
  1403. : Optional.from(base.querySelector(selector)).map(SugarElement.fromDom);
  1404. };
  1405. const eq = (e1, e2) => e1.dom === e2.dom;
  1406. const contains = (e1, e2) => {
  1407. const d1 = e1.dom;
  1408. const d2 = e2.dom;
  1409. return d1 === d2 ? false : d1.contains(d2);
  1410. };
  1411. const owner$1 = (element) => SugarElement.fromDom(element.dom.ownerDocument);
  1412. const documentOrOwner = (dos) => (isDocument$2(dos) ? dos : owner$1(dos));
  1413. const documentElement = (element) =>
  1414. SugarElement.fromDom(documentOrOwner(element).dom.documentElement);
  1415. const defaultView = (element) =>
  1416. SugarElement.fromDom(documentOrOwner(element).dom.defaultView);
  1417. const parent = (element) =>
  1418. Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
  1419. const parentElement = (element) =>
  1420. Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
  1421. const parents$1 = (element, isRoot) => {
  1422. const stop = isFunction(isRoot) ? isRoot : never;
  1423. let dom = element.dom;
  1424. const ret = [];
  1425. while (dom.parentNode !== null && dom.parentNode !== undefined) {
  1426. const rawParent = dom.parentNode;
  1427. const p = SugarElement.fromDom(rawParent);
  1428. ret.push(p);
  1429. if (stop(p) === true) {
  1430. break;
  1431. } else {
  1432. dom = rawParent;
  1433. }
  1434. }
  1435. return ret;
  1436. };
  1437. const siblings = (element) => {
  1438. const filterSelf = (elements) => filter$5(elements, (x) => !eq(element, x));
  1439. return parent(element).map(children$1).map(filterSelf).getOr([]);
  1440. };
  1441. const prevSibling = (element) =>
  1442. Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
  1443. const nextSibling = (element) =>
  1444. Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
  1445. const prevSiblings = (element) => reverse(toArray(element, prevSibling));
  1446. const nextSiblings = (element) => toArray(element, nextSibling);
  1447. const children$1 = (element) =>
  1448. map$3(element.dom.childNodes, SugarElement.fromDom);
  1449. const child$1 = (element, index) => {
  1450. const cs = element.dom.childNodes;
  1451. return Optional.from(cs[index]).map(SugarElement.fromDom);
  1452. };
  1453. const firstChild = (element) => child$1(element, 0);
  1454. const lastChild = (element) =>
  1455. child$1(element, element.dom.childNodes.length - 1);
  1456. const childNodesCount = (element) => element.dom.childNodes.length;
  1457. const hasChildNodes = (element) => element.dom.hasChildNodes();
  1458. const getHead = (doc) => {
  1459. const b = doc.dom.head;
  1460. if (b === null || b === undefined) {
  1461. throw new Error("Head is not available yet");
  1462. }
  1463. return SugarElement.fromDom(b);
  1464. };
  1465. const isShadowRoot = (dos) =>
  1466. isDocumentFragment$1(dos) && isNonNullable(dos.dom.host);
  1467. const supported =
  1468. isFunction(Element.prototype.attachShadow) &&
  1469. isFunction(Node.prototype.getRootNode);
  1470. const isSupported$1 = constant(supported);
  1471. const getRootNode = supported
  1472. ? (e) => SugarElement.fromDom(e.dom.getRootNode())
  1473. : documentOrOwner;
  1474. const getStyleContainer = (dos) =>
  1475. isShadowRoot(dos) ? dos : getHead(documentOrOwner(dos));
  1476. const getContentContainer = (dos) =>
  1477. isShadowRoot(dos)
  1478. ? dos
  1479. : SugarElement.fromDom(documentOrOwner(dos).dom.body);
  1480. const getShadowRoot = (e) => {
  1481. const r = getRootNode(e);
  1482. return isShadowRoot(r) ? Optional.some(r) : Optional.none();
  1483. };
  1484. const getShadowHost = (e) => SugarElement.fromDom(e.dom.host);
  1485. const getOriginalEventTarget = (event) => {
  1486. if (isSupported$1() && isNonNullable(event.target)) {
  1487. const el = SugarElement.fromDom(event.target);
  1488. if (isElement$7(el) && isOpenShadowHost(el)) {
  1489. if (event.composed && event.composedPath) {
  1490. const composedPath = event.composedPath();
  1491. if (composedPath) {
  1492. return head(composedPath);
  1493. }
  1494. }
  1495. }
  1496. }
  1497. return Optional.from(event.target);
  1498. };
  1499. const isOpenShadowHost = (element) => isNonNullable(element.dom.shadowRoot);
  1500. const inBody = (element) => {
  1501. const dom = isText$b(element) ? element.dom.parentNode : element.dom;
  1502. if (dom === undefined || dom === null || dom.ownerDocument === null) {
  1503. return false;
  1504. }
  1505. const doc = dom.ownerDocument;
  1506. return getShadowRoot(SugarElement.fromDom(dom)).fold(
  1507. () => doc.body.contains(dom),
  1508. compose1(inBody, getShadowHost)
  1509. );
  1510. };
  1511. var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
  1512. if (is(scope, a)) {
  1513. return Optional.some(scope);
  1514. } else if (isFunction(isRoot) && isRoot(scope)) {
  1515. return Optional.none();
  1516. } else {
  1517. return ancestor(scope, a, isRoot);
  1518. }
  1519. };
  1520. const ancestor$4 = (scope, predicate, isRoot) => {
  1521. let element = scope.dom;
  1522. const stop = isFunction(isRoot) ? isRoot : never;
  1523. while (element.parentNode) {
  1524. element = element.parentNode;
  1525. const el = SugarElement.fromDom(element);
  1526. if (predicate(el)) {
  1527. return Optional.some(el);
  1528. } else if (stop(el)) {
  1529. break;
  1530. }
  1531. }
  1532. return Optional.none();
  1533. };
  1534. const closest$4 = (scope, predicate, isRoot) => {
  1535. const is = (s, test) => test(s);
  1536. return ClosestOrAncestor(is, ancestor$4, scope, predicate, isRoot);
  1537. };
  1538. const sibling$1 = (scope, predicate) => {
  1539. const element = scope.dom;
  1540. if (!element.parentNode) {
  1541. return Optional.none();
  1542. }
  1543. return child(
  1544. SugarElement.fromDom(element.parentNode),
  1545. (x) => !eq(scope, x) && predicate(x)
  1546. );
  1547. };
  1548. const child = (scope, predicate) => {
  1549. const pred = (node) => predicate(SugarElement.fromDom(node));
  1550. const result = find$2(scope.dom.childNodes, pred);
  1551. return result.map(SugarElement.fromDom);
  1552. };
  1553. const descendant$1 = (scope, predicate) => {
  1554. const descend = (node) => {
  1555. for (let i = 0; i < node.childNodes.length; i++) {
  1556. const child = SugarElement.fromDom(node.childNodes[i]);
  1557. if (predicate(child)) {
  1558. return Optional.some(child);
  1559. }
  1560. const res = descend(node.childNodes[i]);
  1561. if (res.isSome()) {
  1562. return res;
  1563. }
  1564. }
  1565. return Optional.none();
  1566. };
  1567. return descend(scope.dom);
  1568. };
  1569. const ancestor$3 = (scope, selector, isRoot) =>
  1570. ancestor$4(scope, (e) => is$1(e, selector), isRoot);
  1571. const descendant = (scope, selector) => one(selector, scope);
  1572. const closest$3 = (scope, selector, isRoot) => {
  1573. const is = (element, selector) => is$1(element, selector);
  1574. return ClosestOrAncestor(is, ancestor$3, scope, selector, isRoot);
  1575. };
  1576. const closest$2 = (target) => closest$3(target, "[contenteditable]");
  1577. const isEditable$3 = (element, assumeEditable = false) => {
  1578. if (inBody(element)) {
  1579. return element.dom.isContentEditable;
  1580. } else {
  1581. return closest$2(element).fold(
  1582. constant(assumeEditable),
  1583. (editable) => getRaw$1(editable) === "true"
  1584. );
  1585. }
  1586. };
  1587. const getRaw$1 = (element) => element.dom.contentEditable;
  1588. const isSupported = (dom) =>
  1589. dom.style !== undefined && isFunction(dom.style.getPropertyValue);
  1590. const internalSet = (dom, property, value) => {
  1591. if (!isString(value)) {
  1592. console.error(
  1593. "Invalid call to CSS.set. Property ",
  1594. property,
  1595. ":: Value ",
  1596. value,
  1597. ":: Element ",
  1598. dom
  1599. );
  1600. throw new Error("CSS value must be a string: " + value);
  1601. }
  1602. if (isSupported(dom)) {
  1603. dom.style.setProperty(property, value);
  1604. }
  1605. };
  1606. const internalRemove = (dom, property) => {
  1607. if (isSupported(dom)) {
  1608. dom.style.removeProperty(property);
  1609. }
  1610. };
  1611. const set$2 = (element, property, value) => {
  1612. const dom = element.dom;
  1613. internalSet(dom, property, value);
  1614. };
  1615. const setAll = (element, css) => {
  1616. const dom = element.dom;
  1617. each$d(css, (v, k) => {
  1618. internalSet(dom, k, v);
  1619. });
  1620. };
  1621. const get$7 = (element, property) => {
  1622. const dom = element.dom;
  1623. const styles = window.getComputedStyle(dom);
  1624. const r = styles.getPropertyValue(property);
  1625. return r === "" && !inBody(element) ? getUnsafeProperty(dom, property) : r;
  1626. };
  1627. const getUnsafeProperty = (dom, property) =>
  1628. isSupported(dom) ? dom.style.getPropertyValue(property) : "";
  1629. const getRaw = (element, property) => {
  1630. const dom = element.dom;
  1631. const raw = getUnsafeProperty(dom, property);
  1632. return Optional.from(raw).filter((r) => r.length > 0);
  1633. };
  1634. const getAllRaw = (element) => {
  1635. const css = {};
  1636. const dom = element.dom;
  1637. if (isSupported(dom)) {
  1638. for (let i = 0; i < dom.style.length; i++) {
  1639. const ruleName = dom.style.item(i);
  1640. css[ruleName] = dom.style[ruleName];
  1641. }
  1642. }
  1643. return css;
  1644. };
  1645. const remove$6 = (element, property) => {
  1646. const dom = element.dom;
  1647. internalRemove(dom, property);
  1648. if (is$2(getOpt(element, "style").map(trim$3), "")) {
  1649. remove$a(element, "style");
  1650. }
  1651. };
  1652. const reflow = (e) => e.dom.offsetWidth;
  1653. const before$3 = (marker, element) => {
  1654. const parent$1 = parent(marker);
  1655. parent$1.each((v) => {
  1656. v.dom.insertBefore(element.dom, marker.dom);
  1657. });
  1658. };
  1659. const after$4 = (marker, element) => {
  1660. const sibling = nextSibling(marker);
  1661. sibling.fold(
  1662. () => {
  1663. const parent$1 = parent(marker);
  1664. parent$1.each((v) => {
  1665. append$1(v, element);
  1666. });
  1667. },
  1668. (v) => {
  1669. before$3(v, element);
  1670. }
  1671. );
  1672. };
  1673. const prepend = (parent, element) => {
  1674. const firstChild$1 = firstChild(parent);
  1675. firstChild$1.fold(
  1676. () => {
  1677. append$1(parent, element);
  1678. },
  1679. (v) => {
  1680. parent.dom.insertBefore(element.dom, v.dom);
  1681. }
  1682. );
  1683. };
  1684. const append$1 = (parent, element) => {
  1685. parent.dom.appendChild(element.dom);
  1686. };
  1687. const wrap$2 = (element, wrapper) => {
  1688. before$3(element, wrapper);
  1689. append$1(wrapper, element);
  1690. };
  1691. const after$3 = (marker, elements) => {
  1692. each$e(elements, (x, i) => {
  1693. const e = i === 0 ? marker : elements[i - 1];
  1694. after$4(e, x);
  1695. });
  1696. };
  1697. const append = (parent, elements) => {
  1698. each$e(elements, (x) => {
  1699. append$1(parent, x);
  1700. });
  1701. };
  1702. const empty = (element) => {
  1703. element.dom.textContent = "";
  1704. each$e(children$1(element), (rogue) => {
  1705. remove$5(rogue);
  1706. });
  1707. };
  1708. const remove$5 = (element) => {
  1709. const dom = element.dom;
  1710. if (dom.parentNode !== null) {
  1711. dom.parentNode.removeChild(dom);
  1712. }
  1713. };
  1714. const unwrap = (wrapper) => {
  1715. const children = children$1(wrapper);
  1716. if (children.length > 0) {
  1717. after$3(wrapper, children);
  1718. }
  1719. remove$5(wrapper);
  1720. };
  1721. const fromHtml = (html, scope) => {
  1722. const doc = scope || document;
  1723. const div = doc.createElement("div");
  1724. div.innerHTML = html;
  1725. return children$1(SugarElement.fromDom(div));
  1726. };
  1727. const fromDom$1 = (nodes) => map$3(nodes, SugarElement.fromDom);
  1728. const get$6 = (element) => element.dom.innerHTML;
  1729. const set$1 = (element, content) => {
  1730. const owner = owner$1(element);
  1731. const docDom = owner.dom;
  1732. const fragment = SugarElement.fromDom(docDom.createDocumentFragment());
  1733. const contentElements = fromHtml(content, docDom);
  1734. append(fragment, contentElements);
  1735. empty(element);
  1736. append$1(element, fragment);
  1737. };
  1738. const getOuter = (element) => {
  1739. const container = SugarElement.fromTag("div");
  1740. const clone = SugarElement.fromDom(element.dom.cloneNode(true));
  1741. append$1(container, clone);
  1742. return get$6(container);
  1743. };
  1744. const mkEvent = (target, x, y, stop, prevent, kill, raw) => ({
  1745. target,
  1746. x,
  1747. y,
  1748. stop,
  1749. prevent,
  1750. kill,
  1751. raw,
  1752. });
  1753. const fromRawEvent = (rawEvent) => {
  1754. const target = SugarElement.fromDom(
  1755. getOriginalEventTarget(rawEvent).getOr(rawEvent.target)
  1756. );
  1757. const stop = () => rawEvent.stopPropagation();
  1758. const prevent = () => rawEvent.preventDefault();
  1759. const kill = compose(prevent, stop);
  1760. return mkEvent(
  1761. target,
  1762. rawEvent.clientX,
  1763. rawEvent.clientY,
  1764. stop,
  1765. prevent,
  1766. kill,
  1767. rawEvent
  1768. );
  1769. };
  1770. const handle$1 = (filter, handler) => (rawEvent) => {
  1771. if (filter(rawEvent)) {
  1772. handler(fromRawEvent(rawEvent));
  1773. }
  1774. };
  1775. const binder = (element, event, filter, handler, useCapture) => {
  1776. const wrapped = handle$1(filter, handler);
  1777. element.dom.addEventListener(event, wrapped, useCapture);
  1778. return { unbind: curry(unbind, element, event, wrapped, useCapture) };
  1779. };
  1780. const bind$2 = (element, event, filter, handler) =>
  1781. binder(element, event, filter, handler, false);
  1782. const unbind = (element, event, handler, useCapture) => {
  1783. element.dom.removeEventListener(event, handler, useCapture);
  1784. };
  1785. const r = (left, top) => {
  1786. const translate = (x, y) => r(left + x, top + y);
  1787. return {
  1788. left,
  1789. top,
  1790. translate,
  1791. };
  1792. };
  1793. const SugarPosition = r;
  1794. const boxPosition = (dom) => {
  1795. const box = dom.getBoundingClientRect();
  1796. return SugarPosition(box.left, box.top);
  1797. };
  1798. const firstDefinedOrZero = (a, b) => {
  1799. if (a !== undefined) {
  1800. return a;
  1801. } else {
  1802. return b !== undefined ? b : 0;
  1803. }
  1804. };
  1805. const absolute = (element) => {
  1806. const doc = element.dom.ownerDocument;
  1807. const body = doc.body;
  1808. const win = doc.defaultView;
  1809. const html = doc.documentElement;
  1810. if (body === element.dom) {
  1811. return SugarPosition(body.offsetLeft, body.offsetTop);
  1812. }
  1813. const scrollTop = firstDefinedOrZero(
  1814. win === null || win === void 0 ? void 0 : win.pageYOffset,
  1815. html.scrollTop
  1816. );
  1817. const scrollLeft = firstDefinedOrZero(
  1818. win === null || win === void 0 ? void 0 : win.pageXOffset,
  1819. html.scrollLeft
  1820. );
  1821. const clientTop = firstDefinedOrZero(html.clientTop, body.clientTop);
  1822. const clientLeft = firstDefinedOrZero(html.clientLeft, body.clientLeft);
  1823. return viewport(element).translate(
  1824. scrollLeft - clientLeft,
  1825. scrollTop - clientTop
  1826. );
  1827. };
  1828. const viewport = (element) => {
  1829. const dom = element.dom;
  1830. const doc = dom.ownerDocument;
  1831. const body = doc.body;
  1832. if (body === dom) {
  1833. return SugarPosition(body.offsetLeft, body.offsetTop);
  1834. }
  1835. if (!inBody(element)) {
  1836. return SugarPosition(0, 0);
  1837. }
  1838. return boxPosition(dom);
  1839. };
  1840. const get$5 = (_DOC) => {
  1841. const doc = _DOC !== undefined ? _DOC.dom : document;
  1842. const x = doc.body.scrollLeft || doc.documentElement.scrollLeft;
  1843. const y = doc.body.scrollTop || doc.documentElement.scrollTop;
  1844. return SugarPosition(x, y);
  1845. };
  1846. const to = (x, y, _DOC) => {
  1847. const doc = _DOC !== undefined ? _DOC.dom : document;
  1848. const win = doc.defaultView;
  1849. if (win) {
  1850. win.scrollTo(x, y);
  1851. }
  1852. };
  1853. const intoView = (element, alignToTop) => {
  1854. const isSafari = detect$2().browser.isSafari();
  1855. if (isSafari && isFunction(element.dom.scrollIntoViewIfNeeded)) {
  1856. element.dom.scrollIntoViewIfNeeded(false);
  1857. } else {
  1858. element.dom.scrollIntoView(alignToTop);
  1859. }
  1860. };
  1861. const get$4 = (_win) => {
  1862. const win = _win === undefined ? window : _win;
  1863. if (detect$2().browser.isFirefox()) {
  1864. return Optional.none();
  1865. } else {
  1866. return Optional.from(win.visualViewport);
  1867. }
  1868. };
  1869. const bounds = (x, y, width, height) => ({
  1870. x,
  1871. y,
  1872. width,
  1873. height,
  1874. right: x + width,
  1875. bottom: y + height,
  1876. });
  1877. const getBounds = (_win) => {
  1878. const win = _win === undefined ? window : _win;
  1879. const doc = win.document;
  1880. const scroll = get$5(SugarElement.fromDom(doc));
  1881. return get$4(win).fold(
  1882. () => {
  1883. const html = win.document.documentElement;
  1884. const width = html.clientWidth;
  1885. const height = html.clientHeight;
  1886. return bounds(scroll.left, scroll.top, width, height);
  1887. },
  1888. (visualViewport) =>
  1889. bounds(
  1890. Math.max(visualViewport.pageLeft, scroll.left),
  1891. Math.max(visualViewport.pageTop, scroll.top),
  1892. visualViewport.width,
  1893. visualViewport.height
  1894. )
  1895. );
  1896. };
  1897. const children = (scope, predicate) => filter$5(children$1(scope), predicate);
  1898. const descendants$1 = (scope, predicate) => {
  1899. let result = [];
  1900. each$e(children$1(scope), (x) => {
  1901. if (predicate(x)) {
  1902. result = result.concat([x]);
  1903. }
  1904. result = result.concat(descendants$1(x, predicate));
  1905. });
  1906. return result;
  1907. };
  1908. const descendants = (scope, selector) => all(selector, scope);
  1909. const ancestor$2 = (scope, selector, isRoot) =>
  1910. ancestor$3(scope, selector, isRoot).isSome();
  1911. class DomTreeWalker {
  1912. constructor(startNode, rootNode) {
  1913. this.node = startNode;
  1914. this.rootNode = rootNode;
  1915. this.current = this.current.bind(this);
  1916. this.next = this.next.bind(this);
  1917. this.prev = this.prev.bind(this);
  1918. this.prev2 = this.prev2.bind(this);
  1919. }
  1920. current() {
  1921. return this.node;
  1922. }
  1923. next(shallow) {
  1924. this.node = this.findSibling(
  1925. this.node,
  1926. "firstChild",
  1927. "nextSibling",
  1928. shallow
  1929. );
  1930. return this.node;
  1931. }
  1932. prev(shallow) {
  1933. this.node = this.findSibling(
  1934. this.node,
  1935. "lastChild",
  1936. "previousSibling",
  1937. shallow
  1938. );
  1939. return this.node;
  1940. }
  1941. prev2(shallow) {
  1942. this.node = this.findPreviousNode(this.node, shallow);
  1943. return this.node;
  1944. }
  1945. findSibling(node, startName, siblingName, shallow) {
  1946. if (node) {
  1947. if (!shallow && node[startName]) {
  1948. return node[startName];
  1949. }
  1950. if (node !== this.rootNode) {
  1951. let sibling = node[siblingName];
  1952. if (sibling) {
  1953. return sibling;
  1954. }
  1955. for (
  1956. let parent = node.parentNode;
  1957. parent && parent !== this.rootNode;
  1958. parent = parent.parentNode
  1959. ) {
  1960. sibling = parent[siblingName];
  1961. if (sibling) {
  1962. return sibling;
  1963. }
  1964. }
  1965. }
  1966. }
  1967. return undefined;
  1968. }
  1969. findPreviousNode(node, shallow) {
  1970. if (node) {
  1971. const sibling = node.previousSibling;
  1972. if (this.rootNode && sibling === this.rootNode) {
  1973. return;
  1974. }
  1975. if (sibling) {
  1976. if (!shallow) {
  1977. for (
  1978. let child = sibling.lastChild;
  1979. child;
  1980. child = child.lastChild
  1981. ) {
  1982. if (!child.lastChild) {
  1983. return child;
  1984. }
  1985. }
  1986. }
  1987. return sibling;
  1988. }
  1989. const parent = node.parentNode;
  1990. if (parent && parent !== this.rootNode) {
  1991. return parent;
  1992. }
  1993. }
  1994. return undefined;
  1995. }
  1996. }
  1997. const isNodeType = (type) => {
  1998. return (node) => {
  1999. return !!node && node.nodeType === type;
  2000. };
  2001. };
  2002. const isRestrictedNode = (node) => !!node && !Object.getPrototypeOf(node);
  2003. const isElement$6 = isNodeType(1);
  2004. const matchNodeName = (name) => {
  2005. const lowerCasedName = name.toLowerCase();
  2006. return (node) =>
  2007. isNonNullable(node) && node.nodeName.toLowerCase() === lowerCasedName;
  2008. };
  2009. const matchNodeNames = (names) => {
  2010. const lowerCasedNames = names.map((s) => s.toLowerCase());
  2011. return (node) => {
  2012. if (node && node.nodeName) {
  2013. const nodeName = node.nodeName.toLowerCase();
  2014. return contains$2(lowerCasedNames, nodeName);
  2015. }
  2016. return false;
  2017. };
  2018. };
  2019. const matchStyleValues = (name, values) => {
  2020. const items = values.toLowerCase().split(" ");
  2021. return (node) => {
  2022. if (isElement$6(node)) {
  2023. const win = node.ownerDocument.defaultView;
  2024. if (win) {
  2025. for (let i = 0; i < items.length; i++) {
  2026. const computed = win.getComputedStyle(node, null);
  2027. const cssValue = computed ? computed.getPropertyValue(name) : null;
  2028. if (cssValue === items[i]) {
  2029. return true;
  2030. }
  2031. }
  2032. }
  2033. }
  2034. return false;
  2035. };
  2036. };
  2037. const hasAttribute = (attrName) => {
  2038. return (node) => {
  2039. return isElement$6(node) && node.hasAttribute(attrName);
  2040. };
  2041. };
  2042. const hasAttributeValue = (attrName, attrValue) => {
  2043. return (node) => {
  2044. return isElement$6(node) && node.getAttribute(attrName) === attrValue;
  2045. };
  2046. };
  2047. const isBogus$2 = (node) =>
  2048. isElement$6(node) && node.hasAttribute("data-mce-bogus");
  2049. const isBogusAll$1 = (node) =>
  2050. isElement$6(node) && node.getAttribute("data-mce-bogus") === "all";
  2051. const isTable$2 = (node) => isElement$6(node) && node.tagName === "TABLE";
  2052. const hasContentEditableState = (value) => {
  2053. return (node) => {
  2054. if (isElement$6(node)) {
  2055. if (node.contentEditable === value) {
  2056. return true;
  2057. }
  2058. if (node.getAttribute("data-mce-contenteditable") === value) {
  2059. return true;
  2060. }
  2061. }
  2062. return false;
  2063. };
  2064. };
  2065. const isTextareaOrInput = matchNodeNames(["textarea", "input"]);
  2066. const isText$a = isNodeType(3);
  2067. const isCData = isNodeType(4);
  2068. const isPi = isNodeType(7);
  2069. const isComment = isNodeType(8);
  2070. const isDocument$1 = isNodeType(9);
  2071. const isDocumentFragment = isNodeType(11);
  2072. const isBr$6 = matchNodeName("br");
  2073. const isImg = matchNodeName("img");
  2074. const isContentEditableTrue$3 = hasContentEditableState("true");
  2075. const isContentEditableFalse$b = hasContentEditableState("false");
  2076. const isTableCell$3 = matchNodeNames(["td", "th"]);
  2077. const isTableCellOrCaption = matchNodeNames(["td", "th", "caption"]);
  2078. const isMedia$2 = matchNodeNames(["video", "audio", "object", "embed"]);
  2079. const isListItem$2 = matchNodeName("li");
  2080. const isDetails = matchNodeName("details");
  2081. const isSummary = matchNodeName("summary");
  2082. const zeroWidth = "\uFEFF";
  2083. const nbsp = "\xA0";
  2084. const isZwsp$2 = (char) => char === zeroWidth;
  2085. const removeZwsp = (s) => s.replace(/\uFEFF/g, "");
  2086. const NodeValue = (is, name) => {
  2087. const get = (element) => {
  2088. if (!is(element)) {
  2089. throw new Error(
  2090. "Can only get " + name + " value of a " + name + " node"
  2091. );
  2092. }
  2093. return getOption(element).getOr("");
  2094. };
  2095. const getOption = (element) =>
  2096. is(element) ? Optional.from(element.dom.nodeValue) : Optional.none();
  2097. const set = (element, value) => {
  2098. if (!is(element)) {
  2099. throw new Error(
  2100. "Can only set raw " + name + " value of a " + name + " node"
  2101. );
  2102. }
  2103. element.dom.nodeValue = value;
  2104. };
  2105. return {
  2106. get,
  2107. getOption,
  2108. set,
  2109. };
  2110. };
  2111. const api$1 = NodeValue(isText$b, "text");
  2112. const get$3 = (element) => api$1.get(element);
  2113. const getOption = (element) => api$1.getOption(element);
  2114. const set = (element, value) => api$1.set(element, value);
  2115. const blocks = [
  2116. "article",
  2117. "aside",
  2118. "details",
  2119. "div",
  2120. "dt",
  2121. "figcaption",
  2122. "footer",
  2123. "form",
  2124. "fieldset",
  2125. "header",
  2126. "hgroup",
  2127. "html",
  2128. "main",
  2129. "nav",
  2130. "section",
  2131. "summary",
  2132. "body",
  2133. "p",
  2134. "dl",
  2135. "multicol",
  2136. "dd",
  2137. "figure",
  2138. "address",
  2139. "center",
  2140. "blockquote",
  2141. "h1",
  2142. "h2",
  2143. "h3",
  2144. "h4",
  2145. "h5",
  2146. "h6",
  2147. "listing",
  2148. "xmp",
  2149. "pre",
  2150. "plaintext",
  2151. "menu",
  2152. "dir",
  2153. "ul",
  2154. "ol",
  2155. "li",
  2156. "hr",
  2157. "table",
  2158. "tbody",
  2159. "thead",
  2160. "tfoot",
  2161. "th",
  2162. "tr",
  2163. "td",
  2164. "caption",
  2165. ];
  2166. const tableCells = ["td", "th"];
  2167. const tableSections = ["thead", "tbody", "tfoot"];
  2168. const textBlocks = [
  2169. "h1",
  2170. "h2",
  2171. "h3",
  2172. "h4",
  2173. "h5",
  2174. "h6",
  2175. "p",
  2176. "div",
  2177. "address",
  2178. "pre",
  2179. "form",
  2180. "blockquote",
  2181. "center",
  2182. "dir",
  2183. "fieldset",
  2184. "header",
  2185. "footer",
  2186. "article",
  2187. "section",
  2188. "hgroup",
  2189. "aside",
  2190. "nav",
  2191. "figure",
  2192. ];
  2193. const headings = ["h1", "h2", "h3", "h4", "h5", "h6"];
  2194. const listItems$1 = ["li", "dd", "dt"];
  2195. const lists = ["ul", "ol", "dl"];
  2196. const wsElements = ["pre", "script", "textarea", "style"];
  2197. const wrapBlockElements = ["pre"].concat(headings);
  2198. const lazyLookup = (items) => {
  2199. let lookup;
  2200. return (node) => {
  2201. lookup = lookup ? lookup : mapToObject(items, always);
  2202. return has$2(lookup, name(node));
  2203. };
  2204. };
  2205. const isBlock$2 = lazyLookup(blocks);
  2206. const isTable$1 = (node) => name(node) === "table";
  2207. const isInline$1 = (node) => isElement$7(node) && !isBlock$2(node);
  2208. const isBr$5 = (node) => isElement$7(node) && name(node) === "br";
  2209. const isTextBlock$2 = lazyLookup(textBlocks);
  2210. const isList = lazyLookup(lists);
  2211. const isListItem$1 = lazyLookup(listItems$1);
  2212. const isTableSection = lazyLookup(tableSections);
  2213. const isTableCell$2 = lazyLookup(tableCells);
  2214. const isWsPreserveElement = lazyLookup(wsElements);
  2215. const isWrapBlockElement = lazyLookup(wrapBlockElements);
  2216. const isWrapElement = (node) => isWrapBlockElement(node) || isInline$1(node);
  2217. const getLastChildren$1 = (elm) => {
  2218. const children = [];
  2219. let rawNode = elm.dom;
  2220. while (rawNode) {
  2221. children.push(SugarElement.fromDom(rawNode));
  2222. rawNode = rawNode.lastChild;
  2223. }
  2224. return children;
  2225. };
  2226. const removeTrailingBr = (elm) => {
  2227. const allBrs = descendants(elm, "br");
  2228. const brs = filter$5(getLastChildren$1(elm).slice(-1), isBr$5);
  2229. if (allBrs.length === brs.length) {
  2230. each$e(brs, remove$5);
  2231. }
  2232. };
  2233. const createPaddingBr = () => {
  2234. const br = SugarElement.fromTag("br");
  2235. set$3(br, "data-mce-bogus", "1");
  2236. return br;
  2237. };
  2238. const fillWithPaddingBr = (elm) => {
  2239. empty(elm);
  2240. append$1(elm, createPaddingBr());
  2241. };
  2242. const trimBlockTrailingBr = (elm) => {
  2243. lastChild(elm).each((lastChild) => {
  2244. prevSibling(lastChild).each((lastChildPrevSibling) => {
  2245. if (
  2246. isBlock$2(elm) &&
  2247. isBr$5(lastChild) &&
  2248. isBlock$2(lastChildPrevSibling)
  2249. ) {
  2250. remove$5(lastChild);
  2251. }
  2252. });
  2253. });
  2254. };
  2255. const ZWSP$1 = zeroWidth;
  2256. const isZwsp$1 = isZwsp$2;
  2257. const trim$1 = removeZwsp;
  2258. const isElement$5 = isElement$6;
  2259. const isText$9 = isText$a;
  2260. const isCaretContainerBlock$1 = (node) => {
  2261. if (isText$9(node)) {
  2262. node = node.parentNode;
  2263. }
  2264. return isElement$5(node) && node.hasAttribute("data-mce-caret");
  2265. };
  2266. const isCaretContainerInline = (node) =>
  2267. isText$9(node) && isZwsp$1(node.data);
  2268. const isCaretContainer$2 = (node) =>
  2269. isCaretContainerBlock$1(node) || isCaretContainerInline(node);
  2270. const hasContent = (node) =>
  2271. node.firstChild !== node.lastChild || !isBr$6(node.firstChild);
  2272. const insertInline$1 = (node, before) => {
  2273. var _a;
  2274. const doc =
  2275. (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
  2276. const textNode = doc.createTextNode(ZWSP$1);
  2277. const parentNode = node.parentNode;
  2278. if (!before) {
  2279. const sibling = node.nextSibling;
  2280. if (isText$9(sibling)) {
  2281. if (isCaretContainer$2(sibling)) {
  2282. return sibling;
  2283. }
  2284. if (startsWithCaretContainer$1(sibling)) {
  2285. sibling.splitText(1);
  2286. return sibling;
  2287. }
  2288. }
  2289. if (node.nextSibling) {
  2290. parentNode === null || parentNode === void 0
  2291. ? void 0
  2292. : parentNode.insertBefore(textNode, node.nextSibling);
  2293. } else {
  2294. parentNode === null || parentNode === void 0
  2295. ? void 0
  2296. : parentNode.appendChild(textNode);
  2297. }
  2298. } else {
  2299. const sibling = node.previousSibling;
  2300. if (isText$9(sibling)) {
  2301. if (isCaretContainer$2(sibling)) {
  2302. return sibling;
  2303. }
  2304. if (endsWithCaretContainer$1(sibling)) {
  2305. return sibling.splitText(sibling.data.length - 1);
  2306. }
  2307. }
  2308. parentNode === null || parentNode === void 0
  2309. ? void 0
  2310. : parentNode.insertBefore(textNode, node);
  2311. }
  2312. return textNode;
  2313. };
  2314. const isBeforeInline = (pos) => {
  2315. const container = pos.container();
  2316. if (!isText$a(container)) {
  2317. return false;
  2318. }
  2319. return (
  2320. container.data.charAt(pos.offset()) === ZWSP$1 ||
  2321. (pos.isAtStart() && isCaretContainerInline(container.previousSibling))
  2322. );
  2323. };
  2324. const isAfterInline = (pos) => {
  2325. const container = pos.container();
  2326. if (!isText$a(container)) {
  2327. return false;
  2328. }
  2329. return (
  2330. container.data.charAt(pos.offset() - 1) === ZWSP$1 ||
  2331. (pos.isAtEnd() && isCaretContainerInline(container.nextSibling))
  2332. );
  2333. };
  2334. const insertBlock = (blockName, node, before) => {
  2335. var _a;
  2336. const doc =
  2337. (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
  2338. const blockNode = doc.createElement(blockName);
  2339. blockNode.setAttribute("data-mce-caret", before ? "before" : "after");
  2340. blockNode.setAttribute("data-mce-bogus", "all");
  2341. blockNode.appendChild(createPaddingBr().dom);
  2342. const parentNode = node.parentNode;
  2343. if (!before) {
  2344. if (node.nextSibling) {
  2345. parentNode === null || parentNode === void 0
  2346. ? void 0
  2347. : parentNode.insertBefore(blockNode, node.nextSibling);
  2348. } else {
  2349. parentNode === null || parentNode === void 0
  2350. ? void 0
  2351. : parentNode.appendChild(blockNode);
  2352. }
  2353. } else {
  2354. parentNode === null || parentNode === void 0
  2355. ? void 0
  2356. : parentNode.insertBefore(blockNode, node);
  2357. }
  2358. return blockNode;
  2359. };
  2360. const startsWithCaretContainer$1 = (node) =>
  2361. isText$9(node) && node.data[0] === ZWSP$1;
  2362. const endsWithCaretContainer$1 = (node) =>
  2363. isText$9(node) && node.data[node.data.length - 1] === ZWSP$1;
  2364. const trimBogusBr = (elm) => {
  2365. var _a;
  2366. const brs = elm.getElementsByTagName("br");
  2367. const lastBr = brs[brs.length - 1];
  2368. if (isBogus$2(lastBr)) {
  2369. (_a = lastBr.parentNode) === null || _a === void 0
  2370. ? void 0
  2371. : _a.removeChild(lastBr);
  2372. }
  2373. };
  2374. const showCaretContainerBlock = (caretContainer) => {
  2375. if (caretContainer && caretContainer.hasAttribute("data-mce-caret")) {
  2376. trimBogusBr(caretContainer);
  2377. caretContainer.removeAttribute("data-mce-caret");
  2378. caretContainer.removeAttribute("data-mce-bogus");
  2379. caretContainer.removeAttribute("style");
  2380. caretContainer.removeAttribute("data-mce-style");
  2381. caretContainer.removeAttribute("_moz_abspos");
  2382. return caretContainer;
  2383. }
  2384. return null;
  2385. };
  2386. const isRangeInCaretContainerBlock = (range) =>
  2387. isCaretContainerBlock$1(range.startContainer);
  2388. const isContentEditableTrue$2 = isContentEditableTrue$3;
  2389. const isContentEditableFalse$a = isContentEditableFalse$b;
  2390. const isBr$4 = isBr$6;
  2391. const isText$8 = isText$a;
  2392. const isInvalidTextElement = matchNodeNames(["script", "style", "textarea"]);
  2393. const isAtomicInline = matchNodeNames([
  2394. "img",
  2395. "input",
  2396. "textarea",
  2397. "hr",
  2398. "iframe",
  2399. "video",
  2400. "audio",
  2401. "object",
  2402. "embed",
  2403. ]);
  2404. const isTable = matchNodeNames(["table"]);
  2405. const isCaretContainer$1 = isCaretContainer$2;
  2406. const isCaretCandidate$3 = (node) => {
  2407. if (isCaretContainer$1(node)) {
  2408. return false;
  2409. }
  2410. if (isText$8(node)) {
  2411. return !isInvalidTextElement(node.parentNode);
  2412. }
  2413. return (
  2414. isAtomicInline(node) ||
  2415. isBr$4(node) ||
  2416. isTable(node) ||
  2417. isNonUiContentEditableFalse(node)
  2418. );
  2419. };
  2420. const isUnselectable = (node) =>
  2421. isElement$6(node) && node.getAttribute("unselectable") === "true";
  2422. const isNonUiContentEditableFalse = (node) =>
  2423. !isUnselectable(node) && isContentEditableFalse$a(node);
  2424. const isInEditable = (node, root) => {
  2425. for (
  2426. let tempNode = node.parentNode;
  2427. tempNode && tempNode !== root;
  2428. tempNode = tempNode.parentNode
  2429. ) {
  2430. if (isNonUiContentEditableFalse(tempNode)) {
  2431. return false;
  2432. }
  2433. if (isContentEditableTrue$2(tempNode)) {
  2434. return true;
  2435. }
  2436. }
  2437. return true;
  2438. };
  2439. const isAtomicContentEditableFalse = (node) => {
  2440. if (!isNonUiContentEditableFalse(node)) {
  2441. return false;
  2442. }
  2443. return !foldl(
  2444. from(node.getElementsByTagName("*")),
  2445. (result, elm) => {
  2446. return result || isContentEditableTrue$2(elm);
  2447. },
  2448. false
  2449. );
  2450. };
  2451. const isAtomic$1 = (node) =>
  2452. isAtomicInline(node) || isAtomicContentEditableFalse(node);
  2453. const isEditableCaretCandidate$1 = (node, root) =>
  2454. isCaretCandidate$3(node) && isInEditable(node, root);
  2455. const whiteSpaceRegExp = /^[ \t\r\n]*$/;
  2456. const isWhitespaceText = (text) => whiteSpaceRegExp.test(text);
  2457. const isZwsp = (text) => {
  2458. for (const c of text) {
  2459. if (!isZwsp$2(c)) {
  2460. return false;
  2461. }
  2462. }
  2463. return true;
  2464. };
  2465. const isCollapsibleWhitespace$1 = (c) => " \f\t\x0B".indexOf(c) !== -1;
  2466. const isNewLineChar = (c) => c === "\n" || c === "\r";
  2467. const isNewline = (text, idx) =>
  2468. idx < text.length && idx >= 0 ? isNewLineChar(text[idx]) : false;
  2469. const normalize$4 = (
  2470. text,
  2471. tabSpaces = 4,
  2472. isStartOfContent = true,
  2473. isEndOfContent = true
  2474. ) => {
  2475. const tabSpace = repeat(" ", tabSpaces);
  2476. const normalizedText = text.replace(/\t/g, tabSpace);
  2477. const result = foldl(
  2478. normalizedText,
  2479. (acc, c) => {
  2480. if (isCollapsibleWhitespace$1(c) || c === nbsp) {
  2481. if (
  2482. acc.pcIsSpace ||
  2483. (acc.str === "" && isStartOfContent) ||
  2484. (acc.str.length === normalizedText.length - 1 && isEndOfContent) ||
  2485. isNewline(normalizedText, acc.str.length + 1)
  2486. ) {
  2487. return {
  2488. pcIsSpace: false,
  2489. str: acc.str + nbsp,
  2490. };
  2491. } else {
  2492. return {
  2493. pcIsSpace: true,
  2494. str: acc.str + " ",
  2495. };
  2496. }
  2497. } else {
  2498. return {
  2499. pcIsSpace: isNewLineChar(c),
  2500. str: acc.str + c,
  2501. };
  2502. }
  2503. },
  2504. {
  2505. pcIsSpace: false,
  2506. str: "",
  2507. }
  2508. );
  2509. return result.str;
  2510. };
  2511. const hasWhitespacePreserveParent = (node, rootNode) => {
  2512. const rootElement = SugarElement.fromDom(rootNode);
  2513. const startNode = SugarElement.fromDom(node);
  2514. return ancestor$2(startNode, "pre,code", curry(eq, rootElement));
  2515. };
  2516. const isWhitespace$1 = (node, rootNode) => {
  2517. return (
  2518. isText$a(node) &&
  2519. isWhitespaceText(node.data) &&
  2520. !hasWhitespacePreserveParent(node, rootNode)
  2521. );
  2522. };
  2523. const isNamedAnchor = (node) => {
  2524. return (
  2525. isElement$6(node) &&
  2526. node.nodeName === "A" &&
  2527. !node.hasAttribute("href") &&
  2528. (node.hasAttribute("name") || node.hasAttribute("id"))
  2529. );
  2530. };
  2531. const isContent$1 = (node, rootNode) => {
  2532. return (
  2533. (isCaretCandidate$3(node) && !isWhitespace$1(node, rootNode)) ||
  2534. isNamedAnchor(node) ||
  2535. isBookmark(node)
  2536. );
  2537. };
  2538. const isBookmark = hasAttribute("data-mce-bookmark");
  2539. const isBogus$1 = hasAttribute("data-mce-bogus");
  2540. const isBogusAll = hasAttributeValue("data-mce-bogus", "all");
  2541. const isEmptyNode = (targetNode, skipBogus) => {
  2542. let brCount = 0;
  2543. if (isContent$1(targetNode, targetNode)) {
  2544. return false;
  2545. } else {
  2546. let node = targetNode.firstChild;
  2547. if (!node) {
  2548. return true;
  2549. }
  2550. const walker = new DomTreeWalker(node, targetNode);
  2551. do {
  2552. if (skipBogus) {
  2553. if (isBogusAll(node)) {
  2554. node = walker.next(true);
  2555. continue;
  2556. }
  2557. if (isBogus$1(node)) {
  2558. node = walker.next();
  2559. continue;
  2560. }
  2561. }
  2562. if (isBr$6(node)) {
  2563. brCount++;
  2564. node = walker.next();
  2565. continue;
  2566. }
  2567. if (isContent$1(node, targetNode)) {
  2568. return false;
  2569. }
  2570. node = walker.next();
  2571. } while (node);
  2572. return brCount <= 1;
  2573. }
  2574. };
  2575. const isEmpty$2 = (elm, skipBogus = true) => isEmptyNode(elm.dom, skipBogus);
  2576. const transparentBlockAttr = "data-mce-block";
  2577. const elementNames = (map) =>
  2578. filter$5(keys(map), (key) => !/[A-Z]/.test(key));
  2579. const makeSelectorFromSchemaMap = (map) => elementNames(map).join(",");
  2580. const updateTransparent = (blocksSelector, transparent) => {
  2581. if (isNonNullable(transparent.querySelector(blocksSelector))) {
  2582. transparent.setAttribute(transparentBlockAttr, "true");
  2583. if (transparent.getAttribute("data-mce-selected") === "inline-boundary") {
  2584. transparent.removeAttribute("data-mce-selected");
  2585. }
  2586. return true;
  2587. } else {
  2588. transparent.removeAttribute(transparentBlockAttr);
  2589. return false;
  2590. }
  2591. };
  2592. const updateBlockStateOnChildren = (schema, scope) => {
  2593. const transparentSelector = makeSelectorFromSchemaMap(
  2594. schema.getTransparentElements()
  2595. );
  2596. const blocksSelector = makeSelectorFromSchemaMap(schema.getBlockElements());
  2597. return filter$5(
  2598. scope.querySelectorAll(transparentSelector),
  2599. (transparent) => updateTransparent(blocksSelector, transparent)
  2600. );
  2601. };
  2602. const trimEdge = (el, leftSide) => {
  2603. var _a;
  2604. const childPropertyName = leftSide ? "lastChild" : "firstChild";
  2605. for (
  2606. let child = el[childPropertyName];
  2607. child;
  2608. child = child[childPropertyName]
  2609. ) {
  2610. if (isEmpty$2(SugarElement.fromDom(child))) {
  2611. (_a = child.parentNode) === null || _a === void 0
  2612. ? void 0
  2613. : _a.removeChild(child);
  2614. return;
  2615. }
  2616. }
  2617. };
  2618. const split$2 = (parentElm, splitElm) => {
  2619. const range = document.createRange();
  2620. const parentNode = parentElm.parentNode;
  2621. if (parentNode) {
  2622. range.setStartBefore(parentElm);
  2623. range.setEndBefore(splitElm);
  2624. const beforeFragment = range.extractContents();
  2625. trimEdge(beforeFragment, true);
  2626. range.setStartAfter(splitElm);
  2627. range.setEndAfter(parentElm);
  2628. const afterFragment = range.extractContents();
  2629. trimEdge(afterFragment, false);
  2630. if (!isEmpty$2(SugarElement.fromDom(beforeFragment))) {
  2631. parentNode.insertBefore(beforeFragment, parentElm);
  2632. }
  2633. if (!isEmpty$2(SugarElement.fromDom(splitElm))) {
  2634. parentNode.insertBefore(splitElm, parentElm);
  2635. }
  2636. if (!isEmpty$2(SugarElement.fromDom(afterFragment))) {
  2637. parentNode.insertBefore(afterFragment, parentElm);
  2638. }
  2639. parentNode.removeChild(parentElm);
  2640. }
  2641. };
  2642. const splitInvalidChildren = (schema, scope, transparentBlocks) => {
  2643. const blocksElements = schema.getBlockElements();
  2644. const rootNode = SugarElement.fromDom(scope);
  2645. const isBlock = (el) => name(el) in blocksElements;
  2646. const isRoot = (el) => eq(el, rootNode);
  2647. each$e(fromDom$1(transparentBlocks), (transparentBlock) => {
  2648. ancestor$4(transparentBlock, isBlock, isRoot).each((parentBlock) => {
  2649. const invalidChildren = children(
  2650. transparentBlock,
  2651. (el) =>
  2652. isBlock(el) && !schema.isValidChild(name(parentBlock), name(el))
  2653. );
  2654. if (invalidChildren.length > 0) {
  2655. const stateScope = parentElement(parentBlock);
  2656. each$e(invalidChildren, (child) => {
  2657. ancestor$4(child, isBlock, isRoot).each((parentBlock) => {
  2658. split$2(parentBlock.dom, child.dom);
  2659. });
  2660. });
  2661. stateScope.each((scope) =>
  2662. updateBlockStateOnChildren(schema, scope.dom)
  2663. );
  2664. }
  2665. });
  2666. });
  2667. };
  2668. const unwrapInvalidChildren = (schema, scope, transparentBlocks) => {
  2669. each$e(
  2670. [
  2671. ...transparentBlocks,
  2672. ...(isTransparentBlock(schema, scope) ? [scope] : []),
  2673. ],
  2674. (block) =>
  2675. each$e(
  2676. descendants(
  2677. SugarElement.fromDom(block),
  2678. block.nodeName.toLowerCase()
  2679. ),
  2680. (elm) => {
  2681. if (isTransparentInline(schema, elm.dom)) {
  2682. unwrap(elm);
  2683. }
  2684. }
  2685. )
  2686. );
  2687. };
  2688. const updateChildren = (schema, scope) => {
  2689. const transparentBlocks = updateBlockStateOnChildren(schema, scope);
  2690. splitInvalidChildren(schema, scope, transparentBlocks);
  2691. unwrapInvalidChildren(schema, scope, transparentBlocks);
  2692. };
  2693. const updateElement = (schema, target) => {
  2694. if (isTransparentElement(schema, target)) {
  2695. const blocksSelector = makeSelectorFromSchemaMap(
  2696. schema.getBlockElements()
  2697. );
  2698. updateTransparent(blocksSelector, target);
  2699. }
  2700. };
  2701. const updateCaret = (schema, root, caretParent) => {
  2702. const isRoot = (el) => eq(el, SugarElement.fromDom(root));
  2703. const parents = parents$1(SugarElement.fromDom(caretParent), isRoot);
  2704. get$b(parents, parents.length - 2)
  2705. .filter(isElement$7)
  2706. .fold(
  2707. () => updateChildren(schema, root),
  2708. (scope) => updateChildren(schema, scope.dom)
  2709. );
  2710. };
  2711. const hasBlockAttr = (el) => el.hasAttribute(transparentBlockAttr);
  2712. const isTransparentElementName = (schema, name) =>
  2713. has$2(schema.getTransparentElements(), name);
  2714. const isTransparentElement = (schema, node) =>
  2715. isElement$6(node) && isTransparentElementName(schema, node.nodeName);
  2716. const isTransparentBlock = (schema, node) =>
  2717. isTransparentElement(schema, node) && hasBlockAttr(node);
  2718. const isTransparentInline = (schema, node) =>
  2719. isTransparentElement(schema, node) && !hasBlockAttr(node);
  2720. const isTransparentAstBlock = (schema, node) =>
  2721. node.type === 1 &&
  2722. isTransparentElementName(schema, node.name) &&
  2723. isString(node.attr(transparentBlockAttr));
  2724. const browser$2 = detect$2().browser;
  2725. const firstElement = (nodes) => find$2(nodes, isElement$7);
  2726. const getTableCaptionDeltaY = (elm) => {
  2727. if (browser$2.isFirefox() && name(elm) === "table") {
  2728. return firstElement(children$1(elm))
  2729. .filter((elm) => {
  2730. return name(elm) === "caption";
  2731. })
  2732. .bind((caption) => {
  2733. return firstElement(nextSiblings(caption)).map((body) => {
  2734. const bodyTop = body.dom.offsetTop;
  2735. const captionTop = caption.dom.offsetTop;
  2736. const captionHeight = caption.dom.offsetHeight;
  2737. return bodyTop <= captionTop ? -captionHeight : 0;
  2738. });
  2739. })
  2740. .getOr(0);
  2741. } else {
  2742. return 0;
  2743. }
  2744. };
  2745. const hasChild = (elm, child) =>
  2746. elm.children && contains$2(elm.children, child);
  2747. const getPos = (body, elm, rootElm) => {
  2748. let x = 0,
  2749. y = 0;
  2750. const doc = body.ownerDocument;
  2751. rootElm = rootElm ? rootElm : body;
  2752. if (elm) {
  2753. if (
  2754. rootElm === body &&
  2755. elm.getBoundingClientRect &&
  2756. get$7(SugarElement.fromDom(body), "position") === "static"
  2757. ) {
  2758. const pos = elm.getBoundingClientRect();
  2759. x =
  2760. pos.left +
  2761. (doc.documentElement.scrollLeft || body.scrollLeft) -
  2762. doc.documentElement.clientLeft;
  2763. y =
  2764. pos.top +
  2765. (doc.documentElement.scrollTop || body.scrollTop) -
  2766. doc.documentElement.clientTop;
  2767. return {
  2768. x,
  2769. y,
  2770. };
  2771. }
  2772. let offsetParent = elm;
  2773. while (
  2774. offsetParent &&
  2775. offsetParent !== rootElm &&
  2776. offsetParent.nodeType &&
  2777. !hasChild(offsetParent, rootElm)
  2778. ) {
  2779. const castOffsetParent = offsetParent;
  2780. x += castOffsetParent.offsetLeft || 0;
  2781. y += castOffsetParent.offsetTop || 0;
  2782. offsetParent = castOffsetParent.offsetParent;
  2783. }
  2784. offsetParent = elm.parentNode;
  2785. while (
  2786. offsetParent &&
  2787. offsetParent !== rootElm &&
  2788. offsetParent.nodeType &&
  2789. !hasChild(offsetParent, rootElm)
  2790. ) {
  2791. x -= offsetParent.scrollLeft || 0;
  2792. y -= offsetParent.scrollTop || 0;
  2793. offsetParent = offsetParent.parentNode;
  2794. }
  2795. y += getTableCaptionDeltaY(SugarElement.fromDom(elm));
  2796. }
  2797. return {
  2798. x,
  2799. y,
  2800. };
  2801. };
  2802. const StyleSheetLoader = (documentOrShadowRoot, settings = {}) => {
  2803. let idCount = 0;
  2804. const loadedStates = {};
  2805. const edos = SugarElement.fromDom(documentOrShadowRoot);
  2806. const doc = documentOrOwner(edos);
  2807. const _setReferrerPolicy = (referrerPolicy) => {
  2808. settings.referrerPolicy = referrerPolicy;
  2809. };
  2810. const _setContentCssCors = (contentCssCors) => {
  2811. settings.contentCssCors = contentCssCors;
  2812. };
  2813. const addStyle = (element) => {
  2814. append$1(getStyleContainer(edos), element);
  2815. };
  2816. const removeStyle = (id) => {
  2817. const styleContainer = getStyleContainer(edos);
  2818. descendant(styleContainer, "#" + id).each(remove$5);
  2819. };
  2820. const getOrCreateState = (url) =>
  2821. get$a(loadedStates, url).getOrThunk(() => ({
  2822. id: "mce-u" + idCount++,
  2823. passed: [],
  2824. failed: [],
  2825. count: 0,
  2826. }));
  2827. const load = (url) =>
  2828. new Promise((success, failure) => {
  2829. let link;
  2830. const urlWithSuffix = Tools._addCacheSuffix(url);
  2831. const state = getOrCreateState(urlWithSuffix);
  2832. loadedStates[urlWithSuffix] = state;
  2833. state.count++;
  2834. const resolve = (callbacks, status) => {
  2835. each$e(callbacks, call);
  2836. state.status = status;
  2837. state.passed = [];
  2838. state.failed = [];
  2839. if (link) {
  2840. link.onload = null;
  2841. link.onerror = null;
  2842. link = null;
  2843. }
  2844. };
  2845. const passed = () => resolve(state.passed, 2);
  2846. const failed = () => resolve(state.failed, 3);
  2847. if (success) {
  2848. state.passed.push(success);
  2849. }
  2850. if (failure) {
  2851. state.failed.push(failure);
  2852. }
  2853. if (state.status === 1) {
  2854. return;
  2855. }
  2856. if (state.status === 2) {
  2857. passed();
  2858. return;
  2859. }
  2860. if (state.status === 3) {
  2861. failed();
  2862. return;
  2863. }
  2864. state.status = 1;
  2865. const linkElem = SugarElement.fromTag("link", doc.dom);
  2866. setAll$1(linkElem, {
  2867. rel: "stylesheet",
  2868. type: "text/css",
  2869. id: state.id,
  2870. });
  2871. if (settings.contentCssCors) {
  2872. set$3(linkElem, "crossOrigin", "anonymous");
  2873. }
  2874. if (settings.referrerPolicy) {
  2875. set$3(linkElem, "referrerpolicy", settings.referrerPolicy);
  2876. }
  2877. link = linkElem.dom;
  2878. link.onload = passed;
  2879. link.onerror = failed;
  2880. addStyle(linkElem);
  2881. set$3(linkElem, "href", urlWithSuffix);
  2882. });
  2883. const loadAll = (urls) => {
  2884. const loadedUrls = Promise.allSettled(
  2885. map$3(urls, (url) => load(url).then(constant(url)))
  2886. );
  2887. return loadedUrls.then((results) => {
  2888. const parts = partition$2(results, (r) => r.status === "fulfilled");
  2889. if (parts.fail.length > 0) {
  2890. return Promise.reject(map$3(parts.fail, (result) => result.reason));
  2891. } else {
  2892. return map$3(parts.pass, (result) => result.value);
  2893. }
  2894. });
  2895. };
  2896. const unload = (url) => {
  2897. const urlWithSuffix = Tools._addCacheSuffix(url);
  2898. get$a(loadedStates, urlWithSuffix).each((state) => {
  2899. const count = --state.count;
  2900. if (count === 0) {
  2901. delete loadedStates[urlWithSuffix];
  2902. removeStyle(state.id);
  2903. }
  2904. });
  2905. };
  2906. const unloadAll = (urls) => {
  2907. each$e(urls, (url) => {
  2908. unload(url);
  2909. });
  2910. };
  2911. return {
  2912. load,
  2913. loadAll,
  2914. unload,
  2915. unloadAll,
  2916. _setReferrerPolicy,
  2917. _setContentCssCors,
  2918. };
  2919. };
  2920. const create$d = () => {
  2921. const map = new WeakMap();
  2922. const forElement = (referenceElement, settings) => {
  2923. const root = getRootNode(referenceElement);
  2924. const rootDom = root.dom;
  2925. return Optional.from(map.get(rootDom)).getOrThunk(() => {
  2926. const sl = StyleSheetLoader(rootDom, settings);
  2927. map.set(rootDom, sl);
  2928. return sl;
  2929. });
  2930. };
  2931. return { forElement };
  2932. };
  2933. const instance = create$d();
  2934. const isSpan = (node) => node.nodeName.toLowerCase() === "span";
  2935. const isInlineContent = (node, root) =>
  2936. isNonNullable(node) &&
  2937. (isContent$1(node, root) || isInline$1(SugarElement.fromDom(node)));
  2938. const surroundedByInlineContent = (node, root) => {
  2939. const prev = new DomTreeWalker(node, root).prev(false);
  2940. const next = new DomTreeWalker(node, root).next(false);
  2941. const prevIsInline = isUndefined(prev) || isInlineContent(prev, root);
  2942. const nextIsInline = isUndefined(next) || isInlineContent(next, root);
  2943. return prevIsInline && nextIsInline;
  2944. };
  2945. const isBookmarkNode$2 = (node) =>
  2946. isSpan(node) && node.getAttribute("data-mce-type") === "bookmark";
  2947. const isKeepTextNode = (node, root) =>
  2948. isText$a(node) &&
  2949. node.data.length > 0 &&
  2950. surroundedByInlineContent(node, root);
  2951. const isKeepElement = (node) =>
  2952. isElement$6(node) ? node.childNodes.length > 0 : false;
  2953. const isDocument = (node) => isDocumentFragment(node) || isDocument$1(node);
  2954. const trimNode = (dom, node, root) => {
  2955. var _a;
  2956. const rootNode = root || node;
  2957. if (isElement$6(node) && isBookmarkNode$2(node)) {
  2958. return node;
  2959. }
  2960. const children = node.childNodes;
  2961. for (let i = children.length - 1; i >= 0; i--) {
  2962. trimNode(dom, children[i], rootNode);
  2963. }
  2964. if (isElement$6(node)) {
  2965. const currentChildren = node.childNodes;
  2966. if (
  2967. currentChildren.length === 1 &&
  2968. isBookmarkNode$2(currentChildren[0])
  2969. ) {
  2970. (_a = node.parentNode) === null || _a === void 0
  2971. ? void 0
  2972. : _a.insertBefore(currentChildren[0], node);
  2973. }
  2974. }
  2975. if (
  2976. !isDocument(node) &&
  2977. !isContent$1(node, rootNode) &&
  2978. !isKeepElement(node) &&
  2979. !isKeepTextNode(node, rootNode)
  2980. ) {
  2981. dom.remove(node);
  2982. }
  2983. return node;
  2984. };
  2985. const makeMap$3 = Tools.makeMap;
  2986. const attrsCharsRegExp =
  2987. /[&<>\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
  2988. const textCharsRegExp =
  2989. /[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
  2990. const rawCharsRegExp = /[<>&\"\']/g;
  2991. const entityRegExp = /&#([a-z0-9]+);?|&([a-z0-9]+);/gi;
  2992. const asciiMap = {
  2993. 128: "\u20AC",
  2994. 130: "\u201A",
  2995. 131: "\u0192",
  2996. 132: "\u201E",
  2997. 133: "\u2026",
  2998. 134: "\u2020",
  2999. 135: "\u2021",
  3000. 136: "\u02c6",
  3001. 137: "\u2030",
  3002. 138: "\u0160",
  3003. 139: "\u2039",
  3004. 140: "\u0152",
  3005. 142: "\u017d",
  3006. 145: "\u2018",
  3007. 146: "\u2019",
  3008. 147: "\u201C",
  3009. 148: "\u201D",
  3010. 149: "\u2022",
  3011. 150: "\u2013",
  3012. 151: "\u2014",
  3013. 152: "\u02DC",
  3014. 153: "\u2122",
  3015. 154: "\u0161",
  3016. 155: "\u203A",
  3017. 156: "\u0153",
  3018. 158: "\u017e",
  3019. 159: "\u0178",
  3020. };
  3021. const baseEntities = {
  3022. '"': "&quot;",
  3023. "'": "&#39;",
  3024. "<": "&lt;",
  3025. ">": "&gt;",
  3026. "&": "&amp;",
  3027. "`": "&#96;",
  3028. };
  3029. const reverseEntities = {
  3030. "&lt;": "<",
  3031. "&gt;": ">",
  3032. "&amp;": "&",
  3033. "&quot;": '"',
  3034. "&apos;": `'`,
  3035. };
  3036. const nativeDecode = (text) => {
  3037. const elm = SugarElement.fromTag("div").dom;
  3038. elm.innerHTML = text;
  3039. return elm.textContent || elm.innerText || text;
  3040. };
  3041. const buildEntitiesLookup = (items, radix) => {
  3042. const lookup = {};
  3043. if (items) {
  3044. const itemList = items.split(",");
  3045. radix = radix || 10;
  3046. for (let i = 0; i < itemList.length; i += 2) {
  3047. const chr = String.fromCharCode(parseInt(itemList[i], radix));
  3048. if (!baseEntities[chr]) {
  3049. const entity = "&" + itemList[i + 1] + ";";
  3050. lookup[chr] = entity;
  3051. lookup[entity] = chr;
  3052. }
  3053. }
  3054. return lookup;
  3055. } else {
  3056. return undefined;
  3057. }
  3058. };
  3059. const namedEntities = buildEntitiesLookup(
  3060. "50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy," +
  3061. "5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute," +
  3062. "5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34," +
  3063. "5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil," +
  3064. "68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde," +
  3065. "6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute," +
  3066. "6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml," +
  3067. "75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc," +
  3068. "7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash," +
  3069. "7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta," +
  3070. "sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu," +
  3071. "st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi," +
  3072. "t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota," +
  3073. "tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau," +
  3074. "u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip," +
  3075. "81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym," +
  3076. "8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr," +
  3077. "8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod," +
  3078. "8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup," +
  3079. "8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4," +
  3080. "nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob," +
  3081. "rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0," +
  3082. "Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm," +
  3083. "80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger," +
  3084. "811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",
  3085. 32
  3086. );
  3087. const encodeRaw = (text, attr) =>
  3088. text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
  3089. return baseEntities[chr] || chr;
  3090. });
  3091. const encodeAllRaw = (text) =>
  3092. ("" + text).replace(rawCharsRegExp, (chr) => {
  3093. return baseEntities[chr] || chr;
  3094. });
  3095. const encodeNumeric = (text, attr) =>
  3096. text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
  3097. if (chr.length > 1) {
  3098. return (
  3099. "&#" +
  3100. ((chr.charCodeAt(0) - 55296) * 1024 +
  3101. (chr.charCodeAt(1) - 56320) +
  3102. 65536) +
  3103. ";"
  3104. );
  3105. }
  3106. return baseEntities[chr] || "&#" + chr.charCodeAt(0) + ";";
  3107. });
  3108. const encodeNamed = (text, attr, entities) => {
  3109. const resolveEntities = entities || namedEntities;
  3110. return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
  3111. return baseEntities[chr] || resolveEntities[chr] || chr;
  3112. });
  3113. };
  3114. const getEncodeFunc = (name, entities) => {
  3115. const entitiesMap = buildEntitiesLookup(entities) || namedEntities;
  3116. const encodeNamedAndNumeric = (text, attr) =>
  3117. text.replace(attr ? attrsCharsRegExp : textCharsRegExp, (chr) => {
  3118. if (baseEntities[chr] !== undefined) {
  3119. return baseEntities[chr];
  3120. }
  3121. if (entitiesMap[chr] !== undefined) {
  3122. return entitiesMap[chr];
  3123. }
  3124. if (chr.length > 1) {
  3125. return (
  3126. "&#" +
  3127. ((chr.charCodeAt(0) - 55296) * 1024 +
  3128. (chr.charCodeAt(1) - 56320) +
  3129. 65536) +
  3130. ";"
  3131. );
  3132. }
  3133. return "&#" + chr.charCodeAt(0) + ";";
  3134. });
  3135. const encodeCustomNamed = (text, attr) => {
  3136. return encodeNamed(text, attr, entitiesMap);
  3137. };
  3138. const nameMap = makeMap$3(name.replace(/\+/g, ","));
  3139. if (nameMap.named && nameMap.numeric) {
  3140. return encodeNamedAndNumeric;
  3141. }
  3142. if (nameMap.named) {
  3143. if (entities) {
  3144. return encodeCustomNamed;
  3145. }
  3146. return encodeNamed;
  3147. }
  3148. if (nameMap.numeric) {
  3149. return encodeNumeric;
  3150. }
  3151. return encodeRaw;
  3152. };
  3153. const decode = (text) =>
  3154. text.replace(entityRegExp, (all, numeric) => {
  3155. if (numeric) {
  3156. if (numeric.charAt(0).toLowerCase() === "x") {
  3157. numeric = parseInt(numeric.substr(1), 16);
  3158. } else {
  3159. numeric = parseInt(numeric, 10);
  3160. }
  3161. if (numeric > 65535) {
  3162. numeric -= 65536;
  3163. return String.fromCharCode(
  3164. 55296 + (numeric >> 10),
  3165. 56320 + (numeric & 1023)
  3166. );
  3167. }
  3168. return asciiMap[numeric] || String.fromCharCode(numeric);
  3169. }
  3170. return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
  3171. });
  3172. const Entities = {
  3173. encodeRaw,
  3174. encodeAllRaw,
  3175. encodeNumeric,
  3176. encodeNamed,
  3177. getEncodeFunc,
  3178. decode,
  3179. };
  3180. const split$1 = (items, delim) => {
  3181. items = Tools.trim(items);
  3182. return items ? items.split(delim || " ") : [];
  3183. };
  3184. const patternToRegExp = (str) =>
  3185. new RegExp("^" + str.replace(/([?+*])/g, ".$1") + "$");
  3186. const parseCustomElementsRules = (value) => {
  3187. const customElementRegExp = /^(~)?(.+)$/;
  3188. return bind$3(split$1(value, ","), (rule) => {
  3189. const matches = customElementRegExp.exec(rule);
  3190. if (matches) {
  3191. const inline = matches[1] === "~";
  3192. const cloneName = inline ? "span" : "div";
  3193. const name = matches[2];
  3194. return [
  3195. {
  3196. inline,
  3197. cloneName,
  3198. name,
  3199. },
  3200. ];
  3201. } else {
  3202. return [];
  3203. }
  3204. });
  3205. };
  3206. const getElementSetsAsStrings = (type) => {
  3207. let globalAttributes, blockContent;
  3208. let phrasingContent, flowContent;
  3209. globalAttributes = "id accesskey class dir lang style tabindex title role";
  3210. blockContent =
  3211. "address blockquote div dl fieldset form h1 h2 h3 h4 h5 h6 hr menu ol p pre table ul";
  3212. phrasingContent =
  3213. "a abbr b bdo br button cite code del dfn em embed i iframe img input ins kbd " +
  3214. "label map noscript object q s samp script select small span strong sub sup " +
  3215. "textarea u var #text #comment";
  3216. if (type !== "html4") {
  3217. const transparentContent = "a ins del canvas map";
  3218. globalAttributes +=
  3219. " contenteditable contextmenu draggable dropzone " +
  3220. "hidden spellcheck translate";
  3221. blockContent +=
  3222. " article aside details dialog figure main header footer hgroup section nav " +
  3223. transparentContent;
  3224. phrasingContent +=
  3225. " audio canvas command datalist mark meter output picture " +
  3226. "progress time wbr video ruby bdi keygen";
  3227. }
  3228. if (type !== "html5-strict") {
  3229. globalAttributes += " xml:lang";
  3230. const html4PhrasingContent = "acronym applet basefont big font strike tt";
  3231. phrasingContent = [phrasingContent, html4PhrasingContent].join(" ");
  3232. const html4BlockContent = "center dir isindex noframes";
  3233. blockContent = [blockContent, html4BlockContent].join(" ");
  3234. flowContent = [blockContent, phrasingContent].join(" ");
  3235. }
  3236. flowContent = flowContent || [blockContent, phrasingContent].join(" ");
  3237. return {
  3238. globalAttributes,
  3239. blockContent,
  3240. phrasingContent,
  3241. flowContent,
  3242. };
  3243. };
  3244. const makeSchema = (type) => {
  3245. const { globalAttributes, phrasingContent, flowContent } =
  3246. getElementSetsAsStrings(type);
  3247. const schema = {};
  3248. const add = (name, attributes = "", children = "") => {
  3249. const childNames = split$1(children);
  3250. const names = split$1(name);
  3251. let ni = names.length;
  3252. while (ni--) {
  3253. const attributesOrder = split$1(
  3254. [globalAttributes, attributes].join(" ")
  3255. );
  3256. schema[names[ni]] = {
  3257. attributes: mapToObject(attributesOrder, constant({})),
  3258. attributesOrder,
  3259. children: mapToObject(childNames, constant({})),
  3260. };
  3261. }
  3262. };
  3263. const addAttrs = (name, attributes) => {
  3264. const names = split$1(name);
  3265. const attrs = split$1(attributes);
  3266. let ni = names.length;
  3267. while (ni--) {
  3268. const schemaItem = schema[names[ni]];
  3269. for (let i = 0, l = attrs.length; i < l; i++) {
  3270. schemaItem.attributes[attrs[i]] = {};
  3271. schemaItem.attributesOrder.push(attrs[i]);
  3272. }
  3273. }
  3274. };
  3275. if (type !== "html5-strict") {
  3276. const html4PhrasingContent = "acronym applet basefont big font strike tt";
  3277. each$e(split$1(html4PhrasingContent), (name) => {
  3278. add(name, "", phrasingContent);
  3279. });
  3280. const html4BlockContent = "center dir isindex noframes";
  3281. each$e(split$1(html4BlockContent), (name) => {
  3282. add(name, "", flowContent);
  3283. });
  3284. }
  3285. add("html", "manifest", "head body");
  3286. add("head", "", "base command link meta noscript script style title");
  3287. add("title hr noscript br");
  3288. add("base", "href target");
  3289. add("link", "href rel media hreflang type sizes hreflang");
  3290. add("meta", "name http-equiv content charset");
  3291. add("style", "media type scoped");
  3292. add("script", "src async defer type charset");
  3293. add(
  3294. "body",
  3295. "onafterprint onbeforeprint onbeforeunload onblur onerror onfocus " +
  3296. "onhashchange onload onmessage onoffline ononline onpagehide onpageshow " +
  3297. "onpopstate onresize onscroll onstorage onunload",
  3298. flowContent
  3299. );
  3300. add("dd div", "", flowContent);
  3301. add(
  3302. "address dt caption",
  3303. "",
  3304. type === "html4" ? phrasingContent : flowContent
  3305. );
  3306. add(
  3307. "h1 h2 h3 h4 h5 h6 pre p abbr code var samp kbd sub sup i b u bdo span legend em strong small s cite dfn",
  3308. "",
  3309. phrasingContent
  3310. );
  3311. add("blockquote", "cite", flowContent);
  3312. add("ol", "reversed start type", "li");
  3313. add("ul", "", "li");
  3314. add("li", "value", flowContent);
  3315. add("dl", "", "dt dd");
  3316. add(
  3317. "a",
  3318. "href target rel media hreflang type",
  3319. type === "html4" ? phrasingContent : flowContent
  3320. );
  3321. add("q", "cite", phrasingContent);
  3322. add("ins del", "cite datetime", flowContent);
  3323. add("img", "src sizes srcset alt usemap ismap width height");
  3324. add("iframe", "src name width height", flowContent);
  3325. add("embed", "src type width height");
  3326. add(
  3327. "object",
  3328. "data type typemustmatch name usemap form width height",
  3329. [flowContent, "param"].join(" ")
  3330. );
  3331. add("param", "name value");
  3332. add("map", "name", [flowContent, "area"].join(" "));
  3333. add("area", "alt coords shape href target rel media hreflang type");
  3334. add(
  3335. "table",
  3336. "border",
  3337. "caption colgroup thead tfoot tbody tr" + (type === "html4" ? " col" : "")
  3338. );
  3339. add("colgroup", "span", "col");
  3340. add("col", "span");
  3341. add("tbody thead tfoot", "", "tr");
  3342. add("tr", "", "td th");
  3343. add("td", "colspan rowspan headers", flowContent);
  3344. add("th", "colspan rowspan headers scope abbr", flowContent);
  3345. add(
  3346. "form",
  3347. "accept-charset action autocomplete enctype method name novalidate target",
  3348. flowContent
  3349. );
  3350. add("fieldset", "disabled form name", [flowContent, "legend"].join(" "));
  3351. add("label", "form for", phrasingContent);
  3352. add(
  3353. "input",
  3354. "accept alt autocomplete checked dirname disabled form formaction formenctype formmethod formnovalidate " +
  3355. "formtarget height list max maxlength min multiple name pattern readonly required size src step type value width"
  3356. );
  3357. add(
  3358. "button",
  3359. "disabled form formaction formenctype formmethod formnovalidate formtarget name type value",
  3360. type === "html4" ? flowContent : phrasingContent
  3361. );
  3362. add(
  3363. "select",
  3364. "disabled form multiple name required size",
  3365. "option optgroup"
  3366. );
  3367. add("optgroup", "disabled label", "option");
  3368. add("option", "disabled label selected value");
  3369. add(
  3370. "textarea",
  3371. "cols dirname disabled form maxlength name readonly required rows wrap"
  3372. );
  3373. add("menu", "type label", [flowContent, "li"].join(" "));
  3374. add("noscript", "", flowContent);
  3375. if (type !== "html4") {
  3376. add("wbr");
  3377. add("ruby", "", [phrasingContent, "rt rp"].join(" "));
  3378. add("figcaption", "", flowContent);
  3379. add("mark rt rp summary bdi", "", phrasingContent);
  3380. add("canvas", "width height", flowContent);
  3381. add(
  3382. "video",
  3383. "src crossorigin poster preload autoplay mediagroup loop " +
  3384. "muted controls width height buffered",
  3385. [flowContent, "track source"].join(" ")
  3386. );
  3387. add(
  3388. "audio",
  3389. "src crossorigin preload autoplay mediagroup loop muted controls " +
  3390. "buffered volume",
  3391. [flowContent, "track source"].join(" ")
  3392. );
  3393. add("picture", "", "img source");
  3394. add("source", "src srcset type media sizes");
  3395. add("track", "kind src srclang label default");
  3396. add("datalist", "", [phrasingContent, "option"].join(" "));
  3397. add("article section nav aside main header footer", "", flowContent);
  3398. add("hgroup", "", "h1 h2 h3 h4 h5 h6");
  3399. add("figure", "", [flowContent, "figcaption"].join(" "));
  3400. add("time", "datetime", phrasingContent);
  3401. add("dialog", "open", flowContent);
  3402. add("command", "type label icon disabled checked radiogroup command");
  3403. add("output", "for form name", phrasingContent);
  3404. add("progress", "value max", phrasingContent);
  3405. add("meter", "value min max low high optimum", phrasingContent);
  3406. add("details", "open", [flowContent, "summary"].join(" "));
  3407. add("keygen", "autofocus challenge disabled form keytype name");
  3408. }
  3409. if (type !== "html5-strict") {
  3410. addAttrs("script", "language xml:space");
  3411. addAttrs("style", "xml:space");
  3412. addAttrs(
  3413. "object",
  3414. "declare classid code codebase codetype archive standby align border hspace vspace"
  3415. );
  3416. addAttrs("embed", "align name hspace vspace");
  3417. addAttrs("param", "valuetype type");
  3418. addAttrs("a", "charset name rev shape coords");
  3419. addAttrs("br", "clear");
  3420. addAttrs(
  3421. "applet",
  3422. "codebase archive code object alt name width height align hspace vspace"
  3423. );
  3424. addAttrs("img", "name longdesc align border hspace vspace");
  3425. addAttrs(
  3426. "iframe",
  3427. "longdesc frameborder marginwidth marginheight scrolling align"
  3428. );
  3429. addAttrs("font basefont", "size color face");
  3430. addAttrs("input", "usemap align");
  3431. addAttrs("select");
  3432. addAttrs("textarea");
  3433. addAttrs("h1 h2 h3 h4 h5 h6 div p legend caption", "align");
  3434. addAttrs("ul", "type compact");
  3435. addAttrs("li", "type");
  3436. addAttrs("ol dl menu dir", "compact");
  3437. addAttrs("pre", "width xml:space");
  3438. addAttrs("hr", "align noshade size width");
  3439. addAttrs("isindex", "prompt");
  3440. addAttrs(
  3441. "table",
  3442. "summary width frame rules cellspacing cellpadding align bgcolor"
  3443. );
  3444. addAttrs("col", "width align char charoff valign");
  3445. addAttrs("colgroup", "width align char charoff valign");
  3446. addAttrs("thead", "align char charoff valign");
  3447. addAttrs("tr", "align char charoff valign bgcolor");
  3448. addAttrs(
  3449. "th",
  3450. "axis align char charoff valign nowrap bgcolor width height"
  3451. );
  3452. addAttrs("form", "accept");
  3453. addAttrs(
  3454. "td",
  3455. "abbr axis scope align char charoff valign nowrap bgcolor width height"
  3456. );
  3457. addAttrs("tfoot", "align char charoff valign");
  3458. addAttrs("tbody", "align char charoff valign");
  3459. addAttrs("area", "nohref");
  3460. addAttrs("body", "background bgcolor text link vlink alink");
  3461. }
  3462. if (type !== "html4") {
  3463. addAttrs("input button select textarea", "autofocus");
  3464. addAttrs("input textarea", "placeholder");
  3465. addAttrs("a", "download");
  3466. addAttrs("link script img", "crossorigin");
  3467. addAttrs("img", "loading");
  3468. addAttrs("iframe", "sandbox seamless allow allowfullscreen loading");
  3469. }
  3470. if (type !== "html4") {
  3471. each$e([schema.video, schema.audio], (item) => {
  3472. delete item.children.audio;
  3473. delete item.children.video;
  3474. });
  3475. }
  3476. each$e(split$1("a form meter progress dfn"), (name) => {
  3477. if (schema[name]) {
  3478. delete schema[name].children[name];
  3479. }
  3480. });
  3481. delete schema.caption.children.table;
  3482. delete schema.script;
  3483. return schema;
  3484. };
  3485. const prefixToOperation = (prefix) => (prefix === "-" ? "remove" : "add");
  3486. const parseValidChildrenRules = (value) => {
  3487. const childRuleRegExp =
  3488. /^([+\-]?)([A-Za-z0-9_\-.\u00b7\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u037d\u037f-\u1fff\u200c-\u200d\u203f-\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]+)\[([^\]]+)]$/;
  3489. return bind$3(split$1(value, ","), (rule) => {
  3490. const matches = childRuleRegExp.exec(rule);
  3491. if (matches) {
  3492. const prefix = matches[1];
  3493. const operation = prefix ? prefixToOperation(prefix) : "replace";
  3494. const name = matches[2];
  3495. const validChildren = split$1(matches[3], "|");
  3496. return [
  3497. {
  3498. operation,
  3499. name,
  3500. validChildren,
  3501. },
  3502. ];
  3503. } else {
  3504. return [];
  3505. }
  3506. });
  3507. };
  3508. const parseValidElementsAttrDataIntoElement = (attrData, targetElement) => {
  3509. const attrRuleRegExp = /^([!\-])?(\w+[\\:]:\w+|[^=~<]+)?(?:([=~<])(.*))?$/;
  3510. const hasPatternsRegExp = /[*?+]/;
  3511. const { attributes, attributesOrder } = targetElement;
  3512. return each$e(split$1(attrData, "|"), (rule) => {
  3513. const matches = attrRuleRegExp.exec(rule);
  3514. if (matches) {
  3515. const attr = {};
  3516. const attrType = matches[1];
  3517. const attrName = matches[2].replace(/[\\:]:/g, ":");
  3518. const attrPrefix = matches[3];
  3519. const value = matches[4];
  3520. if (attrType === "!") {
  3521. targetElement.attributesRequired =
  3522. targetElement.attributesRequired || [];
  3523. targetElement.attributesRequired.push(attrName);
  3524. attr.required = true;
  3525. }
  3526. if (attrType === "-") {
  3527. delete attributes[attrName];
  3528. attributesOrder.splice(Tools.inArray(attributesOrder, attrName), 1);
  3529. return;
  3530. }
  3531. if (attrPrefix) {
  3532. if (attrPrefix === "=") {
  3533. targetElement.attributesDefault =
  3534. targetElement.attributesDefault || [];
  3535. targetElement.attributesDefault.push({
  3536. name: attrName,
  3537. value,
  3538. });
  3539. attr.defaultValue = value;
  3540. } else if (attrPrefix === "~") {
  3541. targetElement.attributesForced =
  3542. targetElement.attributesForced || [];
  3543. targetElement.attributesForced.push({
  3544. name: attrName,
  3545. value,
  3546. });
  3547. attr.forcedValue = value;
  3548. } else if (attrPrefix === "<") {
  3549. attr.validValues = Tools.makeMap(value, "?");
  3550. }
  3551. }
  3552. if (hasPatternsRegExp.test(attrName)) {
  3553. const attrPattern = attr;
  3554. targetElement.attributePatterns =
  3555. targetElement.attributePatterns || [];
  3556. attrPattern.pattern = patternToRegExp(attrName);
  3557. targetElement.attributePatterns.push(attrPattern);
  3558. } else {
  3559. if (!attributes[attrName]) {
  3560. attributesOrder.push(attrName);
  3561. }
  3562. attributes[attrName] = attr;
  3563. }
  3564. }
  3565. });
  3566. };
  3567. const cloneAttributesInto = (from, to) => {
  3568. each$d(from.attributes, (value, key) => {
  3569. to.attributes[key] = value;
  3570. });
  3571. to.attributesOrder.push(...from.attributesOrder);
  3572. };
  3573. const parseValidElementsRules = (globalElement, validElements) => {
  3574. const elementRuleRegExp =
  3575. /^([#+\-])?([^\[!\/]+)(?:\/([^\[!]+))?(?:(!?)\[([^\]]+)])?$/;
  3576. return bind$3(split$1(validElements, ","), (rule) => {
  3577. const matches = elementRuleRegExp.exec(rule);
  3578. if (matches) {
  3579. const prefix = matches[1];
  3580. const elementName = matches[2];
  3581. const outputName = matches[3];
  3582. const attrsPrefix = matches[4];
  3583. const attrData = matches[5];
  3584. const element = {
  3585. attributes: {},
  3586. attributesOrder: [],
  3587. };
  3588. globalElement.each((el) => cloneAttributesInto(el, element));
  3589. if (prefix === "#") {
  3590. element.paddEmpty = true;
  3591. } else if (prefix === "-") {
  3592. element.removeEmpty = true;
  3593. }
  3594. if (attrsPrefix === "!") {
  3595. element.removeEmptyAttrs = true;
  3596. }
  3597. if (attrData) {
  3598. parseValidElementsAttrDataIntoElement(attrData, element);
  3599. }
  3600. if (outputName) {
  3601. element.outputName = elementName;
  3602. }
  3603. if (elementName === "@") {
  3604. if (globalElement.isNone()) {
  3605. globalElement = Optional.some(element);
  3606. } else {
  3607. return [];
  3608. }
  3609. }
  3610. return [
  3611. outputName
  3612. ? {
  3613. name: elementName,
  3614. element,
  3615. aliasName: outputName,
  3616. }
  3617. : {
  3618. name: elementName,
  3619. element,
  3620. },
  3621. ];
  3622. } else {
  3623. return [];
  3624. }
  3625. });
  3626. };
  3627. const mapCache = {};
  3628. const makeMap$2 = Tools.makeMap,
  3629. each$b = Tools.each,
  3630. extend$2 = Tools.extend,
  3631. explode$2 = Tools.explode;
  3632. const createMap = (defaultValue, extendWith = {}) => {
  3633. const value = makeMap$2(
  3634. defaultValue,
  3635. " ",
  3636. makeMap$2(defaultValue.toUpperCase(), " ")
  3637. );
  3638. return extend$2(value, extendWith);
  3639. };
  3640. const getTextRootBlockElements = (schema) =>
  3641. createMap(
  3642. "td th li dt dd figcaption caption details summary",
  3643. schema.getTextBlockElements()
  3644. );
  3645. const compileElementMap = (value, mode) => {
  3646. if (value) {
  3647. const styles = {};
  3648. if (isString(value)) {
  3649. value = { "*": value };
  3650. }
  3651. each$b(value, (value, key) => {
  3652. styles[key] = styles[key.toUpperCase()] =
  3653. mode === "map" ? makeMap$2(value, /[, ]/) : explode$2(value, /[, ]/);
  3654. });
  3655. return styles;
  3656. } else {
  3657. return undefined;
  3658. }
  3659. };
  3660. const Schema = (settings = {}) => {
  3661. var _a;
  3662. const elements = {};
  3663. const children = {};
  3664. let patternElements = [];
  3665. const customElementsMap = {};
  3666. const specialElements = {};
  3667. const createLookupTable = (option, defaultValue, extendWith) => {
  3668. const value = settings[option];
  3669. if (!value) {
  3670. let newValue = mapCache[option];
  3671. if (!newValue) {
  3672. newValue = createMap(defaultValue, extendWith);
  3673. mapCache[option] = newValue;
  3674. }
  3675. return newValue;
  3676. } else {
  3677. return makeMap$2(value, /[, ]/, makeMap$2(value.toUpperCase(), /[, ]/));
  3678. }
  3679. };
  3680. const schemaType =
  3681. (_a = settings.schema) !== null && _a !== void 0 ? _a : "html5";
  3682. const schemaItems = makeSchema(schemaType);
  3683. if (settings.verify_html === false) {
  3684. settings.valid_elements = "*[*]";
  3685. }
  3686. const validStyles = compileElementMap(settings.valid_styles);
  3687. const invalidStyles = compileElementMap(settings.invalid_styles, "map");
  3688. const validClasses = compileElementMap(settings.valid_classes, "map");
  3689. const whitespaceElementsMap = createLookupTable(
  3690. "whitespace_elements",
  3691. "pre script noscript style textarea video audio iframe object code"
  3692. );
  3693. const selfClosingElementsMap = createLookupTable(
  3694. "self_closing_elements",
  3695. "colgroup dd dt li option p td tfoot th thead tr"
  3696. );
  3697. const voidElementsMap = createLookupTable(
  3698. "void_elements",
  3699. "area base basefont br col frame hr img input isindex link " +
  3700. "meta param embed source wbr track"
  3701. );
  3702. const boolAttrMap = createLookupTable(
  3703. "boolean_attributes",
  3704. "checked compact declare defer disabled ismap multiple nohref noresize " +
  3705. "noshade nowrap readonly selected autoplay loop controls allowfullscreen"
  3706. );
  3707. const nonEmptyOrMoveCaretBeforeOnEnter =
  3708. "td th iframe video audio object script code";
  3709. const nonEmptyElementsMap = createLookupTable(
  3710. "non_empty_elements",
  3711. nonEmptyOrMoveCaretBeforeOnEnter + " pre",
  3712. voidElementsMap
  3713. );
  3714. const moveCaretBeforeOnEnterElementsMap = createLookupTable(
  3715. "move_caret_before_on_enter_elements",
  3716. nonEmptyOrMoveCaretBeforeOnEnter + " table",
  3717. voidElementsMap
  3718. );
  3719. const textBlockElementsMap = createLookupTable(
  3720. "text_block_elements",
  3721. "h1 h2 h3 h4 h5 h6 p div address pre form " +
  3722. "blockquote center dir fieldset header footer article section hgroup aside main nav figure"
  3723. );
  3724. const blockElementsMap = createLookupTable(
  3725. "block_elements",
  3726. "hr table tbody thead tfoot " +
  3727. "th tr td li ol ul caption dl dt dd noscript menu isindex option " +
  3728. "datalist select optgroup figcaption details summary",
  3729. textBlockElementsMap
  3730. );
  3731. const textInlineElementsMap = createLookupTable(
  3732. "text_inline_elements",
  3733. "span strong b em i font s strike u var cite " +
  3734. "dfn code mark q sup sub samp"
  3735. );
  3736. const transparentElementsMap = createLookupTable(
  3737. "transparent_elements",
  3738. "a ins del canvas map"
  3739. );
  3740. each$b(
  3741. "script noscript iframe noframes noembed title style textarea xmp plaintext".split(
  3742. " "
  3743. ),
  3744. (name) => {
  3745. specialElements[name] = new RegExp("</" + name + "[^>]*>", "gi");
  3746. }
  3747. );
  3748. const addValidElements = (validElements) => {
  3749. const globalElement = Optional.from(elements["@"]);
  3750. const hasPatternsRegExp = /[*?+]/;
  3751. each$e(
  3752. parseValidElementsRules(
  3753. globalElement,
  3754. validElements !== null && validElements !== void 0
  3755. ? validElements
  3756. : ""
  3757. ),
  3758. ({ name, element, aliasName }) => {
  3759. if (aliasName) {
  3760. elements[aliasName] = element;
  3761. }
  3762. if (hasPatternsRegExp.test(name)) {
  3763. const patternElement = element;
  3764. patternElement.pattern = patternToRegExp(name);
  3765. patternElements.push(patternElement);
  3766. } else {
  3767. elements[name] = element;
  3768. }
  3769. }
  3770. );
  3771. };
  3772. const setValidElements = (validElements) => {
  3773. patternElements = [];
  3774. each$e(keys(elements), (name) => {
  3775. delete elements[name];
  3776. });
  3777. addValidElements(validElements);
  3778. };
  3779. const addCustomElements = (customElements) => {
  3780. delete mapCache.text_block_elements;
  3781. delete mapCache.block_elements;
  3782. each$e(
  3783. parseCustomElementsRules(
  3784. customElements !== null && customElements !== void 0
  3785. ? customElements
  3786. : ""
  3787. ),
  3788. ({ inline, name, cloneName }) => {
  3789. children[name] = children[cloneName];
  3790. customElementsMap[name] = cloneName;
  3791. nonEmptyElementsMap[name.toUpperCase()] = {};
  3792. nonEmptyElementsMap[name] = {};
  3793. if (!inline) {
  3794. blockElementsMap[name.toUpperCase()] = {};
  3795. blockElementsMap[name] = {};
  3796. }
  3797. if (!elements[name]) {
  3798. let customRule = elements[cloneName];
  3799. customRule = extend$2({}, customRule);
  3800. delete customRule.removeEmptyAttrs;
  3801. delete customRule.removeEmpty;
  3802. elements[name] = customRule;
  3803. }
  3804. each$d(children, (element, elmName) => {
  3805. if (element[cloneName]) {
  3806. children[elmName] = element = extend$2({}, children[elmName]);
  3807. element[name] = element[cloneName];
  3808. }
  3809. });
  3810. }
  3811. );
  3812. };
  3813. const addValidChildren = (validChildren) => {
  3814. each$e(
  3815. parseValidChildrenRules(
  3816. validChildren !== null && validChildren !== void 0
  3817. ? validChildren
  3818. : ""
  3819. ),
  3820. ({ operation, name, validChildren }) => {
  3821. const parent =
  3822. operation === "replace" ? { "#comment": {} } : children[name];
  3823. each$e(validChildren, (child) => {
  3824. if (operation === "remove") {
  3825. delete parent[child];
  3826. } else {
  3827. parent[child] = {};
  3828. }
  3829. });
  3830. children[name] = parent;
  3831. }
  3832. );
  3833. };
  3834. const getElementRule = (name) => {
  3835. const element = elements[name];
  3836. if (element) {
  3837. return element;
  3838. }
  3839. let i = patternElements.length;
  3840. while (i--) {
  3841. const patternElement = patternElements[i];
  3842. if (patternElement.pattern.test(name)) {
  3843. return patternElement;
  3844. }
  3845. }
  3846. return undefined;
  3847. };
  3848. if (!settings.valid_elements) {
  3849. each$b(schemaItems, (element, name) => {
  3850. elements[name] = {
  3851. attributes: element.attributes,
  3852. attributesOrder: element.attributesOrder,
  3853. };
  3854. children[name] = element.children;
  3855. });
  3856. each$b(split$1("strong/b em/i"), (item) => {
  3857. const items = split$1(item, "/");
  3858. elements[items[1]].outputName = items[0];
  3859. });
  3860. each$b(textInlineElementsMap, (_val, name) => {
  3861. if (elements[name]) {
  3862. if (settings.padd_empty_block_inline_children) {
  3863. elements[name].paddInEmptyBlock = true;
  3864. }
  3865. elements[name].removeEmpty = true;
  3866. }
  3867. });
  3868. each$b(split$1("ol ul blockquote a table tbody"), (name) => {
  3869. if (elements[name]) {
  3870. elements[name].removeEmpty = true;
  3871. }
  3872. });
  3873. each$b(
  3874. split$1("p h1 h2 h3 h4 h5 h6 th td pre div address caption li summary"),
  3875. (name) => {
  3876. if (elements[name]) {
  3877. elements[name].paddEmpty = true;
  3878. }
  3879. }
  3880. );
  3881. each$b(split$1("span"), (name) => {
  3882. elements[name].removeEmptyAttrs = true;
  3883. });
  3884. } else {
  3885. setValidElements(settings.valid_elements);
  3886. each$b(schemaItems, (element, name) => {
  3887. children[name] = element.children;
  3888. });
  3889. }
  3890. addCustomElements(settings.custom_elements);
  3891. addValidChildren(settings.valid_children);
  3892. addValidElements(settings.extended_valid_elements);
  3893. addValidChildren("+ol[ul|ol],+ul[ul|ol]");
  3894. each$b(
  3895. {
  3896. dd: "dl",
  3897. dt: "dl",
  3898. li: "ul ol",
  3899. td: "tr",
  3900. th: "tr",
  3901. tr: "tbody thead tfoot",
  3902. tbody: "table",
  3903. thead: "table",
  3904. tfoot: "table",
  3905. legend: "fieldset",
  3906. area: "map",
  3907. param: "video audio object",
  3908. },
  3909. (parents, item) => {
  3910. if (elements[item]) {
  3911. elements[item].parentsRequired = split$1(parents);
  3912. }
  3913. }
  3914. );
  3915. if (settings.invalid_elements) {
  3916. each$b(explode$2(settings.invalid_elements), (item) => {
  3917. if (elements[item]) {
  3918. delete elements[item];
  3919. }
  3920. });
  3921. }
  3922. if (!getElementRule("span")) {
  3923. addValidElements("span[!data-mce-type|*]");
  3924. }
  3925. const getValidStyles = constant(validStyles);
  3926. const getInvalidStyles = constant(invalidStyles);
  3927. const getValidClasses = constant(validClasses);
  3928. const getBoolAttrs = constant(boolAttrMap);
  3929. const getBlockElements = constant(blockElementsMap);
  3930. const getTextBlockElements = constant(textBlockElementsMap);
  3931. const getTextInlineElements = constant(textInlineElementsMap);
  3932. const getVoidElements = constant(Object.seal(voidElementsMap));
  3933. const getSelfClosingElements = constant(selfClosingElementsMap);
  3934. const getNonEmptyElements = constant(nonEmptyElementsMap);
  3935. const getMoveCaretBeforeOnEnterElements = constant(
  3936. moveCaretBeforeOnEnterElementsMap
  3937. );
  3938. const getWhitespaceElements = constant(whitespaceElementsMap);
  3939. const getTransparentElements = constant(transparentElementsMap);
  3940. const getSpecialElements = constant(Object.seal(specialElements));
  3941. const isValidChild = (name, child) => {
  3942. const parent = children[name.toLowerCase()];
  3943. return !!(parent && parent[child.toLowerCase()]);
  3944. };
  3945. const isValid = (name, attr) => {
  3946. const rule = getElementRule(name);
  3947. if (rule) {
  3948. if (attr) {
  3949. if (rule.attributes[attr]) {
  3950. return true;
  3951. }
  3952. const attrPatterns = rule.attributePatterns;
  3953. if (attrPatterns) {
  3954. let i = attrPatterns.length;
  3955. while (i--) {
  3956. if (attrPatterns[i].pattern.test(attr)) {
  3957. return true;
  3958. }
  3959. }
  3960. }
  3961. } else {
  3962. return true;
  3963. }
  3964. }
  3965. return false;
  3966. };
  3967. const getCustomElements = constant(customElementsMap);
  3968. return {
  3969. type: schemaType,
  3970. children,
  3971. elements,
  3972. getValidStyles,
  3973. getValidClasses,
  3974. getBlockElements,
  3975. getInvalidStyles,
  3976. getVoidElements,
  3977. getTextBlockElements,
  3978. getTextInlineElements,
  3979. getBoolAttrs,
  3980. getElementRule,
  3981. getSelfClosingElements,
  3982. getNonEmptyElements,
  3983. getMoveCaretBeforeOnEnterElements,
  3984. getWhitespaceElements,
  3985. getTransparentElements,
  3986. getSpecialElements,
  3987. isValidChild,
  3988. isValid,
  3989. getCustomElements,
  3990. addValidElements,
  3991. setValidElements,
  3992. addCustomElements,
  3993. addValidChildren,
  3994. };
  3995. };
  3996. const Styles = (settings = {}, schema) => {
  3997. const urlOrStrRegExp =
  3998. /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi;
  3999. const styleRegExp = /\s*([^:]+):\s*([^;]+);?/g;
  4000. const trimRightRegExp = /\s+$/;
  4001. const encodingLookup = {};
  4002. let validStyles;
  4003. let invalidStyles;
  4004. const invisibleChar = zeroWidth;
  4005. if (schema) {
  4006. validStyles = schema.getValidStyles();
  4007. invalidStyles = schema.getInvalidStyles();
  4008. }
  4009. const encodingItems = (`\\" \\' \\; \\: ; : ` + invisibleChar).split(" ");
  4010. for (let i = 0; i < encodingItems.length; i++) {
  4011. encodingLookup[encodingItems[i]] = invisibleChar + i;
  4012. encodingLookup[invisibleChar + i] = encodingItems[i];
  4013. }
  4014. const self = {
  4015. parse: (css) => {
  4016. const styles = {};
  4017. let isEncoded = false;
  4018. const urlConverter = settings.url_converter;
  4019. const urlConverterScope = settings.url_converter_scope || self;
  4020. const compress = (prefix, suffix, noJoin) => {
  4021. const top = styles[prefix + "-top" + suffix];
  4022. if (!top) {
  4023. return;
  4024. }
  4025. const right = styles[prefix + "-right" + suffix];
  4026. if (!right) {
  4027. return;
  4028. }
  4029. const bottom = styles[prefix + "-bottom" + suffix];
  4030. if (!bottom) {
  4031. return;
  4032. }
  4033. const left = styles[prefix + "-left" + suffix];
  4034. if (!left) {
  4035. return;
  4036. }
  4037. const box = [top, right, bottom, left];
  4038. let i = box.length - 1;
  4039. while (i--) {
  4040. if (box[i] !== box[i + 1]) {
  4041. break;
  4042. }
  4043. }
  4044. if (i > -1 && noJoin) {
  4045. return;
  4046. }
  4047. styles[prefix + suffix] = i === -1 ? box[0] : box.join(" ");
  4048. delete styles[prefix + "-top" + suffix];
  4049. delete styles[prefix + "-right" + suffix];
  4050. delete styles[prefix + "-bottom" + suffix];
  4051. delete styles[prefix + "-left" + suffix];
  4052. };
  4053. const canCompress = (key) => {
  4054. const value = styles[key];
  4055. if (!value) {
  4056. return;
  4057. }
  4058. const values = value.indexOf(",") > -1 ? [value] : value.split(" ");
  4059. let i = values.length;
  4060. while (i--) {
  4061. if (values[i] !== values[0]) {
  4062. return false;
  4063. }
  4064. }
  4065. styles[key] = values[0];
  4066. return true;
  4067. };
  4068. const compress2 = (target, a, b, c) => {
  4069. if (!canCompress(a)) {
  4070. return;
  4071. }
  4072. if (!canCompress(b)) {
  4073. return;
  4074. }
  4075. if (!canCompress(c)) {
  4076. return;
  4077. }
  4078. styles[target] = styles[a] + " " + styles[b] + " " + styles[c];
  4079. delete styles[a];
  4080. delete styles[b];
  4081. delete styles[c];
  4082. };
  4083. const encode = (str) => {
  4084. isEncoded = true;
  4085. return encodingLookup[str];
  4086. };
  4087. const decode = (str, keepSlashes) => {
  4088. if (isEncoded) {
  4089. str = str.replace(/\uFEFF[0-9]/g, (str) => {
  4090. return encodingLookup[str];
  4091. });
  4092. }
  4093. if (!keepSlashes) {
  4094. str = str.replace(/\\([\'\";:])/g, "$1");
  4095. }
  4096. return str;
  4097. };
  4098. const decodeSingleHexSequence = (escSeq) => {
  4099. return String.fromCharCode(parseInt(escSeq.slice(1), 16));
  4100. };
  4101. const decodeHexSequences = (value) => {
  4102. return value.replace(/\\[0-9a-f]+/gi, decodeSingleHexSequence);
  4103. };
  4104. const processUrl = (match, url, url2, url3, str, str2) => {
  4105. str = str || str2;
  4106. if (str) {
  4107. str = decode(str);
  4108. return `'` + str.replace(/\'/g, `\\'`) + `'`;
  4109. }
  4110. url = decode(url || url2 || url3 || "");
  4111. if (!settings.allow_script_urls) {
  4112. const scriptUrl = url.replace(/[\s\r\n]+/g, "");
  4113. if (/(java|vb)script:/i.test(scriptUrl)) {
  4114. return "";
  4115. }
  4116. if (
  4117. !settings.allow_svg_data_urls &&
  4118. /^data:image\/svg/i.test(scriptUrl)
  4119. ) {
  4120. return "";
  4121. }
  4122. }
  4123. if (urlConverter) {
  4124. url = urlConverter.call(urlConverterScope, url, "style");
  4125. }
  4126. return `url('` + url.replace(/\'/g, `\\'`) + `')`;
  4127. };
  4128. if (css) {
  4129. css = css.replace(/[\u0000-\u001F]/g, "");
  4130. css = css
  4131. .replace(/\\[\"\';:\uFEFF]/g, encode)
  4132. .replace(/\"[^\"]+\"|\'[^\']+\'/g, (str) => {
  4133. return str.replace(/[;:]/g, encode);
  4134. });
  4135. let matches;
  4136. while ((matches = styleRegExp.exec(css))) {
  4137. styleRegExp.lastIndex = matches.index + matches[0].length;
  4138. let name = matches[1].replace(trimRightRegExp, "").toLowerCase();
  4139. let value = matches[2].replace(trimRightRegExp, "");
  4140. if (name && value) {
  4141. name = decodeHexSequences(name);
  4142. value = decodeHexSequences(value);
  4143. if (
  4144. name.indexOf(invisibleChar) !== -1 ||
  4145. name.indexOf('"') !== -1
  4146. ) {
  4147. continue;
  4148. }
  4149. if (
  4150. !settings.allow_script_urls &&
  4151. (name === "behavior" || /expression\s*\(|\/\*|\*\//.test(value))
  4152. ) {
  4153. continue;
  4154. }
  4155. if (name === "font-weight" && value === "700") {
  4156. value = "bold";
  4157. } else if (name === "color" || name === "background-color") {
  4158. value = value.toLowerCase();
  4159. }
  4160. value = value.replace(urlOrStrRegExp, processUrl);
  4161. styles[name] = isEncoded ? decode(value, true) : value;
  4162. }
  4163. }
  4164. compress("border", "", true);
  4165. compress("border", "-width");
  4166. compress("border", "-color");
  4167. compress("border", "-style");
  4168. compress("padding", "");
  4169. compress("margin", "");
  4170. compress2("border", "border-width", "border-style", "border-color");
  4171. if (styles.border === "medium none") {
  4172. delete styles.border;
  4173. }
  4174. if (styles["border-image"] === "none") {
  4175. delete styles["border-image"];
  4176. }
  4177. }
  4178. return styles;
  4179. },
  4180. serialize: (styles, elementName) => {
  4181. let css = "";
  4182. const serializeStyles = (elemName, validStyleList) => {
  4183. const styleList = validStyleList[elemName];
  4184. if (styleList) {
  4185. for (let i = 0, l = styleList.length; i < l; i++) {
  4186. const name = styleList[i];
  4187. const value = styles[name];
  4188. if (value) {
  4189. css += (css.length > 0 ? " " : "") + name + ": " + value + ";";
  4190. }
  4191. }
  4192. }
  4193. };
  4194. const isValid = (name, elemName) => {
  4195. if (!invalidStyles || !elemName) {
  4196. return true;
  4197. }
  4198. let styleMap = invalidStyles["*"];
  4199. if (styleMap && styleMap[name]) {
  4200. return false;
  4201. }
  4202. styleMap = invalidStyles[elemName];
  4203. return !(styleMap && styleMap[name]);
  4204. };
  4205. if (elementName && validStyles) {
  4206. serializeStyles("*", validStyles);
  4207. serializeStyles(elementName, validStyles);
  4208. } else {
  4209. each$d(styles, (value, name) => {
  4210. if (value && isValid(name, elementName)) {
  4211. css += (css.length > 0 ? " " : "") + name + ": " + value + ";";
  4212. }
  4213. });
  4214. }
  4215. return css;
  4216. },
  4217. };
  4218. return self;
  4219. };
  4220. const deprecated = {
  4221. keyLocation: true,
  4222. layerX: true,
  4223. layerY: true,
  4224. returnValue: true,
  4225. webkitMovementX: true,
  4226. webkitMovementY: true,
  4227. keyIdentifier: true,
  4228. mozPressure: true,
  4229. };
  4230. const isNativeEvent = (event) =>
  4231. event instanceof Event || isFunction(event.initEvent);
  4232. const hasIsDefaultPrevented = (event) =>
  4233. event.isDefaultPrevented === always || event.isDefaultPrevented === never;
  4234. const needsNormalizing = (event) =>
  4235. isNullable(event.preventDefault) || isNativeEvent(event);
  4236. const clone$3 = (originalEvent, data) => {
  4237. const event = data !== null && data !== void 0 ? data : {};
  4238. for (const name in originalEvent) {
  4239. if (!has$2(deprecated, name)) {
  4240. event[name] = originalEvent[name];
  4241. }
  4242. }
  4243. if (isNonNullable(originalEvent.composedPath)) {
  4244. event.composedPath = () => originalEvent.composedPath();
  4245. }
  4246. return event;
  4247. };
  4248. const normalize$3 = (type, originalEvent, fallbackTarget, data) => {
  4249. var _a;
  4250. const event = clone$3(originalEvent, data);
  4251. event.type = type;
  4252. if (isNullable(event.target)) {
  4253. event.target =
  4254. (_a = event.srcElement) !== null && _a !== void 0 ? _a : fallbackTarget;
  4255. }
  4256. if (needsNormalizing(originalEvent)) {
  4257. event.preventDefault = () => {
  4258. event.defaultPrevented = true;
  4259. event.isDefaultPrevented = always;
  4260. if (isFunction(originalEvent.preventDefault)) {
  4261. originalEvent.preventDefault();
  4262. }
  4263. };
  4264. event.stopPropagation = () => {
  4265. event.cancelBubble = true;
  4266. event.isPropagationStopped = always;
  4267. if (isFunction(originalEvent.stopPropagation)) {
  4268. originalEvent.stopPropagation();
  4269. }
  4270. };
  4271. event.stopImmediatePropagation = () => {
  4272. event.isImmediatePropagationStopped = always;
  4273. event.stopPropagation();
  4274. };
  4275. if (!hasIsDefaultPrevented(event)) {
  4276. event.isDefaultPrevented =
  4277. event.defaultPrevented === true ? always : never;
  4278. event.isPropagationStopped =
  4279. event.cancelBubble === true ? always : never;
  4280. event.isImmediatePropagationStopped = never;
  4281. }
  4282. }
  4283. return event;
  4284. };
  4285. const eventExpandoPrefix = "mce-data-";
  4286. const mouseEventRe = /^(?:mouse|contextmenu)|click/;
  4287. const addEvent = (target, name, callback, capture) => {
  4288. target.addEventListener(name, callback, capture || false);
  4289. };
  4290. const removeEvent = (target, name, callback, capture) => {
  4291. target.removeEventListener(name, callback, capture || false);
  4292. };
  4293. const isMouseEvent = (event) =>
  4294. isNonNullable(event) && mouseEventRe.test(event.type);
  4295. const fix = (originalEvent, data) => {
  4296. const event = normalize$3(
  4297. originalEvent.type,
  4298. originalEvent,
  4299. document,
  4300. data
  4301. );
  4302. if (
  4303. isMouseEvent(originalEvent) &&
  4304. isUndefined(originalEvent.pageX) &&
  4305. !isUndefined(originalEvent.clientX)
  4306. ) {
  4307. const eventDoc = event.target.ownerDocument || document;
  4308. const doc = eventDoc.documentElement;
  4309. const body = eventDoc.body;
  4310. const mouseEvent = event;
  4311. mouseEvent.pageX =
  4312. originalEvent.clientX +
  4313. ((doc && doc.scrollLeft) || (body && body.scrollLeft) || 0) -
  4314. ((doc && doc.clientLeft) || (body && body.clientLeft) || 0);
  4315. mouseEvent.pageY =
  4316. originalEvent.clientY +
  4317. ((doc && doc.scrollTop) || (body && body.scrollTop) || 0) -
  4318. ((doc && doc.clientTop) || (body && body.clientTop) || 0);
  4319. }
  4320. return event;
  4321. };
  4322. const bindOnReady = (win, callback, eventUtils) => {
  4323. const doc = win.document,
  4324. event = { type: "ready" };
  4325. if (eventUtils.domLoaded) {
  4326. callback(event);
  4327. return;
  4328. }
  4329. const isDocReady = () => {
  4330. return (
  4331. doc.readyState === "complete" ||
  4332. (doc.readyState === "interactive" && doc.body)
  4333. );
  4334. };
  4335. const readyHandler = () => {
  4336. removeEvent(win, "DOMContentLoaded", readyHandler);
  4337. removeEvent(win, "load", readyHandler);
  4338. if (!eventUtils.domLoaded) {
  4339. eventUtils.domLoaded = true;
  4340. callback(event);
  4341. }
  4342. win = null;
  4343. };
  4344. if (isDocReady()) {
  4345. readyHandler();
  4346. } else {
  4347. addEvent(win, "DOMContentLoaded", readyHandler);
  4348. }
  4349. if (!eventUtils.domLoaded) {
  4350. addEvent(win, "load", readyHandler);
  4351. }
  4352. };
  4353. class EventUtils {
  4354. constructor() {
  4355. this.domLoaded = false;
  4356. this.events = {};
  4357. this.count = 1;
  4358. this.expando = eventExpandoPrefix + (+new Date()).toString(32);
  4359. this.hasFocusIn = "onfocusin" in document.documentElement;
  4360. this.count = 1;
  4361. }
  4362. bind(target, names, callback, scope) {
  4363. const self = this;
  4364. let callbackList;
  4365. const win = window;
  4366. const defaultNativeHandler = (evt) => {
  4367. self.executeHandlers(fix(evt || win.event), id);
  4368. };
  4369. if (!target || isText$a(target) || isComment(target)) {
  4370. return callback;
  4371. }
  4372. let id;
  4373. if (!target[self.expando]) {
  4374. id = self.count++;
  4375. target[self.expando] = id;
  4376. self.events[id] = {};
  4377. } else {
  4378. id = target[self.expando];
  4379. }
  4380. scope = scope || target;
  4381. const namesList = names.split(" ");
  4382. let i = namesList.length;
  4383. while (i--) {
  4384. let name = namesList[i];
  4385. let nativeHandler = defaultNativeHandler;
  4386. let capture = false;
  4387. let fakeName = false;
  4388. if (name === "DOMContentLoaded") {
  4389. name = "ready";
  4390. }
  4391. if (
  4392. self.domLoaded &&
  4393. name === "ready" &&
  4394. target.readyState === "complete"
  4395. ) {
  4396. callback.call(scope, fix({ type: name }));
  4397. continue;
  4398. }
  4399. if (!self.hasFocusIn && (name === "focusin" || name === "focusout")) {
  4400. capture = true;
  4401. fakeName = name === "focusin" ? "focus" : "blur";
  4402. nativeHandler = (evt) => {
  4403. const event = fix(evt || win.event);
  4404. event.type = event.type === "focus" ? "focusin" : "focusout";
  4405. self.executeHandlers(event, id);
  4406. };
  4407. }
  4408. callbackList = self.events[id][name];
  4409. if (!callbackList) {
  4410. self.events[id][name] = callbackList = [
  4411. {
  4412. func: callback,
  4413. scope,
  4414. },
  4415. ];
  4416. callbackList.fakeName = fakeName;
  4417. callbackList.capture = capture;
  4418. callbackList.nativeHandler = nativeHandler;
  4419. if (name === "ready") {
  4420. bindOnReady(target, nativeHandler, self);
  4421. } else {
  4422. addEvent(target, fakeName || name, nativeHandler, capture);
  4423. }
  4424. } else {
  4425. if (name === "ready" && self.domLoaded) {
  4426. callback(fix({ type: name }));
  4427. } else {
  4428. callbackList.push({
  4429. func: callback,
  4430. scope,
  4431. });
  4432. }
  4433. }
  4434. }
  4435. target = callbackList = null;
  4436. return callback;
  4437. }
  4438. unbind(target, names, callback) {
  4439. if (!target || isText$a(target) || isComment(target)) {
  4440. return this;
  4441. }
  4442. const id = target[this.expando];
  4443. if (id) {
  4444. let eventMap = this.events[id];
  4445. if (names) {
  4446. const namesList = names.split(" ");
  4447. let i = namesList.length;
  4448. while (i--) {
  4449. const name = namesList[i];
  4450. const callbackList = eventMap[name];
  4451. if (callbackList) {
  4452. if (callback) {
  4453. let ci = callbackList.length;
  4454. while (ci--) {
  4455. if (callbackList[ci].func === callback) {
  4456. const nativeHandler = callbackList.nativeHandler;
  4457. const fakeName = callbackList.fakeName,
  4458. capture = callbackList.capture;
  4459. const newCallbackList = callbackList
  4460. .slice(0, ci)
  4461. .concat(callbackList.slice(ci + 1));
  4462. newCallbackList.nativeHandler = nativeHandler;
  4463. newCallbackList.fakeName = fakeName;
  4464. newCallbackList.capture = capture;
  4465. eventMap[name] = newCallbackList;
  4466. }
  4467. }
  4468. }
  4469. if (!callback || callbackList.length === 0) {
  4470. delete eventMap[name];
  4471. removeEvent(
  4472. target,
  4473. callbackList.fakeName || name,
  4474. callbackList.nativeHandler,
  4475. callbackList.capture
  4476. );
  4477. }
  4478. }
  4479. }
  4480. } else {
  4481. each$d(eventMap, (callbackList, name) => {
  4482. removeEvent(
  4483. target,
  4484. callbackList.fakeName || name,
  4485. callbackList.nativeHandler,
  4486. callbackList.capture
  4487. );
  4488. });
  4489. eventMap = {};
  4490. }
  4491. for (const name in eventMap) {
  4492. if (has$2(eventMap, name)) {
  4493. return this;
  4494. }
  4495. }
  4496. delete this.events[id];
  4497. try {
  4498. delete target[this.expando];
  4499. } catch (ex) {
  4500. target[this.expando] = null;
  4501. }
  4502. }
  4503. return this;
  4504. }
  4505. fire(target, name, args) {
  4506. return this.dispatch(target, name, args);
  4507. }
  4508. dispatch(target, name, args) {
  4509. if (!target || isText$a(target) || isComment(target)) {
  4510. return this;
  4511. }
  4512. const event = fix(
  4513. {
  4514. type: name,
  4515. target,
  4516. },
  4517. args
  4518. );
  4519. do {
  4520. const id = target[this.expando];
  4521. if (id) {
  4522. this.executeHandlers(event, id);
  4523. }
  4524. target =
  4525. target.parentNode ||
  4526. target.ownerDocument ||
  4527. target.defaultView ||
  4528. target.parentWindow;
  4529. } while (target && !event.isPropagationStopped());
  4530. return this;
  4531. }
  4532. clean(target) {
  4533. if (!target || isText$a(target) || isComment(target)) {
  4534. return this;
  4535. }
  4536. if (target[this.expando]) {
  4537. this.unbind(target);
  4538. }
  4539. if (!target.getElementsByTagName) {
  4540. target = target.document;
  4541. }
  4542. if (target && target.getElementsByTagName) {
  4543. this.unbind(target);
  4544. const children = target.getElementsByTagName("*");
  4545. let i = children.length;
  4546. while (i--) {
  4547. target = children[i];
  4548. if (target[this.expando]) {
  4549. this.unbind(target);
  4550. }
  4551. }
  4552. }
  4553. return this;
  4554. }
  4555. destroy() {
  4556. this.events = {};
  4557. }
  4558. cancel(e) {
  4559. if (e) {
  4560. e.preventDefault();
  4561. e.stopImmediatePropagation();
  4562. }
  4563. return false;
  4564. }
  4565. executeHandlers(evt, id) {
  4566. const container = this.events[id];
  4567. const callbackList = container && container[evt.type];
  4568. if (callbackList) {
  4569. for (let i = 0, l = callbackList.length; i < l; i++) {
  4570. const callback = callbackList[i];
  4571. if (callback && callback.func.call(callback.scope, evt) === false) {
  4572. evt.preventDefault();
  4573. }
  4574. if (evt.isImmediatePropagationStopped()) {
  4575. return;
  4576. }
  4577. }
  4578. }
  4579. }
  4580. }
  4581. EventUtils.Event = new EventUtils();
  4582. const each$a = Tools.each;
  4583. const grep = Tools.grep;
  4584. const internalStyleName = "data-mce-style";
  4585. const numericalCssMap = Tools.makeMap(
  4586. "fill-opacity font-weight line-height opacity orphans widows z-index zoom",
  4587. " "
  4588. );
  4589. const legacySetAttribute = (elm, name, value) => {
  4590. if (isNullable(value) || value === "") {
  4591. remove$a(elm, name);
  4592. } else {
  4593. set$3(elm, name, value);
  4594. }
  4595. };
  4596. const camelCaseToHyphens = (name) =>
  4597. name.replace(/[A-Z]/g, (v) => "-" + v.toLowerCase());
  4598. const findNodeIndex = (node, normalized) => {
  4599. let idx = 0;
  4600. if (node) {
  4601. for (
  4602. let lastNodeType = node.nodeType, tempNode = node.previousSibling;
  4603. tempNode;
  4604. tempNode = tempNode.previousSibling
  4605. ) {
  4606. const nodeType = tempNode.nodeType;
  4607. if (normalized && isText$a(tempNode)) {
  4608. if (nodeType === lastNodeType || !tempNode.data.length) {
  4609. continue;
  4610. }
  4611. }
  4612. idx++;
  4613. lastNodeType = nodeType;
  4614. }
  4615. }
  4616. return idx;
  4617. };
  4618. const updateInternalStyleAttr = (styles, elm) => {
  4619. const rawValue = get$9(elm, "style");
  4620. const value = styles.serialize(styles.parse(rawValue), name(elm));
  4621. legacySetAttribute(elm, internalStyleName, value);
  4622. };
  4623. const convertStyleToString = (cssValue, cssName) => {
  4624. if (isNumber(cssValue)) {
  4625. return has$2(numericalCssMap, cssName) ? cssValue + "" : cssValue + "px";
  4626. } else {
  4627. return cssValue;
  4628. }
  4629. };
  4630. const applyStyle$1 = ($elm, cssName, cssValue) => {
  4631. const normalizedName = camelCaseToHyphens(cssName);
  4632. if (isNullable(cssValue) || cssValue === "") {
  4633. remove$6($elm, normalizedName);
  4634. } else {
  4635. set$2(
  4636. $elm,
  4637. normalizedName,
  4638. convertStyleToString(cssValue, normalizedName)
  4639. );
  4640. }
  4641. };
  4642. const setupAttrHooks = (styles, settings, getContext) => {
  4643. const keepValues = settings.keep_values;
  4644. const keepUrlHook = {
  4645. set: (elm, value, name) => {
  4646. const sugarElm = SugarElement.fromDom(elm);
  4647. if (isFunction(settings.url_converter) && isNonNullable(value)) {
  4648. value = settings.url_converter.call(
  4649. settings.url_converter_scope || getContext(),
  4650. String(value),
  4651. name,
  4652. elm
  4653. );
  4654. }
  4655. const internalName = "data-mce-" + name;
  4656. legacySetAttribute(sugarElm, internalName, value);
  4657. legacySetAttribute(sugarElm, name, value);
  4658. },
  4659. get: (elm, name) => {
  4660. const sugarElm = SugarElement.fromDom(elm);
  4661. return get$9(sugarElm, "data-mce-" + name) || get$9(sugarElm, name);
  4662. },
  4663. };
  4664. const attrHooks = {
  4665. style: {
  4666. set: (elm, value) => {
  4667. const sugarElm = SugarElement.fromDom(elm);
  4668. if (keepValues) {
  4669. legacySetAttribute(sugarElm, internalStyleName, value);
  4670. }
  4671. remove$a(sugarElm, "style");
  4672. if (isString(value)) {
  4673. setAll(sugarElm, styles.parse(value));
  4674. }
  4675. },
  4676. get: (elm) => {
  4677. const sugarElm = SugarElement.fromDom(elm);
  4678. const value =
  4679. get$9(sugarElm, internalStyleName) || get$9(sugarElm, "style");
  4680. return styles.serialize(styles.parse(value), name(sugarElm));
  4681. },
  4682. },
  4683. };
  4684. if (keepValues) {
  4685. attrHooks.href = attrHooks.src = keepUrlHook;
  4686. }
  4687. return attrHooks;
  4688. };
  4689. const DOMUtils = (doc, settings = {}) => {
  4690. const addedStyles = {};
  4691. const win = window;
  4692. const files = {};
  4693. let counter = 0;
  4694. const stdMode = true;
  4695. const boxModel = true;
  4696. const styleSheetLoader = instance.forElement(SugarElement.fromDom(doc), {
  4697. contentCssCors: settings.contentCssCors,
  4698. referrerPolicy: settings.referrerPolicy,
  4699. });
  4700. const boundEvents = [];
  4701. const schema = settings.schema ? settings.schema : Schema({});
  4702. const styles = Styles(
  4703. {
  4704. url_converter: settings.url_converter,
  4705. url_converter_scope: settings.url_converter_scope,
  4706. },
  4707. settings.schema
  4708. );
  4709. const events = settings.ownEvents ? new EventUtils() : EventUtils.Event;
  4710. const blockElementsMap = schema.getBlockElements();
  4711. const isBlock = (node) => {
  4712. if (isString(node)) {
  4713. return has$2(blockElementsMap, node);
  4714. } else {
  4715. return (
  4716. isElement$6(node) &&
  4717. (has$2(blockElementsMap, node.nodeName) ||
  4718. isTransparentBlock(schema, node))
  4719. );
  4720. }
  4721. };
  4722. const get = (elm) =>
  4723. elm && doc && isString(elm) ? doc.getElementById(elm) : elm;
  4724. const _get = (elm) => {
  4725. const value = get(elm);
  4726. return isNonNullable(value) ? SugarElement.fromDom(value) : null;
  4727. };
  4728. const getAttrib = (elm, name, defaultVal = "") => {
  4729. let value;
  4730. const $elm = _get(elm);
  4731. if (isNonNullable($elm) && isElement$7($elm)) {
  4732. const hook = attrHooks[name];
  4733. if (hook && hook.get) {
  4734. value = hook.get($elm.dom, name);
  4735. } else {
  4736. value = get$9($elm, name);
  4737. }
  4738. }
  4739. return isNonNullable(value) ? value : defaultVal;
  4740. };
  4741. const getAttribs = (elm) => {
  4742. const node = get(elm);
  4743. return isNullable(node) ? [] : node.attributes;
  4744. };
  4745. const setAttrib = (elm, name, value) => {
  4746. run(elm, (e) => {
  4747. if (isElement$6(e)) {
  4748. const $elm = SugarElement.fromDom(e);
  4749. const val = value === "" ? null : value;
  4750. const originalValue = get$9($elm, name);
  4751. const hook = attrHooks[name];
  4752. if (hook && hook.set) {
  4753. hook.set($elm.dom, val, name);
  4754. } else {
  4755. legacySetAttribute($elm, name, val);
  4756. }
  4757. if (originalValue !== val && settings.onSetAttrib) {
  4758. settings.onSetAttrib({
  4759. attrElm: $elm.dom,
  4760. attrName: name,
  4761. attrValue: val,
  4762. });
  4763. }
  4764. }
  4765. });
  4766. };
  4767. const clone = (node, deep) => {
  4768. return node.cloneNode(deep);
  4769. };
  4770. const getRoot = () => settings.root_element || doc.body;
  4771. const getViewPort = (argWin) => {
  4772. const vp = getBounds(argWin);
  4773. return {
  4774. x: vp.x,
  4775. y: vp.y,
  4776. w: vp.width,
  4777. h: vp.height,
  4778. };
  4779. };
  4780. const getPos$1 = (elm, rootElm) => getPos(doc.body, get(elm), rootElm);
  4781. const setStyle = (elm, name, value) => {
  4782. run(elm, (e) => {
  4783. const $elm = SugarElement.fromDom(e);
  4784. applyStyle$1($elm, name, value);
  4785. if (settings.update_styles) {
  4786. updateInternalStyleAttr(styles, $elm);
  4787. }
  4788. });
  4789. };
  4790. const setStyles = (elm, stylesArg) => {
  4791. run(elm, (e) => {
  4792. const $elm = SugarElement.fromDom(e);
  4793. each$d(stylesArg, (v, n) => {
  4794. applyStyle$1($elm, n, v);
  4795. });
  4796. if (settings.update_styles) {
  4797. updateInternalStyleAttr(styles, $elm);
  4798. }
  4799. });
  4800. };
  4801. const getStyle = (elm, name, computed) => {
  4802. const $elm = get(elm);
  4803. if (isNullable($elm) || !isElement$6($elm)) {
  4804. return undefined;
  4805. }
  4806. if (computed) {
  4807. return get$7(SugarElement.fromDom($elm), camelCaseToHyphens(name));
  4808. } else {
  4809. name = name.replace(/-(\D)/g, (a, b) => b.toUpperCase());
  4810. if (name === "float") {
  4811. name = "cssFloat";
  4812. }
  4813. return $elm.style ? $elm.style[name] : undefined;
  4814. }
  4815. };
  4816. const getSize = (elm) => {
  4817. const $elm = get(elm);
  4818. if (!$elm) {
  4819. return {
  4820. w: 0,
  4821. h: 0,
  4822. };
  4823. }
  4824. let w = getStyle($elm, "width");
  4825. let h = getStyle($elm, "height");
  4826. if (!w || w.indexOf("px") === -1) {
  4827. w = "0";
  4828. }
  4829. if (!h || h.indexOf("px") === -1) {
  4830. h = "0";
  4831. }
  4832. return {
  4833. w: parseInt(w, 10) || $elm.offsetWidth || $elm.clientWidth,
  4834. h: parseInt(h, 10) || $elm.offsetHeight || $elm.clientHeight,
  4835. };
  4836. };
  4837. const getRect = (elm) => {
  4838. const $elm = get(elm);
  4839. const pos = getPos$1($elm);
  4840. const size = getSize($elm);
  4841. return {
  4842. x: pos.x,
  4843. y: pos.y,
  4844. w: size.w,
  4845. h: size.h,
  4846. };
  4847. };
  4848. const is = (elm, selector) => {
  4849. if (!elm) {
  4850. return false;
  4851. }
  4852. const elms = isArray$1(elm) ? elm : [elm];
  4853. return exists(elms, (e) => {
  4854. return is$1(SugarElement.fromDom(e), selector);
  4855. });
  4856. };
  4857. const getParents = (elm, selector, root, collect) => {
  4858. const result = [];
  4859. let node = get(elm);
  4860. collect = collect === undefined;
  4861. const resolvedRoot =
  4862. root || (getRoot().nodeName !== "BODY" ? getRoot().parentNode : null);
  4863. if (isString(selector)) {
  4864. if (selector === "*") {
  4865. selector = isElement$6;
  4866. } else {
  4867. const selectorVal = selector;
  4868. selector = (node) => is(node, selectorVal);
  4869. }
  4870. }
  4871. while (node) {
  4872. if (
  4873. node === resolvedRoot ||
  4874. isNullable(node.nodeType) ||
  4875. isDocument$1(node) ||
  4876. isDocumentFragment(node)
  4877. ) {
  4878. break;
  4879. }
  4880. if (!selector || selector(node)) {
  4881. if (collect) {
  4882. result.push(node);
  4883. } else {
  4884. return [node];
  4885. }
  4886. }
  4887. node = node.parentNode;
  4888. }
  4889. return collect ? result : null;
  4890. };
  4891. const getParent = (node, selector, root) => {
  4892. const parents = getParents(node, selector, root, false);
  4893. return parents && parents.length > 0 ? parents[0] : null;
  4894. };
  4895. const _findSib = (node, selector, name) => {
  4896. let func = selector;
  4897. if (node) {
  4898. if (isString(selector)) {
  4899. func = (node) => {
  4900. return is(node, selector);
  4901. };
  4902. }
  4903. for (let tempNode = node[name]; tempNode; tempNode = tempNode[name]) {
  4904. if (isFunction(func) && func(tempNode)) {
  4905. return tempNode;
  4906. }
  4907. }
  4908. }
  4909. return null;
  4910. };
  4911. const getNext = (node, selector) => _findSib(node, selector, "nextSibling");
  4912. const getPrev = (node, selector) =>
  4913. _findSib(node, selector, "previousSibling");
  4914. const isParentNode = (node) => isFunction(node.querySelectorAll);
  4915. const select = (selector, scope) => {
  4916. var _a, _b;
  4917. const elm =
  4918. (_b =
  4919. (_a = get(scope)) !== null && _a !== void 0
  4920. ? _a
  4921. : settings.root_element) !== null && _b !== void 0
  4922. ? _b
  4923. : doc;
  4924. return isParentNode(elm) ? from(elm.querySelectorAll(selector)) : [];
  4925. };
  4926. const run = function (elm, func, scope) {
  4927. const context = scope !== null && scope !== void 0 ? scope : this;
  4928. if (isArray$1(elm)) {
  4929. const result = [];
  4930. each$a(elm, (e, i) => {
  4931. const node = get(e);
  4932. if (node) {
  4933. result.push(func.call(context, node, i));
  4934. }
  4935. });
  4936. return result;
  4937. } else {
  4938. const node = get(elm);
  4939. return !node ? false : func.call(context, node);
  4940. }
  4941. };
  4942. const setAttribs = (elm, attrs) => {
  4943. run(elm, ($elm) => {
  4944. each$d(attrs, (value, name) => {
  4945. setAttrib($elm, name, value);
  4946. });
  4947. });
  4948. };
  4949. const setHTML = (elm, html) => {
  4950. run(elm, (e) => {
  4951. const $elm = SugarElement.fromDom(e);
  4952. set$1($elm, html);
  4953. });
  4954. };
  4955. const add = (parentElm, name, attrs, html, create) =>
  4956. run(parentElm, (parentElm) => {
  4957. const newElm = isString(name) ? doc.createElement(name) : name;
  4958. if (isNonNullable(attrs)) {
  4959. setAttribs(newElm, attrs);
  4960. }
  4961. if (html) {
  4962. if (!isString(html) && html.nodeType) {
  4963. newElm.appendChild(html);
  4964. } else if (isString(html)) {
  4965. setHTML(newElm, html);
  4966. }
  4967. }
  4968. return !create ? parentElm.appendChild(newElm) : newElm;
  4969. });
  4970. const create = (name, attrs, html) =>
  4971. add(doc.createElement(name), name, attrs, html, true);
  4972. const decode = Entities.decode;
  4973. const encode = Entities.encodeAllRaw;
  4974. const createHTML = (name, attrs, html = "") => {
  4975. let outHtml = "<" + name;
  4976. for (const key in attrs) {
  4977. if (hasNonNullableKey(attrs, key)) {
  4978. outHtml += " " + key + '="' + encode(attrs[key]) + '"';
  4979. }
  4980. }
  4981. if (isEmpty$3(html) && has$2(schema.getVoidElements(), name)) {
  4982. return outHtml + " />";
  4983. } else {
  4984. return outHtml + ">" + html + "</" + name + ">";
  4985. }
  4986. };
  4987. const createFragment = (html) => {
  4988. const container = doc.createElement("div");
  4989. const frag = doc.createDocumentFragment();
  4990. frag.appendChild(container);
  4991. if (html) {
  4992. container.innerHTML = html;
  4993. }
  4994. let node;
  4995. while ((node = container.firstChild)) {
  4996. frag.appendChild(node);
  4997. }
  4998. frag.removeChild(container);
  4999. return frag;
  5000. };
  5001. const remove = (node, keepChildren) => {
  5002. return run(node, (n) => {
  5003. const $node = SugarElement.fromDom(n);
  5004. if (keepChildren) {
  5005. each$e(children$1($node), (child) => {
  5006. if (isText$b(child) && child.dom.length === 0) {
  5007. remove$5(child);
  5008. } else {
  5009. before$3($node, child);
  5010. }
  5011. });
  5012. }
  5013. remove$5($node);
  5014. return $node.dom;
  5015. });
  5016. };
  5017. const removeAllAttribs = (e) =>
  5018. run(e, (e) => {
  5019. const attrs = e.attributes;
  5020. for (let i = attrs.length - 1; i >= 0; i--) {
  5021. e.removeAttributeNode(attrs.item(i));
  5022. }
  5023. });
  5024. const parseStyle = (cssText) => styles.parse(cssText);
  5025. const serializeStyle = (stylesArg, name) =>
  5026. styles.serialize(stylesArg, name);
  5027. const addStyle = (cssText) => {
  5028. if (self !== DOMUtils.DOM && doc === document) {
  5029. if (addedStyles[cssText]) {
  5030. return;
  5031. }
  5032. addedStyles[cssText] = true;
  5033. }
  5034. let styleElm = doc.getElementById("mceDefaultStyles");
  5035. if (!styleElm) {
  5036. styleElm = doc.createElement("style");
  5037. styleElm.id = "mceDefaultStyles";
  5038. styleElm.type = "text/css";
  5039. const head = doc.head;
  5040. if (head.firstChild) {
  5041. head.insertBefore(styleElm, head.firstChild);
  5042. } else {
  5043. head.appendChild(styleElm);
  5044. }
  5045. }
  5046. if (styleElm.styleSheet) {
  5047. styleElm.styleSheet.cssText += cssText;
  5048. } else {
  5049. styleElm.appendChild(doc.createTextNode(cssText));
  5050. }
  5051. };
  5052. const loadCSS = (urls) => {
  5053. if (!urls) {
  5054. urls = "";
  5055. }
  5056. each$e(urls.split(","), (url) => {
  5057. files[url] = true;
  5058. styleSheetLoader.load(url).catch(noop);
  5059. });
  5060. };
  5061. const toggleClass = (elm, cls, state) => {
  5062. run(elm, (e) => {
  5063. if (isElement$6(e)) {
  5064. const $elm = SugarElement.fromDom(e);
  5065. const classes = cls.split(" ");
  5066. each$e(classes, (c) => {
  5067. if (isNonNullable(state)) {
  5068. const fn = state ? add$2 : remove$7;
  5069. fn($elm, c);
  5070. } else {
  5071. toggle$1($elm, c);
  5072. }
  5073. });
  5074. }
  5075. });
  5076. };
  5077. const addClass = (elm, cls) => {
  5078. toggleClass(elm, cls, true);
  5079. };
  5080. const removeClass = (elm, cls) => {
  5081. toggleClass(elm, cls, false);
  5082. };
  5083. const hasClass = (elm, cls) => {
  5084. const $elm = _get(elm);
  5085. const classes = cls.split(" ");
  5086. return isNonNullable($elm) && forall(classes, (c) => has($elm, c));
  5087. };
  5088. const show = (elm) => {
  5089. run(elm, (e) => remove$6(SugarElement.fromDom(e), "display"));
  5090. };
  5091. const hide = (elm) => {
  5092. run(elm, (e) => set$2(SugarElement.fromDom(e), "display", "none"));
  5093. };
  5094. const isHidden = (elm) => {
  5095. const $elm = _get(elm);
  5096. return isNonNullable($elm) && is$2(getRaw($elm, "display"), "none");
  5097. };
  5098. const uniqueId = (prefix) => (!prefix ? "mce_" : prefix) + counter++;
  5099. const getOuterHTML = (elm) => {
  5100. const $elm = _get(elm);
  5101. if (isNonNullable($elm)) {
  5102. return isElement$6($elm.dom) ? $elm.dom.outerHTML : getOuter($elm);
  5103. } else {
  5104. return "";
  5105. }
  5106. };
  5107. const setOuterHTML = (elm, html) => {
  5108. run(elm, ($elm) => {
  5109. if (isElement$6($elm)) {
  5110. $elm.outerHTML = html;
  5111. }
  5112. });
  5113. };
  5114. const insertAfter = (node, reference) => {
  5115. const referenceNode = get(reference);
  5116. return run(node, (node) => {
  5117. const parent =
  5118. referenceNode === null || referenceNode === void 0
  5119. ? void 0
  5120. : referenceNode.parentNode;
  5121. const nextSibling =
  5122. referenceNode === null || referenceNode === void 0
  5123. ? void 0
  5124. : referenceNode.nextSibling;
  5125. if (parent) {
  5126. if (nextSibling) {
  5127. parent.insertBefore(node, nextSibling);
  5128. } else {
  5129. parent.appendChild(node);
  5130. }
  5131. }
  5132. return node;
  5133. });
  5134. };
  5135. const replace = (newElm, oldElm, keepChildren) =>
  5136. run(oldElm, (elm) => {
  5137. var _a;
  5138. const replacee = isArray$1(oldElm) ? newElm.cloneNode(true) : newElm;
  5139. if (keepChildren) {
  5140. each$a(grep(elm.childNodes), (node) => {
  5141. replacee.appendChild(node);
  5142. });
  5143. }
  5144. (_a = elm.parentNode) === null || _a === void 0
  5145. ? void 0
  5146. : _a.replaceChild(replacee, elm);
  5147. return elm;
  5148. });
  5149. const rename = (elm, name) => {
  5150. if (elm.nodeName !== name.toUpperCase()) {
  5151. const newElm = create(name);
  5152. each$a(getAttribs(elm), (attrNode) => {
  5153. setAttrib(
  5154. newElm,
  5155. attrNode.nodeName,
  5156. getAttrib(elm, attrNode.nodeName)
  5157. );
  5158. });
  5159. replace(newElm, elm, true);
  5160. return newElm;
  5161. } else {
  5162. return elm;
  5163. }
  5164. };
  5165. const findCommonAncestor = (a, b) => {
  5166. let ps = a;
  5167. while (ps) {
  5168. let pe = b;
  5169. while (pe && ps !== pe) {
  5170. pe = pe.parentNode;
  5171. }
  5172. if (ps === pe) {
  5173. break;
  5174. }
  5175. ps = ps.parentNode;
  5176. }
  5177. if (!ps && a.ownerDocument) {
  5178. return a.ownerDocument.documentElement;
  5179. } else {
  5180. return ps;
  5181. }
  5182. };
  5183. const isNonEmptyElement = (node) => {
  5184. if (isElement$6(node)) {
  5185. const isNamedAnchor =
  5186. node.nodeName.toLowerCase() === "a" &&
  5187. !getAttrib(node, "href") &&
  5188. getAttrib(node, "id");
  5189. if (
  5190. getAttrib(node, "name") ||
  5191. getAttrib(node, "data-mce-bookmark") ||
  5192. isNamedAnchor
  5193. ) {
  5194. return true;
  5195. }
  5196. }
  5197. return false;
  5198. };
  5199. const isEmpty = (node, elements, options) => {
  5200. let brCount = 0;
  5201. if (isNonEmptyElement(node)) {
  5202. return false;
  5203. }
  5204. const firstChild = node.firstChild;
  5205. if (firstChild) {
  5206. const walker = new DomTreeWalker(firstChild, node);
  5207. const whitespaceElements = schema ? schema.getWhitespaceElements() : {};
  5208. const nonEmptyElements =
  5209. elements || (schema ? schema.getNonEmptyElements() : null);
  5210. let tempNode = firstChild;
  5211. do {
  5212. if (isElement$6(tempNode)) {
  5213. const bogusVal = tempNode.getAttribute("data-mce-bogus");
  5214. if (bogusVal) {
  5215. tempNode = walker.next(bogusVal === "all");
  5216. continue;
  5217. }
  5218. const name = tempNode.nodeName.toLowerCase();
  5219. if (nonEmptyElements && nonEmptyElements[name]) {
  5220. if (name === "br") {
  5221. brCount++;
  5222. tempNode = walker.next();
  5223. continue;
  5224. }
  5225. return false;
  5226. }
  5227. if (isNonEmptyElement(tempNode)) {
  5228. return false;
  5229. }
  5230. }
  5231. if (isComment(tempNode)) {
  5232. return false;
  5233. }
  5234. if (
  5235. isText$a(tempNode) &&
  5236. !isWhitespaceText(tempNode.data) &&
  5237. (!(options === null || options === void 0
  5238. ? void 0
  5239. : options.includeZwsp) ||
  5240. !isZwsp(tempNode.data))
  5241. ) {
  5242. return false;
  5243. }
  5244. if (
  5245. isText$a(tempNode) &&
  5246. tempNode.parentNode &&
  5247. whitespaceElements[tempNode.parentNode.nodeName] &&
  5248. isWhitespaceText(tempNode.data)
  5249. ) {
  5250. return false;
  5251. }
  5252. tempNode = walker.next();
  5253. } while (tempNode);
  5254. }
  5255. return brCount <= 1;
  5256. };
  5257. const createRng = () => doc.createRange();
  5258. const split = (parentElm, splitElm, replacementElm) => {
  5259. let range = createRng();
  5260. let beforeFragment;
  5261. let afterFragment;
  5262. if (
  5263. parentElm &&
  5264. splitElm &&
  5265. parentElm.parentNode &&
  5266. splitElm.parentNode
  5267. ) {
  5268. const parentNode = parentElm.parentNode;
  5269. range.setStart(parentNode, findNodeIndex(parentElm));
  5270. range.setEnd(splitElm.parentNode, findNodeIndex(splitElm));
  5271. beforeFragment = range.extractContents();
  5272. range = createRng();
  5273. range.setStart(splitElm.parentNode, findNodeIndex(splitElm) + 1);
  5274. range.setEnd(parentNode, findNodeIndex(parentElm) + 1);
  5275. afterFragment = range.extractContents();
  5276. parentNode.insertBefore(trimNode(self, beforeFragment), parentElm);
  5277. if (replacementElm) {
  5278. parentNode.insertBefore(replacementElm, parentElm);
  5279. } else {
  5280. parentNode.insertBefore(splitElm, parentElm);
  5281. }
  5282. parentNode.insertBefore(trimNode(self, afterFragment), parentElm);
  5283. remove(parentElm);
  5284. return replacementElm || splitElm;
  5285. } else {
  5286. return undefined;
  5287. }
  5288. };
  5289. const bind = (target, name, func, scope) => {
  5290. if (isArray$1(target)) {
  5291. let i = target.length;
  5292. const rv = [];
  5293. while (i--) {
  5294. rv[i] = bind(target[i], name, func, scope);
  5295. }
  5296. return rv;
  5297. } else {
  5298. if (settings.collect && (target === doc || target === win)) {
  5299. boundEvents.push([target, name, func, scope]);
  5300. }
  5301. return events.bind(target, name, func, scope || self);
  5302. }
  5303. };
  5304. const unbind = (target, name, func) => {
  5305. if (isArray$1(target)) {
  5306. let i = target.length;
  5307. const rv = [];
  5308. while (i--) {
  5309. rv[i] = unbind(target[i], name, func);
  5310. }
  5311. return rv;
  5312. } else {
  5313. if (boundEvents.length > 0 && (target === doc || target === win)) {
  5314. let i = boundEvents.length;
  5315. while (i--) {
  5316. const [boundTarget, boundName, boundFunc] = boundEvents[i];
  5317. if (
  5318. target === boundTarget &&
  5319. (!name || name === boundName) &&
  5320. (!func || func === boundFunc)
  5321. ) {
  5322. events.unbind(boundTarget, boundName, boundFunc);
  5323. }
  5324. }
  5325. }
  5326. return events.unbind(target, name, func);
  5327. }
  5328. };
  5329. const dispatch = (target, name, evt) => events.dispatch(target, name, evt);
  5330. const fire = (target, name, evt) => events.dispatch(target, name, evt);
  5331. const getContentEditable = (node) => {
  5332. if (node && isElement$6(node)) {
  5333. const contentEditable = node.getAttribute("data-mce-contenteditable");
  5334. if (contentEditable && contentEditable !== "inherit") {
  5335. return contentEditable;
  5336. }
  5337. return node.contentEditable !== "inherit" ? node.contentEditable : null;
  5338. } else {
  5339. return null;
  5340. }
  5341. };
  5342. const getContentEditableParent = (node) => {
  5343. const root = getRoot();
  5344. let state = null;
  5345. for (
  5346. let tempNode = node;
  5347. tempNode && tempNode !== root;
  5348. tempNode = tempNode.parentNode
  5349. ) {
  5350. state = getContentEditable(tempNode);
  5351. if (state !== null) {
  5352. break;
  5353. }
  5354. }
  5355. return state;
  5356. };
  5357. const isEditable = (node) => {
  5358. if (isNonNullable(node)) {
  5359. const scope = isElement$6(node) ? node : node.parentElement;
  5360. return (
  5361. isNonNullable(scope) && isEditable$3(SugarElement.fromDom(scope))
  5362. );
  5363. } else {
  5364. return false;
  5365. }
  5366. };
  5367. const destroy = () => {
  5368. if (boundEvents.length > 0) {
  5369. let i = boundEvents.length;
  5370. while (i--) {
  5371. const [boundTarget, boundName, boundFunc] = boundEvents[i];
  5372. events.unbind(boundTarget, boundName, boundFunc);
  5373. }
  5374. }
  5375. each$d(files, (_, url) => {
  5376. styleSheetLoader.unload(url);
  5377. delete files[url];
  5378. });
  5379. };
  5380. const isChildOf = (node, parent) => {
  5381. return node === parent || parent.contains(node);
  5382. };
  5383. const dumpRng = (r) =>
  5384. "startContainer: " +
  5385. r.startContainer.nodeName +
  5386. ", startOffset: " +
  5387. r.startOffset +
  5388. ", endContainer: " +
  5389. r.endContainer.nodeName +
  5390. ", endOffset: " +
  5391. r.endOffset;
  5392. const self = {
  5393. doc,
  5394. settings,
  5395. win,
  5396. files,
  5397. stdMode,
  5398. boxModel,
  5399. styleSheetLoader,
  5400. boundEvents,
  5401. styles,
  5402. schema,
  5403. events,
  5404. isBlock: isBlock,
  5405. root: null,
  5406. clone,
  5407. getRoot,
  5408. getViewPort,
  5409. getRect,
  5410. getSize,
  5411. getParent,
  5412. getParents: getParents,
  5413. get,
  5414. getNext,
  5415. getPrev,
  5416. select,
  5417. is,
  5418. add,
  5419. create,
  5420. createHTML,
  5421. createFragment,
  5422. remove,
  5423. setStyle,
  5424. getStyle: getStyle,
  5425. setStyles,
  5426. removeAllAttribs,
  5427. setAttrib,
  5428. setAttribs,
  5429. getAttrib,
  5430. getPos: getPos$1,
  5431. parseStyle,
  5432. serializeStyle,
  5433. addStyle,
  5434. loadCSS,
  5435. addClass,
  5436. removeClass,
  5437. hasClass,
  5438. toggleClass,
  5439. show,
  5440. hide,
  5441. isHidden,
  5442. uniqueId,
  5443. setHTML,
  5444. getOuterHTML,
  5445. setOuterHTML,
  5446. decode,
  5447. encode,
  5448. insertAfter,
  5449. replace,
  5450. rename,
  5451. findCommonAncestor,
  5452. run,
  5453. getAttribs,
  5454. isEmpty,
  5455. createRng,
  5456. nodeIndex: findNodeIndex,
  5457. split,
  5458. bind: bind,
  5459. unbind: unbind,
  5460. fire,
  5461. dispatch,
  5462. getContentEditable,
  5463. getContentEditableParent,
  5464. isEditable,
  5465. destroy,
  5466. isChildOf,
  5467. dumpRng,
  5468. };
  5469. const attrHooks = setupAttrHooks(styles, settings, constant(self));
  5470. return self;
  5471. };
  5472. DOMUtils.DOM = DOMUtils(document);
  5473. DOMUtils.nodeIndex = findNodeIndex;
  5474. const DOM$b = DOMUtils.DOM;
  5475. const QUEUED = 0;
  5476. const LOADING = 1;
  5477. const LOADED = 2;
  5478. const FAILED = 3;
  5479. class ScriptLoader {
  5480. constructor(settings = {}) {
  5481. this.states = {};
  5482. this.queue = [];
  5483. this.scriptLoadedCallbacks = {};
  5484. this.queueLoadedCallbacks = [];
  5485. this.loading = false;
  5486. this.settings = settings;
  5487. }
  5488. _setReferrerPolicy(referrerPolicy) {
  5489. this.settings.referrerPolicy = referrerPolicy;
  5490. }
  5491. loadScript(url) {
  5492. return new Promise((resolve, reject) => {
  5493. const dom = DOM$b;
  5494. let elm;
  5495. const cleanup = () => {
  5496. dom.remove(id);
  5497. if (elm) {
  5498. elm.onerror = elm.onload = elm = null;
  5499. }
  5500. };
  5501. const done = () => {
  5502. cleanup();
  5503. resolve();
  5504. };
  5505. const error = () => {
  5506. cleanup();
  5507. reject("Failed to load script: " + url);
  5508. };
  5509. const id = dom.uniqueId();
  5510. elm = document.createElement("script");
  5511. elm.id = id;
  5512. elm.type = "text/javascript";
  5513. elm.src = Tools._addCacheSuffix(url);
  5514. if (this.settings.referrerPolicy) {
  5515. dom.setAttrib(elm, "referrerpolicy", this.settings.referrerPolicy);
  5516. }
  5517. elm.onload = done;
  5518. elm.onerror = error;
  5519. (document.getElementsByTagName("head")[0] || document.body).appendChild(
  5520. elm
  5521. );
  5522. });
  5523. }
  5524. isDone(url) {
  5525. return this.states[url] === LOADED;
  5526. }
  5527. markDone(url) {
  5528. this.states[url] = LOADED;
  5529. }
  5530. add(url) {
  5531. const self = this;
  5532. self.queue.push(url);
  5533. const state = self.states[url];
  5534. if (state === undefined) {
  5535. self.states[url] = QUEUED;
  5536. }
  5537. return new Promise((resolve, reject) => {
  5538. if (!self.scriptLoadedCallbacks[url]) {
  5539. self.scriptLoadedCallbacks[url] = [];
  5540. }
  5541. self.scriptLoadedCallbacks[url].push({
  5542. resolve,
  5543. reject,
  5544. });
  5545. });
  5546. }
  5547. load(url) {
  5548. return this.add(url);
  5549. }
  5550. remove(url) {
  5551. delete this.states[url];
  5552. delete this.scriptLoadedCallbacks[url];
  5553. }
  5554. loadQueue() {
  5555. const queue = this.queue;
  5556. this.queue = [];
  5557. return this.loadScripts(queue);
  5558. }
  5559. loadScripts(scripts) {
  5560. const self = this;
  5561. const execCallbacks = (name, url) => {
  5562. get$a(self.scriptLoadedCallbacks, url).each((callbacks) => {
  5563. each$e(callbacks, (callback) => callback[name](url));
  5564. });
  5565. delete self.scriptLoadedCallbacks[url];
  5566. };
  5567. const processResults = (results) => {
  5568. const failures = filter$5(
  5569. results,
  5570. (result) => result.status === "rejected"
  5571. );
  5572. if (failures.length > 0) {
  5573. return Promise.reject(
  5574. bind$3(failures, ({ reason }) =>
  5575. isArray$1(reason) ? reason : [reason]
  5576. )
  5577. );
  5578. } else {
  5579. return Promise.resolve();
  5580. }
  5581. };
  5582. const load = (urls) =>
  5583. Promise.allSettled(
  5584. map$3(urls, (url) => {
  5585. if (self.states[url] === LOADED) {
  5586. execCallbacks("resolve", url);
  5587. return Promise.resolve();
  5588. } else if (self.states[url] === FAILED) {
  5589. execCallbacks("reject", url);
  5590. return Promise.reject(url);
  5591. } else {
  5592. self.states[url] = LOADING;
  5593. return self.loadScript(url).then(
  5594. () => {
  5595. self.states[url] = LOADED;
  5596. execCallbacks("resolve", url);
  5597. const queue = self.queue;
  5598. if (queue.length > 0) {
  5599. self.queue = [];
  5600. return load(queue).then(processResults);
  5601. } else {
  5602. return Promise.resolve();
  5603. }
  5604. },
  5605. () => {
  5606. self.states[url] = FAILED;
  5607. execCallbacks("reject", url);
  5608. return Promise.reject(url);
  5609. }
  5610. );
  5611. }
  5612. })
  5613. );
  5614. const processQueue = (urls) => {
  5615. self.loading = true;
  5616. return load(urls).then((results) => {
  5617. self.loading = false;
  5618. const nextQueuedItem = self.queueLoadedCallbacks.shift();
  5619. Optional.from(nextQueuedItem).each(call);
  5620. return processResults(results);
  5621. });
  5622. };
  5623. const uniqueScripts = stringArray(scripts);
  5624. if (self.loading) {
  5625. return new Promise((resolve, reject) => {
  5626. self.queueLoadedCallbacks.push(() => {
  5627. processQueue(uniqueScripts).then(resolve, reject);
  5628. });
  5629. });
  5630. } else {
  5631. return processQueue(uniqueScripts);
  5632. }
  5633. }
  5634. }
  5635. ScriptLoader.ScriptLoader = new ScriptLoader();
  5636. const Cell = (initial) => {
  5637. let value = initial;
  5638. const get = () => {
  5639. return value;
  5640. };
  5641. const set = (v) => {
  5642. value = v;
  5643. };
  5644. return {
  5645. get,
  5646. set,
  5647. };
  5648. };
  5649. const isDuplicated = (items, item) => {
  5650. const firstIndex = items.indexOf(item);
  5651. return (
  5652. firstIndex !== -1 && items.indexOf(item, firstIndex + 1) > firstIndex
  5653. );
  5654. };
  5655. const isRaw = (str) => isObject(str) && has$2(str, "raw");
  5656. const isTokenised = (str) => isArray$1(str) && str.length > 1;
  5657. const data = {};
  5658. const currentCode = Cell("en");
  5659. const getLanguageData = () => get$a(data, currentCode.get());
  5660. const getData$1 = () => map$2(data, (value) => ({ ...value }));
  5661. const setCode = (newCode) => {
  5662. if (newCode) {
  5663. currentCode.set(newCode);
  5664. }
  5665. };
  5666. const getCode = () => currentCode.get();
  5667. const add$1 = (code, items) => {
  5668. let langData = data[code];
  5669. if (!langData) {
  5670. data[code] = langData = {};
  5671. }
  5672. const lcNames = map$3(keys(items), (name) => name.toLowerCase());
  5673. each$d(items, (translation, name) => {
  5674. const lcName = name.toLowerCase();
  5675. if (lcName !== name && isDuplicated(lcNames, lcName)) {
  5676. if (!has$2(items, lcName)) {
  5677. langData[lcName] = translation;
  5678. }
  5679. langData[name] = translation;
  5680. } else {
  5681. langData[lcName] = translation;
  5682. }
  5683. });
  5684. };
  5685. const translate = (text) => {
  5686. const langData = getLanguageData().getOr({});
  5687. const toString = (obj) => {
  5688. if (isFunction(obj)) {
  5689. return Object.prototype.toString.call(obj);
  5690. }
  5691. return !isEmpty(obj) ? "" + obj : "";
  5692. };
  5693. const isEmpty = (text) =>
  5694. text === "" || text === null || text === undefined;
  5695. const getLangData = (text) => {
  5696. const textStr = toString(text);
  5697. return has$2(langData, textStr)
  5698. ? toString(langData[textStr])
  5699. : get$a(langData, textStr.toLowerCase()).map(toString).getOr(textStr);
  5700. };
  5701. const removeContext = (str) => str.replace(/{context:\w+}$/, "");
  5702. if (isEmpty(text)) {
  5703. return "";
  5704. }
  5705. if (isRaw(text)) {
  5706. return toString(text.raw);
  5707. }
  5708. if (isTokenised(text)) {
  5709. const values = text.slice(1);
  5710. const substitued = getLangData(text[0]).replace(
  5711. /\{([0-9]+)\}/g,
  5712. ($1, $2) => (has$2(values, $2) ? toString(values[$2]) : $1)
  5713. );
  5714. return removeContext(substitued);
  5715. }
  5716. return removeContext(getLangData(text));
  5717. };
  5718. const isRtl$1 = () =>
  5719. getLanguageData()
  5720. .bind((items) => get$a(items, "_dir"))
  5721. .exists((dir) => dir === "rtl");
  5722. const hasCode = (code) => has$2(data, code);
  5723. const I18n = {
  5724. getData: getData$1,
  5725. setCode,
  5726. getCode,
  5727. add: add$1,
  5728. translate,
  5729. isRtl: isRtl$1,
  5730. hasCode,
  5731. };
  5732. const AddOnManager = () => {
  5733. const items = [];
  5734. const urls = {};
  5735. const lookup = {};
  5736. const _listeners = [];
  5737. const runListeners = (name, state) => {
  5738. const matchedListeners = filter$5(
  5739. _listeners,
  5740. (listener) => listener.name === name && listener.state === state
  5741. );
  5742. each$e(matchedListeners, (listener) => listener.resolve());
  5743. };
  5744. const isLoaded = (name) => has$2(urls, name);
  5745. const isAdded = (name) => has$2(lookup, name);
  5746. const get = (name) => {
  5747. if (lookup[name]) {
  5748. return lookup[name].instance;
  5749. }
  5750. return undefined;
  5751. };
  5752. const loadLanguagePack = (name, languages) => {
  5753. const language = I18n.getCode();
  5754. const wrappedLanguages = "," + (languages || "") + ",";
  5755. if (
  5756. !language ||
  5757. (languages && wrappedLanguages.indexOf("," + language + ",") === -1)
  5758. ) {
  5759. return;
  5760. }
  5761. ScriptLoader.ScriptLoader.add(urls[name] + "/langs/" + language + ".js");
  5762. };
  5763. const requireLangPack = (name, languages) => {
  5764. if (AddOnManager.languageLoad !== false) {
  5765. if (isLoaded(name)) {
  5766. loadLanguagePack(name, languages);
  5767. } else {
  5768. waitFor(name, "loaded").then(() => loadLanguagePack(name, languages));
  5769. }
  5770. }
  5771. };
  5772. const add = (id, addOn) => {
  5773. items.push(addOn);
  5774. lookup[id] = { instance: addOn };
  5775. runListeners(id, "added");
  5776. return addOn;
  5777. };
  5778. const remove = (name) => {
  5779. delete urls[name];
  5780. delete lookup[name];
  5781. };
  5782. const createUrl = (baseUrl, dep) => {
  5783. if (isString(dep)) {
  5784. return isString(baseUrl)
  5785. ? {
  5786. prefix: "",
  5787. resource: dep,
  5788. suffix: "",
  5789. }
  5790. : {
  5791. prefix: baseUrl.prefix,
  5792. resource: dep,
  5793. suffix: baseUrl.suffix,
  5794. };
  5795. } else {
  5796. return dep;
  5797. }
  5798. };
  5799. const load = (name, addOnUrl) => {
  5800. if (urls[name]) {
  5801. return Promise.resolve();
  5802. }
  5803. let urlString = isString(addOnUrl)
  5804. ? addOnUrl
  5805. : addOnUrl.prefix + addOnUrl.resource + addOnUrl.suffix;
  5806. if (urlString.indexOf("/") !== 0 && urlString.indexOf("://") === -1) {
  5807. urlString = AddOnManager.baseURL + "/" + urlString;
  5808. }
  5809. urls[name] = urlString.substring(0, urlString.lastIndexOf("/"));
  5810. const done = () => {
  5811. runListeners(name, "loaded");
  5812. return Promise.resolve();
  5813. };
  5814. if (lookup[name]) {
  5815. return done();
  5816. } else {
  5817. return ScriptLoader.ScriptLoader.add(urlString).then(done);
  5818. }
  5819. };
  5820. const waitFor = (name, state = "added") => {
  5821. if (state === "added" && isAdded(name)) {
  5822. return Promise.resolve();
  5823. } else if (state === "loaded" && isLoaded(name)) {
  5824. return Promise.resolve();
  5825. } else {
  5826. return new Promise((resolve) => {
  5827. _listeners.push({
  5828. name,
  5829. state,
  5830. resolve,
  5831. });
  5832. });
  5833. }
  5834. };
  5835. return {
  5836. items,
  5837. urls,
  5838. lookup,
  5839. get,
  5840. requireLangPack,
  5841. add,
  5842. remove,
  5843. createUrl,
  5844. load,
  5845. waitFor,
  5846. };
  5847. };
  5848. AddOnManager.languageLoad = true;
  5849. AddOnManager.baseURL = "";
  5850. AddOnManager.PluginManager = AddOnManager();
  5851. AddOnManager.ThemeManager = AddOnManager();
  5852. AddOnManager.ModelManager = AddOnManager();
  5853. const singleton = (doRevoke) => {
  5854. const subject = Cell(Optional.none());
  5855. const revoke = () => subject.get().each(doRevoke);
  5856. const clear = () => {
  5857. revoke();
  5858. subject.set(Optional.none());
  5859. };
  5860. const isSet = () => subject.get().isSome();
  5861. const get = () => subject.get();
  5862. const set = (s) => {
  5863. revoke();
  5864. subject.set(Optional.some(s));
  5865. };
  5866. return {
  5867. clear,
  5868. isSet,
  5869. get,
  5870. set,
  5871. };
  5872. };
  5873. const repeatable = (delay) => {
  5874. const intervalId = Cell(Optional.none());
  5875. const revoke = () => intervalId.get().each((id) => clearInterval(id));
  5876. const clear = () => {
  5877. revoke();
  5878. intervalId.set(Optional.none());
  5879. };
  5880. const isSet = () => intervalId.get().isSome();
  5881. const get = () => intervalId.get();
  5882. const set = (functionToRepeat) => {
  5883. revoke();
  5884. intervalId.set(Optional.some(setInterval(functionToRepeat, delay)));
  5885. };
  5886. return {
  5887. clear,
  5888. isSet,
  5889. get,
  5890. set,
  5891. };
  5892. };
  5893. const value$2 = () => {
  5894. const subject = singleton(noop);
  5895. const on = (f) => subject.get().each(f);
  5896. return {
  5897. ...subject,
  5898. on,
  5899. };
  5900. };
  5901. const first$1 = (fn, rate) => {
  5902. let timer = null;
  5903. const cancel = () => {
  5904. if (!isNull(timer)) {
  5905. clearTimeout(timer);
  5906. timer = null;
  5907. }
  5908. };
  5909. const throttle = (...args) => {
  5910. if (isNull(timer)) {
  5911. timer = setTimeout(() => {
  5912. timer = null;
  5913. fn.apply(null, args);
  5914. }, rate);
  5915. }
  5916. };
  5917. return {
  5918. cancel,
  5919. throttle,
  5920. };
  5921. };
  5922. const last$1 = (fn, rate) => {
  5923. let timer = null;
  5924. const cancel = () => {
  5925. if (!isNull(timer)) {
  5926. clearTimeout(timer);
  5927. timer = null;
  5928. }
  5929. };
  5930. const throttle = (...args) => {
  5931. cancel();
  5932. timer = setTimeout(() => {
  5933. timer = null;
  5934. fn.apply(null, args);
  5935. }, rate);
  5936. };
  5937. return {
  5938. cancel,
  5939. throttle,
  5940. };
  5941. };
  5942. const annotation = constant("mce-annotation");
  5943. const dataAnnotation = constant("data-mce-annotation");
  5944. const dataAnnotationId = constant("data-mce-annotation-uid");
  5945. const dataAnnotationActive = constant("data-mce-annotation-active");
  5946. const dataAnnotationClasses = constant("data-mce-annotation-classes");
  5947. const dataAnnotationAttributes = constant("data-mce-annotation-attrs");
  5948. const isRoot$1 = (root) => (node) => eq(node, root);
  5949. const identify = (editor, annotationName) => {
  5950. const rng = editor.selection.getRng();
  5951. const start = SugarElement.fromDom(rng.startContainer);
  5952. const root = SugarElement.fromDom(editor.getBody());
  5953. const selector = annotationName.fold(
  5954. () => "." + annotation(),
  5955. (an) => `[${dataAnnotation()}="${an}"]`
  5956. );
  5957. const newStart = child$1(start, rng.startOffset).getOr(start);
  5958. const closest = closest$3(newStart, selector, isRoot$1(root));
  5959. return closest.bind((c) =>
  5960. getOpt(c, `${dataAnnotationId()}`).bind((uid) =>
  5961. getOpt(c, `${dataAnnotation()}`).map((name) => {
  5962. const elements = findMarkers(editor, uid);
  5963. return {
  5964. uid,
  5965. name,
  5966. elements,
  5967. };
  5968. })
  5969. )
  5970. );
  5971. };
  5972. const isAnnotation = (elem) => isElement$7(elem) && has(elem, annotation());
  5973. const isBogusElement = (elem, root) =>
  5974. has$1(elem, "data-mce-bogus") ||
  5975. ancestor$2(elem, '[data-mce-bogus="all"]', isRoot$1(root));
  5976. const findMarkers = (editor, uid) => {
  5977. const body = SugarElement.fromDom(editor.getBody());
  5978. const descendants$1 = descendants(body, `[${dataAnnotationId()}="${uid}"]`);
  5979. return filter$5(
  5980. descendants$1,
  5981. (descendant) => !isBogusElement(descendant, body)
  5982. );
  5983. };
  5984. const findAll = (editor, name) => {
  5985. const body = SugarElement.fromDom(editor.getBody());
  5986. const markers = descendants(body, `[${dataAnnotation()}="${name}"]`);
  5987. const directory = {};
  5988. each$e(markers, (m) => {
  5989. if (!isBogusElement(m, body)) {
  5990. const uid = get$9(m, dataAnnotationId());
  5991. const nodesAlready = get$a(directory, uid).getOr([]);
  5992. directory[uid] = nodesAlready.concat([m]);
  5993. }
  5994. });
  5995. return directory;
  5996. };
  5997. const setup$x = (editor, registry) => {
  5998. const changeCallbacks = Cell({});
  5999. const initData = () => ({
  6000. listeners: [],
  6001. previous: value$2(),
  6002. });
  6003. const withCallbacks = (name, f) => {
  6004. updateCallbacks(name, (data) => {
  6005. f(data);
  6006. return data;
  6007. });
  6008. };
  6009. const updateCallbacks = (name, f) => {
  6010. const callbackMap = changeCallbacks.get();
  6011. const data = get$a(callbackMap, name).getOrThunk(initData);
  6012. const outputData = f(data);
  6013. callbackMap[name] = outputData;
  6014. changeCallbacks.set(callbackMap);
  6015. };
  6016. const fireCallbacks = (name, uid, elements) => {
  6017. withCallbacks(name, (data) => {
  6018. each$e(data.listeners, (f) =>
  6019. f(true, name, {
  6020. uid,
  6021. nodes: map$3(elements, (elem) => elem.dom),
  6022. })
  6023. );
  6024. });
  6025. };
  6026. const fireNoAnnotation = (name) => {
  6027. withCallbacks(name, (data) => {
  6028. each$e(data.listeners, (f) => f(false, name));
  6029. });
  6030. };
  6031. const toggleActiveAttr = (uid, state) => {
  6032. each$e(findMarkers(editor, uid), (elem) => {
  6033. if (state) {
  6034. set$3(elem, dataAnnotationActive(), "true");
  6035. } else {
  6036. remove$a(elem, dataAnnotationActive());
  6037. }
  6038. });
  6039. };
  6040. const onNodeChange = last$1(() => {
  6041. const annotations = sort(registry.getNames());
  6042. each$e(annotations, (name) => {
  6043. updateCallbacks(name, (data) => {
  6044. const prev = data.previous.get();
  6045. identify(editor, Optional.some(name)).fold(
  6046. () => {
  6047. prev.each((uid) => {
  6048. fireNoAnnotation(name);
  6049. data.previous.clear();
  6050. toggleActiveAttr(uid, false);
  6051. });
  6052. },
  6053. ({ uid, name, elements }) => {
  6054. if (!is$2(prev, uid)) {
  6055. prev.each((uid) => toggleActiveAttr(uid, false));
  6056. fireCallbacks(name, uid, elements);
  6057. data.previous.set(uid);
  6058. toggleActiveAttr(uid, true);
  6059. }
  6060. }
  6061. );
  6062. return {
  6063. previous: data.previous,
  6064. listeners: data.listeners,
  6065. };
  6066. });
  6067. });
  6068. }, 30);
  6069. editor.on("remove", () => {
  6070. onNodeChange.cancel();
  6071. });
  6072. editor.on("NodeChange", () => {
  6073. onNodeChange.throttle();
  6074. });
  6075. const addListener = (name, f) => {
  6076. updateCallbacks(name, (data) => ({
  6077. previous: data.previous,
  6078. listeners: data.listeners.concat([f]),
  6079. }));
  6080. };
  6081. return { addListener };
  6082. };
  6083. const setup$w = (editor, registry) => {
  6084. const dataAnnotation$1 = dataAnnotation();
  6085. const identifyParserNode = (node) =>
  6086. Optional.from(node.attr(dataAnnotation$1)).bind(registry.lookup);
  6087. const removeDirectAnnotation = (node) => {
  6088. var _a, _b;
  6089. node.attr(dataAnnotationId(), null);
  6090. node.attr(dataAnnotation(), null);
  6091. node.attr(dataAnnotationActive(), null);
  6092. const customAttrNames = Optional.from(
  6093. node.attr(dataAnnotationAttributes())
  6094. )
  6095. .map((names) => names.split(","))
  6096. .getOr([]);
  6097. const customClasses = Optional.from(node.attr(dataAnnotationClasses()))
  6098. .map((names) => names.split(","))
  6099. .getOr([]);
  6100. each$e(customAttrNames, (name) => node.attr(name, null));
  6101. const classList =
  6102. (_b =
  6103. (_a = node.attr("class")) === null || _a === void 0
  6104. ? void 0
  6105. : _a.split(" ")) !== null && _b !== void 0
  6106. ? _b
  6107. : [];
  6108. const newClassList = difference(
  6109. classList,
  6110. [annotation()].concat(customClasses)
  6111. );
  6112. node.attr(
  6113. "class",
  6114. newClassList.length > 0 ? newClassList.join(" ") : null
  6115. );
  6116. node.attr(dataAnnotationClasses(), null);
  6117. node.attr(dataAnnotationAttributes(), null);
  6118. };
  6119. editor.serializer.addTempAttr(dataAnnotationActive());
  6120. editor.serializer.addAttributeFilter(dataAnnotation$1, (nodes) => {
  6121. for (const node of nodes) {
  6122. identifyParserNode(node).each((settings) => {
  6123. if (settings.persistent === false) {
  6124. if (node.name === "span") {
  6125. node.unwrap();
  6126. } else {
  6127. removeDirectAnnotation(node);
  6128. }
  6129. }
  6130. });
  6131. }
  6132. });
  6133. };
  6134. const create$c = () => {
  6135. const annotations = {};
  6136. const register = (name, settings) => {
  6137. annotations[name] = {
  6138. name,
  6139. settings,
  6140. };
  6141. };
  6142. const lookup = (name) => get$a(annotations, name).map((a) => a.settings);
  6143. const getNames = () => keys(annotations);
  6144. return {
  6145. register,
  6146. lookup,
  6147. getNames,
  6148. };
  6149. };
  6150. let unique = 0;
  6151. const generate$1 = (prefix) => {
  6152. const date = new Date();
  6153. const time = date.getTime();
  6154. const random = Math.floor(Math.random() * 1000000000);
  6155. unique++;
  6156. return prefix + "_" + random + unique + String(time);
  6157. };
  6158. const add = (element, classes) => {
  6159. each$e(classes, (x) => {
  6160. add$2(element, x);
  6161. });
  6162. };
  6163. const remove$4 = (element, classes) => {
  6164. each$e(classes, (x) => {
  6165. remove$7(element, x);
  6166. });
  6167. };
  6168. const clone$2 = (original, isDeep) =>
  6169. SugarElement.fromDom(original.dom.cloneNode(isDeep));
  6170. const shallow$1 = (original) => clone$2(original, false);
  6171. const deep$1 = (original) => clone$2(original, true);
  6172. const shallowAs = (original, tag) => {
  6173. const nu = SugarElement.fromTag(tag);
  6174. const attributes = clone$4(original);
  6175. setAll$1(nu, attributes);
  6176. return nu;
  6177. };
  6178. const mutate = (original, tag) => {
  6179. const nu = shallowAs(original, tag);
  6180. after$4(original, nu);
  6181. const children = children$1(original);
  6182. append(nu, children);
  6183. remove$5(original);
  6184. return nu;
  6185. };
  6186. const TextWalker = (startNode, rootNode, isBoundary = never) => {
  6187. const walker = new DomTreeWalker(startNode, rootNode);
  6188. const walk = (direction) => {
  6189. let next;
  6190. do {
  6191. next = walker[direction]();
  6192. } while (next && !isText$a(next) && !isBoundary(next));
  6193. return Optional.from(next).filter(isText$a);
  6194. };
  6195. return {
  6196. current: () => Optional.from(walker.current()).filter(isText$a),
  6197. next: () => walk("next"),
  6198. prev: () => walk("prev"),
  6199. prev2: () => walk("prev2"),
  6200. };
  6201. };
  6202. const TextSeeker = (dom, isBoundary) => {
  6203. const isBlockBoundary = isBoundary
  6204. ? isBoundary
  6205. : (node) =>
  6206. dom.isBlock(node) || isBr$6(node) || isContentEditableFalse$b(node);
  6207. const walk = (node, offset, walker, process) => {
  6208. if (isText$a(node)) {
  6209. const newOffset = process(node, offset, node.data);
  6210. if (newOffset !== -1) {
  6211. return Optional.some({
  6212. container: node,
  6213. offset: newOffset,
  6214. });
  6215. }
  6216. }
  6217. return walker().bind((next) =>
  6218. walk(next.container, next.offset, walker, process)
  6219. );
  6220. };
  6221. const backwards = (node, offset, process, root) => {
  6222. const walker = TextWalker(
  6223. node,
  6224. root !== null && root !== void 0 ? root : dom.getRoot(),
  6225. isBlockBoundary
  6226. );
  6227. return walk(
  6228. node,
  6229. offset,
  6230. () =>
  6231. walker.prev().map((prev) => ({
  6232. container: prev,
  6233. offset: prev.length,
  6234. })),
  6235. process
  6236. ).getOrNull();
  6237. };
  6238. const forwards = (node, offset, process, root) => {
  6239. const walker = TextWalker(
  6240. node,
  6241. root !== null && root !== void 0 ? root : dom.getRoot(),
  6242. isBlockBoundary
  6243. );
  6244. return walk(
  6245. node,
  6246. offset,
  6247. () =>
  6248. walker.next().map((next) => ({
  6249. container: next,
  6250. offset: 0,
  6251. })),
  6252. process
  6253. ).getOrNull();
  6254. };
  6255. return {
  6256. backwards,
  6257. forwards,
  6258. };
  6259. };
  6260. const round$2 = Math.round;
  6261. const clone$1 = (rect) => {
  6262. if (!rect) {
  6263. return {
  6264. left: 0,
  6265. top: 0,
  6266. bottom: 0,
  6267. right: 0,
  6268. width: 0,
  6269. height: 0,
  6270. };
  6271. }
  6272. return {
  6273. left: round$2(rect.left),
  6274. top: round$2(rect.top),
  6275. bottom: round$2(rect.bottom),
  6276. right: round$2(rect.right),
  6277. width: round$2(rect.width),
  6278. height: round$2(rect.height),
  6279. };
  6280. };
  6281. const collapse = (rect, toStart) => {
  6282. rect = clone$1(rect);
  6283. if (toStart) {
  6284. rect.right = rect.left;
  6285. } else {
  6286. rect.left = rect.left + rect.width;
  6287. rect.right = rect.left;
  6288. }
  6289. rect.width = 0;
  6290. return rect;
  6291. };
  6292. const isEqual = (rect1, rect2) =>
  6293. rect1.left === rect2.left &&
  6294. rect1.top === rect2.top &&
  6295. rect1.bottom === rect2.bottom &&
  6296. rect1.right === rect2.right;
  6297. const isValidOverflow = (overflowY, rect1, rect2) =>
  6298. overflowY >= 0 && overflowY <= Math.min(rect1.height, rect2.height) / 2;
  6299. const isAbove$1 = (rect1, rect2) => {
  6300. const halfHeight = Math.min(rect2.height / 2, rect1.height / 2);
  6301. if (rect1.bottom - halfHeight < rect2.top) {
  6302. return true;
  6303. }
  6304. if (rect1.top > rect2.bottom) {
  6305. return false;
  6306. }
  6307. return isValidOverflow(rect2.top - rect1.bottom, rect1, rect2);
  6308. };
  6309. const isBelow$1 = (rect1, rect2) => {
  6310. if (rect1.top > rect2.bottom) {
  6311. return true;
  6312. }
  6313. if (rect1.bottom < rect2.top) {
  6314. return false;
  6315. }
  6316. return isValidOverflow(rect2.bottom - rect1.top, rect1, rect2);
  6317. };
  6318. const containsXY = (rect, clientX, clientY) =>
  6319. clientX >= rect.left &&
  6320. clientX <= rect.right &&
  6321. clientY >= rect.top &&
  6322. clientY <= rect.bottom;
  6323. const boundingClientRectFromRects = (rects) => {
  6324. return foldl(
  6325. rects,
  6326. (acc, rect) => {
  6327. return acc.fold(
  6328. () => Optional.some(rect),
  6329. (prevRect) => {
  6330. const left = Math.min(rect.left, prevRect.left);
  6331. const top = Math.min(rect.top, prevRect.top);
  6332. const right = Math.max(rect.right, prevRect.right);
  6333. const bottom = Math.max(rect.bottom, prevRect.bottom);
  6334. return Optional.some({
  6335. top,
  6336. right,
  6337. bottom,
  6338. left,
  6339. width: right - left,
  6340. height: bottom - top,
  6341. });
  6342. }
  6343. );
  6344. },
  6345. Optional.none()
  6346. );
  6347. };
  6348. const distanceToRectEdgeFromXY = (rect, x, y) => {
  6349. const cx = Math.max(Math.min(x, rect.left + rect.width), rect.left);
  6350. const cy = Math.max(Math.min(y, rect.top + rect.height), rect.top);
  6351. return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
  6352. };
  6353. const overlapY = (r1, r2) =>
  6354. Math.max(0, Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top));
  6355. const clamp$2 = (value, min, max) => Math.min(Math.max(value, min), max);
  6356. const getSelectedNode = (range) => {
  6357. const startContainer = range.startContainer,
  6358. startOffset = range.startOffset;
  6359. if (
  6360. startContainer === range.endContainer &&
  6361. startContainer.hasChildNodes() &&
  6362. range.endOffset === startOffset + 1
  6363. ) {
  6364. return startContainer.childNodes[startOffset];
  6365. }
  6366. return null;
  6367. };
  6368. const getNode$1 = (container, offset) => {
  6369. if (isElement$6(container) && container.hasChildNodes()) {
  6370. const childNodes = container.childNodes;
  6371. const safeOffset = clamp$2(offset, 0, childNodes.length - 1);
  6372. return childNodes[safeOffset];
  6373. } else {
  6374. return container;
  6375. }
  6376. };
  6377. const getNodeUnsafe = (container, offset) => {
  6378. if (offset < 0 && isElement$6(container) && container.hasChildNodes()) {
  6379. return undefined;
  6380. } else {
  6381. return getNode$1(container, offset);
  6382. }
  6383. };
  6384. const extendingChars = new RegExp(
  6385. "[\u0300-\u036f\u0483-\u0487\u0488-\u0489\u0591-\u05bd\u05bf\u05c1-\u05c2\u05c4-\u05c5\u05c7\u0610-\u061a" +
  6386. "\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7-\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0" +
  6387. "\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0902\u093a\u093c" +
  6388. "\u0941-\u0948\u094d\u0951-\u0957\u0962-\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2-\u09e3" +
  6389. "\u0a01-\u0a02\u0a3c\u0a41-\u0a42\u0a47-\u0a48\u0a4b-\u0a4d\u0a51\u0a70-\u0a71\u0a75\u0a81-\u0a82\u0abc" +
  6390. "\u0ac1-\u0ac5\u0ac7-\u0ac8\u0acd\u0ae2-\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57" +
  6391. "\u0b62-\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c00\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55-\u0c56" +
  6392. "\u0c62-\u0c63\u0c81\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc-\u0ccd\u0cd5-\u0cd6\u0ce2-\u0ce3\u0d01\u0d3e\u0d41-\u0d44" +
  6393. "\u0d4d\u0d57\u0d62-\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9" +
  6394. "\u0ebb-\u0ebc\u0ec8-\u0ecd\u0f18-\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86-\u0f87\u0f8d-\u0f97" +
  6395. "\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039-\u103a\u103d-\u103e\u1058-\u1059\u105e-\u1060\u1071-\u1074" +
  6396. "\u1082\u1085-\u1086\u108d\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752-\u1753\u1772-\u1773\u17b4-\u17b5" +
  6397. "\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927-\u1928\u1932\u1939-\u193b\u1a17-\u1a18" +
  6398. "\u1a1b\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1ab0-\u1abd\u1ABE\u1b00-\u1b03\u1b34" +
  6399. "\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80-\u1b81\u1ba2-\u1ba5\u1ba8-\u1ba9\u1bab-\u1bad\u1be6\u1be8-\u1be9" +
  6400. "\u1bed\u1bef-\u1bf1\u1c2c-\u1c33\u1c36-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1cf4\u1cf8-\u1cf9" +
  6401. "\u1dc0-\u1df5\u1dfc-\u1dff\u200c-\u200d\u20d0-\u20dc\u20DD-\u20E0\u20e1\u20E2-\u20E4\u20e5-\u20f0\u2cef-\u2cf1" +
  6402. "\u2d7f\u2de0-\u2dff\u302a-\u302d\u302e-\u302f\u3099-\u309a\ua66f\uA670-\uA672\ua674-\ua67d\ua69e-\ua69f\ua6f0-\ua6f1" +
  6403. "\ua802\ua806\ua80b\ua825-\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc" +
  6404. "\ua9e5\uaa29-\uaa2e\uaa31-\uaa32\uaa35-\uaa36\uaa43\uaa4c\uaa7c\uaab0\uaab2-\uaab4\uaab7-\uaab8\uaabe-\uaabf\uaac1" +
  6405. "\uaaec-\uaaed\uaaf6\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\uff9e-\uff9f]"
  6406. );
  6407. const isExtendingChar = (ch) =>
  6408. isString(ch) && ch.charCodeAt(0) >= 768 && extendingChars.test(ch);
  6409. const or = (...args) => {
  6410. return (x) => {
  6411. for (let i = 0; i < args.length; i++) {
  6412. if (args[i](x)) {
  6413. return true;
  6414. }
  6415. }
  6416. return false;
  6417. };
  6418. };
  6419. const and = (...args) => {
  6420. return (x) => {
  6421. for (let i = 0; i < args.length; i++) {
  6422. if (!args[i](x)) {
  6423. return false;
  6424. }
  6425. }
  6426. return true;
  6427. };
  6428. };
  6429. const isElement$4 = isElement$6;
  6430. const isCaretCandidate$2 = isCaretCandidate$3;
  6431. const isBlock$1 = matchStyleValues("display", "block table");
  6432. const isFloated = matchStyleValues("float", "left right");
  6433. const isValidElementCaretCandidate = and(
  6434. isElement$4,
  6435. isCaretCandidate$2,
  6436. not(isFloated)
  6437. );
  6438. const isNotPre = not(
  6439. matchStyleValues("white-space", "pre pre-line pre-wrap")
  6440. );
  6441. const isText$7 = isText$a;
  6442. const isBr$3 = isBr$6;
  6443. const nodeIndex$1 = DOMUtils.nodeIndex;
  6444. const resolveIndex$1 = getNodeUnsafe;
  6445. const createRange$1 = (doc) =>
  6446. doc ? doc.createRange() : DOMUtils.DOM.createRng();
  6447. const isWhiteSpace$1 = (chr) => isString(chr) && /[\r\n\t ]/.test(chr);
  6448. const isRange = (rng) => !!rng.setStart && !!rng.setEnd;
  6449. const isHiddenWhiteSpaceRange = (range) => {
  6450. const container = range.startContainer;
  6451. const offset = range.startOffset;
  6452. if (
  6453. isWhiteSpace$1(range.toString()) &&
  6454. isNotPre(container.parentNode) &&
  6455. isText$a(container)
  6456. ) {
  6457. const text = container.data;
  6458. if (
  6459. isWhiteSpace$1(text[offset - 1]) ||
  6460. isWhiteSpace$1(text[offset + 1])
  6461. ) {
  6462. return true;
  6463. }
  6464. }
  6465. return false;
  6466. };
  6467. const getBrClientRect = (brNode) => {
  6468. const doc = brNode.ownerDocument;
  6469. const rng = createRange$1(doc);
  6470. const nbsp$1 = doc.createTextNode(nbsp);
  6471. const parentNode = brNode.parentNode;
  6472. parentNode.insertBefore(nbsp$1, brNode);
  6473. rng.setStart(nbsp$1, 0);
  6474. rng.setEnd(nbsp$1, 1);
  6475. const clientRect = clone$1(rng.getBoundingClientRect());
  6476. parentNode.removeChild(nbsp$1);
  6477. return clientRect;
  6478. };
  6479. const getBoundingClientRectWebKitText = (rng) => {
  6480. const sc = rng.startContainer;
  6481. const ec = rng.endContainer;
  6482. const so = rng.startOffset;
  6483. const eo = rng.endOffset;
  6484. if (sc === ec && isText$a(ec) && so === 0 && eo === 1) {
  6485. const newRng = rng.cloneRange();
  6486. newRng.setEndAfter(ec);
  6487. return getBoundingClientRect$1(newRng);
  6488. } else {
  6489. return null;
  6490. }
  6491. };
  6492. const isZeroRect = (r) =>
  6493. r.left === 0 && r.right === 0 && r.top === 0 && r.bottom === 0;
  6494. const getBoundingClientRect$1 = (item) => {
  6495. var _a;
  6496. let clientRect;
  6497. const clientRects = item.getClientRects();
  6498. if (clientRects.length > 0) {
  6499. clientRect = clone$1(clientRects[0]);
  6500. } else {
  6501. clientRect = clone$1(item.getBoundingClientRect());
  6502. }
  6503. if (!isRange(item) && isBr$3(item) && isZeroRect(clientRect)) {
  6504. return getBrClientRect(item);
  6505. }
  6506. if (isZeroRect(clientRect) && isRange(item)) {
  6507. return (_a = getBoundingClientRectWebKitText(item)) !== null &&
  6508. _a !== void 0
  6509. ? _a
  6510. : clientRect;
  6511. }
  6512. return clientRect;
  6513. };
  6514. const collapseAndInflateWidth = (clientRect, toStart) => {
  6515. const newClientRect = collapse(clientRect, toStart);
  6516. newClientRect.width = 1;
  6517. newClientRect.right = newClientRect.left + 1;
  6518. return newClientRect;
  6519. };
  6520. const getCaretPositionClientRects = (caretPosition) => {
  6521. const clientRects = [];
  6522. const addUniqueAndValidRect = (clientRect) => {
  6523. if (clientRect.height === 0) {
  6524. return;
  6525. }
  6526. if (clientRects.length > 0) {
  6527. if (isEqual(clientRect, clientRects[clientRects.length - 1])) {
  6528. return;
  6529. }
  6530. }
  6531. clientRects.push(clientRect);
  6532. };
  6533. const addCharacterOffset = (container, offset) => {
  6534. const range = createRange$1(container.ownerDocument);
  6535. if (offset < container.data.length) {
  6536. if (isExtendingChar(container.data[offset])) {
  6537. return;
  6538. }
  6539. if (isExtendingChar(container.data[offset - 1])) {
  6540. range.setStart(container, offset);
  6541. range.setEnd(container, offset + 1);
  6542. if (!isHiddenWhiteSpaceRange(range)) {
  6543. addUniqueAndValidRect(
  6544. collapseAndInflateWidth(getBoundingClientRect$1(range), false)
  6545. );
  6546. return;
  6547. }
  6548. }
  6549. }
  6550. if (offset > 0) {
  6551. range.setStart(container, offset - 1);
  6552. range.setEnd(container, offset);
  6553. if (!isHiddenWhiteSpaceRange(range)) {
  6554. addUniqueAndValidRect(
  6555. collapseAndInflateWidth(getBoundingClientRect$1(range), false)
  6556. );
  6557. }
  6558. }
  6559. if (offset < container.data.length) {
  6560. range.setStart(container, offset);
  6561. range.setEnd(container, offset + 1);
  6562. if (!isHiddenWhiteSpaceRange(range)) {
  6563. addUniqueAndValidRect(
  6564. collapseAndInflateWidth(getBoundingClientRect$1(range), true)
  6565. );
  6566. }
  6567. }
  6568. };
  6569. const container = caretPosition.container();
  6570. const offset = caretPosition.offset();
  6571. if (isText$7(container)) {
  6572. addCharacterOffset(container, offset);
  6573. return clientRects;
  6574. }
  6575. if (isElement$4(container)) {
  6576. if (caretPosition.isAtEnd()) {
  6577. const node = resolveIndex$1(container, offset);
  6578. if (isText$7(node)) {
  6579. addCharacterOffset(node, node.data.length);
  6580. }
  6581. if (isValidElementCaretCandidate(node) && !isBr$3(node)) {
  6582. addUniqueAndValidRect(
  6583. collapseAndInflateWidth(getBoundingClientRect$1(node), false)
  6584. );
  6585. }
  6586. } else {
  6587. const node = resolveIndex$1(container, offset);
  6588. if (isText$7(node)) {
  6589. addCharacterOffset(node, 0);
  6590. }
  6591. if (isValidElementCaretCandidate(node) && caretPosition.isAtEnd()) {
  6592. addUniqueAndValidRect(
  6593. collapseAndInflateWidth(getBoundingClientRect$1(node), false)
  6594. );
  6595. return clientRects;
  6596. }
  6597. const beforeNode = resolveIndex$1(
  6598. caretPosition.container(),
  6599. caretPosition.offset() - 1
  6600. );
  6601. if (isValidElementCaretCandidate(beforeNode) && !isBr$3(beforeNode)) {
  6602. if (
  6603. isBlock$1(beforeNode) ||
  6604. isBlock$1(node) ||
  6605. !isValidElementCaretCandidate(node)
  6606. ) {
  6607. addUniqueAndValidRect(
  6608. collapseAndInflateWidth(
  6609. getBoundingClientRect$1(beforeNode),
  6610. false
  6611. )
  6612. );
  6613. }
  6614. }
  6615. if (isValidElementCaretCandidate(node)) {
  6616. addUniqueAndValidRect(
  6617. collapseAndInflateWidth(getBoundingClientRect$1(node), true)
  6618. );
  6619. }
  6620. }
  6621. }
  6622. return clientRects;
  6623. };
  6624. const CaretPosition = (container, offset, clientRects) => {
  6625. const isAtStart = () => {
  6626. if (isText$7(container)) {
  6627. return offset === 0;
  6628. }
  6629. return offset === 0;
  6630. };
  6631. const isAtEnd = () => {
  6632. if (isText$7(container)) {
  6633. return offset >= container.data.length;
  6634. }
  6635. return offset >= container.childNodes.length;
  6636. };
  6637. const toRange = () => {
  6638. const range = createRange$1(container.ownerDocument);
  6639. range.setStart(container, offset);
  6640. range.setEnd(container, offset);
  6641. return range;
  6642. };
  6643. const getClientRects = () => {
  6644. if (!clientRects) {
  6645. clientRects = getCaretPositionClientRects(
  6646. CaretPosition(container, offset)
  6647. );
  6648. }
  6649. return clientRects;
  6650. };
  6651. const isVisible = () => getClientRects().length > 0;
  6652. const isEqual = (caretPosition) =>
  6653. caretPosition &&
  6654. container === caretPosition.container() &&
  6655. offset === caretPosition.offset();
  6656. const getNode = (before) =>
  6657. resolveIndex$1(container, before ? offset - 1 : offset);
  6658. return {
  6659. container: constant(container),
  6660. offset: constant(offset),
  6661. toRange,
  6662. getClientRects,
  6663. isVisible,
  6664. isAtStart,
  6665. isAtEnd,
  6666. isEqual,
  6667. getNode,
  6668. };
  6669. };
  6670. CaretPosition.fromRangeStart = (range) =>
  6671. CaretPosition(range.startContainer, range.startOffset);
  6672. CaretPosition.fromRangeEnd = (range) =>
  6673. CaretPosition(range.endContainer, range.endOffset);
  6674. CaretPosition.after = (node) =>
  6675. CaretPosition(node.parentNode, nodeIndex$1(node) + 1);
  6676. CaretPosition.before = (node) =>
  6677. CaretPosition(node.parentNode, nodeIndex$1(node));
  6678. CaretPosition.isAbove = (pos1, pos2) =>
  6679. lift2(
  6680. head(pos2.getClientRects()),
  6681. last$3(pos1.getClientRects()),
  6682. isAbove$1
  6683. ).getOr(false);
  6684. CaretPosition.isBelow = (pos1, pos2) =>
  6685. lift2(
  6686. last$3(pos2.getClientRects()),
  6687. head(pos1.getClientRects()),
  6688. isBelow$1
  6689. ).getOr(false);
  6690. CaretPosition.isAtStart = (pos) => (pos ? pos.isAtStart() : false);
  6691. CaretPosition.isAtEnd = (pos) => (pos ? pos.isAtEnd() : false);
  6692. CaretPosition.isTextPosition = (pos) =>
  6693. pos ? isText$a(pos.container()) : false;
  6694. CaretPosition.isElementPosition = (pos) => !CaretPosition.isTextPosition(pos);
  6695. const trimEmptyTextNode$1 = (dom, node) => {
  6696. if (isText$a(node) && node.data.length === 0) {
  6697. dom.remove(node);
  6698. }
  6699. };
  6700. const insertNode = (dom, rng, node) => {
  6701. rng.insertNode(node);
  6702. trimEmptyTextNode$1(dom, node.previousSibling);
  6703. trimEmptyTextNode$1(dom, node.nextSibling);
  6704. };
  6705. const insertFragment = (dom, rng, frag) => {
  6706. const firstChild = Optional.from(frag.firstChild);
  6707. const lastChild = Optional.from(frag.lastChild);
  6708. rng.insertNode(frag);
  6709. firstChild.each((child) => trimEmptyTextNode$1(dom, child.previousSibling));
  6710. lastChild.each((child) => trimEmptyTextNode$1(dom, child.nextSibling));
  6711. };
  6712. const rangeInsertNode = (dom, rng, node) => {
  6713. if (isDocumentFragment(node)) {
  6714. insertFragment(dom, rng, node);
  6715. } else {
  6716. insertNode(dom, rng, node);
  6717. }
  6718. };
  6719. const isText$6 = isText$a;
  6720. const isBogus = isBogus$2;
  6721. const nodeIndex = DOMUtils.nodeIndex;
  6722. const normalizedParent = (node) => {
  6723. const parentNode = node.parentNode;
  6724. if (isBogus(parentNode)) {
  6725. return normalizedParent(parentNode);
  6726. }
  6727. return parentNode;
  6728. };
  6729. const getChildNodes = (node) => {
  6730. if (!node) {
  6731. return [];
  6732. }
  6733. return reduce(
  6734. node.childNodes,
  6735. (result, node) => {
  6736. if (isBogus(node) && node.nodeName !== "BR") {
  6737. result = result.concat(getChildNodes(node));
  6738. } else {
  6739. result.push(node);
  6740. }
  6741. return result;
  6742. },
  6743. []
  6744. );
  6745. };
  6746. const normalizedTextOffset = (node, offset) => {
  6747. let tempNode = node;
  6748. while ((tempNode = tempNode.previousSibling)) {
  6749. if (!isText$6(tempNode)) {
  6750. break;
  6751. }
  6752. offset += tempNode.data.length;
  6753. }
  6754. return offset;
  6755. };
  6756. const equal = (a) => (b) => a === b;
  6757. const normalizedNodeIndex = (node) => {
  6758. let nodes, index;
  6759. nodes = getChildNodes(normalizedParent(node));
  6760. index = findIndex$1(nodes, equal(node), node);
  6761. nodes = nodes.slice(0, index + 1);
  6762. const numTextFragments = reduce(
  6763. nodes,
  6764. (result, node, i) => {
  6765. if (isText$6(node) && isText$6(nodes[i - 1])) {
  6766. result++;
  6767. }
  6768. return result;
  6769. },
  6770. 0
  6771. );
  6772. nodes = filter$3(nodes, matchNodeNames([node.nodeName]));
  6773. index = findIndex$1(nodes, equal(node), node);
  6774. return index - numTextFragments;
  6775. };
  6776. const createPathItem = (node) => {
  6777. const name = isText$6(node) ? "text()" : node.nodeName.toLowerCase();
  6778. return name + "[" + normalizedNodeIndex(node) + "]";
  6779. };
  6780. const parentsUntil$1 = (root, node, predicate) => {
  6781. const parents = [];
  6782. for (
  6783. let tempNode = node.parentNode;
  6784. tempNode && tempNode !== root;
  6785. tempNode = tempNode.parentNode
  6786. ) {
  6787. if (predicate && predicate(tempNode)) {
  6788. break;
  6789. }
  6790. parents.push(tempNode);
  6791. }
  6792. return parents;
  6793. };
  6794. const create$b = (root, caretPosition) => {
  6795. let path = [];
  6796. let container = caretPosition.container();
  6797. let offset = caretPosition.offset();
  6798. let outputOffset;
  6799. if (isText$6(container)) {
  6800. outputOffset = normalizedTextOffset(container, offset);
  6801. } else {
  6802. const childNodes = container.childNodes;
  6803. if (offset >= childNodes.length) {
  6804. outputOffset = "after";
  6805. offset = childNodes.length - 1;
  6806. } else {
  6807. outputOffset = "before";
  6808. }
  6809. container = childNodes[offset];
  6810. }
  6811. path.push(createPathItem(container));
  6812. let parents = parentsUntil$1(root, container);
  6813. parents = filter$3(parents, not(isBogus$2));
  6814. path = path.concat(
  6815. map$1(parents, (node) => {
  6816. return createPathItem(node);
  6817. })
  6818. );
  6819. return path.reverse().join("/") + "," + outputOffset;
  6820. };
  6821. const resolvePathItem = (node, name, index) => {
  6822. let nodes = getChildNodes(node);
  6823. nodes = filter$3(nodes, (node, index) => {
  6824. return !isText$6(node) || !isText$6(nodes[index - 1]);
  6825. });
  6826. nodes = filter$3(nodes, matchNodeNames([name]));
  6827. return nodes[index];
  6828. };
  6829. const findTextPosition = (container, offset) => {
  6830. let node = container;
  6831. let targetOffset = 0;
  6832. while (isText$6(node)) {
  6833. const dataLen = node.data.length;
  6834. if (offset >= targetOffset && offset <= targetOffset + dataLen) {
  6835. container = node;
  6836. offset = offset - targetOffset;
  6837. break;
  6838. }
  6839. if (!isText$6(node.nextSibling)) {
  6840. container = node;
  6841. offset = dataLen;
  6842. break;
  6843. }
  6844. targetOffset += dataLen;
  6845. node = node.nextSibling;
  6846. }
  6847. if (isText$6(container) && offset > container.data.length) {
  6848. offset = container.data.length;
  6849. }
  6850. return CaretPosition(container, offset);
  6851. };
  6852. const resolve$1 = (root, path) => {
  6853. if (!path) {
  6854. return null;
  6855. }
  6856. const parts = path.split(",");
  6857. const paths = parts[0].split("/");
  6858. const offset = parts.length > 1 ? parts[1] : "before";
  6859. const container = reduce(
  6860. paths,
  6861. (result, value) => {
  6862. const match = /([\w\-\(\)]+)\[([0-9]+)\]/.exec(value);
  6863. if (!match) {
  6864. return null;
  6865. }
  6866. if (match[1] === "text()") {
  6867. match[1] = "#text";
  6868. }
  6869. return resolvePathItem(result, match[1], parseInt(match[2], 10));
  6870. },
  6871. root
  6872. );
  6873. if (!container) {
  6874. return null;
  6875. }
  6876. if (!isText$6(container) && container.parentNode) {
  6877. let nodeOffset;
  6878. if (offset === "after") {
  6879. nodeOffset = nodeIndex(container) + 1;
  6880. } else {
  6881. nodeOffset = nodeIndex(container);
  6882. }
  6883. return CaretPosition(container.parentNode, nodeOffset);
  6884. }
  6885. return findTextPosition(container, parseInt(offset, 10));
  6886. };
  6887. const isContentEditableFalse$9 = isContentEditableFalse$b;
  6888. const getNormalizedTextOffset$1 = (trim, container, offset) => {
  6889. let trimmedOffset = trim(container.data.slice(0, offset)).length;
  6890. for (
  6891. let node = container.previousSibling;
  6892. node && isText$a(node);
  6893. node = node.previousSibling
  6894. ) {
  6895. trimmedOffset += trim(node.data).length;
  6896. }
  6897. return trimmedOffset;
  6898. };
  6899. const getPoint = (dom, trim, normalized, rng, start) => {
  6900. const container = start ? rng.startContainer : rng.endContainer;
  6901. let offset = start ? rng.startOffset : rng.endOffset;
  6902. const point = [];
  6903. const root = dom.getRoot();
  6904. if (isText$a(container)) {
  6905. point.push(
  6906. normalized ? getNormalizedTextOffset$1(trim, container, offset) : offset
  6907. );
  6908. } else {
  6909. let after = 0;
  6910. const childNodes = container.childNodes;
  6911. if (offset >= childNodes.length && childNodes.length) {
  6912. after = 1;
  6913. offset = Math.max(0, childNodes.length - 1);
  6914. }
  6915. point.push(dom.nodeIndex(childNodes[offset], normalized) + after);
  6916. }
  6917. for (let node = container; node && node !== root; node = node.parentNode) {
  6918. point.push(dom.nodeIndex(node, normalized));
  6919. }
  6920. return point;
  6921. };
  6922. const getLocation = (trim, selection, normalized, rng) => {
  6923. const dom = selection.dom;
  6924. const start = getPoint(dom, trim, normalized, rng, true);
  6925. const forward = selection.isForward();
  6926. const fakeCaret = isRangeInCaretContainerBlock(rng)
  6927. ? { isFakeCaret: true }
  6928. : {};
  6929. if (!selection.isCollapsed()) {
  6930. const end = getPoint(dom, trim, normalized, rng, false);
  6931. return {
  6932. start,
  6933. end,
  6934. forward,
  6935. ...fakeCaret,
  6936. };
  6937. } else {
  6938. return {
  6939. start,
  6940. forward,
  6941. ...fakeCaret,
  6942. };
  6943. }
  6944. };
  6945. const findIndex = (dom, name, element) => {
  6946. let count = 0;
  6947. Tools.each(dom.select(name), (node) => {
  6948. if (node.getAttribute("data-mce-bogus") === "all") {
  6949. return;
  6950. } else if (node === element) {
  6951. return false;
  6952. } else {
  6953. count++;
  6954. return;
  6955. }
  6956. });
  6957. return count;
  6958. };
  6959. const moveEndPoint$1 = (rng, start) => {
  6960. let container = start ? rng.startContainer : rng.endContainer;
  6961. let offset = start ? rng.startOffset : rng.endOffset;
  6962. if (isElement$6(container) && container.nodeName === "TR") {
  6963. const childNodes = container.childNodes;
  6964. container =
  6965. childNodes[
  6966. Math.min(start ? offset : offset - 1, childNodes.length - 1)
  6967. ];
  6968. if (container) {
  6969. offset = start ? 0 : container.childNodes.length;
  6970. if (start) {
  6971. rng.setStart(container, offset);
  6972. } else {
  6973. rng.setEnd(container, offset);
  6974. }
  6975. }
  6976. }
  6977. };
  6978. const normalizeTableCellSelection = (rng) => {
  6979. moveEndPoint$1(rng, true);
  6980. moveEndPoint$1(rng, false);
  6981. return rng;
  6982. };
  6983. const findSibling = (node, offset) => {
  6984. if (isElement$6(node)) {
  6985. node = getNode$1(node, offset);
  6986. if (isContentEditableFalse$9(node)) {
  6987. return node;
  6988. }
  6989. }
  6990. if (isCaretContainer$2(node)) {
  6991. if (isText$a(node) && isCaretContainerBlock$1(node)) {
  6992. node = node.parentNode;
  6993. }
  6994. let sibling = node.previousSibling;
  6995. if (isContentEditableFalse$9(sibling)) {
  6996. return sibling;
  6997. }
  6998. sibling = node.nextSibling;
  6999. if (isContentEditableFalse$9(sibling)) {
  7000. return sibling;
  7001. }
  7002. }
  7003. return undefined;
  7004. };
  7005. const findAdjacentContentEditableFalseElm = (rng) => {
  7006. return (
  7007. findSibling(rng.startContainer, rng.startOffset) ||
  7008. findSibling(rng.endContainer, rng.endOffset)
  7009. );
  7010. };
  7011. const getOffsetBookmark = (trim, normalized, selection) => {
  7012. const element = selection.getNode();
  7013. const rng = selection.getRng();
  7014. if (element.nodeName === "IMG" || isContentEditableFalse$9(element)) {
  7015. const name = element.nodeName;
  7016. return {
  7017. name,
  7018. index: findIndex(selection.dom, name, element),
  7019. };
  7020. }
  7021. const sibling = findAdjacentContentEditableFalseElm(rng);
  7022. if (sibling) {
  7023. const name = sibling.tagName;
  7024. return {
  7025. name,
  7026. index: findIndex(selection.dom, name, sibling),
  7027. };
  7028. }
  7029. return getLocation(trim, selection, normalized, rng);
  7030. };
  7031. const getCaretBookmark = (selection) => {
  7032. const rng = selection.getRng();
  7033. return {
  7034. start: create$b(
  7035. selection.dom.getRoot(),
  7036. CaretPosition.fromRangeStart(rng)
  7037. ),
  7038. end: create$b(selection.dom.getRoot(), CaretPosition.fromRangeEnd(rng)),
  7039. forward: selection.isForward(),
  7040. };
  7041. };
  7042. const getRangeBookmark = (selection) => {
  7043. return {
  7044. rng: selection.getRng(),
  7045. forward: selection.isForward(),
  7046. };
  7047. };
  7048. const createBookmarkSpan = (dom, id, filled) => {
  7049. const args = {
  7050. "data-mce-type": "bookmark",
  7051. id,
  7052. style: "overflow:hidden;line-height:0px",
  7053. };
  7054. return filled
  7055. ? dom.create("span", args, "&#xFEFF;")
  7056. : dom.create("span", args);
  7057. };
  7058. const getPersistentBookmark = (selection, filled) => {
  7059. const dom = selection.dom;
  7060. let rng = selection.getRng();
  7061. const id = dom.uniqueId();
  7062. const collapsed = selection.isCollapsed();
  7063. const element = selection.getNode();
  7064. const name = element.nodeName;
  7065. const forward = selection.isForward();
  7066. if (name === "IMG") {
  7067. return {
  7068. name,
  7069. index: findIndex(dom, name, element),
  7070. };
  7071. }
  7072. const rng2 = normalizeTableCellSelection(rng.cloneRange());
  7073. if (!collapsed) {
  7074. rng2.collapse(false);
  7075. const endBookmarkNode = createBookmarkSpan(dom, id + "_end", filled);
  7076. rangeInsertNode(dom, rng2, endBookmarkNode);
  7077. }
  7078. rng = normalizeTableCellSelection(rng);
  7079. rng.collapse(true);
  7080. const startBookmarkNode = createBookmarkSpan(dom, id + "_start", filled);
  7081. rangeInsertNode(dom, rng, startBookmarkNode);
  7082. selection.moveToBookmark({
  7083. id,
  7084. keep: true,
  7085. forward,
  7086. });
  7087. return {
  7088. id,
  7089. forward,
  7090. };
  7091. };
  7092. const getBookmark$2 = (selection, type, normalized = false) => {
  7093. if (type === 2) {
  7094. return getOffsetBookmark(trim$1, normalized, selection);
  7095. } else if (type === 3) {
  7096. return getCaretBookmark(selection);
  7097. } else if (type) {
  7098. return getRangeBookmark(selection);
  7099. } else {
  7100. return getPersistentBookmark(selection, false);
  7101. }
  7102. };
  7103. const getUndoBookmark = curry(getOffsetBookmark, identity, true);
  7104. const value$1 = (value) => {
  7105. const applyHelper = (fn) => fn(value);
  7106. const constHelper = constant(value);
  7107. const outputHelper = () => output;
  7108. const output = {
  7109. tag: true,
  7110. inner: value,
  7111. fold: (_onError, onValue) => onValue(value),
  7112. isValue: always,
  7113. isError: never,
  7114. map: (mapper) => Result.value(mapper(value)),
  7115. mapError: outputHelper,
  7116. bind: applyHelper,
  7117. exists: applyHelper,
  7118. forall: applyHelper,
  7119. getOr: constHelper,
  7120. or: outputHelper,
  7121. getOrThunk: constHelper,
  7122. orThunk: outputHelper,
  7123. getOrDie: constHelper,
  7124. each: (fn) => {
  7125. fn(value);
  7126. },
  7127. toOptional: () => Optional.some(value),
  7128. };
  7129. return output;
  7130. };
  7131. const error = (error) => {
  7132. const outputHelper = () => output;
  7133. const output = {
  7134. tag: false,
  7135. inner: error,
  7136. fold: (onError, _onValue) => onError(error),
  7137. isValue: never,
  7138. isError: always,
  7139. map: outputHelper,
  7140. mapError: (mapper) => Result.error(mapper(error)),
  7141. bind: outputHelper,
  7142. exists: never,
  7143. forall: always,
  7144. getOr: identity,
  7145. or: identity,
  7146. getOrThunk: apply$1,
  7147. orThunk: apply$1,
  7148. getOrDie: die(String(error)),
  7149. each: noop,
  7150. toOptional: Optional.none,
  7151. };
  7152. return output;
  7153. };
  7154. const fromOption = (optional, err) =>
  7155. optional.fold(() => error(err), value$1);
  7156. const Result = {
  7157. value: value$1,
  7158. error,
  7159. fromOption,
  7160. };
  7161. const generate = (cases) => {
  7162. if (!isArray$1(cases)) {
  7163. throw new Error("cases must be an array");
  7164. }
  7165. if (cases.length === 0) {
  7166. throw new Error("there must be at least one case");
  7167. }
  7168. const constructors = [];
  7169. const adt = {};
  7170. each$e(cases, (acase, count) => {
  7171. const keys$1 = keys(acase);
  7172. if (keys$1.length !== 1) {
  7173. throw new Error("one and only one name per case");
  7174. }
  7175. const key = keys$1[0];
  7176. const value = acase[key];
  7177. if (adt[key] !== undefined) {
  7178. throw new Error("duplicate key detected:" + key);
  7179. } else if (key === "cata") {
  7180. throw new Error("cannot have a case named cata (sorry)");
  7181. } else if (!isArray$1(value)) {
  7182. throw new Error("case arguments must be an array");
  7183. }
  7184. constructors.push(key);
  7185. adt[key] = (...args) => {
  7186. const argLength = args.length;
  7187. if (argLength !== value.length) {
  7188. throw new Error(
  7189. "Wrong number of arguments to case " +
  7190. key +
  7191. ". Expected " +
  7192. value.length +
  7193. " (" +
  7194. value +
  7195. "), got " +
  7196. argLength
  7197. );
  7198. }
  7199. const match = (branches) => {
  7200. const branchKeys = keys(branches);
  7201. if (constructors.length !== branchKeys.length) {
  7202. throw new Error(
  7203. "Wrong number of arguments to match. Expected: " +
  7204. constructors.join(",") +
  7205. "\nActual: " +
  7206. branchKeys.join(",")
  7207. );
  7208. }
  7209. const allReqd = forall(constructors, (reqKey) => {
  7210. return contains$2(branchKeys, reqKey);
  7211. });
  7212. if (!allReqd) {
  7213. throw new Error(
  7214. "Not all branches were specified when using match. Specified: " +
  7215. branchKeys.join(", ") +
  7216. "\nRequired: " +
  7217. constructors.join(", ")
  7218. );
  7219. }
  7220. return branches[key].apply(null, args);
  7221. };
  7222. return {
  7223. fold: (...foldArgs) => {
  7224. if (foldArgs.length !== cases.length) {
  7225. throw new Error(
  7226. "Wrong number of arguments to fold. Expected " +
  7227. cases.length +
  7228. ", got " +
  7229. foldArgs.length
  7230. );
  7231. }
  7232. const target = foldArgs[count];
  7233. return target.apply(null, args);
  7234. },
  7235. match,
  7236. log: (label) => {
  7237. console.log(label, {
  7238. constructors,
  7239. constructor: key,
  7240. params: args,
  7241. });
  7242. },
  7243. };
  7244. };
  7245. });
  7246. return adt;
  7247. };
  7248. const Adt = { generate };
  7249. Adt.generate([
  7250. {
  7251. bothErrors: ["error1", "error2"],
  7252. },
  7253. {
  7254. firstError: ["error1", "value2"],
  7255. },
  7256. {
  7257. secondError: ["value1", "error2"],
  7258. },
  7259. {
  7260. bothValues: ["value1", "value2"],
  7261. },
  7262. ]);
  7263. const partition$1 = (results) => {
  7264. const errors = [];
  7265. const values = [];
  7266. each$e(results, (result) => {
  7267. result.fold(
  7268. (err) => {
  7269. errors.push(err);
  7270. },
  7271. (value) => {
  7272. values.push(value);
  7273. }
  7274. );
  7275. });
  7276. return {
  7277. errors,
  7278. values,
  7279. };
  7280. };
  7281. const isInlinePattern = (pattern) =>
  7282. pattern.type === "inline-command" || pattern.type === "inline-format";
  7283. const isBlockPattern = (pattern) =>
  7284. pattern.type === "block-command" || pattern.type === "block-format";
  7285. const normalizePattern = (pattern) => {
  7286. const err = (message) =>
  7287. Result.error({
  7288. message,
  7289. pattern,
  7290. });
  7291. const formatOrCmd = (name, onFormat, onCommand) => {
  7292. if (pattern.format !== undefined) {
  7293. let formats;
  7294. if (isArray$1(pattern.format)) {
  7295. if (!forall(pattern.format, isString)) {
  7296. return err(
  7297. name + " pattern has non-string items in the `format` array"
  7298. );
  7299. }
  7300. formats = pattern.format;
  7301. } else if (isString(pattern.format)) {
  7302. formats = [pattern.format];
  7303. } else {
  7304. return err(name + " pattern has non-string `format` parameter");
  7305. }
  7306. return Result.value(onFormat(formats));
  7307. } else if (pattern.cmd !== undefined) {
  7308. if (!isString(pattern.cmd)) {
  7309. return err(name + " pattern has non-string `cmd` parameter");
  7310. }
  7311. return Result.value(onCommand(pattern.cmd, pattern.value));
  7312. } else {
  7313. return err(
  7314. name + " pattern is missing both `format` and `cmd` parameters"
  7315. );
  7316. }
  7317. };
  7318. if (!isObject(pattern)) {
  7319. return err("Raw pattern is not an object");
  7320. }
  7321. if (!isString(pattern.start)) {
  7322. return err("Raw pattern is missing `start` parameter");
  7323. }
  7324. if (pattern.end !== undefined) {
  7325. if (!isString(pattern.end)) {
  7326. return err("Inline pattern has non-string `end` parameter");
  7327. }
  7328. if (pattern.start.length === 0 && pattern.end.length === 0) {
  7329. return err("Inline pattern has empty `start` and `end` parameters");
  7330. }
  7331. let start = pattern.start;
  7332. let end = pattern.end;
  7333. if (end.length === 0) {
  7334. end = start;
  7335. start = "";
  7336. }
  7337. return formatOrCmd(
  7338. "Inline",
  7339. (format) => ({
  7340. type: "inline-format",
  7341. start,
  7342. end,
  7343. format,
  7344. }),
  7345. (cmd, value) => ({
  7346. type: "inline-command",
  7347. start,
  7348. end,
  7349. cmd,
  7350. value,
  7351. })
  7352. );
  7353. } else if (pattern.replacement !== undefined) {
  7354. if (!isString(pattern.replacement)) {
  7355. return err(
  7356. "Replacement pattern has non-string `replacement` parameter"
  7357. );
  7358. }
  7359. if (pattern.start.length === 0) {
  7360. return err("Replacement pattern has empty `start` parameter");
  7361. }
  7362. return Result.value({
  7363. type: "inline-command",
  7364. start: "",
  7365. end: pattern.start,
  7366. cmd: "mceInsertContent",
  7367. value: pattern.replacement,
  7368. });
  7369. } else {
  7370. if (pattern.start.length === 0) {
  7371. return err("Block pattern has empty `start` parameter");
  7372. }
  7373. return formatOrCmd(
  7374. "Block",
  7375. (formats) => ({
  7376. type: "block-format",
  7377. start: pattern.start,
  7378. format: formats[0],
  7379. }),
  7380. (command, commandValue) => ({
  7381. type: "block-command",
  7382. start: pattern.start,
  7383. cmd: command,
  7384. value: commandValue,
  7385. })
  7386. );
  7387. }
  7388. };
  7389. const getBlockPatterns = (patterns) => filter$5(patterns, isBlockPattern);
  7390. const getInlinePatterns = (patterns) => filter$5(patterns, isInlinePattern);
  7391. const createPatternSet = (patterns, dynamicPatternsLookup) => ({
  7392. inlinePatterns: getInlinePatterns(patterns),
  7393. blockPatterns: getBlockPatterns(patterns),
  7394. dynamicPatternsLookup,
  7395. });
  7396. const fromRawPatterns = (patterns) => {
  7397. const normalized = partition$1(map$3(patterns, normalizePattern));
  7398. each$e(normalized.errors, (err) => console.error(err.message, err.pattern));
  7399. return normalized.values;
  7400. };
  7401. const fromRawPatternsLookup = (lookupFn) => {
  7402. return (ctx) => {
  7403. const rawPatterns = lookupFn(ctx);
  7404. return fromRawPatterns(rawPatterns);
  7405. };
  7406. };
  7407. const deviceDetection$1 = detect$2().deviceType;
  7408. const isTouch = deviceDetection$1.isTouch();
  7409. const DOM$a = DOMUtils.DOM;
  7410. const getHash = (value) => {
  7411. const items =
  7412. value.indexOf("=") > 0
  7413. ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/)
  7414. : value.split(",");
  7415. return foldl(
  7416. items,
  7417. (output, item) => {
  7418. const arr = item.split("=");
  7419. const key = arr[0];
  7420. const val = arr.length > 1 ? arr[1] : key;
  7421. output[trim$3(key)] = trim$3(val);
  7422. return output;
  7423. },
  7424. {}
  7425. );
  7426. };
  7427. const isRegExp = (x) => is$4(x, RegExp);
  7428. const option = (name) => (editor) => editor.options.get(name);
  7429. const stringOrObjectProcessor = (value) => isString(value) || isObject(value);
  7430. const bodyOptionProcessor =
  7431. (editor, defaultValue = "") =>
  7432. (value) => {
  7433. const valid = isString(value);
  7434. if (valid) {
  7435. if (value.indexOf("=") !== -1) {
  7436. const bodyObj = getHash(value);
  7437. return {
  7438. value: get$a(bodyObj, editor.id).getOr(defaultValue),
  7439. valid,
  7440. };
  7441. } else {
  7442. return {
  7443. value,
  7444. valid,
  7445. };
  7446. }
  7447. } else {
  7448. return {
  7449. valid: false,
  7450. message: "Must be a string.",
  7451. };
  7452. }
  7453. };
  7454. const register$7 = (editor) => {
  7455. const registerOption = editor.options.register;
  7456. registerOption("id", {
  7457. processor: "string",
  7458. default: editor.id,
  7459. });
  7460. registerOption("selector", { processor: "string" });
  7461. registerOption("target", { processor: "object" });
  7462. registerOption("suffix", { processor: "string" });
  7463. registerOption("cache_suffix", { processor: "string" });
  7464. registerOption("base_url", { processor: "string" });
  7465. registerOption("referrer_policy", {
  7466. processor: "string",
  7467. default: "",
  7468. });
  7469. registerOption("language_load", {
  7470. processor: "boolean",
  7471. default: true,
  7472. });
  7473. registerOption("inline", {
  7474. processor: "boolean",
  7475. default: false,
  7476. });
  7477. registerOption("iframe_attrs", {
  7478. processor: "object",
  7479. default: {},
  7480. });
  7481. registerOption("doctype", {
  7482. processor: "string",
  7483. default: "<!DOCTYPE html>",
  7484. });
  7485. registerOption("document_base_url", {
  7486. processor: "string",
  7487. default: editor.documentBaseUrl,
  7488. });
  7489. registerOption("body_id", {
  7490. processor: bodyOptionProcessor(editor, "tinymce"),
  7491. default: "tinymce",
  7492. });
  7493. registerOption("body_class", {
  7494. processor: bodyOptionProcessor(editor),
  7495. default: "",
  7496. });
  7497. registerOption("content_security_policy", {
  7498. processor: "string",
  7499. default: "",
  7500. });
  7501. registerOption("br_in_pre", {
  7502. processor: "boolean",
  7503. default: true,
  7504. });
  7505. registerOption("forced_root_block", {
  7506. processor: (value) => {
  7507. const valid = isString(value) && isNotEmpty(value);
  7508. if (valid) {
  7509. return {
  7510. value,
  7511. valid,
  7512. };
  7513. } else {
  7514. return {
  7515. valid: false,
  7516. message: "Must be a non-empty string.",
  7517. };
  7518. }
  7519. },
  7520. default: "p",
  7521. });
  7522. registerOption("forced_root_block_attrs", {
  7523. processor: "object",
  7524. default: {},
  7525. });
  7526. registerOption("newline_behavior", {
  7527. processor: (value) => {
  7528. const valid = contains$2(
  7529. ["block", "linebreak", "invert", "default"],
  7530. value
  7531. );
  7532. return valid
  7533. ? {
  7534. value,
  7535. valid,
  7536. }
  7537. : {
  7538. valid: false,
  7539. message: "Must be one of: block, linebreak, invert or default.",
  7540. };
  7541. },
  7542. default: "default",
  7543. });
  7544. registerOption("br_newline_selector", {
  7545. processor: "string",
  7546. default: ".mce-toc h2,figcaption,caption",
  7547. });
  7548. registerOption("no_newline_selector", {
  7549. processor: "string",
  7550. default: "",
  7551. });
  7552. registerOption("keep_styles", {
  7553. processor: "boolean",
  7554. default: true,
  7555. });
  7556. registerOption("end_container_on_empty_block", {
  7557. processor: (value) => {
  7558. if (isBoolean(value)) {
  7559. return {
  7560. valid: true,
  7561. value,
  7562. };
  7563. } else if (isString(value)) {
  7564. return {
  7565. valid: true,
  7566. value,
  7567. };
  7568. } else {
  7569. return {
  7570. valid: false,
  7571. message: "Must be boolean or a string",
  7572. };
  7573. }
  7574. },
  7575. default: "blockquote",
  7576. });
  7577. registerOption("font_size_style_values", {
  7578. processor: "string",
  7579. default: "xx-small,x-small,small,medium,large,x-large,xx-large",
  7580. });
  7581. registerOption("font_size_legacy_values", {
  7582. processor: "string",
  7583. default: "xx-small,small,medium,large,x-large,xx-large,300%",
  7584. });
  7585. registerOption("font_size_classes", {
  7586. processor: "string",
  7587. default: "",
  7588. });
  7589. registerOption("automatic_uploads", {
  7590. processor: "boolean",
  7591. default: true,
  7592. });
  7593. registerOption("images_reuse_filename", {
  7594. processor: "boolean",
  7595. default: false,
  7596. });
  7597. registerOption("images_replace_blob_uris", {
  7598. processor: "boolean",
  7599. default: true,
  7600. });
  7601. registerOption("icons", {
  7602. processor: "string",
  7603. default: "",
  7604. });
  7605. registerOption("icons_url", {
  7606. processor: "string",
  7607. default: "",
  7608. });
  7609. registerOption("images_upload_url", {
  7610. processor: "string",
  7611. default: "",
  7612. });
  7613. registerOption("images_upload_base_path", {
  7614. processor: "string",
  7615. default: "",
  7616. });
  7617. registerOption("images_upload_credentials", {
  7618. processor: "boolean",
  7619. default: false,
  7620. });
  7621. registerOption("images_upload_handler", { processor: "function" });
  7622. registerOption("language", {
  7623. processor: "string",
  7624. default: "en",
  7625. });
  7626. registerOption("language_url", {
  7627. processor: "string",
  7628. default: "",
  7629. });
  7630. registerOption("entity_encoding", {
  7631. processor: "string",
  7632. default: "named",
  7633. });
  7634. registerOption("indent", {
  7635. processor: "boolean",
  7636. default: true,
  7637. });
  7638. registerOption("indent_before", {
  7639. processor: "string",
  7640. default:
  7641. "p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead," +
  7642. "tfoot,tbody,tr,section,details,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",
  7643. });
  7644. registerOption("indent_after", {
  7645. processor: "string",
  7646. default:
  7647. "p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead," +
  7648. "tfoot,tbody,tr,section,details,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",
  7649. });
  7650. registerOption("indent_use_margin", {
  7651. processor: "boolean",
  7652. default: false,
  7653. });
  7654. registerOption("indentation", {
  7655. processor: "string",
  7656. default: "40px",
  7657. });
  7658. registerOption("content_css", {
  7659. processor: (value) => {
  7660. const valid =
  7661. value === false || isString(value) || isArrayOf(value, isString);
  7662. if (valid) {
  7663. if (isString(value)) {
  7664. return {
  7665. value: map$3(value.split(","), trim$3),
  7666. valid,
  7667. };
  7668. } else if (isArray$1(value)) {
  7669. return {
  7670. value,
  7671. valid,
  7672. };
  7673. } else if (value === false) {
  7674. return {
  7675. value: [],
  7676. valid,
  7677. };
  7678. } else {
  7679. return {
  7680. value,
  7681. valid,
  7682. };
  7683. }
  7684. } else {
  7685. return {
  7686. valid: false,
  7687. message: "Must be false, a string or an array of strings.",
  7688. };
  7689. }
  7690. },
  7691. default: isInline(editor) ? [] : ["default"],
  7692. });
  7693. registerOption("content_style", { processor: "string" });
  7694. registerOption("content_css_cors", {
  7695. processor: "boolean",
  7696. default: false,
  7697. });
  7698. registerOption("font_css", {
  7699. processor: (value) => {
  7700. const valid = isString(value) || isArrayOf(value, isString);
  7701. if (valid) {
  7702. const newValue = isArray$1(value)
  7703. ? value
  7704. : map$3(value.split(","), trim$3);
  7705. return {
  7706. value: newValue,
  7707. valid,
  7708. };
  7709. } else {
  7710. return {
  7711. valid: false,
  7712. message: "Must be a string or an array of strings.",
  7713. };
  7714. }
  7715. },
  7716. default: [],
  7717. });
  7718. registerOption("inline_boundaries", {
  7719. processor: "boolean",
  7720. default: true,
  7721. });
  7722. registerOption("inline_boundaries_selector", {
  7723. processor: "string",
  7724. default: "a[href],code,span.mce-annotation",
  7725. });
  7726. registerOption("object_resizing", {
  7727. processor: (value) => {
  7728. const valid = isBoolean(value) || isString(value);
  7729. if (valid) {
  7730. if (
  7731. value === false ||
  7732. deviceDetection$1.isiPhone() ||
  7733. deviceDetection$1.isiPad()
  7734. ) {
  7735. return {
  7736. value: "",
  7737. valid,
  7738. };
  7739. } else {
  7740. return {
  7741. value:
  7742. value === true
  7743. ? "table,img,figure.image,div,video,iframe"
  7744. : value,
  7745. valid,
  7746. };
  7747. }
  7748. } else {
  7749. return {
  7750. valid: false,
  7751. message: "Must be boolean or a string",
  7752. };
  7753. }
  7754. },
  7755. default: !isTouch,
  7756. });
  7757. registerOption("resize_img_proportional", {
  7758. processor: "boolean",
  7759. default: true,
  7760. });
  7761. registerOption("event_root", { processor: "object" });
  7762. registerOption("service_message", { processor: "string" });
  7763. registerOption("theme", {
  7764. processor: (value) =>
  7765. value === false || isString(value) || isFunction(value),
  7766. default: "silver",
  7767. });
  7768. registerOption("theme_url", { processor: "string" });
  7769. registerOption("formats", { processor: "object" });
  7770. registerOption("format_empty_lines", {
  7771. processor: "boolean",
  7772. default: false,
  7773. });
  7774. registerOption("format_noneditable_selector", {
  7775. processor: "string",
  7776. default: "",
  7777. });
  7778. registerOption("preview_styles", {
  7779. processor: (value) => {
  7780. const valid = value === false || isString(value);
  7781. if (valid) {
  7782. return {
  7783. value: value === false ? "" : value,
  7784. valid,
  7785. };
  7786. } else {
  7787. return {
  7788. valid: false,
  7789. message: "Must be false or a string",
  7790. };
  7791. }
  7792. },
  7793. default:
  7794. "font-family font-size font-weight font-style text-decoration text-transform color background-color border border-radius outline text-shadow",
  7795. });
  7796. registerOption("custom_ui_selector", {
  7797. processor: "string",
  7798. default: "",
  7799. });
  7800. registerOption("hidden_input", {
  7801. processor: "boolean",
  7802. default: true,
  7803. });
  7804. registerOption("submit_patch", {
  7805. processor: "boolean",
  7806. default: true,
  7807. });
  7808. registerOption("encoding", { processor: "string" });
  7809. registerOption("add_form_submit_trigger", {
  7810. processor: "boolean",
  7811. default: true,
  7812. });
  7813. registerOption("add_unload_trigger", {
  7814. processor: "boolean",
  7815. default: true,
  7816. });
  7817. registerOption("custom_undo_redo_levels", {
  7818. processor: "number",
  7819. default: 0,
  7820. });
  7821. registerOption("disable_nodechange", {
  7822. processor: "boolean",
  7823. default: false,
  7824. });
  7825. registerOption("readonly", {
  7826. processor: "boolean",
  7827. default: false,
  7828. });
  7829. registerOption("editable_root", {
  7830. processor: "boolean",
  7831. default: true,
  7832. });
  7833. registerOption("plugins", {
  7834. processor: "string[]",
  7835. default: [],
  7836. });
  7837. registerOption("external_plugins", { processor: "object" });
  7838. registerOption("forced_plugins", { processor: "string[]" });
  7839. registerOption("model", {
  7840. processor: "string",
  7841. default: editor.hasPlugin("rtc") ? "plugin" : "dom",
  7842. });
  7843. registerOption("model_url", { processor: "string" });
  7844. registerOption("block_unsupported_drop", {
  7845. processor: "boolean",
  7846. default: true,
  7847. });
  7848. registerOption("visual", {
  7849. processor: "boolean",
  7850. default: true,
  7851. });
  7852. registerOption("visual_table_class", {
  7853. processor: "string",
  7854. default: "mce-item-table",
  7855. });
  7856. registerOption("visual_anchor_class", {
  7857. processor: "string",
  7858. default: "mce-item-anchor",
  7859. });
  7860. registerOption("iframe_aria_text", {
  7861. processor: "string",
  7862. default: "Rich Text Area. Press ALT-0 for help.",
  7863. });
  7864. registerOption("setup", { processor: "function" });
  7865. registerOption("init_instance_callback", { processor: "function" });
  7866. registerOption("url_converter", {
  7867. processor: "function",
  7868. default: editor.convertURL,
  7869. });
  7870. registerOption("url_converter_scope", {
  7871. processor: "object",
  7872. default: editor,
  7873. });
  7874. registerOption("urlconverter_callback", { processor: "function" });
  7875. registerOption("allow_conditional_comments", {
  7876. processor: "boolean",
  7877. default: false,
  7878. });
  7879. registerOption("allow_html_data_urls", {
  7880. processor: "boolean",
  7881. default: false,
  7882. });
  7883. registerOption("allow_svg_data_urls", { processor: "boolean" });
  7884. registerOption("allow_html_in_named_anchor", {
  7885. processor: "boolean",
  7886. default: false,
  7887. });
  7888. registerOption("allow_script_urls", {
  7889. processor: "boolean",
  7890. default: false,
  7891. });
  7892. registerOption("allow_unsafe_link_target", {
  7893. processor: "boolean",
  7894. default: false,
  7895. });
  7896. registerOption("convert_fonts_to_spans", {
  7897. processor: "boolean",
  7898. default: true,
  7899. deprecated: true,
  7900. });
  7901. registerOption("fix_list_elements", {
  7902. processor: "boolean",
  7903. default: false,
  7904. });
  7905. registerOption("preserve_cdata", {
  7906. processor: "boolean",
  7907. default: false,
  7908. });
  7909. registerOption("remove_trailing_brs", {
  7910. processor: "boolean",
  7911. default: true,
  7912. });
  7913. registerOption("pad_empty_with_br", {
  7914. processor: "boolean",
  7915. default: false,
  7916. });
  7917. registerOption("inline_styles", {
  7918. processor: "boolean",
  7919. default: true,
  7920. deprecated: true,
  7921. });
  7922. registerOption("element_format", {
  7923. processor: "string",
  7924. default: "html",
  7925. });
  7926. registerOption("entities", { processor: "string" });
  7927. registerOption("schema", {
  7928. processor: "string",
  7929. default: "html5",
  7930. });
  7931. registerOption("convert_urls", {
  7932. processor: "boolean",
  7933. default: true,
  7934. });
  7935. registerOption("relative_urls", {
  7936. processor: "boolean",
  7937. default: true,
  7938. });
  7939. registerOption("remove_script_host", {
  7940. processor: "boolean",
  7941. default: true,
  7942. });
  7943. registerOption("custom_elements", { processor: "string" });
  7944. registerOption("extended_valid_elements", { processor: "string" });
  7945. registerOption("invalid_elements", { processor: "string" });
  7946. registerOption("invalid_styles", { processor: stringOrObjectProcessor });
  7947. registerOption("valid_children", { processor: "string" });
  7948. registerOption("valid_classes", { processor: stringOrObjectProcessor });
  7949. registerOption("valid_elements", { processor: "string" });
  7950. registerOption("valid_styles", { processor: stringOrObjectProcessor });
  7951. registerOption("verify_html", {
  7952. processor: "boolean",
  7953. default: true,
  7954. });
  7955. registerOption("auto_focus", {
  7956. processor: (value) => isString(value) || value === true,
  7957. });
  7958. registerOption("browser_spellcheck", {
  7959. processor: "boolean",
  7960. default: false,
  7961. });
  7962. registerOption("protect", { processor: "array" });
  7963. registerOption("images_file_types", {
  7964. processor: "string",
  7965. default: "jpeg,jpg,jpe,jfi,jif,jfif,png,gif,bmp,webp",
  7966. });
  7967. registerOption("deprecation_warnings", {
  7968. processor: "boolean",
  7969. default: true,
  7970. });
  7971. registerOption("a11y_advanced_options", {
  7972. processor: "boolean",
  7973. default: false,
  7974. });
  7975. registerOption("api_key", { processor: "string" });
  7976. registerOption("paste_block_drop", {
  7977. processor: "boolean",
  7978. default: false,
  7979. });
  7980. registerOption("paste_data_images", {
  7981. processor: "boolean",
  7982. default: true,
  7983. });
  7984. registerOption("paste_preprocess", { processor: "function" });
  7985. registerOption("paste_postprocess", { processor: "function" });
  7986. registerOption("paste_webkit_styles", {
  7987. processor: "string",
  7988. default: "none",
  7989. });
  7990. registerOption("paste_remove_styles_if_webkit", {
  7991. processor: "boolean",
  7992. default: true,
  7993. });
  7994. registerOption("paste_merge_formats", {
  7995. processor: "boolean",
  7996. default: true,
  7997. });
  7998. registerOption("smart_paste", {
  7999. processor: "boolean",
  8000. default: true,
  8001. });
  8002. registerOption("paste_as_text", {
  8003. processor: "boolean",
  8004. default: false,
  8005. });
  8006. registerOption("paste_tab_spaces", {
  8007. processor: "number",
  8008. default: 4,
  8009. });
  8010. registerOption("text_patterns", {
  8011. processor: (value) => {
  8012. if (isArrayOf(value, isObject) || value === false) {
  8013. const patterns = value === false ? [] : value;
  8014. return {
  8015. value: fromRawPatterns(patterns),
  8016. valid: true,
  8017. };
  8018. } else {
  8019. return {
  8020. valid: false,
  8021. message: "Must be an array of objects or false.",
  8022. };
  8023. }
  8024. },
  8025. default: [
  8026. {
  8027. start: "*",
  8028. end: "*",
  8029. format: "italic",
  8030. },
  8031. {
  8032. start: "**",
  8033. end: "**",
  8034. format: "bold",
  8035. },
  8036. {
  8037. start: "#",
  8038. format: "h1",
  8039. },
  8040. {
  8041. start: "##",
  8042. format: "h2",
  8043. },
  8044. {
  8045. start: "###",
  8046. format: "h3",
  8047. },
  8048. {
  8049. start: "####",
  8050. format: "h4",
  8051. },
  8052. {
  8053. start: "#####",
  8054. format: "h5",
  8055. },
  8056. {
  8057. start: "######",
  8058. format: "h6",
  8059. },
  8060. {
  8061. start: "1. ",
  8062. cmd: "InsertOrderedList",
  8063. },
  8064. {
  8065. start: "* ",
  8066. cmd: "InsertUnorderedList",
  8067. },
  8068. {
  8069. start: "- ",
  8070. cmd: "InsertUnorderedList",
  8071. },
  8072. ],
  8073. });
  8074. registerOption("text_patterns_lookup", {
  8075. processor: (value) => {
  8076. if (isFunction(value)) {
  8077. return {
  8078. value: fromRawPatternsLookup(value),
  8079. valid: true,
  8080. };
  8081. } else {
  8082. return {
  8083. valid: false,
  8084. message: "Must be a single function",
  8085. };
  8086. }
  8087. },
  8088. default: (_ctx) => [],
  8089. });
  8090. registerOption("noneditable_class", {
  8091. processor: "string",
  8092. default: "mceNonEditable",
  8093. });
  8094. registerOption("editable_class", {
  8095. processor: "string",
  8096. default: "mceEditable",
  8097. });
  8098. registerOption("noneditable_regexp", {
  8099. processor: (value) => {
  8100. if (isArrayOf(value, isRegExp)) {
  8101. return {
  8102. value,
  8103. valid: true,
  8104. };
  8105. } else if (isRegExp(value)) {
  8106. return {
  8107. value: [value],
  8108. valid: true,
  8109. };
  8110. } else {
  8111. return {
  8112. valid: false,
  8113. message: "Must be a RegExp or an array of RegExp.",
  8114. };
  8115. }
  8116. },
  8117. default: [],
  8118. });
  8119. registerOption("table_tab_navigation", {
  8120. processor: "boolean",
  8121. default: true,
  8122. });
  8123. registerOption("highlight_on_focus", {
  8124. processor: "boolean",
  8125. default: false,
  8126. });
  8127. registerOption("xss_sanitization", {
  8128. processor: "boolean",
  8129. default: true,
  8130. });
  8131. registerOption("details_initial_state", {
  8132. processor: (value) => {
  8133. const valid = contains$2(["inherited", "collapsed", "expanded"], value);
  8134. return valid
  8135. ? {
  8136. value,
  8137. valid,
  8138. }
  8139. : {
  8140. valid: false,
  8141. message: "Must be one of: inherited, collapsed, or expanded.",
  8142. };
  8143. },
  8144. default: "inherited",
  8145. });
  8146. registerOption("details_serialized_state", {
  8147. processor: (value) => {
  8148. const valid = contains$2(["inherited", "collapsed", "expanded"], value);
  8149. return valid
  8150. ? {
  8151. value,
  8152. valid,
  8153. }
  8154. : {
  8155. valid: false,
  8156. message: "Must be one of: inherited, collapsed, or expanded.",
  8157. };
  8158. },
  8159. default: "inherited",
  8160. });
  8161. registerOption("init_content_sync", {
  8162. processor: "boolean",
  8163. default: false,
  8164. });
  8165. registerOption("newdocument_content", {
  8166. processor: "string",
  8167. default: "",
  8168. });
  8169. editor.on("ScriptsLoaded", () => {
  8170. registerOption("directionality", {
  8171. processor: "string",
  8172. default: I18n.isRtl() ? "rtl" : undefined,
  8173. });
  8174. registerOption("placeholder", {
  8175. processor: "string",
  8176. default: DOM$a.getAttrib(editor.getElement(), "placeholder"),
  8177. });
  8178. });
  8179. };
  8180. const getIframeAttrs = option("iframe_attrs");
  8181. const getDocType = option("doctype");
  8182. const getDocumentBaseUrl = option("document_base_url");
  8183. const getBodyId = option("body_id");
  8184. const getBodyClass = option("body_class");
  8185. const getContentSecurityPolicy = option("content_security_policy");
  8186. const shouldPutBrInPre$1 = option("br_in_pre");
  8187. const getForcedRootBlock = option("forced_root_block");
  8188. const getForcedRootBlockAttrs = option("forced_root_block_attrs");
  8189. const getNewlineBehavior = option("newline_behavior");
  8190. const getBrNewLineSelector = option("br_newline_selector");
  8191. const getNoNewLineSelector = option("no_newline_selector");
  8192. const shouldKeepStyles = option("keep_styles");
  8193. const shouldEndContainerOnEmptyBlock = option("end_container_on_empty_block");
  8194. const isAutomaticUploadsEnabled = option("automatic_uploads");
  8195. const shouldReuseFileName = option("images_reuse_filename");
  8196. const shouldReplaceBlobUris = option("images_replace_blob_uris");
  8197. const getIconPackName = option("icons");
  8198. const getIconsUrl = option("icons_url");
  8199. const getImageUploadUrl = option("images_upload_url");
  8200. const getImageUploadBasePath = option("images_upload_base_path");
  8201. const getImagesUploadCredentials = option("images_upload_credentials");
  8202. const getImagesUploadHandler = option("images_upload_handler");
  8203. const shouldUseContentCssCors = option("content_css_cors");
  8204. const getReferrerPolicy = option("referrer_policy");
  8205. const getLanguageCode = option("language");
  8206. const getLanguageUrl = option("language_url");
  8207. const shouldIndentUseMargin = option("indent_use_margin");
  8208. const getIndentation = option("indentation");
  8209. const getContentCss = option("content_css");
  8210. const getContentStyle = option("content_style");
  8211. const getFontCss = option("font_css");
  8212. const getDirectionality = option("directionality");
  8213. const getInlineBoundarySelector = option("inline_boundaries_selector");
  8214. const getObjectResizing = option("object_resizing");
  8215. const getResizeImgProportional = option("resize_img_proportional");
  8216. const getPlaceholder = option("placeholder");
  8217. const getEventRoot = option("event_root");
  8218. const getServiceMessage = option("service_message");
  8219. const getTheme = option("theme");
  8220. const getThemeUrl = option("theme_url");
  8221. const getModel = option("model");
  8222. const getModelUrl = option("model_url");
  8223. const isInlineBoundariesEnabled = option("inline_boundaries");
  8224. const getFormats = option("formats");
  8225. const getPreviewStyles = option("preview_styles");
  8226. const canFormatEmptyLines = option("format_empty_lines");
  8227. const getFormatNoneditableSelector = option("format_noneditable_selector");
  8228. const getCustomUiSelector = option("custom_ui_selector");
  8229. const isInline = option("inline");
  8230. const hasHiddenInput = option("hidden_input");
  8231. const shouldPatchSubmit = option("submit_patch");
  8232. const shouldAddFormSubmitTrigger = option("add_form_submit_trigger");
  8233. const shouldAddUnloadTrigger = option("add_unload_trigger");
  8234. const getCustomUndoRedoLevels = option("custom_undo_redo_levels");
  8235. const shouldDisableNodeChange = option("disable_nodechange");
  8236. const isReadOnly$1 = option("readonly");
  8237. const hasEditableRoot$1 = option("editable_root");
  8238. const hasContentCssCors = option("content_css_cors");
  8239. const getPlugins = option("plugins");
  8240. const getExternalPlugins$1 = option("external_plugins");
  8241. const shouldBlockUnsupportedDrop = option("block_unsupported_drop");
  8242. const isVisualAidsEnabled = option("visual");
  8243. const getVisualAidsTableClass = option("visual_table_class");
  8244. const getVisualAidsAnchorClass = option("visual_anchor_class");
  8245. const getIframeAriaText = option("iframe_aria_text");
  8246. const getSetupCallback = option("setup");
  8247. const getInitInstanceCallback = option("init_instance_callback");
  8248. const getUrlConverterCallback = option("urlconverter_callback");
  8249. const getAutoFocus = option("auto_focus");
  8250. const shouldBrowserSpellcheck = option("browser_spellcheck");
  8251. const getProtect = option("protect");
  8252. const shouldPasteBlockDrop = option("paste_block_drop");
  8253. const shouldPasteDataImages = option("paste_data_images");
  8254. const getPastePreProcess = option("paste_preprocess");
  8255. const getPastePostProcess = option("paste_postprocess");
  8256. const getNewDocumentContent = option("newdocument_content");
  8257. const getPasteWebkitStyles = option("paste_webkit_styles");
  8258. const shouldPasteRemoveWebKitStyles = option("paste_remove_styles_if_webkit");
  8259. const shouldPasteMergeFormats = option("paste_merge_formats");
  8260. const isSmartPasteEnabled = option("smart_paste");
  8261. const isPasteAsTextEnabled = option("paste_as_text");
  8262. const getPasteTabSpaces = option("paste_tab_spaces");
  8263. const shouldAllowHtmlDataUrls = option("allow_html_data_urls");
  8264. const getTextPatterns = option("text_patterns");
  8265. const getTextPatternsLookup = option("text_patterns_lookup");
  8266. const getNonEditableClass = option("noneditable_class");
  8267. const getEditableClass = option("editable_class");
  8268. const getNonEditableRegExps = option("noneditable_regexp");
  8269. const shouldPreserveCData = option("preserve_cdata");
  8270. const shouldHighlightOnFocus = option("highlight_on_focus");
  8271. const shouldSanitizeXss = option("xss_sanitization");
  8272. const shouldUseDocumentWrite = option("init_content_sync");
  8273. const hasTextPatternsLookup = (editor) =>
  8274. editor.options.isSet("text_patterns_lookup");
  8275. const getFontStyleValues = (editor) =>
  8276. Tools.explode(editor.options.get("font_size_style_values"));
  8277. const getFontSizeClasses = (editor) =>
  8278. Tools.explode(editor.options.get("font_size_classes"));
  8279. const isEncodingXml = (editor) => editor.options.get("encoding") === "xml";
  8280. const getAllowedImageFileTypes = (editor) =>
  8281. Tools.explode(editor.options.get("images_file_types"));
  8282. const hasTableTabNavigation = option("table_tab_navigation");
  8283. const getDetailsInitialState = option("details_initial_state");
  8284. const getDetailsSerializedState = option("details_serialized_state");
  8285. const isElement$3 = isElement$6;
  8286. const isText$5 = isText$a;
  8287. const removeNode$1 = (node) => {
  8288. const parentNode = node.parentNode;
  8289. if (parentNode) {
  8290. parentNode.removeChild(node);
  8291. }
  8292. };
  8293. const trimCount = (text) => {
  8294. const trimmedText = trim$1(text);
  8295. return {
  8296. count: text.length - trimmedText.length,
  8297. text: trimmedText,
  8298. };
  8299. };
  8300. const deleteZwspChars = (caretContainer) => {
  8301. let idx;
  8302. while ((idx = caretContainer.data.lastIndexOf(ZWSP$1)) !== -1) {
  8303. caretContainer.deleteData(idx, 1);
  8304. }
  8305. };
  8306. const removeUnchanged = (caretContainer, pos) => {
  8307. remove$3(caretContainer);
  8308. return pos;
  8309. };
  8310. const removeTextAndReposition = (caretContainer, pos) => {
  8311. const before = trimCount(caretContainer.data.substr(0, pos.offset()));
  8312. const after = trimCount(caretContainer.data.substr(pos.offset()));
  8313. const text = before.text + after.text;
  8314. if (text.length > 0) {
  8315. deleteZwspChars(caretContainer);
  8316. return CaretPosition(caretContainer, pos.offset() - before.count);
  8317. } else {
  8318. return pos;
  8319. }
  8320. };
  8321. const removeElementAndReposition = (caretContainer, pos) => {
  8322. const parentNode = pos.container();
  8323. const newPosition = indexOf$1(from(parentNode.childNodes), caretContainer)
  8324. .map((index) => {
  8325. return index < pos.offset()
  8326. ? CaretPosition(parentNode, pos.offset() - 1)
  8327. : pos;
  8328. })
  8329. .getOr(pos);
  8330. remove$3(caretContainer);
  8331. return newPosition;
  8332. };
  8333. const removeTextCaretContainer = (caretContainer, pos) =>
  8334. isText$5(caretContainer) && pos.container() === caretContainer
  8335. ? removeTextAndReposition(caretContainer, pos)
  8336. : removeUnchanged(caretContainer, pos);
  8337. const removeElementCaretContainer = (caretContainer, pos) =>
  8338. pos.container() === caretContainer.parentNode
  8339. ? removeElementAndReposition(caretContainer, pos)
  8340. : removeUnchanged(caretContainer, pos);
  8341. const removeAndReposition = (container, pos) =>
  8342. CaretPosition.isTextPosition(pos)
  8343. ? removeTextCaretContainer(container, pos)
  8344. : removeElementCaretContainer(container, pos);
  8345. const remove$3 = (caretContainerNode) => {
  8346. if (
  8347. isElement$3(caretContainerNode) &&
  8348. isCaretContainer$2(caretContainerNode)
  8349. ) {
  8350. if (hasContent(caretContainerNode)) {
  8351. caretContainerNode.removeAttribute("data-mce-caret");
  8352. } else {
  8353. removeNode$1(caretContainerNode);
  8354. }
  8355. }
  8356. if (isText$5(caretContainerNode)) {
  8357. deleteZwspChars(caretContainerNode);
  8358. if (caretContainerNode.data.length === 0) {
  8359. removeNode$1(caretContainerNode);
  8360. }
  8361. }
  8362. };
  8363. const isContentEditableFalse$8 = isContentEditableFalse$b;
  8364. const isMedia$1 = isMedia$2;
  8365. const isTableCell$1 = isTableCell$3;
  8366. const inlineFakeCaretSelector =
  8367. "*[contentEditable=false],video,audio,embed,object";
  8368. const getAbsoluteClientRect = (root, element, before) => {
  8369. const clientRect = collapse(element.getBoundingClientRect(), before);
  8370. let scrollX;
  8371. let scrollY;
  8372. if (root.tagName === "BODY") {
  8373. const docElm = root.ownerDocument.documentElement;
  8374. scrollX = root.scrollLeft || docElm.scrollLeft;
  8375. scrollY = root.scrollTop || docElm.scrollTop;
  8376. } else {
  8377. const rootRect = root.getBoundingClientRect();
  8378. scrollX = root.scrollLeft - rootRect.left;
  8379. scrollY = root.scrollTop - rootRect.top;
  8380. }
  8381. clientRect.left += scrollX;
  8382. clientRect.right += scrollX;
  8383. clientRect.top += scrollY;
  8384. clientRect.bottom += scrollY;
  8385. clientRect.width = 1;
  8386. let margin = element.offsetWidth - element.clientWidth;
  8387. if (margin > 0) {
  8388. if (before) {
  8389. margin *= -1;
  8390. }
  8391. clientRect.left += margin;
  8392. clientRect.right += margin;
  8393. }
  8394. return clientRect;
  8395. };
  8396. const trimInlineCaretContainers = (root) => {
  8397. var _a, _b;
  8398. const fakeCaretTargetNodes = descendants(
  8399. SugarElement.fromDom(root),
  8400. inlineFakeCaretSelector
  8401. );
  8402. for (let i = 0; i < fakeCaretTargetNodes.length; i++) {
  8403. const node = fakeCaretTargetNodes[i].dom;
  8404. let sibling = node.previousSibling;
  8405. if (endsWithCaretContainer$1(sibling)) {
  8406. const data = sibling.data;
  8407. if (data.length === 1) {
  8408. (_a = sibling.parentNode) === null || _a === void 0
  8409. ? void 0
  8410. : _a.removeChild(sibling);
  8411. } else {
  8412. sibling.deleteData(data.length - 1, 1);
  8413. }
  8414. }
  8415. sibling = node.nextSibling;
  8416. if (startsWithCaretContainer$1(sibling)) {
  8417. const data = sibling.data;
  8418. if (data.length === 1) {
  8419. (_b = sibling.parentNode) === null || _b === void 0
  8420. ? void 0
  8421. : _b.removeChild(sibling);
  8422. } else {
  8423. sibling.deleteData(0, 1);
  8424. }
  8425. }
  8426. }
  8427. };
  8428. const FakeCaret = (editor, root, isBlock, hasFocus) => {
  8429. const lastVisualCaret = value$2();
  8430. let cursorInterval;
  8431. let caretContainerNode;
  8432. const caretBlock = getForcedRootBlock(editor);
  8433. const dom = editor.dom;
  8434. const show = (before, element) => {
  8435. let rng;
  8436. hide();
  8437. if (isTableCell$1(element)) {
  8438. return null;
  8439. }
  8440. if (isBlock(element)) {
  8441. const caretContainer = insertBlock(caretBlock, element, before);
  8442. const clientRect = getAbsoluteClientRect(root, element, before);
  8443. dom.setStyle(caretContainer, "top", clientRect.top);
  8444. caretContainerNode = caretContainer;
  8445. const caret = dom.create("div", {
  8446. class: "mce-visual-caret",
  8447. "data-mce-bogus": "all",
  8448. });
  8449. dom.setStyles(caret, { ...clientRect });
  8450. dom.add(root, caret);
  8451. lastVisualCaret.set({
  8452. caret,
  8453. element,
  8454. before,
  8455. });
  8456. if (before) {
  8457. dom.addClass(caret, "mce-visual-caret-before");
  8458. }
  8459. startBlink();
  8460. rng = element.ownerDocument.createRange();
  8461. rng.setStart(caretContainer, 0);
  8462. rng.setEnd(caretContainer, 0);
  8463. } else {
  8464. caretContainerNode = insertInline$1(element, before);
  8465. rng = element.ownerDocument.createRange();
  8466. if (isInlineFakeCaretTarget(caretContainerNode.nextSibling)) {
  8467. rng.setStart(caretContainerNode, 0);
  8468. rng.setEnd(caretContainerNode, 0);
  8469. } else {
  8470. rng.setStart(caretContainerNode, 1);
  8471. rng.setEnd(caretContainerNode, 1);
  8472. }
  8473. return rng;
  8474. }
  8475. return rng;
  8476. };
  8477. const hide = () => {
  8478. trimInlineCaretContainers(root);
  8479. if (caretContainerNode) {
  8480. remove$3(caretContainerNode);
  8481. caretContainerNode = null;
  8482. }
  8483. lastVisualCaret.on((caretState) => {
  8484. dom.remove(caretState.caret);
  8485. lastVisualCaret.clear();
  8486. });
  8487. if (cursorInterval) {
  8488. clearInterval(cursorInterval);
  8489. cursorInterval = undefined;
  8490. }
  8491. };
  8492. const startBlink = () => {
  8493. cursorInterval = setInterval(() => {
  8494. lastVisualCaret.on((caretState) => {
  8495. if (hasFocus()) {
  8496. dom.toggleClass(caretState.caret, "mce-visual-caret-hidden");
  8497. } else {
  8498. dom.addClass(caretState.caret, "mce-visual-caret-hidden");
  8499. }
  8500. });
  8501. }, 500);
  8502. };
  8503. const reposition = () => {
  8504. lastVisualCaret.on((caretState) => {
  8505. const clientRect = getAbsoluteClientRect(
  8506. root,
  8507. caretState.element,
  8508. caretState.before
  8509. );
  8510. dom.setStyles(caretState.caret, { ...clientRect });
  8511. });
  8512. };
  8513. const destroy = () => clearInterval(cursorInterval);
  8514. const getCss = () =>
  8515. ".mce-visual-caret {" +
  8516. "position: absolute;" +
  8517. "background-color: black;" +
  8518. "background-color: currentcolor;" +
  8519. "}" +
  8520. ".mce-visual-caret-hidden {" +
  8521. "display: none;" +
  8522. "}" +
  8523. "*[data-mce-caret] {" +
  8524. "position: absolute;" +
  8525. "left: -1000px;" +
  8526. "right: auto;" +
  8527. "top: 0;" +
  8528. "margin: 0;" +
  8529. "padding: 0;" +
  8530. "}";
  8531. return {
  8532. show,
  8533. hide,
  8534. getCss,
  8535. reposition,
  8536. destroy,
  8537. };
  8538. };
  8539. const isFakeCaretTableBrowser = () => Env.browser.isFirefox();
  8540. const isInlineFakeCaretTarget = (node) =>
  8541. isContentEditableFalse$8(node) || isMedia$1(node);
  8542. const isFakeCaretTarget = (node) => {
  8543. const isTarget =
  8544. isInlineFakeCaretTarget(node) ||
  8545. (isTable$2(node) && isFakeCaretTableBrowser());
  8546. return (
  8547. isTarget && parentElement(SugarElement.fromDom(node)).exists(isEditable$3)
  8548. );
  8549. };
  8550. const isContentEditableTrue$1 = isContentEditableTrue$3;
  8551. const isContentEditableFalse$7 = isContentEditableFalse$b;
  8552. const isMedia = isMedia$2;
  8553. const isBlockLike = matchStyleValues(
  8554. "display",
  8555. "block table table-cell table-caption list-item"
  8556. );
  8557. const isCaretContainer = isCaretContainer$2;
  8558. const isCaretContainerBlock = isCaretContainerBlock$1;
  8559. const isElement$2 = isElement$6;
  8560. const isText$4 = isText$a;
  8561. const isCaretCandidate$1 = isCaretCandidate$3;
  8562. const isForwards = (direction) => direction > 0;
  8563. const isBackwards = (direction) => direction < 0;
  8564. const skipCaretContainers = (walk, shallow) => {
  8565. let node;
  8566. while ((node = walk(shallow))) {
  8567. if (!isCaretContainerBlock(node)) {
  8568. return node;
  8569. }
  8570. }
  8571. return null;
  8572. };
  8573. const findNode = (node, direction, predicateFn, rootNode, shallow) => {
  8574. const walker = new DomTreeWalker(node, rootNode);
  8575. const isCefOrCaretContainer =
  8576. isContentEditableFalse$7(node) || isCaretContainerBlock(node);
  8577. let tempNode;
  8578. if (isBackwards(direction)) {
  8579. if (isCefOrCaretContainer) {
  8580. tempNode = skipCaretContainers(walker.prev.bind(walker), true);
  8581. if (predicateFn(tempNode)) {
  8582. return tempNode;
  8583. }
  8584. }
  8585. while (
  8586. (tempNode = skipCaretContainers(walker.prev.bind(walker), shallow))
  8587. ) {
  8588. if (predicateFn(tempNode)) {
  8589. return tempNode;
  8590. }
  8591. }
  8592. }
  8593. if (isForwards(direction)) {
  8594. if (isCefOrCaretContainer) {
  8595. tempNode = skipCaretContainers(walker.next.bind(walker), true);
  8596. if (predicateFn(tempNode)) {
  8597. return tempNode;
  8598. }
  8599. }
  8600. while (
  8601. (tempNode = skipCaretContainers(walker.next.bind(walker), shallow))
  8602. ) {
  8603. if (predicateFn(tempNode)) {
  8604. return tempNode;
  8605. }
  8606. }
  8607. }
  8608. return null;
  8609. };
  8610. const getEditingHost = (node, rootNode) => {
  8611. const isCETrue = (node) => isContentEditableTrue$1(node.dom);
  8612. const isRoot = (node) => node.dom === rootNode;
  8613. return ancestor$4(SugarElement.fromDom(node), isCETrue, isRoot)
  8614. .map((elm) => elm.dom)
  8615. .getOr(rootNode);
  8616. };
  8617. const getParentBlock$3 = (node, rootNode) => {
  8618. while (node && node !== rootNode) {
  8619. if (isBlockLike(node)) {
  8620. return node;
  8621. }
  8622. node = node.parentNode;
  8623. }
  8624. return null;
  8625. };
  8626. const isInSameBlock = (caretPosition1, caretPosition2, rootNode) =>
  8627. getParentBlock$3(caretPosition1.container(), rootNode) ===
  8628. getParentBlock$3(caretPosition2.container(), rootNode);
  8629. const getChildNodeAtRelativeOffset = (relativeOffset, caretPosition) => {
  8630. if (!caretPosition) {
  8631. return Optional.none();
  8632. }
  8633. const container = caretPosition.container();
  8634. const offset = caretPosition.offset();
  8635. if (!isElement$2(container)) {
  8636. return Optional.none();
  8637. }
  8638. return Optional.from(container.childNodes[offset + relativeOffset]);
  8639. };
  8640. const beforeAfter = (before, node) => {
  8641. var _a;
  8642. const doc =
  8643. (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
  8644. const range = doc.createRange();
  8645. if (before) {
  8646. range.setStartBefore(node);
  8647. range.setEndBefore(node);
  8648. } else {
  8649. range.setStartAfter(node);
  8650. range.setEndAfter(node);
  8651. }
  8652. return range;
  8653. };
  8654. const isNodesInSameBlock = (root, node1, node2) =>
  8655. getParentBlock$3(node1, root) === getParentBlock$3(node2, root);
  8656. const lean = (left, root, node) => {
  8657. const siblingName = left ? "previousSibling" : "nextSibling";
  8658. let tempNode = node;
  8659. while (tempNode && tempNode !== root) {
  8660. let sibling = tempNode[siblingName];
  8661. if (sibling && isCaretContainer(sibling)) {
  8662. sibling = sibling[siblingName];
  8663. }
  8664. if (isContentEditableFalse$7(sibling) || isMedia(sibling)) {
  8665. if (isNodesInSameBlock(root, sibling, tempNode)) {
  8666. return sibling;
  8667. }
  8668. break;
  8669. }
  8670. if (isCaretCandidate$1(sibling)) {
  8671. break;
  8672. }
  8673. tempNode = tempNode.parentNode;
  8674. }
  8675. return null;
  8676. };
  8677. const before$2 = curry(beforeAfter, true);
  8678. const after$2 = curry(beforeAfter, false);
  8679. const normalizeRange = (direction, root, range) => {
  8680. let node;
  8681. const leanLeft = curry(lean, true, root);
  8682. const leanRight = curry(lean, false, root);
  8683. const container = range.startContainer;
  8684. const offset = range.startOffset;
  8685. if (isCaretContainerBlock$1(container)) {
  8686. const block = isText$4(container) ? container.parentNode : container;
  8687. const location = block.getAttribute("data-mce-caret");
  8688. if (location === "before") {
  8689. node = block.nextSibling;
  8690. if (isFakeCaretTarget(node)) {
  8691. return before$2(node);
  8692. }
  8693. }
  8694. if (location === "after") {
  8695. node = block.previousSibling;
  8696. if (isFakeCaretTarget(node)) {
  8697. return after$2(node);
  8698. }
  8699. }
  8700. }
  8701. if (!range.collapsed) {
  8702. return range;
  8703. }
  8704. if (isText$a(container)) {
  8705. if (isCaretContainer(container)) {
  8706. if (direction === 1) {
  8707. node = leanRight(container);
  8708. if (node) {
  8709. return before$2(node);
  8710. }
  8711. node = leanLeft(container);
  8712. if (node) {
  8713. return after$2(node);
  8714. }
  8715. }
  8716. if (direction === -1) {
  8717. node = leanLeft(container);
  8718. if (node) {
  8719. return after$2(node);
  8720. }
  8721. node = leanRight(container);
  8722. if (node) {
  8723. return before$2(node);
  8724. }
  8725. }
  8726. return range;
  8727. }
  8728. if (
  8729. endsWithCaretContainer$1(container) &&
  8730. offset >= container.data.length - 1
  8731. ) {
  8732. if (direction === 1) {
  8733. node = leanRight(container);
  8734. if (node) {
  8735. return before$2(node);
  8736. }
  8737. }
  8738. return range;
  8739. }
  8740. if (startsWithCaretContainer$1(container) && offset <= 1) {
  8741. if (direction === -1) {
  8742. node = leanLeft(container);
  8743. if (node) {
  8744. return after$2(node);
  8745. }
  8746. }
  8747. return range;
  8748. }
  8749. if (offset === container.data.length) {
  8750. node = leanRight(container);
  8751. if (node) {
  8752. return before$2(node);
  8753. }
  8754. return range;
  8755. }
  8756. if (offset === 0) {
  8757. node = leanLeft(container);
  8758. if (node) {
  8759. return after$2(node);
  8760. }
  8761. return range;
  8762. }
  8763. }
  8764. return range;
  8765. };
  8766. const getRelativeCefElm = (forward, caretPosition) =>
  8767. getChildNodeAtRelativeOffset(forward ? 0 : -1, caretPosition).filter(
  8768. isContentEditableFalse$7
  8769. );
  8770. const getNormalizedRangeEndPoint = (direction, root, range) => {
  8771. const normalizedRange = normalizeRange(direction, root, range);
  8772. return direction === -1
  8773. ? CaretPosition.fromRangeStart(normalizedRange)
  8774. : CaretPosition.fromRangeEnd(normalizedRange);
  8775. };
  8776. const getElementFromPosition = (pos) =>
  8777. Optional.from(pos.getNode()).map(SugarElement.fromDom);
  8778. const getElementFromPrevPosition = (pos) =>
  8779. Optional.from(pos.getNode(true)).map(SugarElement.fromDom);
  8780. const getVisualCaretPosition = (walkFn, caretPosition) => {
  8781. let pos = caretPosition;
  8782. while ((pos = walkFn(pos))) {
  8783. if (pos.isVisible()) {
  8784. return pos;
  8785. }
  8786. }
  8787. return pos;
  8788. };
  8789. const isMoveInsideSameBlock = (from, to) => {
  8790. const inSameBlock = isInSameBlock(from, to);
  8791. if (!inSameBlock && isBr$6(from.getNode())) {
  8792. return true;
  8793. }
  8794. return inSameBlock;
  8795. };
  8796. var HDirection;
  8797. (function (HDirection) {
  8798. HDirection[(HDirection["Backwards"] = -1)] = "Backwards";
  8799. HDirection[(HDirection["Forwards"] = 1)] = "Forwards";
  8800. })(HDirection || (HDirection = {}));
  8801. const isContentEditableFalse$6 = isContentEditableFalse$b;
  8802. const isText$3 = isText$a;
  8803. const isElement$1 = isElement$6;
  8804. const isBr$2 = isBr$6;
  8805. const isCaretCandidate = isCaretCandidate$3;
  8806. const isAtomic = isAtomic$1;
  8807. const isEditableCaretCandidate = isEditableCaretCandidate$1;
  8808. const getParents$3 = (node, root) => {
  8809. const parents = [];
  8810. let tempNode = node;
  8811. while (tempNode && tempNode !== root) {
  8812. parents.push(tempNode);
  8813. tempNode = tempNode.parentNode;
  8814. }
  8815. return parents;
  8816. };
  8817. const nodeAtIndex = (container, offset) => {
  8818. if (container.hasChildNodes() && offset < container.childNodes.length) {
  8819. return container.childNodes[offset];
  8820. }
  8821. return null;
  8822. };
  8823. const getCaretCandidatePosition = (direction, node) => {
  8824. if (isForwards(direction)) {
  8825. if (
  8826. isCaretCandidate(node.previousSibling) &&
  8827. !isText$3(node.previousSibling)
  8828. ) {
  8829. return CaretPosition.before(node);
  8830. }
  8831. if (isText$3(node)) {
  8832. return CaretPosition(node, 0);
  8833. }
  8834. }
  8835. if (isBackwards(direction)) {
  8836. if (isCaretCandidate(node.nextSibling) && !isText$3(node.nextSibling)) {
  8837. return CaretPosition.after(node);
  8838. }
  8839. if (isText$3(node)) {
  8840. return CaretPosition(node, node.data.length);
  8841. }
  8842. }
  8843. if (isBackwards(direction)) {
  8844. if (isBr$2(node)) {
  8845. return CaretPosition.before(node);
  8846. }
  8847. return CaretPosition.after(node);
  8848. }
  8849. return CaretPosition.before(node);
  8850. };
  8851. const moveForwardFromBr = (root, nextNode) => {
  8852. const nextSibling = nextNode.nextSibling;
  8853. if (nextSibling && isCaretCandidate(nextSibling)) {
  8854. if (isText$3(nextSibling)) {
  8855. return CaretPosition(nextSibling, 0);
  8856. } else {
  8857. return CaretPosition.before(nextSibling);
  8858. }
  8859. } else {
  8860. return findCaretPosition$1(
  8861. HDirection.Forwards,
  8862. CaretPosition.after(nextNode),
  8863. root
  8864. );
  8865. }
  8866. };
  8867. const findCaretPosition$1 = (direction, startPos, root) => {
  8868. let node;
  8869. let nextNode;
  8870. let innerNode;
  8871. let caretPosition;
  8872. if (!isElement$1(root) || !startPos) {
  8873. return null;
  8874. }
  8875. if (startPos.isEqual(CaretPosition.after(root)) && root.lastChild) {
  8876. caretPosition = CaretPosition.after(root.lastChild);
  8877. if (
  8878. isBackwards(direction) &&
  8879. isCaretCandidate(root.lastChild) &&
  8880. isElement$1(root.lastChild)
  8881. ) {
  8882. return isBr$2(root.lastChild)
  8883. ? CaretPosition.before(root.lastChild)
  8884. : caretPosition;
  8885. }
  8886. } else {
  8887. caretPosition = startPos;
  8888. }
  8889. const container = caretPosition.container();
  8890. let offset = caretPosition.offset();
  8891. if (isText$3(container)) {
  8892. if (isBackwards(direction) && offset > 0) {
  8893. return CaretPosition(container, --offset);
  8894. }
  8895. if (isForwards(direction) && offset < container.length) {
  8896. return CaretPosition(container, ++offset);
  8897. }
  8898. node = container;
  8899. } else {
  8900. if (isBackwards(direction) && offset > 0) {
  8901. nextNode = nodeAtIndex(container, offset - 1);
  8902. if (isCaretCandidate(nextNode)) {
  8903. if (!isAtomic(nextNode)) {
  8904. innerNode = findNode(
  8905. nextNode,
  8906. direction,
  8907. isEditableCaretCandidate,
  8908. nextNode
  8909. );
  8910. if (innerNode) {
  8911. if (isText$3(innerNode)) {
  8912. return CaretPosition(innerNode, innerNode.data.length);
  8913. }
  8914. return CaretPosition.after(innerNode);
  8915. }
  8916. }
  8917. if (isText$3(nextNode)) {
  8918. return CaretPosition(nextNode, nextNode.data.length);
  8919. }
  8920. return CaretPosition.before(nextNode);
  8921. }
  8922. }
  8923. if (isForwards(direction) && offset < container.childNodes.length) {
  8924. nextNode = nodeAtIndex(container, offset);
  8925. if (isCaretCandidate(nextNode)) {
  8926. if (isBr$2(nextNode)) {
  8927. return moveForwardFromBr(root, nextNode);
  8928. }
  8929. if (!isAtomic(nextNode)) {
  8930. innerNode = findNode(
  8931. nextNode,
  8932. direction,
  8933. isEditableCaretCandidate,
  8934. nextNode
  8935. );
  8936. if (innerNode) {
  8937. if (isText$3(innerNode)) {
  8938. return CaretPosition(innerNode, 0);
  8939. }
  8940. return CaretPosition.before(innerNode);
  8941. }
  8942. }
  8943. if (isText$3(nextNode)) {
  8944. return CaretPosition(nextNode, 0);
  8945. }
  8946. return CaretPosition.after(nextNode);
  8947. }
  8948. }
  8949. node = nextNode ? nextNode : caretPosition.getNode();
  8950. }
  8951. if (
  8952. node &&
  8953. ((isForwards(direction) && caretPosition.isAtEnd()) ||
  8954. (isBackwards(direction) && caretPosition.isAtStart()))
  8955. ) {
  8956. node = findNode(node, direction, always, root, true);
  8957. if (isEditableCaretCandidate(node, root)) {
  8958. return getCaretCandidatePosition(direction, node);
  8959. }
  8960. }
  8961. nextNode = node
  8962. ? findNode(node, direction, isEditableCaretCandidate, root)
  8963. : node;
  8964. const rootContentEditableFalseElm = last$2(
  8965. filter$5(getParents$3(container, root), isContentEditableFalse$6)
  8966. );
  8967. if (
  8968. rootContentEditableFalseElm &&
  8969. (!nextNode || !rootContentEditableFalseElm.contains(nextNode))
  8970. ) {
  8971. if (isForwards(direction)) {
  8972. caretPosition = CaretPosition.after(rootContentEditableFalseElm);
  8973. } else {
  8974. caretPosition = CaretPosition.before(rootContentEditableFalseElm);
  8975. }
  8976. return caretPosition;
  8977. }
  8978. if (nextNode) {
  8979. return getCaretCandidatePosition(direction, nextNode);
  8980. }
  8981. return null;
  8982. };
  8983. const CaretWalker = (root) => ({
  8984. next: (caretPosition) => {
  8985. return findCaretPosition$1(HDirection.Forwards, caretPosition, root);
  8986. },
  8987. prev: (caretPosition) => {
  8988. return findCaretPosition$1(HDirection.Backwards, caretPosition, root);
  8989. },
  8990. });
  8991. const walkToPositionIn = (forward, root, start) => {
  8992. const position = forward
  8993. ? CaretPosition.before(start)
  8994. : CaretPosition.after(start);
  8995. return fromPosition(forward, root, position);
  8996. };
  8997. const afterElement = (node) =>
  8998. isBr$6(node) ? CaretPosition.before(node) : CaretPosition.after(node);
  8999. const isBeforeOrStart = (position) => {
  9000. if (CaretPosition.isTextPosition(position)) {
  9001. return position.offset() === 0;
  9002. } else {
  9003. return isCaretCandidate$3(position.getNode());
  9004. }
  9005. };
  9006. const isAfterOrEnd = (position) => {
  9007. if (CaretPosition.isTextPosition(position)) {
  9008. const container = position.container();
  9009. return position.offset() === container.data.length;
  9010. } else {
  9011. return isCaretCandidate$3(position.getNode(true));
  9012. }
  9013. };
  9014. const isBeforeAfterSameElement = (from, to) =>
  9015. !CaretPosition.isTextPosition(from) &&
  9016. !CaretPosition.isTextPosition(to) &&
  9017. from.getNode() === to.getNode(true);
  9018. const isAtBr = (position) =>
  9019. !CaretPosition.isTextPosition(position) && isBr$6(position.getNode());
  9020. const shouldSkipPosition = (forward, from, to) => {
  9021. if (forward) {
  9022. return (
  9023. !isBeforeAfterSameElement(from, to) &&
  9024. !isAtBr(from) &&
  9025. isAfterOrEnd(from) &&
  9026. isBeforeOrStart(to)
  9027. );
  9028. } else {
  9029. return (
  9030. !isBeforeAfterSameElement(to, from) &&
  9031. isBeforeOrStart(from) &&
  9032. isAfterOrEnd(to)
  9033. );
  9034. }
  9035. };
  9036. const fromPosition = (forward, root, pos) => {
  9037. const walker = CaretWalker(root);
  9038. return Optional.from(forward ? walker.next(pos) : walker.prev(pos));
  9039. };
  9040. const navigate = (forward, root, from) =>
  9041. fromPosition(forward, root, from).bind((to) => {
  9042. if (
  9043. isInSameBlock(from, to, root) &&
  9044. shouldSkipPosition(forward, from, to)
  9045. ) {
  9046. return fromPosition(forward, root, to);
  9047. } else {
  9048. return Optional.some(to);
  9049. }
  9050. });
  9051. const navigateIgnore = (forward, root, from, ignoreFilter) =>
  9052. navigate(forward, root, from).bind((pos) =>
  9053. ignoreFilter(pos)
  9054. ? navigateIgnore(forward, root, pos, ignoreFilter)
  9055. : Optional.some(pos)
  9056. );
  9057. const positionIn = (forward, element) => {
  9058. const startNode = forward ? element.firstChild : element.lastChild;
  9059. if (isText$a(startNode)) {
  9060. return Optional.some(
  9061. CaretPosition(startNode, forward ? 0 : startNode.data.length)
  9062. );
  9063. } else if (startNode) {
  9064. if (isCaretCandidate$3(startNode)) {
  9065. return Optional.some(
  9066. forward ? CaretPosition.before(startNode) : afterElement(startNode)
  9067. );
  9068. } else {
  9069. return walkToPositionIn(forward, element, startNode);
  9070. }
  9071. } else {
  9072. return Optional.none();
  9073. }
  9074. };
  9075. const nextPosition = curry(fromPosition, true);
  9076. const prevPosition = curry(fromPosition, false);
  9077. const firstPositionIn = curry(positionIn, true);
  9078. const lastPositionIn = curry(positionIn, false);
  9079. const CARET_ID = "_mce_caret";
  9080. const isCaretNode = (node) => isElement$6(node) && node.id === CARET_ID;
  9081. const getParentCaretContainer = (body, node) => {
  9082. let currentNode = node;
  9083. while (currentNode && currentNode !== body) {
  9084. if (isCaretNode(currentNode)) {
  9085. return currentNode;
  9086. }
  9087. currentNode = currentNode.parentNode;
  9088. }
  9089. return null;
  9090. };
  9091. const isStringPathBookmark = (bookmark) => isString(bookmark.start);
  9092. const isRangeBookmark = (bookmark) => has$2(bookmark, "rng");
  9093. const isIdBookmark = (bookmark) => has$2(bookmark, "id");
  9094. const isIndexBookmark = (bookmark) => has$2(bookmark, "name");
  9095. const isPathBookmark = (bookmark) => Tools.isArray(bookmark.start);
  9096. const isForwardBookmark = (bookmark) =>
  9097. !isIndexBookmark(bookmark) && isBoolean(bookmark.forward)
  9098. ? bookmark.forward
  9099. : true;
  9100. const addBogus = (dom, node) => {
  9101. if (isElement$6(node) && dom.isBlock(node) && !node.innerHTML) {
  9102. node.innerHTML = '<br data-mce-bogus="1" />';
  9103. }
  9104. return node;
  9105. };
  9106. const resolveCaretPositionBookmark = (dom, bookmark) => {
  9107. const startPos = Optional.from(resolve$1(dom.getRoot(), bookmark.start));
  9108. const endPos = Optional.from(resolve$1(dom.getRoot(), bookmark.end));
  9109. return lift2(startPos, endPos, (start, end) => {
  9110. const range = dom.createRng();
  9111. range.setStart(start.container(), start.offset());
  9112. range.setEnd(end.container(), end.offset());
  9113. return {
  9114. range,
  9115. forward: isForwardBookmark(bookmark),
  9116. };
  9117. });
  9118. };
  9119. const insertZwsp = (node, rng) => {
  9120. var _a;
  9121. const doc =
  9122. (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
  9123. const textNode = doc.createTextNode(ZWSP$1);
  9124. node.appendChild(textNode);
  9125. rng.setStart(textNode, 0);
  9126. rng.setEnd(textNode, 0);
  9127. };
  9128. const isEmpty$1 = (node) => !node.hasChildNodes();
  9129. const tryFindRangePosition = (node, rng) =>
  9130. lastPositionIn(node).fold(never, (pos) => {
  9131. rng.setStart(pos.container(), pos.offset());
  9132. rng.setEnd(pos.container(), pos.offset());
  9133. return true;
  9134. });
  9135. const padEmptyCaretContainer = (root, node, rng) => {
  9136. if (isEmpty$1(node) && getParentCaretContainer(root, node)) {
  9137. insertZwsp(node, rng);
  9138. return true;
  9139. } else {
  9140. return false;
  9141. }
  9142. };
  9143. const setEndPoint = (dom, start, bookmark, rng) => {
  9144. const point = bookmark[start ? "start" : "end"];
  9145. const root = dom.getRoot();
  9146. if (point) {
  9147. let node = root;
  9148. let offset = point[0];
  9149. for (let i = point.length - 1; node && i >= 1; i--) {
  9150. const children = node.childNodes;
  9151. if (padEmptyCaretContainer(root, node, rng)) {
  9152. return true;
  9153. }
  9154. if (point[i] > children.length - 1) {
  9155. if (padEmptyCaretContainer(root, node, rng)) {
  9156. return true;
  9157. }
  9158. return tryFindRangePosition(node, rng);
  9159. }
  9160. node = children[point[i]];
  9161. }
  9162. if (isText$a(node)) {
  9163. offset = Math.min(point[0], node.data.length);
  9164. }
  9165. if (isElement$6(node)) {
  9166. offset = Math.min(point[0], node.childNodes.length);
  9167. }
  9168. if (start) {
  9169. rng.setStart(node, offset);
  9170. } else {
  9171. rng.setEnd(node, offset);
  9172. }
  9173. }
  9174. return true;
  9175. };
  9176. const isValidTextNode = (node) => isText$a(node) && node.data.length > 0;
  9177. const restoreEndPoint = (dom, suffix, bookmark) => {
  9178. const marker = dom.get(bookmark.id + "_" + suffix);
  9179. const markerParent =
  9180. marker === null || marker === void 0 ? void 0 : marker.parentNode;
  9181. const keep = bookmark.keep;
  9182. if (marker && markerParent) {
  9183. let container;
  9184. let offset;
  9185. if (suffix === "start") {
  9186. if (!keep) {
  9187. container = markerParent;
  9188. offset = dom.nodeIndex(marker);
  9189. } else {
  9190. if (marker.hasChildNodes()) {
  9191. container = marker.firstChild;
  9192. offset = 1;
  9193. } else if (isValidTextNode(marker.nextSibling)) {
  9194. container = marker.nextSibling;
  9195. offset = 0;
  9196. } else if (isValidTextNode(marker.previousSibling)) {
  9197. container = marker.previousSibling;
  9198. offset = marker.previousSibling.data.length;
  9199. } else {
  9200. container = markerParent;
  9201. offset = dom.nodeIndex(marker) + 1;
  9202. }
  9203. }
  9204. } else {
  9205. if (!keep) {
  9206. container = markerParent;
  9207. offset = dom.nodeIndex(marker);
  9208. } else {
  9209. if (marker.hasChildNodes()) {
  9210. container = marker.firstChild;
  9211. offset = 1;
  9212. } else if (isValidTextNode(marker.previousSibling)) {
  9213. container = marker.previousSibling;
  9214. offset = marker.previousSibling.data.length;
  9215. } else {
  9216. container = markerParent;
  9217. offset = dom.nodeIndex(marker);
  9218. }
  9219. }
  9220. }
  9221. if (!keep) {
  9222. const prev = marker.previousSibling;
  9223. const next = marker.nextSibling;
  9224. Tools.each(Tools.grep(marker.childNodes), (node) => {
  9225. if (isText$a(node)) {
  9226. node.data = node.data.replace(/\uFEFF/g, "");
  9227. }
  9228. });
  9229. let otherMarker;
  9230. while ((otherMarker = dom.get(bookmark.id + "_" + suffix))) {
  9231. dom.remove(otherMarker, true);
  9232. }
  9233. if (isText$a(next) && isText$a(prev) && !Env.browser.isOpera()) {
  9234. const idx = prev.data.length;
  9235. prev.appendData(next.data);
  9236. dom.remove(next);
  9237. container = prev;
  9238. offset = idx;
  9239. }
  9240. }
  9241. return Optional.some(CaretPosition(container, offset));
  9242. } else {
  9243. return Optional.none();
  9244. }
  9245. };
  9246. const resolvePaths = (dom, bookmark) => {
  9247. const range = dom.createRng();
  9248. if (
  9249. setEndPoint(dom, true, bookmark, range) &&
  9250. setEndPoint(dom, false, bookmark, range)
  9251. ) {
  9252. return Optional.some({
  9253. range,
  9254. forward: isForwardBookmark(bookmark),
  9255. });
  9256. } else {
  9257. return Optional.none();
  9258. }
  9259. };
  9260. const resolveId = (dom, bookmark) => {
  9261. const startPos = restoreEndPoint(dom, "start", bookmark);
  9262. const endPos = restoreEndPoint(dom, "end", bookmark);
  9263. return lift2(startPos, endPos.or(startPos), (spos, epos) => {
  9264. const range = dom.createRng();
  9265. range.setStart(addBogus(dom, spos.container()), spos.offset());
  9266. range.setEnd(addBogus(dom, epos.container()), epos.offset());
  9267. return {
  9268. range,
  9269. forward: isForwardBookmark(bookmark),
  9270. };
  9271. });
  9272. };
  9273. const resolveIndex = (dom, bookmark) =>
  9274. Optional.from(dom.select(bookmark.name)[bookmark.index]).map((elm) => {
  9275. const range = dom.createRng();
  9276. range.selectNode(elm);
  9277. return {
  9278. range,
  9279. forward: true,
  9280. };
  9281. });
  9282. const resolve = (selection, bookmark) => {
  9283. const dom = selection.dom;
  9284. if (bookmark) {
  9285. if (isPathBookmark(bookmark)) {
  9286. return resolvePaths(dom, bookmark);
  9287. } else if (isStringPathBookmark(bookmark)) {
  9288. return resolveCaretPositionBookmark(dom, bookmark);
  9289. } else if (isIdBookmark(bookmark)) {
  9290. return resolveId(dom, bookmark);
  9291. } else if (isIndexBookmark(bookmark)) {
  9292. return resolveIndex(dom, bookmark);
  9293. } else if (isRangeBookmark(bookmark)) {
  9294. return Optional.some({
  9295. range: bookmark.rng,
  9296. forward: isForwardBookmark(bookmark),
  9297. });
  9298. }
  9299. }
  9300. return Optional.none();
  9301. };
  9302. const getBookmark$1 = (selection, type, normalized) => {
  9303. return getBookmark$2(selection, type, normalized);
  9304. };
  9305. const moveToBookmark = (selection, bookmark) => {
  9306. resolve(selection, bookmark).each(({ range, forward }) => {
  9307. selection.setRng(range, forward);
  9308. });
  9309. };
  9310. const isBookmarkNode$1 = (node) => {
  9311. return (
  9312. isElement$6(node) &&
  9313. node.tagName === "SPAN" &&
  9314. node.getAttribute("data-mce-type") === "bookmark"
  9315. );
  9316. };
  9317. const is = (expected) => (actual) => expected === actual;
  9318. const isNbsp = is(nbsp);
  9319. const isWhiteSpace = (chr) =>
  9320. chr !== "" && " \f\n\r\t\x0B".indexOf(chr) !== -1;
  9321. const isContent = (chr) =>
  9322. !isWhiteSpace(chr) && !isNbsp(chr) && !isZwsp$2(chr);
  9323. const hexColour = (value) => ({ value: normalizeHex(value) });
  9324. const normalizeHex = (hex) => removeLeading(hex, "#").toUpperCase();
  9325. const toHex = (component) => {
  9326. const hex = component.toString(16);
  9327. return (hex.length === 1 ? "0" + hex : hex).toUpperCase();
  9328. };
  9329. const fromRgba = (rgbaColour) => {
  9330. const value =
  9331. toHex(rgbaColour.red) + toHex(rgbaColour.green) + toHex(rgbaColour.blue);
  9332. return hexColour(value);
  9333. };
  9334. const rgbRegex = /^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$/i;
  9335. const rgbaRegex =
  9336. /^\s*rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d?(?:\.\d+)?)\s*\)\s*$/i;
  9337. const rgbaColour = (red, green, blue, alpha) => ({
  9338. red,
  9339. green,
  9340. blue,
  9341. alpha,
  9342. });
  9343. const fromStringValues = (red, green, blue, alpha) => {
  9344. const r = parseInt(red, 10);
  9345. const g = parseInt(green, 10);
  9346. const b = parseInt(blue, 10);
  9347. const a = parseFloat(alpha);
  9348. return rgbaColour(r, g, b, a);
  9349. };
  9350. const fromString = (rgbaString) => {
  9351. if (rgbaString === "transparent") {
  9352. return Optional.some(rgbaColour(0, 0, 0, 0));
  9353. }
  9354. const rgbMatch = rgbRegex.exec(rgbaString);
  9355. if (rgbMatch !== null) {
  9356. return Optional.some(
  9357. fromStringValues(rgbMatch[1], rgbMatch[2], rgbMatch[3], "1")
  9358. );
  9359. }
  9360. const rgbaMatch = rgbaRegex.exec(rgbaString);
  9361. if (rgbaMatch !== null) {
  9362. return Optional.some(
  9363. fromStringValues(rgbaMatch[1], rgbaMatch[2], rgbaMatch[3], rgbaMatch[4])
  9364. );
  9365. }
  9366. return Optional.none();
  9367. };
  9368. const rgbaToHexString = (color) =>
  9369. fromString(color)
  9370. .map(fromRgba)
  9371. .map((h) => "#" + h.value)
  9372. .getOr(color);
  9373. const getRanges$1 = (selection) => {
  9374. const ranges = [];
  9375. if (selection) {
  9376. for (let i = 0; i < selection.rangeCount; i++) {
  9377. ranges.push(selection.getRangeAt(i));
  9378. }
  9379. }
  9380. return ranges;
  9381. };
  9382. const getSelectedNodes = (ranges) => {
  9383. return bind$3(ranges, (range) => {
  9384. const node = getSelectedNode(range);
  9385. return node ? [SugarElement.fromDom(node)] : [];
  9386. });
  9387. };
  9388. const hasMultipleRanges = (selection) => {
  9389. return getRanges$1(selection).length > 1;
  9390. };
  9391. const getCellsFromRanges = (ranges) =>
  9392. filter$5(getSelectedNodes(ranges), isTableCell$2);
  9393. const getCellsFromElement = (elm) =>
  9394. descendants(elm, "td[data-mce-selected],th[data-mce-selected]");
  9395. const getCellsFromElementOrRanges = (ranges, element) => {
  9396. const selectedCells = getCellsFromElement(element);
  9397. return selectedCells.length > 0
  9398. ? selectedCells
  9399. : getCellsFromRanges(ranges);
  9400. };
  9401. const getCellsFromEditor = (editor) =>
  9402. getCellsFromElementOrRanges(
  9403. getRanges$1(editor.selection.getSel()),
  9404. SugarElement.fromDom(editor.getBody())
  9405. );
  9406. const getClosestTable = (cell, isRoot) => ancestor$3(cell, "table", isRoot);
  9407. const getStartNode = (rng) => {
  9408. const sc = rng.startContainer,
  9409. so = rng.startOffset;
  9410. if (isText$a(sc)) {
  9411. return so === 0
  9412. ? Optional.some(SugarElement.fromDom(sc))
  9413. : Optional.none();
  9414. } else {
  9415. return Optional.from(sc.childNodes[so]).map(SugarElement.fromDom);
  9416. }
  9417. };
  9418. const getEndNode = (rng) => {
  9419. const ec = rng.endContainer,
  9420. eo = rng.endOffset;
  9421. if (isText$a(ec)) {
  9422. return eo === ec.data.length
  9423. ? Optional.some(SugarElement.fromDom(ec))
  9424. : Optional.none();
  9425. } else {
  9426. return Optional.from(ec.childNodes[eo - 1]).map(SugarElement.fromDom);
  9427. }
  9428. };
  9429. const getFirstChildren = (node) => {
  9430. return firstChild(node).fold(constant([node]), (child) => {
  9431. return [node].concat(getFirstChildren(child));
  9432. });
  9433. };
  9434. const getLastChildren = (node) => {
  9435. return lastChild(node).fold(constant([node]), (child) => {
  9436. if (name(child) === "br") {
  9437. return prevSibling(child)
  9438. .map((sibling) => {
  9439. return [node].concat(getLastChildren(sibling));
  9440. })
  9441. .getOr([]);
  9442. } else {
  9443. return [node].concat(getLastChildren(child));
  9444. }
  9445. });
  9446. };
  9447. const hasAllContentsSelected = (elm, rng) => {
  9448. return lift2(getStartNode(rng), getEndNode(rng), (startNode, endNode) => {
  9449. const start = find$2(getFirstChildren(elm), curry(eq, startNode));
  9450. const end = find$2(getLastChildren(elm), curry(eq, endNode));
  9451. return start.isSome() && end.isSome();
  9452. }).getOr(false);
  9453. };
  9454. const moveEndPoint = (dom, rng, node, start) => {
  9455. const root = node;
  9456. const walker = new DomTreeWalker(node, root);
  9457. const moveCaretBeforeOnEnterElementsMap = filter$4(
  9458. dom.schema.getMoveCaretBeforeOnEnterElements(),
  9459. (_, name) => !contains$2(["td", "th", "table"], name.toLowerCase())
  9460. );
  9461. let currentNode = node;
  9462. do {
  9463. if (isText$a(currentNode) && Tools.trim(currentNode.data).length !== 0) {
  9464. if (start) {
  9465. rng.setStart(currentNode, 0);
  9466. } else {
  9467. rng.setEnd(currentNode, currentNode.data.length);
  9468. }
  9469. return;
  9470. }
  9471. if (moveCaretBeforeOnEnterElementsMap[currentNode.nodeName]) {
  9472. if (start) {
  9473. rng.setStartBefore(currentNode);
  9474. } else {
  9475. if (currentNode.nodeName === "BR") {
  9476. rng.setEndBefore(currentNode);
  9477. } else {
  9478. rng.setEndAfter(currentNode);
  9479. }
  9480. }
  9481. return;
  9482. }
  9483. } while ((currentNode = start ? walker.next() : walker.prev()));
  9484. if (root.nodeName === "BODY") {
  9485. if (start) {
  9486. rng.setStart(root, 0);
  9487. } else {
  9488. rng.setEnd(root, root.childNodes.length);
  9489. }
  9490. }
  9491. };
  9492. const hasAnyRanges = (editor) => {
  9493. const sel = editor.selection.getSel();
  9494. return isNonNullable(sel) && sel.rangeCount > 0;
  9495. };
  9496. const runOnRanges = (editor, executor) => {
  9497. const fakeSelectionNodes = getCellsFromEditor(editor);
  9498. if (fakeSelectionNodes.length > 0) {
  9499. each$e(fakeSelectionNodes, (elem) => {
  9500. const node = elem.dom;
  9501. const fakeNodeRng = editor.dom.createRng();
  9502. fakeNodeRng.setStartBefore(node);
  9503. fakeNodeRng.setEndAfter(node);
  9504. executor(fakeNodeRng, true);
  9505. });
  9506. } else {
  9507. executor(editor.selection.getRng(), false);
  9508. }
  9509. };
  9510. const preserve = (selection, fillBookmark, executor) => {
  9511. const bookmark = getPersistentBookmark(selection, fillBookmark);
  9512. executor(bookmark);
  9513. selection.moveToBookmark(bookmark);
  9514. };
  9515. const isNode = (node) =>
  9516. isNumber(node === null || node === void 0 ? void 0 : node.nodeType);
  9517. const isElementNode$1 = (node) =>
  9518. isElement$6(node) &&
  9519. !isBookmarkNode$1(node) &&
  9520. !isCaretNode(node) &&
  9521. !isBogus$2(node);
  9522. const isElementDirectlySelected = (dom, node) => {
  9523. if (isElementNode$1(node) && !/^(TD|TH)$/.test(node.nodeName)) {
  9524. const selectedAttr = dom.getAttrib(node, "data-mce-selected");
  9525. const value = parseInt(selectedAttr, 10);
  9526. return !isNaN(value) && value > 0;
  9527. } else {
  9528. return false;
  9529. }
  9530. };
  9531. const isEditable$2 = (elm) => elm.isContentEditable === true;
  9532. const preserveSelection = (editor, action, shouldMoveStart) => {
  9533. const { selection, dom } = editor;
  9534. const selectedNodeBeforeAction = selection.getNode();
  9535. const isSelectedBeforeNodeNoneditable = isContentEditableFalse$b(
  9536. selectedNodeBeforeAction
  9537. );
  9538. preserve(selection, true, () => {
  9539. action();
  9540. });
  9541. const isBeforeNodeStillNoneditable =
  9542. isSelectedBeforeNodeNoneditable &&
  9543. isContentEditableFalse$b(selectedNodeBeforeAction);
  9544. if (
  9545. isBeforeNodeStillNoneditable &&
  9546. dom.isChildOf(selectedNodeBeforeAction, editor.getBody())
  9547. ) {
  9548. editor.selection.select(selectedNodeBeforeAction);
  9549. } else if (shouldMoveStart(selection.getStart())) {
  9550. moveStartToNearestText(dom, selection);
  9551. }
  9552. };
  9553. const moveStartToNearestText = (dom, selection) => {
  9554. var _a, _b;
  9555. const rng = selection.getRng();
  9556. const { startContainer, startOffset } = rng;
  9557. const selectedNode = selection.getNode();
  9558. if (isElementDirectlySelected(dom, selectedNode)) {
  9559. return;
  9560. }
  9561. if (isElement$6(startContainer)) {
  9562. const nodes = startContainer.childNodes;
  9563. const root = dom.getRoot();
  9564. let walker;
  9565. if (startOffset < nodes.length) {
  9566. const startNode = nodes[startOffset];
  9567. walker = new DomTreeWalker(
  9568. startNode,
  9569. (_a = dom.getParent(startNode, dom.isBlock)) !== null && _a !== void 0
  9570. ? _a
  9571. : root
  9572. );
  9573. } else {
  9574. const startNode = nodes[nodes.length - 1];
  9575. walker = new DomTreeWalker(
  9576. startNode,
  9577. (_b = dom.getParent(startNode, dom.isBlock)) !== null && _b !== void 0
  9578. ? _b
  9579. : root
  9580. );
  9581. walker.next(true);
  9582. }
  9583. for (let node = walker.current(); node; node = walker.next()) {
  9584. if (dom.getContentEditable(node) === "false") {
  9585. return;
  9586. } else if (isText$a(node) && !isWhiteSpaceNode$1(node)) {
  9587. rng.setStart(node, 0);
  9588. selection.setRng(rng);
  9589. return;
  9590. }
  9591. }
  9592. }
  9593. };
  9594. const getNonWhiteSpaceSibling = (node, next, inc) => {
  9595. if (node) {
  9596. const nextName = next ? "nextSibling" : "previousSibling";
  9597. for (node = inc ? node : node[nextName]; node; node = node[nextName]) {
  9598. if (isElement$6(node) || !isWhiteSpaceNode$1(node)) {
  9599. return node;
  9600. }
  9601. }
  9602. }
  9603. return undefined;
  9604. };
  9605. const isTextBlock$1 = (schema, node) =>
  9606. !!schema.getTextBlockElements()[node.nodeName.toLowerCase()] ||
  9607. isTransparentBlock(schema, node);
  9608. const isValid = (ed, parent, child) => {
  9609. return ed.schema.isValidChild(parent, child);
  9610. };
  9611. const isWhiteSpaceNode$1 = (node, allowSpaces = false) => {
  9612. if (isNonNullable(node) && isText$a(node)) {
  9613. const data = allowSpaces ? node.data.replace(/ /g, "\xA0") : node.data;
  9614. return isWhitespaceText(data);
  9615. } else {
  9616. return false;
  9617. }
  9618. };
  9619. const isEmptyTextNode$1 = (node) => {
  9620. return isNonNullable(node) && isText$a(node) && node.length === 0;
  9621. };
  9622. const isWrapNoneditableTarget = (editor, node) => {
  9623. const baseDataSelector = "[data-mce-cef-wrappable]";
  9624. const formatNoneditableSelector = getFormatNoneditableSelector(editor);
  9625. const selector = isEmpty$3(formatNoneditableSelector)
  9626. ? baseDataSelector
  9627. : `${baseDataSelector},${formatNoneditableSelector}`;
  9628. return is$1(SugarElement.fromDom(node), selector);
  9629. };
  9630. const isWrappableNoneditable = (editor, node) => {
  9631. const dom = editor.dom;
  9632. return (
  9633. isElementNode$1(node) &&
  9634. dom.getContentEditable(node) === "false" &&
  9635. isWrapNoneditableTarget(editor, node) &&
  9636. dom.select('[contenteditable="true"]', node).length === 0
  9637. );
  9638. };
  9639. const replaceVars = (value, vars) => {
  9640. if (isFunction(value)) {
  9641. return value(vars);
  9642. } else if (isNonNullable(vars)) {
  9643. value = value.replace(/%(\w+)/g, (str, name) => {
  9644. return vars[name] || str;
  9645. });
  9646. }
  9647. return value;
  9648. };
  9649. const isEq$5 = (str1, str2) => {
  9650. str1 = str1 || "";
  9651. str2 = str2 || "";
  9652. str1 = "" + (str1.nodeName || str1);
  9653. str2 = "" + (str2.nodeName || str2);
  9654. return str1.toLowerCase() === str2.toLowerCase();
  9655. };
  9656. const normalizeStyleValue = (value, name) => {
  9657. if (isNullable(value)) {
  9658. return null;
  9659. } else {
  9660. let strValue = String(value);
  9661. if (name === "color" || name === "backgroundColor") {
  9662. strValue = rgbaToHexString(strValue);
  9663. }
  9664. if (name === "fontWeight" && value === 700) {
  9665. strValue = "bold";
  9666. }
  9667. if (name === "fontFamily") {
  9668. strValue = strValue.replace(/[\'\"]/g, "").replace(/,\s+/g, ",");
  9669. }
  9670. return strValue;
  9671. }
  9672. };
  9673. const getStyle = (dom, node, name) => {
  9674. const style = dom.getStyle(node, name);
  9675. return normalizeStyleValue(style, name);
  9676. };
  9677. const getTextDecoration = (dom, node) => {
  9678. let decoration;
  9679. dom.getParent(node, (n) => {
  9680. if (isElement$6(n)) {
  9681. decoration = dom.getStyle(n, "text-decoration");
  9682. return !!decoration && decoration !== "none";
  9683. } else {
  9684. return false;
  9685. }
  9686. });
  9687. return decoration;
  9688. };
  9689. const getParents$2 = (dom, node, selector) => {
  9690. return dom.getParents(node, selector, dom.getRoot());
  9691. };
  9692. const isFormatPredicate = (editor, formatName, predicate) => {
  9693. const formats = editor.formatter.get(formatName);
  9694. return isNonNullable(formats) && exists(formats, predicate);
  9695. };
  9696. const isVariableFormatName = (editor, formatName) => {
  9697. const hasVariableValues = (format) => {
  9698. const isVariableValue = (val) =>
  9699. isFunction(val) || (val.length > 1 && val.charAt(0) === "%");
  9700. return exists(["styles", "attributes"], (key) =>
  9701. get$a(format, key).exists((field) => {
  9702. const fieldValues = isArray$1(field) ? field : values(field);
  9703. return exists(fieldValues, isVariableValue);
  9704. })
  9705. );
  9706. };
  9707. return isFormatPredicate(editor, formatName, hasVariableValues);
  9708. };
  9709. const areSimilarFormats = (editor, formatName, otherFormatName) => {
  9710. const validKeys = [
  9711. "inline",
  9712. "block",
  9713. "selector",
  9714. "attributes",
  9715. "styles",
  9716. "classes",
  9717. ];
  9718. const filterObj = (format) =>
  9719. filter$4(format, (_, key) =>
  9720. exists(validKeys, (validKey) => validKey === key)
  9721. );
  9722. return isFormatPredicate(editor, formatName, (fmt1) => {
  9723. const filteredFmt1 = filterObj(fmt1);
  9724. return isFormatPredicate(editor, otherFormatName, (fmt2) => {
  9725. const filteredFmt2 = filterObj(fmt2);
  9726. return equal$1(filteredFmt1, filteredFmt2);
  9727. });
  9728. });
  9729. };
  9730. const isBlockFormat = (format) => hasNonNullableKey(format, "block");
  9731. const isWrappingBlockFormat = (format) =>
  9732. isBlockFormat(format) && format.wrapper === true;
  9733. const isNonWrappingBlockFormat = (format) =>
  9734. isBlockFormat(format) && format.wrapper !== true;
  9735. const isSelectorFormat = (format) => hasNonNullableKey(format, "selector");
  9736. const isInlineFormat = (format) => hasNonNullableKey(format, "inline");
  9737. const isMixedFormat = (format) =>
  9738. isSelectorFormat(format) &&
  9739. isInlineFormat(format) &&
  9740. is$2(get$a(format, "mixed"), true);
  9741. const shouldExpandToSelector = (format) =>
  9742. isSelectorFormat(format) &&
  9743. format.expand !== false &&
  9744. !isInlineFormat(format);
  9745. const isBookmarkNode = isBookmarkNode$1;
  9746. const getParents$1 = getParents$2;
  9747. const isWhiteSpaceNode = isWhiteSpaceNode$1;
  9748. const isTextBlock = isTextBlock$1;
  9749. const isBogusBr = (node) => {
  9750. return (
  9751. isBr$6(node) && node.getAttribute("data-mce-bogus") && !node.nextSibling
  9752. );
  9753. };
  9754. const findParentContentEditable = (dom, node) => {
  9755. let parent = node;
  9756. while (parent) {
  9757. if (isElement$6(parent) && dom.getContentEditable(parent)) {
  9758. return dom.getContentEditable(parent) === "false" ? parent : node;
  9759. }
  9760. parent = parent.parentNode;
  9761. }
  9762. return node;
  9763. };
  9764. const walkText = (start, node, offset, predicate) => {
  9765. const str = node.data;
  9766. if (start) {
  9767. for (let i = offset; i > 0; i--) {
  9768. if (predicate(str.charAt(i - 1))) {
  9769. return i;
  9770. }
  9771. }
  9772. } else {
  9773. for (let i = offset; i < str.length; i++) {
  9774. if (predicate(str.charAt(i))) {
  9775. return i;
  9776. }
  9777. }
  9778. }
  9779. return -1;
  9780. };
  9781. const findSpace = (start, node, offset) =>
  9782. walkText(start, node, offset, (c) => isNbsp(c) || isWhiteSpace(c));
  9783. const findContent = (start, node, offset) =>
  9784. walkText(start, node, offset, isContent);
  9785. const findWordEndPoint = (
  9786. dom,
  9787. body,
  9788. container,
  9789. offset,
  9790. start,
  9791. includeTrailingSpaces
  9792. ) => {
  9793. let lastTextNode;
  9794. const rootNode = dom.getParent(container, dom.isBlock) || body;
  9795. const walk = (container, offset, pred) => {
  9796. const textSeeker = TextSeeker(dom);
  9797. const walker = start ? textSeeker.backwards : textSeeker.forwards;
  9798. return Optional.from(
  9799. walker(
  9800. container,
  9801. offset,
  9802. (text, textOffset) => {
  9803. if (isBookmarkNode(text.parentNode)) {
  9804. return -1;
  9805. } else {
  9806. lastTextNode = text;
  9807. return pred(start, text, textOffset);
  9808. }
  9809. },
  9810. rootNode
  9811. )
  9812. );
  9813. };
  9814. const spaceResult = walk(container, offset, findSpace);
  9815. return spaceResult
  9816. .bind((result) =>
  9817. includeTrailingSpaces
  9818. ? walk(
  9819. result.container,
  9820. result.offset + (start ? -1 : 0),
  9821. findContent
  9822. )
  9823. : Optional.some(result)
  9824. )
  9825. .orThunk(() =>
  9826. lastTextNode
  9827. ? Optional.some({
  9828. container: lastTextNode,
  9829. offset: start ? 0 : lastTextNode.length,
  9830. })
  9831. : Optional.none()
  9832. );
  9833. };
  9834. const findSelectorEndPoint = (
  9835. dom,
  9836. formatList,
  9837. rng,
  9838. container,
  9839. siblingName
  9840. ) => {
  9841. const sibling = container[siblingName];
  9842. if (isText$a(container) && isEmpty$3(container.data) && sibling) {
  9843. container = sibling;
  9844. }
  9845. const parents = getParents$1(dom, container);
  9846. for (let i = 0; i < parents.length; i++) {
  9847. for (let y = 0; y < formatList.length; y++) {
  9848. const curFormat = formatList[y];
  9849. if (
  9850. isNonNullable(curFormat.collapsed) &&
  9851. curFormat.collapsed !== rng.collapsed
  9852. ) {
  9853. continue;
  9854. }
  9855. if (
  9856. isSelectorFormat(curFormat) &&
  9857. dom.is(parents[i], curFormat.selector)
  9858. ) {
  9859. return parents[i];
  9860. }
  9861. }
  9862. }
  9863. return container;
  9864. };
  9865. const findBlockEndPoint = (dom, formatList, container, siblingName) => {
  9866. var _a;
  9867. let node = container;
  9868. const root = dom.getRoot();
  9869. const format = formatList[0];
  9870. if (isBlockFormat(format)) {
  9871. node = format.wrapper
  9872. ? null
  9873. : dom.getParent(container, format.block, root);
  9874. }
  9875. if (!node) {
  9876. const scopeRoot =
  9877. (_a = dom.getParent(container, "LI,TD,TH")) !== null && _a !== void 0
  9878. ? _a
  9879. : root;
  9880. node = dom.getParent(
  9881. isText$a(container) ? container.parentNode : container,
  9882. (node) => node !== root && isTextBlock(dom.schema, node),
  9883. scopeRoot
  9884. );
  9885. }
  9886. if (node && isBlockFormat(format) && format.wrapper) {
  9887. node = getParents$1(dom, node, "ul,ol").reverse()[0] || node;
  9888. }
  9889. if (!node) {
  9890. node = container;
  9891. while (node && node[siblingName] && !dom.isBlock(node[siblingName])) {
  9892. node = node[siblingName];
  9893. if (isEq$5(node, "br")) {
  9894. break;
  9895. }
  9896. }
  9897. }
  9898. return node || container;
  9899. };
  9900. const isAtBlockBoundary$1 = (dom, root, container, siblingName) => {
  9901. const parent = container.parentNode;
  9902. if (isNonNullable(container[siblingName])) {
  9903. return false;
  9904. } else if (parent === root || isNullable(parent) || dom.isBlock(parent)) {
  9905. return true;
  9906. } else {
  9907. return isAtBlockBoundary$1(dom, root, parent, siblingName);
  9908. }
  9909. };
  9910. const findParentContainer = (dom, formatList, container, offset, start) => {
  9911. let parent = container;
  9912. const siblingName = start ? "previousSibling" : "nextSibling";
  9913. const root = dom.getRoot();
  9914. if (isText$a(container) && !isWhiteSpaceNode(container)) {
  9915. if (start ? offset > 0 : offset < container.data.length) {
  9916. return container;
  9917. }
  9918. }
  9919. while (parent) {
  9920. if (!formatList[0].block_expand && dom.isBlock(parent)) {
  9921. return parent;
  9922. }
  9923. for (
  9924. let sibling = parent[siblingName];
  9925. sibling;
  9926. sibling = sibling[siblingName]
  9927. ) {
  9928. const allowSpaces =
  9929. isText$a(sibling) &&
  9930. !isAtBlockBoundary$1(dom, root, sibling, siblingName);
  9931. if (
  9932. !isBookmarkNode(sibling) &&
  9933. !isBogusBr(sibling) &&
  9934. !isWhiteSpaceNode(sibling, allowSpaces)
  9935. ) {
  9936. return parent;
  9937. }
  9938. }
  9939. if (parent === root || parent.parentNode === root) {
  9940. container = parent;
  9941. break;
  9942. }
  9943. parent = parent.parentNode;
  9944. }
  9945. return container;
  9946. };
  9947. const isSelfOrParentBookmark = (container) =>
  9948. isBookmarkNode(container.parentNode) || isBookmarkNode(container);
  9949. const expandRng = (dom, rng, formatList, includeTrailingSpace = false) => {
  9950. let { startContainer, startOffset, endContainer, endOffset } = rng;
  9951. const format = formatList[0];
  9952. if (isElement$6(startContainer) && startContainer.hasChildNodes()) {
  9953. startContainer = getNode$1(startContainer, startOffset);
  9954. if (isText$a(startContainer)) {
  9955. startOffset = 0;
  9956. }
  9957. }
  9958. if (isElement$6(endContainer) && endContainer.hasChildNodes()) {
  9959. endContainer = getNode$1(
  9960. endContainer,
  9961. rng.collapsed ? endOffset : endOffset - 1
  9962. );
  9963. if (isText$a(endContainer)) {
  9964. endOffset = endContainer.data.length;
  9965. }
  9966. }
  9967. startContainer = findParentContentEditable(dom, startContainer);
  9968. endContainer = findParentContentEditable(dom, endContainer);
  9969. if (isSelfOrParentBookmark(startContainer)) {
  9970. startContainer = isBookmarkNode(startContainer)
  9971. ? startContainer
  9972. : startContainer.parentNode;
  9973. if (rng.collapsed) {
  9974. startContainer = startContainer.previousSibling || startContainer;
  9975. } else {
  9976. startContainer = startContainer.nextSibling || startContainer;
  9977. }
  9978. if (isText$a(startContainer)) {
  9979. startOffset = rng.collapsed ? startContainer.length : 0;
  9980. }
  9981. }
  9982. if (isSelfOrParentBookmark(endContainer)) {
  9983. endContainer = isBookmarkNode(endContainer)
  9984. ? endContainer
  9985. : endContainer.parentNode;
  9986. if (rng.collapsed) {
  9987. endContainer = endContainer.nextSibling || endContainer;
  9988. } else {
  9989. endContainer = endContainer.previousSibling || endContainer;
  9990. }
  9991. if (isText$a(endContainer)) {
  9992. endOffset = rng.collapsed ? 0 : endContainer.length;
  9993. }
  9994. }
  9995. if (rng.collapsed) {
  9996. const startPoint = findWordEndPoint(
  9997. dom,
  9998. dom.getRoot(),
  9999. startContainer,
  10000. startOffset,
  10001. true,
  10002. includeTrailingSpace
  10003. );
  10004. startPoint.each(({ container, offset }) => {
  10005. startContainer = container;
  10006. startOffset = offset;
  10007. });
  10008. const endPoint = findWordEndPoint(
  10009. dom,
  10010. dom.getRoot(),
  10011. endContainer,
  10012. endOffset,
  10013. false,
  10014. includeTrailingSpace
  10015. );
  10016. endPoint.each(({ container, offset }) => {
  10017. endContainer = container;
  10018. endOffset = offset;
  10019. });
  10020. }
  10021. if (isInlineFormat(format) || format.block_expand) {
  10022. if (
  10023. !isInlineFormat(format) ||
  10024. !isText$a(startContainer) ||
  10025. startOffset === 0
  10026. ) {
  10027. startContainer = findParentContainer(
  10028. dom,
  10029. formatList,
  10030. startContainer,
  10031. startOffset,
  10032. true
  10033. );
  10034. }
  10035. if (
  10036. !isInlineFormat(format) ||
  10037. !isText$a(endContainer) ||
  10038. endOffset === endContainer.data.length
  10039. ) {
  10040. endContainer = findParentContainer(
  10041. dom,
  10042. formatList,
  10043. endContainer,
  10044. endOffset,
  10045. false
  10046. );
  10047. }
  10048. }
  10049. if (shouldExpandToSelector(format)) {
  10050. startContainer = findSelectorEndPoint(
  10051. dom,
  10052. formatList,
  10053. rng,
  10054. startContainer,
  10055. "previousSibling"
  10056. );
  10057. endContainer = findSelectorEndPoint(
  10058. dom,
  10059. formatList,
  10060. rng,
  10061. endContainer,
  10062. "nextSibling"
  10063. );
  10064. }
  10065. if (isBlockFormat(format) || isSelectorFormat(format)) {
  10066. startContainer = findBlockEndPoint(
  10067. dom,
  10068. formatList,
  10069. startContainer,
  10070. "previousSibling"
  10071. );
  10072. endContainer = findBlockEndPoint(
  10073. dom,
  10074. formatList,
  10075. endContainer,
  10076. "nextSibling"
  10077. );
  10078. if (isBlockFormat(format)) {
  10079. if (!dom.isBlock(startContainer)) {
  10080. startContainer = findParentContainer(
  10081. dom,
  10082. formatList,
  10083. startContainer,
  10084. startOffset,
  10085. true
  10086. );
  10087. }
  10088. if (!dom.isBlock(endContainer)) {
  10089. endContainer = findParentContainer(
  10090. dom,
  10091. formatList,
  10092. endContainer,
  10093. endOffset,
  10094. false
  10095. );
  10096. }
  10097. }
  10098. }
  10099. if (isElement$6(startContainer) && startContainer.parentNode) {
  10100. startOffset = dom.nodeIndex(startContainer);
  10101. startContainer = startContainer.parentNode;
  10102. }
  10103. if (isElement$6(endContainer) && endContainer.parentNode) {
  10104. endOffset = dom.nodeIndex(endContainer) + 1;
  10105. endContainer = endContainer.parentNode;
  10106. }
  10107. return {
  10108. startContainer,
  10109. startOffset,
  10110. endContainer,
  10111. endOffset,
  10112. };
  10113. };
  10114. const walk$3 = (dom, rng, callback) => {
  10115. var _a;
  10116. const startOffset = rng.startOffset;
  10117. const startContainer = getNode$1(rng.startContainer, startOffset);
  10118. const endOffset = rng.endOffset;
  10119. const endContainer = getNode$1(rng.endContainer, endOffset - 1);
  10120. const exclude = (nodes) => {
  10121. const firstNode = nodes[0];
  10122. if (
  10123. isText$a(firstNode) &&
  10124. firstNode === startContainer &&
  10125. startOffset >= firstNode.data.length
  10126. ) {
  10127. nodes.splice(0, 1);
  10128. }
  10129. const lastNode = nodes[nodes.length - 1];
  10130. if (
  10131. endOffset === 0 &&
  10132. nodes.length > 0 &&
  10133. lastNode === endContainer &&
  10134. isText$a(lastNode)
  10135. ) {
  10136. nodes.splice(nodes.length - 1, 1);
  10137. }
  10138. return nodes;
  10139. };
  10140. const collectSiblings = (node, name, endNode) => {
  10141. const siblings = [];
  10142. for (; node && node !== endNode; node = node[name]) {
  10143. siblings.push(node);
  10144. }
  10145. return siblings;
  10146. };
  10147. const findEndPoint = (node, root) =>
  10148. dom.getParent(node, (node) => node.parentNode === root, root);
  10149. const walkBoundary = (startNode, endNode, next) => {
  10150. const siblingName = next ? "nextSibling" : "previousSibling";
  10151. for (
  10152. let node = startNode, parent = node.parentNode;
  10153. node && node !== endNode;
  10154. node = parent
  10155. ) {
  10156. parent = node.parentNode;
  10157. const siblings = collectSiblings(
  10158. node === startNode ? node : node[siblingName],
  10159. siblingName
  10160. );
  10161. if (siblings.length) {
  10162. if (!next) {
  10163. siblings.reverse();
  10164. }
  10165. callback(exclude(siblings));
  10166. }
  10167. }
  10168. };
  10169. if (startContainer === endContainer) {
  10170. return callback(exclude([startContainer]));
  10171. }
  10172. const ancestor =
  10173. (_a = dom.findCommonAncestor(startContainer, endContainer)) !== null &&
  10174. _a !== void 0
  10175. ? _a
  10176. : dom.getRoot();
  10177. if (dom.isChildOf(startContainer, endContainer)) {
  10178. return walkBoundary(startContainer, ancestor, true);
  10179. }
  10180. if (dom.isChildOf(endContainer, startContainer)) {
  10181. return walkBoundary(endContainer, ancestor);
  10182. }
  10183. const startPoint = findEndPoint(startContainer, ancestor) || startContainer;
  10184. const endPoint = findEndPoint(endContainer, ancestor) || endContainer;
  10185. walkBoundary(startContainer, startPoint, true);
  10186. const siblings = collectSiblings(
  10187. startPoint === startContainer ? startPoint : startPoint.nextSibling,
  10188. "nextSibling",
  10189. endPoint === endContainer ? endPoint.nextSibling : endPoint
  10190. );
  10191. if (siblings.length) {
  10192. callback(exclude(siblings));
  10193. }
  10194. walkBoundary(endContainer, endPoint);
  10195. };
  10196. const validBlocks = [
  10197. 'pre[class*=language-][contenteditable="false"]',
  10198. "figure.image",
  10199. "div[data-ephox-embed-iri]",
  10200. "div.tiny-pageembed",
  10201. "div.mce-toc",
  10202. "div[data-mce-toc]",
  10203. ];
  10204. const isZeroWidth = (elem) => isText$b(elem) && get$3(elem) === ZWSP$1;
  10205. const context = (editor, elem, wrapName, nodeName) =>
  10206. parent(elem).fold(
  10207. () => "skipping",
  10208. (parent) => {
  10209. if (nodeName === "br" || isZeroWidth(elem)) {
  10210. return "valid";
  10211. } else if (isAnnotation(elem)) {
  10212. return "existing";
  10213. } else if (isCaretNode(elem.dom)) {
  10214. return "caret";
  10215. } else if (exists(validBlocks, (selector) => is$1(elem, selector))) {
  10216. return "valid-block";
  10217. } else if (
  10218. !isValid(editor, wrapName, nodeName) ||
  10219. !isValid(editor, name(parent), wrapName)
  10220. ) {
  10221. return "invalid-child";
  10222. } else {
  10223. return "valid";
  10224. }
  10225. }
  10226. );
  10227. const applyWordGrab = (editor, rng) => {
  10228. const r = expandRng(editor.dom, rng, [{ inline: "span" }]);
  10229. rng.setStart(r.startContainer, r.startOffset);
  10230. rng.setEnd(r.endContainer, r.endOffset);
  10231. editor.selection.setRng(rng);
  10232. };
  10233. const applyAnnotation = (
  10234. elem,
  10235. masterUId,
  10236. data,
  10237. annotationName,
  10238. decorate,
  10239. directAnnotation
  10240. ) => {
  10241. const { uid = masterUId, ...otherData } = data;
  10242. add$2(elem, annotation());
  10243. set$3(elem, `${dataAnnotationId()}`, uid);
  10244. set$3(elem, `${dataAnnotation()}`, annotationName);
  10245. const { attributes = {}, classes = [] } = decorate(uid, otherData);
  10246. setAll$1(elem, attributes);
  10247. add(elem, classes);
  10248. if (directAnnotation) {
  10249. if (classes.length > 0) {
  10250. set$3(elem, `${dataAnnotationClasses()}`, classes.join(","));
  10251. }
  10252. const attributeNames = keys(attributes);
  10253. if (attributeNames.length > 0) {
  10254. set$3(elem, `${dataAnnotationAttributes()}`, attributeNames.join(","));
  10255. }
  10256. }
  10257. };
  10258. const removeDirectAnnotation = (elem) => {
  10259. remove$7(elem, annotation());
  10260. remove$a(elem, `${dataAnnotationId()}`);
  10261. remove$a(elem, `${dataAnnotation()}`);
  10262. remove$a(elem, `${dataAnnotationActive()}`);
  10263. const customAttrNames = getOpt(elem, `${dataAnnotationAttributes()}`)
  10264. .map((names) => names.split(","))
  10265. .getOr([]);
  10266. const customClasses = getOpt(elem, `${dataAnnotationClasses()}`)
  10267. .map((names) => names.split(","))
  10268. .getOr([]);
  10269. each$e(customAttrNames, (name) => remove$a(elem, name));
  10270. remove$4(elem, customClasses);
  10271. remove$a(elem, `${dataAnnotationClasses()}`);
  10272. remove$a(elem, `${dataAnnotationAttributes()}`);
  10273. };
  10274. const makeAnnotation = (eDoc, uid, data, annotationName, decorate) => {
  10275. const master = SugarElement.fromTag("span", eDoc);
  10276. applyAnnotation(master, uid, data, annotationName, decorate, false);
  10277. return master;
  10278. };
  10279. const annotate = (editor, rng, uid, annotationName, decorate, data) => {
  10280. const newWrappers = [];
  10281. const master = makeAnnotation(
  10282. editor.getDoc(),
  10283. uid,
  10284. data,
  10285. annotationName,
  10286. decorate
  10287. );
  10288. const wrapper = value$2();
  10289. const finishWrapper = () => {
  10290. wrapper.clear();
  10291. };
  10292. const getOrOpenWrapper = () =>
  10293. wrapper.get().getOrThunk(() => {
  10294. const nu = shallow$1(master);
  10295. newWrappers.push(nu);
  10296. wrapper.set(nu);
  10297. return nu;
  10298. });
  10299. const processElements = (elems) => {
  10300. each$e(elems, processElement);
  10301. };
  10302. const processElement = (elem) => {
  10303. const ctx = context(editor, elem, "span", name(elem));
  10304. switch (ctx) {
  10305. case "invalid-child": {
  10306. finishWrapper();
  10307. const children = children$1(elem);
  10308. processElements(children);
  10309. finishWrapper();
  10310. break;
  10311. }
  10312. case "valid-block": {
  10313. finishWrapper();
  10314. applyAnnotation(elem, uid, data, annotationName, decorate, true);
  10315. break;
  10316. }
  10317. case "valid": {
  10318. const w = getOrOpenWrapper();
  10319. wrap$2(elem, w);
  10320. break;
  10321. }
  10322. }
  10323. };
  10324. const processNodes = (nodes) => {
  10325. const elems = map$3(nodes, SugarElement.fromDom);
  10326. processElements(elems);
  10327. };
  10328. walk$3(editor.dom, rng, (nodes) => {
  10329. finishWrapper();
  10330. processNodes(nodes);
  10331. });
  10332. return newWrappers;
  10333. };
  10334. const annotateWithBookmark = (editor, name, settings, data) => {
  10335. editor.undoManager.transact(() => {
  10336. const selection = editor.selection;
  10337. const initialRng = selection.getRng();
  10338. const hasFakeSelection = getCellsFromEditor(editor).length > 0;
  10339. const masterUid = generate$1("mce-annotation");
  10340. if (initialRng.collapsed && !hasFakeSelection) {
  10341. applyWordGrab(editor, initialRng);
  10342. }
  10343. if (selection.getRng().collapsed && !hasFakeSelection) {
  10344. const wrapper = makeAnnotation(
  10345. editor.getDoc(),
  10346. masterUid,
  10347. data,
  10348. name,
  10349. settings.decorate
  10350. );
  10351. set$1(wrapper, nbsp);
  10352. selection.getRng().insertNode(wrapper.dom);
  10353. selection.select(wrapper.dom);
  10354. } else {
  10355. preserve(selection, false, () => {
  10356. runOnRanges(editor, (selectionRng) => {
  10357. annotate(
  10358. editor,
  10359. selectionRng,
  10360. masterUid,
  10361. name,
  10362. settings.decorate,
  10363. data
  10364. );
  10365. });
  10366. });
  10367. }
  10368. });
  10369. };
  10370. const Annotator = (editor) => {
  10371. const registry = create$c();
  10372. setup$w(editor, registry);
  10373. const changes = setup$x(editor, registry);
  10374. const isSpan = isTag("span");
  10375. const removeAnnotations = (elements) => {
  10376. each$e(elements, (element) => {
  10377. if (isSpan(element)) {
  10378. unwrap(element);
  10379. } else {
  10380. removeDirectAnnotation(element);
  10381. }
  10382. });
  10383. };
  10384. return {
  10385. register: (name, settings) => {
  10386. registry.register(name, settings);
  10387. },
  10388. annotate: (name, data) => {
  10389. registry.lookup(name).each((settings) => {
  10390. annotateWithBookmark(editor, name, settings, data);
  10391. });
  10392. },
  10393. annotationChanged: (name, callback) => {
  10394. changes.addListener(name, callback);
  10395. },
  10396. remove: (name) => {
  10397. identify(editor, Optional.some(name)).each(({ elements }) => {
  10398. const bookmark = editor.selection.getBookmark();
  10399. removeAnnotations(elements);
  10400. editor.selection.moveToBookmark(bookmark);
  10401. });
  10402. },
  10403. removeAll: (name) => {
  10404. const bookmark = editor.selection.getBookmark();
  10405. each$d(findAll(editor, name), (elements, _) => {
  10406. removeAnnotations(elements);
  10407. });
  10408. editor.selection.moveToBookmark(bookmark);
  10409. },
  10410. getAll: (name) => {
  10411. const directory = findAll(editor, name);
  10412. return map$2(directory, (elems) => map$3(elems, (elem) => elem.dom));
  10413. },
  10414. };
  10415. };
  10416. const BookmarkManager = (selection) => {
  10417. return {
  10418. getBookmark: curry(getBookmark$1, selection),
  10419. moveToBookmark: curry(moveToBookmark, selection),
  10420. };
  10421. };
  10422. BookmarkManager.isBookmarkNode = isBookmarkNode$1;
  10423. const isXYWithinRange = (clientX, clientY, range) => {
  10424. if (range.collapsed) {
  10425. return false;
  10426. } else {
  10427. return exists(range.getClientRects(), (rect) =>
  10428. containsXY(rect, clientX, clientY)
  10429. );
  10430. }
  10431. };
  10432. const firePreProcess = (editor, args) => editor.dispatch("PreProcess", args);
  10433. const firePostProcess = (editor, args) =>
  10434. editor.dispatch("PostProcess", args);
  10435. const fireRemove = (editor) => {
  10436. editor.dispatch("remove");
  10437. };
  10438. const fireDetach = (editor) => {
  10439. editor.dispatch("detach");
  10440. };
  10441. const fireSwitchMode = (editor, mode) => {
  10442. editor.dispatch("SwitchMode", { mode });
  10443. };
  10444. const fireObjectResizeStart = (editor, target, width, height, origin) => {
  10445. editor.dispatch("ObjectResizeStart", {
  10446. target,
  10447. width,
  10448. height,
  10449. origin,
  10450. });
  10451. };
  10452. const fireObjectResized = (editor, target, width, height, origin) => {
  10453. editor.dispatch("ObjectResized", {
  10454. target,
  10455. width,
  10456. height,
  10457. origin,
  10458. });
  10459. };
  10460. const firePreInit = (editor) => {
  10461. editor.dispatch("PreInit");
  10462. };
  10463. const firePostRender = (editor) => {
  10464. editor.dispatch("PostRender");
  10465. };
  10466. const fireInit = (editor) => {
  10467. editor.dispatch("Init");
  10468. };
  10469. const firePlaceholderToggle = (editor, state) => {
  10470. editor.dispatch("PlaceholderToggle", { state });
  10471. };
  10472. const fireError = (editor, errorType, error) => {
  10473. editor.dispatch(errorType, error);
  10474. };
  10475. const fireFormatApply = (editor, format, node, vars) => {
  10476. editor.dispatch("FormatApply", {
  10477. format,
  10478. node,
  10479. vars,
  10480. });
  10481. };
  10482. const fireFormatRemove = (editor, format, node, vars) => {
  10483. editor.dispatch("FormatRemove", {
  10484. format,
  10485. node,
  10486. vars,
  10487. });
  10488. };
  10489. const fireBeforeSetContent = (editor, args) =>
  10490. editor.dispatch("BeforeSetContent", args);
  10491. const fireSetContent = (editor, args) => editor.dispatch("SetContent", args);
  10492. const fireBeforeGetContent = (editor, args) =>
  10493. editor.dispatch("BeforeGetContent", args);
  10494. const fireGetContent = (editor, args) => editor.dispatch("GetContent", args);
  10495. const fireAutocompleterStart = (editor, args) => {
  10496. editor.dispatch("AutocompleterStart", args);
  10497. };
  10498. const fireAutocompleterUpdate = (editor, args) => {
  10499. editor.dispatch("AutocompleterUpdate", args);
  10500. };
  10501. const fireAutocompleterEnd = (editor) => {
  10502. editor.dispatch("AutocompleterEnd");
  10503. };
  10504. const firePastePreProcess = (editor, html, internal) =>
  10505. editor.dispatch("PastePreProcess", {
  10506. content: html,
  10507. internal,
  10508. });
  10509. const firePastePostProcess = (editor, node, internal) =>
  10510. editor.dispatch("PastePostProcess", {
  10511. node,
  10512. internal,
  10513. });
  10514. const firePastePlainTextToggle = (editor, state) =>
  10515. editor.dispatch("PastePlainTextToggle", { state });
  10516. const fireEditableRootStateChange = (editor, state) =>
  10517. editor.dispatch("EditableRootStateChange", { state });
  10518. const VK = {
  10519. BACKSPACE: 8,
  10520. DELETE: 46,
  10521. DOWN: 40,
  10522. ENTER: 13,
  10523. ESC: 27,
  10524. LEFT: 37,
  10525. RIGHT: 39,
  10526. SPACEBAR: 32,
  10527. TAB: 9,
  10528. UP: 38,
  10529. PAGE_UP: 33,
  10530. PAGE_DOWN: 34,
  10531. END: 35,
  10532. HOME: 36,
  10533. modifierPressed: (e) => {
  10534. return e.shiftKey || e.ctrlKey || e.altKey || VK.metaKeyPressed(e);
  10535. },
  10536. metaKeyPressed: (e) => {
  10537. return Env.os.isMacOS() || Env.os.isiOS()
  10538. ? e.metaKey
  10539. : e.ctrlKey && !e.altKey;
  10540. },
  10541. };
  10542. const elementSelectionAttr = "data-mce-selected";
  10543. const controlElmSelector =
  10544. "table,img,figure.image,hr,video,span.mce-preview-object,details";
  10545. const abs = Math.abs;
  10546. const round$1 = Math.round;
  10547. const resizeHandles = {
  10548. nw: [0, 0, -1, -1],
  10549. ne: [1, 0, 1, -1],
  10550. se: [1, 1, 1, 1],
  10551. sw: [0, 1, -1, 1],
  10552. };
  10553. const isTouchEvent = (evt) =>
  10554. evt.type === "longpress" || evt.type.indexOf("touch") === 0;
  10555. const ControlSelection = (selection, editor) => {
  10556. const dom = editor.dom;
  10557. const editableDoc = editor.getDoc();
  10558. const rootDocument = document;
  10559. const rootElement = editor.getBody();
  10560. let selectedElm,
  10561. selectedElmGhost,
  10562. resizeHelper,
  10563. selectedHandle,
  10564. resizeBackdrop;
  10565. let startX,
  10566. startY,
  10567. selectedElmX,
  10568. selectedElmY,
  10569. startW,
  10570. startH,
  10571. ratio,
  10572. resizeStarted;
  10573. let width;
  10574. let height;
  10575. let startScrollWidth;
  10576. let startScrollHeight;
  10577. const isImage = (elm) =>
  10578. isNonNullable(elm) && (isImg(elm) || dom.is(elm, "figure.image"));
  10579. const isMedia = (elm) =>
  10580. isMedia$2(elm) || dom.hasClass(elm, "mce-preview-object");
  10581. const isEventOnImageOutsideRange = (evt, range) => {
  10582. if (isTouchEvent(evt)) {
  10583. const touch = evt.touches[0];
  10584. return (
  10585. isImage(evt.target) &&
  10586. !isXYWithinRange(touch.clientX, touch.clientY, range)
  10587. );
  10588. } else {
  10589. return (
  10590. isImage(evt.target) &&
  10591. !isXYWithinRange(evt.clientX, evt.clientY, range)
  10592. );
  10593. }
  10594. };
  10595. const contextMenuSelectImage = (evt) => {
  10596. const target = evt.target;
  10597. if (
  10598. isEventOnImageOutsideRange(evt, editor.selection.getRng()) &&
  10599. !evt.isDefaultPrevented()
  10600. ) {
  10601. editor.selection.select(target);
  10602. }
  10603. };
  10604. const getResizeTargets = (elm) => {
  10605. if (
  10606. dom.hasClass(elm, "mce-preview-object") &&
  10607. isNonNullable(elm.firstElementChild)
  10608. ) {
  10609. return [elm, elm.firstElementChild];
  10610. } else if (dom.is(elm, "figure.image")) {
  10611. return [elm.querySelector("img")];
  10612. } else {
  10613. return [elm];
  10614. }
  10615. };
  10616. const isResizable = (elm) => {
  10617. const selector = getObjectResizing(editor);
  10618. if (!selector) {
  10619. return false;
  10620. }
  10621. if (elm.getAttribute("data-mce-resize") === "false") {
  10622. return false;
  10623. }
  10624. if (elm === editor.getBody()) {
  10625. return false;
  10626. }
  10627. if (
  10628. dom.hasClass(elm, "mce-preview-object") &&
  10629. isNonNullable(elm.firstElementChild)
  10630. ) {
  10631. return is$1(SugarElement.fromDom(elm.firstElementChild), selector);
  10632. } else {
  10633. return is$1(SugarElement.fromDom(elm), selector);
  10634. }
  10635. };
  10636. const createGhostElement = (elm) => {
  10637. if (isMedia(elm)) {
  10638. return dom.create("img", { src: Env.transparentSrc });
  10639. } else {
  10640. return elm.cloneNode(true);
  10641. }
  10642. };
  10643. const setSizeProp = (element, name, value) => {
  10644. if (isNonNullable(value)) {
  10645. const targets = getResizeTargets(element);
  10646. each$e(targets, (target) => {
  10647. if (
  10648. target.style[name] ||
  10649. !editor.schema.isValid(target.nodeName.toLowerCase(), name)
  10650. ) {
  10651. dom.setStyle(target, name, value);
  10652. } else {
  10653. dom.setAttrib(target, name, "" + value);
  10654. }
  10655. });
  10656. }
  10657. };
  10658. const setGhostElmSize = (ghostElm, width, height) => {
  10659. setSizeProp(ghostElm, "width", width);
  10660. setSizeProp(ghostElm, "height", height);
  10661. };
  10662. const resizeGhostElement = (e) => {
  10663. let deltaX, deltaY, proportional;
  10664. let resizeHelperX, resizeHelperY;
  10665. deltaX = e.screenX - startX;
  10666. deltaY = e.screenY - startY;
  10667. width = deltaX * selectedHandle[2] + startW;
  10668. height = deltaY * selectedHandle[3] + startH;
  10669. width = width < 5 ? 5 : width;
  10670. height = height < 5 ? 5 : height;
  10671. if (
  10672. (isImage(selectedElm) || isMedia(selectedElm)) &&
  10673. getResizeImgProportional(editor) !== false
  10674. ) {
  10675. proportional = !VK.modifierPressed(e);
  10676. } else {
  10677. proportional = VK.modifierPressed(e);
  10678. }
  10679. if (proportional) {
  10680. if (abs(deltaX) > abs(deltaY)) {
  10681. height = round$1(width * ratio);
  10682. width = round$1(height / ratio);
  10683. } else {
  10684. width = round$1(height / ratio);
  10685. height = round$1(width * ratio);
  10686. }
  10687. }
  10688. setGhostElmSize(selectedElmGhost, width, height);
  10689. resizeHelperX = selectedHandle.startPos.x + deltaX;
  10690. resizeHelperY = selectedHandle.startPos.y + deltaY;
  10691. resizeHelperX = resizeHelperX > 0 ? resizeHelperX : 0;
  10692. resizeHelperY = resizeHelperY > 0 ? resizeHelperY : 0;
  10693. dom.setStyles(resizeHelper, {
  10694. left: resizeHelperX,
  10695. top: resizeHelperY,
  10696. display: "block",
  10697. });
  10698. resizeHelper.innerHTML = width + " &times; " + height;
  10699. if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {
  10700. dom.setStyle(selectedElmGhost, "left", selectedElmX + (startW - width));
  10701. }
  10702. if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {
  10703. dom.setStyle(selectedElmGhost, "top", selectedElmY + (startH - height));
  10704. }
  10705. deltaX = rootElement.scrollWidth - startScrollWidth;
  10706. deltaY = rootElement.scrollHeight - startScrollHeight;
  10707. if (deltaX + deltaY !== 0) {
  10708. dom.setStyles(resizeHelper, {
  10709. left: resizeHelperX - deltaX,
  10710. top: resizeHelperY - deltaY,
  10711. });
  10712. }
  10713. if (!resizeStarted) {
  10714. fireObjectResizeStart(
  10715. editor,
  10716. selectedElm,
  10717. startW,
  10718. startH,
  10719. "corner-" + selectedHandle.name
  10720. );
  10721. resizeStarted = true;
  10722. }
  10723. };
  10724. const endGhostResize = () => {
  10725. const wasResizeStarted = resizeStarted;
  10726. resizeStarted = false;
  10727. if (wasResizeStarted) {
  10728. setSizeProp(selectedElm, "width", width);
  10729. setSizeProp(selectedElm, "height", height);
  10730. }
  10731. dom.unbind(editableDoc, "mousemove", resizeGhostElement);
  10732. dom.unbind(editableDoc, "mouseup", endGhostResize);
  10733. if (rootDocument !== editableDoc) {
  10734. dom.unbind(rootDocument, "mousemove", resizeGhostElement);
  10735. dom.unbind(rootDocument, "mouseup", endGhostResize);
  10736. }
  10737. dom.remove(selectedElmGhost);
  10738. dom.remove(resizeHelper);
  10739. dom.remove(resizeBackdrop);
  10740. showResizeRect(selectedElm);
  10741. if (wasResizeStarted) {
  10742. fireObjectResized(
  10743. editor,
  10744. selectedElm,
  10745. width,
  10746. height,
  10747. "corner-" + selectedHandle.name
  10748. );
  10749. dom.setAttrib(
  10750. selectedElm,
  10751. "style",
  10752. dom.getAttrib(selectedElm, "style")
  10753. );
  10754. }
  10755. editor.nodeChanged();
  10756. };
  10757. const showResizeRect = (targetElm) => {
  10758. unbindResizeHandleEvents();
  10759. const position = dom.getPos(targetElm, rootElement);
  10760. const selectedElmX = position.x;
  10761. const selectedElmY = position.y;
  10762. const rect = targetElm.getBoundingClientRect();
  10763. const targetWidth = rect.width || rect.right - rect.left;
  10764. const targetHeight = rect.height || rect.bottom - rect.top;
  10765. if (selectedElm !== targetElm) {
  10766. hideResizeRect();
  10767. selectedElm = targetElm;
  10768. width = height = 0;
  10769. }
  10770. const e = editor.dispatch("ObjectSelected", { target: targetElm });
  10771. if (isResizable(targetElm) && !e.isDefaultPrevented()) {
  10772. each$d(resizeHandles, (handle, name) => {
  10773. const startDrag = (e) => {
  10774. const target = getResizeTargets(selectedElm)[0];
  10775. startX = e.screenX;
  10776. startY = e.screenY;
  10777. startW = target.clientWidth;
  10778. startH = target.clientHeight;
  10779. ratio = startH / startW;
  10780. selectedHandle = handle;
  10781. selectedHandle.name = name;
  10782. selectedHandle.startPos = {
  10783. x: targetWidth * handle[0] + selectedElmX,
  10784. y: targetHeight * handle[1] + selectedElmY,
  10785. };
  10786. startScrollWidth = rootElement.scrollWidth;
  10787. startScrollHeight = rootElement.scrollHeight;
  10788. resizeBackdrop = dom.add(rootElement, "div", {
  10789. class: "mce-resize-backdrop",
  10790. "data-mce-bogus": "all",
  10791. });
  10792. dom.setStyles(resizeBackdrop, {
  10793. position: "fixed",
  10794. left: "0",
  10795. top: "0",
  10796. width: "100%",
  10797. height: "100%",
  10798. });
  10799. selectedElmGhost = createGhostElement(selectedElm);
  10800. dom.addClass(selectedElmGhost, "mce-clonedresizable");
  10801. dom.setAttrib(selectedElmGhost, "data-mce-bogus", "all");
  10802. selectedElmGhost.contentEditable = "false";
  10803. dom.setStyles(selectedElmGhost, {
  10804. left: selectedElmX,
  10805. top: selectedElmY,
  10806. margin: 0,
  10807. });
  10808. setGhostElmSize(selectedElmGhost, targetWidth, targetHeight);
  10809. selectedElmGhost.removeAttribute(elementSelectionAttr);
  10810. rootElement.appendChild(selectedElmGhost);
  10811. dom.bind(editableDoc, "mousemove", resizeGhostElement);
  10812. dom.bind(editableDoc, "mouseup", endGhostResize);
  10813. if (rootDocument !== editableDoc) {
  10814. dom.bind(rootDocument, "mousemove", resizeGhostElement);
  10815. dom.bind(rootDocument, "mouseup", endGhostResize);
  10816. }
  10817. resizeHelper = dom.add(
  10818. rootElement,
  10819. "div",
  10820. {
  10821. class: "mce-resize-helper",
  10822. "data-mce-bogus": "all",
  10823. },
  10824. startW + " &times; " + startH
  10825. );
  10826. };
  10827. let handleElm = dom.get("mceResizeHandle" + name);
  10828. if (handleElm) {
  10829. dom.remove(handleElm);
  10830. }
  10831. handleElm = dom.add(rootElement, "div", {
  10832. id: "mceResizeHandle" + name,
  10833. "data-mce-bogus": "all",
  10834. class: "mce-resizehandle",
  10835. unselectable: true,
  10836. style: "cursor:" + name + "-resize; margin:0; padding:0",
  10837. });
  10838. dom.bind(handleElm, "mousedown", (e) => {
  10839. e.stopImmediatePropagation();
  10840. e.preventDefault();
  10841. startDrag(e);
  10842. });
  10843. handle.elm = handleElm;
  10844. dom.setStyles(handleElm, {
  10845. left:
  10846. targetWidth * handle[0] +
  10847. selectedElmX -
  10848. handleElm.offsetWidth / 2,
  10849. top:
  10850. targetHeight * handle[1] +
  10851. selectedElmY -
  10852. handleElm.offsetHeight / 2,
  10853. });
  10854. });
  10855. } else {
  10856. hideResizeRect(false);
  10857. }
  10858. };
  10859. const throttledShowResizeRect = first$1(showResizeRect, 0);
  10860. const hideResizeRect = (removeSelected = true) => {
  10861. throttledShowResizeRect.cancel();
  10862. unbindResizeHandleEvents();
  10863. if (selectedElm && removeSelected) {
  10864. selectedElm.removeAttribute(elementSelectionAttr);
  10865. }
  10866. each$d(resizeHandles, (value, name) => {
  10867. const handleElm = dom.get("mceResizeHandle" + name);
  10868. if (handleElm) {
  10869. dom.unbind(handleElm);
  10870. dom.remove(handleElm);
  10871. }
  10872. });
  10873. };
  10874. const isChildOrEqual = (node, parent) => dom.isChildOf(node, parent);
  10875. const updateResizeRect = (e) => {
  10876. if (resizeStarted || editor.removed || editor.composing) {
  10877. return;
  10878. }
  10879. const targetElm = e.type === "mousedown" ? e.target : selection.getNode();
  10880. const controlElm = closest$3(
  10881. SugarElement.fromDom(targetElm),
  10882. controlElmSelector
  10883. )
  10884. .map((e) => e.dom)
  10885. .filter((e) => dom.isEditable(e.parentElement))
  10886. .getOrUndefined();
  10887. const selectedValue = isNonNullable(controlElm)
  10888. ? dom.getAttrib(controlElm, elementSelectionAttr, "1")
  10889. : "1";
  10890. each$e(
  10891. dom.select(`img[${elementSelectionAttr}],hr[${elementSelectionAttr}]`),
  10892. (img) => {
  10893. img.removeAttribute(elementSelectionAttr);
  10894. }
  10895. );
  10896. if (
  10897. isNonNullable(controlElm) &&
  10898. isChildOrEqual(controlElm, rootElement) &&
  10899. editor.hasFocus()
  10900. ) {
  10901. disableGeckoResize();
  10902. const startElm = selection.getStart(true);
  10903. if (
  10904. isChildOrEqual(startElm, controlElm) &&
  10905. isChildOrEqual(selection.getEnd(true), controlElm)
  10906. ) {
  10907. dom.setAttrib(controlElm, elementSelectionAttr, selectedValue);
  10908. throttledShowResizeRect.throttle(controlElm);
  10909. return;
  10910. }
  10911. }
  10912. hideResizeRect();
  10913. };
  10914. const unbindResizeHandleEvents = () => {
  10915. each$d(resizeHandles, (handle) => {
  10916. if (handle.elm) {
  10917. dom.unbind(handle.elm);
  10918. delete handle.elm;
  10919. }
  10920. });
  10921. };
  10922. const disableGeckoResize = () => {
  10923. try {
  10924. editor.getDoc().execCommand("enableObjectResizing", false, "false");
  10925. } catch (ex) {}
  10926. };
  10927. editor.on("init", () => {
  10928. disableGeckoResize();
  10929. editor.on(
  10930. "NodeChange ResizeEditor ResizeWindow ResizeContent drop",
  10931. updateResizeRect
  10932. );
  10933. editor.on("keyup compositionend", (e) => {
  10934. if (selectedElm && selectedElm.nodeName === "TABLE") {
  10935. updateResizeRect(e);
  10936. }
  10937. });
  10938. editor.on("hide blur", hideResizeRect);
  10939. editor.on("contextmenu longpress", contextMenuSelectImage, true);
  10940. });
  10941. editor.on("remove", unbindResizeHandleEvents);
  10942. const destroy = () => {
  10943. throttledShowResizeRect.cancel();
  10944. selectedElm = selectedElmGhost = resizeBackdrop = null;
  10945. };
  10946. return {
  10947. isResizable,
  10948. showResizeRect,
  10949. hideResizeRect,
  10950. updateResizeRect,
  10951. destroy,
  10952. };
  10953. };
  10954. const setStart = (rng, situ) => {
  10955. situ.fold(
  10956. (e) => {
  10957. rng.setStartBefore(e.dom);
  10958. },
  10959. (e, o) => {
  10960. rng.setStart(e.dom, o);
  10961. },
  10962. (e) => {
  10963. rng.setStartAfter(e.dom);
  10964. }
  10965. );
  10966. };
  10967. const setFinish = (rng, situ) => {
  10968. situ.fold(
  10969. (e) => {
  10970. rng.setEndBefore(e.dom);
  10971. },
  10972. (e, o) => {
  10973. rng.setEnd(e.dom, o);
  10974. },
  10975. (e) => {
  10976. rng.setEndAfter(e.dom);
  10977. }
  10978. );
  10979. };
  10980. const relativeToNative = (win, startSitu, finishSitu) => {
  10981. const range = win.document.createRange();
  10982. setStart(range, startSitu);
  10983. setFinish(range, finishSitu);
  10984. return range;
  10985. };
  10986. const exactToNative = (win, start, soffset, finish, foffset) => {
  10987. const rng = win.document.createRange();
  10988. rng.setStart(start.dom, soffset);
  10989. rng.setEnd(finish.dom, foffset);
  10990. return rng;
  10991. };
  10992. const adt$3 = Adt.generate([
  10993. {
  10994. ltr: ["start", "soffset", "finish", "foffset"],
  10995. },
  10996. {
  10997. rtl: ["start", "soffset", "finish", "foffset"],
  10998. },
  10999. ]);
  11000. const fromRange = (win, type, range) =>
  11001. type(
  11002. SugarElement.fromDom(range.startContainer),
  11003. range.startOffset,
  11004. SugarElement.fromDom(range.endContainer),
  11005. range.endOffset
  11006. );
  11007. const getRanges = (win, selection) =>
  11008. selection.match({
  11009. domRange: (rng) => {
  11010. return {
  11011. ltr: constant(rng),
  11012. rtl: Optional.none,
  11013. };
  11014. },
  11015. relative: (startSitu, finishSitu) => {
  11016. return {
  11017. ltr: cached(() => relativeToNative(win, startSitu, finishSitu)),
  11018. rtl: cached(() =>
  11019. Optional.some(relativeToNative(win, finishSitu, startSitu))
  11020. ),
  11021. };
  11022. },
  11023. exact: (start, soffset, finish, foffset) => {
  11024. return {
  11025. ltr: cached(() =>
  11026. exactToNative(win, start, soffset, finish, foffset)
  11027. ),
  11028. rtl: cached(() =>
  11029. Optional.some(exactToNative(win, finish, foffset, start, soffset))
  11030. ),
  11031. };
  11032. },
  11033. });
  11034. const doDiagnose = (win, ranges) => {
  11035. const rng = ranges.ltr();
  11036. if (rng.collapsed) {
  11037. const reversed = ranges.rtl().filter((rev) => rev.collapsed === false);
  11038. return reversed
  11039. .map((rev) =>
  11040. adt$3.rtl(
  11041. SugarElement.fromDom(rev.endContainer),
  11042. rev.endOffset,
  11043. SugarElement.fromDom(rev.startContainer),
  11044. rev.startOffset
  11045. )
  11046. )
  11047. .getOrThunk(() => fromRange(win, adt$3.ltr, rng));
  11048. } else {
  11049. return fromRange(win, adt$3.ltr, rng);
  11050. }
  11051. };
  11052. const diagnose = (win, selection) => {
  11053. const ranges = getRanges(win, selection);
  11054. return doDiagnose(win, ranges);
  11055. };
  11056. adt$3.ltr;
  11057. adt$3.rtl;
  11058. const create$a = (start, soffset, finish, foffset) => ({
  11059. start,
  11060. soffset,
  11061. finish,
  11062. foffset,
  11063. });
  11064. const SimRange = { create: create$a };
  11065. const caretPositionFromPoint = (doc, x, y) => {
  11066. var _a, _b;
  11067. return Optional.from(
  11068. (_b = (_a = doc.dom).caretPositionFromPoint) === null || _b === void 0
  11069. ? void 0
  11070. : _b.call(_a, x, y)
  11071. ).bind((pos) => {
  11072. if (pos.offsetNode === null) {
  11073. return Optional.none();
  11074. }
  11075. const r = doc.dom.createRange();
  11076. r.setStart(pos.offsetNode, pos.offset);
  11077. r.collapse();
  11078. return Optional.some(r);
  11079. });
  11080. };
  11081. const caretRangeFromPoint = (doc, x, y) => {
  11082. var _a, _b;
  11083. return Optional.from(
  11084. (_b = (_a = doc.dom).caretRangeFromPoint) === null || _b === void 0
  11085. ? void 0
  11086. : _b.call(_a, x, y)
  11087. );
  11088. };
  11089. const availableSearch = (() => {
  11090. if (document.caretPositionFromPoint) {
  11091. return caretPositionFromPoint;
  11092. } else if (document.caretRangeFromPoint) {
  11093. return caretRangeFromPoint;
  11094. } else {
  11095. return Optional.none;
  11096. }
  11097. })();
  11098. const fromPoint$1 = (win, x, y) => {
  11099. const doc = SugarElement.fromDom(win.document);
  11100. return availableSearch(doc, x, y).map((rng) =>
  11101. SimRange.create(
  11102. SugarElement.fromDom(rng.startContainer),
  11103. rng.startOffset,
  11104. SugarElement.fromDom(rng.endContainer),
  11105. rng.endOffset
  11106. )
  11107. );
  11108. };
  11109. const adt$2 = Adt.generate([
  11110. { before: ["element"] },
  11111. {
  11112. on: ["element", "offset"],
  11113. },
  11114. { after: ["element"] },
  11115. ]);
  11116. const cata = (subject, onBefore, onOn, onAfter) =>
  11117. subject.fold(onBefore, onOn, onAfter);
  11118. const getStart$2 = (situ) => situ.fold(identity, identity, identity);
  11119. const before$1 = adt$2.before;
  11120. const on = adt$2.on;
  11121. const after$1 = adt$2.after;
  11122. const Situ = {
  11123. before: before$1,
  11124. on,
  11125. after: after$1,
  11126. cata,
  11127. getStart: getStart$2,
  11128. };
  11129. const adt$1 = Adt.generate([
  11130. { domRange: ["rng"] },
  11131. {
  11132. relative: ["startSitu", "finishSitu"],
  11133. },
  11134. {
  11135. exact: ["start", "soffset", "finish", "foffset"],
  11136. },
  11137. ]);
  11138. const exactFromRange = (simRange) =>
  11139. adt$1.exact(
  11140. simRange.start,
  11141. simRange.soffset,
  11142. simRange.finish,
  11143. simRange.foffset
  11144. );
  11145. const getStart$1 = (selection) =>
  11146. selection.match({
  11147. domRange: (rng) => SugarElement.fromDom(rng.startContainer),
  11148. relative: (startSitu, _finishSitu) => Situ.getStart(startSitu),
  11149. exact: (start, _soffset, _finish, _foffset) => start,
  11150. });
  11151. const domRange = adt$1.domRange;
  11152. const relative = adt$1.relative;
  11153. const exact = adt$1.exact;
  11154. const getWin = (selection) => {
  11155. const start = getStart$1(selection);
  11156. return defaultView(start);
  11157. };
  11158. const range = SimRange.create;
  11159. const SimSelection = {
  11160. domRange,
  11161. relative,
  11162. exact,
  11163. exactFromRange,
  11164. getWin,
  11165. range,
  11166. };
  11167. const beforeSpecial = (element, offset) => {
  11168. const name$1 = name(element);
  11169. if ("input" === name$1) {
  11170. return Situ.after(element);
  11171. } else if (!contains$2(["br", "img"], name$1)) {
  11172. return Situ.on(element, offset);
  11173. } else {
  11174. return offset === 0 ? Situ.before(element) : Situ.after(element);
  11175. }
  11176. };
  11177. const preprocessRelative = (startSitu, finishSitu) => {
  11178. const start = startSitu.fold(Situ.before, beforeSpecial, Situ.after);
  11179. const finish = finishSitu.fold(Situ.before, beforeSpecial, Situ.after);
  11180. return SimSelection.relative(start, finish);
  11181. };
  11182. const preprocessExact = (start, soffset, finish, foffset) => {
  11183. const startSitu = beforeSpecial(start, soffset);
  11184. const finishSitu = beforeSpecial(finish, foffset);
  11185. return SimSelection.relative(startSitu, finishSitu);
  11186. };
  11187. const preprocess = (selection) =>
  11188. selection.match({
  11189. domRange: (rng) => {
  11190. const start = SugarElement.fromDom(rng.startContainer);
  11191. const finish = SugarElement.fromDom(rng.endContainer);
  11192. return preprocessExact(start, rng.startOffset, finish, rng.endOffset);
  11193. },
  11194. relative: preprocessRelative,
  11195. exact: preprocessExact,
  11196. });
  11197. const fromElements = (elements, scope) => {
  11198. const doc = scope || document;
  11199. const fragment = doc.createDocumentFragment();
  11200. each$e(elements, (element) => {
  11201. fragment.appendChild(element.dom);
  11202. });
  11203. return SugarElement.fromDom(fragment);
  11204. };
  11205. const toNative = (selection) => {
  11206. const win = SimSelection.getWin(selection).dom;
  11207. const getDomRange = (start, soffset, finish, foffset) =>
  11208. exactToNative(win, start, soffset, finish, foffset);
  11209. const filtered = preprocess(selection);
  11210. return diagnose(win, filtered).match({
  11211. ltr: getDomRange,
  11212. rtl: getDomRange,
  11213. });
  11214. };
  11215. const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
  11216. const fromPoint = (clientX, clientY, doc) => {
  11217. const win = defaultView(SugarElement.fromDom(doc));
  11218. return getAtPoint(win.dom, clientX, clientY)
  11219. .map((simRange) => {
  11220. const rng = doc.createRange();
  11221. rng.setStart(simRange.start.dom, simRange.soffset);
  11222. rng.setEnd(simRange.finish.dom, simRange.foffset);
  11223. return rng;
  11224. })
  11225. .getOrUndefined();
  11226. };
  11227. const isEq$4 = (rng1, rng2) => {
  11228. return (
  11229. isNonNullable(rng1) &&
  11230. isNonNullable(rng2) &&
  11231. rng1.startContainer === rng2.startContainer &&
  11232. rng1.startOffset === rng2.startOffset &&
  11233. rng1.endContainer === rng2.endContainer &&
  11234. rng1.endOffset === rng2.endOffset
  11235. );
  11236. };
  11237. const findParent = (node, rootNode, predicate) => {
  11238. let currentNode = node;
  11239. while (currentNode && currentNode !== rootNode) {
  11240. if (predicate(currentNode)) {
  11241. return currentNode;
  11242. }
  11243. currentNode = currentNode.parentNode;
  11244. }
  11245. return null;
  11246. };
  11247. const hasParent$1 = (node, rootNode, predicate) =>
  11248. findParent(node, rootNode, predicate) !== null;
  11249. const hasParentWithName = (node, rootNode, name) =>
  11250. hasParent$1(node, rootNode, (node) => node.nodeName === name);
  11251. const isCeFalseCaretContainer = (node, rootNode) =>
  11252. isCaretContainer$2(node) && !hasParent$1(node, rootNode, isCaretNode);
  11253. const hasBrBeforeAfter = (dom, node, left) => {
  11254. const parentNode = node.parentNode;
  11255. if (parentNode) {
  11256. const walker = new DomTreeWalker(
  11257. node,
  11258. dom.getParent(parentNode, dom.isBlock) || dom.getRoot()
  11259. );
  11260. let currentNode;
  11261. while ((currentNode = walker[left ? "prev" : "next"]())) {
  11262. if (isBr$6(currentNode)) {
  11263. return true;
  11264. }
  11265. }
  11266. }
  11267. return false;
  11268. };
  11269. const isPrevNode = (node, name) => {
  11270. var _a;
  11271. return (
  11272. ((_a = node.previousSibling) === null || _a === void 0
  11273. ? void 0
  11274. : _a.nodeName) === name
  11275. );
  11276. };
  11277. const hasContentEditableFalseParent = (root, node) => {
  11278. let currentNode = node;
  11279. while (currentNode && currentNode !== root) {
  11280. if (isContentEditableFalse$b(currentNode)) {
  11281. return true;
  11282. }
  11283. currentNode = currentNode.parentNode;
  11284. }
  11285. return false;
  11286. };
  11287. const findTextNodeRelative = (
  11288. dom,
  11289. isAfterNode,
  11290. collapsed,
  11291. left,
  11292. startNode
  11293. ) => {
  11294. const body = dom.getRoot();
  11295. const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
  11296. const parentNode = startNode.parentNode;
  11297. let lastInlineElement;
  11298. let node;
  11299. if (!parentNode) {
  11300. return Optional.none();
  11301. }
  11302. const parentBlockContainer = dom.getParent(parentNode, dom.isBlock) || body;
  11303. if (
  11304. left &&
  11305. isBr$6(startNode) &&
  11306. isAfterNode &&
  11307. dom.isEmpty(parentBlockContainer)
  11308. ) {
  11309. return Optional.some(CaretPosition(parentNode, dom.nodeIndex(startNode)));
  11310. }
  11311. const walker = new DomTreeWalker(startNode, parentBlockContainer);
  11312. while ((node = walker[left ? "prev" : "next"]())) {
  11313. if (
  11314. dom.getContentEditableParent(node) === "false" ||
  11315. isCeFalseCaretContainer(node, body)
  11316. ) {
  11317. return Optional.none();
  11318. }
  11319. if (isText$a(node) && node.data.length > 0) {
  11320. if (!hasParentWithName(node, body, "A")) {
  11321. return Optional.some(
  11322. CaretPosition(node, left ? node.data.length : 0)
  11323. );
  11324. }
  11325. return Optional.none();
  11326. }
  11327. if (
  11328. dom.isBlock(node) ||
  11329. nonEmptyElementsMap[node.nodeName.toLowerCase()]
  11330. ) {
  11331. return Optional.none();
  11332. }
  11333. lastInlineElement = node;
  11334. }
  11335. if (isComment(lastInlineElement)) {
  11336. return Optional.none();
  11337. }
  11338. if (collapsed && lastInlineElement) {
  11339. return Optional.some(CaretPosition(lastInlineElement, 0));
  11340. }
  11341. return Optional.none();
  11342. };
  11343. const normalizeEndPoint = (dom, collapsed, start, rng) => {
  11344. const body = dom.getRoot();
  11345. let node;
  11346. let normalized = false;
  11347. let container = start ? rng.startContainer : rng.endContainer;
  11348. let offset = start ? rng.startOffset : rng.endOffset;
  11349. const isAfterNode =
  11350. isElement$6(container) && offset === container.childNodes.length;
  11351. const nonEmptyElementsMap = dom.schema.getNonEmptyElements();
  11352. let directionLeft = start;
  11353. if (isCaretContainer$2(container)) {
  11354. return Optional.none();
  11355. }
  11356. if (isElement$6(container) && offset > container.childNodes.length - 1) {
  11357. directionLeft = false;
  11358. }
  11359. if (isDocument$1(container)) {
  11360. container = body;
  11361. offset = 0;
  11362. }
  11363. if (container === body) {
  11364. if (directionLeft) {
  11365. node = container.childNodes[offset > 0 ? offset - 1 : 0];
  11366. if (node) {
  11367. if (isCaretContainer$2(node)) {
  11368. return Optional.none();
  11369. }
  11370. if (nonEmptyElementsMap[node.nodeName] || isTable$2(node)) {
  11371. return Optional.none();
  11372. }
  11373. }
  11374. }
  11375. if (container.hasChildNodes()) {
  11376. offset = Math.min(
  11377. !directionLeft && offset > 0 ? offset - 1 : offset,
  11378. container.childNodes.length - 1
  11379. );
  11380. container = container.childNodes[offset];
  11381. offset = isText$a(container) && isAfterNode ? container.data.length : 0;
  11382. if (
  11383. !collapsed &&
  11384. container === body.lastChild &&
  11385. isTable$2(container)
  11386. ) {
  11387. return Optional.none();
  11388. }
  11389. if (
  11390. hasContentEditableFalseParent(body, container) ||
  11391. isCaretContainer$2(container)
  11392. ) {
  11393. return Optional.none();
  11394. }
  11395. if (container.hasChildNodes() && !isTable$2(container)) {
  11396. node = container;
  11397. const walker = new DomTreeWalker(container, body);
  11398. do {
  11399. if (isContentEditableFalse$b(node) || isCaretContainer$2(node)) {
  11400. normalized = false;
  11401. break;
  11402. }
  11403. if (isText$a(node) && node.data.length > 0) {
  11404. offset = directionLeft ? 0 : node.data.length;
  11405. container = node;
  11406. normalized = true;
  11407. break;
  11408. }
  11409. if (
  11410. nonEmptyElementsMap[node.nodeName.toLowerCase()] &&
  11411. !isTableCellOrCaption(node)
  11412. ) {
  11413. offset = dom.nodeIndex(node);
  11414. container = node.parentNode;
  11415. if (!directionLeft) {
  11416. offset++;
  11417. }
  11418. normalized = true;
  11419. break;
  11420. }
  11421. } while ((node = directionLeft ? walker.next() : walker.prev()));
  11422. }
  11423. }
  11424. }
  11425. if (collapsed) {
  11426. if (isText$a(container) && offset === 0) {
  11427. findTextNodeRelative(dom, isAfterNode, collapsed, true, container).each(
  11428. (pos) => {
  11429. container = pos.container();
  11430. offset = pos.offset();
  11431. normalized = true;
  11432. }
  11433. );
  11434. }
  11435. if (isElement$6(container)) {
  11436. node = container.childNodes[offset];
  11437. if (!node) {
  11438. node = container.childNodes[offset - 1];
  11439. }
  11440. if (
  11441. node &&
  11442. isBr$6(node) &&
  11443. !isPrevNode(node, "A") &&
  11444. !hasBrBeforeAfter(dom, node, false) &&
  11445. !hasBrBeforeAfter(dom, node, true)
  11446. ) {
  11447. findTextNodeRelative(dom, isAfterNode, collapsed, true, node).each(
  11448. (pos) => {
  11449. container = pos.container();
  11450. offset = pos.offset();
  11451. normalized = true;
  11452. }
  11453. );
  11454. }
  11455. }
  11456. }
  11457. if (
  11458. directionLeft &&
  11459. !collapsed &&
  11460. isText$a(container) &&
  11461. offset === container.data.length
  11462. ) {
  11463. findTextNodeRelative(dom, isAfterNode, collapsed, false, container).each(
  11464. (pos) => {
  11465. container = pos.container();
  11466. offset = pos.offset();
  11467. normalized = true;
  11468. }
  11469. );
  11470. }
  11471. return normalized && container
  11472. ? Optional.some(CaretPosition(container, offset))
  11473. : Optional.none();
  11474. };
  11475. const normalize$2 = (dom, rng) => {
  11476. const collapsed = rng.collapsed,
  11477. normRng = rng.cloneRange();
  11478. const startPos = CaretPosition.fromRangeStart(rng);
  11479. normalizeEndPoint(dom, collapsed, true, normRng).each((pos) => {
  11480. if (!collapsed || !CaretPosition.isAbove(startPos, pos)) {
  11481. normRng.setStart(pos.container(), pos.offset());
  11482. }
  11483. });
  11484. if (!collapsed) {
  11485. normalizeEndPoint(dom, collapsed, false, normRng).each((pos) => {
  11486. normRng.setEnd(pos.container(), pos.offset());
  11487. });
  11488. }
  11489. if (collapsed) {
  11490. normRng.collapse(true);
  11491. }
  11492. return isEq$4(rng, normRng) ? Optional.none() : Optional.some(normRng);
  11493. };
  11494. const splitText = (node, offset) => {
  11495. return node.splitText(offset);
  11496. };
  11497. const split = (rng) => {
  11498. let startContainer = rng.startContainer,
  11499. startOffset = rng.startOffset,
  11500. endContainer = rng.endContainer,
  11501. endOffset = rng.endOffset;
  11502. if (startContainer === endContainer && isText$a(startContainer)) {
  11503. if (startOffset > 0 && startOffset < startContainer.data.length) {
  11504. endContainer = splitText(startContainer, startOffset);
  11505. startContainer = endContainer.previousSibling;
  11506. if (endOffset > startOffset) {
  11507. endOffset = endOffset - startOffset;
  11508. const newContainer = splitText(
  11509. endContainer,
  11510. endOffset
  11511. ).previousSibling;
  11512. startContainer = endContainer = newContainer;
  11513. endOffset = newContainer.data.length;
  11514. startOffset = 0;
  11515. } else {
  11516. endOffset = 0;
  11517. }
  11518. }
  11519. } else {
  11520. if (
  11521. isText$a(startContainer) &&
  11522. startOffset > 0 &&
  11523. startOffset < startContainer.data.length
  11524. ) {
  11525. startContainer = splitText(startContainer, startOffset);
  11526. startOffset = 0;
  11527. }
  11528. if (
  11529. isText$a(endContainer) &&
  11530. endOffset > 0 &&
  11531. endOffset < endContainer.data.length
  11532. ) {
  11533. const newContainer = splitText(endContainer, endOffset).previousSibling;
  11534. endContainer = newContainer;
  11535. endOffset = newContainer.data.length;
  11536. }
  11537. }
  11538. return {
  11539. startContainer,
  11540. startOffset,
  11541. endContainer,
  11542. endOffset,
  11543. };
  11544. };
  11545. const RangeUtils = (dom) => {
  11546. const walk = (rng, callback) => {
  11547. return walk$3(dom, rng, callback);
  11548. };
  11549. const split$1 = split;
  11550. const normalize = (rng) => {
  11551. return normalize$2(dom, rng).fold(never, (normalizedRng) => {
  11552. rng.setStart(normalizedRng.startContainer, normalizedRng.startOffset);
  11553. rng.setEnd(normalizedRng.endContainer, normalizedRng.endOffset);
  11554. return true;
  11555. });
  11556. };
  11557. const expand = (rng, options = { type: "word" }) => {
  11558. if (options.type === "word") {
  11559. const rangeLike = expandRng(dom, rng, [{ inline: "span" }]);
  11560. const newRange = dom.createRng();
  11561. newRange.setStart(rangeLike.startContainer, rangeLike.startOffset);
  11562. newRange.setEnd(rangeLike.endContainer, rangeLike.endOffset);
  11563. return newRange;
  11564. }
  11565. return rng;
  11566. };
  11567. return {
  11568. walk,
  11569. split: split$1,
  11570. expand,
  11571. normalize,
  11572. };
  11573. };
  11574. RangeUtils.compareRanges = isEq$4;
  11575. RangeUtils.getCaretRangeFromPoint = fromPoint;
  11576. RangeUtils.getSelectedNode = getSelectedNode;
  11577. RangeUtils.getNode = getNode$1;
  11578. const Dimension = (name, getOffset) => {
  11579. const set = (element, h) => {
  11580. if (!isNumber(h) && !h.match(/^[0-9]+$/)) {
  11581. throw new Error(
  11582. name + ".set accepts only positive integer values. Value was " + h
  11583. );
  11584. }
  11585. const dom = element.dom;
  11586. if (isSupported(dom)) {
  11587. dom.style[name] = h + "px";
  11588. }
  11589. };
  11590. const get = (element) => {
  11591. const r = getOffset(element);
  11592. if (r <= 0 || r === null) {
  11593. const css = get$7(element, name);
  11594. return parseFloat(css) || 0;
  11595. }
  11596. return r;
  11597. };
  11598. const getOuter = get;
  11599. const aggregate = (element, properties) =>
  11600. foldl(
  11601. properties,
  11602. (acc, property) => {
  11603. const val = get$7(element, property);
  11604. const value = val === undefined ? 0 : parseInt(val, 10);
  11605. return isNaN(value) ? acc : acc + value;
  11606. },
  11607. 0
  11608. );
  11609. const max = (element, value, properties) => {
  11610. const cumulativeInclusions = aggregate(element, properties);
  11611. const absoluteMax =
  11612. value > cumulativeInclusions ? value - cumulativeInclusions : 0;
  11613. return absoluteMax;
  11614. };
  11615. return {
  11616. set,
  11617. get,
  11618. getOuter,
  11619. aggregate,
  11620. max,
  11621. };
  11622. };
  11623. const api = Dimension("height", (element) => {
  11624. const dom = element.dom;
  11625. return inBody(element)
  11626. ? dom.getBoundingClientRect().height
  11627. : dom.offsetHeight;
  11628. });
  11629. const get$2 = (element) => api.get(element);
  11630. const getDocument = () => SugarElement.fromDom(document);
  11631. const walkUp = (navigation, doc) => {
  11632. const frame = navigation.view(doc);
  11633. return frame.fold(constant([]), (f) => {
  11634. const parent = navigation.owner(f);
  11635. const rest = walkUp(navigation, parent);
  11636. return [f].concat(rest);
  11637. });
  11638. };
  11639. const pathTo = (element, navigation) => {
  11640. const d = navigation.owner(element);
  11641. return walkUp(navigation, d);
  11642. };
  11643. const view = (doc) => {
  11644. var _a;
  11645. const element =
  11646. doc.dom === document
  11647. ? Optional.none()
  11648. : Optional.from(
  11649. (_a = doc.dom.defaultView) === null || _a === void 0
  11650. ? void 0
  11651. : _a.frameElement
  11652. );
  11653. return element.map(SugarElement.fromDom);
  11654. };
  11655. const owner = (element) => documentOrOwner(element);
  11656. var Navigation = /*#__PURE__*/ Object.freeze({
  11657. __proto__: null,
  11658. view: view,
  11659. owner: owner,
  11660. });
  11661. const find = (element) => {
  11662. const doc = getDocument();
  11663. const scroll = get$5(doc);
  11664. const frames = pathTo(element, Navigation);
  11665. const offset = viewport(element);
  11666. const r = foldr(
  11667. frames,
  11668. (b, a) => {
  11669. const loc = viewport(a);
  11670. return {
  11671. left: b.left + loc.left,
  11672. top: b.top + loc.top,
  11673. };
  11674. },
  11675. {
  11676. left: 0,
  11677. top: 0,
  11678. }
  11679. );
  11680. return SugarPosition(
  11681. r.left + offset.left + scroll.left,
  11682. r.top + offset.top + scroll.top
  11683. );
  11684. };
  11685. const excludeFromDescend = (element) => name(element) === "textarea";
  11686. const fireScrollIntoViewEvent = (editor, data) => {
  11687. const scrollEvent = editor.dispatch("ScrollIntoView", data);
  11688. return scrollEvent.isDefaultPrevented();
  11689. };
  11690. const fireAfterScrollIntoViewEvent = (editor, data) => {
  11691. editor.dispatch("AfterScrollIntoView", data);
  11692. };
  11693. const descend = (element, offset) => {
  11694. const children = children$1(element);
  11695. if (children.length === 0 || excludeFromDescend(element)) {
  11696. return {
  11697. element,
  11698. offset,
  11699. };
  11700. } else if (
  11701. offset < children.length &&
  11702. !excludeFromDescend(children[offset])
  11703. ) {
  11704. return {
  11705. element: children[offset],
  11706. offset: 0,
  11707. };
  11708. } else {
  11709. const last = children[children.length - 1];
  11710. if (excludeFromDescend(last)) {
  11711. return {
  11712. element,
  11713. offset,
  11714. };
  11715. } else {
  11716. if (name(last) === "img") {
  11717. return {
  11718. element: last,
  11719. offset: 1,
  11720. };
  11721. } else if (isText$b(last)) {
  11722. return {
  11723. element: last,
  11724. offset: get$3(last).length,
  11725. };
  11726. } else {
  11727. return {
  11728. element: last,
  11729. offset: children$1(last).length,
  11730. };
  11731. }
  11732. }
  11733. }
  11734. };
  11735. const markerInfo = (element, cleanupFun) => {
  11736. const pos = absolute(element);
  11737. const height = get$2(element);
  11738. return {
  11739. element,
  11740. bottom: pos.top + height,
  11741. height,
  11742. pos,
  11743. cleanup: cleanupFun,
  11744. };
  11745. };
  11746. const createMarker$1 = (element, offset) => {
  11747. const startPoint = descend(element, offset);
  11748. const span = SugarElement.fromHtml(
  11749. '<span data-mce-bogus="all" style="display: inline-block;">' +
  11750. ZWSP$1 +
  11751. "</span>"
  11752. );
  11753. before$3(startPoint.element, span);
  11754. return markerInfo(span, () => remove$5(span));
  11755. };
  11756. const elementMarker = (element) =>
  11757. markerInfo(SugarElement.fromDom(element), noop);
  11758. const withMarker = (editor, f, rng, alignToTop) => {
  11759. preserveWith(
  11760. editor,
  11761. (_s, _e) => applyWithMarker(editor, f, rng, alignToTop),
  11762. rng
  11763. );
  11764. };
  11765. const withScrollEvents = (editor, doc, f, marker, alignToTop) => {
  11766. const data = {
  11767. elm: marker.element.dom,
  11768. alignToTop,
  11769. };
  11770. if (fireScrollIntoViewEvent(editor, data)) {
  11771. return;
  11772. }
  11773. const scrollTop = get$5(doc).top;
  11774. f(editor, doc, scrollTop, marker, alignToTop);
  11775. fireAfterScrollIntoViewEvent(editor, data);
  11776. };
  11777. const applyWithMarker = (editor, f, rng, alignToTop) => {
  11778. const body = SugarElement.fromDom(editor.getBody());
  11779. const doc = SugarElement.fromDom(editor.getDoc());
  11780. reflow(body);
  11781. const marker = createMarker$1(
  11782. SugarElement.fromDom(rng.startContainer),
  11783. rng.startOffset
  11784. );
  11785. withScrollEvents(editor, doc, f, marker, alignToTop);
  11786. marker.cleanup();
  11787. };
  11788. const withElement = (editor, element, f, alignToTop) => {
  11789. const doc = SugarElement.fromDom(editor.getDoc());
  11790. withScrollEvents(editor, doc, f, elementMarker(element), alignToTop);
  11791. };
  11792. const preserveWith = (editor, f, rng) => {
  11793. const startElement = rng.startContainer;
  11794. const startOffset = rng.startOffset;
  11795. const endElement = rng.endContainer;
  11796. const endOffset = rng.endOffset;
  11797. f(SugarElement.fromDom(startElement), SugarElement.fromDom(endElement));
  11798. const newRng = editor.dom.createRng();
  11799. newRng.setStart(startElement, startOffset);
  11800. newRng.setEnd(endElement, endOffset);
  11801. editor.selection.setRng(rng);
  11802. };
  11803. const scrollToMarker = (editor, marker, viewHeight, alignToTop, doc) => {
  11804. const pos = marker.pos;
  11805. if (alignToTop) {
  11806. to(pos.left, pos.top, doc);
  11807. } else {
  11808. const y = pos.top - viewHeight + marker.height;
  11809. to(-editor.getBody().getBoundingClientRect().left, y, doc);
  11810. }
  11811. };
  11812. const intoWindowIfNeeded = (
  11813. editor,
  11814. doc,
  11815. scrollTop,
  11816. viewHeight,
  11817. marker,
  11818. alignToTop
  11819. ) => {
  11820. const viewportBottom = viewHeight + scrollTop;
  11821. const markerTop = marker.pos.top;
  11822. const markerBottom = marker.bottom;
  11823. const largerThanViewport = markerBottom - markerTop >= viewHeight;
  11824. if (markerTop < scrollTop) {
  11825. scrollToMarker(editor, marker, viewHeight, alignToTop !== false, doc);
  11826. } else if (markerTop > viewportBottom) {
  11827. const align = largerThanViewport
  11828. ? alignToTop !== false
  11829. : alignToTop === true;
  11830. scrollToMarker(editor, marker, viewHeight, align, doc);
  11831. } else if (markerBottom > viewportBottom && !largerThanViewport) {
  11832. scrollToMarker(editor, marker, viewHeight, alignToTop === true, doc);
  11833. }
  11834. };
  11835. const intoWindow = (editor, doc, scrollTop, marker, alignToTop) => {
  11836. const viewHeight = defaultView(doc).dom.innerHeight;
  11837. intoWindowIfNeeded(editor, doc, scrollTop, viewHeight, marker, alignToTop);
  11838. };
  11839. const intoFrame = (editor, doc, scrollTop, marker, alignToTop) => {
  11840. const frameViewHeight = defaultView(doc).dom.innerHeight;
  11841. intoWindowIfNeeded(
  11842. editor,
  11843. doc,
  11844. scrollTop,
  11845. frameViewHeight,
  11846. marker,
  11847. alignToTop
  11848. );
  11849. const op = find(marker.element);
  11850. const viewportBounds = getBounds(window);
  11851. if (op.top < viewportBounds.y) {
  11852. intoView(marker.element, alignToTop !== false);
  11853. } else if (op.top > viewportBounds.bottom) {
  11854. intoView(marker.element, alignToTop === true);
  11855. }
  11856. };
  11857. const rangeIntoWindow = (editor, rng, alignToTop) =>
  11858. withMarker(editor, intoWindow, rng, alignToTop);
  11859. const elementIntoWindow = (editor, element, alignToTop) =>
  11860. withElement(editor, element, intoWindow, alignToTop);
  11861. const rangeIntoFrame = (editor, rng, alignToTop) =>
  11862. withMarker(editor, intoFrame, rng, alignToTop);
  11863. const elementIntoFrame = (editor, element, alignToTop) =>
  11864. withElement(editor, element, intoFrame, alignToTop);
  11865. const scrollElementIntoView = (editor, element, alignToTop) => {
  11866. const scroller = editor.inline ? elementIntoWindow : elementIntoFrame;
  11867. scroller(editor, element, alignToTop);
  11868. };
  11869. const scrollRangeIntoView = (editor, rng, alignToTop) => {
  11870. const scroller = editor.inline ? rangeIntoWindow : rangeIntoFrame;
  11871. scroller(editor, rng, alignToTop);
  11872. };
  11873. const focus$1 = (element) => element.dom.focus();
  11874. const hasFocus$1 = (element) => {
  11875. const root = getRootNode(element).dom;
  11876. return element.dom === root.activeElement;
  11877. };
  11878. const active$1 = (root = getDocument()) =>
  11879. Optional.from(root.dom.activeElement).map(SugarElement.fromDom);
  11880. const search = (element) =>
  11881. active$1(getRootNode(element)).filter((e) => element.dom.contains(e.dom));
  11882. const clamp$1 = (offset, element) => {
  11883. const max = isText$b(element)
  11884. ? get$3(element).length
  11885. : children$1(element).length + 1;
  11886. if (offset > max) {
  11887. return max;
  11888. } else if (offset < 0) {
  11889. return 0;
  11890. }
  11891. return offset;
  11892. };
  11893. const normalizeRng = (rng) =>
  11894. SimSelection.range(
  11895. rng.start,
  11896. clamp$1(rng.soffset, rng.start),
  11897. rng.finish,
  11898. clamp$1(rng.foffset, rng.finish)
  11899. );
  11900. const isOrContains = (root, elm) =>
  11901. !isRestrictedNode(elm.dom) && (contains(root, elm) || eq(root, elm));
  11902. const isRngInRoot = (root) => (rng) =>
  11903. isOrContains(root, rng.start) && isOrContains(root, rng.finish);
  11904. const shouldStore = (editor) => editor.inline || Env.browser.isFirefox();
  11905. const nativeRangeToSelectionRange = (r) =>
  11906. SimSelection.range(
  11907. SugarElement.fromDom(r.startContainer),
  11908. r.startOffset,
  11909. SugarElement.fromDom(r.endContainer),
  11910. r.endOffset
  11911. );
  11912. const readRange = (win) => {
  11913. const selection = win.getSelection();
  11914. const rng =
  11915. !selection || selection.rangeCount === 0
  11916. ? Optional.none()
  11917. : Optional.from(selection.getRangeAt(0));
  11918. return rng.map(nativeRangeToSelectionRange);
  11919. };
  11920. const getBookmark = (root) => {
  11921. const win = defaultView(root);
  11922. return readRange(win.dom).filter(isRngInRoot(root));
  11923. };
  11924. const validate = (root, bookmark) =>
  11925. Optional.from(bookmark).filter(isRngInRoot(root)).map(normalizeRng);
  11926. const bookmarkToNativeRng = (bookmark) => {
  11927. const rng = document.createRange();
  11928. try {
  11929. rng.setStart(bookmark.start.dom, bookmark.soffset);
  11930. rng.setEnd(bookmark.finish.dom, bookmark.foffset);
  11931. return Optional.some(rng);
  11932. } catch (_) {
  11933. return Optional.none();
  11934. }
  11935. };
  11936. const store = (editor) => {
  11937. const newBookmark = shouldStore(editor)
  11938. ? getBookmark(SugarElement.fromDom(editor.getBody()))
  11939. : Optional.none();
  11940. editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
  11941. };
  11942. const getRng = (editor) => {
  11943. const bookmark = editor.bookmark ? editor.bookmark : Optional.none();
  11944. return bookmark
  11945. .bind((x) => validate(SugarElement.fromDom(editor.getBody()), x))
  11946. .bind(bookmarkToNativeRng);
  11947. };
  11948. const restore = (editor) => {
  11949. getRng(editor).each((rng) => editor.selection.setRng(rng));
  11950. };
  11951. const isEditorUIElement$1 = (elm) => {
  11952. const className = elm.className.toString();
  11953. return className.indexOf("tox-") !== -1 || className.indexOf("mce-") !== -1;
  11954. };
  11955. const FocusManager = { isEditorUIElement: isEditorUIElement$1 };
  11956. const wrappedSetTimeout = (callback, time) => {
  11957. if (!isNumber(time)) {
  11958. time = 0;
  11959. }
  11960. return setTimeout(callback, time);
  11961. };
  11962. const wrappedSetInterval = (callback, time) => {
  11963. if (!isNumber(time)) {
  11964. time = 0;
  11965. }
  11966. return setInterval(callback, time);
  11967. };
  11968. const Delay = {
  11969. setEditorTimeout: (editor, callback, time) => {
  11970. return wrappedSetTimeout(() => {
  11971. if (!editor.removed) {
  11972. callback();
  11973. }
  11974. }, time);
  11975. },
  11976. setEditorInterval: (editor, callback, time) => {
  11977. const timer = wrappedSetInterval(() => {
  11978. if (!editor.removed) {
  11979. callback();
  11980. } else {
  11981. clearInterval(timer);
  11982. }
  11983. }, time);
  11984. return timer;
  11985. },
  11986. };
  11987. const isManualNodeChange = (e) => {
  11988. return e.type === "nodechange" && e.selectionChange;
  11989. };
  11990. const registerPageMouseUp = (editor, throttledStore) => {
  11991. const mouseUpPage = () => {
  11992. throttledStore.throttle();
  11993. };
  11994. DOMUtils.DOM.bind(document, "mouseup", mouseUpPage);
  11995. editor.on("remove", () => {
  11996. DOMUtils.DOM.unbind(document, "mouseup", mouseUpPage);
  11997. });
  11998. };
  11999. const registerMouseUp = (editor, throttledStore) => {
  12000. editor.on("mouseup touchend", (_e) => {
  12001. throttledStore.throttle();
  12002. });
  12003. };
  12004. const registerEditorEvents = (editor, throttledStore) => {
  12005. registerMouseUp(editor, throttledStore);
  12006. editor.on("keyup NodeChange AfterSetSelectionRange", (e) => {
  12007. if (!isManualNodeChange(e)) {
  12008. store(editor);
  12009. }
  12010. });
  12011. };
  12012. const register$6 = (editor) => {
  12013. const throttledStore = first$1(() => {
  12014. store(editor);
  12015. }, 0);
  12016. editor.on("init", () => {
  12017. if (editor.inline) {
  12018. registerPageMouseUp(editor, throttledStore);
  12019. }
  12020. registerEditorEvents(editor, throttledStore);
  12021. });
  12022. editor.on("remove", () => {
  12023. throttledStore.cancel();
  12024. });
  12025. };
  12026. let documentFocusInHandler;
  12027. const DOM$9 = DOMUtils.DOM;
  12028. const isEditorUIElement = (elm) => {
  12029. return isElement$6(elm) && FocusManager.isEditorUIElement(elm);
  12030. };
  12031. const isEditorContentAreaElement = (elm) => {
  12032. const classList = elm.classList;
  12033. if (classList !== undefined) {
  12034. return (
  12035. classList.contains("tox-edit-area") ||
  12036. classList.contains("tox-edit-area__iframe") ||
  12037. classList.contains("mce-content-body")
  12038. );
  12039. } else {
  12040. return false;
  12041. }
  12042. };
  12043. const isUIElement = (editor, elm) => {
  12044. const customSelector = getCustomUiSelector(editor);
  12045. const parent = DOM$9.getParent(elm, (elm) => {
  12046. return (
  12047. isEditorUIElement(elm) ||
  12048. (customSelector ? editor.dom.is(elm, customSelector) : false)
  12049. );
  12050. });
  12051. return parent !== null;
  12052. };
  12053. const getActiveElement = (editor) => {
  12054. try {
  12055. const root = getRootNode(SugarElement.fromDom(editor.getElement()));
  12056. return active$1(root).fold(
  12057. () => document.body,
  12058. (x) => x.dom
  12059. );
  12060. } catch (ex) {
  12061. return document.body;
  12062. }
  12063. };
  12064. const registerEvents$1 = (editorManager, e) => {
  12065. const editor = e.editor;
  12066. register$6(editor);
  12067. const toggleContentAreaOnFocus = (editor, fn) => {
  12068. if (shouldHighlightOnFocus(editor) && editor.inline !== true) {
  12069. const contentArea = SugarElement.fromDom(editor.getContainer());
  12070. fn(contentArea, "tox-edit-focus");
  12071. }
  12072. };
  12073. editor.on("focusin", () => {
  12074. const focusedEditor = editorManager.focusedEditor;
  12075. if (isEditorContentAreaElement(getActiveElement(editor))) {
  12076. toggleContentAreaOnFocus(editor, add$2);
  12077. }
  12078. if (focusedEditor !== editor) {
  12079. if (focusedEditor) {
  12080. focusedEditor.dispatch("blur", { focusedEditor: editor });
  12081. }
  12082. editorManager.setActive(editor);
  12083. editorManager.focusedEditor = editor;
  12084. editor.dispatch("focus", { blurredEditor: focusedEditor });
  12085. editor.focus(true);
  12086. }
  12087. });
  12088. editor.on("focusout", () => {
  12089. Delay.setEditorTimeout(editor, () => {
  12090. const focusedEditor = editorManager.focusedEditor;
  12091. if (
  12092. !isEditorContentAreaElement(getActiveElement(editor)) ||
  12093. focusedEditor !== editor
  12094. ) {
  12095. toggleContentAreaOnFocus(editor, remove$7);
  12096. }
  12097. if (
  12098. !isUIElement(editor, getActiveElement(editor)) &&
  12099. focusedEditor === editor
  12100. ) {
  12101. editor.dispatch("blur", { focusedEditor: null });
  12102. editorManager.focusedEditor = null;
  12103. }
  12104. });
  12105. });
  12106. if (!documentFocusInHandler) {
  12107. documentFocusInHandler = (e) => {
  12108. const activeEditor = editorManager.activeEditor;
  12109. if (activeEditor) {
  12110. getOriginalEventTarget(e).each((target) => {
  12111. const elem = target;
  12112. if (elem.ownerDocument === document) {
  12113. if (
  12114. elem !== document.body &&
  12115. !isUIElement(activeEditor, elem) &&
  12116. editorManager.focusedEditor === activeEditor
  12117. ) {
  12118. activeEditor.dispatch("blur", { focusedEditor: null });
  12119. editorManager.focusedEditor = null;
  12120. }
  12121. }
  12122. });
  12123. }
  12124. };
  12125. DOM$9.bind(document, "focusin", documentFocusInHandler);
  12126. }
  12127. };
  12128. const unregisterDocumentEvents = (editorManager, e) => {
  12129. if (editorManager.focusedEditor === e.editor) {
  12130. editorManager.focusedEditor = null;
  12131. }
  12132. if (!editorManager.activeEditor && documentFocusInHandler) {
  12133. DOM$9.unbind(document, "focusin", documentFocusInHandler);
  12134. documentFocusInHandler = null;
  12135. }
  12136. };
  12137. const setup$v = (editorManager) => {
  12138. editorManager.on("AddEditor", curry(registerEvents$1, editorManager));
  12139. editorManager.on(
  12140. "RemoveEditor",
  12141. curry(unregisterDocumentEvents, editorManager)
  12142. );
  12143. };
  12144. const getContentEditableHost = (editor, node) =>
  12145. editor.dom.getParent(
  12146. node,
  12147. (node) => editor.dom.getContentEditable(node) === "true"
  12148. );
  12149. const getCollapsedNode = (rng) =>
  12150. rng.collapsed
  12151. ? Optional.from(getNode$1(rng.startContainer, rng.startOffset)).map(
  12152. SugarElement.fromDom
  12153. )
  12154. : Optional.none();
  12155. const getFocusInElement = (root, rng) =>
  12156. getCollapsedNode(rng).bind((node) => {
  12157. if (isTableSection(node)) {
  12158. return Optional.some(node);
  12159. } else if (!contains(root, node)) {
  12160. return Optional.some(root);
  12161. } else {
  12162. return Optional.none();
  12163. }
  12164. });
  12165. const normalizeSelection = (editor, rng) => {
  12166. getFocusInElement(SugarElement.fromDom(editor.getBody()), rng)
  12167. .bind((elm) => {
  12168. return firstPositionIn(elm.dom);
  12169. })
  12170. .fold(
  12171. () => {
  12172. editor.selection.normalize();
  12173. },
  12174. (caretPos) => editor.selection.setRng(caretPos.toRange())
  12175. );
  12176. };
  12177. const focusBody = (body) => {
  12178. if (body.setActive) {
  12179. try {
  12180. body.setActive();
  12181. } catch (ex) {
  12182. body.focus();
  12183. }
  12184. } else {
  12185. body.focus();
  12186. }
  12187. };
  12188. const hasElementFocus = (elm) => hasFocus$1(elm) || search(elm).isSome();
  12189. const hasIframeFocus = (editor) =>
  12190. isNonNullable(editor.iframeElement) &&
  12191. hasFocus$1(SugarElement.fromDom(editor.iframeElement));
  12192. const hasInlineFocus = (editor) => {
  12193. const rawBody = editor.getBody();
  12194. return rawBody && hasElementFocus(SugarElement.fromDom(rawBody));
  12195. };
  12196. const hasUiFocus = (editor) => {
  12197. const dos = getRootNode(SugarElement.fromDom(editor.getElement()));
  12198. return active$1(dos)
  12199. .filter(
  12200. (elem) =>
  12201. !isEditorContentAreaElement(elem.dom) && isUIElement(editor, elem.dom)
  12202. )
  12203. .isSome();
  12204. };
  12205. const hasFocus = (editor) =>
  12206. editor.inline ? hasInlineFocus(editor) : hasIframeFocus(editor);
  12207. const hasEditorOrUiFocus = (editor) => hasFocus(editor) || hasUiFocus(editor);
  12208. const focusEditor = (editor) => {
  12209. const selection = editor.selection;
  12210. const body = editor.getBody();
  12211. let rng = selection.getRng();
  12212. editor.quirks.refreshContentEditable();
  12213. if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
  12214. getRng(editor).each((bookmarkRng) => {
  12215. editor.selection.setRng(bookmarkRng);
  12216. rng = bookmarkRng;
  12217. });
  12218. }
  12219. const contentEditableHost = getContentEditableHost(
  12220. editor,
  12221. selection.getNode()
  12222. );
  12223. if (
  12224. contentEditableHost &&
  12225. editor.dom.isChildOf(contentEditableHost, body)
  12226. ) {
  12227. focusBody(contentEditableHost);
  12228. normalizeSelection(editor, rng);
  12229. activateEditor(editor);
  12230. return;
  12231. }
  12232. if (!editor.inline) {
  12233. if (!Env.browser.isOpera()) {
  12234. focusBody(body);
  12235. }
  12236. editor.getWin().focus();
  12237. }
  12238. if (Env.browser.isFirefox() || editor.inline) {
  12239. focusBody(body);
  12240. normalizeSelection(editor, rng);
  12241. }
  12242. activateEditor(editor);
  12243. };
  12244. const activateEditor = (editor) => editor.editorManager.setActive(editor);
  12245. const focus = (editor, skipFocus) => {
  12246. if (editor.removed) {
  12247. return;
  12248. }
  12249. if (skipFocus) {
  12250. activateEditor(editor);
  12251. } else {
  12252. focusEditor(editor);
  12253. }
  12254. };
  12255. const getEndpointElement = (root, rng, start, real, resolve) => {
  12256. const container = start ? rng.startContainer : rng.endContainer;
  12257. const offset = start ? rng.startOffset : rng.endOffset;
  12258. return Optional.from(container)
  12259. .map(SugarElement.fromDom)
  12260. .map((elm) =>
  12261. !real || !rng.collapsed
  12262. ? child$1(elm, resolve(elm, offset)).getOr(elm)
  12263. : elm
  12264. )
  12265. .bind((elm) =>
  12266. isElement$7(elm) ? Optional.some(elm) : parent(elm).filter(isElement$7)
  12267. )
  12268. .map((elm) => elm.dom)
  12269. .getOr(root);
  12270. };
  12271. const getStart = (root, rng, real = false) =>
  12272. getEndpointElement(root, rng, true, real, (elm, offset) =>
  12273. Math.min(childNodesCount(elm), offset)
  12274. );
  12275. const getEnd$1 = (root, rng, real = false) =>
  12276. getEndpointElement(root, rng, false, real, (elm, offset) =>
  12277. offset > 0 ? offset - 1 : offset
  12278. );
  12279. const skipEmptyTextNodes = (node, forwards) => {
  12280. const orig = node;
  12281. while (node && isText$a(node) && node.length === 0) {
  12282. node = forwards ? node.nextSibling : node.previousSibling;
  12283. }
  12284. return node || orig;
  12285. };
  12286. const getNode = (root, rng) => {
  12287. if (!rng) {
  12288. return root;
  12289. }
  12290. let startContainer = rng.startContainer;
  12291. let endContainer = rng.endContainer;
  12292. const startOffset = rng.startOffset;
  12293. const endOffset = rng.endOffset;
  12294. let node = rng.commonAncestorContainer;
  12295. if (!rng.collapsed) {
  12296. if (startContainer === endContainer) {
  12297. if (endOffset - startOffset < 2) {
  12298. if (startContainer.hasChildNodes()) {
  12299. node = startContainer.childNodes[startOffset];
  12300. }
  12301. }
  12302. }
  12303. if (isText$a(startContainer) && isText$a(endContainer)) {
  12304. if (startContainer.length === startOffset) {
  12305. startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
  12306. } else {
  12307. startContainer = startContainer.parentNode;
  12308. }
  12309. if (endOffset === 0) {
  12310. endContainer = skipEmptyTextNodes(
  12311. endContainer.previousSibling,
  12312. false
  12313. );
  12314. } else {
  12315. endContainer = endContainer.parentNode;
  12316. }
  12317. if (startContainer && startContainer === endContainer) {
  12318. node = startContainer;
  12319. }
  12320. }
  12321. }
  12322. const elm = isText$a(node) ? node.parentNode : node;
  12323. return isElement$6(elm) ? elm : root;
  12324. };
  12325. const getSelectedBlocks = (dom, rng, startElm, endElm) => {
  12326. const selectedBlocks = [];
  12327. const root = dom.getRoot();
  12328. const start = dom.getParent(
  12329. startElm || getStart(root, rng, rng.collapsed),
  12330. dom.isBlock
  12331. );
  12332. const end = dom.getParent(
  12333. endElm || getEnd$1(root, rng, rng.collapsed),
  12334. dom.isBlock
  12335. );
  12336. if (start && start !== root) {
  12337. selectedBlocks.push(start);
  12338. }
  12339. if (start && end && start !== end) {
  12340. let node;
  12341. const walker = new DomTreeWalker(start, root);
  12342. while ((node = walker.next()) && node !== end) {
  12343. if (dom.isBlock(node)) {
  12344. selectedBlocks.push(node);
  12345. }
  12346. }
  12347. }
  12348. if (end && start !== end && end !== root) {
  12349. selectedBlocks.push(end);
  12350. }
  12351. return selectedBlocks;
  12352. };
  12353. const select = (dom, node, content) =>
  12354. Optional.from(node).bind((node) =>
  12355. Optional.from(node.parentNode).map((parent) => {
  12356. const idx = dom.nodeIndex(node);
  12357. const rng = dom.createRng();
  12358. rng.setStart(parent, idx);
  12359. rng.setEnd(parent, idx + 1);
  12360. if (content) {
  12361. moveEndPoint(dom, rng, node, true);
  12362. moveEndPoint(dom, rng, node, false);
  12363. }
  12364. return rng;
  12365. })
  12366. );
  12367. const processRanges = (editor, ranges) =>
  12368. map$3(ranges, (range) => {
  12369. const evt = editor.dispatch("GetSelectionRange", { range });
  12370. return evt.range !== range ? evt.range : range;
  12371. });
  12372. const getEnd = (element) =>
  12373. name(element) === "img"
  12374. ? 1
  12375. : getOption(element).fold(
  12376. () => children$1(element).length,
  12377. (v) => v.length
  12378. );
  12379. const isTextNodeWithCursorPosition = (el) =>
  12380. getOption(el)
  12381. .filter((text) => text.trim().length !== 0 || text.indexOf(nbsp) > -1)
  12382. .isSome();
  12383. const isContentEditableFalse$5 = (elem) =>
  12384. isHTMLElement(elem) && get$9(elem, "contenteditable") === "false";
  12385. const elementsWithCursorPosition = ["img", "br"];
  12386. const isCursorPosition = (elem) => {
  12387. const hasCursorPosition = isTextNodeWithCursorPosition(elem);
  12388. return (
  12389. hasCursorPosition ||
  12390. contains$2(elementsWithCursorPosition, name(elem)) ||
  12391. isContentEditableFalse$5(elem)
  12392. );
  12393. };
  12394. const first = (element) => descendant$1(element, isCursorPosition);
  12395. const last = (element) => descendantRtl(element, isCursorPosition);
  12396. const descendantRtl = (scope, predicate) => {
  12397. const descend = (element) => {
  12398. const children = children$1(element);
  12399. for (let i = children.length - 1; i >= 0; i--) {
  12400. const child = children[i];
  12401. if (predicate(child)) {
  12402. return Optional.some(child);
  12403. }
  12404. const res = descend(child);
  12405. if (res.isSome()) {
  12406. return res;
  12407. }
  12408. }
  12409. return Optional.none();
  12410. };
  12411. return descend(scope);
  12412. };
  12413. const autocompleteSelector = "[data-mce-autocompleter]";
  12414. const create$9 = (editor, range) => {
  12415. if (findIn(SugarElement.fromDom(editor.getBody())).isNone()) {
  12416. const wrapper = SugarElement.fromHtml(
  12417. '<span data-mce-autocompleter="1" data-mce-bogus="1"></span>',
  12418. editor.getDoc()
  12419. );
  12420. append$1(wrapper, SugarElement.fromDom(range.extractContents()));
  12421. range.insertNode(wrapper.dom);
  12422. parent(wrapper).each((elm) => elm.dom.normalize());
  12423. last(wrapper).map((last) => {
  12424. editor.selection.setCursorLocation(last.dom, getEnd(last));
  12425. });
  12426. }
  12427. };
  12428. const detect$1 = (elm) => closest$3(elm, autocompleteSelector);
  12429. const findIn = (elm) => descendant(elm, autocompleteSelector);
  12430. const remove$2 = (editor, elm) =>
  12431. findIn(elm).each((wrapper) => {
  12432. const bookmark = editor.selection.getBookmark();
  12433. unwrap(wrapper);
  12434. editor.selection.moveToBookmark(bookmark);
  12435. });
  12436. const typeLookup = {
  12437. "#text": 3,
  12438. "#comment": 8,
  12439. "#cdata": 4,
  12440. "#pi": 7,
  12441. "#doctype": 10,
  12442. "#document-fragment": 11,
  12443. };
  12444. const walk$2 = (node, root, prev) => {
  12445. const startName = prev ? "lastChild" : "firstChild";
  12446. const siblingName = prev ? "prev" : "next";
  12447. if (node[startName]) {
  12448. return node[startName];
  12449. }
  12450. if (node !== root) {
  12451. let sibling = node[siblingName];
  12452. if (sibling) {
  12453. return sibling;
  12454. }
  12455. for (
  12456. let parent = node.parent;
  12457. parent && parent !== root;
  12458. parent = parent.parent
  12459. ) {
  12460. sibling = parent[siblingName];
  12461. if (sibling) {
  12462. return sibling;
  12463. }
  12464. }
  12465. }
  12466. return undefined;
  12467. };
  12468. const isEmptyTextNode = (node) => {
  12469. var _a;
  12470. const text = (_a = node.value) !== null && _a !== void 0 ? _a : "";
  12471. if (!isWhitespaceText(text)) {
  12472. return false;
  12473. }
  12474. const parentNode = node.parent;
  12475. if (
  12476. parentNode &&
  12477. (parentNode.name !== "span" || parentNode.attr("style")) &&
  12478. /^[ ]+$/.test(text)
  12479. ) {
  12480. return false;
  12481. }
  12482. return true;
  12483. };
  12484. const isNonEmptyElement = (node) => {
  12485. const isNamedAnchor =
  12486. node.name === "a" && !node.attr("href") && node.attr("id");
  12487. return (
  12488. node.attr("name") ||
  12489. (node.attr("id") && !node.firstChild) ||
  12490. node.attr("data-mce-bookmark") ||
  12491. isNamedAnchor
  12492. );
  12493. };
  12494. class AstNode {
  12495. static create(name, attrs) {
  12496. const node = new AstNode(name, typeLookup[name] || 1);
  12497. if (attrs) {
  12498. each$d(attrs, (value, attrName) => {
  12499. node.attr(attrName, value);
  12500. });
  12501. }
  12502. return node;
  12503. }
  12504. constructor(name, type) {
  12505. this.name = name;
  12506. this.type = type;
  12507. if (type === 1) {
  12508. this.attributes = [];
  12509. this.attributes.map = {};
  12510. }
  12511. }
  12512. replace(node) {
  12513. const self = this;
  12514. if (node.parent) {
  12515. node.remove();
  12516. }
  12517. self.insert(node, self);
  12518. self.remove();
  12519. return self;
  12520. }
  12521. attr(name, value) {
  12522. const self = this;
  12523. if (!isString(name)) {
  12524. if (isNonNullable(name)) {
  12525. each$d(name, (value, key) => {
  12526. self.attr(key, value);
  12527. });
  12528. }
  12529. return self;
  12530. }
  12531. const attrs = self.attributes;
  12532. if (attrs) {
  12533. if (value !== undefined) {
  12534. if (value === null) {
  12535. if (name in attrs.map) {
  12536. delete attrs.map[name];
  12537. let i = attrs.length;
  12538. while (i--) {
  12539. if (attrs[i].name === name) {
  12540. attrs.splice(i, 1);
  12541. return self;
  12542. }
  12543. }
  12544. }
  12545. return self;
  12546. }
  12547. if (name in attrs.map) {
  12548. let i = attrs.length;
  12549. while (i--) {
  12550. if (attrs[i].name === name) {
  12551. attrs[i].value = value;
  12552. break;
  12553. }
  12554. }
  12555. } else {
  12556. attrs.push({
  12557. name,
  12558. value,
  12559. });
  12560. }
  12561. attrs.map[name] = value;
  12562. return self;
  12563. }
  12564. return attrs.map[name];
  12565. }
  12566. return undefined;
  12567. }
  12568. clone() {
  12569. const self = this;
  12570. const clone = new AstNode(self.name, self.type);
  12571. const selfAttrs = self.attributes;
  12572. if (selfAttrs) {
  12573. const cloneAttrs = [];
  12574. cloneAttrs.map = {};
  12575. for (let i = 0, l = selfAttrs.length; i < l; i++) {
  12576. const selfAttr = selfAttrs[i];
  12577. if (selfAttr.name !== "id") {
  12578. cloneAttrs[cloneAttrs.length] = {
  12579. name: selfAttr.name,
  12580. value: selfAttr.value,
  12581. };
  12582. cloneAttrs.map[selfAttr.name] = selfAttr.value;
  12583. }
  12584. }
  12585. clone.attributes = cloneAttrs;
  12586. }
  12587. clone.value = self.value;
  12588. return clone;
  12589. }
  12590. wrap(wrapper) {
  12591. const self = this;
  12592. if (self.parent) {
  12593. self.parent.insert(wrapper, self);
  12594. wrapper.append(self);
  12595. }
  12596. return self;
  12597. }
  12598. unwrap() {
  12599. const self = this;
  12600. for (let node = self.firstChild; node; ) {
  12601. const next = node.next;
  12602. self.insert(node, self, true);
  12603. node = next;
  12604. }
  12605. self.remove();
  12606. }
  12607. remove() {
  12608. const self = this,
  12609. parent = self.parent,
  12610. next = self.next,
  12611. prev = self.prev;
  12612. if (parent) {
  12613. if (parent.firstChild === self) {
  12614. parent.firstChild = next;
  12615. if (next) {
  12616. next.prev = null;
  12617. }
  12618. } else if (prev) {
  12619. prev.next = next;
  12620. }
  12621. if (parent.lastChild === self) {
  12622. parent.lastChild = prev;
  12623. if (prev) {
  12624. prev.next = null;
  12625. }
  12626. } else if (next) {
  12627. next.prev = prev;
  12628. }
  12629. self.parent = self.next = self.prev = null;
  12630. }
  12631. return self;
  12632. }
  12633. append(node) {
  12634. const self = this;
  12635. if (node.parent) {
  12636. node.remove();
  12637. }
  12638. const last = self.lastChild;
  12639. if (last) {
  12640. last.next = node;
  12641. node.prev = last;
  12642. self.lastChild = node;
  12643. } else {
  12644. self.lastChild = self.firstChild = node;
  12645. }
  12646. node.parent = self;
  12647. return node;
  12648. }
  12649. insert(node, refNode, before) {
  12650. if (node.parent) {
  12651. node.remove();
  12652. }
  12653. const parent = refNode.parent || this;
  12654. if (before) {
  12655. if (refNode === parent.firstChild) {
  12656. parent.firstChild = node;
  12657. } else if (refNode.prev) {
  12658. refNode.prev.next = node;
  12659. }
  12660. node.prev = refNode.prev;
  12661. node.next = refNode;
  12662. refNode.prev = node;
  12663. } else {
  12664. if (refNode === parent.lastChild) {
  12665. parent.lastChild = node;
  12666. } else if (refNode.next) {
  12667. refNode.next.prev = node;
  12668. }
  12669. node.next = refNode.next;
  12670. node.prev = refNode;
  12671. refNode.next = node;
  12672. }
  12673. node.parent = parent;
  12674. return node;
  12675. }
  12676. getAll(name) {
  12677. const self = this;
  12678. const collection = [];
  12679. for (let node = self.firstChild; node; node = walk$2(node, self)) {
  12680. if (node.name === name) {
  12681. collection.push(node);
  12682. }
  12683. }
  12684. return collection;
  12685. }
  12686. children() {
  12687. const self = this;
  12688. const collection = [];
  12689. for (let node = self.firstChild; node; node = node.next) {
  12690. collection.push(node);
  12691. }
  12692. return collection;
  12693. }
  12694. empty() {
  12695. const self = this;
  12696. if (self.firstChild) {
  12697. const nodes = [];
  12698. for (let node = self.firstChild; node; node = walk$2(node, self)) {
  12699. nodes.push(node);
  12700. }
  12701. let i = nodes.length;
  12702. while (i--) {
  12703. const node = nodes[i];
  12704. node.parent =
  12705. node.firstChild =
  12706. node.lastChild =
  12707. node.next =
  12708. node.prev =
  12709. null;
  12710. }
  12711. }
  12712. self.firstChild = self.lastChild = null;
  12713. return self;
  12714. }
  12715. isEmpty(elements, whitespace = {}, predicate) {
  12716. var _a;
  12717. const self = this;
  12718. let node = self.firstChild;
  12719. if (isNonEmptyElement(self)) {
  12720. return false;
  12721. }
  12722. if (node) {
  12723. do {
  12724. if (node.type === 1) {
  12725. if (node.attr("data-mce-bogus")) {
  12726. continue;
  12727. }
  12728. if (elements[node.name]) {
  12729. return false;
  12730. }
  12731. if (isNonEmptyElement(node)) {
  12732. return false;
  12733. }
  12734. }
  12735. if (node.type === 8) {
  12736. return false;
  12737. }
  12738. if (node.type === 3 && !isEmptyTextNode(node)) {
  12739. return false;
  12740. }
  12741. if (
  12742. node.type === 3 &&
  12743. node.parent &&
  12744. whitespace[node.parent.name] &&
  12745. isWhitespaceText(
  12746. (_a = node.value) !== null && _a !== void 0 ? _a : ""
  12747. )
  12748. ) {
  12749. return false;
  12750. }
  12751. if (predicate && predicate(node)) {
  12752. return false;
  12753. }
  12754. } while ((node = walk$2(node, self)));
  12755. }
  12756. return true;
  12757. }
  12758. walk(prev) {
  12759. return walk$2(this, null, prev);
  12760. }
  12761. }
  12762. const isConditionalComment = (html, startIndex) =>
  12763. /^\s*\[if [\w\W]+\]>.*<!\[endif\](--!?)?>/.test(html.substr(startIndex));
  12764. const findCommentEndIndex = (html, isBogus, startIndex = 0) => {
  12765. const lcHtml = html.toLowerCase();
  12766. if (
  12767. lcHtml.indexOf("[if ", startIndex) !== -1 &&
  12768. isConditionalComment(lcHtml, startIndex)
  12769. ) {
  12770. const endIfIndex = lcHtml.indexOf("[endif]", startIndex);
  12771. return lcHtml.indexOf(">", endIfIndex);
  12772. } else {
  12773. if (isBogus) {
  12774. const endIndex = lcHtml.indexOf(">", startIndex);
  12775. return endIndex !== -1 ? endIndex : lcHtml.length;
  12776. } else {
  12777. const endCommentRegexp = /--!?>/g;
  12778. endCommentRegexp.lastIndex = startIndex;
  12779. const match = endCommentRegexp.exec(html);
  12780. return match ? match.index + match[0].length : lcHtml.length;
  12781. }
  12782. }
  12783. };
  12784. const findMatchingEndTagIndex = (schema, html, startIndex) => {
  12785. const startTagRegExp = /<([!?\/])?([A-Za-z0-9\-_:.]+)/g;
  12786. const endTagRegExp =
  12787. /(?:\s(?:[^'">]+(?:"[^"]*"|'[^']*'))*[^"'>]*(?:"[^">]*|'[^'>]*)?|\s*|\/)>/g;
  12788. const voidElements = schema.getVoidElements();
  12789. let count = 1,
  12790. index = startIndex;
  12791. while (count !== 0) {
  12792. startTagRegExp.lastIndex = index;
  12793. while (true) {
  12794. const startMatch = startTagRegExp.exec(html);
  12795. if (startMatch === null) {
  12796. return index;
  12797. } else if (startMatch[1] === "!") {
  12798. if (startsWith(startMatch[2], "--")) {
  12799. index = findCommentEndIndex(
  12800. html,
  12801. false,
  12802. startMatch.index + "!--".length
  12803. );
  12804. } else {
  12805. index = findCommentEndIndex(html, true, startMatch.index + 1);
  12806. }
  12807. break;
  12808. } else {
  12809. endTagRegExp.lastIndex = startTagRegExp.lastIndex;
  12810. const endMatch = endTagRegExp.exec(html);
  12811. if (isNull(endMatch) || endMatch.index !== startTagRegExp.lastIndex) {
  12812. continue;
  12813. }
  12814. if (startMatch[1] === "/") {
  12815. count -= 1;
  12816. } else if (!has$2(voidElements, startMatch[2])) {
  12817. count += 1;
  12818. }
  12819. index = startTagRegExp.lastIndex + endMatch[0].length;
  12820. break;
  12821. }
  12822. }
  12823. }
  12824. return index;
  12825. };
  12826. const trimHtml$1 = (tempAttrs, html) => {
  12827. const trimContentRegExp = new RegExp(
  12828. ["\\s?(" + tempAttrs.join("|") + ')="[^"]+"'].join("|"),
  12829. "gi"
  12830. );
  12831. return html.replace(trimContentRegExp, "");
  12832. };
  12833. const trimInternal = (serializer, html) => {
  12834. const bogusAllRegExp = /<(\w+) [^>]*data-mce-bogus="all"[^>]*>/g;
  12835. const schema = serializer.schema;
  12836. let content = trimHtml$1(serializer.getTempAttrs(), html);
  12837. const voidElements = schema.getVoidElements();
  12838. let matches;
  12839. while ((matches = bogusAllRegExp.exec(content))) {
  12840. const index = bogusAllRegExp.lastIndex;
  12841. const matchLength = matches[0].length;
  12842. let endTagIndex;
  12843. if (voidElements[matches[1]]) {
  12844. endTagIndex = index;
  12845. } else {
  12846. endTagIndex = findMatchingEndTagIndex(schema, content, index);
  12847. }
  12848. content =
  12849. content.substring(0, index - matchLength) +
  12850. content.substring(endTagIndex);
  12851. bogusAllRegExp.lastIndex = index - matchLength;
  12852. }
  12853. return trim$1(content);
  12854. };
  12855. const trimExternal = trimInternal;
  12856. const cleanupBogusElements = (parent) => {
  12857. const bogusElements = descendants(parent, "[data-mce-bogus]");
  12858. each$e(bogusElements, (elem) => {
  12859. const bogusValue = get$9(elem, "data-mce-bogus");
  12860. if (bogusValue === "all") {
  12861. remove$5(elem);
  12862. } else if (isBr$5(elem)) {
  12863. before$3(elem, SugarElement.fromText(zeroWidth));
  12864. remove$5(elem);
  12865. } else {
  12866. unwrap(elem);
  12867. }
  12868. });
  12869. };
  12870. const cleanupInputNames = (parent) => {
  12871. const inputs = descendants(parent, "input");
  12872. each$e(inputs, (input) => {
  12873. remove$a(input, "name");
  12874. });
  12875. };
  12876. const trimEmptyContents = (editor, html) => {
  12877. const blockName = getForcedRootBlock(editor);
  12878. const emptyRegExp = new RegExp(
  12879. `^(<${blockName}[^>]*>(&nbsp;|&#160;|\\s|\u00a0|<br \\/>|)<\\/${blockName}>[\r\n]*|<br \\/>[\r\n]*)$`
  12880. );
  12881. return html.replace(emptyRegExp, "");
  12882. };
  12883. const getPlainTextContent = (editor, body) => {
  12884. const doc = editor.getDoc();
  12885. const dos = getRootNode(SugarElement.fromDom(editor.getBody()));
  12886. const offscreenDiv = SugarElement.fromTag("div", doc);
  12887. set$3(offscreenDiv, "data-mce-bogus", "all");
  12888. setAll(offscreenDiv, {
  12889. position: "fixed",
  12890. left: "-9999999px",
  12891. top: "0",
  12892. });
  12893. set$1(offscreenDiv, body.innerHTML);
  12894. cleanupBogusElements(offscreenDiv);
  12895. cleanupInputNames(offscreenDiv);
  12896. const root = getContentContainer(dos);
  12897. append$1(root, offscreenDiv);
  12898. const content = trim$1(offscreenDiv.dom.innerText);
  12899. remove$5(offscreenDiv);
  12900. return content;
  12901. };
  12902. const getContentFromBody = (editor, args, body) => {
  12903. let content;
  12904. if (args.format === "raw") {
  12905. content = Tools.trim(trimExternal(editor.serializer, body.innerHTML));
  12906. } else if (args.format === "text") {
  12907. content = getPlainTextContent(editor, body);
  12908. } else if (args.format === "tree") {
  12909. content = editor.serializer.serialize(body, args);
  12910. } else {
  12911. content = trimEmptyContents(
  12912. editor,
  12913. editor.serializer.serialize(body, args)
  12914. );
  12915. }
  12916. const shouldTrim =
  12917. args.format !== "text" &&
  12918. !isWsPreserveElement(SugarElement.fromDom(body));
  12919. return shouldTrim && isString(content) ? Tools.trim(content) : content;
  12920. };
  12921. const getContentInternal = (editor, args) =>
  12922. Optional.from(editor.getBody()).fold(
  12923. constant(args.format === "tree" ? new AstNode("body", 11) : ""),
  12924. (body) => getContentFromBody(editor, args, body)
  12925. );
  12926. const makeMap$1 = Tools.makeMap;
  12927. const Writer = (settings) => {
  12928. const html = [];
  12929. settings = settings || {};
  12930. const indent = settings.indent;
  12931. const indentBefore = makeMap$1(settings.indent_before || "");
  12932. const indentAfter = makeMap$1(settings.indent_after || "");
  12933. const encode = Entities.getEncodeFunc(
  12934. settings.entity_encoding || "raw",
  12935. settings.entities
  12936. );
  12937. const htmlOutput = settings.element_format !== "xhtml";
  12938. return {
  12939. start: (name, attrs, empty) => {
  12940. if (indent && indentBefore[name] && html.length > 0) {
  12941. const value = html[html.length - 1];
  12942. if (value.length > 0 && value !== "\n") {
  12943. html.push("\n");
  12944. }
  12945. }
  12946. html.push("<", name);
  12947. if (attrs) {
  12948. for (let i = 0, l = attrs.length; i < l; i++) {
  12949. const attr = attrs[i];
  12950. html.push(" ", attr.name, '="', encode(attr.value, true), '"');
  12951. }
  12952. }
  12953. if (!empty || htmlOutput) {
  12954. html[html.length] = ">";
  12955. } else {
  12956. html[html.length] = " />";
  12957. }
  12958. if (empty && indent && indentAfter[name] && html.length > 0) {
  12959. const value = html[html.length - 1];
  12960. if (value.length > 0 && value !== "\n") {
  12961. html.push("\n");
  12962. }
  12963. }
  12964. },
  12965. end: (name) => {
  12966. let value;
  12967. html.push("</", name, ">");
  12968. if (indent && indentAfter[name] && html.length > 0) {
  12969. value = html[html.length - 1];
  12970. if (value.length > 0 && value !== "\n") {
  12971. html.push("\n");
  12972. }
  12973. }
  12974. },
  12975. text: (text, raw) => {
  12976. if (text.length > 0) {
  12977. html[html.length] = raw ? text : encode(text);
  12978. }
  12979. },
  12980. cdata: (text) => {
  12981. html.push("<![CDATA[", text, "]]>");
  12982. },
  12983. comment: (text) => {
  12984. html.push("<!--", text, "-->");
  12985. },
  12986. pi: (name, text) => {
  12987. if (text) {
  12988. html.push("<?", name, " ", encode(text), "?>");
  12989. } else {
  12990. html.push("<?", name, "?>");
  12991. }
  12992. if (indent) {
  12993. html.push("\n");
  12994. }
  12995. },
  12996. doctype: (text) => {
  12997. html.push("<!DOCTYPE", text, ">", indent ? "\n" : "");
  12998. },
  12999. reset: () => {
  13000. html.length = 0;
  13001. },
  13002. getContent: () => {
  13003. return html.join("").replace(/\n$/, "");
  13004. },
  13005. };
  13006. };
  13007. const HtmlSerializer = (settings = {}, schema = Schema()) => {
  13008. const writer = Writer(settings);
  13009. settings.validate = "validate" in settings ? settings.validate : true;
  13010. const serialize = (node) => {
  13011. const validate = settings.validate;
  13012. const handlers = {
  13013. 3: (node) => {
  13014. var _a;
  13015. writer.text(
  13016. (_a = node.value) !== null && _a !== void 0 ? _a : "",
  13017. node.raw
  13018. );
  13019. },
  13020. 8: (node) => {
  13021. var _a;
  13022. writer.comment((_a = node.value) !== null && _a !== void 0 ? _a : "");
  13023. },
  13024. 7: (node) => {
  13025. writer.pi(node.name, node.value);
  13026. },
  13027. 10: (node) => {
  13028. var _a;
  13029. writer.doctype((_a = node.value) !== null && _a !== void 0 ? _a : "");
  13030. },
  13031. 4: (node) => {
  13032. var _a;
  13033. writer.cdata((_a = node.value) !== null && _a !== void 0 ? _a : "");
  13034. },
  13035. 11: (node) => {
  13036. let tempNode = node;
  13037. if ((tempNode = tempNode.firstChild)) {
  13038. do {
  13039. walk(tempNode);
  13040. } while ((tempNode = tempNode.next));
  13041. }
  13042. },
  13043. };
  13044. writer.reset();
  13045. const walk = (node) => {
  13046. var _a;
  13047. const handler = handlers[node.type];
  13048. if (!handler) {
  13049. const name = node.name;
  13050. const isEmpty = name in schema.getVoidElements();
  13051. let attrs = node.attributes;
  13052. if (validate && attrs && attrs.length > 1) {
  13053. const sortedAttrs = [];
  13054. sortedAttrs.map = {};
  13055. const elementRule = schema.getElementRule(node.name);
  13056. if (elementRule) {
  13057. for (
  13058. let i = 0, l = elementRule.attributesOrder.length;
  13059. i < l;
  13060. i++
  13061. ) {
  13062. const attrName = elementRule.attributesOrder[i];
  13063. if (attrName in attrs.map) {
  13064. const attrValue = attrs.map[attrName];
  13065. sortedAttrs.map[attrName] = attrValue;
  13066. sortedAttrs.push({
  13067. name: attrName,
  13068. value: attrValue,
  13069. });
  13070. }
  13071. }
  13072. for (let i = 0, l = attrs.length; i < l; i++) {
  13073. const attrName = attrs[i].name;
  13074. if (!(attrName in sortedAttrs.map)) {
  13075. const attrValue = attrs.map[attrName];
  13076. sortedAttrs.map[attrName] = attrValue;
  13077. sortedAttrs.push({
  13078. name: attrName,
  13079. value: attrValue,
  13080. });
  13081. }
  13082. }
  13083. attrs = sortedAttrs;
  13084. }
  13085. }
  13086. writer.start(name, attrs, isEmpty);
  13087. if (!isEmpty) {
  13088. let child = node.firstChild;
  13089. if (child) {
  13090. if (
  13091. (name === "pre" || name === "textarea") &&
  13092. child.type === 3 &&
  13093. ((_a = child.value) === null || _a === void 0
  13094. ? void 0
  13095. : _a[0]) === "\n"
  13096. ) {
  13097. writer.text("\n", true);
  13098. }
  13099. do {
  13100. walk(child);
  13101. } while ((child = child.next));
  13102. }
  13103. writer.end(name);
  13104. }
  13105. } else {
  13106. handler(node);
  13107. }
  13108. };
  13109. if (node.type === 1 && !settings.inner) {
  13110. walk(node);
  13111. } else if (node.type === 3) {
  13112. handlers[3](node);
  13113. } else {
  13114. handlers[11](node);
  13115. }
  13116. return writer.getContent();
  13117. };
  13118. return { serialize };
  13119. };
  13120. const nonInheritableStyles = new Set();
  13121. (() => {
  13122. const nonInheritableStylesArr = [
  13123. "margin",
  13124. "margin-left",
  13125. "margin-right",
  13126. "margin-top",
  13127. "margin-bottom",
  13128. "padding",
  13129. "padding-left",
  13130. "padding-right",
  13131. "padding-top",
  13132. "padding-bottom",
  13133. "border",
  13134. "border-width",
  13135. "border-style",
  13136. "border-color",
  13137. "background",
  13138. "background-attachment",
  13139. "background-clip",
  13140. "background-color",
  13141. "background-image",
  13142. "background-origin",
  13143. "background-position",
  13144. "background-repeat",
  13145. "background-size",
  13146. "float",
  13147. "position",
  13148. "left",
  13149. "right",
  13150. "top",
  13151. "bottom",
  13152. "z-index",
  13153. "display",
  13154. "transform",
  13155. "width",
  13156. "max-width",
  13157. "min-width",
  13158. "height",
  13159. "max-height",
  13160. "min-height",
  13161. "overflow",
  13162. "overflow-x",
  13163. "overflow-y",
  13164. "text-overflow",
  13165. "vertical-align",
  13166. "transition",
  13167. "transition-delay",
  13168. "transition-duration",
  13169. "transition-property",
  13170. "transition-timing-function",
  13171. ];
  13172. each$e(nonInheritableStylesArr, (style) => {
  13173. nonInheritableStyles.add(style);
  13174. });
  13175. })();
  13176. const shorthandStyleProps = ["font", "text-decoration", "text-emphasis"];
  13177. const getStyleProps = (dom, node) =>
  13178. keys(dom.parseStyle(dom.getAttrib(node, "style")));
  13179. const isNonInheritableStyle = (style) => nonInheritableStyles.has(style);
  13180. const hasInheritableStyles = (dom, node) =>
  13181. forall(getStyleProps(dom, node), (style) => !isNonInheritableStyle(style));
  13182. const getLonghandStyleProps = (styles) =>
  13183. filter$5(styles, (style) =>
  13184. exists(shorthandStyleProps, (prop) => startsWith(style, prop))
  13185. );
  13186. const hasStyleConflict = (dom, node, parentNode) => {
  13187. const nodeStyleProps = getStyleProps(dom, node);
  13188. const parentNodeStyleProps = getStyleProps(dom, parentNode);
  13189. const valueMismatch = (prop) => {
  13190. var _a, _b;
  13191. const nodeValue =
  13192. (_a = dom.getStyle(node, prop)) !== null && _a !== void 0 ? _a : "";
  13193. const parentValue =
  13194. (_b = dom.getStyle(parentNode, prop)) !== null && _b !== void 0
  13195. ? _b
  13196. : "";
  13197. return (
  13198. isNotEmpty(nodeValue) &&
  13199. isNotEmpty(parentValue) &&
  13200. nodeValue !== parentValue
  13201. );
  13202. };
  13203. return exists(nodeStyleProps, (nodeStyleProp) => {
  13204. const propExists = (props) =>
  13205. exists(props, (prop) => prop === nodeStyleProp);
  13206. if (
  13207. !propExists(parentNodeStyleProps) &&
  13208. propExists(shorthandStyleProps)
  13209. ) {
  13210. const longhandProps = getLonghandStyleProps(parentNodeStyleProps);
  13211. return exists(longhandProps, valueMismatch);
  13212. } else {
  13213. return valueMismatch(nodeStyleProp);
  13214. }
  13215. });
  13216. };
  13217. const isChar = (forward, predicate, pos) =>
  13218. Optional.from(pos.container())
  13219. .filter(isText$a)
  13220. .exists((text) => {
  13221. const delta = forward ? 0 : -1;
  13222. return predicate(text.data.charAt(pos.offset() + delta));
  13223. });
  13224. const isBeforeSpace = curry(isChar, true, isWhiteSpace);
  13225. const isAfterSpace = curry(isChar, false, isWhiteSpace);
  13226. const isEmptyText = (pos) => {
  13227. const container = pos.container();
  13228. return (
  13229. isText$a(container) &&
  13230. (container.data.length === 0 ||
  13231. (isZwsp$1(container.data) &&
  13232. BookmarkManager.isBookmarkNode(container.parentNode)))
  13233. );
  13234. };
  13235. const matchesElementPosition = (before, predicate) => (pos) =>
  13236. getChildNodeAtRelativeOffset(before ? 0 : -1, pos)
  13237. .filter(predicate)
  13238. .isSome();
  13239. const isImageBlock = (node) =>
  13240. isImg(node) && get$7(SugarElement.fromDom(node), "display") === "block";
  13241. const isCefNode = (node) =>
  13242. isContentEditableFalse$b(node) && !isBogusAll$1(node);
  13243. const isBeforeImageBlock = matchesElementPosition(true, isImageBlock);
  13244. const isAfterImageBlock = matchesElementPosition(false, isImageBlock);
  13245. const isBeforeMedia = matchesElementPosition(true, isMedia$2);
  13246. const isAfterMedia = matchesElementPosition(false, isMedia$2);
  13247. const isBeforeTable = matchesElementPosition(true, isTable$2);
  13248. const isAfterTable = matchesElementPosition(false, isTable$2);
  13249. const isBeforeContentEditableFalse = matchesElementPosition(true, isCefNode);
  13250. const isAfterContentEditableFalse = matchesElementPosition(false, isCefNode);
  13251. const dropLast = (xs) => xs.slice(0, -1);
  13252. const parentsUntil = (start, root, predicate) => {
  13253. if (contains(root, start)) {
  13254. return dropLast(
  13255. parents$1(start, (elm) => {
  13256. return predicate(elm) || eq(elm, root);
  13257. })
  13258. );
  13259. } else {
  13260. return [];
  13261. }
  13262. };
  13263. const parents = (start, root) => parentsUntil(start, root, never);
  13264. const parentsAndSelf = (start, root) => [start].concat(parents(start, root));
  13265. const navigateIgnoreEmptyTextNodes = (forward, root, from) =>
  13266. navigateIgnore(forward, root, from, isEmptyText);
  13267. const getClosestBlock$1 = (root, pos) =>
  13268. find$2(
  13269. parentsAndSelf(SugarElement.fromDom(pos.container()), root),
  13270. isBlock$2
  13271. );
  13272. const isAtBeforeAfterBlockBoundary = (forward, root, pos) =>
  13273. navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall((newPos) =>
  13274. getClosestBlock$1(root, pos).fold(
  13275. () => !isInSameBlock(newPos, pos, root.dom),
  13276. (fromBlock) =>
  13277. !isInSameBlock(newPos, pos, root.dom) &&
  13278. contains(fromBlock, SugarElement.fromDom(newPos.container()))
  13279. )
  13280. );
  13281. const isAtBlockBoundary = (forward, root, pos) =>
  13282. getClosestBlock$1(root, pos).fold(
  13283. () =>
  13284. navigateIgnoreEmptyTextNodes(forward, root.dom, pos).forall(
  13285. (newPos) => !isInSameBlock(newPos, pos, root.dom)
  13286. ),
  13287. (parent) =>
  13288. navigateIgnoreEmptyTextNodes(forward, parent.dom, pos).isNone()
  13289. );
  13290. const isAtStartOfBlock = curry(isAtBlockBoundary, false);
  13291. const isAtEndOfBlock = curry(isAtBlockBoundary, true);
  13292. const isBeforeBlock = curry(isAtBeforeAfterBlockBoundary, false);
  13293. const isAfterBlock = curry(isAtBeforeAfterBlockBoundary, true);
  13294. const isBr$1 = (pos) => getElementFromPosition(pos).exists(isBr$5);
  13295. const findBr = (forward, root, pos) => {
  13296. const parentBlocks = filter$5(
  13297. parentsAndSelf(SugarElement.fromDom(pos.container()), root),
  13298. isBlock$2
  13299. );
  13300. const scope = head(parentBlocks).getOr(root);
  13301. return fromPosition(forward, scope.dom, pos).filter(isBr$1);
  13302. };
  13303. const isBeforeBr$1 = (root, pos) =>
  13304. getElementFromPosition(pos).exists(isBr$5) ||
  13305. findBr(true, root, pos).isSome();
  13306. const isAfterBr = (root, pos) =>
  13307. getElementFromPrevPosition(pos).exists(isBr$5) ||
  13308. findBr(false, root, pos).isSome();
  13309. const findPreviousBr = curry(findBr, false);
  13310. const findNextBr = curry(findBr, true);
  13311. const isInMiddleOfText = (pos) =>
  13312. CaretPosition.isTextPosition(pos) && !pos.isAtStart() && !pos.isAtEnd();
  13313. const getClosestBlock = (root, pos) => {
  13314. const parentBlocks = filter$5(
  13315. parentsAndSelf(SugarElement.fromDom(pos.container()), root),
  13316. isBlock$2
  13317. );
  13318. return head(parentBlocks).getOr(root);
  13319. };
  13320. const hasSpaceBefore = (root, pos) => {
  13321. if (isInMiddleOfText(pos)) {
  13322. return isAfterSpace(pos);
  13323. } else {
  13324. return (
  13325. isAfterSpace(pos) ||
  13326. prevPosition(getClosestBlock(root, pos).dom, pos).exists(isAfterSpace)
  13327. );
  13328. }
  13329. };
  13330. const hasSpaceAfter = (root, pos) => {
  13331. if (isInMiddleOfText(pos)) {
  13332. return isBeforeSpace(pos);
  13333. } else {
  13334. return (
  13335. isBeforeSpace(pos) ||
  13336. nextPosition(getClosestBlock(root, pos).dom, pos).exists(isBeforeSpace)
  13337. );
  13338. }
  13339. };
  13340. const isPreValue = (value) => contains$2(["pre", "pre-wrap"], value);
  13341. const isInPre = (pos) =>
  13342. getElementFromPosition(pos)
  13343. .bind((elm) => closest$4(elm, isElement$7))
  13344. .exists((elm) => isPreValue(get$7(elm, "white-space")));
  13345. const isAtBeginningOfBody = (root, pos) =>
  13346. prevPosition(root.dom, pos).isNone();
  13347. const isAtEndOfBody = (root, pos) => nextPosition(root.dom, pos).isNone();
  13348. const isAtLineBoundary = (root, pos) =>
  13349. isAtBeginningOfBody(root, pos) ||
  13350. isAtEndOfBody(root, pos) ||
  13351. isAtStartOfBlock(root, pos) ||
  13352. isAtEndOfBlock(root, pos) ||
  13353. isAfterBr(root, pos) ||
  13354. isBeforeBr$1(root, pos);
  13355. const isCefBlock = (node) =>
  13356. isNonNullable(node) && isContentEditableFalse$b(node) && isBlockLike(node);
  13357. const isSiblingCefBlock = (root, direction) => (container) => {
  13358. return isCefBlock(new DomTreeWalker(container, root)[direction]());
  13359. };
  13360. const isBeforeCefBlock = (root, pos) => {
  13361. const nextPos = nextPosition(root.dom, pos).getOr(pos);
  13362. const isNextCefBlock = isSiblingCefBlock(root.dom, "next");
  13363. return (
  13364. pos.isAtEnd() &&
  13365. (isNextCefBlock(pos.container()) || isNextCefBlock(nextPos.container()))
  13366. );
  13367. };
  13368. const isAfterCefBlock = (root, pos) => {
  13369. const prevPos = prevPosition(root.dom, pos).getOr(pos);
  13370. const isPrevCefBlock = isSiblingCefBlock(root.dom, "prev");
  13371. return (
  13372. pos.isAtStart() &&
  13373. (isPrevCefBlock(pos.container()) || isPrevCefBlock(prevPos.container()))
  13374. );
  13375. };
  13376. const needsToHaveNbsp = (root, pos) => {
  13377. if (isInPre(pos)) {
  13378. return false;
  13379. } else {
  13380. return (
  13381. isAtLineBoundary(root, pos) ||
  13382. hasSpaceBefore(root, pos) ||
  13383. hasSpaceAfter(root, pos)
  13384. );
  13385. }
  13386. };
  13387. const needsToBeNbspLeft = (root, pos) => {
  13388. if (isInPre(pos)) {
  13389. return false;
  13390. } else {
  13391. return (
  13392. isAtStartOfBlock(root, pos) ||
  13393. isBeforeBlock(root, pos) ||
  13394. isAfterBr(root, pos) ||
  13395. hasSpaceBefore(root, pos) ||
  13396. isAfterCefBlock(root, pos)
  13397. );
  13398. }
  13399. };
  13400. const leanRight = (pos) => {
  13401. const container = pos.container();
  13402. const offset = pos.offset();
  13403. if (isText$a(container) && offset < container.data.length) {
  13404. return CaretPosition(container, offset + 1);
  13405. } else {
  13406. return pos;
  13407. }
  13408. };
  13409. const needsToBeNbspRight = (root, pos) => {
  13410. if (isInPre(pos)) {
  13411. return false;
  13412. } else {
  13413. return (
  13414. isAtEndOfBlock(root, pos) ||
  13415. isAfterBlock(root, pos) ||
  13416. isBeforeBr$1(root, pos) ||
  13417. hasSpaceAfter(root, pos) ||
  13418. isBeforeCefBlock(root, pos)
  13419. );
  13420. }
  13421. };
  13422. const needsToBeNbsp = (root, pos) =>
  13423. needsToBeNbspLeft(root, pos) || needsToBeNbspRight(root, leanRight(pos));
  13424. const isNbspAt = (text, offset) => isNbsp(text.charAt(offset));
  13425. const isWhiteSpaceAt = (text, offset) => isWhiteSpace(text.charAt(offset));
  13426. const hasNbsp = (pos) => {
  13427. const container = pos.container();
  13428. return isText$a(container) && contains$1(container.data, nbsp);
  13429. };
  13430. const normalizeNbspMiddle = (text) => {
  13431. const chars = text.split("");
  13432. return map$3(chars, (chr, i) => {
  13433. if (
  13434. isNbsp(chr) &&
  13435. i > 0 &&
  13436. i < chars.length - 1 &&
  13437. isContent(chars[i - 1]) &&
  13438. isContent(chars[i + 1])
  13439. ) {
  13440. return " ";
  13441. } else {
  13442. return chr;
  13443. }
  13444. }).join("");
  13445. };
  13446. const normalizeNbspAtStart = (root, node, makeNbsp) => {
  13447. const text = node.data;
  13448. const firstPos = CaretPosition(node, 0);
  13449. if (!makeNbsp && isNbspAt(text, 0) && !needsToBeNbsp(root, firstPos)) {
  13450. node.data = " " + text.slice(1);
  13451. return true;
  13452. } else if (
  13453. makeNbsp &&
  13454. isWhiteSpaceAt(text, 0) &&
  13455. needsToBeNbspLeft(root, firstPos)
  13456. ) {
  13457. node.data = nbsp + text.slice(1);
  13458. return true;
  13459. } else {
  13460. return false;
  13461. }
  13462. };
  13463. const normalizeNbspInMiddleOfTextNode = (node) => {
  13464. const text = node.data;
  13465. const newText = normalizeNbspMiddle(text);
  13466. if (newText !== text) {
  13467. node.data = newText;
  13468. return true;
  13469. } else {
  13470. return false;
  13471. }
  13472. };
  13473. const normalizeNbspAtEnd = (root, node, makeNbsp) => {
  13474. const text = node.data;
  13475. const lastPos = CaretPosition(node, text.length - 1);
  13476. if (
  13477. !makeNbsp &&
  13478. isNbspAt(text, text.length - 1) &&
  13479. !needsToBeNbsp(root, lastPos)
  13480. ) {
  13481. node.data = text.slice(0, -1) + " ";
  13482. return true;
  13483. } else if (
  13484. makeNbsp &&
  13485. isWhiteSpaceAt(text, text.length - 1) &&
  13486. needsToBeNbspRight(root, lastPos)
  13487. ) {
  13488. node.data = text.slice(0, -1) + nbsp;
  13489. return true;
  13490. } else {
  13491. return false;
  13492. }
  13493. };
  13494. const normalizeNbsps = (root, pos) => {
  13495. const container = pos.container();
  13496. if (!isText$a(container)) {
  13497. return Optional.none();
  13498. }
  13499. if (hasNbsp(pos)) {
  13500. const normalized =
  13501. normalizeNbspAtStart(root, container, false) ||
  13502. normalizeNbspInMiddleOfTextNode(container) ||
  13503. normalizeNbspAtEnd(root, container, false);
  13504. return someIf(normalized, pos);
  13505. } else if (needsToBeNbsp(root, pos)) {
  13506. const normalized =
  13507. normalizeNbspAtStart(root, container, true) ||
  13508. normalizeNbspAtEnd(root, container, true);
  13509. return someIf(normalized, pos);
  13510. } else {
  13511. return Optional.none();
  13512. }
  13513. };
  13514. const normalizeNbspsInEditor = (editor) => {
  13515. const root = SugarElement.fromDom(editor.getBody());
  13516. if (editor.selection.isCollapsed()) {
  13517. normalizeNbsps(
  13518. root,
  13519. CaretPosition.fromRangeStart(editor.selection.getRng())
  13520. ).each((pos) => {
  13521. editor.selection.setRng(pos.toRange());
  13522. });
  13523. }
  13524. };
  13525. const normalize$1 = (node, offset, count) => {
  13526. if (count === 0) {
  13527. return;
  13528. }
  13529. const elm = SugarElement.fromDom(node);
  13530. const root = ancestor$4(elm, isBlock$2).getOr(elm);
  13531. const whitespace = node.data.slice(offset, offset + count);
  13532. const isEndOfContent =
  13533. offset + count >= node.data.length &&
  13534. needsToBeNbspRight(root, CaretPosition(node, node.data.length));
  13535. const isStartOfContent =
  13536. offset === 0 && needsToBeNbspLeft(root, CaretPosition(node, 0));
  13537. node.replaceData(
  13538. offset,
  13539. count,
  13540. normalize$4(whitespace, 4, isStartOfContent, isEndOfContent)
  13541. );
  13542. };
  13543. const normalizeWhitespaceAfter = (node, offset) => {
  13544. const content = node.data.slice(offset);
  13545. const whitespaceCount = content.length - lTrim(content).length;
  13546. normalize$1(node, offset, whitespaceCount);
  13547. };
  13548. const normalizeWhitespaceBefore = (node, offset) => {
  13549. const content = node.data.slice(0, offset);
  13550. const whitespaceCount = content.length - rTrim(content).length;
  13551. normalize$1(node, offset - whitespaceCount, whitespaceCount);
  13552. };
  13553. const mergeTextNodes = (
  13554. prevNode,
  13555. nextNode,
  13556. normalizeWhitespace,
  13557. mergeToPrev = true
  13558. ) => {
  13559. const whitespaceOffset = rTrim(prevNode.data).length;
  13560. const newNode = mergeToPrev ? prevNode : nextNode;
  13561. const removeNode = mergeToPrev ? nextNode : prevNode;
  13562. if (mergeToPrev) {
  13563. newNode.appendData(removeNode.data);
  13564. } else {
  13565. newNode.insertData(0, removeNode.data);
  13566. }
  13567. remove$5(SugarElement.fromDom(removeNode));
  13568. if (normalizeWhitespace) {
  13569. normalizeWhitespaceAfter(newNode, whitespaceOffset);
  13570. }
  13571. return newNode;
  13572. };
  13573. const needsReposition = (pos, elm) => {
  13574. const container = pos.container();
  13575. const offset = pos.offset();
  13576. return (
  13577. !CaretPosition.isTextPosition(pos) &&
  13578. container === elm.parentNode &&
  13579. offset > CaretPosition.before(elm).offset()
  13580. );
  13581. };
  13582. const reposition = (elm, pos) =>
  13583. needsReposition(pos, elm)
  13584. ? CaretPosition(pos.container(), pos.offset() - 1)
  13585. : pos;
  13586. const beforeOrStartOf = (node) =>
  13587. isText$a(node) ? CaretPosition(node, 0) : CaretPosition.before(node);
  13588. const afterOrEndOf = (node) =>
  13589. isText$a(node)
  13590. ? CaretPosition(node, node.data.length)
  13591. : CaretPosition.after(node);
  13592. const getPreviousSiblingCaretPosition = (elm) => {
  13593. if (isCaretCandidate$3(elm.previousSibling)) {
  13594. return Optional.some(afterOrEndOf(elm.previousSibling));
  13595. } else {
  13596. return elm.previousSibling
  13597. ? lastPositionIn(elm.previousSibling)
  13598. : Optional.none();
  13599. }
  13600. };
  13601. const getNextSiblingCaretPosition = (elm) => {
  13602. if (isCaretCandidate$3(elm.nextSibling)) {
  13603. return Optional.some(beforeOrStartOf(elm.nextSibling));
  13604. } else {
  13605. return elm.nextSibling
  13606. ? firstPositionIn(elm.nextSibling)
  13607. : Optional.none();
  13608. }
  13609. };
  13610. const findCaretPositionBackwardsFromElm = (rootElement, elm) => {
  13611. return Optional.from(
  13612. elm.previousSibling ? elm.previousSibling : elm.parentNode
  13613. )
  13614. .bind((node) => prevPosition(rootElement, CaretPosition.before(node)))
  13615. .orThunk(() => nextPosition(rootElement, CaretPosition.after(elm)));
  13616. };
  13617. const findCaretPositionForwardsFromElm = (rootElement, elm) =>
  13618. nextPosition(rootElement, CaretPosition.after(elm)).orThunk(() =>
  13619. prevPosition(rootElement, CaretPosition.before(elm))
  13620. );
  13621. const findCaretPositionBackwards = (rootElement, elm) =>
  13622. getPreviousSiblingCaretPosition(elm)
  13623. .orThunk(() => getNextSiblingCaretPosition(elm))
  13624. .orThunk(() => findCaretPositionBackwardsFromElm(rootElement, elm));
  13625. const findCaretPositionForward = (rootElement, elm) =>
  13626. getNextSiblingCaretPosition(elm)
  13627. .orThunk(() => getPreviousSiblingCaretPosition(elm))
  13628. .orThunk(() => findCaretPositionForwardsFromElm(rootElement, elm));
  13629. const findCaretPosition = (forward, rootElement, elm) =>
  13630. forward
  13631. ? findCaretPositionForward(rootElement, elm)
  13632. : findCaretPositionBackwards(rootElement, elm);
  13633. const findCaretPosOutsideElmAfterDelete = (forward, rootElement, elm) =>
  13634. findCaretPosition(forward, rootElement, elm).map(curry(reposition, elm));
  13635. const setSelection$1 = (editor, forward, pos) => {
  13636. pos.fold(
  13637. () => {
  13638. editor.focus();
  13639. },
  13640. (pos) => {
  13641. editor.selection.setRng(pos.toRange(), forward);
  13642. }
  13643. );
  13644. };
  13645. const eqRawNode = (rawNode) => (elm) => elm.dom === rawNode;
  13646. const isBlock = (editor, elm) =>
  13647. elm && has$2(editor.schema.getBlockElements(), name(elm));
  13648. const paddEmptyBlock = (elm) => {
  13649. if (isEmpty$2(elm)) {
  13650. const br = SugarElement.fromHtml('<br data-mce-bogus="1">');
  13651. empty(elm);
  13652. append$1(elm, br);
  13653. return Optional.some(CaretPosition.before(br.dom));
  13654. } else {
  13655. return Optional.none();
  13656. }
  13657. };
  13658. const deleteNormalized = (elm, afterDeletePosOpt, normalizeWhitespace) => {
  13659. const prevTextOpt = prevSibling(elm).filter(isText$b);
  13660. const nextTextOpt = nextSibling(elm).filter(isText$b);
  13661. remove$5(elm);
  13662. return lift3(
  13663. prevTextOpt,
  13664. nextTextOpt,
  13665. afterDeletePosOpt,
  13666. (prev, next, pos) => {
  13667. const prevNode = prev.dom,
  13668. nextNode = next.dom;
  13669. const offset = prevNode.data.length;
  13670. mergeTextNodes(prevNode, nextNode, normalizeWhitespace);
  13671. return pos.container() === nextNode
  13672. ? CaretPosition(prevNode, offset)
  13673. : pos;
  13674. }
  13675. ).orThunk(() => {
  13676. if (normalizeWhitespace) {
  13677. prevTextOpt.each((elm) =>
  13678. normalizeWhitespaceBefore(elm.dom, elm.dom.length)
  13679. );
  13680. nextTextOpt.each((elm) => normalizeWhitespaceAfter(elm.dom, 0));
  13681. }
  13682. return afterDeletePosOpt;
  13683. });
  13684. };
  13685. const isInlineElement = (editor, element) =>
  13686. has$2(editor.schema.getTextInlineElements(), name(element));
  13687. const deleteElement$2 = (editor, forward, elm, moveCaret = true) => {
  13688. const afterDeletePos = findCaretPosOutsideElmAfterDelete(
  13689. forward,
  13690. editor.getBody(),
  13691. elm.dom
  13692. );
  13693. const parentBlock = ancestor$4(
  13694. elm,
  13695. curry(isBlock, editor),
  13696. eqRawNode(editor.getBody())
  13697. );
  13698. const normalizedAfterDeletePos = deleteNormalized(
  13699. elm,
  13700. afterDeletePos,
  13701. isInlineElement(editor, elm)
  13702. );
  13703. if (editor.dom.isEmpty(editor.getBody())) {
  13704. editor.setContent("");
  13705. editor.selection.setCursorLocation();
  13706. } else {
  13707. parentBlock.bind(paddEmptyBlock).fold(
  13708. () => {
  13709. if (moveCaret) {
  13710. setSelection$1(editor, forward, normalizedAfterDeletePos);
  13711. }
  13712. },
  13713. (paddPos) => {
  13714. if (moveCaret) {
  13715. setSelection$1(editor, forward, Optional.some(paddPos));
  13716. }
  13717. }
  13718. );
  13719. }
  13720. };
  13721. const strongRtl = /[\u0591-\u07FF\uFB1D-\uFDFF\uFE70-\uFEFC]/;
  13722. const hasStrongRtl = (text) => strongRtl.test(text);
  13723. const isInlineTarget = (editor, elm) =>
  13724. is$1(SugarElement.fromDom(elm), getInlineBoundarySelector(editor)) &&
  13725. !isTransparentBlock(editor.schema, elm) &&
  13726. editor.dom.isEditable(elm);
  13727. const isRtl = (element) => {
  13728. var _a;
  13729. return (
  13730. DOMUtils.DOM.getStyle(element, "direction", true) === "rtl" ||
  13731. hasStrongRtl(
  13732. (_a = element.textContent) !== null && _a !== void 0 ? _a : ""
  13733. )
  13734. );
  13735. };
  13736. const findInlineParents = (isInlineTarget, rootNode, pos) =>
  13737. filter$5(
  13738. DOMUtils.DOM.getParents(pos.container(), "*", rootNode),
  13739. isInlineTarget
  13740. );
  13741. const findRootInline = (isInlineTarget, rootNode, pos) => {
  13742. const parents = findInlineParents(isInlineTarget, rootNode, pos);
  13743. return Optional.from(parents[parents.length - 1]);
  13744. };
  13745. const hasSameParentBlock = (rootNode, node1, node2) => {
  13746. const block1 = getParentBlock$3(node1, rootNode);
  13747. const block2 = getParentBlock$3(node2, rootNode);
  13748. return isNonNullable(block1) && block1 === block2;
  13749. };
  13750. const isAtZwsp = (pos) => isBeforeInline(pos) || isAfterInline(pos);
  13751. const normalizePosition = (forward, pos) => {
  13752. const container = pos.container(),
  13753. offset = pos.offset();
  13754. if (forward) {
  13755. if (isCaretContainerInline(container)) {
  13756. if (isText$a(container.nextSibling)) {
  13757. return CaretPosition(container.nextSibling, 0);
  13758. } else {
  13759. return CaretPosition.after(container);
  13760. }
  13761. } else {
  13762. return isBeforeInline(pos) ? CaretPosition(container, offset + 1) : pos;
  13763. }
  13764. } else {
  13765. if (isCaretContainerInline(container)) {
  13766. if (isText$a(container.previousSibling)) {
  13767. return CaretPosition(
  13768. container.previousSibling,
  13769. container.previousSibling.data.length
  13770. );
  13771. } else {
  13772. return CaretPosition.before(container);
  13773. }
  13774. } else {
  13775. return isAfterInline(pos) ? CaretPosition(container, offset - 1) : pos;
  13776. }
  13777. }
  13778. };
  13779. const normalizeForwards = curry(normalizePosition, true);
  13780. const normalizeBackwards = curry(normalizePosition, false);
  13781. const execCommandIgnoreInputEvents = (editor, command) => {
  13782. const inputBlocker = (e) => e.stopImmediatePropagation();
  13783. editor.on("beforeinput input", inputBlocker, true);
  13784. editor.getDoc().execCommand(command);
  13785. editor.off("beforeinput input", inputBlocker);
  13786. };
  13787. const execEditorDeleteCommand = (editor) => {
  13788. editor.execCommand("delete");
  13789. };
  13790. const execNativeDeleteCommand = (editor) =>
  13791. execCommandIgnoreInputEvents(editor, "Delete");
  13792. const execNativeForwardDeleteCommand = (editor) =>
  13793. execCommandIgnoreInputEvents(editor, "ForwardDelete");
  13794. const isBeforeRoot = (rootNode) => (elm) => is$2(parent(elm), rootNode, eq);
  13795. const isTextBlockOrListItem = (element) =>
  13796. isTextBlock$2(element) || isListItem$1(element);
  13797. const getParentBlock$2 = (rootNode, elm) => {
  13798. if (contains(rootNode, elm)) {
  13799. return closest$4(elm, isTextBlockOrListItem, isBeforeRoot(rootNode));
  13800. } else {
  13801. return Optional.none();
  13802. }
  13803. };
  13804. const paddEmptyBody = (editor, moveSelection = true) => {
  13805. if (editor.dom.isEmpty(editor.getBody())) {
  13806. editor.setContent("", { no_selection: !moveSelection });
  13807. }
  13808. };
  13809. const willDeleteLastPositionInElement = (forward, fromPos, elm) =>
  13810. lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
  13811. const normalizedFirstPos = normalizePosition(true, firstPos);
  13812. const normalizedLastPos = normalizePosition(false, lastPos);
  13813. const normalizedFromPos = normalizePosition(false, fromPos);
  13814. if (forward) {
  13815. return nextPosition(elm, normalizedFromPos).exists(
  13816. (nextPos) =>
  13817. nextPos.isEqual(normalizedLastPos) &&
  13818. fromPos.isEqual(normalizedFirstPos)
  13819. );
  13820. } else {
  13821. return prevPosition(elm, normalizedFromPos).exists(
  13822. (prevPos) =>
  13823. prevPos.isEqual(normalizedFirstPos) &&
  13824. fromPos.isEqual(normalizedLastPos)
  13825. );
  13826. }
  13827. }).getOr(true);
  13828. const freefallRtl = (root) => {
  13829. const child = isComment$1(root) ? prevSibling(root) : lastChild(root);
  13830. return child.bind(freefallRtl).orThunk(() => Optional.some(root));
  13831. };
  13832. const deleteRangeContents = (editor, rng, root, moveSelection = true) => {
  13833. var _a;
  13834. rng.deleteContents();
  13835. const lastNode = freefallRtl(root).getOr(root);
  13836. const lastBlock = SugarElement.fromDom(
  13837. (_a = editor.dom.getParent(lastNode.dom, editor.dom.isBlock)) !== null &&
  13838. _a !== void 0
  13839. ? _a
  13840. : root.dom
  13841. );
  13842. if (lastBlock.dom === editor.getBody()) {
  13843. paddEmptyBody(editor, moveSelection);
  13844. } else if (isEmpty$2(lastBlock)) {
  13845. fillWithPaddingBr(lastBlock);
  13846. if (moveSelection) {
  13847. editor.selection.setCursorLocation(lastBlock.dom, 0);
  13848. }
  13849. }
  13850. if (!eq(root, lastBlock)) {
  13851. const additionalCleanupNodes = is$2(parent(lastBlock), root)
  13852. ? []
  13853. : siblings(lastBlock);
  13854. each$e(additionalCleanupNodes.concat(children$1(root)), (node) => {
  13855. if (
  13856. !eq(node, lastBlock) &&
  13857. !contains(node, lastBlock) &&
  13858. isEmpty$2(node)
  13859. ) {
  13860. remove$5(node);
  13861. }
  13862. });
  13863. }
  13864. };
  13865. const isRootFromElement = (root) => (cur) => eq(root, cur);
  13866. const getTableCells = (table) => descendants(table, "td,th");
  13867. const getTableDetailsFromRange = (rng, isRoot) => {
  13868. const getTable = (node) =>
  13869. getClosestTable(SugarElement.fromDom(node), isRoot);
  13870. const startTable = getTable(rng.startContainer);
  13871. const endTable = getTable(rng.endContainer);
  13872. const isStartInTable = startTable.isSome();
  13873. const isEndInTable = endTable.isSome();
  13874. const isSameTable = lift2(startTable, endTable, eq).getOr(false);
  13875. const isMultiTable = !isSameTable && isStartInTable && isEndInTable;
  13876. return {
  13877. startTable,
  13878. endTable,
  13879. isStartInTable,
  13880. isEndInTable,
  13881. isSameTable,
  13882. isMultiTable,
  13883. };
  13884. };
  13885. const tableCellRng = (start, end) => ({
  13886. start,
  13887. end,
  13888. });
  13889. const tableSelection = (rng, table, cells) => ({
  13890. rng,
  13891. table,
  13892. cells,
  13893. });
  13894. const deleteAction = Adt.generate([
  13895. {
  13896. singleCellTable: ["rng", "cell"],
  13897. },
  13898. { fullTable: ["table"] },
  13899. {
  13900. partialTable: ["cells", "outsideDetails"],
  13901. },
  13902. {
  13903. multiTable: ["startTableCells", "endTableCells", "betweenRng"],
  13904. },
  13905. ]);
  13906. const getClosestCell$1 = (container, isRoot) =>
  13907. closest$3(SugarElement.fromDom(container), "td,th", isRoot);
  13908. const isExpandedCellRng = (cellRng) => !eq(cellRng.start, cellRng.end);
  13909. const getTableFromCellRng = (cellRng, isRoot) =>
  13910. getClosestTable(cellRng.start, isRoot).bind((startParentTable) =>
  13911. getClosestTable(cellRng.end, isRoot).bind((endParentTable) =>
  13912. someIf(eq(startParentTable, endParentTable), startParentTable)
  13913. )
  13914. );
  13915. const isSingleCellTable = (cellRng, isRoot) =>
  13916. !isExpandedCellRng(cellRng) &&
  13917. getTableFromCellRng(cellRng, isRoot).exists((table) => {
  13918. const rows = table.dom.rows;
  13919. return rows.length === 1 && rows[0].cells.length === 1;
  13920. });
  13921. const getCellRng = (rng, isRoot) => {
  13922. const startCell = getClosestCell$1(rng.startContainer, isRoot);
  13923. const endCell = getClosestCell$1(rng.endContainer, isRoot);
  13924. return lift2(startCell, endCell, tableCellRng);
  13925. };
  13926. const getCellRangeFromStartTable = (isRoot) => (startCell) =>
  13927. getClosestTable(startCell, isRoot).bind((table) =>
  13928. last$3(getTableCells(table)).map((endCell) =>
  13929. tableCellRng(startCell, endCell)
  13930. )
  13931. );
  13932. const getCellRangeFromEndTable = (isRoot) => (endCell) =>
  13933. getClosestTable(endCell, isRoot).bind((table) =>
  13934. head(getTableCells(table)).map((startCell) =>
  13935. tableCellRng(startCell, endCell)
  13936. )
  13937. );
  13938. const getTableSelectionFromCellRng = (isRoot) => (cellRng) =>
  13939. getTableFromCellRng(cellRng, isRoot).map((table) =>
  13940. tableSelection(cellRng, table, getTableCells(table))
  13941. );
  13942. const getTableSelections = (cellRng, selectionDetails, rng, isRoot) => {
  13943. if (rng.collapsed || !cellRng.forall(isExpandedCellRng)) {
  13944. return Optional.none();
  13945. } else if (selectionDetails.isSameTable) {
  13946. const sameTableSelection = cellRng.bind(
  13947. getTableSelectionFromCellRng(isRoot)
  13948. );
  13949. return Optional.some({
  13950. start: sameTableSelection,
  13951. end: sameTableSelection,
  13952. });
  13953. } else {
  13954. const startCell = getClosestCell$1(rng.startContainer, isRoot);
  13955. const endCell = getClosestCell$1(rng.endContainer, isRoot);
  13956. const startTableSelection = startCell
  13957. .bind(getCellRangeFromStartTable(isRoot))
  13958. .bind(getTableSelectionFromCellRng(isRoot));
  13959. const endTableSelection = endCell
  13960. .bind(getCellRangeFromEndTable(isRoot))
  13961. .bind(getTableSelectionFromCellRng(isRoot));
  13962. return Optional.some({
  13963. start: startTableSelection,
  13964. end: endTableSelection,
  13965. });
  13966. }
  13967. };
  13968. const getCellIndex = (cells, cell) => findIndex$2(cells, (x) => eq(x, cell));
  13969. const getSelectedCells = (tableSelection) =>
  13970. lift2(
  13971. getCellIndex(tableSelection.cells, tableSelection.rng.start),
  13972. getCellIndex(tableSelection.cells, tableSelection.rng.end),
  13973. (startIndex, endIndex) =>
  13974. tableSelection.cells.slice(startIndex, endIndex + 1)
  13975. );
  13976. const isSingleCellTableContentSelected = (optCellRng, rng, isRoot) =>
  13977. optCellRng.exists(
  13978. (cellRng) =>
  13979. isSingleCellTable(cellRng, isRoot) &&
  13980. hasAllContentsSelected(cellRng.start, rng)
  13981. );
  13982. const unselectCells = (rng, selectionDetails) => {
  13983. const { startTable, endTable } = selectionDetails;
  13984. const otherContentRng = rng.cloneRange();
  13985. startTable.each((table) => otherContentRng.setStartAfter(table.dom));
  13986. endTable.each((table) => otherContentRng.setEndBefore(table.dom));
  13987. return otherContentRng;
  13988. };
  13989. const handleSingleTable = (cellRng, selectionDetails, rng, isRoot) =>
  13990. getTableSelections(cellRng, selectionDetails, rng, isRoot)
  13991. .bind(({ start, end }) => start.or(end))
  13992. .bind((tableSelection) => {
  13993. const { isSameTable } = selectionDetails;
  13994. const selectedCells = getSelectedCells(tableSelection).getOr([]);
  13995. if (
  13996. isSameTable &&
  13997. tableSelection.cells.length === selectedCells.length
  13998. ) {
  13999. return Optional.some(deleteAction.fullTable(tableSelection.table));
  14000. } else if (selectedCells.length > 0) {
  14001. if (isSameTable) {
  14002. return Optional.some(
  14003. deleteAction.partialTable(selectedCells, Optional.none())
  14004. );
  14005. } else {
  14006. const otherContentRng = unselectCells(rng, selectionDetails);
  14007. return Optional.some(
  14008. deleteAction.partialTable(
  14009. selectedCells,
  14010. Optional.some({
  14011. ...selectionDetails,
  14012. rng: otherContentRng,
  14013. })
  14014. )
  14015. );
  14016. }
  14017. } else {
  14018. return Optional.none();
  14019. }
  14020. });
  14021. const handleMultiTable = (cellRng, selectionDetails, rng, isRoot) =>
  14022. getTableSelections(cellRng, selectionDetails, rng, isRoot).bind(
  14023. ({ start, end }) => {
  14024. const startTableSelectedCells = start.bind(getSelectedCells).getOr([]);
  14025. const endTableSelectedCells = end.bind(getSelectedCells).getOr([]);
  14026. if (
  14027. startTableSelectedCells.length > 0 &&
  14028. endTableSelectedCells.length > 0
  14029. ) {
  14030. const otherContentRng = unselectCells(rng, selectionDetails);
  14031. return Optional.some(
  14032. deleteAction.multiTable(
  14033. startTableSelectedCells,
  14034. endTableSelectedCells,
  14035. otherContentRng
  14036. )
  14037. );
  14038. } else {
  14039. return Optional.none();
  14040. }
  14041. }
  14042. );
  14043. const getActionFromRange = (root, rng) => {
  14044. const isRoot = isRootFromElement(root);
  14045. const optCellRng = getCellRng(rng, isRoot);
  14046. const selectionDetails = getTableDetailsFromRange(rng, isRoot);
  14047. if (isSingleCellTableContentSelected(optCellRng, rng, isRoot)) {
  14048. return optCellRng.map((cellRng) =>
  14049. deleteAction.singleCellTable(rng, cellRng.start)
  14050. );
  14051. } else if (selectionDetails.isMultiTable) {
  14052. return handleMultiTable(optCellRng, selectionDetails, rng, isRoot);
  14053. } else {
  14054. return handleSingleTable(optCellRng, selectionDetails, rng, isRoot);
  14055. }
  14056. };
  14057. const cleanCells = (cells) =>
  14058. each$e(cells, (cell) => {
  14059. remove$a(cell, "contenteditable");
  14060. fillWithPaddingBr(cell);
  14061. });
  14062. const getOutsideBlock = (editor, container) =>
  14063. Optional.from(editor.dom.getParent(container, editor.dom.isBlock)).map(
  14064. SugarElement.fromDom
  14065. );
  14066. const handleEmptyBlock = (editor, startInTable, emptyBlock) => {
  14067. emptyBlock.each((block) => {
  14068. if (startInTable) {
  14069. remove$5(block);
  14070. } else {
  14071. fillWithPaddingBr(block);
  14072. editor.selection.setCursorLocation(block.dom, 0);
  14073. }
  14074. });
  14075. };
  14076. const deleteContentInsideCell = (
  14077. editor,
  14078. cell,
  14079. rng,
  14080. isFirstCellInSelection
  14081. ) => {
  14082. const insideTableRng = rng.cloneRange();
  14083. if (isFirstCellInSelection) {
  14084. insideTableRng.setStart(rng.startContainer, rng.startOffset);
  14085. insideTableRng.setEndAfter(cell.dom.lastChild);
  14086. } else {
  14087. insideTableRng.setStartBefore(cell.dom.firstChild);
  14088. insideTableRng.setEnd(rng.endContainer, rng.endOffset);
  14089. }
  14090. deleteCellContents(editor, insideTableRng, cell, false).each((action) =>
  14091. action()
  14092. );
  14093. };
  14094. const collapseAndRestoreCellSelection = (editor) => {
  14095. const selectedCells = getCellsFromEditor(editor);
  14096. const selectedNode = SugarElement.fromDom(editor.selection.getNode());
  14097. if (isTableCell$3(selectedNode.dom) && isEmpty$2(selectedNode)) {
  14098. editor.selection.setCursorLocation(selectedNode.dom, 0);
  14099. } else {
  14100. editor.selection.collapse(true);
  14101. }
  14102. if (
  14103. selectedCells.length > 1 &&
  14104. exists(selectedCells, (cell) => eq(cell, selectedNode))
  14105. ) {
  14106. set$3(selectedNode, "data-mce-selected", "1");
  14107. }
  14108. };
  14109. const emptySingleTableCells = (editor, cells, outsideDetails) =>
  14110. Optional.some(() => {
  14111. const editorRng = editor.selection.getRng();
  14112. const cellsToClean = outsideDetails
  14113. .bind(({ rng, isStartInTable }) => {
  14114. const outsideBlock = getOutsideBlock(
  14115. editor,
  14116. isStartInTable ? rng.endContainer : rng.startContainer
  14117. );
  14118. rng.deleteContents();
  14119. handleEmptyBlock(
  14120. editor,
  14121. isStartInTable,
  14122. outsideBlock.filter(isEmpty$2)
  14123. );
  14124. const endPointCell = isStartInTable
  14125. ? cells[0]
  14126. : cells[cells.length - 1];
  14127. deleteContentInsideCell(
  14128. editor,
  14129. endPointCell,
  14130. editorRng,
  14131. isStartInTable
  14132. );
  14133. if (!isEmpty$2(endPointCell)) {
  14134. return Optional.some(
  14135. isStartInTable ? cells.slice(1) : cells.slice(0, -1)
  14136. );
  14137. } else {
  14138. return Optional.none();
  14139. }
  14140. })
  14141. .getOr(cells);
  14142. cleanCells(cellsToClean);
  14143. collapseAndRestoreCellSelection(editor);
  14144. });
  14145. const emptyMultiTableCells = (
  14146. editor,
  14147. startTableCells,
  14148. endTableCells,
  14149. betweenRng
  14150. ) =>
  14151. Optional.some(() => {
  14152. const rng = editor.selection.getRng();
  14153. const startCell = startTableCells[0];
  14154. const endCell = endTableCells[endTableCells.length - 1];
  14155. deleteContentInsideCell(editor, startCell, rng, true);
  14156. deleteContentInsideCell(editor, endCell, rng, false);
  14157. const startTableCellsToClean = isEmpty$2(startCell)
  14158. ? startTableCells
  14159. : startTableCells.slice(1);
  14160. const endTableCellsToClean = isEmpty$2(endCell)
  14161. ? endTableCells
  14162. : endTableCells.slice(0, -1);
  14163. cleanCells(startTableCellsToClean.concat(endTableCellsToClean));
  14164. betweenRng.deleteContents();
  14165. collapseAndRestoreCellSelection(editor);
  14166. });
  14167. const deleteCellContents = (editor, rng, cell, moveSelection = true) =>
  14168. Optional.some(() => {
  14169. deleteRangeContents(editor, rng, cell, moveSelection);
  14170. });
  14171. const deleteTableElement = (editor, table) =>
  14172. Optional.some(() => deleteElement$2(editor, false, table));
  14173. const deleteCellRange = (editor, rootElm, rng) =>
  14174. getActionFromRange(rootElm, rng).bind((action) =>
  14175. action.fold(
  14176. curry(deleteCellContents, editor),
  14177. curry(deleteTableElement, editor),
  14178. curry(emptySingleTableCells, editor),
  14179. curry(emptyMultiTableCells, editor)
  14180. )
  14181. );
  14182. const deleteCaptionRange = (editor, caption) => emptyElement(editor, caption);
  14183. const deleteTableRange = (editor, rootElm, rng, startElm) =>
  14184. getParentCaption(rootElm, startElm).fold(
  14185. () => deleteCellRange(editor, rootElm, rng),
  14186. (caption) => deleteCaptionRange(editor, caption)
  14187. );
  14188. const deleteRange$3 = (editor, startElm, selectedCells) => {
  14189. const rootNode = SugarElement.fromDom(editor.getBody());
  14190. const rng = editor.selection.getRng();
  14191. return selectedCells.length !== 0
  14192. ? emptySingleTableCells(editor, selectedCells, Optional.none())
  14193. : deleteTableRange(editor, rootNode, rng, startElm);
  14194. };
  14195. const getParentCell = (rootElm, elm) =>
  14196. find$2(parentsAndSelf(elm, rootElm), isTableCell$2);
  14197. const getParentCaption = (rootElm, elm) =>
  14198. find$2(parentsAndSelf(elm, rootElm), isTag("caption"));
  14199. const deleteBetweenCells = (editor, rootElm, forward, fromCell, from) =>
  14200. navigate(forward, editor.getBody(), from).bind((to) =>
  14201. getParentCell(rootElm, SugarElement.fromDom(to.getNode())).bind(
  14202. (toCell) =>
  14203. eq(toCell, fromCell) ? Optional.none() : Optional.some(noop)
  14204. )
  14205. );
  14206. const emptyElement = (editor, elm) =>
  14207. Optional.some(() => {
  14208. fillWithPaddingBr(elm);
  14209. editor.selection.setCursorLocation(elm.dom, 0);
  14210. });
  14211. const isDeleteOfLastCharPos = (fromCaption, forward, from, to) =>
  14212. firstPositionIn(fromCaption.dom)
  14213. .bind((first) =>
  14214. lastPositionIn(fromCaption.dom).map((last) =>
  14215. forward
  14216. ? from.isEqual(first) && to.isEqual(last)
  14217. : from.isEqual(last) && to.isEqual(first)
  14218. )
  14219. )
  14220. .getOr(true);
  14221. const emptyCaretCaption = (editor, elm) => emptyElement(editor, elm);
  14222. const validateCaretCaption = (rootElm, fromCaption, to) =>
  14223. getParentCaption(rootElm, SugarElement.fromDom(to.getNode())).fold(
  14224. () => Optional.some(noop),
  14225. (toCaption) => someIf(!eq(toCaption, fromCaption), noop)
  14226. );
  14227. const deleteCaretInsideCaption = (
  14228. editor,
  14229. rootElm,
  14230. forward,
  14231. fromCaption,
  14232. from
  14233. ) =>
  14234. navigate(forward, editor.getBody(), from).fold(
  14235. () => Optional.some(noop),
  14236. (to) =>
  14237. isDeleteOfLastCharPos(fromCaption, forward, from, to)
  14238. ? emptyCaretCaption(editor, fromCaption)
  14239. : validateCaretCaption(rootElm, fromCaption, to)
  14240. );
  14241. const deleteCaretCells = (editor, forward, rootElm, startElm) => {
  14242. const from = CaretPosition.fromRangeStart(editor.selection.getRng());
  14243. return getParentCell(rootElm, startElm).bind((fromCell) =>
  14244. isEmpty$2(fromCell)
  14245. ? emptyElement(editor, fromCell)
  14246. : deleteBetweenCells(editor, rootElm, forward, fromCell, from)
  14247. );
  14248. };
  14249. const deleteCaretCaption = (editor, forward, rootElm, fromCaption) => {
  14250. const from = CaretPosition.fromRangeStart(editor.selection.getRng());
  14251. return isEmpty$2(fromCaption)
  14252. ? emptyElement(editor, fromCaption)
  14253. : deleteCaretInsideCaption(editor, rootElm, forward, fromCaption, from);
  14254. };
  14255. const isNearTable = (forward, pos) =>
  14256. forward ? isBeforeTable(pos) : isAfterTable(pos);
  14257. const isBeforeOrAfterTable = (editor, forward) => {
  14258. const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
  14259. return (
  14260. isNearTable(forward, fromPos) ||
  14261. fromPosition(forward, editor.getBody(), fromPos).exists((pos) =>
  14262. isNearTable(forward, pos)
  14263. )
  14264. );
  14265. };
  14266. const deleteCaret$3 = (editor, forward, startElm) => {
  14267. const rootElm = SugarElement.fromDom(editor.getBody());
  14268. return getParentCaption(rootElm, startElm).fold(
  14269. () =>
  14270. deleteCaretCells(editor, forward, rootElm, startElm).orThunk(() =>
  14271. someIf(isBeforeOrAfterTable(editor, forward), noop)
  14272. ),
  14273. (fromCaption) => deleteCaretCaption(editor, forward, rootElm, fromCaption)
  14274. );
  14275. };
  14276. const backspaceDelete$a = (editor, forward) => {
  14277. const startElm = SugarElement.fromDom(editor.selection.getStart(true));
  14278. const cells = getCellsFromEditor(editor);
  14279. return editor.selection.isCollapsed() && cells.length === 0
  14280. ? deleteCaret$3(editor, forward, startElm)
  14281. : deleteRange$3(editor, startElm, cells);
  14282. };
  14283. const getContentEditableRoot$1 = (root, node) => {
  14284. let tempNode = node;
  14285. while (tempNode && tempNode !== root) {
  14286. if (
  14287. isContentEditableTrue$3(tempNode) ||
  14288. isContentEditableFalse$b(tempNode)
  14289. ) {
  14290. return tempNode;
  14291. }
  14292. tempNode = tempNode.parentNode;
  14293. }
  14294. return null;
  14295. };
  14296. const internalAttributesPrefixes = [
  14297. "data-ephox-",
  14298. "data-mce-",
  14299. "data-alloy-",
  14300. "data-snooker-",
  14301. "_",
  14302. ];
  14303. const each$9 = Tools.each;
  14304. const ElementUtils = (editor) => {
  14305. const dom = editor.dom;
  14306. const internalAttributes = new Set(editor.serializer.getTempAttrs());
  14307. const compare = (node1, node2) => {
  14308. if (
  14309. node1.nodeName !== node2.nodeName ||
  14310. node1.nodeType !== node2.nodeType
  14311. ) {
  14312. return false;
  14313. }
  14314. const getAttribs = (node) => {
  14315. const attribs = {};
  14316. each$9(dom.getAttribs(node), (attr) => {
  14317. const name = attr.nodeName.toLowerCase();
  14318. if (name !== "style" && !isAttributeInternal(name)) {
  14319. attribs[name] = dom.getAttrib(node, name);
  14320. }
  14321. });
  14322. return attribs;
  14323. };
  14324. const compareObjects = (obj1, obj2) => {
  14325. for (const name in obj1) {
  14326. if (has$2(obj1, name)) {
  14327. const value = obj2[name];
  14328. if (isUndefined(value)) {
  14329. return false;
  14330. }
  14331. if (obj1[name] !== value) {
  14332. return false;
  14333. }
  14334. delete obj2[name];
  14335. }
  14336. }
  14337. for (const name in obj2) {
  14338. if (has$2(obj2, name)) {
  14339. return false;
  14340. }
  14341. }
  14342. return true;
  14343. };
  14344. if (isElement$6(node1) && isElement$6(node2)) {
  14345. if (!compareObjects(getAttribs(node1), getAttribs(node2))) {
  14346. return false;
  14347. }
  14348. if (
  14349. !compareObjects(
  14350. dom.parseStyle(dom.getAttrib(node1, "style")),
  14351. dom.parseStyle(dom.getAttrib(node2, "style"))
  14352. )
  14353. ) {
  14354. return false;
  14355. }
  14356. }
  14357. return !isBookmarkNode$1(node1) && !isBookmarkNode$1(node2);
  14358. };
  14359. const isAttributeInternal = (attributeName) =>
  14360. exists(internalAttributesPrefixes, (value) =>
  14361. startsWith(attributeName, value)
  14362. ) || internalAttributes.has(attributeName);
  14363. return {
  14364. compare,
  14365. isAttributeInternal,
  14366. };
  14367. };
  14368. const traverse = (root, fn) => {
  14369. let node = root;
  14370. while ((node = node.walk())) {
  14371. fn(node);
  14372. }
  14373. };
  14374. const matchNode$1 = (nodeFilters, attributeFilters, node, matches) => {
  14375. const name = node.name;
  14376. for (let ni = 0, nl = nodeFilters.length; ni < nl; ni++) {
  14377. const filter = nodeFilters[ni];
  14378. if (filter.name === name) {
  14379. const match = matches.nodes[name];
  14380. if (match) {
  14381. match.nodes.push(node);
  14382. } else {
  14383. matches.nodes[name] = {
  14384. filter,
  14385. nodes: [node],
  14386. };
  14387. }
  14388. }
  14389. }
  14390. if (node.attributes) {
  14391. for (let ai = 0, al = attributeFilters.length; ai < al; ai++) {
  14392. const filter = attributeFilters[ai];
  14393. const attrName = filter.name;
  14394. if (attrName in node.attributes.map) {
  14395. const match = matches.attributes[attrName];
  14396. if (match) {
  14397. match.nodes.push(node);
  14398. } else {
  14399. matches.attributes[attrName] = {
  14400. filter,
  14401. nodes: [node],
  14402. };
  14403. }
  14404. }
  14405. }
  14406. }
  14407. };
  14408. const findMatchingNodes = (nodeFilters, attributeFilters, node) => {
  14409. const matches = {
  14410. nodes: {},
  14411. attributes: {},
  14412. };
  14413. if (node.firstChild) {
  14414. traverse(node, (childNode) => {
  14415. matchNode$1(nodeFilters, attributeFilters, childNode, matches);
  14416. });
  14417. }
  14418. return matches;
  14419. };
  14420. const runFilters = (matches, args) => {
  14421. const run = (matchRecord, filteringAttributes) => {
  14422. each$d(matchRecord, (match) => {
  14423. const nodes = from(match.nodes);
  14424. each$e(match.filter.callbacks, (callback) => {
  14425. for (let i = nodes.length - 1; i >= 0; i--) {
  14426. const node = nodes[i];
  14427. const valueMatches = filteringAttributes
  14428. ? node.attr(match.filter.name) !== undefined
  14429. : node.name === match.filter.name;
  14430. if (!valueMatches || isNullable(node.parent)) {
  14431. nodes.splice(i, 1);
  14432. }
  14433. }
  14434. if (nodes.length > 0) {
  14435. callback(nodes, match.filter.name, args);
  14436. }
  14437. });
  14438. });
  14439. };
  14440. run(matches.nodes, false);
  14441. run(matches.attributes, true);
  14442. };
  14443. const filter$2 = (nodeFilters, attributeFilters, node, args = {}) => {
  14444. const matches = findMatchingNodes(nodeFilters, attributeFilters, node);
  14445. runFilters(matches, args);
  14446. };
  14447. const paddEmptyNode = (settings, args, isBlock, node) => {
  14448. const brPreferred = settings.pad_empty_with_br || args.insert;
  14449. if (brPreferred && isBlock(node)) {
  14450. const astNode = new AstNode("br", 1);
  14451. if (args.insert) {
  14452. astNode.attr("data-mce-bogus", "1");
  14453. }
  14454. node.empty().append(astNode);
  14455. } else {
  14456. node.empty().append(new AstNode("#text", 3)).value = nbsp;
  14457. }
  14458. };
  14459. const isPaddedWithNbsp = (node) => {
  14460. var _a;
  14461. return (
  14462. hasOnlyChild(node, "#text") &&
  14463. ((_a = node === null || node === void 0 ? void 0 : node.firstChild) ===
  14464. null || _a === void 0
  14465. ? void 0
  14466. : _a.value) === nbsp
  14467. );
  14468. };
  14469. const hasOnlyChild = (node, name) => {
  14470. const firstChild =
  14471. node === null || node === void 0 ? void 0 : node.firstChild;
  14472. return (
  14473. isNonNullable(firstChild) &&
  14474. firstChild === node.lastChild &&
  14475. firstChild.name === name
  14476. );
  14477. };
  14478. const isPadded = (schema, node) => {
  14479. const rule = schema.getElementRule(node.name);
  14480. return (
  14481. (rule === null || rule === void 0 ? void 0 : rule.paddEmpty) === true
  14482. );
  14483. };
  14484. const isEmpty = (schema, nonEmptyElements, whitespaceElements, node) =>
  14485. node.isEmpty(nonEmptyElements, whitespaceElements, (node) =>
  14486. isPadded(schema, node)
  14487. );
  14488. const isLineBreakNode = (node, isBlock) =>
  14489. isNonNullable(node) && (isBlock(node) || node.name === "br");
  14490. const findClosestEditingHost = (scope) => {
  14491. let editableNode;
  14492. for (let node = scope; node; node = node.parent) {
  14493. const contentEditable = node.attr("contenteditable");
  14494. if (contentEditable === "false") {
  14495. break;
  14496. } else if (contentEditable === "true") {
  14497. editableNode = node;
  14498. }
  14499. }
  14500. return Optional.from(editableNode);
  14501. };
  14502. const removeOrUnwrapInvalidNode = (
  14503. node,
  14504. schema,
  14505. originalNodeParent = node.parent
  14506. ) => {
  14507. if (schema.getSpecialElements()[node.name]) {
  14508. node.empty().remove();
  14509. } else {
  14510. const children = node.children();
  14511. for (const childNode of children) {
  14512. if (
  14513. originalNodeParent &&
  14514. !schema.isValidChild(originalNodeParent.name, childNode.name)
  14515. ) {
  14516. removeOrUnwrapInvalidNode(childNode, schema, originalNodeParent);
  14517. }
  14518. }
  14519. node.unwrap();
  14520. }
  14521. };
  14522. const cleanInvalidNodes = (nodes, schema, rootNode, onCreate = noop) => {
  14523. const textBlockElements = schema.getTextBlockElements();
  14524. const nonEmptyElements = schema.getNonEmptyElements();
  14525. const whitespaceElements = schema.getWhitespaceElements();
  14526. const nonSplittableElements = Tools.makeMap(
  14527. "tr,td,th,tbody,thead,tfoot,table,summary"
  14528. );
  14529. const fixed = new Set();
  14530. const isSplittableElement = (node) =>
  14531. node !== rootNode && !nonSplittableElements[node.name];
  14532. for (let ni = 0; ni < nodes.length; ni++) {
  14533. const node = nodes[ni];
  14534. let parent;
  14535. let newParent;
  14536. let tempNode;
  14537. if (!node.parent || fixed.has(node)) {
  14538. continue;
  14539. }
  14540. if (textBlockElements[node.name] && node.parent.name === "li") {
  14541. let sibling = node.next;
  14542. while (sibling) {
  14543. if (textBlockElements[sibling.name]) {
  14544. sibling.name = "li";
  14545. fixed.add(sibling);
  14546. node.parent.insert(sibling, node.parent);
  14547. } else {
  14548. break;
  14549. }
  14550. sibling = sibling.next;
  14551. }
  14552. node.unwrap();
  14553. continue;
  14554. }
  14555. const parents = [node];
  14556. for (
  14557. parent = node.parent;
  14558. parent &&
  14559. !schema.isValidChild(parent.name, node.name) &&
  14560. isSplittableElement(parent);
  14561. parent = parent.parent
  14562. ) {
  14563. parents.push(parent);
  14564. }
  14565. if (parent && parents.length > 1) {
  14566. if (schema.isValidChild(parent.name, node.name)) {
  14567. parents.reverse();
  14568. newParent = parents[0].clone();
  14569. onCreate(newParent);
  14570. let currentNode = newParent;
  14571. for (let i = 0; i < parents.length - 1; i++) {
  14572. if (
  14573. schema.isValidChild(currentNode.name, parents[i].name) &&
  14574. i > 0
  14575. ) {
  14576. tempNode = parents[i].clone();
  14577. onCreate(tempNode);
  14578. currentNode.append(tempNode);
  14579. } else {
  14580. tempNode = currentNode;
  14581. }
  14582. for (
  14583. let childNode = parents[i].firstChild;
  14584. childNode && childNode !== parents[i + 1];
  14585. ) {
  14586. const nextNode = childNode.next;
  14587. tempNode.append(childNode);
  14588. childNode = nextNode;
  14589. }
  14590. currentNode = tempNode;
  14591. }
  14592. if (
  14593. !isEmpty(schema, nonEmptyElements, whitespaceElements, newParent)
  14594. ) {
  14595. parent.insert(newParent, parents[0], true);
  14596. parent.insert(node, newParent);
  14597. } else {
  14598. parent.insert(node, parents[0], true);
  14599. }
  14600. parent = parents[0];
  14601. if (
  14602. isEmpty(schema, nonEmptyElements, whitespaceElements, parent) ||
  14603. hasOnlyChild(parent, "br")
  14604. ) {
  14605. parent.empty().remove();
  14606. }
  14607. } else {
  14608. removeOrUnwrapInvalidNode(node, schema);
  14609. }
  14610. } else if (node.parent) {
  14611. if (node.name === "li") {
  14612. let sibling = node.prev;
  14613. if (sibling && (sibling.name === "ul" || sibling.name === "ol")) {
  14614. sibling.append(node);
  14615. continue;
  14616. }
  14617. sibling = node.next;
  14618. if (
  14619. sibling &&
  14620. (sibling.name === "ul" || sibling.name === "ol") &&
  14621. sibling.firstChild
  14622. ) {
  14623. sibling.insert(node, sibling.firstChild, true);
  14624. continue;
  14625. }
  14626. const wrapper = new AstNode("ul", 1);
  14627. onCreate(wrapper);
  14628. node.wrap(wrapper);
  14629. continue;
  14630. }
  14631. if (
  14632. schema.isValidChild(node.parent.name, "div") &&
  14633. schema.isValidChild("div", node.name)
  14634. ) {
  14635. const wrapper = new AstNode("div", 1);
  14636. onCreate(wrapper);
  14637. node.wrap(wrapper);
  14638. } else {
  14639. removeOrUnwrapInvalidNode(node, schema);
  14640. }
  14641. }
  14642. }
  14643. };
  14644. const hasClosest = (node, parentName) => {
  14645. let tempNode = node;
  14646. while (tempNode) {
  14647. if (tempNode.name === parentName) {
  14648. return true;
  14649. }
  14650. tempNode = tempNode.parent;
  14651. }
  14652. return false;
  14653. };
  14654. const isInvalid = (schema, node, parent = node.parent) => {
  14655. if (
  14656. parent &&
  14657. schema.children[node.name] &&
  14658. !schema.isValidChild(parent.name, node.name)
  14659. ) {
  14660. return true;
  14661. } else if (parent && node.name === "a" && hasClosest(parent, "a")) {
  14662. return true;
  14663. } else {
  14664. return false;
  14665. }
  14666. };
  14667. const createRange = (sc, so, ec, eo) => {
  14668. const rng = document.createRange();
  14669. rng.setStart(sc, so);
  14670. rng.setEnd(ec, eo);
  14671. return rng;
  14672. };
  14673. const normalizeBlockSelectionRange = (rng) => {
  14674. const startPos = CaretPosition.fromRangeStart(rng);
  14675. const endPos = CaretPosition.fromRangeEnd(rng);
  14676. const rootNode = rng.commonAncestorContainer;
  14677. return fromPosition(false, rootNode, endPos)
  14678. .map((newEndPos) => {
  14679. if (
  14680. !isInSameBlock(startPos, endPos, rootNode) &&
  14681. isInSameBlock(startPos, newEndPos, rootNode)
  14682. ) {
  14683. return createRange(
  14684. startPos.container(),
  14685. startPos.offset(),
  14686. newEndPos.container(),
  14687. newEndPos.offset()
  14688. );
  14689. } else {
  14690. return rng;
  14691. }
  14692. })
  14693. .getOr(rng);
  14694. };
  14695. const normalize = (rng) =>
  14696. rng.collapsed ? rng : normalizeBlockSelectionRange(rng);
  14697. const hasOnlyOneChild$1 = (node) => {
  14698. return isNonNullable(node.firstChild) && node.firstChild === node.lastChild;
  14699. };
  14700. const isPaddingNode = (node) => {
  14701. return node.name === "br" || node.value === nbsp;
  14702. };
  14703. const isPaddedEmptyBlock = (schema, node) => {
  14704. const blockElements = schema.getBlockElements();
  14705. return (
  14706. blockElements[node.name] &&
  14707. hasOnlyOneChild$1(node) &&
  14708. isPaddingNode(node.firstChild)
  14709. );
  14710. };
  14711. const isEmptyFragmentElement = (schema, node) => {
  14712. const nonEmptyElements = schema.getNonEmptyElements();
  14713. return (
  14714. isNonNullable(node) &&
  14715. (node.isEmpty(nonEmptyElements) || isPaddedEmptyBlock(schema, node))
  14716. );
  14717. };
  14718. const isListFragment = (schema, fragment) => {
  14719. let firstChild = fragment.firstChild;
  14720. let lastChild = fragment.lastChild;
  14721. if (firstChild && firstChild.name === "meta") {
  14722. firstChild = firstChild.next;
  14723. }
  14724. if (lastChild && lastChild.attr("id") === "mce_marker") {
  14725. lastChild = lastChild.prev;
  14726. }
  14727. if (isEmptyFragmentElement(schema, lastChild)) {
  14728. lastChild =
  14729. lastChild === null || lastChild === void 0 ? void 0 : lastChild.prev;
  14730. }
  14731. if (!firstChild || firstChild !== lastChild) {
  14732. return false;
  14733. }
  14734. return firstChild.name === "ul" || firstChild.name === "ol";
  14735. };
  14736. const cleanupDomFragment = (domFragment) => {
  14737. var _a, _b;
  14738. const firstChild = domFragment.firstChild;
  14739. const lastChild = domFragment.lastChild;
  14740. if (firstChild && firstChild.nodeName === "META") {
  14741. (_a = firstChild.parentNode) === null || _a === void 0
  14742. ? void 0
  14743. : _a.removeChild(firstChild);
  14744. }
  14745. if (lastChild && lastChild.id === "mce_marker") {
  14746. (_b = lastChild.parentNode) === null || _b === void 0
  14747. ? void 0
  14748. : _b.removeChild(lastChild);
  14749. }
  14750. return domFragment;
  14751. };
  14752. const toDomFragment = (dom, serializer, fragment) => {
  14753. const html = serializer.serialize(fragment);
  14754. const domFragment = dom.createFragment(html);
  14755. return cleanupDomFragment(domFragment);
  14756. };
  14757. const listItems = (elm) => {
  14758. var _a;
  14759. return filter$5(
  14760. (_a = elm === null || elm === void 0 ? void 0 : elm.childNodes) !==
  14761. null && _a !== void 0
  14762. ? _a
  14763. : [],
  14764. (child) => {
  14765. return child.nodeName === "LI";
  14766. }
  14767. );
  14768. };
  14769. const isPadding = (node) => {
  14770. return node.data === nbsp || isBr$6(node);
  14771. };
  14772. const isListItemPadded = (node) => {
  14773. return (
  14774. isNonNullable(
  14775. node === null || node === void 0 ? void 0 : node.firstChild
  14776. ) &&
  14777. node.firstChild === node.lastChild &&
  14778. isPadding(node.firstChild)
  14779. );
  14780. };
  14781. const isEmptyOrPadded = (elm) => {
  14782. return !elm.firstChild || isListItemPadded(elm);
  14783. };
  14784. const trimListItems = (elms) => {
  14785. return elms.length > 0 && isEmptyOrPadded(elms[elms.length - 1])
  14786. ? elms.slice(0, -1)
  14787. : elms;
  14788. };
  14789. const getParentLi = (dom, node) => {
  14790. const parentBlock = dom.getParent(node, dom.isBlock);
  14791. return parentBlock && parentBlock.nodeName === "LI" ? parentBlock : null;
  14792. };
  14793. const isParentBlockLi = (dom, node) => {
  14794. return !!getParentLi(dom, node);
  14795. };
  14796. const getSplit = (parentNode, rng) => {
  14797. const beforeRng = rng.cloneRange();
  14798. const afterRng = rng.cloneRange();
  14799. beforeRng.setStartBefore(parentNode);
  14800. afterRng.setEndAfter(parentNode);
  14801. return [beforeRng.cloneContents(), afterRng.cloneContents()];
  14802. };
  14803. const findFirstIn = (node, rootNode) => {
  14804. const caretPos = CaretPosition.before(node);
  14805. const caretWalker = CaretWalker(rootNode);
  14806. const newCaretPos = caretWalker.next(caretPos);
  14807. return newCaretPos ? newCaretPos.toRange() : null;
  14808. };
  14809. const findLastOf = (node, rootNode) => {
  14810. const caretPos = CaretPosition.after(node);
  14811. const caretWalker = CaretWalker(rootNode);
  14812. const newCaretPos = caretWalker.prev(caretPos);
  14813. return newCaretPos ? newCaretPos.toRange() : null;
  14814. };
  14815. const insertMiddle = (target, elms, rootNode, rng) => {
  14816. const parts = getSplit(target, rng);
  14817. const parentElm = target.parentNode;
  14818. if (parentElm) {
  14819. parentElm.insertBefore(parts[0], target);
  14820. Tools.each(elms, (li) => {
  14821. parentElm.insertBefore(li, target);
  14822. });
  14823. parentElm.insertBefore(parts[1], target);
  14824. parentElm.removeChild(target);
  14825. }
  14826. return findLastOf(elms[elms.length - 1], rootNode);
  14827. };
  14828. const insertBefore$2 = (target, elms, rootNode) => {
  14829. const parentElm = target.parentNode;
  14830. if (parentElm) {
  14831. Tools.each(elms, (elm) => {
  14832. parentElm.insertBefore(elm, target);
  14833. });
  14834. }
  14835. return findFirstIn(target, rootNode);
  14836. };
  14837. const insertAfter$2 = (target, elms, rootNode, dom) => {
  14838. dom.insertAfter(elms.reverse(), target);
  14839. return findLastOf(elms[0], rootNode);
  14840. };
  14841. const insertAtCaret$1 = (serializer, dom, rng, fragment) => {
  14842. const domFragment = toDomFragment(dom, serializer, fragment);
  14843. const liTarget = getParentLi(dom, rng.startContainer);
  14844. const liElms = trimListItems(listItems(domFragment.firstChild));
  14845. const BEGINNING = 1,
  14846. END = 2;
  14847. const rootNode = dom.getRoot();
  14848. const isAt = (location) => {
  14849. const caretPos = CaretPosition.fromRangeStart(rng);
  14850. const caretWalker = CaretWalker(dom.getRoot());
  14851. const newPos =
  14852. location === BEGINNING
  14853. ? caretWalker.prev(caretPos)
  14854. : caretWalker.next(caretPos);
  14855. const newPosNode =
  14856. newPos === null || newPos === void 0 ? void 0 : newPos.getNode();
  14857. return newPosNode ? getParentLi(dom, newPosNode) !== liTarget : true;
  14858. };
  14859. if (!liTarget) {
  14860. return null;
  14861. } else if (isAt(BEGINNING)) {
  14862. return insertBefore$2(liTarget, liElms, rootNode);
  14863. } else if (isAt(END)) {
  14864. return insertAfter$2(liTarget, liElms, rootNode, dom);
  14865. } else {
  14866. return insertMiddle(liTarget, liElms, rootNode, rng);
  14867. }
  14868. };
  14869. const mergeableWrappedElements = ["pre"];
  14870. const shouldPasteContentOnly = (dom, fragment, parentNode, root) => {
  14871. var _a;
  14872. const firstNode = fragment.firstChild;
  14873. const lastNode = fragment.lastChild;
  14874. const last =
  14875. lastNode.attr("data-mce-type") === "bookmark" ? lastNode.prev : lastNode;
  14876. const isPastingSingleElement = firstNode === last;
  14877. const isWrappedElement = contains$2(
  14878. mergeableWrappedElements,
  14879. firstNode.name
  14880. );
  14881. if (isPastingSingleElement && isWrappedElement) {
  14882. const isContentEditable = firstNode.attr("contenteditable") !== "false";
  14883. const isPastingInTheSameBlockTag =
  14884. ((_a = dom.getParent(parentNode, dom.isBlock)) === null || _a === void 0
  14885. ? void 0
  14886. : _a.nodeName.toLowerCase()) === firstNode.name;
  14887. const isPastingInContentEditable = Optional.from(
  14888. getContentEditableRoot$1(root, parentNode)
  14889. ).forall(isContentEditableTrue$3);
  14890. return (
  14891. isContentEditable &&
  14892. isPastingInTheSameBlockTag &&
  14893. isPastingInContentEditable
  14894. );
  14895. } else {
  14896. return false;
  14897. }
  14898. };
  14899. const isTableCell = isTableCell$3;
  14900. const isTableCellContentSelected = (dom, rng, cell) => {
  14901. if (isNonNullable(cell)) {
  14902. const endCell = dom.getParent(rng.endContainer, isTableCell);
  14903. return (
  14904. cell === endCell &&
  14905. hasAllContentsSelected(SugarElement.fromDom(cell), rng)
  14906. );
  14907. } else {
  14908. return false;
  14909. }
  14910. };
  14911. const validInsertion = (editor, value, parentNode) => {
  14912. var _a;
  14913. if (parentNode.getAttribute("data-mce-bogus") === "all") {
  14914. (_a = parentNode.parentNode) === null || _a === void 0
  14915. ? void 0
  14916. : _a.insertBefore(editor.dom.createFragment(value), parentNode);
  14917. } else {
  14918. const node = parentNode.firstChild;
  14919. const node2 = parentNode.lastChild;
  14920. if (!node || (node === node2 && node.nodeName === "BR")) {
  14921. editor.dom.setHTML(parentNode, value);
  14922. } else {
  14923. editor.selection.setContent(value, { no_events: true });
  14924. }
  14925. }
  14926. };
  14927. const trimBrsFromTableCell = (dom, elm) => {
  14928. Optional.from(dom.getParent(elm, "td,th"))
  14929. .map(SugarElement.fromDom)
  14930. .each(trimBlockTrailingBr);
  14931. };
  14932. const reduceInlineTextElements = (editor, merge) => {
  14933. const textInlineElements = editor.schema.getTextInlineElements();
  14934. const dom = editor.dom;
  14935. if (merge) {
  14936. const root = editor.getBody();
  14937. const elementUtils = ElementUtils(editor);
  14938. Tools.each(dom.select("*[data-mce-fragment]"), (node) => {
  14939. const isInline = isNonNullable(
  14940. textInlineElements[node.nodeName.toLowerCase()]
  14941. );
  14942. if (isInline && hasInheritableStyles(dom, node)) {
  14943. for (
  14944. let parentNode = node.parentElement;
  14945. isNonNullable(parentNode) && parentNode !== root;
  14946. parentNode = parentNode.parentElement
  14947. ) {
  14948. const styleConflict = hasStyleConflict(dom, node, parentNode);
  14949. if (styleConflict) {
  14950. break;
  14951. }
  14952. if (elementUtils.compare(parentNode, node)) {
  14953. dom.remove(node, true);
  14954. break;
  14955. }
  14956. }
  14957. }
  14958. });
  14959. }
  14960. };
  14961. const markFragmentElements = (fragment) => {
  14962. let node = fragment;
  14963. while ((node = node.walk())) {
  14964. if (node.type === 1) {
  14965. node.attr("data-mce-fragment", "1");
  14966. }
  14967. }
  14968. };
  14969. const unmarkFragmentElements = (elm) => {
  14970. Tools.each(elm.getElementsByTagName("*"), (elm) => {
  14971. elm.removeAttribute("data-mce-fragment");
  14972. });
  14973. };
  14974. const isPartOfFragment = (node) => {
  14975. return !!node.getAttribute("data-mce-fragment");
  14976. };
  14977. const canHaveChildren = (editor, node) => {
  14978. return (
  14979. isNonNullable(node) && !editor.schema.getVoidElements()[node.nodeName]
  14980. );
  14981. };
  14982. const moveSelectionToMarker = (editor, marker) => {
  14983. var _a, _b, _c;
  14984. let nextRng;
  14985. const dom = editor.dom;
  14986. const selection = editor.selection;
  14987. if (!marker) {
  14988. return;
  14989. }
  14990. selection.scrollIntoView(marker);
  14991. const parentEditableElm = getContentEditableRoot$1(
  14992. editor.getBody(),
  14993. marker
  14994. );
  14995. if (
  14996. parentEditableElm &&
  14997. dom.getContentEditable(parentEditableElm) === "false"
  14998. ) {
  14999. dom.remove(marker);
  15000. selection.select(parentEditableElm);
  15001. return;
  15002. }
  15003. let rng = dom.createRng();
  15004. const node = marker.previousSibling;
  15005. if (isText$a(node)) {
  15006. rng.setStart(
  15007. node,
  15008. (_b =
  15009. (_a = node.nodeValue) === null || _a === void 0
  15010. ? void 0
  15011. : _a.length) !== null && _b !== void 0
  15012. ? _b
  15013. : 0
  15014. );
  15015. const node2 = marker.nextSibling;
  15016. if (isText$a(node2)) {
  15017. node.appendData(node2.data);
  15018. (_c = node2.parentNode) === null || _c === void 0
  15019. ? void 0
  15020. : _c.removeChild(node2);
  15021. }
  15022. } else {
  15023. rng.setStartBefore(marker);
  15024. rng.setEndBefore(marker);
  15025. }
  15026. const findNextCaretRng = (rng) => {
  15027. let caretPos = CaretPosition.fromRangeStart(rng);
  15028. const caretWalker = CaretWalker(editor.getBody());
  15029. caretPos = caretWalker.next(caretPos);
  15030. return caretPos === null || caretPos === void 0
  15031. ? void 0
  15032. : caretPos.toRange();
  15033. };
  15034. const parentBlock = dom.getParent(marker, dom.isBlock);
  15035. dom.remove(marker);
  15036. if (parentBlock && dom.isEmpty(parentBlock)) {
  15037. const isCell = isTableCell(parentBlock);
  15038. empty(SugarElement.fromDom(parentBlock));
  15039. rng.setStart(parentBlock, 0);
  15040. rng.setEnd(parentBlock, 0);
  15041. if (
  15042. !isCell &&
  15043. !isPartOfFragment(parentBlock) &&
  15044. (nextRng = findNextCaretRng(rng))
  15045. ) {
  15046. rng = nextRng;
  15047. dom.remove(parentBlock);
  15048. } else {
  15049. dom.add(
  15050. parentBlock,
  15051. dom.create("br", isCell ? {} : { "data-mce-bogus": "1" })
  15052. );
  15053. }
  15054. }
  15055. selection.setRng(rng);
  15056. };
  15057. const deleteSelectedContent = (editor) => {
  15058. const dom = editor.dom;
  15059. const rng = normalize(editor.selection.getRng());
  15060. editor.selection.setRng(rng);
  15061. const startCell = dom.getParent(rng.startContainer, isTableCell);
  15062. if (isTableCellContentSelected(dom, rng, startCell)) {
  15063. deleteCellContents(editor, rng, SugarElement.fromDom(startCell));
  15064. } else if (
  15065. rng.startContainer === rng.endContainer &&
  15066. rng.endOffset - rng.startOffset === 1 &&
  15067. isText$a(rng.startContainer.childNodes[rng.startOffset])
  15068. ) {
  15069. rng.deleteContents();
  15070. } else {
  15071. editor.getDoc().execCommand("Delete", false);
  15072. }
  15073. };
  15074. const findMarkerNode = (scope) => {
  15075. for (let markerNode = scope; markerNode; markerNode = markerNode.walk()) {
  15076. if (markerNode.attr("id") === "mce_marker") {
  15077. return Optional.some(markerNode);
  15078. }
  15079. }
  15080. return Optional.none();
  15081. };
  15082. const insertHtmlAtCaret = (editor, value, details) => {
  15083. var _a, _b;
  15084. const selection = editor.selection;
  15085. const dom = editor.dom;
  15086. const parser = editor.parser;
  15087. const merge = details.merge;
  15088. const serializer = HtmlSerializer({ validate: true }, editor.schema);
  15089. const bookmarkHtml =
  15090. '<span id="mce_marker" data-mce-type="bookmark">&#xFEFF;</span>';
  15091. if (value.indexOf("{$caret}") === -1) {
  15092. value += "{$caret}";
  15093. }
  15094. value = value.replace(/\{\$caret\}/, bookmarkHtml);
  15095. let rng = selection.getRng();
  15096. const caretElement = rng.startContainer;
  15097. const body = editor.getBody();
  15098. if (caretElement === body && selection.isCollapsed()) {
  15099. if (
  15100. dom.isBlock(body.firstChild) &&
  15101. canHaveChildren(editor, body.firstChild) &&
  15102. dom.isEmpty(body.firstChild)
  15103. ) {
  15104. rng = dom.createRng();
  15105. rng.setStart(body.firstChild, 0);
  15106. rng.setEnd(body.firstChild, 0);
  15107. selection.setRng(rng);
  15108. }
  15109. }
  15110. if (!selection.isCollapsed()) {
  15111. deleteSelectedContent(editor);
  15112. }
  15113. const parentNode = selection.getNode();
  15114. const parserArgs = {
  15115. context: parentNode.nodeName.toLowerCase(),
  15116. data: details.data,
  15117. insert: true,
  15118. };
  15119. const fragment = parser.parse(value, parserArgs);
  15120. if (
  15121. details.paste === true &&
  15122. isListFragment(editor.schema, fragment) &&
  15123. isParentBlockLi(dom, parentNode)
  15124. ) {
  15125. rng = insertAtCaret$1(serializer, dom, selection.getRng(), fragment);
  15126. if (rng) {
  15127. selection.setRng(rng);
  15128. }
  15129. return value;
  15130. }
  15131. if (
  15132. details.paste === true &&
  15133. shouldPasteContentOnly(dom, fragment, parentNode, editor.getBody())
  15134. ) {
  15135. (_a = fragment.firstChild) === null || _a === void 0
  15136. ? void 0
  15137. : _a.unwrap();
  15138. }
  15139. markFragmentElements(fragment);
  15140. let node = fragment.lastChild;
  15141. if (node && node.attr("id") === "mce_marker") {
  15142. const marker = node;
  15143. for (node = node.prev; node; node = node.walk(true)) {
  15144. if (node.type === 3 || !dom.isBlock(node.name)) {
  15145. if (
  15146. node.parent &&
  15147. editor.schema.isValidChild(node.parent.name, "span")
  15148. ) {
  15149. node.parent.insert(marker, node, node.name === "br");
  15150. }
  15151. break;
  15152. }
  15153. }
  15154. }
  15155. editor._selectionOverrides.showBlockCaretContainer(parentNode);
  15156. if (!parserArgs.invalid) {
  15157. value = serializer.serialize(fragment);
  15158. validInsertion(editor, value, parentNode);
  15159. } else {
  15160. editor.selection.setContent(bookmarkHtml);
  15161. let parentNode = selection.getNode();
  15162. let tempNode;
  15163. const rootNode = editor.getBody();
  15164. if (isDocument$1(parentNode)) {
  15165. parentNode = tempNode = rootNode;
  15166. } else {
  15167. tempNode = parentNode;
  15168. }
  15169. while (tempNode && tempNode !== rootNode) {
  15170. parentNode = tempNode;
  15171. tempNode = tempNode.parentNode;
  15172. }
  15173. value =
  15174. parentNode === rootNode
  15175. ? rootNode.innerHTML
  15176. : dom.getOuterHTML(parentNode);
  15177. const root = parser.parse(value);
  15178. const markerNode = findMarkerNode(root);
  15179. const editingHost = markerNode.bind(findClosestEditingHost).getOr(root);
  15180. markerNode.each((marker) => marker.replace(fragment));
  15181. const toExtract = fragment.children();
  15182. const parent =
  15183. (_b = fragment.parent) !== null && _b !== void 0 ? _b : root;
  15184. fragment.unwrap();
  15185. const invalidChildren = filter$5(toExtract, (node) =>
  15186. isInvalid(editor.schema, node, parent)
  15187. );
  15188. cleanInvalidNodes(invalidChildren, editor.schema, editingHost);
  15189. filter$2(parser.getNodeFilters(), parser.getAttributeFilters(), root);
  15190. value = serializer.serialize(root);
  15191. if (parentNode === rootNode) {
  15192. dom.setHTML(rootNode, value);
  15193. } else {
  15194. dom.setOuterHTML(parentNode, value);
  15195. }
  15196. }
  15197. reduceInlineTextElements(editor, merge);
  15198. moveSelectionToMarker(editor, dom.get("mce_marker"));
  15199. unmarkFragmentElements(editor.getBody());
  15200. trimBrsFromTableCell(dom, selection.getStart());
  15201. updateCaret(editor.schema, editor.getBody(), selection.getStart());
  15202. return value;
  15203. };
  15204. const isTreeNode = (content) => content instanceof AstNode;
  15205. const moveSelection = (editor) => {
  15206. if (hasFocus(editor)) {
  15207. firstPositionIn(editor.getBody()).each((pos) => {
  15208. const node = pos.getNode();
  15209. const caretPos = isTable$2(node)
  15210. ? firstPositionIn(node).getOr(pos)
  15211. : pos;
  15212. editor.selection.setRng(caretPos.toRange());
  15213. });
  15214. }
  15215. };
  15216. const setEditorHtml = (editor, html, noSelection) => {
  15217. editor.dom.setHTML(editor.getBody(), html);
  15218. if (noSelection !== true) {
  15219. moveSelection(editor);
  15220. }
  15221. };
  15222. const setContentString = (editor, body, content, args) => {
  15223. if (content.length === 0 || /^\s+$/.test(content)) {
  15224. const padd = '<br data-mce-bogus="1">';
  15225. if (body.nodeName === "TABLE") {
  15226. content = "<tr><td>" + padd + "</td></tr>";
  15227. } else if (/^(UL|OL)$/.test(body.nodeName)) {
  15228. content = "<li>" + padd + "</li>";
  15229. }
  15230. const forcedRootBlockName = getForcedRootBlock(editor);
  15231. if (
  15232. editor.schema.isValidChild(
  15233. body.nodeName.toLowerCase(),
  15234. forcedRootBlockName.toLowerCase()
  15235. )
  15236. ) {
  15237. content = padd;
  15238. content = editor.dom.createHTML(
  15239. forcedRootBlockName,
  15240. getForcedRootBlockAttrs(editor),
  15241. content
  15242. );
  15243. } else if (!content) {
  15244. content = padd;
  15245. }
  15246. setEditorHtml(editor, content, args.no_selection);
  15247. return {
  15248. content,
  15249. html: content,
  15250. };
  15251. } else {
  15252. if (args.format !== "raw") {
  15253. content = HtmlSerializer({ validate: false }, editor.schema).serialize(
  15254. editor.parser.parse(content, {
  15255. isRootContent: true,
  15256. insert: true,
  15257. })
  15258. );
  15259. }
  15260. const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body))
  15261. ? content
  15262. : Tools.trim(content);
  15263. setEditorHtml(editor, trimmedHtml, args.no_selection);
  15264. return {
  15265. content: trimmedHtml,
  15266. html: trimmedHtml,
  15267. };
  15268. }
  15269. };
  15270. const setContentTree = (editor, body, content, args) => {
  15271. filter$2(
  15272. editor.parser.getNodeFilters(),
  15273. editor.parser.getAttributeFilters(),
  15274. content
  15275. );
  15276. const html = HtmlSerializer({ validate: false }, editor.schema).serialize(
  15277. content
  15278. );
  15279. const trimmedHtml = isWsPreserveElement(SugarElement.fromDom(body))
  15280. ? html
  15281. : Tools.trim(html);
  15282. setEditorHtml(editor, trimmedHtml, args.no_selection);
  15283. return {
  15284. content,
  15285. html: trimmedHtml,
  15286. };
  15287. };
  15288. const setContentInternal = (editor, content, args) => {
  15289. return Optional.from(editor.getBody())
  15290. .map((body) => {
  15291. if (isTreeNode(content)) {
  15292. return setContentTree(editor, body, content, args);
  15293. } else {
  15294. return setContentString(editor, body, content, args);
  15295. }
  15296. })
  15297. .getOr({
  15298. content,
  15299. html: isTreeNode(args.content) ? "" : args.content,
  15300. });
  15301. };
  15302. const ancestor$1 = (scope, predicate, isRoot) =>
  15303. ancestor$4(scope, predicate, isRoot).isSome();
  15304. const sibling = (scope, predicate) => sibling$1(scope, predicate).isSome();
  15305. const ensureIsRoot = (isRoot) => (isFunction(isRoot) ? isRoot : never);
  15306. const ancestor = (scope, transform, isRoot) => {
  15307. let element = scope.dom;
  15308. const stop = ensureIsRoot(isRoot);
  15309. while (element.parentNode) {
  15310. element = element.parentNode;
  15311. const el = SugarElement.fromDom(element);
  15312. const transformed = transform(el);
  15313. if (transformed.isSome()) {
  15314. return transformed;
  15315. } else if (stop(el)) {
  15316. break;
  15317. }
  15318. }
  15319. return Optional.none();
  15320. };
  15321. const closest$1 = (scope, transform, isRoot) => {
  15322. const current = transform(scope);
  15323. const stop = ensureIsRoot(isRoot);
  15324. return current.orThunk(() =>
  15325. stop(scope) ? Optional.none() : ancestor(scope, transform, stop)
  15326. );
  15327. };
  15328. const isEq$3 = isEq$5;
  15329. const matchesUnInheritedFormatSelector = (ed, node, name) => {
  15330. const formatList = ed.formatter.get(name);
  15331. if (formatList) {
  15332. for (let i = 0; i < formatList.length; i++) {
  15333. const format = formatList[i];
  15334. if (
  15335. isSelectorFormat(format) &&
  15336. format.inherit === false &&
  15337. ed.dom.is(node, format.selector)
  15338. ) {
  15339. return true;
  15340. }
  15341. }
  15342. }
  15343. return false;
  15344. };
  15345. const matchParents = (editor, node, name, vars, similar) => {
  15346. const root = editor.dom.getRoot();
  15347. if (node === root) {
  15348. return false;
  15349. }
  15350. const matchedNode = editor.dom.getParent(node, (elm) => {
  15351. if (matchesUnInheritedFormatSelector(editor, elm, name)) {
  15352. return true;
  15353. }
  15354. return (
  15355. elm.parentNode === root || !!matchNode(editor, elm, name, vars, true)
  15356. );
  15357. });
  15358. return !!matchNode(editor, matchedNode, name, vars, similar);
  15359. };
  15360. const matchName = (dom, node, format) => {
  15361. if (isInlineFormat(format) && isEq$3(node, format.inline)) {
  15362. return true;
  15363. }
  15364. if (isBlockFormat(format) && isEq$3(node, format.block)) {
  15365. return true;
  15366. }
  15367. if (isSelectorFormat(format)) {
  15368. return isElement$6(node) && dom.is(node, format.selector);
  15369. }
  15370. return false;
  15371. };
  15372. const matchItems = (dom, node, format, itemName, similar, vars) => {
  15373. const items = format[itemName];
  15374. const matchAttributes = itemName === "attributes";
  15375. if (isFunction(format.onmatch)) {
  15376. return format.onmatch(node, format, itemName);
  15377. }
  15378. if (items) {
  15379. if (!isArrayLike(items)) {
  15380. for (const key in items) {
  15381. if (has$2(items, key)) {
  15382. const value = matchAttributes
  15383. ? dom.getAttrib(node, key)
  15384. : getStyle(dom, node, key);
  15385. const expectedValue = replaceVars(items[key], vars);
  15386. const isEmptyValue = isNullable(value) || isEmpty$3(value);
  15387. if (isEmptyValue && isNullable(expectedValue)) {
  15388. continue;
  15389. }
  15390. if (similar && isEmptyValue && !format.exact) {
  15391. return false;
  15392. }
  15393. if (
  15394. (!similar || format.exact) &&
  15395. !isEq$3(value, normalizeStyleValue(expectedValue, key))
  15396. ) {
  15397. return false;
  15398. }
  15399. }
  15400. }
  15401. } else {
  15402. for (let i = 0; i < items.length; i++) {
  15403. if (
  15404. matchAttributes
  15405. ? dom.getAttrib(node, items[i])
  15406. : getStyle(dom, node, items[i])
  15407. ) {
  15408. return true;
  15409. }
  15410. }
  15411. }
  15412. }
  15413. return true;
  15414. };
  15415. const matchNode = (ed, node, name, vars, similar) => {
  15416. const formatList = ed.formatter.get(name);
  15417. const dom = ed.dom;
  15418. if (formatList && isElement$6(node)) {
  15419. for (let i = 0; i < formatList.length; i++) {
  15420. const format = formatList[i];
  15421. if (
  15422. matchName(ed.dom, node, format) &&
  15423. matchItems(dom, node, format, "attributes", similar, vars) &&
  15424. matchItems(dom, node, format, "styles", similar, vars)
  15425. ) {
  15426. const classes = format.classes;
  15427. if (classes) {
  15428. for (let x = 0; x < classes.length; x++) {
  15429. if (!ed.dom.hasClass(node, replaceVars(classes[x], vars))) {
  15430. return;
  15431. }
  15432. }
  15433. }
  15434. return format;
  15435. }
  15436. }
  15437. }
  15438. return undefined;
  15439. };
  15440. const match$2 = (editor, name, vars, node, similar) => {
  15441. if (node) {
  15442. return matchParents(editor, node, name, vars, similar);
  15443. }
  15444. node = editor.selection.getNode();
  15445. if (matchParents(editor, node, name, vars, similar)) {
  15446. return true;
  15447. }
  15448. const startNode = editor.selection.getStart();
  15449. if (startNode !== node) {
  15450. if (matchParents(editor, startNode, name, vars, similar)) {
  15451. return true;
  15452. }
  15453. }
  15454. return false;
  15455. };
  15456. const matchAll = (editor, names, vars) => {
  15457. const matchedFormatNames = [];
  15458. const checkedMap = {};
  15459. const startElement = editor.selection.getStart();
  15460. editor.dom.getParent(
  15461. startElement,
  15462. (node) => {
  15463. for (let i = 0; i < names.length; i++) {
  15464. const name = names[i];
  15465. if (!checkedMap[name] && matchNode(editor, node, name, vars)) {
  15466. checkedMap[name] = true;
  15467. matchedFormatNames.push(name);
  15468. }
  15469. }
  15470. },
  15471. editor.dom.getRoot()
  15472. );
  15473. return matchedFormatNames;
  15474. };
  15475. const closest = (editor, names) => {
  15476. const isRoot = (elm) => eq(elm, SugarElement.fromDom(editor.getBody()));
  15477. const match = (elm, name) =>
  15478. matchNode(editor, elm.dom, name) ? Optional.some(name) : Optional.none();
  15479. return Optional.from(editor.selection.getStart(true))
  15480. .bind((rawElm) =>
  15481. closest$1(
  15482. SugarElement.fromDom(rawElm),
  15483. (elm) => findMap(names, (name) => match(elm, name)),
  15484. isRoot
  15485. )
  15486. )
  15487. .getOrNull();
  15488. };
  15489. const canApply = (editor, name) => {
  15490. const formatList = editor.formatter.get(name);
  15491. const dom = editor.dom;
  15492. if (formatList && editor.selection.isEditable()) {
  15493. const startNode = editor.selection.getStart();
  15494. const parents = getParents$2(dom, startNode);
  15495. for (let x = formatList.length - 1; x >= 0; x--) {
  15496. const format = formatList[x];
  15497. if (!isSelectorFormat(format)) {
  15498. return true;
  15499. }
  15500. for (let i = parents.length - 1; i >= 0; i--) {
  15501. if (dom.is(parents[i], format.selector)) {
  15502. return true;
  15503. }
  15504. }
  15505. }
  15506. }
  15507. return false;
  15508. };
  15509. const matchAllOnNode = (editor, node, formatNames) =>
  15510. foldl(
  15511. formatNames,
  15512. (acc, name) => {
  15513. const matchSimilar = isVariableFormatName(editor, name);
  15514. if (editor.formatter.matchNode(node, name, {}, matchSimilar)) {
  15515. return acc.concat([name]);
  15516. } else {
  15517. return acc;
  15518. }
  15519. },
  15520. []
  15521. );
  15522. const ZWSP = ZWSP$1;
  15523. const importNode = (ownerDocument, node) => {
  15524. return ownerDocument.importNode(node, true);
  15525. };
  15526. const getEmptyCaretContainers = (node) => {
  15527. const nodes = [];
  15528. let tempNode = node;
  15529. while (tempNode) {
  15530. if (
  15531. (isText$a(tempNode) && tempNode.data !== ZWSP) ||
  15532. tempNode.childNodes.length > 1
  15533. ) {
  15534. return [];
  15535. }
  15536. if (isElement$6(tempNode)) {
  15537. nodes.push(tempNode);
  15538. }
  15539. tempNode = tempNode.firstChild;
  15540. }
  15541. return nodes;
  15542. };
  15543. const isCaretContainerEmpty = (node) => {
  15544. return getEmptyCaretContainers(node).length > 0;
  15545. };
  15546. const findFirstTextNode = (node) => {
  15547. if (node) {
  15548. const walker = new DomTreeWalker(node, node);
  15549. for (
  15550. let tempNode = walker.current();
  15551. tempNode;
  15552. tempNode = walker.next()
  15553. ) {
  15554. if (isText$a(tempNode)) {
  15555. return tempNode;
  15556. }
  15557. }
  15558. }
  15559. return null;
  15560. };
  15561. const createCaretContainer = (fill) => {
  15562. const caretContainer = SugarElement.fromTag("span");
  15563. setAll$1(caretContainer, {
  15564. id: CARET_ID,
  15565. "data-mce-bogus": "1",
  15566. "data-mce-type": "format-caret",
  15567. });
  15568. if (fill) {
  15569. append$1(caretContainer, SugarElement.fromText(ZWSP));
  15570. }
  15571. return caretContainer;
  15572. };
  15573. const trimZwspFromCaretContainer = (caretContainerNode) => {
  15574. const textNode = findFirstTextNode(caretContainerNode);
  15575. if (textNode && textNode.data.charAt(0) === ZWSP) {
  15576. textNode.deleteData(0, 1);
  15577. }
  15578. return textNode;
  15579. };
  15580. const removeCaretContainerNode = (editor, node, moveCaret = true) => {
  15581. const dom = editor.dom,
  15582. selection = editor.selection;
  15583. if (isCaretContainerEmpty(node)) {
  15584. deleteElement$2(editor, false, SugarElement.fromDom(node), moveCaret);
  15585. } else {
  15586. const rng = selection.getRng();
  15587. const block = dom.getParent(node, dom.isBlock);
  15588. const startContainer = rng.startContainer;
  15589. const startOffset = rng.startOffset;
  15590. const endContainer = rng.endContainer;
  15591. const endOffset = rng.endOffset;
  15592. const textNode = trimZwspFromCaretContainer(node);
  15593. dom.remove(node, true);
  15594. if (startContainer === textNode && startOffset > 0) {
  15595. rng.setStart(textNode, startOffset - 1);
  15596. }
  15597. if (endContainer === textNode && endOffset > 0) {
  15598. rng.setEnd(textNode, endOffset - 1);
  15599. }
  15600. if (block && dom.isEmpty(block)) {
  15601. fillWithPaddingBr(SugarElement.fromDom(block));
  15602. }
  15603. selection.setRng(rng);
  15604. }
  15605. };
  15606. const removeCaretContainer = (editor, node, moveCaret = true) => {
  15607. const dom = editor.dom,
  15608. selection = editor.selection;
  15609. if (!node) {
  15610. node = getParentCaretContainer(editor.getBody(), selection.getStart());
  15611. if (!node) {
  15612. while ((node = dom.get(CARET_ID))) {
  15613. removeCaretContainerNode(editor, node, moveCaret);
  15614. }
  15615. }
  15616. } else {
  15617. removeCaretContainerNode(editor, node, moveCaret);
  15618. }
  15619. };
  15620. const insertCaretContainerNode = (editor, caretContainer, formatNode) => {
  15621. var _a, _b;
  15622. const dom = editor.dom;
  15623. const block = dom.getParent(
  15624. formatNode,
  15625. curry(isTextBlock$1, editor.schema)
  15626. );
  15627. if (block && dom.isEmpty(block)) {
  15628. (_a = formatNode.parentNode) === null || _a === void 0
  15629. ? void 0
  15630. : _a.replaceChild(caretContainer, formatNode);
  15631. } else {
  15632. removeTrailingBr(SugarElement.fromDom(formatNode));
  15633. if (dom.isEmpty(formatNode)) {
  15634. (_b = formatNode.parentNode) === null || _b === void 0
  15635. ? void 0
  15636. : _b.replaceChild(caretContainer, formatNode);
  15637. } else {
  15638. dom.insertAfter(caretContainer, formatNode);
  15639. }
  15640. }
  15641. };
  15642. const appendNode = (parentNode, node) => {
  15643. parentNode.appendChild(node);
  15644. return node;
  15645. };
  15646. const insertFormatNodesIntoCaretContainer = (formatNodes, caretContainer) => {
  15647. var _a;
  15648. const innerMostFormatNode = foldr(
  15649. formatNodes,
  15650. (parentNode, formatNode) => {
  15651. return appendNode(parentNode, formatNode.cloneNode(false));
  15652. },
  15653. caretContainer
  15654. );
  15655. const doc =
  15656. (_a = innerMostFormatNode.ownerDocument) !== null && _a !== void 0
  15657. ? _a
  15658. : document;
  15659. return appendNode(innerMostFormatNode, doc.createTextNode(ZWSP));
  15660. };
  15661. const cleanFormatNode = (
  15662. editor,
  15663. caretContainer,
  15664. formatNode,
  15665. name,
  15666. vars,
  15667. similar
  15668. ) => {
  15669. const formatter = editor.formatter;
  15670. const dom = editor.dom;
  15671. const validFormats = filter$5(
  15672. keys(formatter.get()),
  15673. (formatName) =>
  15674. formatName !== name && !contains$1(formatName, "removeformat")
  15675. );
  15676. const matchedFormats = matchAllOnNode(editor, formatNode, validFormats);
  15677. const uniqueFormats = filter$5(
  15678. matchedFormats,
  15679. (fmtName) => !areSimilarFormats(editor, fmtName, name)
  15680. );
  15681. if (uniqueFormats.length > 0) {
  15682. const clonedFormatNode = formatNode.cloneNode(false);
  15683. dom.add(caretContainer, clonedFormatNode);
  15684. formatter.remove(name, vars, clonedFormatNode, similar);
  15685. dom.remove(clonedFormatNode);
  15686. return Optional.some(clonedFormatNode);
  15687. } else {
  15688. return Optional.none();
  15689. }
  15690. };
  15691. const applyCaretFormat = (editor, name, vars) => {
  15692. let caretContainer;
  15693. const selection = editor.selection;
  15694. const formatList = editor.formatter.get(name);
  15695. if (!formatList) {
  15696. return;
  15697. }
  15698. const selectionRng = selection.getRng();
  15699. let offset = selectionRng.startOffset;
  15700. const container = selectionRng.startContainer;
  15701. const text = container.nodeValue;
  15702. caretContainer = getParentCaretContainer(
  15703. editor.getBody(),
  15704. selection.getStart()
  15705. );
  15706. const wordcharRegex = /[^\s\u00a0\u00ad\u200b\ufeff]/;
  15707. if (
  15708. text &&
  15709. offset > 0 &&
  15710. offset < text.length &&
  15711. wordcharRegex.test(text.charAt(offset)) &&
  15712. wordcharRegex.test(text.charAt(offset - 1))
  15713. ) {
  15714. const bookmark = selection.getBookmark();
  15715. selectionRng.collapse(true);
  15716. let rng = expandRng(editor.dom, selectionRng, formatList);
  15717. rng = split(rng);
  15718. editor.formatter.apply(name, vars, rng);
  15719. selection.moveToBookmark(bookmark);
  15720. } else {
  15721. let textNode = caretContainer ? findFirstTextNode(caretContainer) : null;
  15722. if (
  15723. !caretContainer ||
  15724. (textNode === null || textNode === void 0 ? void 0 : textNode.data) !==
  15725. ZWSP
  15726. ) {
  15727. caretContainer = importNode(
  15728. editor.getDoc(),
  15729. createCaretContainer(true).dom
  15730. );
  15731. textNode = caretContainer.firstChild;
  15732. selectionRng.insertNode(caretContainer);
  15733. offset = 1;
  15734. editor.formatter.apply(name, vars, caretContainer);
  15735. } else {
  15736. editor.formatter.apply(name, vars, caretContainer);
  15737. }
  15738. selection.setCursorLocation(textNode, offset);
  15739. }
  15740. };
  15741. const removeCaretFormat = (editor, name, vars, similar) => {
  15742. const dom = editor.dom;
  15743. const selection = editor.selection;
  15744. let hasContentAfter = false;
  15745. const formatList = editor.formatter.get(name);
  15746. if (!formatList) {
  15747. return;
  15748. }
  15749. const rng = selection.getRng();
  15750. const container = rng.startContainer;
  15751. const offset = rng.startOffset;
  15752. let node = container;
  15753. if (isText$a(container)) {
  15754. if (offset !== container.data.length) {
  15755. hasContentAfter = true;
  15756. }
  15757. node = node.parentNode;
  15758. }
  15759. const parents = [];
  15760. let formatNode;
  15761. while (node) {
  15762. if (matchNode(editor, node, name, vars, similar)) {
  15763. formatNode = node;
  15764. break;
  15765. }
  15766. if (node.nextSibling) {
  15767. hasContentAfter = true;
  15768. }
  15769. parents.push(node);
  15770. node = node.parentNode;
  15771. }
  15772. if (!formatNode) {
  15773. return;
  15774. }
  15775. if (hasContentAfter) {
  15776. const bookmark = selection.getBookmark();
  15777. rng.collapse(true);
  15778. let expandedRng = expandRng(dom, rng, formatList, true);
  15779. expandedRng = split(expandedRng);
  15780. editor.formatter.remove(name, vars, expandedRng, similar);
  15781. selection.moveToBookmark(bookmark);
  15782. } else {
  15783. const caretContainer = getParentCaretContainer(
  15784. editor.getBody(),
  15785. formatNode
  15786. );
  15787. const newCaretContainer = createCaretContainer(false).dom;
  15788. insertCaretContainerNode(
  15789. editor,
  15790. newCaretContainer,
  15791. caretContainer !== null && caretContainer !== void 0
  15792. ? caretContainer
  15793. : formatNode
  15794. );
  15795. const cleanedFormatNode = cleanFormatNode(
  15796. editor,
  15797. newCaretContainer,
  15798. formatNode,
  15799. name,
  15800. vars,
  15801. similar
  15802. );
  15803. const caretTextNode = insertFormatNodesIntoCaretContainer(
  15804. parents.concat(cleanedFormatNode.toArray()),
  15805. newCaretContainer
  15806. );
  15807. if (caretContainer) {
  15808. removeCaretContainerNode(editor, caretContainer, false);
  15809. }
  15810. selection.setCursorLocation(caretTextNode, 1);
  15811. if (dom.isEmpty(formatNode)) {
  15812. dom.remove(formatNode);
  15813. }
  15814. }
  15815. };
  15816. const disableCaretContainer = (editor, keyCode, moveCaret) => {
  15817. const selection = editor.selection,
  15818. body = editor.getBody();
  15819. removeCaretContainer(editor, null, moveCaret);
  15820. if (
  15821. (keyCode === 8 || keyCode === 46) &&
  15822. selection.isCollapsed() &&
  15823. selection.getStart().innerHTML === ZWSP
  15824. ) {
  15825. removeCaretContainer(
  15826. editor,
  15827. getParentCaretContainer(body, selection.getStart())
  15828. );
  15829. }
  15830. if (keyCode === 37 || keyCode === 39) {
  15831. removeCaretContainer(
  15832. editor,
  15833. getParentCaretContainer(body, selection.getStart())
  15834. );
  15835. }
  15836. };
  15837. const endsWithNbsp = (element) =>
  15838. isText$a(element) && endsWith(element.data, nbsp);
  15839. const setup$u = (editor) => {
  15840. editor.on("mouseup keydown", (e) => {
  15841. disableCaretContainer(
  15842. editor,
  15843. e.keyCode,
  15844. endsWithNbsp(editor.selection.getRng().endContainer)
  15845. );
  15846. });
  15847. };
  15848. const createCaretFormat = (formatNodes) => {
  15849. const caretContainer = createCaretContainer(false);
  15850. const innerMost = insertFormatNodesIntoCaretContainer(
  15851. formatNodes,
  15852. caretContainer.dom
  15853. );
  15854. return {
  15855. caretContainer,
  15856. caretPosition: CaretPosition(innerMost, 0),
  15857. };
  15858. };
  15859. const replaceWithCaretFormat = (targetNode, formatNodes) => {
  15860. const { caretContainer, caretPosition } = createCaretFormat(formatNodes);
  15861. before$3(SugarElement.fromDom(targetNode), caretContainer);
  15862. remove$5(SugarElement.fromDom(targetNode));
  15863. return caretPosition;
  15864. };
  15865. const createCaretFormatAtStart$1 = (rng, formatNodes) => {
  15866. const { caretContainer, caretPosition } = createCaretFormat(formatNodes);
  15867. rng.insertNode(caretContainer.dom);
  15868. return caretPosition;
  15869. };
  15870. const isFormatElement = (editor, element) => {
  15871. const inlineElements = editor.schema.getTextInlineElements();
  15872. return (
  15873. has$2(inlineElements, name(element)) &&
  15874. !isCaretNode(element.dom) &&
  15875. !isBogus$2(element.dom)
  15876. );
  15877. };
  15878. const isEmptyCaretFormatElement = (element) => {
  15879. return isCaretNode(element.dom) && isCaretContainerEmpty(element.dom);
  15880. };
  15881. const postProcessHooks = {};
  15882. const isPre = matchNodeNames(["pre"]);
  15883. const addPostProcessHook = (name, hook) => {
  15884. const hooks = postProcessHooks[name];
  15885. if (!hooks) {
  15886. postProcessHooks[name] = [];
  15887. }
  15888. postProcessHooks[name].push(hook);
  15889. };
  15890. const postProcess$1 = (name, editor) => {
  15891. if (has$2(postProcessHooks, name)) {
  15892. each$e(postProcessHooks[name], (hook) => {
  15893. hook(editor);
  15894. });
  15895. }
  15896. };
  15897. addPostProcessHook("pre", (editor) => {
  15898. const rng = editor.selection.getRng();
  15899. const hasPreSibling = (blocks) => (pre) => {
  15900. const prev = pre.previousSibling;
  15901. return isPre(prev) && contains$2(blocks, prev);
  15902. };
  15903. const joinPre = (pre1, pre2) => {
  15904. const sPre2 = SugarElement.fromDom(pre2);
  15905. const doc = documentOrOwner(sPre2).dom;
  15906. remove$5(sPre2);
  15907. append(SugarElement.fromDom(pre1), [
  15908. SugarElement.fromTag("br", doc),
  15909. SugarElement.fromTag("br", doc),
  15910. ...children$1(sPre2),
  15911. ]);
  15912. };
  15913. if (!rng.collapsed) {
  15914. const blocks = editor.selection.getSelectedBlocks();
  15915. const preBlocks = filter$5(
  15916. filter$5(blocks, isPre),
  15917. hasPreSibling(blocks)
  15918. );
  15919. each$e(preBlocks, (pre) => {
  15920. joinPre(pre.previousSibling, pre);
  15921. });
  15922. }
  15923. });
  15924. const listItemStyles = [
  15925. "fontWeight",
  15926. "fontStyle",
  15927. "color",
  15928. "fontSize",
  15929. "fontFamily",
  15930. ];
  15931. const hasListStyles = (fmt) =>
  15932. isObject(fmt.styles) &&
  15933. exists(keys(fmt.styles), (name) => contains$2(listItemStyles, name));
  15934. const findExpandedListItemFormat = (formats) =>
  15935. find$2(
  15936. formats,
  15937. (fmt) =>
  15938. isInlineFormat(fmt) && fmt.inline === "span" && hasListStyles(fmt)
  15939. );
  15940. const getExpandedListItemFormat = (formatter, format) => {
  15941. const formatList = formatter.get(format);
  15942. return isArray$1(formatList)
  15943. ? findExpandedListItemFormat(formatList)
  15944. : Optional.none();
  15945. };
  15946. const isRngStartAtStartOfElement = (rng, elm) =>
  15947. prevPosition(elm, CaretPosition.fromRangeStart(rng)).isNone();
  15948. const isRngEndAtEndOfElement = (rng, elm) => {
  15949. return (
  15950. nextPosition(elm, CaretPosition.fromRangeEnd(rng)).exists(
  15951. (pos) => !isBr$6(pos.getNode()) || nextPosition(elm, pos).isSome()
  15952. ) === false
  15953. );
  15954. };
  15955. const isEditableListItem = (dom) => (elm) =>
  15956. isListItem$2(elm) && dom.isEditable(elm);
  15957. const getFullySelectedBlocks = (selection) => {
  15958. const blocks = selection.getSelectedBlocks();
  15959. const rng = selection.getRng();
  15960. if (selection.isCollapsed()) {
  15961. return [];
  15962. }
  15963. if (blocks.length === 1) {
  15964. return isRngStartAtStartOfElement(rng, blocks[0]) &&
  15965. isRngEndAtEndOfElement(rng, blocks[0])
  15966. ? blocks
  15967. : [];
  15968. } else {
  15969. const first = head(blocks)
  15970. .filter((elm) => isRngStartAtStartOfElement(rng, elm))
  15971. .toArray();
  15972. const last = last$3(blocks)
  15973. .filter((elm) => isRngEndAtEndOfElement(rng, elm))
  15974. .toArray();
  15975. const middle = blocks.slice(1, -1);
  15976. return first.concat(middle).concat(last);
  15977. }
  15978. };
  15979. const getFullySelectedListItems = (selection) =>
  15980. filter$5(
  15981. getFullySelectedBlocks(selection),
  15982. isEditableListItem(selection.dom)
  15983. );
  15984. const getPartiallySelectedListItems = (selection) =>
  15985. filter$5(selection.getSelectedBlocks(), isEditableListItem(selection.dom));
  15986. const each$8 = Tools.each;
  15987. const isElementNode = (node) =>
  15988. isElement$6(node) &&
  15989. !isBookmarkNode$1(node) &&
  15990. !isCaretNode(node) &&
  15991. !isBogus$2(node);
  15992. const findElementSibling = (node, siblingName) => {
  15993. for (let sibling = node; sibling; sibling = sibling[siblingName]) {
  15994. if (isText$a(sibling) && isNotEmpty(sibling.data)) {
  15995. return node;
  15996. }
  15997. if (isElement$6(sibling) && !isBookmarkNode$1(sibling)) {
  15998. return sibling;
  15999. }
  16000. }
  16001. return node;
  16002. };
  16003. const mergeSiblingsNodes = (editor, prev, next) => {
  16004. const elementUtils = ElementUtils(editor);
  16005. const isPrevEditable = isElement$6(prev) && isEditable$2(prev);
  16006. const isNextEditable = isElement$6(next) && isEditable$2(next);
  16007. if (isPrevEditable && isNextEditable) {
  16008. const prevSibling = findElementSibling(prev, "previousSibling");
  16009. const nextSibling = findElementSibling(next, "nextSibling");
  16010. if (elementUtils.compare(prevSibling, nextSibling)) {
  16011. for (
  16012. let sibling = prevSibling.nextSibling;
  16013. sibling && sibling !== nextSibling;
  16014. ) {
  16015. const tmpSibling = sibling;
  16016. sibling = sibling.nextSibling;
  16017. prevSibling.appendChild(tmpSibling);
  16018. }
  16019. editor.dom.remove(nextSibling);
  16020. Tools.each(Tools.grep(nextSibling.childNodes), (node) => {
  16021. prevSibling.appendChild(node);
  16022. });
  16023. return prevSibling;
  16024. }
  16025. }
  16026. return next;
  16027. };
  16028. const mergeSiblings = (editor, format, vars, node) => {
  16029. var _a;
  16030. if (node && format.merge_siblings !== false) {
  16031. const newNode =
  16032. (_a = mergeSiblingsNodes(
  16033. editor,
  16034. getNonWhiteSpaceSibling(node),
  16035. node
  16036. )) !== null && _a !== void 0
  16037. ? _a
  16038. : node;
  16039. mergeSiblingsNodes(
  16040. editor,
  16041. newNode,
  16042. getNonWhiteSpaceSibling(newNode, true)
  16043. );
  16044. }
  16045. };
  16046. const clearChildStyles = (dom, format, node) => {
  16047. if (format.clear_child_styles) {
  16048. const selector = format.links ? "*:not(a)" : "*";
  16049. each$8(dom.select(selector, node), (childNode) => {
  16050. if (isElementNode(childNode) && isEditable$2(childNode)) {
  16051. each$8(format.styles, (_value, name) => {
  16052. dom.setStyle(childNode, name, "");
  16053. });
  16054. }
  16055. });
  16056. }
  16057. };
  16058. const processChildElements = (node, filter, process) => {
  16059. each$8(node.childNodes, (node) => {
  16060. if (isElementNode(node)) {
  16061. if (filter(node)) {
  16062. process(node);
  16063. }
  16064. if (node.hasChildNodes()) {
  16065. processChildElements(node, filter, process);
  16066. }
  16067. }
  16068. });
  16069. };
  16070. const unwrapEmptySpan = (dom, node) => {
  16071. if (node.nodeName === "SPAN" && dom.getAttribs(node).length === 0) {
  16072. dom.remove(node, true);
  16073. }
  16074. };
  16075. const hasStyle = (dom, name) => (node) =>
  16076. !!(node && getStyle(dom, node, name));
  16077. const applyStyle = (dom, name, value) => (node) => {
  16078. dom.setStyle(node, name, value);
  16079. if (node.getAttribute("style") === "") {
  16080. node.removeAttribute("style");
  16081. }
  16082. unwrapEmptySpan(dom, node);
  16083. };
  16084. const removeResult = Adt.generate([
  16085. { keep: [] },
  16086. { rename: ["name"] },
  16087. { removed: [] },
  16088. ]);
  16089. const MCE_ATTR_RE = /^(src|href|style)$/;
  16090. const each$7 = Tools.each;
  16091. const isEq$2 = isEq$5;
  16092. const isTableCellOrRow = (node) => /^(TR|TH|TD)$/.test(node.nodeName);
  16093. const isChildOfInlineParent = (dom, node, parent) =>
  16094. dom.isChildOf(node, parent) && node !== parent && !dom.isBlock(parent);
  16095. const getContainer = (ed, rng, start) => {
  16096. let container = rng[start ? "startContainer" : "endContainer"];
  16097. let offset = rng[start ? "startOffset" : "endOffset"];
  16098. if (isElement$6(container)) {
  16099. const lastIdx = container.childNodes.length - 1;
  16100. if (!start && offset) {
  16101. offset--;
  16102. }
  16103. container = container.childNodes[offset > lastIdx ? lastIdx : offset];
  16104. }
  16105. if (isText$a(container) && start && offset >= container.data.length) {
  16106. container =
  16107. new DomTreeWalker(container, ed.getBody()).next() || container;
  16108. }
  16109. if (isText$a(container) && !start && offset === 0) {
  16110. container =
  16111. new DomTreeWalker(container, ed.getBody()).prev() || container;
  16112. }
  16113. return container;
  16114. };
  16115. const normalizeTableSelection = (node, start) => {
  16116. const prop = start ? "firstChild" : "lastChild";
  16117. const childNode = node[prop];
  16118. if (isTableCellOrRow(node) && childNode) {
  16119. if (node.nodeName === "TR") {
  16120. return childNode[prop] || childNode;
  16121. } else {
  16122. return childNode;
  16123. }
  16124. }
  16125. return node;
  16126. };
  16127. const wrap$1 = (dom, node, name, attrs) => {
  16128. var _a;
  16129. const wrapper = dom.create(name, attrs);
  16130. (_a = node.parentNode) === null || _a === void 0
  16131. ? void 0
  16132. : _a.insertBefore(wrapper, node);
  16133. wrapper.appendChild(node);
  16134. return wrapper;
  16135. };
  16136. const wrapWithSiblings = (dom, node, next, name, attrs) => {
  16137. const start = SugarElement.fromDom(node);
  16138. const wrapper = SugarElement.fromDom(dom.create(name, attrs));
  16139. const siblings = next ? nextSiblings(start) : prevSiblings(start);
  16140. append(wrapper, siblings);
  16141. if (next) {
  16142. before$3(start, wrapper);
  16143. prepend(wrapper, start);
  16144. } else {
  16145. after$4(start, wrapper);
  16146. append$1(wrapper, start);
  16147. }
  16148. return wrapper.dom;
  16149. };
  16150. const isColorFormatAndAnchor = (node, format) =>
  16151. format.links && node.nodeName === "A";
  16152. const removeNode = (ed, node, format) => {
  16153. const parentNode = node.parentNode;
  16154. let rootBlockElm;
  16155. const dom = ed.dom;
  16156. const forcedRootBlock = getForcedRootBlock(ed);
  16157. if (isBlockFormat(format)) {
  16158. if (parentNode === dom.getRoot()) {
  16159. if (!format.list_block || !isEq$2(node, format.list_block)) {
  16160. each$e(from(node.childNodes), (node) => {
  16161. if (isValid(ed, forcedRootBlock, node.nodeName.toLowerCase())) {
  16162. if (!rootBlockElm) {
  16163. rootBlockElm = wrap$1(dom, node, forcedRootBlock);
  16164. dom.setAttribs(rootBlockElm, getForcedRootBlockAttrs(ed));
  16165. } else {
  16166. rootBlockElm.appendChild(node);
  16167. }
  16168. } else {
  16169. rootBlockElm = null;
  16170. }
  16171. });
  16172. }
  16173. }
  16174. }
  16175. if (isMixedFormat(format) && !isEq$2(format.inline, node)) {
  16176. return;
  16177. }
  16178. dom.remove(node, true);
  16179. };
  16180. const processFormatAttrOrStyle = (name, value, vars) => {
  16181. if (isNumber(name)) {
  16182. return {
  16183. name: value,
  16184. value: null,
  16185. };
  16186. } else {
  16187. return {
  16188. name,
  16189. value: replaceVars(value, vars),
  16190. };
  16191. }
  16192. };
  16193. const removeEmptyStyleAttributeIfNeeded = (dom, elm) => {
  16194. if (dom.getAttrib(elm, "style") === "") {
  16195. elm.removeAttribute("style");
  16196. elm.removeAttribute("data-mce-style");
  16197. }
  16198. };
  16199. const removeStyles = (dom, elm, format, vars, compareNode) => {
  16200. let stylesModified = false;
  16201. each$7(format.styles, (value, name) => {
  16202. const { name: styleName, value: styleValue } = processFormatAttrOrStyle(
  16203. name,
  16204. value,
  16205. vars
  16206. );
  16207. const normalizedStyleValue = normalizeStyleValue(styleValue, styleName);
  16208. if (
  16209. format.remove_similar ||
  16210. isNull(styleValue) ||
  16211. !isElement$6(compareNode) ||
  16212. isEq$2(getStyle(dom, compareNode, styleName), normalizedStyleValue)
  16213. ) {
  16214. dom.setStyle(elm, styleName, "");
  16215. }
  16216. stylesModified = true;
  16217. });
  16218. if (stylesModified) {
  16219. removeEmptyStyleAttributeIfNeeded(dom, elm);
  16220. }
  16221. };
  16222. const removeListStyleFormats = (editor, name, vars) => {
  16223. if (name === "removeformat") {
  16224. each$e(getPartiallySelectedListItems(editor.selection), (li) => {
  16225. each$e(listItemStyles, (name) => editor.dom.setStyle(li, name, ""));
  16226. removeEmptyStyleAttributeIfNeeded(editor.dom, li);
  16227. });
  16228. } else {
  16229. getExpandedListItemFormat(editor.formatter, name).each((liFmt) => {
  16230. each$e(getPartiallySelectedListItems(editor.selection), (li) =>
  16231. removeStyles(editor.dom, li, liFmt, vars, null)
  16232. );
  16233. });
  16234. }
  16235. };
  16236. const removeNodeFormatInternal = (ed, format, vars, node, compareNode) => {
  16237. const dom = ed.dom;
  16238. const elementUtils = ElementUtils(ed);
  16239. const schema = ed.schema;
  16240. if (
  16241. isInlineFormat(format) &&
  16242. isTransparentElementName(schema, format.inline) &&
  16243. isTransparentBlock(schema, node) &&
  16244. node.parentElement === ed.getBody()
  16245. ) {
  16246. removeNode(ed, node, format);
  16247. return removeResult.removed();
  16248. }
  16249. if (
  16250. !format.ceFalseOverride &&
  16251. node &&
  16252. dom.getContentEditableParent(node) === "false"
  16253. ) {
  16254. return removeResult.keep();
  16255. }
  16256. if (
  16257. node &&
  16258. !matchName(dom, node, format) &&
  16259. !isColorFormatAndAnchor(node, format)
  16260. ) {
  16261. return removeResult.keep();
  16262. }
  16263. const elm = node;
  16264. const preserveAttributes = format.preserve_attributes;
  16265. if (
  16266. isInlineFormat(format) &&
  16267. format.remove === "all" &&
  16268. isArray$1(preserveAttributes)
  16269. ) {
  16270. const attrsToPreserve = filter$5(dom.getAttribs(elm), (attr) =>
  16271. contains$2(preserveAttributes, attr.name.toLowerCase())
  16272. );
  16273. dom.removeAllAttribs(elm);
  16274. each$e(attrsToPreserve, (attr) =>
  16275. dom.setAttrib(elm, attr.name, attr.value)
  16276. );
  16277. if (attrsToPreserve.length > 0) {
  16278. return removeResult.rename("span");
  16279. }
  16280. }
  16281. if (format.remove !== "all") {
  16282. removeStyles(dom, elm, format, vars, compareNode);
  16283. each$7(format.attributes, (value, name) => {
  16284. const { name: attrName, value: attrValue } = processFormatAttrOrStyle(
  16285. name,
  16286. value,
  16287. vars
  16288. );
  16289. if (
  16290. format.remove_similar ||
  16291. isNull(attrValue) ||
  16292. !isElement$6(compareNode) ||
  16293. isEq$2(dom.getAttrib(compareNode, attrName), attrValue)
  16294. ) {
  16295. if (attrName === "class") {
  16296. const currentValue = dom.getAttrib(elm, attrName);
  16297. if (currentValue) {
  16298. let valueOut = "";
  16299. each$e(currentValue.split(/\s+/), (cls) => {
  16300. if (/mce\-\w+/.test(cls)) {
  16301. valueOut += (valueOut ? " " : "") + cls;
  16302. }
  16303. });
  16304. if (valueOut) {
  16305. dom.setAttrib(elm, attrName, valueOut);
  16306. return;
  16307. }
  16308. }
  16309. }
  16310. if (MCE_ATTR_RE.test(attrName)) {
  16311. elm.removeAttribute("data-mce-" + attrName);
  16312. }
  16313. if (
  16314. attrName === "style" &&
  16315. matchNodeNames(["li"])(elm) &&
  16316. dom.getStyle(elm, "list-style-type") === "none"
  16317. ) {
  16318. elm.removeAttribute(attrName);
  16319. dom.setStyle(elm, "list-style-type", "none");
  16320. return;
  16321. }
  16322. if (attrName === "class") {
  16323. elm.removeAttribute("className");
  16324. }
  16325. elm.removeAttribute(attrName);
  16326. }
  16327. });
  16328. each$7(format.classes, (value) => {
  16329. value = replaceVars(value, vars);
  16330. if (!isElement$6(compareNode) || dom.hasClass(compareNode, value)) {
  16331. dom.removeClass(elm, value);
  16332. }
  16333. });
  16334. const attrs = dom.getAttribs(elm);
  16335. for (let i = 0; i < attrs.length; i++) {
  16336. const attrName = attrs[i].nodeName;
  16337. if (!elementUtils.isAttributeInternal(attrName)) {
  16338. return removeResult.keep();
  16339. }
  16340. }
  16341. }
  16342. if (format.remove !== "none") {
  16343. removeNode(ed, elm, format);
  16344. return removeResult.removed();
  16345. }
  16346. return removeResult.keep();
  16347. };
  16348. const findFormatRoot = (editor, container, name, vars, similar) => {
  16349. let formatRoot;
  16350. if (container.parentNode) {
  16351. each$e(
  16352. getParents$2(editor.dom, container.parentNode).reverse(),
  16353. (parent) => {
  16354. if (
  16355. !formatRoot &&
  16356. isElement$6(parent) &&
  16357. parent.id !== "_start" &&
  16358. parent.id !== "_end"
  16359. ) {
  16360. const format = matchNode(editor, parent, name, vars, similar);
  16361. if (format && format.split !== false) {
  16362. formatRoot = parent;
  16363. }
  16364. }
  16365. }
  16366. );
  16367. }
  16368. return formatRoot;
  16369. };
  16370. const removeNodeFormatFromClone = (editor, format, vars, clone) =>
  16371. removeNodeFormatInternal(editor, format, vars, clone, clone).fold(
  16372. constant(clone),
  16373. (newName) => {
  16374. const fragment = editor.dom.createFragment();
  16375. fragment.appendChild(clone);
  16376. return editor.dom.rename(clone, newName);
  16377. },
  16378. constant(null)
  16379. );
  16380. const wrapAndSplit = (
  16381. editor,
  16382. formatList,
  16383. formatRoot,
  16384. container,
  16385. target,
  16386. split,
  16387. format,
  16388. vars
  16389. ) => {
  16390. var _a, _b;
  16391. let lastClone;
  16392. let firstClone;
  16393. const dom = editor.dom;
  16394. if (formatRoot) {
  16395. const formatRootParent = formatRoot.parentNode;
  16396. for (
  16397. let parent = container.parentNode;
  16398. parent && parent !== formatRootParent;
  16399. parent = parent.parentNode
  16400. ) {
  16401. let clone = dom.clone(parent, false);
  16402. for (let i = 0; i < formatList.length; i++) {
  16403. clone = removeNodeFormatFromClone(editor, formatList[i], vars, clone);
  16404. if (clone === null) {
  16405. break;
  16406. }
  16407. }
  16408. if (clone) {
  16409. if (lastClone) {
  16410. clone.appendChild(lastClone);
  16411. }
  16412. if (!firstClone) {
  16413. firstClone = clone;
  16414. }
  16415. lastClone = clone;
  16416. }
  16417. }
  16418. if (split && (!format.mixed || !dom.isBlock(formatRoot))) {
  16419. container =
  16420. (_a = dom.split(formatRoot, container)) !== null && _a !== void 0
  16421. ? _a
  16422. : container;
  16423. }
  16424. if (lastClone && firstClone) {
  16425. (_b = target.parentNode) === null || _b === void 0
  16426. ? void 0
  16427. : _b.insertBefore(lastClone, target);
  16428. firstClone.appendChild(target);
  16429. if (isInlineFormat(format)) {
  16430. mergeSiblings(editor, format, vars, lastClone);
  16431. }
  16432. }
  16433. }
  16434. return container;
  16435. };
  16436. const removeFormatInternal = (ed, name, vars, node, similar) => {
  16437. const formatList = ed.formatter.get(name);
  16438. const format = formatList[0];
  16439. const dom = ed.dom;
  16440. const selection = ed.selection;
  16441. const splitToFormatRoot = (container) => {
  16442. const formatRoot = findFormatRoot(ed, container, name, vars, similar);
  16443. return wrapAndSplit(
  16444. ed,
  16445. formatList,
  16446. formatRoot,
  16447. container,
  16448. container,
  16449. true,
  16450. format,
  16451. vars
  16452. );
  16453. };
  16454. const isRemoveBookmarkNode = (node) =>
  16455. isBookmarkNode$1(node) &&
  16456. isElement$6(node) &&
  16457. (node.id === "_start" || node.id === "_end");
  16458. const removeFormatOnNode = (node) =>
  16459. exists(formatList, (fmt) => removeNodeFormat(ed, fmt, vars, node, node));
  16460. const process = (node) => {
  16461. const children = from(node.childNodes);
  16462. const removed = removeFormatOnNode(node);
  16463. const currentNodeMatches =
  16464. removed || exists(formatList, (f) => matchName(dom, node, f));
  16465. const parentNode = node.parentNode;
  16466. if (
  16467. !currentNodeMatches &&
  16468. isNonNullable(parentNode) &&
  16469. shouldExpandToSelector(format)
  16470. ) {
  16471. removeFormatOnNode(parentNode);
  16472. }
  16473. if (format.deep) {
  16474. if (children.length) {
  16475. for (let i = 0; i < children.length; i++) {
  16476. process(children[i]);
  16477. }
  16478. }
  16479. }
  16480. const textDecorations = ["underline", "line-through", "overline"];
  16481. each$e(textDecorations, (decoration) => {
  16482. if (
  16483. isElement$6(node) &&
  16484. ed.dom.getStyle(node, "text-decoration") === decoration &&
  16485. node.parentNode &&
  16486. getTextDecoration(dom, node.parentNode) === decoration
  16487. ) {
  16488. removeNodeFormat(
  16489. ed,
  16490. {
  16491. deep: false,
  16492. exact: true,
  16493. inline: "span",
  16494. styles: { textDecoration: decoration },
  16495. },
  16496. undefined,
  16497. node
  16498. );
  16499. }
  16500. });
  16501. };
  16502. const unwrap = (start) => {
  16503. const node = dom.get(start ? "_start" : "_end");
  16504. if (node) {
  16505. let out = node[start ? "firstChild" : "lastChild"];
  16506. if (isRemoveBookmarkNode(out)) {
  16507. out = out[start ? "firstChild" : "lastChild"];
  16508. }
  16509. if (isText$a(out) && out.data.length === 0) {
  16510. out = start
  16511. ? node.previousSibling || node.nextSibling
  16512. : node.nextSibling || node.previousSibling;
  16513. }
  16514. dom.remove(node, true);
  16515. return out;
  16516. } else {
  16517. return null;
  16518. }
  16519. };
  16520. const removeRngStyle = (rng) => {
  16521. let startContainer;
  16522. let endContainer;
  16523. let expandedRng = expandRng(dom, rng, formatList, rng.collapsed);
  16524. if (format.split) {
  16525. expandedRng = split(expandedRng);
  16526. startContainer = getContainer(ed, expandedRng, true);
  16527. endContainer = getContainer(ed, expandedRng);
  16528. if (startContainer !== endContainer) {
  16529. startContainer = normalizeTableSelection(startContainer, true);
  16530. endContainer = normalizeTableSelection(endContainer, false);
  16531. if (isChildOfInlineParent(dom, startContainer, endContainer)) {
  16532. const marker = Optional.from(startContainer.firstChild).getOr(
  16533. startContainer
  16534. );
  16535. splitToFormatRoot(
  16536. wrapWithSiblings(dom, marker, true, "span", {
  16537. id: "_start",
  16538. "data-mce-type": "bookmark",
  16539. })
  16540. );
  16541. unwrap(true);
  16542. return;
  16543. }
  16544. if (isChildOfInlineParent(dom, endContainer, startContainer)) {
  16545. const marker = Optional.from(endContainer.lastChild).getOr(
  16546. endContainer
  16547. );
  16548. splitToFormatRoot(
  16549. wrapWithSiblings(dom, marker, false, "span", {
  16550. id: "_end",
  16551. "data-mce-type": "bookmark",
  16552. })
  16553. );
  16554. unwrap(false);
  16555. return;
  16556. }
  16557. startContainer = wrap$1(dom, startContainer, "span", {
  16558. id: "_start",
  16559. "data-mce-type": "bookmark",
  16560. });
  16561. endContainer = wrap$1(dom, endContainer, "span", {
  16562. id: "_end",
  16563. "data-mce-type": "bookmark",
  16564. });
  16565. const newRng = dom.createRng();
  16566. newRng.setStartAfter(startContainer);
  16567. newRng.setEndBefore(endContainer);
  16568. walk$3(dom, newRng, (nodes) => {
  16569. each$e(nodes, (n) => {
  16570. if (!isBookmarkNode$1(n) && !isBookmarkNode$1(n.parentNode)) {
  16571. splitToFormatRoot(n);
  16572. }
  16573. });
  16574. });
  16575. splitToFormatRoot(startContainer);
  16576. splitToFormatRoot(endContainer);
  16577. startContainer = unwrap(true);
  16578. endContainer = unwrap();
  16579. } else {
  16580. startContainer = endContainer = splitToFormatRoot(startContainer);
  16581. }
  16582. expandedRng.startContainer = startContainer.parentNode
  16583. ? startContainer.parentNode
  16584. : startContainer;
  16585. expandedRng.startOffset = dom.nodeIndex(startContainer);
  16586. expandedRng.endContainer = endContainer.parentNode
  16587. ? endContainer.parentNode
  16588. : endContainer;
  16589. expandedRng.endOffset = dom.nodeIndex(endContainer) + 1;
  16590. }
  16591. walk$3(dom, expandedRng, (nodes) => {
  16592. each$e(nodes, process);
  16593. });
  16594. };
  16595. if (node) {
  16596. if (isNode(node)) {
  16597. const rng = dom.createRng();
  16598. rng.setStartBefore(node);
  16599. rng.setEndAfter(node);
  16600. removeRngStyle(rng);
  16601. } else {
  16602. removeRngStyle(node);
  16603. }
  16604. fireFormatRemove(ed, name, node, vars);
  16605. return;
  16606. }
  16607. if (
  16608. !selection.isCollapsed() ||
  16609. !isInlineFormat(format) ||
  16610. getCellsFromEditor(ed).length
  16611. ) {
  16612. preserveSelection(
  16613. ed,
  16614. () => runOnRanges(ed, removeRngStyle),
  16615. (startNode) =>
  16616. isInlineFormat(format) && match$2(ed, name, vars, startNode)
  16617. );
  16618. ed.nodeChanged();
  16619. } else {
  16620. removeCaretFormat(ed, name, vars, similar);
  16621. }
  16622. removeListStyleFormats(ed, name, vars);
  16623. fireFormatRemove(ed, name, node, vars);
  16624. };
  16625. const removeFormat$1 = (ed, name, vars, node, similar) => {
  16626. if (node || ed.selection.isEditable()) {
  16627. removeFormatInternal(ed, name, vars, node, similar);
  16628. }
  16629. };
  16630. const removeNodeFormat = (editor, format, vars, node, compareNode) => {
  16631. return removeNodeFormatInternal(
  16632. editor,
  16633. format,
  16634. vars,
  16635. node,
  16636. compareNode
  16637. ).fold(
  16638. never,
  16639. (newName) => {
  16640. editor.dom.rename(node, newName);
  16641. return true;
  16642. },
  16643. always
  16644. );
  16645. };
  16646. const each$6 = Tools.each;
  16647. const mergeTextDecorationsAndColor = (dom, format, vars, node) => {
  16648. const processTextDecorationsAndColor = (n) => {
  16649. if (isElement$6(n) && isElement$6(n.parentNode) && isEditable$2(n)) {
  16650. const parentTextDecoration = getTextDecoration(dom, n.parentNode);
  16651. if (dom.getStyle(n, "color") && parentTextDecoration) {
  16652. dom.setStyle(n, "text-decoration", parentTextDecoration);
  16653. } else if (
  16654. dom.getStyle(n, "text-decoration") === parentTextDecoration
  16655. ) {
  16656. dom.setStyle(n, "text-decoration", null);
  16657. }
  16658. }
  16659. };
  16660. if (
  16661. format.styles &&
  16662. (format.styles.color || format.styles.textDecoration)
  16663. ) {
  16664. Tools.walk(node, processTextDecorationsAndColor, "childNodes");
  16665. processTextDecorationsAndColor(node);
  16666. }
  16667. };
  16668. const mergeBackgroundColorAndFontSize = (dom, format, vars, node) => {
  16669. if (format.styles && format.styles.backgroundColor) {
  16670. const hasFontSize = hasStyle(dom, "fontSize");
  16671. processChildElements(
  16672. node,
  16673. (elm) => hasFontSize(elm) && isEditable$2(elm),
  16674. applyStyle(
  16675. dom,
  16676. "backgroundColor",
  16677. replaceVars(format.styles.backgroundColor, vars)
  16678. )
  16679. );
  16680. }
  16681. };
  16682. const mergeSubSup = (dom, format, vars, node) => {
  16683. if (
  16684. isInlineFormat(format) &&
  16685. (format.inline === "sub" || format.inline === "sup")
  16686. ) {
  16687. const hasFontSize = hasStyle(dom, "fontSize");
  16688. processChildElements(
  16689. node,
  16690. (elm) => hasFontSize(elm) && isEditable$2(elm),
  16691. applyStyle(dom, "fontSize", "")
  16692. );
  16693. const inverseTagDescendants = filter$5(
  16694. dom.select(format.inline === "sup" ? "sub" : "sup", node),
  16695. isEditable$2
  16696. );
  16697. dom.remove(inverseTagDescendants, true);
  16698. }
  16699. };
  16700. const mergeWithChildren = (editor, formatList, vars, node) => {
  16701. each$6(formatList, (format) => {
  16702. if (isInlineFormat(format)) {
  16703. each$6(editor.dom.select(format.inline, node), (child) => {
  16704. if (isElementNode(child)) {
  16705. removeNodeFormat(
  16706. editor,
  16707. format,
  16708. vars,
  16709. child,
  16710. format.exact ? child : null
  16711. );
  16712. }
  16713. });
  16714. }
  16715. clearChildStyles(editor.dom, format, node);
  16716. });
  16717. };
  16718. const mergeWithParents = (editor, format, name, vars, node) => {
  16719. const parentNode = node.parentNode;
  16720. if (matchNode(editor, parentNode, name, vars)) {
  16721. if (removeNodeFormat(editor, format, vars, node)) {
  16722. return;
  16723. }
  16724. }
  16725. if (format.merge_with_parents && parentNode) {
  16726. editor.dom.getParent(parentNode, (parent) => {
  16727. if (matchNode(editor, parent, name, vars)) {
  16728. removeNodeFormat(editor, format, vars, node);
  16729. return true;
  16730. } else {
  16731. return false;
  16732. }
  16733. });
  16734. }
  16735. };
  16736. const each$5 = Tools.each;
  16737. const canFormatBR = (editor, format, node, parentName) => {
  16738. if (
  16739. canFormatEmptyLines(editor) &&
  16740. isInlineFormat(format) &&
  16741. node.parentNode
  16742. ) {
  16743. const validBRParentElements = getTextRootBlockElements(editor.schema);
  16744. const hasCaretNodeSibling = sibling(
  16745. SugarElement.fromDom(node),
  16746. (sibling) => isCaretNode(sibling.dom)
  16747. );
  16748. return (
  16749. hasNonNullableKey(validBRParentElements, parentName) &&
  16750. isEmpty$2(SugarElement.fromDom(node.parentNode), false) &&
  16751. !hasCaretNodeSibling
  16752. );
  16753. } else {
  16754. return false;
  16755. }
  16756. };
  16757. const applyStyles = (dom, elm, format, vars) => {
  16758. each$5(format.styles, (value, name) => {
  16759. dom.setStyle(elm, name, replaceVars(value, vars));
  16760. });
  16761. if (format.styles) {
  16762. const styleVal = dom.getAttrib(elm, "style");
  16763. if (styleVal) {
  16764. dom.setAttrib(elm, "data-mce-style", styleVal);
  16765. }
  16766. }
  16767. };
  16768. const applyFormatAction = (ed, name, vars, node) => {
  16769. const formatList = ed.formatter.get(name);
  16770. const format = formatList[0];
  16771. const isCollapsed = !node && ed.selection.isCollapsed();
  16772. const dom = ed.dom;
  16773. const selection = ed.selection;
  16774. const setElementFormat = (elm, fmt = format) => {
  16775. if (isFunction(fmt.onformat)) {
  16776. fmt.onformat(elm, fmt, vars, node);
  16777. }
  16778. applyStyles(dom, elm, fmt, vars);
  16779. each$5(fmt.attributes, (value, name) => {
  16780. dom.setAttrib(elm, name, replaceVars(value, vars));
  16781. });
  16782. each$5(fmt.classes, (value) => {
  16783. const newValue = replaceVars(value, vars);
  16784. if (!dom.hasClass(elm, newValue)) {
  16785. dom.addClass(elm, newValue);
  16786. }
  16787. });
  16788. };
  16789. const applyNodeStyle = (formatList, node) => {
  16790. let found = false;
  16791. each$5(formatList, (format) => {
  16792. if (!isSelectorFormat(format)) {
  16793. return false;
  16794. }
  16795. if (
  16796. dom.getContentEditable(node) === "false" &&
  16797. !format.ceFalseOverride
  16798. ) {
  16799. return true;
  16800. }
  16801. if (
  16802. isNonNullable(format.collapsed) &&
  16803. format.collapsed !== isCollapsed
  16804. ) {
  16805. return true;
  16806. }
  16807. if (dom.is(node, format.selector) && !isCaretNode(node)) {
  16808. setElementFormat(node, format);
  16809. found = true;
  16810. return false;
  16811. }
  16812. return true;
  16813. });
  16814. return found;
  16815. };
  16816. const createWrapElement = (wrapName) => {
  16817. if (isString(wrapName)) {
  16818. const wrapElm = dom.create(wrapName);
  16819. setElementFormat(wrapElm);
  16820. return wrapElm;
  16821. } else {
  16822. return null;
  16823. }
  16824. };
  16825. const applyRngStyle = (dom, rng, nodeSpecific) => {
  16826. const newWrappers = [];
  16827. let contentEditable = true;
  16828. const wrapName = format.inline || format.block;
  16829. const wrapElm = createWrapElement(wrapName);
  16830. const isMatchingWrappingBlock = (node) =>
  16831. isWrappingBlockFormat(format) && matchNode(ed, node, name, vars);
  16832. const canRenameBlock = (node, parentName, isEditableDescendant) => {
  16833. const isValidBlockFormatForNode =
  16834. isNonWrappingBlockFormat(format) &&
  16835. isTextBlock$1(ed.schema, node) &&
  16836. isValid(ed, parentName, wrapName);
  16837. return isEditableDescendant && isValidBlockFormatForNode;
  16838. };
  16839. const canWrapNode = (
  16840. node,
  16841. parentName,
  16842. isEditableDescendant,
  16843. isWrappableNoneditableElm
  16844. ) => {
  16845. const nodeName = node.nodeName.toLowerCase();
  16846. const isValidWrapNode =
  16847. isValid(ed, wrapName, nodeName) && isValid(ed, parentName, wrapName);
  16848. const isZwsp = !nodeSpecific && isText$a(node) && isZwsp$1(node.data);
  16849. const isCaret = isCaretNode(node);
  16850. const isCorrectFormatForNode =
  16851. !isInlineFormat(format) || !dom.isBlock(node);
  16852. return (
  16853. (isEditableDescendant || isWrappableNoneditableElm) &&
  16854. isValidWrapNode &&
  16855. !isZwsp &&
  16856. !isCaret &&
  16857. isCorrectFormatForNode
  16858. );
  16859. };
  16860. walk$3(dom, rng, (nodes) => {
  16861. let currentWrapElm;
  16862. const process = (node) => {
  16863. let hasContentEditableState = false;
  16864. let lastContentEditable = contentEditable;
  16865. let isWrappableNoneditableElm = false;
  16866. const parentNode = node.parentNode;
  16867. const parentName = parentNode.nodeName.toLowerCase();
  16868. const contentEditableValue = dom.getContentEditable(node);
  16869. if (isNonNullable(contentEditableValue)) {
  16870. lastContentEditable = contentEditable;
  16871. contentEditable = contentEditableValue === "true";
  16872. hasContentEditableState = true;
  16873. isWrappableNoneditableElm = isWrappableNoneditable(ed, node);
  16874. }
  16875. const isEditableDescendant =
  16876. contentEditable && !hasContentEditableState;
  16877. if (isBr$6(node) && !canFormatBR(ed, format, node, parentName)) {
  16878. currentWrapElm = null;
  16879. if (isBlockFormat(format)) {
  16880. dom.remove(node);
  16881. }
  16882. return;
  16883. }
  16884. if (isMatchingWrappingBlock(node)) {
  16885. currentWrapElm = null;
  16886. return;
  16887. }
  16888. if (canRenameBlock(node, parentName, isEditableDescendant)) {
  16889. const elm = dom.rename(node, wrapName);
  16890. setElementFormat(elm);
  16891. newWrappers.push(elm);
  16892. currentWrapElm = null;
  16893. return;
  16894. }
  16895. if (isSelectorFormat(format)) {
  16896. let found = applyNodeStyle(formatList, node);
  16897. if (
  16898. !found &&
  16899. isNonNullable(parentNode) &&
  16900. shouldExpandToSelector(format)
  16901. ) {
  16902. found = applyNodeStyle(formatList, parentNode);
  16903. }
  16904. if (!isInlineFormat(format) || found) {
  16905. currentWrapElm = null;
  16906. return;
  16907. }
  16908. }
  16909. if (
  16910. isNonNullable(wrapElm) &&
  16911. canWrapNode(
  16912. node,
  16913. parentName,
  16914. isEditableDescendant,
  16915. isWrappableNoneditableElm
  16916. )
  16917. ) {
  16918. if (!currentWrapElm) {
  16919. currentWrapElm = dom.clone(wrapElm, false);
  16920. parentNode.insertBefore(currentWrapElm, node);
  16921. newWrappers.push(currentWrapElm);
  16922. }
  16923. if (isWrappableNoneditableElm && hasContentEditableState) {
  16924. contentEditable = lastContentEditable;
  16925. }
  16926. currentWrapElm.appendChild(node);
  16927. } else {
  16928. currentWrapElm = null;
  16929. each$e(from(node.childNodes), process);
  16930. if (hasContentEditableState) {
  16931. contentEditable = lastContentEditable;
  16932. }
  16933. currentWrapElm = null;
  16934. }
  16935. };
  16936. each$e(nodes, process);
  16937. });
  16938. if (format.links === true) {
  16939. each$e(newWrappers, (node) => {
  16940. const process = (node) => {
  16941. if (node.nodeName === "A") {
  16942. setElementFormat(node, format);
  16943. }
  16944. each$e(from(node.childNodes), process);
  16945. };
  16946. process(node);
  16947. });
  16948. }
  16949. each$e(newWrappers, (node) => {
  16950. const getChildCount = (node) => {
  16951. let count = 0;
  16952. each$e(node.childNodes, (node) => {
  16953. if (!isEmptyTextNode$1(node) && !isBookmarkNode$1(node)) {
  16954. count++;
  16955. }
  16956. });
  16957. return count;
  16958. };
  16959. const mergeStyles = (node) => {
  16960. const childElement = find$2(node.childNodes, isElementNode$1).filter(
  16961. (child) =>
  16962. dom.getContentEditable(child) !== "false" &&
  16963. matchName(dom, child, format)
  16964. );
  16965. return childElement
  16966. .map((child) => {
  16967. const clone = dom.clone(child, false);
  16968. setElementFormat(clone);
  16969. dom.replace(clone, node, true);
  16970. dom.remove(child, true);
  16971. return clone;
  16972. })
  16973. .getOr(node);
  16974. };
  16975. const childCount = getChildCount(node);
  16976. if (
  16977. (newWrappers.length > 1 || !dom.isBlock(node)) &&
  16978. childCount === 0
  16979. ) {
  16980. dom.remove(node, true);
  16981. return;
  16982. }
  16983. if (
  16984. isInlineFormat(format) ||
  16985. (isBlockFormat(format) && format.wrapper)
  16986. ) {
  16987. if (!format.exact && childCount === 1) {
  16988. node = mergeStyles(node);
  16989. }
  16990. mergeWithChildren(ed, formatList, vars, node);
  16991. mergeWithParents(ed, format, name, vars, node);
  16992. mergeBackgroundColorAndFontSize(dom, format, vars, node);
  16993. mergeTextDecorationsAndColor(dom, format, vars, node);
  16994. mergeSubSup(dom, format, vars, node);
  16995. mergeSiblings(ed, format, vars, node);
  16996. }
  16997. });
  16998. };
  16999. const targetNode = isNode(node) ? node : selection.getNode();
  17000. if (
  17001. dom.getContentEditable(targetNode) === "false" &&
  17002. !isWrappableNoneditable(ed, targetNode)
  17003. ) {
  17004. node = targetNode;
  17005. applyNodeStyle(formatList, node);
  17006. fireFormatApply(ed, name, node, vars);
  17007. return;
  17008. }
  17009. if (format) {
  17010. if (node) {
  17011. if (isNode(node)) {
  17012. if (!applyNodeStyle(formatList, node)) {
  17013. const rng = dom.createRng();
  17014. rng.setStartBefore(node);
  17015. rng.setEndAfter(node);
  17016. applyRngStyle(dom, expandRng(dom, rng, formatList), true);
  17017. }
  17018. } else {
  17019. applyRngStyle(dom, node, true);
  17020. }
  17021. } else {
  17022. if (
  17023. !isCollapsed ||
  17024. !isInlineFormat(format) ||
  17025. getCellsFromEditor(ed).length
  17026. ) {
  17027. selection.setRng(normalize(selection.getRng()));
  17028. preserveSelection(
  17029. ed,
  17030. () => {
  17031. runOnRanges(ed, (selectionRng, fake) => {
  17032. const expandedRng = fake
  17033. ? selectionRng
  17034. : expandRng(dom, selectionRng, formatList);
  17035. applyRngStyle(dom, expandedRng, false);
  17036. });
  17037. },
  17038. always
  17039. );
  17040. ed.nodeChanged();
  17041. } else {
  17042. applyCaretFormat(ed, name, vars);
  17043. }
  17044. getExpandedListItemFormat(ed.formatter, name).each((liFmt) => {
  17045. each$e(getFullySelectedListItems(ed.selection), (li) =>
  17046. applyStyles(dom, li, liFmt, vars)
  17047. );
  17048. });
  17049. }
  17050. postProcess$1(name, ed);
  17051. }
  17052. fireFormatApply(ed, name, node, vars);
  17053. };
  17054. const applyFormat$1 = (editor, name, vars, node) => {
  17055. if (node || editor.selection.isEditable()) {
  17056. applyFormatAction(editor, name, vars, node);
  17057. }
  17058. };
  17059. const hasVars = (value) => has$2(value, "vars");
  17060. const setup$t = (registeredFormatListeners, editor) => {
  17061. registeredFormatListeners.set({});
  17062. editor.on("NodeChange", (e) => {
  17063. updateAndFireChangeCallbacks(
  17064. editor,
  17065. e.element,
  17066. registeredFormatListeners.get()
  17067. );
  17068. });
  17069. editor.on("FormatApply FormatRemove", (e) => {
  17070. const element = Optional.from(e.node)
  17071. .map((nodeOrRange) =>
  17072. isNode(nodeOrRange) ? nodeOrRange : nodeOrRange.startContainer
  17073. )
  17074. .bind((node) =>
  17075. isElement$6(node)
  17076. ? Optional.some(node)
  17077. : Optional.from(node.parentElement)
  17078. )
  17079. .getOrThunk(() => fallbackElement(editor));
  17080. updateAndFireChangeCallbacks(
  17081. editor,
  17082. element,
  17083. registeredFormatListeners.get()
  17084. );
  17085. });
  17086. };
  17087. const fallbackElement = (editor) => editor.selection.getStart();
  17088. const matchingNode = (editor, parents, format, similar, vars) => {
  17089. const isMatchingNode = (node) => {
  17090. const matchingFormat = editor.formatter.matchNode(
  17091. node,
  17092. format,
  17093. vars !== null && vars !== void 0 ? vars : {},
  17094. similar
  17095. );
  17096. return !isUndefined(matchingFormat);
  17097. };
  17098. const isUnableToMatch = (node) => {
  17099. if (matchesUnInheritedFormatSelector(editor, node, format)) {
  17100. return true;
  17101. } else {
  17102. if (!similar) {
  17103. return isNonNullable(
  17104. editor.formatter.matchNode(node, format, vars, true)
  17105. );
  17106. } else {
  17107. return false;
  17108. }
  17109. }
  17110. };
  17111. return findUntil$1(parents, isMatchingNode, isUnableToMatch);
  17112. };
  17113. const getParents = (editor, elm) => {
  17114. const element =
  17115. elm !== null && elm !== void 0 ? elm : fallbackElement(editor);
  17116. return filter$5(
  17117. getParents$2(editor.dom, element),
  17118. (node) => isElement$6(node) && !isBogus$2(node)
  17119. );
  17120. };
  17121. const updateAndFireChangeCallbacks = (editor, elm, registeredCallbacks) => {
  17122. const parents = getParents(editor, elm);
  17123. each$d(registeredCallbacks, (data, format) => {
  17124. const runIfChanged = (spec) => {
  17125. const match = matchingNode(
  17126. editor,
  17127. parents,
  17128. format,
  17129. spec.similar,
  17130. hasVars(spec) ? spec.vars : undefined
  17131. );
  17132. const isSet = match.isSome();
  17133. if (spec.state.get() !== isSet) {
  17134. spec.state.set(isSet);
  17135. const node = match.getOr(elm);
  17136. if (hasVars(spec)) {
  17137. spec.callback(isSet, {
  17138. node,
  17139. format,
  17140. parents,
  17141. });
  17142. } else {
  17143. each$e(spec.callbacks, (callback) =>
  17144. callback(isSet, {
  17145. node,
  17146. format,
  17147. parents,
  17148. })
  17149. );
  17150. }
  17151. }
  17152. };
  17153. each$e([data.withSimilar, data.withoutSimilar], runIfChanged);
  17154. each$e(data.withVars, runIfChanged);
  17155. });
  17156. };
  17157. const addListeners = (
  17158. editor,
  17159. registeredFormatListeners,
  17160. formats,
  17161. callback,
  17162. similar,
  17163. vars
  17164. ) => {
  17165. const formatChangeItems = registeredFormatListeners.get();
  17166. each$e(formats.split(","), (format) => {
  17167. const group = get$a(formatChangeItems, format).getOrThunk(() => {
  17168. const base = {
  17169. withSimilar: {
  17170. state: Cell(false),
  17171. similar: true,
  17172. callbacks: [],
  17173. },
  17174. withoutSimilar: {
  17175. state: Cell(false),
  17176. similar: false,
  17177. callbacks: [],
  17178. },
  17179. withVars: [],
  17180. };
  17181. formatChangeItems[format] = base;
  17182. return base;
  17183. });
  17184. const getCurrent = () => {
  17185. const parents = getParents(editor);
  17186. return matchingNode(editor, parents, format, similar, vars).isSome();
  17187. };
  17188. if (isUndefined(vars)) {
  17189. const toAppendTo = similar ? group.withSimilar : group.withoutSimilar;
  17190. toAppendTo.callbacks.push(callback);
  17191. if (toAppendTo.callbacks.length === 1) {
  17192. toAppendTo.state.set(getCurrent());
  17193. }
  17194. } else {
  17195. group.withVars.push({
  17196. state: Cell(getCurrent()),
  17197. similar,
  17198. vars,
  17199. callback,
  17200. });
  17201. }
  17202. });
  17203. registeredFormatListeners.set(formatChangeItems);
  17204. };
  17205. const removeListeners = (registeredFormatListeners, formats, callback) => {
  17206. const formatChangeItems = registeredFormatListeners.get();
  17207. each$e(formats.split(","), (format) =>
  17208. get$a(formatChangeItems, format).each((group) => {
  17209. formatChangeItems[format] = {
  17210. withSimilar: {
  17211. ...group.withSimilar,
  17212. callbacks: filter$5(
  17213. group.withSimilar.callbacks,
  17214. (cb) => cb !== callback
  17215. ),
  17216. },
  17217. withoutSimilar: {
  17218. ...group.withoutSimilar,
  17219. callbacks: filter$5(
  17220. group.withoutSimilar.callbacks,
  17221. (cb) => cb !== callback
  17222. ),
  17223. },
  17224. withVars: filter$5(
  17225. group.withVars,
  17226. (item) => item.callback !== callback
  17227. ),
  17228. };
  17229. })
  17230. );
  17231. registeredFormatListeners.set(formatChangeItems);
  17232. };
  17233. const formatChangedInternal = (
  17234. editor,
  17235. registeredFormatListeners,
  17236. formats,
  17237. callback,
  17238. similar,
  17239. vars
  17240. ) => {
  17241. addListeners(
  17242. editor,
  17243. registeredFormatListeners,
  17244. formats,
  17245. callback,
  17246. similar,
  17247. vars
  17248. );
  17249. return {
  17250. unbind: () =>
  17251. removeListeners(registeredFormatListeners, formats, callback),
  17252. };
  17253. };
  17254. const toggle = (editor, name, vars, node) => {
  17255. const fmt = editor.formatter.get(name);
  17256. if (fmt) {
  17257. if (
  17258. match$2(editor, name, vars, node) &&
  17259. (!("toggle" in fmt[0]) || fmt[0].toggle)
  17260. ) {
  17261. removeFormat$1(editor, name, vars, node);
  17262. } else {
  17263. applyFormat$1(editor, name, vars, node);
  17264. }
  17265. }
  17266. };
  17267. const explode$1 = Tools.explode;
  17268. const create$8 = () => {
  17269. const filters = {};
  17270. const addFilter = (name, callback) => {
  17271. each$e(explode$1(name), (name) => {
  17272. if (!has$2(filters, name)) {
  17273. filters[name] = {
  17274. name,
  17275. callbacks: [],
  17276. };
  17277. }
  17278. filters[name].callbacks.push(callback);
  17279. });
  17280. };
  17281. const getFilters = () => values(filters);
  17282. const removeFilter = (name, callback) => {
  17283. each$e(explode$1(name), (name) => {
  17284. if (has$2(filters, name)) {
  17285. if (isNonNullable(callback)) {
  17286. const filter = filters[name];
  17287. const newCallbacks = filter$5(
  17288. filter.callbacks,
  17289. (c) => c !== callback
  17290. );
  17291. if (newCallbacks.length > 0) {
  17292. filter.callbacks = newCallbacks;
  17293. } else {
  17294. delete filters[name];
  17295. }
  17296. } else {
  17297. delete filters[name];
  17298. }
  17299. }
  17300. });
  17301. };
  17302. return {
  17303. addFilter,
  17304. getFilters,
  17305. removeFilter,
  17306. };
  17307. };
  17308. const removeAttrs = (node, names) => {
  17309. each$e(names, (name) => {
  17310. node.attr(name, null);
  17311. });
  17312. };
  17313. const addFontToSpansFilter = (domParser, styles, fontSizes) => {
  17314. domParser.addNodeFilter("font", (nodes) => {
  17315. each$e(nodes, (node) => {
  17316. const props = styles.parse(node.attr("style"));
  17317. const color = node.attr("color");
  17318. const face = node.attr("face");
  17319. const size = node.attr("size");
  17320. if (color) {
  17321. props.color = color;
  17322. }
  17323. if (face) {
  17324. props["font-family"] = face;
  17325. }
  17326. if (size) {
  17327. toInt(size).each((num) => {
  17328. props["font-size"] = fontSizes[num - 1];
  17329. });
  17330. }
  17331. node.name = "span";
  17332. node.attr("style", styles.serialize(props));
  17333. removeAttrs(node, ["color", "face", "size"]);
  17334. });
  17335. });
  17336. };
  17337. const addStrikeFilter = (domParser, schema, styles) => {
  17338. domParser.addNodeFilter("strike", (nodes) => {
  17339. const convertToSTag = schema.type !== "html4";
  17340. each$e(nodes, (node) => {
  17341. if (convertToSTag) {
  17342. node.name = "s";
  17343. } else {
  17344. const props = styles.parse(node.attr("style"));
  17345. props["text-decoration"] = "line-through";
  17346. node.name = "span";
  17347. node.attr("style", styles.serialize(props));
  17348. }
  17349. });
  17350. });
  17351. };
  17352. const addFilters = (domParser, settings, schema) => {
  17353. var _a;
  17354. const styles = Styles();
  17355. if (settings.convert_fonts_to_spans) {
  17356. addFontToSpansFilter(
  17357. domParser,
  17358. styles,
  17359. Tools.explode(
  17360. (_a = settings.font_size_legacy_values) !== null && _a !== void 0
  17361. ? _a
  17362. : ""
  17363. )
  17364. );
  17365. }
  17366. addStrikeFilter(domParser, schema, styles);
  17367. };
  17368. const register$5 = (domParser, settings, schema) => {
  17369. if (settings.inline_styles) {
  17370. addFilters(domParser, settings, schema);
  17371. }
  17372. };
  17373. const addNodeFilter = (settings, htmlParser, schema) => {
  17374. htmlParser.addNodeFilter("br", (nodes, _, args) => {
  17375. const blockElements = Tools.extend({}, schema.getBlockElements());
  17376. const nonEmptyElements = schema.getNonEmptyElements();
  17377. const whitespaceElements = schema.getWhitespaceElements();
  17378. blockElements.body = 1;
  17379. const isBlock = (node) =>
  17380. node.name in blockElements || isTransparentAstBlock(schema, node);
  17381. for (let i = 0, l = nodes.length; i < l; i++) {
  17382. let node = nodes[i];
  17383. let parent = node.parent;
  17384. if (parent && isBlock(parent) && node === parent.lastChild) {
  17385. let prev = node.prev;
  17386. while (prev) {
  17387. const prevName = prev.name;
  17388. if (
  17389. prevName !== "span" ||
  17390. prev.attr("data-mce-type") !== "bookmark"
  17391. ) {
  17392. if (prevName === "br") {
  17393. node = null;
  17394. }
  17395. break;
  17396. }
  17397. prev = prev.prev;
  17398. }
  17399. if (node) {
  17400. node.remove();
  17401. if (isEmpty(schema, nonEmptyElements, whitespaceElements, parent)) {
  17402. const elementRule = schema.getElementRule(parent.name);
  17403. if (elementRule) {
  17404. if (elementRule.removeEmpty) {
  17405. parent.remove();
  17406. } else if (elementRule.paddEmpty) {
  17407. paddEmptyNode(settings, args, isBlock, parent);
  17408. }
  17409. }
  17410. }
  17411. }
  17412. } else {
  17413. let lastParent = node;
  17414. while (
  17415. parent &&
  17416. parent.firstChild === lastParent &&
  17417. parent.lastChild === lastParent
  17418. ) {
  17419. lastParent = parent;
  17420. if (blockElements[parent.name]) {
  17421. break;
  17422. }
  17423. parent = parent.parent;
  17424. }
  17425. if (lastParent === parent) {
  17426. const textNode = new AstNode("#text", 3);
  17427. textNode.value = nbsp;
  17428. node.replace(textNode);
  17429. }
  17430. }
  17431. }
  17432. });
  17433. };
  17434. const blobUriToBlob = (url) =>
  17435. fetch(url)
  17436. .then((res) => (res.ok ? res.blob() : Promise.reject()))
  17437. .catch(() =>
  17438. Promise.reject({
  17439. message: `Cannot convert ${url} to Blob. Resource might not exist or is inaccessible.`,
  17440. uriType: "blob",
  17441. })
  17442. );
  17443. const extractBase64Data = (data) => {
  17444. const matches = /([a-z0-9+\/=\s]+)/i.exec(data);
  17445. return matches ? matches[1] : "";
  17446. };
  17447. const parseDataUri = (uri) => {
  17448. const [type, ...rest] = uri.split(",");
  17449. const data = rest.join(",");
  17450. const matches = /data:([^/]+\/[^;]+)(;.+)?/.exec(type);
  17451. if (matches) {
  17452. const base64Encoded = matches[2] === ";base64";
  17453. const extractedData = base64Encoded
  17454. ? extractBase64Data(data)
  17455. : decodeURIComponent(data);
  17456. return Optional.some({
  17457. type: matches[1],
  17458. data: extractedData,
  17459. base64Encoded,
  17460. });
  17461. } else {
  17462. return Optional.none();
  17463. }
  17464. };
  17465. const buildBlob = (type, data, base64Encoded = true) => {
  17466. let str = data;
  17467. if (base64Encoded) {
  17468. try {
  17469. str = atob(data);
  17470. } catch (e) {
  17471. return Optional.none();
  17472. }
  17473. }
  17474. const arr = new Uint8Array(str.length);
  17475. for (let i = 0; i < arr.length; i++) {
  17476. arr[i] = str.charCodeAt(i);
  17477. }
  17478. return Optional.some(new Blob([arr], { type }));
  17479. };
  17480. const dataUriToBlob = (uri) => {
  17481. return new Promise((resolve, reject) => {
  17482. parseDataUri(uri)
  17483. .bind(({ type, data, base64Encoded }) =>
  17484. buildBlob(type, data, base64Encoded)
  17485. )
  17486. .fold(() => reject("Invalid data URI"), resolve);
  17487. });
  17488. };
  17489. const uriToBlob = (url) => {
  17490. if (startsWith(url, "blob:")) {
  17491. return blobUriToBlob(url);
  17492. } else if (startsWith(url, "data:")) {
  17493. return dataUriToBlob(url);
  17494. } else {
  17495. return Promise.reject("Unknown URI format");
  17496. }
  17497. };
  17498. const blobToDataUri = (blob) => {
  17499. return new Promise((resolve, reject) => {
  17500. const reader = new FileReader();
  17501. reader.onloadend = () => {
  17502. resolve(reader.result);
  17503. };
  17504. reader.onerror = () => {
  17505. var _a;
  17506. reject(
  17507. (_a = reader.error) === null || _a === void 0 ? void 0 : _a.message
  17508. );
  17509. };
  17510. reader.readAsDataURL(blob);
  17511. });
  17512. };
  17513. let count$1 = 0;
  17514. const uniqueId$1 = (prefix) => {
  17515. return (prefix || "blobid") + count$1++;
  17516. };
  17517. const processDataUri = (dataUri, base64Only, generateBlobInfo) => {
  17518. return parseDataUri(dataUri).bind(({ data, type, base64Encoded }) => {
  17519. if (base64Only && !base64Encoded) {
  17520. return Optional.none();
  17521. } else {
  17522. const base64 = base64Encoded ? data : btoa(data);
  17523. return generateBlobInfo(base64, type);
  17524. }
  17525. });
  17526. };
  17527. const createBlobInfo$1 = (blobCache, blob, base64) => {
  17528. const blobInfo = blobCache.create(uniqueId$1(), blob, base64);
  17529. blobCache.add(blobInfo);
  17530. return blobInfo;
  17531. };
  17532. const dataUriToBlobInfo = (blobCache, dataUri, base64Only = false) => {
  17533. return processDataUri(dataUri, base64Only, (base64, type) =>
  17534. Optional.from(blobCache.getByData(base64, type)).orThunk(() =>
  17535. buildBlob(type, base64).map((blob) =>
  17536. createBlobInfo$1(blobCache, blob, base64)
  17537. )
  17538. )
  17539. );
  17540. };
  17541. const imageToBlobInfo = (blobCache, imageSrc) => {
  17542. const invalidDataUri = () => Promise.reject("Invalid data URI");
  17543. if (startsWith(imageSrc, "blob:")) {
  17544. const blobInfo = blobCache.getByUri(imageSrc);
  17545. if (isNonNullable(blobInfo)) {
  17546. return Promise.resolve(blobInfo);
  17547. } else {
  17548. return uriToBlob(imageSrc).then((blob) => {
  17549. return blobToDataUri(blob).then((dataUri) => {
  17550. return processDataUri(dataUri, false, (base64) => {
  17551. return Optional.some(createBlobInfo$1(blobCache, blob, base64));
  17552. }).getOrThunk(invalidDataUri);
  17553. });
  17554. });
  17555. }
  17556. } else if (startsWith(imageSrc, "data:")) {
  17557. return dataUriToBlobInfo(blobCache, imageSrc).fold(
  17558. invalidDataUri,
  17559. (blobInfo) => Promise.resolve(blobInfo)
  17560. );
  17561. } else {
  17562. return Promise.reject("Unknown image data format");
  17563. }
  17564. };
  17565. const isBogusImage = (img) => isNonNullable(img.attr("data-mce-bogus"));
  17566. const isInternalImageSource = (img) =>
  17567. img.attr("src") === Env.transparentSrc ||
  17568. isNonNullable(img.attr("data-mce-placeholder"));
  17569. const registerBase64ImageFilter = (parser, settings) => {
  17570. const { blob_cache: blobCache } = settings;
  17571. if (blobCache) {
  17572. const processImage = (img) => {
  17573. const inputSrc = img.attr("src");
  17574. if (
  17575. isInternalImageSource(img) ||
  17576. isBogusImage(img) ||
  17577. isNullable(inputSrc)
  17578. ) {
  17579. return;
  17580. }
  17581. dataUriToBlobInfo(blobCache, inputSrc, true).each((blobInfo) => {
  17582. img.attr("src", blobInfo.blobUri());
  17583. });
  17584. };
  17585. parser.addAttributeFilter("src", (nodes) => each$e(nodes, processImage));
  17586. }
  17587. };
  17588. const register$4 = (parser, settings) => {
  17589. const schema = parser.schema;
  17590. if (settings.remove_trailing_brs) {
  17591. addNodeFilter(settings, parser, schema);
  17592. }
  17593. parser.addAttributeFilter("href", (nodes) => {
  17594. let i = nodes.length;
  17595. const appendRel = (rel) => {
  17596. const parts = rel.split(" ").filter((p) => p.length > 0);
  17597. return parts.concat(["noopener"]).sort().join(" ");
  17598. };
  17599. const addNoOpener = (rel) => {
  17600. const newRel = rel ? Tools.trim(rel) : "";
  17601. if (!/\b(noopener)\b/g.test(newRel)) {
  17602. return appendRel(newRel);
  17603. } else {
  17604. return newRel;
  17605. }
  17606. };
  17607. if (!settings.allow_unsafe_link_target) {
  17608. while (i--) {
  17609. const node = nodes[i];
  17610. if (node.name === "a" && node.attr("target") === "_blank") {
  17611. node.attr("rel", addNoOpener(node.attr("rel")));
  17612. }
  17613. }
  17614. }
  17615. });
  17616. if (!settings.allow_html_in_named_anchor) {
  17617. parser.addAttributeFilter("id,name", (nodes) => {
  17618. let i = nodes.length,
  17619. sibling,
  17620. prevSibling,
  17621. parent,
  17622. node;
  17623. while (i--) {
  17624. node = nodes[i];
  17625. if (node.name === "a" && node.firstChild && !node.attr("href")) {
  17626. parent = node.parent;
  17627. sibling = node.lastChild;
  17628. while (sibling && parent) {
  17629. prevSibling = sibling.prev;
  17630. parent.insert(sibling, node);
  17631. sibling = prevSibling;
  17632. }
  17633. }
  17634. }
  17635. });
  17636. }
  17637. if (settings.fix_list_elements) {
  17638. parser.addNodeFilter("ul,ol", (nodes) => {
  17639. let i = nodes.length,
  17640. node,
  17641. parentNode;
  17642. while (i--) {
  17643. node = nodes[i];
  17644. parentNode = node.parent;
  17645. if (
  17646. parentNode &&
  17647. (parentNode.name === "ul" || parentNode.name === "ol")
  17648. ) {
  17649. if (node.prev && node.prev.name === "li") {
  17650. node.prev.append(node);
  17651. } else {
  17652. const li = new AstNode("li", 1);
  17653. li.attr("style", "list-style-type: none");
  17654. node.wrap(li);
  17655. }
  17656. }
  17657. }
  17658. });
  17659. }
  17660. const validClasses = schema.getValidClasses();
  17661. if (settings.validate && validClasses) {
  17662. parser.addAttributeFilter("class", (nodes) => {
  17663. var _a;
  17664. let i = nodes.length;
  17665. while (i--) {
  17666. const node = nodes[i];
  17667. const clazz =
  17668. (_a = node.attr("class")) !== null && _a !== void 0 ? _a : "";
  17669. const classList = Tools.explode(clazz, " ");
  17670. let classValue = "";
  17671. for (let ci = 0; ci < classList.length; ci++) {
  17672. const className = classList[ci];
  17673. let valid = false;
  17674. let validClassesMap = validClasses["*"];
  17675. if (validClassesMap && validClassesMap[className]) {
  17676. valid = true;
  17677. }
  17678. validClassesMap = validClasses[node.name];
  17679. if (!valid && validClassesMap && validClassesMap[className]) {
  17680. valid = true;
  17681. }
  17682. if (valid) {
  17683. if (classValue) {
  17684. classValue += " ";
  17685. }
  17686. classValue += className;
  17687. }
  17688. }
  17689. if (!classValue.length) {
  17690. classValue = null;
  17691. }
  17692. node.attr("class", classValue);
  17693. }
  17694. });
  17695. }
  17696. registerBase64ImageFilter(parser, settings);
  17697. };
  17698. function _typeof(obj) {
  17699. "@babel/helpers - typeof";
  17700. return (
  17701. (_typeof =
  17702. "function" == typeof Symbol && "symbol" == typeof Symbol.iterator
  17703. ? function (obj) {
  17704. return typeof obj;
  17705. }
  17706. : function (obj) {
  17707. return obj &&
  17708. "function" == typeof Symbol &&
  17709. obj.constructor === Symbol &&
  17710. obj !== Symbol.prototype
  17711. ? "symbol"
  17712. : typeof obj;
  17713. }),
  17714. _typeof(obj)
  17715. );
  17716. }
  17717. function _setPrototypeOf(o, p) {
  17718. _setPrototypeOf =
  17719. Object.setPrototypeOf ||
  17720. function _setPrototypeOf(o, p) {
  17721. o.__proto__ = p;
  17722. return o;
  17723. };
  17724. return _setPrototypeOf(o, p);
  17725. }
  17726. function _isNativeReflectConstruct() {
  17727. if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  17728. if (Reflect.construct.sham) return false;
  17729. if (typeof Proxy === "function") return true;
  17730. try {
  17731. Boolean.prototype.valueOf.call(
  17732. Reflect.construct(Boolean, [], function () {})
  17733. );
  17734. return true;
  17735. } catch (e) {
  17736. return false;
  17737. }
  17738. }
  17739. function _construct(Parent, args, Class) {
  17740. if (_isNativeReflectConstruct()) {
  17741. _construct = Reflect.construct;
  17742. } else {
  17743. _construct = function _construct(Parent, args, Class) {
  17744. var a = [null];
  17745. a.push.apply(a, args);
  17746. var Constructor = Function.bind.apply(Parent, a);
  17747. var instance = new Constructor();
  17748. if (Class) _setPrototypeOf(instance, Class.prototype);
  17749. return instance;
  17750. };
  17751. }
  17752. return _construct.apply(null, arguments);
  17753. }
  17754. function _toConsumableArray(arr) {
  17755. return (
  17756. _arrayWithoutHoles(arr) ||
  17757. _iterableToArray(arr) ||
  17758. _unsupportedIterableToArray(arr) ||
  17759. _nonIterableSpread()
  17760. );
  17761. }
  17762. function _arrayWithoutHoles(arr) {
  17763. if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  17764. }
  17765. function _iterableToArray(iter) {
  17766. if (
  17767. (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null) ||
  17768. iter["@@iterator"] != null
  17769. )
  17770. return Array.from(iter);
  17771. }
  17772. function _unsupportedIterableToArray(o, minLen) {
  17773. if (!o) return;
  17774. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  17775. var n = Object.prototype.toString.call(o).slice(8, -1);
  17776. if (n === "Object" && o.constructor) n = o.constructor.name;
  17777. if (n === "Map" || n === "Set") return Array.from(o);
  17778. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
  17779. return _arrayLikeToArray(o, minLen);
  17780. }
  17781. function _arrayLikeToArray(arr, len) {
  17782. if (len == null || len > arr.length) len = arr.length;
  17783. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  17784. return arr2;
  17785. }
  17786. function _nonIterableSpread() {
  17787. throw new TypeError(
  17788. "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
  17789. );
  17790. }
  17791. var hasOwnProperty = Object.hasOwnProperty,
  17792. setPrototypeOf = Object.setPrototypeOf,
  17793. isFrozen = Object.isFrozen,
  17794. getPrototypeOf = Object.getPrototypeOf,
  17795. getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
  17796. var freeze = Object.freeze,
  17797. seal = Object.seal,
  17798. create$7 = Object.create;
  17799. var _ref = typeof Reflect !== "undefined" && Reflect,
  17800. apply = _ref.apply,
  17801. construct = _ref.construct;
  17802. if (!apply) {
  17803. apply = function apply(fun, thisValue, args) {
  17804. return fun.apply(thisValue, args);
  17805. };
  17806. }
  17807. if (!freeze) {
  17808. freeze = function freeze(x) {
  17809. return x;
  17810. };
  17811. }
  17812. if (!seal) {
  17813. seal = function seal(x) {
  17814. return x;
  17815. };
  17816. }
  17817. if (!construct) {
  17818. construct = function construct(Func, args) {
  17819. return _construct(Func, _toConsumableArray(args));
  17820. };
  17821. }
  17822. var arrayForEach = unapply(Array.prototype.forEach);
  17823. var arrayPop = unapply(Array.prototype.pop);
  17824. var arrayPush = unapply(Array.prototype.push);
  17825. var stringToLowerCase = unapply(String.prototype.toLowerCase);
  17826. var stringMatch = unapply(String.prototype.match);
  17827. var stringReplace = unapply(String.prototype.replace);
  17828. var stringIndexOf = unapply(String.prototype.indexOf);
  17829. var stringTrim = unapply(String.prototype.trim);
  17830. var regExpTest = unapply(RegExp.prototype.test);
  17831. var typeErrorCreate = unconstruct(TypeError);
  17832. function unapply(func) {
  17833. return function (thisArg) {
  17834. for (
  17835. var _len = arguments.length,
  17836. args = new Array(_len > 1 ? _len - 1 : 0),
  17837. _key = 1;
  17838. _key < _len;
  17839. _key++
  17840. ) {
  17841. args[_key - 1] = arguments[_key];
  17842. }
  17843. return apply(func, thisArg, args);
  17844. };
  17845. }
  17846. function unconstruct(func) {
  17847. return function () {
  17848. for (
  17849. var _len2 = arguments.length, args = new Array(_len2), _key2 = 0;
  17850. _key2 < _len2;
  17851. _key2++
  17852. ) {
  17853. args[_key2] = arguments[_key2];
  17854. }
  17855. return construct(func, args);
  17856. };
  17857. }
  17858. function addToSet(set, array) {
  17859. if (setPrototypeOf) {
  17860. setPrototypeOf(set, null);
  17861. }
  17862. var l = array.length;
  17863. while (l--) {
  17864. var element = array[l];
  17865. if (typeof element === "string") {
  17866. var lcElement = stringToLowerCase(element);
  17867. if (lcElement !== element) {
  17868. if (!isFrozen(array)) {
  17869. array[l] = lcElement;
  17870. }
  17871. element = lcElement;
  17872. }
  17873. }
  17874. set[element] = true;
  17875. }
  17876. return set;
  17877. }
  17878. function clone(object) {
  17879. var newObject = create$7(null);
  17880. var property;
  17881. for (property in object) {
  17882. if (apply(hasOwnProperty, object, [property])) {
  17883. newObject[property] = object[property];
  17884. }
  17885. }
  17886. return newObject;
  17887. }
  17888. function lookupGetter(object, prop) {
  17889. while (object !== null) {
  17890. var desc = getOwnPropertyDescriptor(object, prop);
  17891. if (desc) {
  17892. if (desc.get) {
  17893. return unapply(desc.get);
  17894. }
  17895. if (typeof desc.value === "function") {
  17896. return unapply(desc.value);
  17897. }
  17898. }
  17899. object = getPrototypeOf(object);
  17900. }
  17901. function fallbackValue(element) {
  17902. console.warn("fallback value for", element);
  17903. return null;
  17904. }
  17905. return fallbackValue;
  17906. }
  17907. var html$1 = freeze([
  17908. "a",
  17909. "abbr",
  17910. "acronym",
  17911. "address",
  17912. "area",
  17913. "article",
  17914. "aside",
  17915. "audio",
  17916. "b",
  17917. "bdi",
  17918. "bdo",
  17919. "big",
  17920. "blink",
  17921. "blockquote",
  17922. "body",
  17923. "br",
  17924. "button",
  17925. "canvas",
  17926. "caption",
  17927. "center",
  17928. "cite",
  17929. "code",
  17930. "col",
  17931. "colgroup",
  17932. "content",
  17933. "data",
  17934. "datalist",
  17935. "dd",
  17936. "decorator",
  17937. "del",
  17938. "details",
  17939. "dfn",
  17940. "dialog",
  17941. "dir",
  17942. "div",
  17943. "dl",
  17944. "dt",
  17945. "element",
  17946. "em",
  17947. "fieldset",
  17948. "figcaption",
  17949. "figure",
  17950. "font",
  17951. "footer",
  17952. "form",
  17953. "h1",
  17954. "h2",
  17955. "h3",
  17956. "h4",
  17957. "h5",
  17958. "h6",
  17959. "head",
  17960. "header",
  17961. "hgroup",
  17962. "hr",
  17963. "html",
  17964. "i",
  17965. "img",
  17966. "input",
  17967. "ins",
  17968. "kbd",
  17969. "label",
  17970. "legend",
  17971. "li",
  17972. "main",
  17973. "map",
  17974. "mark",
  17975. "marquee",
  17976. "menu",
  17977. "menuitem",
  17978. "meter",
  17979. "nav",
  17980. "nobr",
  17981. "ol",
  17982. "optgroup",
  17983. "option",
  17984. "output",
  17985. "p",
  17986. "picture",
  17987. "pre",
  17988. "progress",
  17989. "q",
  17990. "rp",
  17991. "rt",
  17992. "ruby",
  17993. "s",
  17994. "samp",
  17995. "section",
  17996. "select",
  17997. "shadow",
  17998. "small",
  17999. "source",
  18000. "spacer",
  18001. "span",
  18002. "strike",
  18003. "strong",
  18004. "style",
  18005. "sub",
  18006. "summary",
  18007. "sup",
  18008. "table",
  18009. "tbody",
  18010. "td",
  18011. "template",
  18012. "textarea",
  18013. "tfoot",
  18014. "th",
  18015. "thead",
  18016. "time",
  18017. "tr",
  18018. "track",
  18019. "tt",
  18020. "u",
  18021. "ul",
  18022. "var",
  18023. "video",
  18024. "wbr",
  18025. ]);
  18026. var svg$1 = freeze([
  18027. "svg",
  18028. "a",
  18029. "altglyph",
  18030. "altglyphdef",
  18031. "altglyphitem",
  18032. "animatecolor",
  18033. "animatemotion",
  18034. "animatetransform",
  18035. "circle",
  18036. "clippath",
  18037. "defs",
  18038. "desc",
  18039. "ellipse",
  18040. "filter",
  18041. "font",
  18042. "g",
  18043. "glyph",
  18044. "glyphref",
  18045. "hkern",
  18046. "image",
  18047. "line",
  18048. "lineargradient",
  18049. "marker",
  18050. "mask",
  18051. "metadata",
  18052. "mpath",
  18053. "path",
  18054. "pattern",
  18055. "polygon",
  18056. "polyline",
  18057. "radialgradient",
  18058. "rect",
  18059. "stop",
  18060. "style",
  18061. "switch",
  18062. "symbol",
  18063. "text",
  18064. "textpath",
  18065. "title",
  18066. "tref",
  18067. "tspan",
  18068. "view",
  18069. "vkern",
  18070. ]);
  18071. var svgFilters = freeze([
  18072. "feBlend",
  18073. "feColorMatrix",
  18074. "feComponentTransfer",
  18075. "feComposite",
  18076. "feConvolveMatrix",
  18077. "feDiffuseLighting",
  18078. "feDisplacementMap",
  18079. "feDistantLight",
  18080. "feFlood",
  18081. "feFuncA",
  18082. "feFuncB",
  18083. "feFuncG",
  18084. "feFuncR",
  18085. "feGaussianBlur",
  18086. "feImage",
  18087. "feMerge",
  18088. "feMergeNode",
  18089. "feMorphology",
  18090. "feOffset",
  18091. "fePointLight",
  18092. "feSpecularLighting",
  18093. "feSpotLight",
  18094. "feTile",
  18095. "feTurbulence",
  18096. ]);
  18097. var svgDisallowed = freeze([
  18098. "animate",
  18099. "color-profile",
  18100. "cursor",
  18101. "discard",
  18102. "fedropshadow",
  18103. "font-face",
  18104. "font-face-format",
  18105. "font-face-name",
  18106. "font-face-src",
  18107. "font-face-uri",
  18108. "foreignobject",
  18109. "hatch",
  18110. "hatchpath",
  18111. "mesh",
  18112. "meshgradient",
  18113. "meshpatch",
  18114. "meshrow",
  18115. "missing-glyph",
  18116. "script",
  18117. "set",
  18118. "solidcolor",
  18119. "unknown",
  18120. "use",
  18121. ]);
  18122. var mathMl$1 = freeze([
  18123. "math",
  18124. "menclose",
  18125. "merror",
  18126. "mfenced",
  18127. "mfrac",
  18128. "mglyph",
  18129. "mi",
  18130. "mlabeledtr",
  18131. "mmultiscripts",
  18132. "mn",
  18133. "mo",
  18134. "mover",
  18135. "mpadded",
  18136. "mphantom",
  18137. "mroot",
  18138. "mrow",
  18139. "ms",
  18140. "mspace",
  18141. "msqrt",
  18142. "mstyle",
  18143. "msub",
  18144. "msup",
  18145. "msubsup",
  18146. "mtable",
  18147. "mtd",
  18148. "mtext",
  18149. "mtr",
  18150. "munder",
  18151. "munderover",
  18152. ]);
  18153. var mathMlDisallowed = freeze([
  18154. "maction",
  18155. "maligngroup",
  18156. "malignmark",
  18157. "mlongdiv",
  18158. "mscarries",
  18159. "mscarry",
  18160. "msgroup",
  18161. "mstack",
  18162. "msline",
  18163. "msrow",
  18164. "semantics",
  18165. "annotation",
  18166. "annotation-xml",
  18167. "mprescripts",
  18168. "none",
  18169. ]);
  18170. var text = freeze(["#text"]);
  18171. var html = freeze([
  18172. "accept",
  18173. "action",
  18174. "align",
  18175. "alt",
  18176. "autocapitalize",
  18177. "autocomplete",
  18178. "autopictureinpicture",
  18179. "autoplay",
  18180. "background",
  18181. "bgcolor",
  18182. "border",
  18183. "capture",
  18184. "cellpadding",
  18185. "cellspacing",
  18186. "checked",
  18187. "cite",
  18188. "class",
  18189. "clear",
  18190. "color",
  18191. "cols",
  18192. "colspan",
  18193. "controls",
  18194. "controlslist",
  18195. "coords",
  18196. "crossorigin",
  18197. "datetime",
  18198. "decoding",
  18199. "default",
  18200. "dir",
  18201. "disabled",
  18202. "disablepictureinpicture",
  18203. "disableremoteplayback",
  18204. "download",
  18205. "draggable",
  18206. "enctype",
  18207. "enterkeyhint",
  18208. "face",
  18209. "for",
  18210. "headers",
  18211. "height",
  18212. "hidden",
  18213. "high",
  18214. "href",
  18215. "hreflang",
  18216. "id",
  18217. "inputmode",
  18218. "integrity",
  18219. "ismap",
  18220. "kind",
  18221. "label",
  18222. "lang",
  18223. "list",
  18224. "loading",
  18225. "loop",
  18226. "low",
  18227. "max",
  18228. "maxlength",
  18229. "media",
  18230. "method",
  18231. "min",
  18232. "minlength",
  18233. "multiple",
  18234. "muted",
  18235. "name",
  18236. "nonce",
  18237. "noshade",
  18238. "novalidate",
  18239. "nowrap",
  18240. "open",
  18241. "optimum",
  18242. "pattern",
  18243. "placeholder",
  18244. "playsinline",
  18245. "poster",
  18246. "preload",
  18247. "pubdate",
  18248. "radiogroup",
  18249. "readonly",
  18250. "rel",
  18251. "required",
  18252. "rev",
  18253. "reversed",
  18254. "role",
  18255. "rows",
  18256. "rowspan",
  18257. "spellcheck",
  18258. "scope",
  18259. "selected",
  18260. "shape",
  18261. "size",
  18262. "sizes",
  18263. "span",
  18264. "srclang",
  18265. "start",
  18266. "src",
  18267. "srcset",
  18268. "step",
  18269. "style",
  18270. "summary",
  18271. "tabindex",
  18272. "title",
  18273. "translate",
  18274. "type",
  18275. "usemap",
  18276. "valign",
  18277. "value",
  18278. "width",
  18279. "xmlns",
  18280. "slot",
  18281. ]);
  18282. var svg = freeze([
  18283. "accent-height",
  18284. "accumulate",
  18285. "additive",
  18286. "alignment-baseline",
  18287. "ascent",
  18288. "attributename",
  18289. "attributetype",
  18290. "azimuth",
  18291. "basefrequency",
  18292. "baseline-shift",
  18293. "begin",
  18294. "bias",
  18295. "by",
  18296. "class",
  18297. "clip",
  18298. "clippathunits",
  18299. "clip-path",
  18300. "clip-rule",
  18301. "color",
  18302. "color-interpolation",
  18303. "color-interpolation-filters",
  18304. "color-profile",
  18305. "color-rendering",
  18306. "cx",
  18307. "cy",
  18308. "d",
  18309. "dx",
  18310. "dy",
  18311. "diffuseconstant",
  18312. "direction",
  18313. "display",
  18314. "divisor",
  18315. "dur",
  18316. "edgemode",
  18317. "elevation",
  18318. "end",
  18319. "fill",
  18320. "fill-opacity",
  18321. "fill-rule",
  18322. "filter",
  18323. "filterunits",
  18324. "flood-color",
  18325. "flood-opacity",
  18326. "font-family",
  18327. "font-size",
  18328. "font-size-adjust",
  18329. "font-stretch",
  18330. "font-style",
  18331. "font-variant",
  18332. "font-weight",
  18333. "fx",
  18334. "fy",
  18335. "g1",
  18336. "g2",
  18337. "glyph-name",
  18338. "glyphref",
  18339. "gradientunits",
  18340. "gradienttransform",
  18341. "height",
  18342. "href",
  18343. "id",
  18344. "image-rendering",
  18345. "in",
  18346. "in2",
  18347. "k",
  18348. "k1",
  18349. "k2",
  18350. "k3",
  18351. "k4",
  18352. "kerning",
  18353. "keypoints",
  18354. "keysplines",
  18355. "keytimes",
  18356. "lang",
  18357. "lengthadjust",
  18358. "letter-spacing",
  18359. "kernelmatrix",
  18360. "kernelunitlength",
  18361. "lighting-color",
  18362. "local",
  18363. "marker-end",
  18364. "marker-mid",
  18365. "marker-start",
  18366. "markerheight",
  18367. "markerunits",
  18368. "markerwidth",
  18369. "maskcontentunits",
  18370. "maskunits",
  18371. "max",
  18372. "mask",
  18373. "media",
  18374. "method",
  18375. "mode",
  18376. "min",
  18377. "name",
  18378. "numoctaves",
  18379. "offset",
  18380. "operator",
  18381. "opacity",
  18382. "order",
  18383. "orient",
  18384. "orientation",
  18385. "origin",
  18386. "overflow",
  18387. "paint-order",
  18388. "path",
  18389. "pathlength",
  18390. "patterncontentunits",
  18391. "patterntransform",
  18392. "patternunits",
  18393. "points",
  18394. "preservealpha",
  18395. "preserveaspectratio",
  18396. "primitiveunits",
  18397. "r",
  18398. "rx",
  18399. "ry",
  18400. "radius",
  18401. "refx",
  18402. "refy",
  18403. "repeatcount",
  18404. "repeatdur",
  18405. "restart",
  18406. "result",
  18407. "rotate",
  18408. "scale",
  18409. "seed",
  18410. "shape-rendering",
  18411. "specularconstant",
  18412. "specularexponent",
  18413. "spreadmethod",
  18414. "startoffset",
  18415. "stddeviation",
  18416. "stitchtiles",
  18417. "stop-color",
  18418. "stop-opacity",
  18419. "stroke-dasharray",
  18420. "stroke-dashoffset",
  18421. "stroke-linecap",
  18422. "stroke-linejoin",
  18423. "stroke-miterlimit",
  18424. "stroke-opacity",
  18425. "stroke",
  18426. "stroke-width",
  18427. "style",
  18428. "surfacescale",
  18429. "systemlanguage",
  18430. "tabindex",
  18431. "targetx",
  18432. "targety",
  18433. "transform",
  18434. "transform-origin",
  18435. "text-anchor",
  18436. "text-decoration",
  18437. "text-rendering",
  18438. "textlength",
  18439. "type",
  18440. "u1",
  18441. "u2",
  18442. "unicode",
  18443. "values",
  18444. "viewbox",
  18445. "visibility",
  18446. "version",
  18447. "vert-adv-y",
  18448. "vert-origin-x",
  18449. "vert-origin-y",
  18450. "width",
  18451. "word-spacing",
  18452. "wrap",
  18453. "writing-mode",
  18454. "xchannelselector",
  18455. "ychannelselector",
  18456. "x",
  18457. "x1",
  18458. "x2",
  18459. "xmlns",
  18460. "y",
  18461. "y1",
  18462. "y2",
  18463. "z",
  18464. "zoomandpan",
  18465. ]);
  18466. var mathMl = freeze([
  18467. "accent",
  18468. "accentunder",
  18469. "align",
  18470. "bevelled",
  18471. "close",
  18472. "columnsalign",
  18473. "columnlines",
  18474. "columnspan",
  18475. "denomalign",
  18476. "depth",
  18477. "dir",
  18478. "display",
  18479. "displaystyle",
  18480. "encoding",
  18481. "fence",
  18482. "frame",
  18483. "height",
  18484. "href",
  18485. "id",
  18486. "largeop",
  18487. "length",
  18488. "linethickness",
  18489. "lspace",
  18490. "lquote",
  18491. "mathbackground",
  18492. "mathcolor",
  18493. "mathsize",
  18494. "mathvariant",
  18495. "maxsize",
  18496. "minsize",
  18497. "movablelimits",
  18498. "notation",
  18499. "numalign",
  18500. "open",
  18501. "rowalign",
  18502. "rowlines",
  18503. "rowspacing",
  18504. "rowspan",
  18505. "rspace",
  18506. "rquote",
  18507. "scriptlevel",
  18508. "scriptminsize",
  18509. "scriptsizemultiplier",
  18510. "selection",
  18511. "separator",
  18512. "separators",
  18513. "stretchy",
  18514. "subscriptshift",
  18515. "supscriptshift",
  18516. "symmetric",
  18517. "voffset",
  18518. "width",
  18519. "xmlns",
  18520. ]);
  18521. var xml = freeze([
  18522. "xlink:href",
  18523. "xml:id",
  18524. "xlink:title",
  18525. "xml:space",
  18526. "xmlns:xlink",
  18527. ]);
  18528. var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm);
  18529. var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
  18530. var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]/);
  18531. var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
  18532. var IS_ALLOWED_URI = seal(
  18533. /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
  18534. );
  18535. var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
  18536. var ATTR_WHITESPACE = seal(
  18537. /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
  18538. );
  18539. var DOCTYPE_NAME = seal(/^html$/i);
  18540. var getGlobal = function getGlobal() {
  18541. return typeof window === "undefined" ? null : window;
  18542. };
  18543. var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(
  18544. trustedTypes,
  18545. document
  18546. ) {
  18547. if (
  18548. _typeof(trustedTypes) !== "object" ||
  18549. typeof trustedTypes.createPolicy !== "function"
  18550. ) {
  18551. return null;
  18552. }
  18553. var suffix = null;
  18554. var ATTR_NAME = "data-tt-policy-suffix";
  18555. if (
  18556. document.currentScript &&
  18557. document.currentScript.hasAttribute(ATTR_NAME)
  18558. ) {
  18559. suffix = document.currentScript.getAttribute(ATTR_NAME);
  18560. }
  18561. var policyName = "dompurify" + (suffix ? "#" + suffix : "");
  18562. try {
  18563. return trustedTypes.createPolicy(policyName, {
  18564. createHTML: function createHTML(html) {
  18565. return html;
  18566. },
  18567. });
  18568. } catch (_) {
  18569. console.warn(
  18570. "TrustedTypes policy " + policyName + " could not be created."
  18571. );
  18572. return null;
  18573. }
  18574. };
  18575. function createDOMPurify() {
  18576. var window =
  18577. arguments.length > 0 && arguments[0] !== undefined
  18578. ? arguments[0]
  18579. : getGlobal();
  18580. var DOMPurify = function DOMPurify(root) {
  18581. return createDOMPurify(root);
  18582. };
  18583. DOMPurify.version = "2.3.8";
  18584. DOMPurify.removed = [];
  18585. if (!window || !window.document || window.document.nodeType !== 9) {
  18586. DOMPurify.isSupported = false;
  18587. return DOMPurify;
  18588. }
  18589. var originalDocument = window.document;
  18590. var document = window.document;
  18591. var DocumentFragment = window.DocumentFragment,
  18592. HTMLTemplateElement = window.HTMLTemplateElement,
  18593. Node = window.Node,
  18594. Element = window.Element,
  18595. NodeFilter = window.NodeFilter,
  18596. _window$NamedNodeMap = window.NamedNodeMap,
  18597. NamedNodeMap =
  18598. _window$NamedNodeMap === void 0
  18599. ? window.NamedNodeMap || window.MozNamedAttrMap
  18600. : _window$NamedNodeMap,
  18601. HTMLFormElement = window.HTMLFormElement,
  18602. DOMParser = window.DOMParser,
  18603. trustedTypes = window.trustedTypes;
  18604. var ElementPrototype = Element.prototype;
  18605. var cloneNode = lookupGetter(ElementPrototype, "cloneNode");
  18606. var getNextSibling = lookupGetter(ElementPrototype, "nextSibling");
  18607. var getChildNodes = lookupGetter(ElementPrototype, "childNodes");
  18608. var getParentNode = lookupGetter(ElementPrototype, "parentNode");
  18609. if (typeof HTMLTemplateElement === "function") {
  18610. var template = document.createElement("template");
  18611. if (template.content && template.content.ownerDocument) {
  18612. document = template.content.ownerDocument;
  18613. }
  18614. }
  18615. var trustedTypesPolicy = _createTrustedTypesPolicy(
  18616. trustedTypes,
  18617. originalDocument
  18618. );
  18619. var emptyHTML = trustedTypesPolicy ? trustedTypesPolicy.createHTML("") : "";
  18620. var _document = document,
  18621. implementation = _document.implementation,
  18622. createNodeIterator = _document.createNodeIterator,
  18623. createDocumentFragment = _document.createDocumentFragment,
  18624. getElementsByTagName = _document.getElementsByTagName;
  18625. var importNode = originalDocument.importNode;
  18626. var documentMode = {};
  18627. try {
  18628. documentMode = clone(document).documentMode ? document.documentMode : {};
  18629. } catch (_) {}
  18630. var hooks = {};
  18631. DOMPurify.isSupported =
  18632. typeof getParentNode === "function" &&
  18633. implementation &&
  18634. typeof implementation.createHTMLDocument !== "undefined" &&
  18635. documentMode !== 9;
  18636. var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
  18637. ERB_EXPR$1 = ERB_EXPR,
  18638. DATA_ATTR$1 = DATA_ATTR,
  18639. ARIA_ATTR$1 = ARIA_ATTR,
  18640. IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
  18641. ATTR_WHITESPACE$1 = ATTR_WHITESPACE;
  18642. var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
  18643. var ALLOWED_TAGS = null;
  18644. var DEFAULT_ALLOWED_TAGS = addToSet(
  18645. {},
  18646. [].concat(
  18647. _toConsumableArray(html$1),
  18648. _toConsumableArray(svg$1),
  18649. _toConsumableArray(svgFilters),
  18650. _toConsumableArray(mathMl$1),
  18651. _toConsumableArray(text)
  18652. )
  18653. );
  18654. var ALLOWED_ATTR = null;
  18655. var DEFAULT_ALLOWED_ATTR = addToSet(
  18656. {},
  18657. [].concat(
  18658. _toConsumableArray(html),
  18659. _toConsumableArray(svg),
  18660. _toConsumableArray(mathMl),
  18661. _toConsumableArray(xml)
  18662. )
  18663. );
  18664. var CUSTOM_ELEMENT_HANDLING = Object.seal(
  18665. Object.create(null, {
  18666. tagNameCheck: {
  18667. writable: true,
  18668. configurable: false,
  18669. enumerable: true,
  18670. value: null,
  18671. },
  18672. attributeNameCheck: {
  18673. writable: true,
  18674. configurable: false,
  18675. enumerable: true,
  18676. value: null,
  18677. },
  18678. allowCustomizedBuiltInElements: {
  18679. writable: true,
  18680. configurable: false,
  18681. enumerable: true,
  18682. value: false,
  18683. },
  18684. })
  18685. );
  18686. var FORBID_TAGS = null;
  18687. var FORBID_ATTR = null;
  18688. var ALLOW_ARIA_ATTR = true;
  18689. var ALLOW_DATA_ATTR = true;
  18690. var ALLOW_UNKNOWN_PROTOCOLS = false;
  18691. var SAFE_FOR_TEMPLATES = false;
  18692. var WHOLE_DOCUMENT = false;
  18693. var SET_CONFIG = false;
  18694. var FORCE_BODY = false;
  18695. var RETURN_DOM = false;
  18696. var RETURN_DOM_FRAGMENT = false;
  18697. var RETURN_TRUSTED_TYPE = false;
  18698. var SANITIZE_DOM = true;
  18699. var KEEP_CONTENT = true;
  18700. var IN_PLACE = false;
  18701. var USE_PROFILES = {};
  18702. var FORBID_CONTENTS = null;
  18703. var DEFAULT_FORBID_CONTENTS = addToSet({}, [
  18704. "annotation-xml",
  18705. "audio",
  18706. "colgroup",
  18707. "desc",
  18708. "foreignobject",
  18709. "head",
  18710. "iframe",
  18711. "math",
  18712. "mi",
  18713. "mn",
  18714. "mo",
  18715. "ms",
  18716. "mtext",
  18717. "noembed",
  18718. "noframes",
  18719. "noscript",
  18720. "plaintext",
  18721. "script",
  18722. "style",
  18723. "svg",
  18724. "template",
  18725. "thead",
  18726. "title",
  18727. "video",
  18728. "xmp",
  18729. ]);
  18730. var DATA_URI_TAGS = null;
  18731. var DEFAULT_DATA_URI_TAGS = addToSet({}, [
  18732. "audio",
  18733. "video",
  18734. "img",
  18735. "source",
  18736. "image",
  18737. "track",
  18738. ]);
  18739. var URI_SAFE_ATTRIBUTES = null;
  18740. var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, [
  18741. "alt",
  18742. "class",
  18743. "for",
  18744. "id",
  18745. "label",
  18746. "name",
  18747. "pattern",
  18748. "placeholder",
  18749. "role",
  18750. "summary",
  18751. "title",
  18752. "value",
  18753. "style",
  18754. "xmlns",
  18755. ]);
  18756. var MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
  18757. var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
  18758. var HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
  18759. var NAMESPACE = HTML_NAMESPACE;
  18760. var IS_EMPTY_INPUT = false;
  18761. var PARSER_MEDIA_TYPE;
  18762. var SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
  18763. var DEFAULT_PARSER_MEDIA_TYPE = "text/html";
  18764. var transformCaseFunc;
  18765. var CONFIG = null;
  18766. var formElement = document.createElement("form");
  18767. var isRegexOrFunction = function isRegexOrFunction(testValue) {
  18768. return testValue instanceof RegExp || testValue instanceof Function;
  18769. };
  18770. var _parseConfig = function _parseConfig(cfg) {
  18771. if (CONFIG && CONFIG === cfg) {
  18772. return;
  18773. }
  18774. if (!cfg || _typeof(cfg) !== "object") {
  18775. cfg = {};
  18776. }
  18777. cfg = clone(cfg);
  18778. ALLOWED_TAGS =
  18779. "ALLOWED_TAGS" in cfg
  18780. ? addToSet({}, cfg.ALLOWED_TAGS)
  18781. : DEFAULT_ALLOWED_TAGS;
  18782. ALLOWED_ATTR =
  18783. "ALLOWED_ATTR" in cfg
  18784. ? addToSet({}, cfg.ALLOWED_ATTR)
  18785. : DEFAULT_ALLOWED_ATTR;
  18786. URI_SAFE_ATTRIBUTES =
  18787. "ADD_URI_SAFE_ATTR" in cfg
  18788. ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR)
  18789. : DEFAULT_URI_SAFE_ATTRIBUTES;
  18790. DATA_URI_TAGS =
  18791. "ADD_DATA_URI_TAGS" in cfg
  18792. ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS)
  18793. : DEFAULT_DATA_URI_TAGS;
  18794. FORBID_CONTENTS =
  18795. "FORBID_CONTENTS" in cfg
  18796. ? addToSet({}, cfg.FORBID_CONTENTS)
  18797. : DEFAULT_FORBID_CONTENTS;
  18798. FORBID_TAGS = "FORBID_TAGS" in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};
  18799. FORBID_ATTR = "FORBID_ATTR" in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};
  18800. USE_PROFILES = "USE_PROFILES" in cfg ? cfg.USE_PROFILES : false;
  18801. ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
  18802. ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
  18803. ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
  18804. SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
  18805. WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
  18806. RETURN_DOM = cfg.RETURN_DOM || false;
  18807. RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
  18808. RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
  18809. FORCE_BODY = cfg.FORCE_BODY || false;
  18810. SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
  18811. KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
  18812. IN_PLACE = cfg.IN_PLACE || false;
  18813. IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
  18814. NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
  18815. if (
  18816. cfg.CUSTOM_ELEMENT_HANDLING &&
  18817. isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)
  18818. ) {
  18819. CUSTOM_ELEMENT_HANDLING.tagNameCheck =
  18820. cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
  18821. }
  18822. if (
  18823. cfg.CUSTOM_ELEMENT_HANDLING &&
  18824. isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)
  18825. ) {
  18826. CUSTOM_ELEMENT_HANDLING.attributeNameCheck =
  18827. cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;
  18828. }
  18829. if (
  18830. cfg.CUSTOM_ELEMENT_HANDLING &&
  18831. typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements ===
  18832. "boolean"
  18833. ) {
  18834. CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =
  18835. cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;
  18836. }
  18837. PARSER_MEDIA_TYPE =
  18838. SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1
  18839. ? (PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE)
  18840. : (PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE);
  18841. transformCaseFunc =
  18842. PARSER_MEDIA_TYPE === "application/xhtml+xml"
  18843. ? function (x) {
  18844. return x;
  18845. }
  18846. : stringToLowerCase;
  18847. if (SAFE_FOR_TEMPLATES) {
  18848. ALLOW_DATA_ATTR = false;
  18849. }
  18850. if (RETURN_DOM_FRAGMENT) {
  18851. RETURN_DOM = true;
  18852. }
  18853. if (USE_PROFILES) {
  18854. ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
  18855. ALLOWED_ATTR = [];
  18856. if (USE_PROFILES.html === true) {
  18857. addToSet(ALLOWED_TAGS, html$1);
  18858. addToSet(ALLOWED_ATTR, html);
  18859. }
  18860. if (USE_PROFILES.svg === true) {
  18861. addToSet(ALLOWED_TAGS, svg$1);
  18862. addToSet(ALLOWED_ATTR, svg);
  18863. addToSet(ALLOWED_ATTR, xml);
  18864. }
  18865. if (USE_PROFILES.svgFilters === true) {
  18866. addToSet(ALLOWED_TAGS, svgFilters);
  18867. addToSet(ALLOWED_ATTR, svg);
  18868. addToSet(ALLOWED_ATTR, xml);
  18869. }
  18870. if (USE_PROFILES.mathMl === true) {
  18871. addToSet(ALLOWED_TAGS, mathMl$1);
  18872. addToSet(ALLOWED_ATTR, mathMl);
  18873. addToSet(ALLOWED_ATTR, xml);
  18874. }
  18875. }
  18876. if (cfg.ADD_TAGS) {
  18877. if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
  18878. ALLOWED_TAGS = clone(ALLOWED_TAGS);
  18879. }
  18880. addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
  18881. }
  18882. if (cfg.ADD_ATTR) {
  18883. if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
  18884. ALLOWED_ATTR = clone(ALLOWED_ATTR);
  18885. }
  18886. addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
  18887. }
  18888. if (cfg.ADD_URI_SAFE_ATTR) {
  18889. addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);
  18890. }
  18891. if (cfg.FORBID_CONTENTS) {
  18892. if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
  18893. FORBID_CONTENTS = clone(FORBID_CONTENTS);
  18894. }
  18895. addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS);
  18896. }
  18897. if (KEEP_CONTENT) {
  18898. ALLOWED_TAGS["#text"] = true;
  18899. }
  18900. if (WHOLE_DOCUMENT) {
  18901. addToSet(ALLOWED_TAGS, ["html", "head", "body"]);
  18902. }
  18903. if (ALLOWED_TAGS.table) {
  18904. addToSet(ALLOWED_TAGS, ["tbody"]);
  18905. delete FORBID_TAGS.tbody;
  18906. }
  18907. if (freeze) {
  18908. freeze(cfg);
  18909. }
  18910. CONFIG = cfg;
  18911. };
  18912. var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, [
  18913. "mi",
  18914. "mo",
  18915. "mn",
  18916. "ms",
  18917. "mtext",
  18918. ]);
  18919. var HTML_INTEGRATION_POINTS = addToSet({}, [
  18920. "foreignobject",
  18921. "desc",
  18922. "title",
  18923. "annotation-xml",
  18924. ]);
  18925. var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, [
  18926. "title",
  18927. "style",
  18928. "font",
  18929. "a",
  18930. "script",
  18931. ]);
  18932. var ALL_SVG_TAGS = addToSet({}, svg$1);
  18933. addToSet(ALL_SVG_TAGS, svgFilters);
  18934. addToSet(ALL_SVG_TAGS, svgDisallowed);
  18935. var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
  18936. addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
  18937. var _checkValidNamespace = function _checkValidNamespace(element) {
  18938. var parent = getParentNode(element);
  18939. if (!parent || !parent.tagName) {
  18940. parent = {
  18941. namespaceURI: HTML_NAMESPACE,
  18942. tagName: "template",
  18943. };
  18944. }
  18945. var tagName = stringToLowerCase(element.tagName);
  18946. var parentTagName = stringToLowerCase(parent.tagName);
  18947. if (element.namespaceURI === SVG_NAMESPACE) {
  18948. if (parent.namespaceURI === HTML_NAMESPACE) {
  18949. return tagName === "svg";
  18950. }
  18951. if (parent.namespaceURI === MATHML_NAMESPACE) {
  18952. return (
  18953. tagName === "svg" &&
  18954. (parentTagName === "annotation-xml" ||
  18955. MATHML_TEXT_INTEGRATION_POINTS[parentTagName])
  18956. );
  18957. }
  18958. return Boolean(ALL_SVG_TAGS[tagName]);
  18959. }
  18960. if (element.namespaceURI === MATHML_NAMESPACE) {
  18961. if (parent.namespaceURI === HTML_NAMESPACE) {
  18962. return tagName === "math";
  18963. }
  18964. if (parent.namespaceURI === SVG_NAMESPACE) {
  18965. return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
  18966. }
  18967. return Boolean(ALL_MATHML_TAGS[tagName]);
  18968. }
  18969. if (element.namespaceURI === HTML_NAMESPACE) {
  18970. if (
  18971. parent.namespaceURI === SVG_NAMESPACE &&
  18972. !HTML_INTEGRATION_POINTS[parentTagName]
  18973. ) {
  18974. return false;
  18975. }
  18976. if (
  18977. parent.namespaceURI === MATHML_NAMESPACE &&
  18978. !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]
  18979. ) {
  18980. return false;
  18981. }
  18982. return (
  18983. !ALL_MATHML_TAGS[tagName] &&
  18984. (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName])
  18985. );
  18986. }
  18987. return false;
  18988. };
  18989. var _forceRemove = function _forceRemove(node) {
  18990. arrayPush(DOMPurify.removed, { element: node });
  18991. try {
  18992. node.parentNode.removeChild(node);
  18993. } catch (_) {
  18994. try {
  18995. node.outerHTML = emptyHTML;
  18996. } catch (_) {
  18997. node.remove();
  18998. }
  18999. }
  19000. };
  19001. var _removeAttribute = function _removeAttribute(name, node) {
  19002. try {
  19003. arrayPush(DOMPurify.removed, {
  19004. attribute: node.getAttributeNode(name),
  19005. from: node,
  19006. });
  19007. } catch (_) {
  19008. arrayPush(DOMPurify.removed, {
  19009. attribute: null,
  19010. from: node,
  19011. });
  19012. }
  19013. node.removeAttribute(name);
  19014. if (name === "is" && !ALLOWED_ATTR[name]) {
  19015. if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
  19016. try {
  19017. _forceRemove(node);
  19018. } catch (_) {}
  19019. } else {
  19020. try {
  19021. node.setAttribute(name, "");
  19022. } catch (_) {}
  19023. }
  19024. }
  19025. };
  19026. var _initDocument = function _initDocument(dirty) {
  19027. var doc;
  19028. var leadingWhitespace;
  19029. if (FORCE_BODY) {
  19030. dirty = "<remove></remove>" + dirty;
  19031. } else {
  19032. var matches = stringMatch(dirty, /^[\r\n\t ]+/);
  19033. leadingWhitespace = matches && matches[0];
  19034. }
  19035. if (PARSER_MEDIA_TYPE === "application/xhtml+xml") {
  19036. dirty =
  19037. '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' +
  19038. dirty +
  19039. "</body></html>";
  19040. }
  19041. var dirtyPayload = trustedTypesPolicy
  19042. ? trustedTypesPolicy.createHTML(dirty)
  19043. : dirty;
  19044. if (NAMESPACE === HTML_NAMESPACE) {
  19045. try {
  19046. doc = new DOMParser().parseFromString(
  19047. dirtyPayload,
  19048. PARSER_MEDIA_TYPE
  19049. );
  19050. } catch (_) {}
  19051. }
  19052. if (!doc || !doc.documentElement) {
  19053. doc = implementation.createDocument(NAMESPACE, "template", null);
  19054. try {
  19055. doc.documentElement.innerHTML = IS_EMPTY_INPUT ? "" : dirtyPayload;
  19056. } catch (_) {}
  19057. }
  19058. var body = doc.body || doc.documentElement;
  19059. if (dirty && leadingWhitespace) {
  19060. body.insertBefore(
  19061. document.createTextNode(leadingWhitespace),
  19062. body.childNodes[0] || null
  19063. );
  19064. }
  19065. if (NAMESPACE === HTML_NAMESPACE) {
  19066. return getElementsByTagName.call(
  19067. doc,
  19068. WHOLE_DOCUMENT ? "html" : "body"
  19069. )[0];
  19070. }
  19071. return WHOLE_DOCUMENT ? doc.documentElement : body;
  19072. };
  19073. var _createIterator = function _createIterator(root) {
  19074. return createNodeIterator.call(
  19075. root.ownerDocument || root,
  19076. root,
  19077. NodeFilter.SHOW_ELEMENT |
  19078. NodeFilter.SHOW_COMMENT |
  19079. NodeFilter.SHOW_TEXT,
  19080. null,
  19081. false
  19082. );
  19083. };
  19084. var _isClobbered = function _isClobbered(elm) {
  19085. return (
  19086. elm instanceof HTMLFormElement &&
  19087. (typeof elm.nodeName !== "string" ||
  19088. typeof elm.textContent !== "string" ||
  19089. typeof elm.removeChild !== "function" ||
  19090. !(elm.attributes instanceof NamedNodeMap) ||
  19091. typeof elm.removeAttribute !== "function" ||
  19092. typeof elm.setAttribute !== "function" ||
  19093. typeof elm.namespaceURI !== "string" ||
  19094. typeof elm.insertBefore !== "function")
  19095. );
  19096. };
  19097. var _isNode = function _isNode(object) {
  19098. return _typeof(Node) === "object"
  19099. ? object instanceof Node
  19100. : object &&
  19101. _typeof(object) === "object" &&
  19102. typeof object.nodeType === "number" &&
  19103. typeof object.nodeName === "string";
  19104. };
  19105. var _executeHook = function _executeHook(entryPoint, currentNode, data) {
  19106. if (!hooks[entryPoint]) {
  19107. return;
  19108. }
  19109. arrayForEach(hooks[entryPoint], function (hook) {
  19110. hook.call(DOMPurify, currentNode, data, CONFIG);
  19111. });
  19112. };
  19113. var _sanitizeElements = function _sanitizeElements(currentNode) {
  19114. var content;
  19115. _executeHook("beforeSanitizeElements", currentNode, null);
  19116. if (_isClobbered(currentNode)) {
  19117. _forceRemove(currentNode);
  19118. return true;
  19119. }
  19120. if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
  19121. _forceRemove(currentNode);
  19122. return true;
  19123. }
  19124. var tagName = transformCaseFunc(currentNode.nodeName);
  19125. _executeHook("uponSanitizeElement", currentNode, {
  19126. tagName: tagName,
  19127. allowedTags: ALLOWED_TAGS,
  19128. });
  19129. if (
  19130. currentNode.hasChildNodes() &&
  19131. !_isNode(currentNode.firstElementChild) &&
  19132. (!_isNode(currentNode.content) ||
  19133. !_isNode(currentNode.content.firstElementChild)) &&
  19134. regExpTest(/<[/\w]/g, currentNode.innerHTML) &&
  19135. regExpTest(/<[/\w]/g, currentNode.textContent)
  19136. ) {
  19137. _forceRemove(currentNode);
  19138. return true;
  19139. }
  19140. if (
  19141. tagName === "select" &&
  19142. regExpTest(/<template/i, currentNode.innerHTML)
  19143. ) {
  19144. _forceRemove(currentNode);
  19145. return true;
  19146. }
  19147. if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
  19148. if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
  19149. if (
  19150. CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp &&
  19151. regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)
  19152. )
  19153. return false;
  19154. if (
  19155. CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function &&
  19156. CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)
  19157. )
  19158. return false;
  19159. }
  19160. if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
  19161. var parentNode = getParentNode(currentNode) || currentNode.parentNode;
  19162. var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
  19163. if (childNodes && parentNode) {
  19164. var childCount = childNodes.length;
  19165. for (var i = childCount - 1; i >= 0; --i) {
  19166. parentNode.insertBefore(
  19167. cloneNode(childNodes[i], true),
  19168. getNextSibling(currentNode)
  19169. );
  19170. }
  19171. }
  19172. }
  19173. _forceRemove(currentNode);
  19174. return true;
  19175. }
  19176. if (
  19177. currentNode instanceof Element &&
  19178. !_checkValidNamespace(currentNode)
  19179. ) {
  19180. _forceRemove(currentNode);
  19181. return true;
  19182. }
  19183. if (
  19184. (tagName === "noscript" || tagName === "noembed") &&
  19185. regExpTest(/<\/no(script|embed)/i, currentNode.innerHTML)
  19186. ) {
  19187. _forceRemove(currentNode);
  19188. return true;
  19189. }
  19190. if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
  19191. content = currentNode.textContent;
  19192. content = stringReplace(content, MUSTACHE_EXPR$1, " ");
  19193. content = stringReplace(content, ERB_EXPR$1, " ");
  19194. if (currentNode.textContent !== content) {
  19195. arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });
  19196. currentNode.textContent = content;
  19197. }
  19198. }
  19199. _executeHook("afterSanitizeElements", currentNode, null);
  19200. return false;
  19201. };
  19202. var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
  19203. if (
  19204. SANITIZE_DOM &&
  19205. (lcName === "id" || lcName === "name") &&
  19206. (value in document || value in formElement)
  19207. ) {
  19208. return false;
  19209. }
  19210. if (
  19211. ALLOW_DATA_ATTR &&
  19212. !FORBID_ATTR[lcName] &&
  19213. regExpTest(DATA_ATTR$1, lcName)
  19214. );
  19215. else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
  19216. else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
  19217. if (
  19218. (_basicCustomElementTest(lcTag) &&
  19219. ((CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp &&
  19220. regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag)) ||
  19221. (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function &&
  19222. CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag))) &&
  19223. ((CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp &&
  19224. regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName)) ||
  19225. (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function &&
  19226. CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName)))) ||
  19227. (lcName === "is" &&
  19228. CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements &&
  19229. ((CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp &&
  19230. regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value)) ||
  19231. (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function &&
  19232. CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))))
  19233. );
  19234. else {
  19235. return false;
  19236. }
  19237. } else if (URI_SAFE_ATTRIBUTES[lcName]);
  19238. else if (
  19239. regExpTest(
  19240. IS_ALLOWED_URI$1,
  19241. stringReplace(value, ATTR_WHITESPACE$1, "")
  19242. )
  19243. );
  19244. else if (
  19245. (lcName === "src" || lcName === "xlink:href" || lcName === "href") &&
  19246. lcTag !== "script" &&
  19247. stringIndexOf(value, "data:") === 0 &&
  19248. DATA_URI_TAGS[lcTag]
  19249. );
  19250. else if (
  19251. ALLOW_UNKNOWN_PROTOCOLS &&
  19252. !regExpTest(
  19253. IS_SCRIPT_OR_DATA$1,
  19254. stringReplace(value, ATTR_WHITESPACE$1, "")
  19255. )
  19256. );
  19257. else if (!value);
  19258. else {
  19259. return false;
  19260. }
  19261. return true;
  19262. };
  19263. var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
  19264. return tagName.indexOf("-") > 0;
  19265. };
  19266. var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
  19267. var attr;
  19268. var value;
  19269. var lcName;
  19270. var l;
  19271. _executeHook("beforeSanitizeAttributes", currentNode, null);
  19272. var attributes = currentNode.attributes;
  19273. if (!attributes) {
  19274. return;
  19275. }
  19276. var hookEvent = {
  19277. attrName: "",
  19278. attrValue: "",
  19279. keepAttr: true,
  19280. allowedAttributes: ALLOWED_ATTR,
  19281. };
  19282. l = attributes.length;
  19283. while (l--) {
  19284. attr = attributes[l];
  19285. var _attr = attr,
  19286. name = _attr.name,
  19287. namespaceURI = _attr.namespaceURI;
  19288. value = name === "value" ? attr.value : stringTrim(attr.value);
  19289. lcName = transformCaseFunc(name);
  19290. var initValue = value;
  19291. hookEvent.attrName = lcName;
  19292. hookEvent.attrValue = value;
  19293. hookEvent.keepAttr = true;
  19294. hookEvent.forceKeepAttr = undefined;
  19295. _executeHook("uponSanitizeAttribute", currentNode, hookEvent);
  19296. value = hookEvent.attrValue;
  19297. if (hookEvent.forceKeepAttr) {
  19298. continue;
  19299. }
  19300. if (!hookEvent.keepAttr) {
  19301. _removeAttribute(name, currentNode);
  19302. continue;
  19303. }
  19304. if (regExpTest(/\/>/i, value)) {
  19305. _removeAttribute(name, currentNode);
  19306. continue;
  19307. }
  19308. if (SAFE_FOR_TEMPLATES) {
  19309. value = stringReplace(value, MUSTACHE_EXPR$1, " ");
  19310. value = stringReplace(value, ERB_EXPR$1, " ");
  19311. }
  19312. var lcTag = transformCaseFunc(currentNode.nodeName);
  19313. if (!_isValidAttribute(lcTag, lcName, value)) {
  19314. _removeAttribute(name, currentNode);
  19315. continue;
  19316. }
  19317. if (value !== initValue) {
  19318. try {
  19319. if (namespaceURI) {
  19320. currentNode.setAttributeNS(namespaceURI, name, value);
  19321. } else {
  19322. currentNode.setAttribute(name, value);
  19323. }
  19324. } catch (_) {
  19325. _removeAttribute(name, currentNode);
  19326. }
  19327. }
  19328. }
  19329. _executeHook("afterSanitizeAttributes", currentNode, null);
  19330. };
  19331. var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
  19332. var shadowNode;
  19333. var shadowIterator = _createIterator(fragment);
  19334. _executeHook("beforeSanitizeShadowDOM", fragment, null);
  19335. while ((shadowNode = shadowIterator.nextNode())) {
  19336. _executeHook("uponSanitizeShadowNode", shadowNode, null);
  19337. if (_sanitizeElements(shadowNode)) {
  19338. continue;
  19339. }
  19340. if (shadowNode.content instanceof DocumentFragment) {
  19341. _sanitizeShadowDOM(shadowNode.content);
  19342. }
  19343. _sanitizeAttributes(shadowNode);
  19344. }
  19345. _executeHook("afterSanitizeShadowDOM", fragment, null);
  19346. };
  19347. DOMPurify.sanitize = function (dirty, cfg) {
  19348. var body;
  19349. var importedNode;
  19350. var currentNode;
  19351. var oldNode;
  19352. var returnNode;
  19353. IS_EMPTY_INPUT = !dirty;
  19354. if (IS_EMPTY_INPUT) {
  19355. dirty = "<!-->";
  19356. }
  19357. if (typeof dirty !== "string" && !_isNode(dirty)) {
  19358. if (typeof dirty.toString !== "function") {
  19359. throw typeErrorCreate("toString is not a function");
  19360. } else {
  19361. dirty = dirty.toString();
  19362. if (typeof dirty !== "string") {
  19363. throw typeErrorCreate("dirty is not a string, aborting");
  19364. }
  19365. }
  19366. }
  19367. if (!DOMPurify.isSupported) {
  19368. if (
  19369. _typeof(window.toStaticHTML) === "object" ||
  19370. typeof window.toStaticHTML === "function"
  19371. ) {
  19372. if (typeof dirty === "string") {
  19373. return window.toStaticHTML(dirty);
  19374. }
  19375. if (_isNode(dirty)) {
  19376. return window.toStaticHTML(dirty.outerHTML);
  19377. }
  19378. }
  19379. return dirty;
  19380. }
  19381. if (!SET_CONFIG) {
  19382. _parseConfig(cfg);
  19383. }
  19384. DOMPurify.removed = [];
  19385. if (typeof dirty === "string") {
  19386. IN_PLACE = false;
  19387. }
  19388. if (IN_PLACE) {
  19389. if (dirty.nodeName) {
  19390. var tagName = transformCaseFunc(dirty.nodeName);
  19391. if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
  19392. throw typeErrorCreate(
  19393. "root node is forbidden and cannot be sanitized in-place"
  19394. );
  19395. }
  19396. }
  19397. } else if (dirty instanceof Node) {
  19398. body = _initDocument("<!---->");
  19399. importedNode = body.ownerDocument.importNode(dirty, true);
  19400. if (importedNode.nodeType === 1 && importedNode.nodeName === "BODY") {
  19401. body = importedNode;
  19402. } else if (importedNode.nodeName === "HTML") {
  19403. body = importedNode;
  19404. } else {
  19405. body.appendChild(importedNode);
  19406. }
  19407. } else {
  19408. if (
  19409. !RETURN_DOM &&
  19410. !SAFE_FOR_TEMPLATES &&
  19411. !WHOLE_DOCUMENT &&
  19412. dirty.indexOf("<") === -1
  19413. ) {
  19414. return trustedTypesPolicy && RETURN_TRUSTED_TYPE
  19415. ? trustedTypesPolicy.createHTML(dirty)
  19416. : dirty;
  19417. }
  19418. body = _initDocument(dirty);
  19419. if (!body) {
  19420. return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : "";
  19421. }
  19422. }
  19423. if (body && FORCE_BODY) {
  19424. _forceRemove(body.firstChild);
  19425. }
  19426. var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
  19427. while ((currentNode = nodeIterator.nextNode())) {
  19428. if (currentNode.nodeType === 3 && currentNode === oldNode) {
  19429. continue;
  19430. }
  19431. if (_sanitizeElements(currentNode)) {
  19432. continue;
  19433. }
  19434. if (currentNode.content instanceof DocumentFragment) {
  19435. _sanitizeShadowDOM(currentNode.content);
  19436. }
  19437. _sanitizeAttributes(currentNode);
  19438. oldNode = currentNode;
  19439. }
  19440. oldNode = null;
  19441. if (IN_PLACE) {
  19442. return dirty;
  19443. }
  19444. if (RETURN_DOM) {
  19445. if (RETURN_DOM_FRAGMENT) {
  19446. returnNode = createDocumentFragment.call(body.ownerDocument);
  19447. while (body.firstChild) {
  19448. returnNode.appendChild(body.firstChild);
  19449. }
  19450. } else {
  19451. returnNode = body;
  19452. }
  19453. if (ALLOWED_ATTR.shadowroot) {
  19454. returnNode = importNode.call(originalDocument, returnNode, true);
  19455. }
  19456. return returnNode;
  19457. }
  19458. var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
  19459. if (
  19460. WHOLE_DOCUMENT &&
  19461. ALLOWED_TAGS["!doctype"] &&
  19462. body.ownerDocument &&
  19463. body.ownerDocument.doctype &&
  19464. body.ownerDocument.doctype.name &&
  19465. regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)
  19466. ) {
  19467. serializedHTML =
  19468. "<!DOCTYPE " +
  19469. body.ownerDocument.doctype.name +
  19470. ">\n" +
  19471. serializedHTML;
  19472. }
  19473. if (SAFE_FOR_TEMPLATES) {
  19474. serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, " ");
  19475. serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, " ");
  19476. }
  19477. return trustedTypesPolicy && RETURN_TRUSTED_TYPE
  19478. ? trustedTypesPolicy.createHTML(serializedHTML)
  19479. : serializedHTML;
  19480. };
  19481. DOMPurify.setConfig = function (cfg) {
  19482. _parseConfig(cfg);
  19483. SET_CONFIG = true;
  19484. };
  19485. DOMPurify.clearConfig = function () {
  19486. CONFIG = null;
  19487. SET_CONFIG = false;
  19488. };
  19489. DOMPurify.isValidAttribute = function (tag, attr, value) {
  19490. if (!CONFIG) {
  19491. _parseConfig({});
  19492. }
  19493. var lcTag = transformCaseFunc(tag);
  19494. var lcName = transformCaseFunc(attr);
  19495. return _isValidAttribute(lcTag, lcName, value);
  19496. };
  19497. DOMPurify.addHook = function (entryPoint, hookFunction) {
  19498. if (typeof hookFunction !== "function") {
  19499. return;
  19500. }
  19501. hooks[entryPoint] = hooks[entryPoint] || [];
  19502. arrayPush(hooks[entryPoint], hookFunction);
  19503. };
  19504. DOMPurify.removeHook = function (entryPoint) {
  19505. if (hooks[entryPoint]) {
  19506. return arrayPop(hooks[entryPoint]);
  19507. }
  19508. };
  19509. DOMPurify.removeHooks = function (entryPoint) {
  19510. if (hooks[entryPoint]) {
  19511. hooks[entryPoint] = [];
  19512. }
  19513. };
  19514. DOMPurify.removeAllHooks = function () {
  19515. hooks = {};
  19516. };
  19517. return DOMPurify;
  19518. }
  19519. var purify = createDOMPurify();
  19520. const each$4 = Tools.each,
  19521. trim = Tools.trim;
  19522. const queryParts = [
  19523. "source",
  19524. "protocol",
  19525. "authority",
  19526. "userInfo",
  19527. "user",
  19528. "password",
  19529. "host",
  19530. "port",
  19531. "relative",
  19532. "path",
  19533. "directory",
  19534. "file",
  19535. "query",
  19536. "anchor",
  19537. ];
  19538. const DEFAULT_PORTS = {
  19539. ftp: 21,
  19540. http: 80,
  19541. https: 443,
  19542. mailto: 25,
  19543. };
  19544. const safeSvgDataUrlElements = ["img", "video"];
  19545. const blockSvgDataUris = (allowSvgDataUrls, tagName) => {
  19546. if (isNonNullable(allowSvgDataUrls)) {
  19547. return !allowSvgDataUrls;
  19548. } else {
  19549. return isNonNullable(tagName)
  19550. ? !contains$2(safeSvgDataUrlElements, tagName)
  19551. : true;
  19552. }
  19553. };
  19554. const decodeUri = (encodedUri) => {
  19555. try {
  19556. return decodeURIComponent(encodedUri);
  19557. } catch (ex) {
  19558. return unescape(encodedUri);
  19559. }
  19560. };
  19561. const isInvalidUri = (settings, uri, tagName) => {
  19562. const decodedUri = decodeUri(uri).replace(/\s/g, "");
  19563. if (settings.allow_script_urls) {
  19564. return false;
  19565. } else if (/((java|vb)script|mhtml):/i.test(decodedUri)) {
  19566. return true;
  19567. } else if (settings.allow_html_data_urls) {
  19568. return false;
  19569. } else if (/^data:image\//i.test(decodedUri)) {
  19570. return (
  19571. blockSvgDataUris(settings.allow_svg_data_urls, tagName) &&
  19572. /^data:image\/svg\+xml/i.test(decodedUri)
  19573. );
  19574. } else {
  19575. return /^data:/i.test(decodedUri);
  19576. }
  19577. };
  19578. class URI {
  19579. static parseDataUri(uri) {
  19580. let type;
  19581. const uriComponents = decodeURIComponent(uri).split(",");
  19582. const matches = /data:([^;]+)/.exec(uriComponents[0]);
  19583. if (matches) {
  19584. type = matches[1];
  19585. }
  19586. return {
  19587. type,
  19588. data: uriComponents[1],
  19589. };
  19590. }
  19591. static isDomSafe(uri, context, options = {}) {
  19592. if (options.allow_script_urls) {
  19593. return true;
  19594. } else {
  19595. const decodedUri = Entities.decode(uri).replace(
  19596. /[\s\u0000-\u001F]+/g,
  19597. ""
  19598. );
  19599. return !isInvalidUri(options, decodedUri, context);
  19600. }
  19601. }
  19602. static getDocumentBaseUrl(loc) {
  19603. var _a;
  19604. let baseUrl;
  19605. if (loc.protocol.indexOf("http") !== 0 && loc.protocol !== "file:") {
  19606. baseUrl = (_a = loc.href) !== null && _a !== void 0 ? _a : "";
  19607. } else {
  19608. baseUrl = loc.protocol + "//" + loc.host + loc.pathname;
  19609. }
  19610. if (/^[^:]+:\/\/\/?[^\/]+\//.test(baseUrl)) {
  19611. baseUrl = baseUrl.replace(/[\?#].*$/, "").replace(/[\/\\][^\/]+$/, "");
  19612. if (!/[\/\\]$/.test(baseUrl)) {
  19613. baseUrl += "/";
  19614. }
  19615. }
  19616. return baseUrl;
  19617. }
  19618. constructor(url, settings = {}) {
  19619. this.path = "";
  19620. this.directory = "";
  19621. url = trim(url);
  19622. this.settings = settings;
  19623. const baseUri = settings.base_uri;
  19624. const self = this;
  19625. if (/^([\w\-]+):([^\/]{2})/i.test(url) || /^\s*#/.test(url)) {
  19626. self.source = url;
  19627. return;
  19628. }
  19629. const isProtocolRelative = url.indexOf("//") === 0;
  19630. if (url.indexOf("/") === 0 && !isProtocolRelative) {
  19631. url =
  19632. (baseUri ? baseUri.protocol || "http" : "http") + "://mce_host" + url;
  19633. }
  19634. if (!/^[\w\-]*:?\/\//.test(url)) {
  19635. const baseUrl = baseUri
  19636. ? baseUri.path
  19637. : new URI(document.location.href).directory;
  19638. if (
  19639. (baseUri === null || baseUri === void 0
  19640. ? void 0
  19641. : baseUri.protocol) === ""
  19642. ) {
  19643. url = "//mce_host" + self.toAbsPath(baseUrl, url);
  19644. } else {
  19645. const match = /([^#?]*)([#?]?.*)/.exec(url);
  19646. if (match) {
  19647. url =
  19648. ((baseUri && baseUri.protocol) || "http") +
  19649. "://mce_host" +
  19650. self.toAbsPath(baseUrl, match[1]) +
  19651. match[2];
  19652. }
  19653. }
  19654. }
  19655. url = url.replace(/@@/g, "(mce_at)");
  19656. const urlMatch =
  19657. /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@\/]*):?([^:@\/]*))?@)?(\[[a-zA-Z0-9:.%]+\]|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(
  19658. url
  19659. );
  19660. if (urlMatch) {
  19661. each$4(queryParts, (v, i) => {
  19662. let part = urlMatch[i];
  19663. if (part) {
  19664. part = part.replace(/\(mce_at\)/g, "@@");
  19665. }
  19666. self[v] = part;
  19667. });
  19668. }
  19669. if (baseUri) {
  19670. if (!self.protocol) {
  19671. self.protocol = baseUri.protocol;
  19672. }
  19673. if (!self.userInfo) {
  19674. self.userInfo = baseUri.userInfo;
  19675. }
  19676. if (!self.port && self.host === "mce_host") {
  19677. self.port = baseUri.port;
  19678. }
  19679. if (!self.host || self.host === "mce_host") {
  19680. self.host = baseUri.host;
  19681. }
  19682. self.source = "";
  19683. }
  19684. if (isProtocolRelative) {
  19685. self.protocol = "";
  19686. }
  19687. }
  19688. setPath(path) {
  19689. const pathMatch = /^(.*?)\/?(\w+)?$/.exec(path);
  19690. if (pathMatch) {
  19691. this.path = pathMatch[0];
  19692. this.directory = pathMatch[1];
  19693. this.file = pathMatch[2];
  19694. }
  19695. this.source = "";
  19696. this.getURI();
  19697. }
  19698. toRelative(uri) {
  19699. if (uri === "./") {
  19700. return uri;
  19701. }
  19702. const relativeUri = new URI(uri, { base_uri: this });
  19703. if (
  19704. (relativeUri.host !== "mce_host" &&
  19705. this.host !== relativeUri.host &&
  19706. relativeUri.host) ||
  19707. this.port !== relativeUri.port ||
  19708. (this.protocol !== relativeUri.protocol && relativeUri.protocol !== "")
  19709. ) {
  19710. return relativeUri.getURI();
  19711. }
  19712. const tu = this.getURI(),
  19713. uu = relativeUri.getURI();
  19714. if (
  19715. tu === uu ||
  19716. (tu.charAt(tu.length - 1) === "/" && tu.substr(0, tu.length - 1) === uu)
  19717. ) {
  19718. return tu;
  19719. }
  19720. let output = this.toRelPath(this.path, relativeUri.path);
  19721. if (relativeUri.query) {
  19722. output += "?" + relativeUri.query;
  19723. }
  19724. if (relativeUri.anchor) {
  19725. output += "#" + relativeUri.anchor;
  19726. }
  19727. return output;
  19728. }
  19729. toAbsolute(uri, noHost) {
  19730. const absoluteUri = new URI(uri, { base_uri: this });
  19731. return absoluteUri.getURI(noHost && this.isSameOrigin(absoluteUri));
  19732. }
  19733. isSameOrigin(uri) {
  19734. if (this.host == uri.host && this.protocol == uri.protocol) {
  19735. if (this.port == uri.port) {
  19736. return true;
  19737. }
  19738. const defaultPort = this.protocol ? DEFAULT_PORTS[this.protocol] : null;
  19739. if (
  19740. defaultPort &&
  19741. (this.port || defaultPort) == (uri.port || defaultPort)
  19742. ) {
  19743. return true;
  19744. }
  19745. }
  19746. return false;
  19747. }
  19748. toRelPath(base, path) {
  19749. let breakPoint = 0,
  19750. out = "",
  19751. i,
  19752. l;
  19753. const normalizedBase = base
  19754. .substring(0, base.lastIndexOf("/"))
  19755. .split("/");
  19756. const items = path.split("/");
  19757. if (normalizedBase.length >= items.length) {
  19758. for (i = 0, l = normalizedBase.length; i < l; i++) {
  19759. if (i >= items.length || normalizedBase[i] !== items[i]) {
  19760. breakPoint = i + 1;
  19761. break;
  19762. }
  19763. }
  19764. }
  19765. if (normalizedBase.length < items.length) {
  19766. for (i = 0, l = items.length; i < l; i++) {
  19767. if (i >= normalizedBase.length || normalizedBase[i] !== items[i]) {
  19768. breakPoint = i + 1;
  19769. break;
  19770. }
  19771. }
  19772. }
  19773. if (breakPoint === 1) {
  19774. return path;
  19775. }
  19776. for (i = 0, l = normalizedBase.length - (breakPoint - 1); i < l; i++) {
  19777. out += "../";
  19778. }
  19779. for (i = breakPoint - 1, l = items.length; i < l; i++) {
  19780. if (i !== breakPoint - 1) {
  19781. out += "/" + items[i];
  19782. } else {
  19783. out += items[i];
  19784. }
  19785. }
  19786. return out;
  19787. }
  19788. toAbsPath(base, path) {
  19789. let nb = 0;
  19790. const tr = /\/$/.test(path) ? "/" : "";
  19791. const normalizedBase = base.split("/");
  19792. const normalizedPath = path.split("/");
  19793. const baseParts = [];
  19794. each$4(normalizedBase, (k) => {
  19795. if (k) {
  19796. baseParts.push(k);
  19797. }
  19798. });
  19799. const pathParts = [];
  19800. for (let i = normalizedPath.length - 1; i >= 0; i--) {
  19801. if (normalizedPath[i].length === 0 || normalizedPath[i] === ".") {
  19802. continue;
  19803. }
  19804. if (normalizedPath[i] === "..") {
  19805. nb++;
  19806. continue;
  19807. }
  19808. if (nb > 0) {
  19809. nb--;
  19810. continue;
  19811. }
  19812. pathParts.push(normalizedPath[i]);
  19813. }
  19814. const i = baseParts.length - nb;
  19815. let outPath;
  19816. if (i <= 0) {
  19817. outPath = reverse(pathParts).join("/");
  19818. } else {
  19819. outPath =
  19820. baseParts.slice(0, i).join("/") + "/" + reverse(pathParts).join("/");
  19821. }
  19822. if (outPath.indexOf("/") !== 0) {
  19823. outPath = "/" + outPath;
  19824. }
  19825. if (tr && outPath.lastIndexOf("/") !== outPath.length - 1) {
  19826. outPath += tr;
  19827. }
  19828. return outPath;
  19829. }
  19830. getURI(noProtoHost = false) {
  19831. let s;
  19832. if (!this.source || noProtoHost) {
  19833. s = "";
  19834. if (!noProtoHost) {
  19835. if (this.protocol) {
  19836. s += this.protocol + "://";
  19837. } else {
  19838. s += "//";
  19839. }
  19840. if (this.userInfo) {
  19841. s += this.userInfo + "@";
  19842. }
  19843. if (this.host) {
  19844. s += this.host;
  19845. }
  19846. if (this.port) {
  19847. s += ":" + this.port;
  19848. }
  19849. }
  19850. if (this.path) {
  19851. s += this.path;
  19852. }
  19853. if (this.query) {
  19854. s += "?" + this.query;
  19855. }
  19856. if (this.anchor) {
  19857. s += "#" + this.anchor;
  19858. }
  19859. this.source = s;
  19860. }
  19861. return this.source;
  19862. }
  19863. }
  19864. const filteredUrlAttrs = Tools.makeMap(
  19865. "src,href,data,background,action,formaction,poster,xlink:href"
  19866. );
  19867. const internalElementAttr = "data-mce-type";
  19868. let uid = 0;
  19869. const processNode = (node, settings, schema, evt) => {
  19870. var _a, _b, _c, _d;
  19871. const validate = settings.validate;
  19872. const specialElements = schema.getSpecialElements();
  19873. if (
  19874. node.nodeType === COMMENT &&
  19875. !settings.allow_conditional_comments &&
  19876. /^\[if/i.test((_a = node.nodeValue) !== null && _a !== void 0 ? _a : "")
  19877. ) {
  19878. node.nodeValue = " " + node.nodeValue;
  19879. }
  19880. const lcTagName =
  19881. (_b = evt === null || evt === void 0 ? void 0 : evt.tagName) !== null &&
  19882. _b !== void 0
  19883. ? _b
  19884. : node.nodeName.toLowerCase();
  19885. if (node.nodeType !== ELEMENT || lcTagName === "body") {
  19886. return;
  19887. }
  19888. const element = SugarElement.fromDom(node);
  19889. const isInternalElement = has$1(element, internalElementAttr);
  19890. const bogus = get$9(element, "data-mce-bogus");
  19891. if (!isInternalElement && isString(bogus)) {
  19892. if (bogus === "all") {
  19893. remove$5(element);
  19894. } else {
  19895. unwrap(element);
  19896. }
  19897. return;
  19898. }
  19899. const rule = schema.getElementRule(lcTagName);
  19900. if (validate && !rule) {
  19901. if (has$2(specialElements, lcTagName)) {
  19902. remove$5(element);
  19903. } else {
  19904. unwrap(element);
  19905. }
  19906. return;
  19907. } else {
  19908. if (isNonNullable(evt)) {
  19909. evt.allowedTags[lcTagName] = true;
  19910. }
  19911. }
  19912. if (validate && rule && !isInternalElement) {
  19913. each$e(
  19914. (_c = rule.attributesForced) !== null && _c !== void 0 ? _c : [],
  19915. (attr) => {
  19916. set$3(
  19917. element,
  19918. attr.name,
  19919. attr.value === "{$uid}" ? `mce_${uid++}` : attr.value
  19920. );
  19921. }
  19922. );
  19923. each$e(
  19924. (_d = rule.attributesDefault) !== null && _d !== void 0 ? _d : [],
  19925. (attr) => {
  19926. if (!has$1(element, attr.name)) {
  19927. set$3(
  19928. element,
  19929. attr.name,
  19930. attr.value === "{$uid}" ? `mce_${uid++}` : attr.value
  19931. );
  19932. }
  19933. }
  19934. );
  19935. if (
  19936. rule.attributesRequired &&
  19937. !exists(rule.attributesRequired, (attr) => has$1(element, attr))
  19938. ) {
  19939. unwrap(element);
  19940. return;
  19941. }
  19942. if (rule.removeEmptyAttrs && hasNone(element)) {
  19943. unwrap(element);
  19944. return;
  19945. }
  19946. if (rule.outputName && rule.outputName !== lcTagName) {
  19947. mutate(element, rule.outputName);
  19948. }
  19949. }
  19950. };
  19951. const shouldKeepAttribute = (
  19952. settings,
  19953. schema,
  19954. tagName,
  19955. attrName,
  19956. attrValue
  19957. ) =>
  19958. !(
  19959. attrName in filteredUrlAttrs && isInvalidUri(settings, attrValue, tagName)
  19960. ) &&
  19961. (!settings.validate ||
  19962. schema.isValid(tagName, attrName) ||
  19963. startsWith(attrName, "data-") ||
  19964. startsWith(attrName, "aria-"));
  19965. const isRequiredAttributeOfInternalElement = (ele, attrName) =>
  19966. ele.hasAttribute(internalElementAttr) &&
  19967. (attrName === "id" || attrName === "class" || attrName === "style");
  19968. const isBooleanAttribute = (attrName, schema) =>
  19969. attrName in schema.getBoolAttrs();
  19970. const filterAttributes = (ele, settings, schema) => {
  19971. const { attributes } = ele;
  19972. for (let i = attributes.length - 1; i >= 0; i--) {
  19973. const attr = attributes[i];
  19974. const attrName = attr.name;
  19975. const attrValue = attr.value;
  19976. if (
  19977. !shouldKeepAttribute(
  19978. settings,
  19979. schema,
  19980. ele.tagName.toLowerCase(),
  19981. attrName,
  19982. attrValue
  19983. ) &&
  19984. !isRequiredAttributeOfInternalElement(ele, attrName)
  19985. ) {
  19986. ele.removeAttribute(attrName);
  19987. } else if (isBooleanAttribute(attrName, schema)) {
  19988. ele.setAttribute(attrName, attrName);
  19989. }
  19990. }
  19991. };
  19992. const setupPurify = (settings, schema) => {
  19993. const purify$1 = purify();
  19994. purify$1.addHook("uponSanitizeElement", (ele, evt) => {
  19995. processNode(ele, settings, schema, evt);
  19996. });
  19997. purify$1.addHook("uponSanitizeAttribute", (ele, evt) => {
  19998. const tagName = ele.tagName.toLowerCase();
  19999. const { attrName, attrValue } = evt;
  20000. evt.keepAttr = shouldKeepAttribute(
  20001. settings,
  20002. schema,
  20003. tagName,
  20004. attrName,
  20005. attrValue
  20006. );
  20007. if (evt.keepAttr) {
  20008. evt.allowedAttributes[attrName] = true;
  20009. if (isBooleanAttribute(attrName, schema)) {
  20010. evt.attrValue = attrName;
  20011. }
  20012. if (
  20013. settings.allow_svg_data_urls &&
  20014. startsWith(attrValue, "data:image/svg+xml")
  20015. ) {
  20016. evt.forceKeepAttr = true;
  20017. }
  20018. } else if (isRequiredAttributeOfInternalElement(ele, attrName)) {
  20019. evt.forceKeepAttr = true;
  20020. }
  20021. });
  20022. return purify$1;
  20023. };
  20024. const getPurifyConfig = (settings, mimeType) => {
  20025. const basePurifyConfig = {
  20026. IN_PLACE: true,
  20027. ALLOW_UNKNOWN_PROTOCOLS: true,
  20028. ALLOWED_TAGS: ["#comment", "#cdata-section", "body"],
  20029. ALLOWED_ATTR: [],
  20030. };
  20031. const config = { ...basePurifyConfig };
  20032. config.PARSER_MEDIA_TYPE = mimeType;
  20033. if (settings.allow_script_urls) {
  20034. config.ALLOWED_URI_REGEXP = /.*/;
  20035. } else if (settings.allow_html_data_urls) {
  20036. config.ALLOWED_URI_REGEXP = /^(?!(\w+script|mhtml):)/i;
  20037. }
  20038. return config;
  20039. };
  20040. const getSanitizer = (settings, schema) => {
  20041. if (settings.sanitize) {
  20042. const purify = setupPurify(settings, schema);
  20043. return (body, mimeType) => {
  20044. purify.sanitize(body, getPurifyConfig(settings, mimeType));
  20045. purify.removed = [];
  20046. };
  20047. } else {
  20048. return (body, _) => {
  20049. const nodeIterator = document.createNodeIterator(
  20050. body,
  20051. NodeFilter.SHOW_ELEMENT |
  20052. NodeFilter.SHOW_COMMENT |
  20053. NodeFilter.SHOW_TEXT
  20054. );
  20055. let node;
  20056. while ((node = nodeIterator.nextNode())) {
  20057. processNode(node, settings, schema);
  20058. if (isElement$6(node)) {
  20059. filterAttributes(node, settings, schema);
  20060. }
  20061. }
  20062. };
  20063. }
  20064. };
  20065. const makeMap = Tools.makeMap,
  20066. extend$1 = Tools.extend;
  20067. const transferChildren = (parent, nativeParent, specialElements) => {
  20068. const parentName = parent.name;
  20069. const isSpecial =
  20070. parentName in specialElements &&
  20071. parentName !== "title" &&
  20072. parentName !== "textarea";
  20073. const childNodes = nativeParent.childNodes;
  20074. for (let ni = 0, nl = childNodes.length; ni < nl; ni++) {
  20075. const nativeChild = childNodes[ni];
  20076. const child = new AstNode(
  20077. nativeChild.nodeName.toLowerCase(),
  20078. nativeChild.nodeType
  20079. );
  20080. if (isElement$6(nativeChild)) {
  20081. const attributes = nativeChild.attributes;
  20082. for (let ai = 0, al = attributes.length; ai < al; ai++) {
  20083. const attr = attributes[ai];
  20084. child.attr(attr.name, attr.value);
  20085. }
  20086. } else if (isText$a(nativeChild)) {
  20087. child.value = nativeChild.data;
  20088. if (isSpecial) {
  20089. child.raw = true;
  20090. }
  20091. } else if (
  20092. isComment(nativeChild) ||
  20093. isCData(nativeChild) ||
  20094. isPi(nativeChild)
  20095. ) {
  20096. child.value = nativeChild.data;
  20097. }
  20098. transferChildren(child, nativeChild, specialElements);
  20099. parent.append(child);
  20100. }
  20101. };
  20102. const walkTree = (root, preprocessors, postprocessors) => {
  20103. const traverseOrder = [];
  20104. for (
  20105. let node = root, lastNode = node;
  20106. node;
  20107. lastNode = node, node = node.walk()
  20108. ) {
  20109. const tempNode = node;
  20110. each$e(preprocessors, (preprocess) => preprocess(tempNode));
  20111. if (isNullable(tempNode.parent) && tempNode !== root) {
  20112. node = lastNode;
  20113. } else {
  20114. traverseOrder.push(tempNode);
  20115. }
  20116. }
  20117. for (let i = traverseOrder.length - 1; i >= 0; i--) {
  20118. const node = traverseOrder[i];
  20119. each$e(postprocessors, (postprocess) => postprocess(node));
  20120. }
  20121. };
  20122. const whitespaceCleaner = (root, schema, settings, args) => {
  20123. const validate = settings.validate;
  20124. const nonEmptyElements = schema.getNonEmptyElements();
  20125. const whitespaceElements = schema.getWhitespaceElements();
  20126. const blockElements = extend$1(
  20127. makeMap("script,style,head,html,body,title,meta,param"),
  20128. schema.getBlockElements()
  20129. );
  20130. const textRootBlockElements = getTextRootBlockElements(schema);
  20131. const allWhiteSpaceRegExp = /[ \t\r\n]+/g;
  20132. const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
  20133. const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
  20134. const hasWhitespaceParent = (node) => {
  20135. let tempNode = node.parent;
  20136. while (isNonNullable(tempNode)) {
  20137. if (tempNode.name in whitespaceElements) {
  20138. return true;
  20139. } else {
  20140. tempNode = tempNode.parent;
  20141. }
  20142. }
  20143. return false;
  20144. };
  20145. const isTextRootBlockEmpty = (node) => {
  20146. let tempNode = node;
  20147. while (isNonNullable(tempNode)) {
  20148. if (tempNode.name in textRootBlockElements) {
  20149. return isEmpty(
  20150. schema,
  20151. nonEmptyElements,
  20152. whitespaceElements,
  20153. tempNode
  20154. );
  20155. } else {
  20156. tempNode = tempNode.parent;
  20157. }
  20158. }
  20159. return false;
  20160. };
  20161. const isBlock = (node) =>
  20162. node.name in blockElements || isTransparentAstBlock(schema, node);
  20163. const isAtEdgeOfBlock = (node, start) => {
  20164. const neighbour = start ? node.prev : node.next;
  20165. if (isNonNullable(neighbour) || isNullable(node.parent)) {
  20166. return false;
  20167. }
  20168. return (
  20169. isBlock(node.parent) &&
  20170. (node.parent !== root || args.isRootContent === true)
  20171. );
  20172. };
  20173. const preprocess = (node) => {
  20174. var _a;
  20175. if (node.type === 3) {
  20176. if (!hasWhitespaceParent(node)) {
  20177. let text = (_a = node.value) !== null && _a !== void 0 ? _a : "";
  20178. text = text.replace(allWhiteSpaceRegExp, " ");
  20179. if (
  20180. isLineBreakNode(node.prev, isBlock) ||
  20181. isAtEdgeOfBlock(node, true)
  20182. ) {
  20183. text = text.replace(startWhiteSpaceRegExp, "");
  20184. }
  20185. if (text.length === 0) {
  20186. node.remove();
  20187. } else {
  20188. node.value = text;
  20189. }
  20190. }
  20191. }
  20192. };
  20193. const postprocess = (node) => {
  20194. var _a;
  20195. if (node.type === 1) {
  20196. const elementRule = schema.getElementRule(node.name);
  20197. if (validate && elementRule) {
  20198. const isNodeEmpty = isEmpty(
  20199. schema,
  20200. nonEmptyElements,
  20201. whitespaceElements,
  20202. node
  20203. );
  20204. if (
  20205. elementRule.paddInEmptyBlock &&
  20206. isNodeEmpty &&
  20207. isTextRootBlockEmpty(node)
  20208. ) {
  20209. paddEmptyNode(settings, args, isBlock, node);
  20210. } else if (elementRule.removeEmpty && isNodeEmpty) {
  20211. if (isBlock(node)) {
  20212. node.remove();
  20213. } else {
  20214. node.unwrap();
  20215. }
  20216. } else if (
  20217. elementRule.paddEmpty &&
  20218. (isNodeEmpty || isPaddedWithNbsp(node))
  20219. ) {
  20220. paddEmptyNode(settings, args, isBlock, node);
  20221. }
  20222. }
  20223. } else if (node.type === 3) {
  20224. if (!hasWhitespaceParent(node)) {
  20225. let text = (_a = node.value) !== null && _a !== void 0 ? _a : "";
  20226. if (
  20227. (node.next && isBlock(node.next)) ||
  20228. isAtEdgeOfBlock(node, false)
  20229. ) {
  20230. text = text.replace(endWhiteSpaceRegExp, "");
  20231. }
  20232. if (text.length === 0) {
  20233. node.remove();
  20234. } else {
  20235. node.value = text;
  20236. }
  20237. }
  20238. }
  20239. };
  20240. return [preprocess, postprocess];
  20241. };
  20242. const getRootBlockName = (settings, args) => {
  20243. var _a;
  20244. const name =
  20245. (_a = args.forced_root_block) !== null && _a !== void 0
  20246. ? _a
  20247. : settings.forced_root_block;
  20248. if (name === false) {
  20249. return "";
  20250. } else if (name === true) {
  20251. return "p";
  20252. } else {
  20253. return name;
  20254. }
  20255. };
  20256. const DomParser = (settings = {}, schema = Schema()) => {
  20257. const nodeFilterRegistry = create$8();
  20258. const attributeFilterRegistry = create$8();
  20259. const defaultedSettings = {
  20260. validate: true,
  20261. root_name: "body",
  20262. sanitize: true,
  20263. ...settings,
  20264. };
  20265. const parser = new DOMParser();
  20266. const sanitize = getSanitizer(defaultedSettings, schema);
  20267. const parseAndSanitizeWithContext = (html, rootName, format = "html") => {
  20268. const mimeType =
  20269. format === "xhtml" ? "application/xhtml+xml" : "text/html";
  20270. const isSpecialRoot = has$2(
  20271. schema.getSpecialElements(),
  20272. rootName.toLowerCase()
  20273. );
  20274. const content = isSpecialRoot
  20275. ? `<${rootName}>${html}</${rootName}>`
  20276. : html;
  20277. const wrappedHtml =
  20278. format === "xhtml"
  20279. ? `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${content}</body></html>`
  20280. : `<body>${content}</body>`;
  20281. const body = parser.parseFromString(wrappedHtml, mimeType).body;
  20282. sanitize(body, mimeType);
  20283. return isSpecialRoot ? body.firstChild : body;
  20284. };
  20285. const addNodeFilter = nodeFilterRegistry.addFilter;
  20286. const getNodeFilters = nodeFilterRegistry.getFilters;
  20287. const removeNodeFilter = nodeFilterRegistry.removeFilter;
  20288. const addAttributeFilter = attributeFilterRegistry.addFilter;
  20289. const getAttributeFilters = attributeFilterRegistry.getFilters;
  20290. const removeAttributeFilter = attributeFilterRegistry.removeFilter;
  20291. const findInvalidChildren = (node, invalidChildren) => {
  20292. if (isInvalid(schema, node)) {
  20293. invalidChildren.push(node);
  20294. }
  20295. };
  20296. const isWrappableNode = (blockElements, node) => {
  20297. const isInternalElement = isString(node.attr(internalElementAttr));
  20298. const isInlineElement =
  20299. node.type === 1 &&
  20300. !has$2(blockElements, node.name) &&
  20301. !isTransparentAstBlock(schema, node);
  20302. return node.type === 3 || (isInlineElement && !isInternalElement);
  20303. };
  20304. const addRootBlocks = (rootNode, rootBlockName) => {
  20305. const blockElements = extend$1(
  20306. makeMap("script,style,head,html,body,title,meta,param"),
  20307. schema.getBlockElements()
  20308. );
  20309. const startWhiteSpaceRegExp = /^[ \t\r\n]+/;
  20310. const endWhiteSpaceRegExp = /[ \t\r\n]+$/;
  20311. let node = rootNode.firstChild,
  20312. rootBlockNode = null;
  20313. const trim = (rootBlock) => {
  20314. var _a, _b;
  20315. if (rootBlock) {
  20316. node = rootBlock.firstChild;
  20317. if (node && node.type === 3) {
  20318. node.value =
  20319. (_a = node.value) === null || _a === void 0
  20320. ? void 0
  20321. : _a.replace(startWhiteSpaceRegExp, "");
  20322. }
  20323. node = rootBlock.lastChild;
  20324. if (node && node.type === 3) {
  20325. node.value =
  20326. (_b = node.value) === null || _b === void 0
  20327. ? void 0
  20328. : _b.replace(endWhiteSpaceRegExp, "");
  20329. }
  20330. }
  20331. };
  20332. if (!schema.isValidChild(rootNode.name, rootBlockName.toLowerCase())) {
  20333. return;
  20334. }
  20335. while (node) {
  20336. const next = node.next;
  20337. if (isWrappableNode(blockElements, node)) {
  20338. if (!rootBlockNode) {
  20339. rootBlockNode = new AstNode(rootBlockName, 1);
  20340. rootBlockNode.attr(defaultedSettings.forced_root_block_attrs);
  20341. rootNode.insert(rootBlockNode, node);
  20342. rootBlockNode.append(node);
  20343. } else {
  20344. rootBlockNode.append(node);
  20345. }
  20346. } else {
  20347. trim(rootBlockNode);
  20348. rootBlockNode = null;
  20349. }
  20350. node = next;
  20351. }
  20352. trim(rootBlockNode);
  20353. };
  20354. const parse = (html, args = {}) => {
  20355. var _a;
  20356. const validate = defaultedSettings.validate;
  20357. const rootName =
  20358. (_a = args.context) !== null && _a !== void 0
  20359. ? _a
  20360. : defaultedSettings.root_name;
  20361. const element = parseAndSanitizeWithContext(html, rootName, args.format);
  20362. updateChildren(schema, element);
  20363. const rootNode = new AstNode(rootName, 11);
  20364. transferChildren(rootNode, element, schema.getSpecialElements());
  20365. element.innerHTML = "";
  20366. const [whitespacePre, whitespacePost] = whitespaceCleaner(
  20367. rootNode,
  20368. schema,
  20369. defaultedSettings,
  20370. args
  20371. );
  20372. const invalidChildren = [];
  20373. const invalidFinder = validate
  20374. ? (node) => findInvalidChildren(node, invalidChildren)
  20375. : noop;
  20376. const matches = {
  20377. nodes: {},
  20378. attributes: {},
  20379. };
  20380. const matchFinder = (node) =>
  20381. matchNode$1(getNodeFilters(), getAttributeFilters(), node, matches);
  20382. walkTree(
  20383. rootNode,
  20384. [whitespacePre, matchFinder],
  20385. [whitespacePost, invalidFinder]
  20386. );
  20387. invalidChildren.reverse();
  20388. if (validate && invalidChildren.length > 0) {
  20389. if (args.context) {
  20390. const { pass: topLevelChildren, fail: otherChildren } = partition$2(
  20391. invalidChildren,
  20392. (child) => child.parent === rootNode
  20393. );
  20394. cleanInvalidNodes(otherChildren, schema, rootNode, matchFinder);
  20395. args.invalid = topLevelChildren.length > 0;
  20396. } else {
  20397. cleanInvalidNodes(invalidChildren, schema, rootNode, matchFinder);
  20398. }
  20399. }
  20400. const rootBlockName = getRootBlockName(defaultedSettings, args);
  20401. if (rootBlockName && (rootNode.name === "body" || args.isRootContent)) {
  20402. addRootBlocks(rootNode, rootBlockName);
  20403. }
  20404. if (!args.invalid) {
  20405. runFilters(matches, args);
  20406. }
  20407. return rootNode;
  20408. };
  20409. const exports = {
  20410. schema,
  20411. addAttributeFilter,
  20412. getAttributeFilters,
  20413. removeAttributeFilter,
  20414. addNodeFilter,
  20415. getNodeFilters,
  20416. removeNodeFilter,
  20417. parse,
  20418. };
  20419. register$4(exports, defaultedSettings);
  20420. register$5(exports, defaultedSettings, schema);
  20421. return exports;
  20422. };
  20423. const serializeContent = (content) =>
  20424. isTreeNode(content)
  20425. ? HtmlSerializer({ validate: false }).serialize(content)
  20426. : content;
  20427. const withSerializedContent = (content, fireEvent, sanitize) => {
  20428. const serializedContent = serializeContent(content);
  20429. const eventArgs = fireEvent(serializedContent);
  20430. if (eventArgs.isDefaultPrevented()) {
  20431. return eventArgs;
  20432. } else if (isTreeNode(content)) {
  20433. if (eventArgs.content !== serializedContent) {
  20434. const rootNode = DomParser({
  20435. validate: false,
  20436. forced_root_block: false,
  20437. sanitize,
  20438. }).parse(eventArgs.content, { context: content.name });
  20439. return {
  20440. ...eventArgs,
  20441. content: rootNode,
  20442. };
  20443. } else {
  20444. return {
  20445. ...eventArgs,
  20446. content,
  20447. };
  20448. }
  20449. } else {
  20450. return eventArgs;
  20451. }
  20452. };
  20453. const preProcessGetContent = (editor, args) => {
  20454. if (args.no_events) {
  20455. return Result.value(args);
  20456. } else {
  20457. const eventArgs = fireBeforeGetContent(editor, args);
  20458. if (eventArgs.isDefaultPrevented()) {
  20459. return Result.error(
  20460. fireGetContent(editor, {
  20461. content: "",
  20462. ...eventArgs,
  20463. }).content
  20464. );
  20465. } else {
  20466. return Result.value(eventArgs);
  20467. }
  20468. }
  20469. };
  20470. const postProcessGetContent = (editor, content, args) => {
  20471. if (args.no_events) {
  20472. return content;
  20473. } else {
  20474. const processedEventArgs = withSerializedContent(
  20475. content,
  20476. (content) =>
  20477. fireGetContent(editor, {
  20478. ...args,
  20479. content,
  20480. }),
  20481. shouldSanitizeXss(editor)
  20482. );
  20483. return processedEventArgs.content;
  20484. }
  20485. };
  20486. const preProcessSetContent = (editor, args) => {
  20487. if (args.no_events) {
  20488. return Result.value(args);
  20489. } else {
  20490. const processedEventArgs = withSerializedContent(
  20491. args.content,
  20492. (content) =>
  20493. fireBeforeSetContent(editor, {
  20494. ...args,
  20495. content,
  20496. }),
  20497. shouldSanitizeXss(editor)
  20498. );
  20499. if (processedEventArgs.isDefaultPrevented()) {
  20500. fireSetContent(editor, processedEventArgs);
  20501. return Result.error(undefined);
  20502. } else {
  20503. return Result.value(processedEventArgs);
  20504. }
  20505. }
  20506. };
  20507. const postProcessSetContent = (editor, content, args) => {
  20508. if (!args.no_events) {
  20509. fireSetContent(editor, {
  20510. ...args,
  20511. content,
  20512. });
  20513. }
  20514. };
  20515. const tableModel = (element, width, rows) => ({
  20516. element,
  20517. width,
  20518. rows,
  20519. });
  20520. const tableRow = (element, cells) => ({
  20521. element,
  20522. cells,
  20523. });
  20524. const cellPosition = (x, y) => ({
  20525. x,
  20526. y,
  20527. });
  20528. const getSpan = (td, key) => {
  20529. return getOpt(td, key).bind(toInt).getOr(1);
  20530. };
  20531. const fillout = (table, x, y, tr, td) => {
  20532. const rowspan = getSpan(td, "rowspan");
  20533. const colspan = getSpan(td, "colspan");
  20534. const rows = table.rows;
  20535. for (let y2 = y; y2 < y + rowspan; y2++) {
  20536. if (!rows[y2]) {
  20537. rows[y2] = tableRow(deep$1(tr), []);
  20538. }
  20539. for (let x2 = x; x2 < x + colspan; x2++) {
  20540. const cells = rows[y2].cells;
  20541. cells[x2] = y2 === y && x2 === x ? td : shallow$1(td);
  20542. }
  20543. }
  20544. };
  20545. const cellExists = (table, x, y) => {
  20546. const rows = table.rows;
  20547. const cells = rows[y] ? rows[y].cells : [];
  20548. return !!cells[x];
  20549. };
  20550. const skipCellsX = (table, x, y) => {
  20551. while (cellExists(table, x, y)) {
  20552. x++;
  20553. }
  20554. return x;
  20555. };
  20556. const getWidth = (rows) => {
  20557. return foldl(
  20558. rows,
  20559. (acc, row) => {
  20560. return row.cells.length > acc ? row.cells.length : acc;
  20561. },
  20562. 0
  20563. );
  20564. };
  20565. const findElementPos = (table, element) => {
  20566. const rows = table.rows;
  20567. for (let y = 0; y < rows.length; y++) {
  20568. const cells = rows[y].cells;
  20569. for (let x = 0; x < cells.length; x++) {
  20570. if (eq(cells[x], element)) {
  20571. return Optional.some(cellPosition(x, y));
  20572. }
  20573. }
  20574. }
  20575. return Optional.none();
  20576. };
  20577. const extractRows = (table, sx, sy, ex, ey) => {
  20578. const newRows = [];
  20579. const rows = table.rows;
  20580. for (let y = sy; y <= ey; y++) {
  20581. const cells = rows[y].cells;
  20582. const slice = sx < ex ? cells.slice(sx, ex + 1) : cells.slice(ex, sx + 1);
  20583. newRows.push(tableRow(rows[y].element, slice));
  20584. }
  20585. return newRows;
  20586. };
  20587. const subTable = (table, startPos, endPos) => {
  20588. const sx = startPos.x,
  20589. sy = startPos.y;
  20590. const ex = endPos.x,
  20591. ey = endPos.y;
  20592. const newRows =
  20593. sy < ey
  20594. ? extractRows(table, sx, sy, ex, ey)
  20595. : extractRows(table, sx, ey, ex, sy);
  20596. return tableModel(table.element, getWidth(newRows), newRows);
  20597. };
  20598. const createDomTable = (table, rows) => {
  20599. const tableElement = shallow$1(table.element);
  20600. const tableBody = SugarElement.fromTag("tbody");
  20601. append(tableBody, rows);
  20602. append$1(tableElement, tableBody);
  20603. return tableElement;
  20604. };
  20605. const modelRowsToDomRows = (table) => {
  20606. return map$3(table.rows, (row) => {
  20607. const cells = map$3(row.cells, (cell) => {
  20608. const td = deep$1(cell);
  20609. remove$a(td, "colspan");
  20610. remove$a(td, "rowspan");
  20611. return td;
  20612. });
  20613. const tr = shallow$1(row.element);
  20614. append(tr, cells);
  20615. return tr;
  20616. });
  20617. };
  20618. const fromDom = (tableElm) => {
  20619. const table = tableModel(shallow$1(tableElm), 0, []);
  20620. each$e(descendants(tableElm, "tr"), (tr, y) => {
  20621. each$e(descendants(tr, "td,th"), (td, x) => {
  20622. fillout(table, skipCellsX(table, x, y), y, tr, td);
  20623. });
  20624. });
  20625. return tableModel(table.element, getWidth(table.rows), table.rows);
  20626. };
  20627. const toDom = (table) => {
  20628. return createDomTable(table, modelRowsToDomRows(table));
  20629. };
  20630. const subsection = (table, startElement, endElement) => {
  20631. return findElementPos(table, startElement).bind((startPos) => {
  20632. return findElementPos(table, endElement).map((endPos) => {
  20633. return subTable(table, startPos, endPos);
  20634. });
  20635. });
  20636. };
  20637. const findParentListContainer = (parents) =>
  20638. find$2(parents, (elm) => name(elm) === "ul" || name(elm) === "ol");
  20639. const getFullySelectedListWrappers = (parents, rng) =>
  20640. find$2(
  20641. parents,
  20642. (elm) => name(elm) === "li" && hasAllContentsSelected(elm, rng)
  20643. ).fold(constant([]), (_li) =>
  20644. findParentListContainer(parents)
  20645. .map((listCont) => {
  20646. const listElm = SugarElement.fromTag(name(listCont));
  20647. const listStyles = filter$4(getAllRaw(listCont), (_style, name) =>
  20648. startsWith(name, "list-style")
  20649. );
  20650. setAll(listElm, listStyles);
  20651. return [SugarElement.fromTag("li"), listElm];
  20652. })
  20653. .getOr([])
  20654. );
  20655. const wrap = (innerElm, elms) => {
  20656. const wrapped = foldl(
  20657. elms,
  20658. (acc, elm) => {
  20659. append$1(elm, acc);
  20660. return elm;
  20661. },
  20662. innerElm
  20663. );
  20664. return elms.length > 0 ? fromElements([wrapped]) : wrapped;
  20665. };
  20666. const directListWrappers = (commonAnchorContainer) => {
  20667. if (isListItem$1(commonAnchorContainer)) {
  20668. return parent(commonAnchorContainer)
  20669. .filter(isList)
  20670. .fold(constant([]), (listElm) => [commonAnchorContainer, listElm]);
  20671. } else {
  20672. return isList(commonAnchorContainer) ? [commonAnchorContainer] : [];
  20673. }
  20674. };
  20675. const getWrapElements = (rootNode, rng) => {
  20676. const commonAnchorContainer = SugarElement.fromDom(
  20677. rng.commonAncestorContainer
  20678. );
  20679. const parents = parentsAndSelf(commonAnchorContainer, rootNode);
  20680. const wrapElements = filter$5(parents, isWrapElement);
  20681. const listWrappers = getFullySelectedListWrappers(parents, rng);
  20682. const allWrappers = wrapElements.concat(
  20683. listWrappers.length
  20684. ? listWrappers
  20685. : directListWrappers(commonAnchorContainer)
  20686. );
  20687. return map$3(allWrappers, shallow$1);
  20688. };
  20689. const emptyFragment = () => fromElements([]);
  20690. const getFragmentFromRange = (rootNode, rng) =>
  20691. wrap(
  20692. SugarElement.fromDom(rng.cloneContents()),
  20693. getWrapElements(rootNode, rng)
  20694. );
  20695. const getParentTable = (rootElm, cell) =>
  20696. ancestor$3(cell, "table", curry(eq, rootElm));
  20697. const getTableFragment = (rootNode, selectedTableCells) =>
  20698. getParentTable(rootNode, selectedTableCells[0])
  20699. .bind((tableElm) => {
  20700. const firstCell = selectedTableCells[0];
  20701. const lastCell = selectedTableCells[selectedTableCells.length - 1];
  20702. const fullTableModel = fromDom(tableElm);
  20703. return subsection(fullTableModel, firstCell, lastCell).map(
  20704. (sectionedTableModel) => fromElements([toDom(sectionedTableModel)])
  20705. );
  20706. })
  20707. .getOrThunk(emptyFragment);
  20708. const getSelectionFragment = (rootNode, ranges) =>
  20709. ranges.length > 0 && ranges[0].collapsed
  20710. ? emptyFragment()
  20711. : getFragmentFromRange(rootNode, ranges[0]);
  20712. const read$3 = (rootNode, ranges) => {
  20713. const selectedCells = getCellsFromElementOrRanges(ranges, rootNode);
  20714. return selectedCells.length > 0
  20715. ? getTableFragment(rootNode, selectedCells)
  20716. : getSelectionFragment(rootNode, ranges);
  20717. };
  20718. const isCollapsibleWhitespace = (text, index) =>
  20719. index >= 0 && index < text.length && isWhiteSpace(text.charAt(index));
  20720. const getInnerText = (bin) => {
  20721. return trim$1(bin.innerText);
  20722. };
  20723. const getContextNodeName = (parentBlockOpt) =>
  20724. parentBlockOpt
  20725. .map((block) => block.nodeName)
  20726. .getOr("div")
  20727. .toLowerCase();
  20728. const getTextContent = (editor) =>
  20729. Optional.from(editor.selection.getRng())
  20730. .map((rng) => {
  20731. var _a;
  20732. const parentBlockOpt = Optional.from(
  20733. editor.dom.getParent(rng.commonAncestorContainer, editor.dom.isBlock)
  20734. );
  20735. const body = editor.getBody();
  20736. const contextNodeName = getContextNodeName(parentBlockOpt);
  20737. const rangeContentClone = SugarElement.fromDom(rng.cloneContents());
  20738. cleanupBogusElements(rangeContentClone);
  20739. cleanupInputNames(rangeContentClone);
  20740. const bin = editor.dom.add(
  20741. body,
  20742. contextNodeName,
  20743. {
  20744. "data-mce-bogus": "all",
  20745. style: "overflow: hidden; opacity: 0;",
  20746. },
  20747. rangeContentClone.dom
  20748. );
  20749. const text = getInnerText(bin);
  20750. const nonRenderedText = trim$1(
  20751. (_a = bin.textContent) !== null && _a !== void 0 ? _a : ""
  20752. );
  20753. editor.dom.remove(bin);
  20754. if (
  20755. isCollapsibleWhitespace(nonRenderedText, 0) ||
  20756. isCollapsibleWhitespace(nonRenderedText, nonRenderedText.length - 1)
  20757. ) {
  20758. const parentBlock = parentBlockOpt.getOr(body);
  20759. const parentBlockText = getInnerText(parentBlock);
  20760. const textIndex = parentBlockText.indexOf(text);
  20761. if (textIndex === -1) {
  20762. return text;
  20763. } else {
  20764. const hasProceedingSpace = isCollapsibleWhitespace(
  20765. parentBlockText,
  20766. textIndex - 1
  20767. );
  20768. const hasTrailingSpace = isCollapsibleWhitespace(
  20769. parentBlockText,
  20770. textIndex + text.length
  20771. );
  20772. return (
  20773. (hasProceedingSpace ? " " : "") +
  20774. text +
  20775. (hasTrailingSpace ? " " : "")
  20776. );
  20777. }
  20778. } else {
  20779. return text;
  20780. }
  20781. })
  20782. .getOr("");
  20783. const getSerializedContent = (editor, args) => {
  20784. const rng = editor.selection.getRng(),
  20785. tmpElm = editor.dom.create("body");
  20786. const sel = editor.selection.getSel();
  20787. const ranges = processRanges(editor, getRanges$1(sel));
  20788. const fragment = args.contextual
  20789. ? read$3(SugarElement.fromDom(editor.getBody()), ranges).dom
  20790. : rng.cloneContents();
  20791. if (fragment) {
  20792. tmpElm.appendChild(fragment);
  20793. }
  20794. return editor.selection.serializer.serialize(tmpElm, args);
  20795. };
  20796. const extractSelectedContent = (editor, args) => {
  20797. if (args.format === "text") {
  20798. return getTextContent(editor);
  20799. } else {
  20800. const content = getSerializedContent(editor, args);
  20801. if (args.format === "tree") {
  20802. return content;
  20803. } else {
  20804. return editor.selection.isCollapsed() ? "" : content;
  20805. }
  20806. }
  20807. };
  20808. const setupArgs$3 = (args, format) => ({
  20809. ...args,
  20810. format,
  20811. get: true,
  20812. selection: true,
  20813. getInner: true,
  20814. });
  20815. const getSelectedContentInternal = (editor, format, args = {}) => {
  20816. const defaultedArgs = setupArgs$3(args, format);
  20817. return preProcessGetContent(editor, defaultedArgs).fold(
  20818. identity,
  20819. (updatedArgs) => {
  20820. const content = extractSelectedContent(editor, updatedArgs);
  20821. return postProcessGetContent(editor, content, updatedArgs);
  20822. }
  20823. );
  20824. };
  20825. const KEEP = 0,
  20826. INSERT = 1,
  20827. DELETE = 2;
  20828. const diff = (left, right) => {
  20829. const size = left.length + right.length + 2;
  20830. const vDown = new Array(size);
  20831. const vUp = new Array(size);
  20832. const snake = (start, end, diag) => {
  20833. return {
  20834. start,
  20835. end,
  20836. diag,
  20837. };
  20838. };
  20839. const buildScript = (start1, end1, start2, end2, script) => {
  20840. const middle = getMiddleSnake(start1, end1, start2, end2);
  20841. if (
  20842. middle === null ||
  20843. (middle.start === end1 && middle.diag === end1 - end2) ||
  20844. (middle.end === start1 && middle.diag === start1 - start2)
  20845. ) {
  20846. let i = start1;
  20847. let j = start2;
  20848. while (i < end1 || j < end2) {
  20849. if (i < end1 && j < end2 && left[i] === right[j]) {
  20850. script.push([KEEP, left[i]]);
  20851. ++i;
  20852. ++j;
  20853. } else {
  20854. if (end1 - start1 > end2 - start2) {
  20855. script.push([DELETE, left[i]]);
  20856. ++i;
  20857. } else {
  20858. script.push([INSERT, right[j]]);
  20859. ++j;
  20860. }
  20861. }
  20862. }
  20863. } else {
  20864. buildScript(
  20865. start1,
  20866. middle.start,
  20867. start2,
  20868. middle.start - middle.diag,
  20869. script
  20870. );
  20871. for (let i2 = middle.start; i2 < middle.end; ++i2) {
  20872. script.push([KEEP, left[i2]]);
  20873. }
  20874. buildScript(middle.end, end1, middle.end - middle.diag, end2, script);
  20875. }
  20876. };
  20877. const buildSnake = (start, diag, end1, end2) => {
  20878. let end = start;
  20879. while (
  20880. end - diag < end2 &&
  20881. end < end1 &&
  20882. left[end] === right[end - diag]
  20883. ) {
  20884. ++end;
  20885. }
  20886. return snake(start, end, diag);
  20887. };
  20888. const getMiddleSnake = (start1, end1, start2, end2) => {
  20889. const m = end1 - start1;
  20890. const n = end2 - start2;
  20891. if (m === 0 || n === 0) {
  20892. return null;
  20893. }
  20894. const delta = m - n;
  20895. const sum = n + m;
  20896. const offset = (sum % 2 === 0 ? sum : sum + 1) / 2;
  20897. vDown[1 + offset] = start1;
  20898. vUp[1 + offset] = end1 + 1;
  20899. let d, k, i, x, y;
  20900. for (d = 0; d <= offset; ++d) {
  20901. for (k = -d; k <= d; k += 2) {
  20902. i = k + offset;
  20903. if (k === -d || (k !== d && vDown[i - 1] < vDown[i + 1])) {
  20904. vDown[i] = vDown[i + 1];
  20905. } else {
  20906. vDown[i] = vDown[i - 1] + 1;
  20907. }
  20908. x = vDown[i];
  20909. y = x - start1 + start2 - k;
  20910. while (x < end1 && y < end2 && left[x] === right[y]) {
  20911. vDown[i] = ++x;
  20912. ++y;
  20913. }
  20914. if (delta % 2 !== 0 && delta - d <= k && k <= delta + d) {
  20915. if (vUp[i - delta] <= vDown[i]) {
  20916. return buildSnake(
  20917. vUp[i - delta],
  20918. k + start1 - start2,
  20919. end1,
  20920. end2
  20921. );
  20922. }
  20923. }
  20924. }
  20925. for (k = delta - d; k <= delta + d; k += 2) {
  20926. i = k + offset - delta;
  20927. if (
  20928. k === delta - d ||
  20929. (k !== delta + d && vUp[i + 1] <= vUp[i - 1])
  20930. ) {
  20931. vUp[i] = vUp[i + 1] - 1;
  20932. } else {
  20933. vUp[i] = vUp[i - 1];
  20934. }
  20935. x = vUp[i] - 1;
  20936. y = x - start1 + start2 - k;
  20937. while (x >= start1 && y >= start2 && left[x] === right[y]) {
  20938. vUp[i] = x--;
  20939. y--;
  20940. }
  20941. if (delta % 2 === 0 && -d <= k && k <= d) {
  20942. if (vUp[i] <= vDown[i + delta]) {
  20943. return buildSnake(vUp[i], k + start1 - start2, end1, end2);
  20944. }
  20945. }
  20946. }
  20947. }
  20948. return null;
  20949. };
  20950. const script = [];
  20951. buildScript(0, left.length, 0, right.length, script);
  20952. return script;
  20953. };
  20954. const getOuterHtml = (elm) => {
  20955. if (isElement$6(elm)) {
  20956. return elm.outerHTML;
  20957. } else if (isText$a(elm)) {
  20958. return Entities.encodeRaw(elm.data, false);
  20959. } else if (isComment(elm)) {
  20960. return "<!--" + elm.data + "-->";
  20961. }
  20962. return "";
  20963. };
  20964. const createFragment = (html) => {
  20965. let node;
  20966. const container = document.createElement("div");
  20967. const frag = document.createDocumentFragment();
  20968. if (html) {
  20969. container.innerHTML = html;
  20970. }
  20971. while ((node = container.firstChild)) {
  20972. frag.appendChild(node);
  20973. }
  20974. return frag;
  20975. };
  20976. const insertAt = (elm, html, index) => {
  20977. const fragment = createFragment(html);
  20978. if (elm.hasChildNodes() && index < elm.childNodes.length) {
  20979. const target = elm.childNodes[index];
  20980. elm.insertBefore(fragment, target);
  20981. } else {
  20982. elm.appendChild(fragment);
  20983. }
  20984. };
  20985. const removeAt = (elm, index) => {
  20986. if (elm.hasChildNodes() && index < elm.childNodes.length) {
  20987. const target = elm.childNodes[index];
  20988. elm.removeChild(target);
  20989. }
  20990. };
  20991. const applyDiff = (diff, elm) => {
  20992. let index = 0;
  20993. each$e(diff, (action) => {
  20994. if (action[0] === KEEP) {
  20995. index++;
  20996. } else if (action[0] === INSERT) {
  20997. insertAt(elm, action[1], index);
  20998. index++;
  20999. } else if (action[0] === DELETE) {
  21000. removeAt(elm, index);
  21001. }
  21002. });
  21003. };
  21004. const read$2 = (elm) => {
  21005. return filter$5(map$3(from(elm.childNodes), getOuterHtml), (item) => {
  21006. return item.length > 0;
  21007. });
  21008. };
  21009. const write = (fragments, elm) => {
  21010. const currentFragments = map$3(from(elm.childNodes), getOuterHtml);
  21011. applyDiff(diff(currentFragments, fragments), elm);
  21012. return elm;
  21013. };
  21014. const lazyTempDocument = cached(() =>
  21015. document.implementation.createHTMLDocument("undo")
  21016. );
  21017. const hasIframes = (html) => {
  21018. return html.indexOf("</iframe>") !== -1;
  21019. };
  21020. const createFragmentedLevel = (fragments) => {
  21021. return {
  21022. type: "fragmented",
  21023. fragments,
  21024. content: "",
  21025. bookmark: null,
  21026. beforeBookmark: null,
  21027. };
  21028. };
  21029. const createCompleteLevel = (content) => {
  21030. return {
  21031. type: "complete",
  21032. fragments: null,
  21033. content,
  21034. bookmark: null,
  21035. beforeBookmark: null,
  21036. };
  21037. };
  21038. const createFromEditor = (editor) => {
  21039. const fragments = read$2(editor.getBody());
  21040. const trimmedFragments = bind$3(fragments, (html) => {
  21041. const trimmed = trimInternal(editor.serializer, html);
  21042. return trimmed.length > 0 ? [trimmed] : [];
  21043. });
  21044. const content = trimmedFragments.join("");
  21045. return hasIframes(content)
  21046. ? createFragmentedLevel(trimmedFragments)
  21047. : createCompleteLevel(content);
  21048. };
  21049. const applyToEditor = (editor, level, before) => {
  21050. const bookmark = before ? level.beforeBookmark : level.bookmark;
  21051. if (level.type === "fragmented") {
  21052. write(level.fragments, editor.getBody());
  21053. } else {
  21054. editor.setContent(level.content, {
  21055. format: "raw",
  21056. no_selection:
  21057. isNonNullable(bookmark) && isPathBookmark(bookmark)
  21058. ? !bookmark.isFakeCaret
  21059. : true,
  21060. });
  21061. }
  21062. if (bookmark) {
  21063. editor.selection.moveToBookmark(bookmark);
  21064. editor.selection.scrollIntoView();
  21065. }
  21066. };
  21067. const getLevelContent = (level) => {
  21068. return level.type === "fragmented"
  21069. ? level.fragments.join("")
  21070. : level.content;
  21071. };
  21072. const getCleanLevelContent = (level) => {
  21073. const elm = SugarElement.fromTag("body", lazyTempDocument());
  21074. set$1(elm, getLevelContent(level));
  21075. each$e(descendants(elm, "*[data-mce-bogus]"), unwrap);
  21076. return get$6(elm);
  21077. };
  21078. const hasEqualContent = (level1, level2) =>
  21079. getLevelContent(level1) === getLevelContent(level2);
  21080. const hasEqualCleanedContent = (level1, level2) =>
  21081. getCleanLevelContent(level1) === getCleanLevelContent(level2);
  21082. const isEq$1 = (level1, level2) => {
  21083. if (!level1 || !level2) {
  21084. return false;
  21085. } else if (hasEqualContent(level1, level2)) {
  21086. return true;
  21087. } else {
  21088. return hasEqualCleanedContent(level1, level2);
  21089. }
  21090. };
  21091. const isUnlocked = (locks) => locks.get() === 0;
  21092. const setTyping = (undoManager, typing, locks) => {
  21093. if (isUnlocked(locks)) {
  21094. undoManager.typing = typing;
  21095. }
  21096. };
  21097. const endTyping = (undoManager, locks) => {
  21098. if (undoManager.typing) {
  21099. setTyping(undoManager, false, locks);
  21100. undoManager.add();
  21101. }
  21102. };
  21103. const endTypingLevelIgnoreLocks = (undoManager) => {
  21104. if (undoManager.typing) {
  21105. undoManager.typing = false;
  21106. undoManager.add();
  21107. }
  21108. };
  21109. const beforeChange$1 = (editor, locks, beforeBookmark) => {
  21110. if (isUnlocked(locks)) {
  21111. beforeBookmark.set(getUndoBookmark(editor.selection));
  21112. }
  21113. };
  21114. const addUndoLevel$1 = (
  21115. editor,
  21116. undoManager,
  21117. index,
  21118. locks,
  21119. beforeBookmark,
  21120. level,
  21121. event
  21122. ) => {
  21123. const currentLevel = createFromEditor(editor);
  21124. const newLevel = Tools.extend(level || {}, currentLevel);
  21125. if (!isUnlocked(locks) || editor.removed) {
  21126. return null;
  21127. }
  21128. const lastLevel = undoManager.data[index.get()];
  21129. if (
  21130. editor
  21131. .dispatch("BeforeAddUndo", {
  21132. level: newLevel,
  21133. lastLevel,
  21134. originalEvent: event,
  21135. })
  21136. .isDefaultPrevented()
  21137. ) {
  21138. return null;
  21139. }
  21140. if (lastLevel && isEq$1(lastLevel, newLevel)) {
  21141. return null;
  21142. }
  21143. if (undoManager.data[index.get()]) {
  21144. beforeBookmark.get().each((bm) => {
  21145. undoManager.data[index.get()].beforeBookmark = bm;
  21146. });
  21147. }
  21148. const customUndoRedoLevels = getCustomUndoRedoLevels(editor);
  21149. if (customUndoRedoLevels) {
  21150. if (undoManager.data.length > customUndoRedoLevels) {
  21151. for (let i = 0; i < undoManager.data.length - 1; i++) {
  21152. undoManager.data[i] = undoManager.data[i + 1];
  21153. }
  21154. undoManager.data.length--;
  21155. index.set(undoManager.data.length);
  21156. }
  21157. }
  21158. newLevel.bookmark = getUndoBookmark(editor.selection);
  21159. if (index.get() < undoManager.data.length - 1) {
  21160. undoManager.data.length = index.get() + 1;
  21161. }
  21162. undoManager.data.push(newLevel);
  21163. index.set(undoManager.data.length - 1);
  21164. const args = {
  21165. level: newLevel,
  21166. lastLevel,
  21167. originalEvent: event,
  21168. };
  21169. if (index.get() > 0) {
  21170. editor.setDirty(true);
  21171. editor.dispatch("AddUndo", args);
  21172. editor.dispatch("change", args);
  21173. } else {
  21174. editor.dispatch("AddUndo", args);
  21175. }
  21176. return newLevel;
  21177. };
  21178. const clear$1 = (editor, undoManager, index) => {
  21179. undoManager.data = [];
  21180. index.set(0);
  21181. undoManager.typing = false;
  21182. editor.dispatch("ClearUndos");
  21183. };
  21184. const extra$1 = (editor, undoManager, index, callback1, callback2) => {
  21185. if (undoManager.transact(callback1)) {
  21186. const bookmark = undoManager.data[index.get()].bookmark;
  21187. const lastLevel = undoManager.data[index.get() - 1];
  21188. applyToEditor(editor, lastLevel, true);
  21189. if (undoManager.transact(callback2)) {
  21190. undoManager.data[index.get() - 1].beforeBookmark = bookmark;
  21191. }
  21192. }
  21193. };
  21194. const redo$1 = (editor, index, data) => {
  21195. let level;
  21196. if (index.get() < data.length - 1) {
  21197. index.set(index.get() + 1);
  21198. level = data[index.get()];
  21199. applyToEditor(editor, level, false);
  21200. editor.setDirty(true);
  21201. editor.dispatch("Redo", { level });
  21202. }
  21203. return level;
  21204. };
  21205. const undo$1 = (editor, undoManager, locks, index) => {
  21206. let level;
  21207. if (undoManager.typing) {
  21208. undoManager.add();
  21209. undoManager.typing = false;
  21210. setTyping(undoManager, false, locks);
  21211. }
  21212. if (index.get() > 0) {
  21213. index.set(index.get() - 1);
  21214. level = undoManager.data[index.get()];
  21215. applyToEditor(editor, level, true);
  21216. editor.setDirty(true);
  21217. editor.dispatch("Undo", { level });
  21218. }
  21219. return level;
  21220. };
  21221. const reset$1 = (undoManager) => {
  21222. undoManager.clear();
  21223. undoManager.add();
  21224. };
  21225. const hasUndo$1 = (editor, undoManager, index) =>
  21226. index.get() > 0 ||
  21227. (undoManager.typing &&
  21228. undoManager.data[0] &&
  21229. !isEq$1(createFromEditor(editor), undoManager.data[0]));
  21230. const hasRedo$1 = (undoManager, index) =>
  21231. index.get() < undoManager.data.length - 1 && !undoManager.typing;
  21232. const transact$1 = (undoManager, locks, callback) => {
  21233. endTyping(undoManager, locks);
  21234. undoManager.beforeChange();
  21235. undoManager.ignore(callback);
  21236. return undoManager.add();
  21237. };
  21238. const ignore$1 = (locks, callback) => {
  21239. try {
  21240. locks.set(locks.get() + 1);
  21241. callback();
  21242. } finally {
  21243. locks.set(locks.get() - 1);
  21244. }
  21245. };
  21246. const addVisualInternal = (editor, elm) => {
  21247. const dom = editor.dom;
  21248. const scope = isNonNullable(elm) ? elm : editor.getBody();
  21249. each$e(dom.select("table,a", scope), (matchedElm) => {
  21250. switch (matchedElm.nodeName) {
  21251. case "TABLE":
  21252. const cls = getVisualAidsTableClass(editor);
  21253. const value = dom.getAttrib(matchedElm, "border");
  21254. if ((!value || value === "0") && editor.hasVisual) {
  21255. dom.addClass(matchedElm, cls);
  21256. } else {
  21257. dom.removeClass(matchedElm, cls);
  21258. }
  21259. break;
  21260. case "A":
  21261. if (!dom.getAttrib(matchedElm, "href")) {
  21262. const value = dom.getAttrib(matchedElm, "name") || matchedElm.id;
  21263. const cls = getVisualAidsAnchorClass(editor);
  21264. if (value && editor.hasVisual) {
  21265. dom.addClass(matchedElm, cls);
  21266. } else {
  21267. dom.removeClass(matchedElm, cls);
  21268. }
  21269. }
  21270. break;
  21271. }
  21272. });
  21273. editor.dispatch("VisualAid", {
  21274. element: elm,
  21275. hasVisual: editor.hasVisual,
  21276. });
  21277. };
  21278. const makePlainAdaptor = (editor) => ({
  21279. init: { bindEvents: noop },
  21280. undoManager: {
  21281. beforeChange: (locks, beforeBookmark) =>
  21282. beforeChange$1(editor, locks, beforeBookmark),
  21283. add: (undoManager, index, locks, beforeBookmark, level, event) =>
  21284. addUndoLevel$1(
  21285. editor,
  21286. undoManager,
  21287. index,
  21288. locks,
  21289. beforeBookmark,
  21290. level,
  21291. event
  21292. ),
  21293. undo: (undoManager, locks, index) =>
  21294. undo$1(editor, undoManager, locks, index),
  21295. redo: (index, data) => redo$1(editor, index, data),
  21296. clear: (undoManager, index) => clear$1(editor, undoManager, index),
  21297. reset: (undoManager) => reset$1(undoManager),
  21298. hasUndo: (undoManager, index) => hasUndo$1(editor, undoManager, index),
  21299. hasRedo: (undoManager, index) => hasRedo$1(undoManager, index),
  21300. transact: (undoManager, locks, callback) =>
  21301. transact$1(undoManager, locks, callback),
  21302. ignore: (locks, callback) => ignore$1(locks, callback),
  21303. extra: (undoManager, index, callback1, callback2) =>
  21304. extra$1(editor, undoManager, index, callback1, callback2),
  21305. },
  21306. formatter: {
  21307. match: (name, vars, node, similar) =>
  21308. match$2(editor, name, vars, node, similar),
  21309. matchAll: (names, vars) => matchAll(editor, names, vars),
  21310. matchNode: (node, name, vars, similar) =>
  21311. matchNode(editor, node, name, vars, similar),
  21312. canApply: (name) => canApply(editor, name),
  21313. closest: (names) => closest(editor, names),
  21314. apply: (name, vars, node) => applyFormat$1(editor, name, vars, node),
  21315. remove: (name, vars, node, similar) =>
  21316. removeFormat$1(editor, name, vars, node, similar),
  21317. toggle: (name, vars, node) => toggle(editor, name, vars, node),
  21318. formatChanged: (
  21319. registeredFormatListeners,
  21320. formats,
  21321. callback,
  21322. similar,
  21323. vars
  21324. ) =>
  21325. formatChangedInternal(
  21326. editor,
  21327. registeredFormatListeners,
  21328. formats,
  21329. callback,
  21330. similar,
  21331. vars
  21332. ),
  21333. },
  21334. editor: {
  21335. getContent: (args) => getContentInternal(editor, args),
  21336. setContent: (content, args) => setContentInternal(editor, content, args),
  21337. insertContent: (value, details) =>
  21338. insertHtmlAtCaret(editor, value, details),
  21339. addVisual: (elm) => addVisualInternal(editor, elm),
  21340. },
  21341. selection: {
  21342. getContent: (format, args) =>
  21343. getSelectedContentInternal(editor, format, args),
  21344. },
  21345. autocompleter: {
  21346. addDecoration: (range) => create$9(editor, range),
  21347. removeDecoration: () =>
  21348. remove$2(editor, SugarElement.fromDom(editor.getBody())),
  21349. },
  21350. raw: { getModel: () => Optional.none() },
  21351. });
  21352. const makeRtcAdaptor = (rtcEditor) => {
  21353. const defaultVars = (vars) => (isObject(vars) ? vars : {});
  21354. const {
  21355. init,
  21356. undoManager,
  21357. formatter,
  21358. editor,
  21359. selection,
  21360. autocompleter,
  21361. raw,
  21362. } = rtcEditor;
  21363. return {
  21364. init: { bindEvents: init.bindEvents },
  21365. undoManager: {
  21366. beforeChange: undoManager.beforeChange,
  21367. add: undoManager.add,
  21368. undo: undoManager.undo,
  21369. redo: undoManager.redo,
  21370. clear: undoManager.clear,
  21371. reset: undoManager.reset,
  21372. hasUndo: undoManager.hasUndo,
  21373. hasRedo: undoManager.hasRedo,
  21374. transact: (_undoManager, _locks, fn) => undoManager.transact(fn),
  21375. ignore: (_locks, callback) => undoManager.ignore(callback),
  21376. extra: (_undoManager, _index, callback1, callback2) =>
  21377. undoManager.extra(callback1, callback2),
  21378. },
  21379. formatter: {
  21380. match: (name, vars, _node, similar) =>
  21381. formatter.match(name, defaultVars(vars), similar),
  21382. matchAll: formatter.matchAll,
  21383. matchNode: formatter.matchNode,
  21384. canApply: (name) => formatter.canApply(name),
  21385. closest: (names) => formatter.closest(names),
  21386. apply: (name, vars, _node) => formatter.apply(name, defaultVars(vars)),
  21387. remove: (name, vars, _node, _similar) =>
  21388. formatter.remove(name, defaultVars(vars)),
  21389. toggle: (name, vars, _node) =>
  21390. formatter.toggle(name, defaultVars(vars)),
  21391. formatChanged: (_rfl, formats, callback, similar, vars) =>
  21392. formatter.formatChanged(formats, callback, similar, vars),
  21393. },
  21394. editor: {
  21395. getContent: (args) => editor.getContent(args),
  21396. setContent: (content, args) => {
  21397. return {
  21398. content: editor.setContent(content, args),
  21399. html: "",
  21400. };
  21401. },
  21402. insertContent: (content, _details) => {
  21403. editor.insertContent(content);
  21404. return "";
  21405. },
  21406. addVisual: editor.addVisual,
  21407. },
  21408. selection: { getContent: (_format, args) => selection.getContent(args) },
  21409. autocompleter: {
  21410. addDecoration: autocompleter.addDecoration,
  21411. removeDecoration: autocompleter.removeDecoration,
  21412. },
  21413. raw: { getModel: () => Optional.some(raw.getRawModel()) },
  21414. };
  21415. };
  21416. const makeNoopAdaptor = () => {
  21417. const nul = constant(null);
  21418. const empty = constant("");
  21419. return {
  21420. init: { bindEvents: noop },
  21421. undoManager: {
  21422. beforeChange: noop,
  21423. add: nul,
  21424. undo: nul,
  21425. redo: nul,
  21426. clear: noop,
  21427. reset: noop,
  21428. hasUndo: never,
  21429. hasRedo: never,
  21430. transact: nul,
  21431. ignore: noop,
  21432. extra: noop,
  21433. },
  21434. formatter: {
  21435. match: never,
  21436. matchAll: constant([]),
  21437. matchNode: constant(undefined),
  21438. canApply: never,
  21439. closest: empty,
  21440. apply: noop,
  21441. remove: noop,
  21442. toggle: noop,
  21443. formatChanged: constant({ unbind: noop }),
  21444. },
  21445. editor: {
  21446. getContent: empty,
  21447. setContent: constant({
  21448. content: "",
  21449. html: "",
  21450. }),
  21451. insertContent: constant(""),
  21452. addVisual: noop,
  21453. },
  21454. selection: { getContent: empty },
  21455. autocompleter: {
  21456. addDecoration: noop,
  21457. removeDecoration: noop,
  21458. },
  21459. raw: { getModel: constant(Optional.none()) },
  21460. };
  21461. };
  21462. const isRtc = (editor) => has$2(editor.plugins, "rtc");
  21463. const getRtcSetup = (editor) =>
  21464. get$a(editor.plugins, "rtc").bind((rtcPlugin) =>
  21465. Optional.from(rtcPlugin.setup)
  21466. );
  21467. const setup$s = (editor) => {
  21468. const editorCast = editor;
  21469. return getRtcSetup(editor).fold(
  21470. () => {
  21471. editorCast.rtcInstance = makePlainAdaptor(editor);
  21472. return Optional.none();
  21473. },
  21474. (setup) => {
  21475. editorCast.rtcInstance = makeNoopAdaptor();
  21476. return Optional.some(() =>
  21477. setup().then((rtcEditor) => {
  21478. editorCast.rtcInstance = makeRtcAdaptor(rtcEditor);
  21479. return rtcEditor.rtc.isRemote;
  21480. })
  21481. );
  21482. }
  21483. );
  21484. };
  21485. const getRtcInstanceWithFallback = (editor) =>
  21486. editor.rtcInstance ? editor.rtcInstance : makePlainAdaptor(editor);
  21487. const getRtcInstanceWithError = (editor) => {
  21488. const rtcInstance = editor.rtcInstance;
  21489. if (!rtcInstance) {
  21490. throw new Error("Failed to get RTC instance not yet initialized.");
  21491. } else {
  21492. return rtcInstance;
  21493. }
  21494. };
  21495. const beforeChange = (editor, locks, beforeBookmark) => {
  21496. getRtcInstanceWithError(editor).undoManager.beforeChange(
  21497. locks,
  21498. beforeBookmark
  21499. );
  21500. };
  21501. const addUndoLevel = (
  21502. editor,
  21503. undoManager,
  21504. index,
  21505. locks,
  21506. beforeBookmark,
  21507. level,
  21508. event
  21509. ) =>
  21510. getRtcInstanceWithError(editor).undoManager.add(
  21511. undoManager,
  21512. index,
  21513. locks,
  21514. beforeBookmark,
  21515. level,
  21516. event
  21517. );
  21518. const undo = (editor, undoManager, locks, index) =>
  21519. getRtcInstanceWithError(editor).undoManager.undo(undoManager, locks, index);
  21520. const redo = (editor, index, data) =>
  21521. getRtcInstanceWithError(editor).undoManager.redo(index, data);
  21522. const clear = (editor, undoManager, index) => {
  21523. getRtcInstanceWithError(editor).undoManager.clear(undoManager, index);
  21524. };
  21525. const reset = (editor, undoManager) => {
  21526. getRtcInstanceWithError(editor).undoManager.reset(undoManager);
  21527. };
  21528. const hasUndo = (editor, undoManager, index) =>
  21529. getRtcInstanceWithError(editor).undoManager.hasUndo(undoManager, index);
  21530. const hasRedo = (editor, undoManager, index) =>
  21531. getRtcInstanceWithError(editor).undoManager.hasRedo(undoManager, index);
  21532. const transact = (editor, undoManager, locks, callback) =>
  21533. getRtcInstanceWithError(editor).undoManager.transact(
  21534. undoManager,
  21535. locks,
  21536. callback
  21537. );
  21538. const ignore = (editor, locks, callback) => {
  21539. getRtcInstanceWithError(editor).undoManager.ignore(locks, callback);
  21540. };
  21541. const extra = (editor, undoManager, index, callback1, callback2) => {
  21542. getRtcInstanceWithError(editor).undoManager.extra(
  21543. undoManager,
  21544. index,
  21545. callback1,
  21546. callback2
  21547. );
  21548. };
  21549. const matchFormat = (editor, name, vars, node, similar) =>
  21550. getRtcInstanceWithError(editor).formatter.match(name, vars, node, similar);
  21551. const matchAllFormats = (editor, names, vars) =>
  21552. getRtcInstanceWithError(editor).formatter.matchAll(names, vars);
  21553. const matchNodeFormat = (editor, node, name, vars, similar) =>
  21554. getRtcInstanceWithError(editor).formatter.matchNode(
  21555. node,
  21556. name,
  21557. vars,
  21558. similar
  21559. );
  21560. const canApplyFormat = (editor, name) =>
  21561. getRtcInstanceWithError(editor).formatter.canApply(name);
  21562. const closestFormat = (editor, names) =>
  21563. getRtcInstanceWithError(editor).formatter.closest(names);
  21564. const applyFormat = (editor, name, vars, node) => {
  21565. getRtcInstanceWithError(editor).formatter.apply(name, vars, node);
  21566. };
  21567. const removeFormat = (editor, name, vars, node, similar) => {
  21568. getRtcInstanceWithError(editor).formatter.remove(name, vars, node, similar);
  21569. };
  21570. const toggleFormat = (editor, name, vars, node) => {
  21571. getRtcInstanceWithError(editor).formatter.toggle(name, vars, node);
  21572. };
  21573. const formatChanged = (
  21574. editor,
  21575. registeredFormatListeners,
  21576. formats,
  21577. callback,
  21578. similar,
  21579. vars
  21580. ) =>
  21581. getRtcInstanceWithError(editor).formatter.formatChanged(
  21582. registeredFormatListeners,
  21583. formats,
  21584. callback,
  21585. similar,
  21586. vars
  21587. );
  21588. const getContent$2 = (editor, args) =>
  21589. getRtcInstanceWithFallback(editor).editor.getContent(args);
  21590. const setContent$2 = (editor, content, args) =>
  21591. getRtcInstanceWithFallback(editor).editor.setContent(content, args);
  21592. const insertContent$1 = (editor, value, details) =>
  21593. getRtcInstanceWithFallback(editor).editor.insertContent(value, details);
  21594. const getSelectedContent = (editor, format, args) =>
  21595. getRtcInstanceWithError(editor).selection.getContent(format, args);
  21596. const addVisual$1 = (editor, elm) =>
  21597. getRtcInstanceWithError(editor).editor.addVisual(elm);
  21598. const bindEvents = (editor) =>
  21599. getRtcInstanceWithError(editor).init.bindEvents();
  21600. const addAutocompleterDecoration = (editor, range) =>
  21601. getRtcInstanceWithError(editor).autocompleter.addDecoration(range);
  21602. const removeAutocompleterDecoration = (editor) =>
  21603. getRtcInstanceWithError(editor).autocompleter.removeDecoration();
  21604. const getContent$1 = (editor, args = {}) => {
  21605. const format = args.format ? args.format : "html";
  21606. return getSelectedContent(editor, format, args);
  21607. };
  21608. const removeEmpty = (text) => {
  21609. if (text.dom.length === 0) {
  21610. remove$5(text);
  21611. return Optional.none();
  21612. } else {
  21613. return Optional.some(text);
  21614. }
  21615. };
  21616. const walkPastBookmark = (node, start) =>
  21617. node
  21618. .filter((elm) => BookmarkManager.isBookmarkNode(elm.dom))
  21619. .bind(start ? nextSibling : prevSibling);
  21620. const merge$1 = (outer, inner, rng, start) => {
  21621. const outerElm = outer.dom;
  21622. const innerElm = inner.dom;
  21623. const oldLength = start ? outerElm.length : innerElm.length;
  21624. if (start) {
  21625. mergeTextNodes(outerElm, innerElm, false, !start);
  21626. rng.setStart(innerElm, oldLength);
  21627. } else {
  21628. mergeTextNodes(innerElm, outerElm, false, !start);
  21629. rng.setEnd(innerElm, oldLength);
  21630. }
  21631. };
  21632. const normalizeTextIfRequired = (inner, start) => {
  21633. parent(inner).each((root) => {
  21634. const text = inner.dom;
  21635. if (start && needsToBeNbspLeft(root, CaretPosition(text, 0))) {
  21636. normalizeWhitespaceAfter(text, 0);
  21637. } else if (
  21638. !start &&
  21639. needsToBeNbspRight(root, CaretPosition(text, text.length))
  21640. ) {
  21641. normalizeWhitespaceBefore(text, text.length);
  21642. }
  21643. });
  21644. };
  21645. const mergeAndNormalizeText = (outerNode, innerNode, rng, start) => {
  21646. outerNode
  21647. .bind((outer) => {
  21648. const normalizer = start
  21649. ? normalizeWhitespaceBefore
  21650. : normalizeWhitespaceAfter;
  21651. normalizer(outer.dom, start ? outer.dom.length : 0);
  21652. return innerNode
  21653. .filter(isText$b)
  21654. .map((inner) => merge$1(outer, inner, rng, start));
  21655. })
  21656. .orThunk(() => {
  21657. const innerTextNode = walkPastBookmark(innerNode, start)
  21658. .or(innerNode)
  21659. .filter(isText$b);
  21660. return innerTextNode.map((inner) =>
  21661. normalizeTextIfRequired(inner, start)
  21662. );
  21663. });
  21664. };
  21665. const rngSetContent = (rng, fragment) => {
  21666. const firstChild = Optional.from(fragment.firstChild).map(
  21667. SugarElement.fromDom
  21668. );
  21669. const lastChild = Optional.from(fragment.lastChild).map(
  21670. SugarElement.fromDom
  21671. );
  21672. rng.deleteContents();
  21673. rng.insertNode(fragment);
  21674. const prevText = firstChild
  21675. .bind(prevSibling)
  21676. .filter(isText$b)
  21677. .bind(removeEmpty);
  21678. const nextText = lastChild
  21679. .bind(nextSibling)
  21680. .filter(isText$b)
  21681. .bind(removeEmpty);
  21682. mergeAndNormalizeText(prevText, firstChild, rng, true);
  21683. mergeAndNormalizeText(nextText, lastChild, rng, false);
  21684. rng.collapse(false);
  21685. };
  21686. const setupArgs$2 = (args, content) => ({
  21687. format: "html",
  21688. ...args,
  21689. set: true,
  21690. selection: true,
  21691. content,
  21692. });
  21693. const cleanContent = (editor, args) => {
  21694. if (args.format !== "raw") {
  21695. const rng = editor.selection.getRng();
  21696. const contextBlock = editor.dom.getParent(
  21697. rng.commonAncestorContainer,
  21698. editor.dom.isBlock
  21699. );
  21700. const contextArgs = contextBlock
  21701. ? { context: contextBlock.nodeName.toLowerCase() }
  21702. : {};
  21703. const node = editor.parser.parse(args.content, {
  21704. forced_root_block: false,
  21705. ...contextArgs,
  21706. ...args,
  21707. });
  21708. return HtmlSerializer({ validate: false }, editor.schema).serialize(node);
  21709. } else {
  21710. return args.content;
  21711. }
  21712. };
  21713. const setContent$1 = (editor, content, args = {}) => {
  21714. const defaultedArgs = setupArgs$2(args, content);
  21715. preProcessSetContent(editor, defaultedArgs).each((updatedArgs) => {
  21716. const cleanedContent = cleanContent(editor, updatedArgs);
  21717. const rng = editor.selection.getRng();
  21718. rngSetContent(rng, rng.createContextualFragment(cleanedContent));
  21719. editor.selection.setRng(rng);
  21720. scrollRangeIntoView(editor, rng);
  21721. postProcessSetContent(editor, cleanedContent, updatedArgs);
  21722. });
  21723. };
  21724. const deleteFromCallbackMap = (callbackMap, selector, callback) => {
  21725. if (has$2(callbackMap, selector)) {
  21726. const newCallbacks = filter$5(
  21727. callbackMap[selector],
  21728. (cb) => cb !== callback
  21729. );
  21730. if (newCallbacks.length === 0) {
  21731. delete callbackMap[selector];
  21732. } else {
  21733. callbackMap[selector] = newCallbacks;
  21734. }
  21735. }
  21736. };
  21737. var SelectorChanged = (dom, editor) => {
  21738. let selectorChangedData;
  21739. let currentSelectors;
  21740. const findMatchingNode = (selector, nodes) =>
  21741. find$2(nodes, (node) => dom.is(node, selector));
  21742. const getParents = (elem) => dom.getParents(elem, undefined, dom.getRoot());
  21743. const setup = () => {
  21744. selectorChangedData = {};
  21745. currentSelectors = {};
  21746. editor.on("NodeChange", (e) => {
  21747. const node = e.element;
  21748. const parents = getParents(node);
  21749. const matchedSelectors = {};
  21750. each$d(selectorChangedData, (callbacks, selector) => {
  21751. findMatchingNode(selector, parents).each((node) => {
  21752. if (!currentSelectors[selector]) {
  21753. each$e(callbacks, (callback) => {
  21754. callback(true, {
  21755. node,
  21756. selector,
  21757. parents,
  21758. });
  21759. });
  21760. currentSelectors[selector] = callbacks;
  21761. }
  21762. matchedSelectors[selector] = callbacks;
  21763. });
  21764. });
  21765. each$d(currentSelectors, (callbacks, selector) => {
  21766. if (!matchedSelectors[selector]) {
  21767. delete currentSelectors[selector];
  21768. each$e(callbacks, (callback) => {
  21769. callback(false, {
  21770. node,
  21771. selector,
  21772. parents,
  21773. });
  21774. });
  21775. }
  21776. });
  21777. });
  21778. };
  21779. return {
  21780. selectorChangedWithUnbind: (selector, callback) => {
  21781. if (!selectorChangedData) {
  21782. setup();
  21783. }
  21784. if (!selectorChangedData[selector]) {
  21785. selectorChangedData[selector] = [];
  21786. }
  21787. selectorChangedData[selector].push(callback);
  21788. findMatchingNode(
  21789. selector,
  21790. getParents(editor.selection.getStart())
  21791. ).each(() => {
  21792. currentSelectors[selector] = selectorChangedData[selector];
  21793. });
  21794. return {
  21795. unbind: () => {
  21796. deleteFromCallbackMap(selectorChangedData, selector, callback);
  21797. deleteFromCallbackMap(currentSelectors, selector, callback);
  21798. },
  21799. };
  21800. },
  21801. };
  21802. };
  21803. const isAttachedToDom = (node) => {
  21804. return (
  21805. !!(node && node.ownerDocument) &&
  21806. contains(
  21807. SugarElement.fromDom(node.ownerDocument),
  21808. SugarElement.fromDom(node)
  21809. )
  21810. );
  21811. };
  21812. const isValidRange = (rng) => {
  21813. if (!rng) {
  21814. return false;
  21815. } else {
  21816. return (
  21817. isAttachedToDom(rng.startContainer) && isAttachedToDom(rng.endContainer)
  21818. );
  21819. }
  21820. };
  21821. const EditorSelection = (dom, win, serializer, editor) => {
  21822. let selectedRange;
  21823. let explicitRange;
  21824. const { selectorChangedWithUnbind } = SelectorChanged(dom, editor);
  21825. const setCursorLocation = (node, offset) => {
  21826. const rng = dom.createRng();
  21827. if (isNonNullable(node) && isNonNullable(offset)) {
  21828. rng.setStart(node, offset);
  21829. rng.setEnd(node, offset);
  21830. setRng(rng);
  21831. collapse(false);
  21832. } else {
  21833. moveEndPoint(dom, rng, editor.getBody(), true);
  21834. setRng(rng);
  21835. }
  21836. };
  21837. const getContent = (args) => getContent$1(editor, args);
  21838. const setContent = (content, args) => setContent$1(editor, content, args);
  21839. const getStart$1 = (real) => getStart(editor.getBody(), getRng$1(), real);
  21840. const getEnd = (real) => getEnd$1(editor.getBody(), getRng$1(), real);
  21841. const getBookmark = (type, normalized) =>
  21842. bookmarkManager.getBookmark(type, normalized);
  21843. const moveToBookmark = (bookmark) =>
  21844. bookmarkManager.moveToBookmark(bookmark);
  21845. const select$1 = (node, content) => {
  21846. select(dom, node, content).each(setRng);
  21847. return node;
  21848. };
  21849. const isCollapsed = () => {
  21850. const rng = getRng$1(),
  21851. sel = getSel();
  21852. if (!rng || rng.item) {
  21853. return false;
  21854. }
  21855. if (rng.compareEndPoints) {
  21856. return rng.compareEndPoints("StartToEnd", rng) === 0;
  21857. }
  21858. return !sel || rng.collapsed;
  21859. };
  21860. const isEditable = () => {
  21861. const rng = getRng$1();
  21862. const fakeSelectedElements = editor
  21863. .getBody()
  21864. .querySelectorAll('[data-mce-selected="1"]');
  21865. if (fakeSelectedElements.length > 0) {
  21866. return forall(fakeSelectedElements, (el) =>
  21867. dom.isEditable(el.parentElement)
  21868. );
  21869. } else if (rng.startContainer === rng.endContainer) {
  21870. return dom.isEditable(rng.startContainer);
  21871. } else {
  21872. return (
  21873. dom.isEditable(rng.startContainer) && dom.isEditable(rng.endContainer)
  21874. );
  21875. }
  21876. };
  21877. const collapse = (toStart) => {
  21878. const rng = getRng$1();
  21879. rng.collapse(!!toStart);
  21880. setRng(rng);
  21881. };
  21882. const getSel = () =>
  21883. win.getSelection ? win.getSelection() : win.document.selection;
  21884. const getRng$1 = () => {
  21885. let rng;
  21886. const tryCompareBoundaryPoints = (how, sourceRange, destinationRange) => {
  21887. try {
  21888. return sourceRange.compareBoundaryPoints(how, destinationRange);
  21889. } catch (ex) {
  21890. return -1;
  21891. }
  21892. };
  21893. const doc = win.document;
  21894. if (isNonNullable(editor.bookmark) && !hasFocus(editor)) {
  21895. const bookmark = getRng(editor);
  21896. if (bookmark.isSome()) {
  21897. return bookmark
  21898. .map((r) => processRanges(editor, [r])[0])
  21899. .getOr(doc.createRange());
  21900. }
  21901. }
  21902. try {
  21903. const selection = getSel();
  21904. if (selection && !isRestrictedNode(selection.anchorNode)) {
  21905. if (selection.rangeCount > 0) {
  21906. rng = selection.getRangeAt(0);
  21907. } else {
  21908. rng = doc.createRange();
  21909. }
  21910. rng = processRanges(editor, [rng])[0];
  21911. }
  21912. } catch (ex) {}
  21913. if (!rng) {
  21914. rng = doc.createRange();
  21915. }
  21916. if (isDocument$1(rng.startContainer) && rng.collapsed) {
  21917. const elm = dom.getRoot();
  21918. rng.setStart(elm, 0);
  21919. rng.setEnd(elm, 0);
  21920. }
  21921. if (selectedRange && explicitRange) {
  21922. if (
  21923. tryCompareBoundaryPoints(rng.START_TO_START, rng, selectedRange) ===
  21924. 0 &&
  21925. tryCompareBoundaryPoints(rng.END_TO_END, rng, selectedRange) === 0
  21926. ) {
  21927. rng = explicitRange;
  21928. } else {
  21929. selectedRange = null;
  21930. explicitRange = null;
  21931. }
  21932. }
  21933. return rng;
  21934. };
  21935. const setRng = (rng, forward) => {
  21936. if (!isValidRange(rng)) {
  21937. return;
  21938. }
  21939. const sel = getSel();
  21940. const evt = editor.dispatch("SetSelectionRange", {
  21941. range: rng,
  21942. forward,
  21943. });
  21944. rng = evt.range;
  21945. if (sel) {
  21946. explicitRange = rng;
  21947. try {
  21948. sel.removeAllRanges();
  21949. sel.addRange(rng);
  21950. } catch (ex) {}
  21951. if (forward === false && sel.extend) {
  21952. sel.collapse(rng.endContainer, rng.endOffset);
  21953. sel.extend(rng.startContainer, rng.startOffset);
  21954. }
  21955. selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
  21956. }
  21957. if (
  21958. !rng.collapsed &&
  21959. rng.startContainer === rng.endContainer &&
  21960. (sel === null || sel === void 0 ? void 0 : sel.setBaseAndExtent)
  21961. ) {
  21962. if (rng.endOffset - rng.startOffset < 2) {
  21963. if (rng.startContainer.hasChildNodes()) {
  21964. const node = rng.startContainer.childNodes[rng.startOffset];
  21965. if (node && node.nodeName === "IMG") {
  21966. sel.setBaseAndExtent(
  21967. rng.startContainer,
  21968. rng.startOffset,
  21969. rng.endContainer,
  21970. rng.endOffset
  21971. );
  21972. if (
  21973. sel.anchorNode !== rng.startContainer ||
  21974. sel.focusNode !== rng.endContainer
  21975. ) {
  21976. sel.setBaseAndExtent(node, 0, node, 1);
  21977. }
  21978. }
  21979. }
  21980. }
  21981. }
  21982. editor.dispatch("AfterSetSelectionRange", {
  21983. range: rng,
  21984. forward,
  21985. });
  21986. };
  21987. const setNode = (elm) => {
  21988. setContent(dom.getOuterHTML(elm));
  21989. return elm;
  21990. };
  21991. const getNode$1 = () => getNode(editor.getBody(), getRng$1());
  21992. const getSelectedBlocks$1 = (startElm, endElm) =>
  21993. getSelectedBlocks(dom, getRng$1(), startElm, endElm);
  21994. const isForward = () => {
  21995. const sel = getSel();
  21996. const anchorNode =
  21997. sel === null || sel === void 0 ? void 0 : sel.anchorNode;
  21998. const focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
  21999. if (
  22000. !sel ||
  22001. !anchorNode ||
  22002. !focusNode ||
  22003. isRestrictedNode(anchorNode) ||
  22004. isRestrictedNode(focusNode)
  22005. ) {
  22006. return true;
  22007. }
  22008. const anchorRange = dom.createRng();
  22009. const focusRange = dom.createRng();
  22010. try {
  22011. anchorRange.setStart(anchorNode, sel.anchorOffset);
  22012. anchorRange.collapse(true);
  22013. focusRange.setStart(focusNode, sel.focusOffset);
  22014. focusRange.collapse(true);
  22015. } catch (e) {
  22016. return true;
  22017. }
  22018. return (
  22019. anchorRange.compareBoundaryPoints(
  22020. anchorRange.START_TO_START,
  22021. focusRange
  22022. ) <= 0
  22023. );
  22024. };
  22025. const normalize = () => {
  22026. const rng = getRng$1();
  22027. const sel = getSel();
  22028. if (!hasMultipleRanges(sel) && hasAnyRanges(editor)) {
  22029. const normRng = normalize$2(dom, rng);
  22030. normRng.each((normRng) => {
  22031. setRng(normRng, isForward());
  22032. });
  22033. return normRng.getOr(rng);
  22034. }
  22035. return rng;
  22036. };
  22037. const selectorChanged = (selector, callback) => {
  22038. selectorChangedWithUnbind(selector, callback);
  22039. return exports;
  22040. };
  22041. const getScrollContainer = () => {
  22042. let scrollContainer;
  22043. let node = dom.getRoot();
  22044. while (node && node.nodeName !== "BODY") {
  22045. if (node.scrollHeight > node.clientHeight) {
  22046. scrollContainer = node;
  22047. break;
  22048. }
  22049. node = node.parentNode;
  22050. }
  22051. return scrollContainer;
  22052. };
  22053. const scrollIntoView = (elm, alignToTop) => {
  22054. if (isNonNullable(elm)) {
  22055. scrollElementIntoView(editor, elm, alignToTop);
  22056. } else {
  22057. scrollRangeIntoView(editor, getRng$1(), alignToTop);
  22058. }
  22059. };
  22060. const placeCaretAt = (clientX, clientY) =>
  22061. setRng(fromPoint(clientX, clientY, editor.getDoc()));
  22062. const getBoundingClientRect = () => {
  22063. const rng = getRng$1();
  22064. return rng.collapsed
  22065. ? CaretPosition.fromRangeStart(rng).getClientRects()[0]
  22066. : rng.getBoundingClientRect();
  22067. };
  22068. const destroy = () => {
  22069. win = selectedRange = explicitRange = null;
  22070. controlSelection.destroy();
  22071. };
  22072. const expand = (options = { type: "word" }) =>
  22073. setRng(RangeUtils(dom).expand(getRng$1(), options));
  22074. const exports = {
  22075. dom,
  22076. win,
  22077. serializer,
  22078. editor,
  22079. expand,
  22080. collapse,
  22081. setCursorLocation,
  22082. getContent,
  22083. setContent,
  22084. getBookmark,
  22085. moveToBookmark,
  22086. select: select$1,
  22087. isCollapsed,
  22088. isEditable,
  22089. isForward,
  22090. setNode,
  22091. getNode: getNode$1,
  22092. getSel,
  22093. setRng,
  22094. getRng: getRng$1,
  22095. getStart: getStart$1,
  22096. getEnd,
  22097. getSelectedBlocks: getSelectedBlocks$1,
  22098. normalize,
  22099. selectorChanged,
  22100. selectorChangedWithUnbind,
  22101. getScrollContainer,
  22102. scrollIntoView,
  22103. placeCaretAt,
  22104. getBoundingClientRect,
  22105. destroy,
  22106. };
  22107. const bookmarkManager = BookmarkManager(exports);
  22108. const controlSelection = ControlSelection(exports, editor);
  22109. exports.bookmarkManager = bookmarkManager;
  22110. exports.controlSelection = controlSelection;
  22111. return exports;
  22112. };
  22113. const register$3 = (htmlParser, settings, dom) => {
  22114. htmlParser.addAttributeFilter("data-mce-tabindex", (nodes, name) => {
  22115. let i = nodes.length;
  22116. while (i--) {
  22117. const node = nodes[i];
  22118. node.attr("tabindex", node.attr("data-mce-tabindex"));
  22119. node.attr(name, null);
  22120. }
  22121. });
  22122. htmlParser.addAttributeFilter("src,href,style", (nodes, name) => {
  22123. const internalName = "data-mce-" + name;
  22124. const urlConverter = settings.url_converter;
  22125. const urlConverterScope = settings.url_converter_scope;
  22126. let i = nodes.length;
  22127. while (i--) {
  22128. const node = nodes[i];
  22129. let value = node.attr(internalName);
  22130. if (value !== undefined) {
  22131. node.attr(name, value.length > 0 ? value : null);
  22132. node.attr(internalName, null);
  22133. } else {
  22134. value = node.attr(name);
  22135. if (name === "style") {
  22136. value = dom.serializeStyle(dom.parseStyle(value), node.name);
  22137. } else if (urlConverter) {
  22138. value = urlConverter.call(
  22139. urlConverterScope,
  22140. value,
  22141. name,
  22142. node.name
  22143. );
  22144. }
  22145. node.attr(name, value.length > 0 ? value : null);
  22146. }
  22147. }
  22148. });
  22149. htmlParser.addAttributeFilter("class", (nodes) => {
  22150. let i = nodes.length;
  22151. while (i--) {
  22152. const node = nodes[i];
  22153. let value = node.attr("class");
  22154. if (value) {
  22155. value = value.replace(/(?:^|\s)mce-item-\w+(?!\S)/g, "");
  22156. node.attr("class", value.length > 0 ? value : null);
  22157. }
  22158. }
  22159. });
  22160. htmlParser.addAttributeFilter("data-mce-type", (nodes, name, args) => {
  22161. let i = nodes.length;
  22162. while (i--) {
  22163. const node = nodes[i];
  22164. if (node.attr("data-mce-type") === "bookmark" && !args.cleanup) {
  22165. const hasChildren = Optional.from(node.firstChild).exists(
  22166. (firstChild) => {
  22167. var _a;
  22168. return !isZwsp$1(
  22169. (_a = firstChild.value) !== null && _a !== void 0 ? _a : ""
  22170. );
  22171. }
  22172. );
  22173. if (hasChildren) {
  22174. node.unwrap();
  22175. } else {
  22176. node.remove();
  22177. }
  22178. }
  22179. }
  22180. });
  22181. htmlParser.addNodeFilter("noscript", (nodes) => {
  22182. var _a;
  22183. let i = nodes.length;
  22184. while (i--) {
  22185. const node = nodes[i].firstChild;
  22186. if (node) {
  22187. node.value = Entities.decode(
  22188. (_a = node.value) !== null && _a !== void 0 ? _a : ""
  22189. );
  22190. }
  22191. }
  22192. });
  22193. htmlParser.addNodeFilter("script,style", (nodes, name) => {
  22194. var _a;
  22195. const trim = (value) => {
  22196. return value
  22197. .replace(/(<!--\[CDATA\[|\]\]-->)/g, "\n")
  22198. .replace(/^[\r\n]*|[\r\n]*$/g, "")
  22199. .replace(
  22200. /^\s*((<!--)?(\s*\/\/)?\s*<!\[CDATA\[|(<!--\s*)?\/\*\s*<!\[CDATA\[\s*\*\/|(\/\/)?\s*<!--|\/\*\s*<!--\s*\*\/)\s*[\r\n]*/gi,
  22201. ""
  22202. )
  22203. .replace(
  22204. /\s*(\/\*\s*\]\]>\s*\*\/(-->)?|\s*\/\/\s*\]\]>(-->)?|\/\/\s*(-->)?|\]\]>|\/\*\s*-->\s*\*\/|\s*-->\s*)\s*$/g,
  22205. ""
  22206. );
  22207. };
  22208. let i = nodes.length;
  22209. while (i--) {
  22210. const node = nodes[i];
  22211. const firstChild = node.firstChild;
  22212. const value =
  22213. (_a =
  22214. firstChild === null || firstChild === void 0
  22215. ? void 0
  22216. : firstChild.value) !== null && _a !== void 0
  22217. ? _a
  22218. : "";
  22219. if (name === "script") {
  22220. const type = node.attr("type");
  22221. if (type) {
  22222. node.attr(
  22223. "type",
  22224. type === "mce-no/type" ? null : type.replace(/^mce\-/, "")
  22225. );
  22226. }
  22227. if (
  22228. settings.element_format === "xhtml" &&
  22229. firstChild &&
  22230. value.length > 0
  22231. ) {
  22232. firstChild.value = "// <![CDATA[\n" + trim(value) + "\n// ]]>";
  22233. }
  22234. } else {
  22235. if (
  22236. settings.element_format === "xhtml" &&
  22237. firstChild &&
  22238. value.length > 0
  22239. ) {
  22240. firstChild.value = "<!--\n" + trim(value) + "\n-->";
  22241. }
  22242. }
  22243. }
  22244. });
  22245. htmlParser.addNodeFilter("#comment", (nodes) => {
  22246. let i = nodes.length;
  22247. while (i--) {
  22248. const node = nodes[i];
  22249. const value = node.value;
  22250. if (
  22251. settings.preserve_cdata &&
  22252. (value === null || value === void 0
  22253. ? void 0
  22254. : value.indexOf("[CDATA[")) === 0
  22255. ) {
  22256. node.name = "#cdata";
  22257. node.type = 4;
  22258. node.value = dom.decode(value.replace(/^\[CDATA\[|\]\]$/g, ""));
  22259. } else if (
  22260. (value === null || value === void 0
  22261. ? void 0
  22262. : value.indexOf("mce:protected ")) === 0
  22263. ) {
  22264. node.name = "#text";
  22265. node.type = 3;
  22266. node.raw = true;
  22267. node.value = unescape(value).substr(14);
  22268. }
  22269. }
  22270. });
  22271. htmlParser.addNodeFilter("xml:namespace,input", (nodes, name) => {
  22272. let i = nodes.length;
  22273. while (i--) {
  22274. const node = nodes[i];
  22275. if (node.type === 7) {
  22276. node.remove();
  22277. } else if (node.type === 1) {
  22278. if (name === "input" && !node.attr("type")) {
  22279. node.attr("type", "text");
  22280. }
  22281. }
  22282. }
  22283. });
  22284. htmlParser.addAttributeFilter("data-mce-type", (nodes) => {
  22285. each$e(nodes, (node) => {
  22286. if (node.attr("data-mce-type") === "format-caret") {
  22287. if (node.isEmpty(htmlParser.schema.getNonEmptyElements())) {
  22288. node.remove();
  22289. } else {
  22290. node.unwrap();
  22291. }
  22292. }
  22293. });
  22294. });
  22295. htmlParser.addAttributeFilter(
  22296. "data-mce-src,data-mce-href,data-mce-style," +
  22297. "data-mce-selected,data-mce-expando,data-mce-block," +
  22298. "data-mce-type,data-mce-resize,data-mce-placeholder",
  22299. (nodes, name) => {
  22300. let i = nodes.length;
  22301. while (i--) {
  22302. nodes[i].attr(name, null);
  22303. }
  22304. }
  22305. );
  22306. if (settings.remove_trailing_brs) {
  22307. addNodeFilter(settings, htmlParser, htmlParser.schema);
  22308. }
  22309. };
  22310. const trimTrailingBr = (rootNode) => {
  22311. const isBr = (node) => {
  22312. return (node === null || node === void 0 ? void 0 : node.name) === "br";
  22313. };
  22314. const brNode1 = rootNode.lastChild;
  22315. if (isBr(brNode1)) {
  22316. const brNode2 = brNode1.prev;
  22317. if (isBr(brNode2)) {
  22318. brNode1.remove();
  22319. brNode2.remove();
  22320. }
  22321. }
  22322. };
  22323. const preProcess$1 = (editor, node, args) => {
  22324. let oldDoc;
  22325. const dom = editor.dom;
  22326. let clonedNode = node.cloneNode(true);
  22327. const impl = document.implementation;
  22328. if (impl.createHTMLDocument) {
  22329. const doc = impl.createHTMLDocument("");
  22330. Tools.each(
  22331. clonedNode.nodeName === "BODY" ? clonedNode.childNodes : [clonedNode],
  22332. (node) => {
  22333. doc.body.appendChild(doc.importNode(node, true));
  22334. }
  22335. );
  22336. if (clonedNode.nodeName !== "BODY") {
  22337. clonedNode = doc.body.firstChild;
  22338. } else {
  22339. clonedNode = doc.body;
  22340. }
  22341. oldDoc = dom.doc;
  22342. dom.doc = doc;
  22343. }
  22344. firePreProcess(editor, {
  22345. ...args,
  22346. node: clonedNode,
  22347. });
  22348. if (oldDoc) {
  22349. dom.doc = oldDoc;
  22350. }
  22351. return clonedNode;
  22352. };
  22353. const shouldFireEvent = (editor, args) => {
  22354. return (
  22355. isNonNullable(editor) &&
  22356. editor.hasEventListeners("PreProcess") &&
  22357. !args.no_events
  22358. );
  22359. };
  22360. const process$1 = (editor, node, args) => {
  22361. return shouldFireEvent(editor, args)
  22362. ? preProcess$1(editor, node, args)
  22363. : node;
  22364. };
  22365. const addTempAttr = (htmlParser, tempAttrs, name) => {
  22366. if (Tools.inArray(tempAttrs, name) === -1) {
  22367. htmlParser.addAttributeFilter(name, (nodes, name) => {
  22368. let i = nodes.length;
  22369. while (i--) {
  22370. nodes[i].attr(name, null);
  22371. }
  22372. });
  22373. tempAttrs.push(name);
  22374. }
  22375. };
  22376. const postProcess = (editor, args, content) => {
  22377. if (!args.no_events && editor) {
  22378. const outArgs = firePostProcess(editor, {
  22379. ...args,
  22380. content,
  22381. });
  22382. return outArgs.content;
  22383. } else {
  22384. return content;
  22385. }
  22386. };
  22387. const getHtmlFromNode = (dom, node, args) => {
  22388. const html = trim$1(
  22389. args.getInner ? node.innerHTML : dom.getOuterHTML(node)
  22390. );
  22391. return args.selection || isWsPreserveElement(SugarElement.fromDom(node))
  22392. ? html
  22393. : Tools.trim(html);
  22394. };
  22395. const parseHtml = (htmlParser, html, args) => {
  22396. const parserArgs = args.selection
  22397. ? {
  22398. forced_root_block: false,
  22399. ...args,
  22400. }
  22401. : args;
  22402. const rootNode = htmlParser.parse(html, parserArgs);
  22403. trimTrailingBr(rootNode);
  22404. return rootNode;
  22405. };
  22406. const serializeNode = (settings, schema, node) => {
  22407. const htmlSerializer = HtmlSerializer(settings, schema);
  22408. return htmlSerializer.serialize(node);
  22409. };
  22410. const toHtml = (editor, settings, schema, rootNode, args) => {
  22411. const content = serializeNode(settings, schema, rootNode);
  22412. return postProcess(editor, args, content);
  22413. };
  22414. const DomSerializerImpl = (settings, editor) => {
  22415. const tempAttrs = ["data-mce-selected"];
  22416. const defaultedSettings = {
  22417. entity_encoding: "named",
  22418. remove_trailing_brs: true,
  22419. pad_empty_with_br: false,
  22420. ...settings,
  22421. };
  22422. const dom = editor && editor.dom ? editor.dom : DOMUtils.DOM;
  22423. const schema =
  22424. editor && editor.schema ? editor.schema : Schema(defaultedSettings);
  22425. const htmlParser = DomParser(defaultedSettings, schema);
  22426. register$3(htmlParser, defaultedSettings, dom);
  22427. const serialize = (node, parserArgs = {}) => {
  22428. const args = {
  22429. format: "html",
  22430. ...parserArgs,
  22431. };
  22432. const targetNode = process$1(editor, node, args);
  22433. const html = getHtmlFromNode(dom, targetNode, args);
  22434. const rootNode = parseHtml(htmlParser, html, args);
  22435. return args.format === "tree"
  22436. ? rootNode
  22437. : toHtml(editor, defaultedSettings, schema, rootNode, args);
  22438. };
  22439. return {
  22440. schema,
  22441. addNodeFilter: htmlParser.addNodeFilter,
  22442. addAttributeFilter: htmlParser.addAttributeFilter,
  22443. serialize: serialize,
  22444. addRules: schema.addValidElements,
  22445. setRules: schema.setValidElements,
  22446. addTempAttr: curry(addTempAttr, htmlParser, tempAttrs),
  22447. getTempAttrs: constant(tempAttrs),
  22448. getNodeFilters: htmlParser.getNodeFilters,
  22449. getAttributeFilters: htmlParser.getAttributeFilters,
  22450. removeNodeFilter: htmlParser.removeNodeFilter,
  22451. removeAttributeFilter: htmlParser.removeAttributeFilter,
  22452. };
  22453. };
  22454. const DomSerializer = (settings, editor) => {
  22455. const domSerializer = DomSerializerImpl(settings, editor);
  22456. return {
  22457. schema: domSerializer.schema,
  22458. addNodeFilter: domSerializer.addNodeFilter,
  22459. addAttributeFilter: domSerializer.addAttributeFilter,
  22460. serialize: domSerializer.serialize,
  22461. addRules: domSerializer.addRules,
  22462. setRules: domSerializer.setRules,
  22463. addTempAttr: domSerializer.addTempAttr,
  22464. getTempAttrs: domSerializer.getTempAttrs,
  22465. getNodeFilters: domSerializer.getNodeFilters,
  22466. getAttributeFilters: domSerializer.getAttributeFilters,
  22467. removeNodeFilter: domSerializer.removeNodeFilter,
  22468. removeAttributeFilter: domSerializer.removeAttributeFilter,
  22469. };
  22470. };
  22471. const defaultFormat$1 = "html";
  22472. const setupArgs$1 = (args, format) => ({
  22473. ...args,
  22474. format,
  22475. get: true,
  22476. getInner: true,
  22477. });
  22478. const getContent = (editor, args = {}) => {
  22479. const format = args.format ? args.format : defaultFormat$1;
  22480. const defaultedArgs = setupArgs$1(args, format);
  22481. return preProcessGetContent(editor, defaultedArgs).fold(
  22482. identity,
  22483. (updatedArgs) => {
  22484. const content = getContent$2(editor, updatedArgs);
  22485. return postProcessGetContent(editor, content, updatedArgs);
  22486. }
  22487. );
  22488. };
  22489. const defaultFormat = "html";
  22490. const setupArgs = (args, content) => ({
  22491. format: defaultFormat,
  22492. ...args,
  22493. set: true,
  22494. content,
  22495. });
  22496. const setContent = (editor, content, args = {}) => {
  22497. const defaultedArgs = setupArgs(args, content);
  22498. return preProcessSetContent(editor, defaultedArgs)
  22499. .map((updatedArgs) => {
  22500. const result = setContent$2(editor, updatedArgs.content, updatedArgs);
  22501. postProcessSetContent(editor, result.html, updatedArgs);
  22502. return result.content;
  22503. })
  22504. .getOr(content);
  22505. };
  22506. const removedOptions = (
  22507. "autoresize_on_init,content_editable_state,padd_empty_with_br,block_elements," +
  22508. "boolean_attributes,editor_deselector,editor_selector,elements,file_browser_callback_types,filepicker_validator_handler," +
  22509. "force_hex_style_colors,force_p_newlines,gecko_spellcheck,images_dataimg_filter,media_scripts,mode,move_caret_before_on_enter_elements," +
  22510. "non_empty_elements,self_closing_elements,short_ended_elements,special,spellchecker_select_languages,spellchecker_whitelist," +
  22511. "tab_focus,tabfocus_elements,table_responsive_width,text_block_elements,text_inline_elements,toolbar_drawer,types,validate,whitespace_elements," +
  22512. "paste_enable_default_filters,paste_filter_drop,paste_word_valid_elements,paste_retain_style_properties,paste_convert_word_fake_lists"
  22513. ).split(",");
  22514. const deprecatedOptions =
  22515. "template_cdate_classes,template_mdate_classes,template_selected_content_classes,template_preview_replace_values,template_replace_values,templates,template_cdate_format,template_mdate_format".split(
  22516. ","
  22517. );
  22518. const removedPlugins =
  22519. "bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,textcolor".split(
  22520. ","
  22521. );
  22522. const deprecatedPlugins = [
  22523. {
  22524. name: "template",
  22525. replacedWith: "Advanced Template",
  22526. },
  22527. { name: "rtc" },
  22528. ];
  22529. const getMatchingOptions = (options, searchingFor) => {
  22530. const settingNames = filter$5(searchingFor, (setting) =>
  22531. has$2(options, setting)
  22532. );
  22533. return sort(settingNames);
  22534. };
  22535. const getRemovedOptions = (options) => {
  22536. const settingNames = getMatchingOptions(options, removedOptions);
  22537. const forcedRootBlock = options.forced_root_block;
  22538. if (forcedRootBlock === false || forcedRootBlock === "") {
  22539. settingNames.push("forced_root_block (false only)");
  22540. }
  22541. return sort(settingNames);
  22542. };
  22543. const getDeprecatedOptions = (options) =>
  22544. getMatchingOptions(options, deprecatedOptions);
  22545. const getMatchingPlugins = (options, searchingFor) => {
  22546. const plugins = Tools.makeMap(options.plugins, " ");
  22547. const hasPlugin = (plugin) => has$2(plugins, plugin);
  22548. const pluginNames = filter$5(searchingFor, hasPlugin);
  22549. return sort(pluginNames);
  22550. };
  22551. const getRemovedPlugins = (options) =>
  22552. getMatchingPlugins(options, removedPlugins);
  22553. const getDeprecatedPlugins = (options) =>
  22554. getMatchingPlugins(
  22555. options,
  22556. deprecatedPlugins.map((entry) => entry.name)
  22557. );
  22558. const logRemovedWarnings = (rawOptions, normalizedOptions) => {
  22559. const removedOptions = getRemovedOptions(rawOptions);
  22560. const removedPlugins = getRemovedPlugins(normalizedOptions);
  22561. const hasRemovedPlugins = removedPlugins.length > 0;
  22562. const hasRemovedOptions = removedOptions.length > 0;
  22563. const isLegacyMobileTheme = normalizedOptions.theme === "mobile";
  22564. if (hasRemovedPlugins || hasRemovedOptions || isLegacyMobileTheme) {
  22565. const listJoiner = "\n- ";
  22566. const themesMessage = isLegacyMobileTheme
  22567. ? `\n\nThemes:${listJoiner}mobile`
  22568. : "";
  22569. const pluginsMessage = hasRemovedPlugins
  22570. ? `\n\nPlugins:${listJoiner}${removedPlugins.join(listJoiner)}`
  22571. : "";
  22572. const optionsMessage = hasRemovedOptions
  22573. ? `\n\nOptions:${listJoiner}${removedOptions.join(listJoiner)}`
  22574. : "";
  22575. console.warn(
  22576. "The following deprecated features are currently enabled and have been removed in TinyMCE 6.0. These features will no longer work and should be removed from the TinyMCE configuration. " +
  22577. "See https://www.tiny.cloud/docs/tinymce/6/migration-from-5x/ for more information." +
  22578. themesMessage +
  22579. pluginsMessage +
  22580. optionsMessage
  22581. );
  22582. }
  22583. };
  22584. const getPluginDescription = (name) =>
  22585. find$2(deprecatedPlugins, (entry) => entry.name === name).fold(
  22586. () => name,
  22587. (entry) => {
  22588. if (entry.replacedWith) {
  22589. return `${name}, replaced by ${entry.replacedWith}`;
  22590. } else {
  22591. return name;
  22592. }
  22593. }
  22594. );
  22595. const logDeprecatedWarnings = (rawOptions, normalizedOptions) => {
  22596. const deprecatedOptions = getDeprecatedOptions(rawOptions);
  22597. const deprecatedPlugins = getDeprecatedPlugins(normalizedOptions);
  22598. const hasDeprecatedPlugins = deprecatedPlugins.length > 0;
  22599. const hasDeprecatedOptions = deprecatedOptions.length > 0;
  22600. if (hasDeprecatedPlugins || hasDeprecatedOptions) {
  22601. const listJoiner = "\n- ";
  22602. const pluginsMessage = hasDeprecatedPlugins
  22603. ? `\n\nPlugins:${listJoiner}${deprecatedPlugins
  22604. .map(getPluginDescription)
  22605. .join(listJoiner)}`
  22606. : "";
  22607. const optionsMessage = hasDeprecatedOptions
  22608. ? `\n\nOptions:${listJoiner}${deprecatedOptions.join(listJoiner)}`
  22609. : "";
  22610. console.warn(
  22611. "The following deprecated features are currently enabled but will be removed soon." +
  22612. pluginsMessage +
  22613. optionsMessage
  22614. );
  22615. }
  22616. };
  22617. const logWarnings = (rawOptions, normalizedOptions) => {
  22618. logRemovedWarnings(rawOptions, normalizedOptions);
  22619. logDeprecatedWarnings(rawOptions, normalizedOptions);
  22620. };
  22621. const DOM$8 = DOMUtils.DOM;
  22622. const restoreOriginalStyles = (editor) => {
  22623. DOM$8.setStyle(editor.id, "display", editor.orgDisplay);
  22624. };
  22625. const safeDestroy = (x) => Optional.from(x).each((x) => x.destroy());
  22626. const clearDomReferences = (editor) => {
  22627. const ed = editor;
  22628. ed.contentAreaContainer =
  22629. ed.formElement =
  22630. ed.container =
  22631. ed.editorContainer =
  22632. null;
  22633. ed.bodyElement = ed.contentDocument = ed.contentWindow = null;
  22634. ed.iframeElement = ed.targetElm = null;
  22635. const selection = editor.selection;
  22636. if (selection) {
  22637. const dom = selection.dom;
  22638. ed.selection = selection.win = selection.dom = dom.doc = null;
  22639. }
  22640. };
  22641. const restoreForm = (editor) => {
  22642. const form = editor.formElement;
  22643. if (form) {
  22644. if (form._mceOldSubmit) {
  22645. form.submit = form._mceOldSubmit;
  22646. delete form._mceOldSubmit;
  22647. }
  22648. DOM$8.unbind(form, "submit reset", editor.formEventDelegate);
  22649. }
  22650. };
  22651. const remove$1 = (editor) => {
  22652. if (!editor.removed) {
  22653. const { _selectionOverrides, editorUpload } = editor;
  22654. const body = editor.getBody();
  22655. const element = editor.getElement();
  22656. if (body) {
  22657. editor.save({ is_removing: true });
  22658. }
  22659. editor.removed = true;
  22660. editor.unbindAllNativeEvents();
  22661. if (
  22662. editor.hasHiddenInput &&
  22663. isNonNullable(
  22664. element === null || element === void 0 ? void 0 : element.nextSibling
  22665. )
  22666. ) {
  22667. DOM$8.remove(element.nextSibling);
  22668. }
  22669. fireRemove(editor);
  22670. editor.editorManager.remove(editor);
  22671. if (!editor.inline && body) {
  22672. restoreOriginalStyles(editor);
  22673. }
  22674. fireDetach(editor);
  22675. DOM$8.remove(editor.getContainer());
  22676. safeDestroy(_selectionOverrides);
  22677. safeDestroy(editorUpload);
  22678. editor.destroy();
  22679. }
  22680. };
  22681. const destroy = (editor, automatic) => {
  22682. const { selection, dom } = editor;
  22683. if (editor.destroyed) {
  22684. return;
  22685. }
  22686. if (!automatic && !editor.removed) {
  22687. editor.remove();
  22688. return;
  22689. }
  22690. if (!automatic) {
  22691. editor.editorManager.off("beforeunload", editor._beforeUnload);
  22692. if (editor.theme && editor.theme.destroy) {
  22693. editor.theme.destroy();
  22694. }
  22695. safeDestroy(selection);
  22696. safeDestroy(dom);
  22697. }
  22698. restoreForm(editor);
  22699. clearDomReferences(editor);
  22700. editor.destroyed = true;
  22701. };
  22702. const CreateIconManager = () => {
  22703. const lookup = {};
  22704. const add = (id, iconPack) => {
  22705. lookup[id] = iconPack;
  22706. };
  22707. const get = (id) => {
  22708. if (lookup[id]) {
  22709. return lookup[id];
  22710. } else {
  22711. return { icons: {} };
  22712. }
  22713. };
  22714. const has = (id) => has$2(lookup, id);
  22715. return {
  22716. add,
  22717. get,
  22718. has,
  22719. };
  22720. };
  22721. const IconManager = CreateIconManager();
  22722. const ModelManager = AddOnManager.ModelManager;
  22723. const getProp = (propName, elm) => {
  22724. const rawElm = elm.dom;
  22725. return rawElm[propName];
  22726. };
  22727. const getComputedSizeProp = (propName, elm) =>
  22728. parseInt(get$7(elm, propName), 10);
  22729. const getClientWidth = curry(getProp, "clientWidth");
  22730. const getClientHeight = curry(getProp, "clientHeight");
  22731. const getMarginTop = curry(getComputedSizeProp, "margin-top");
  22732. const getMarginLeft = curry(getComputedSizeProp, "margin-left");
  22733. const getBoundingClientRect = (elm) => elm.dom.getBoundingClientRect();
  22734. const isInsideElementContentArea = (bodyElm, clientX, clientY) => {
  22735. const clientWidth = getClientWidth(bodyElm);
  22736. const clientHeight = getClientHeight(bodyElm);
  22737. return (
  22738. clientX >= 0 &&
  22739. clientY >= 0 &&
  22740. clientX <= clientWidth &&
  22741. clientY <= clientHeight
  22742. );
  22743. };
  22744. const transpose = (inline, elm, clientX, clientY) => {
  22745. const clientRect = getBoundingClientRect(elm);
  22746. const deltaX = inline
  22747. ? clientRect.left + elm.dom.clientLeft + getMarginLeft(elm)
  22748. : 0;
  22749. const deltaY = inline
  22750. ? clientRect.top + elm.dom.clientTop + getMarginTop(elm)
  22751. : 0;
  22752. const x = clientX - deltaX;
  22753. const y = clientY - deltaY;
  22754. return {
  22755. x,
  22756. y,
  22757. };
  22758. };
  22759. const isXYInContentArea = (editor, clientX, clientY) => {
  22760. const bodyElm = SugarElement.fromDom(editor.getBody());
  22761. const targetElm = editor.inline ? bodyElm : documentElement(bodyElm);
  22762. const transposedPoint = transpose(
  22763. editor.inline,
  22764. targetElm,
  22765. clientX,
  22766. clientY
  22767. );
  22768. return isInsideElementContentArea(
  22769. targetElm,
  22770. transposedPoint.x,
  22771. transposedPoint.y
  22772. );
  22773. };
  22774. const fromDomSafe = (node) => Optional.from(node).map(SugarElement.fromDom);
  22775. const isEditorAttachedToDom = (editor) => {
  22776. const rawContainer = editor.inline
  22777. ? editor.getBody()
  22778. : editor.getContentAreaContainer();
  22779. return fromDomSafe(rawContainer).map(inBody).getOr(false);
  22780. };
  22781. var NotificationManagerImpl = () => {
  22782. const unimplemented = () => {
  22783. throw new Error(
  22784. "Theme did not provide a NotificationManager implementation."
  22785. );
  22786. };
  22787. return {
  22788. open: unimplemented,
  22789. close: unimplemented,
  22790. getArgs: unimplemented,
  22791. };
  22792. };
  22793. const NotificationManager = (editor) => {
  22794. const notifications = [];
  22795. const getImplementation = () => {
  22796. const theme = editor.theme;
  22797. return theme && theme.getNotificationManagerImpl
  22798. ? theme.getNotificationManagerImpl()
  22799. : NotificationManagerImpl();
  22800. };
  22801. const getTopNotification = () => {
  22802. return Optional.from(notifications[0]);
  22803. };
  22804. const isEqual = (a, b) => {
  22805. return (
  22806. a.type === b.type &&
  22807. a.text === b.text &&
  22808. !a.progressBar &&
  22809. !a.timeout &&
  22810. !b.progressBar &&
  22811. !b.timeout
  22812. );
  22813. };
  22814. const reposition = () => {
  22815. each$e(notifications, (notification) => {
  22816. notification.reposition();
  22817. });
  22818. };
  22819. const addNotification = (notification) => {
  22820. notifications.push(notification);
  22821. };
  22822. const closeNotification = (notification) => {
  22823. findIndex$2(notifications, (otherNotification) => {
  22824. return otherNotification === notification;
  22825. }).each((index) => {
  22826. notifications.splice(index, 1);
  22827. });
  22828. };
  22829. const open = (spec, fireEvent = true) => {
  22830. if (editor.removed || !isEditorAttachedToDom(editor)) {
  22831. return {};
  22832. }
  22833. if (fireEvent) {
  22834. editor.dispatch("BeforeOpenNotification", { notification: spec });
  22835. }
  22836. return find$2(notifications, (notification) => {
  22837. return isEqual(getImplementation().getArgs(notification), spec);
  22838. }).getOrThunk(() => {
  22839. editor.editorManager.setActive(editor);
  22840. const notification = getImplementation().open(spec, () => {
  22841. closeNotification(notification);
  22842. reposition();
  22843. getTopNotification().fold(
  22844. () => editor.focus(),
  22845. (top) => focus$1(SugarElement.fromDom(top.getEl()))
  22846. );
  22847. });
  22848. addNotification(notification);
  22849. reposition();
  22850. editor.dispatch("OpenNotification", {
  22851. notification: { ...notification },
  22852. });
  22853. return notification;
  22854. });
  22855. };
  22856. const close = () => {
  22857. getTopNotification().each((notification) => {
  22858. getImplementation().close(notification);
  22859. closeNotification(notification);
  22860. reposition();
  22861. });
  22862. };
  22863. const getNotifications = constant(notifications);
  22864. const registerEvents = (editor) => {
  22865. editor.on("SkinLoaded", () => {
  22866. const serviceMessage = getServiceMessage(editor);
  22867. if (serviceMessage) {
  22868. open(
  22869. {
  22870. text: serviceMessage,
  22871. type: "warning",
  22872. timeout: 0,
  22873. },
  22874. false
  22875. );
  22876. }
  22877. reposition();
  22878. });
  22879. editor.on("show ResizeEditor ResizeWindow NodeChange", () => {
  22880. requestAnimationFrame(reposition);
  22881. });
  22882. editor.on("remove", () => {
  22883. each$e(notifications.slice(), (notification) => {
  22884. getImplementation().close(notification);
  22885. });
  22886. });
  22887. };
  22888. registerEvents(editor);
  22889. return {
  22890. open,
  22891. close,
  22892. getNotifications,
  22893. };
  22894. };
  22895. const PluginManager = AddOnManager.PluginManager;
  22896. const ThemeManager = AddOnManager.ThemeManager;
  22897. var WindowManagerImpl = () => {
  22898. const unimplemented = () => {
  22899. throw new Error("Theme did not provide a WindowManager implementation.");
  22900. };
  22901. return {
  22902. open: unimplemented,
  22903. openUrl: unimplemented,
  22904. alert: unimplemented,
  22905. confirm: unimplemented,
  22906. close: unimplemented,
  22907. };
  22908. };
  22909. const WindowManager = (editor) => {
  22910. let dialogs = [];
  22911. const getImplementation = () => {
  22912. const theme = editor.theme;
  22913. return theme && theme.getWindowManagerImpl
  22914. ? theme.getWindowManagerImpl()
  22915. : WindowManagerImpl();
  22916. };
  22917. const funcBind = (scope, f) => {
  22918. return (...args) => {
  22919. return f ? f.apply(scope, args) : undefined;
  22920. };
  22921. };
  22922. const fireOpenEvent = (dialog) => {
  22923. editor.dispatch("OpenWindow", { dialog });
  22924. };
  22925. const fireCloseEvent = (dialog) => {
  22926. editor.dispatch("CloseWindow", { dialog });
  22927. };
  22928. const addDialog = (dialog) => {
  22929. dialogs.push(dialog);
  22930. fireOpenEvent(dialog);
  22931. };
  22932. const closeDialog = (dialog) => {
  22933. fireCloseEvent(dialog);
  22934. dialogs = filter$5(dialogs, (otherDialog) => {
  22935. return otherDialog !== dialog;
  22936. });
  22937. if (dialogs.length === 0) {
  22938. editor.focus();
  22939. }
  22940. };
  22941. const getTopDialog = () => {
  22942. return Optional.from(dialogs[dialogs.length - 1]);
  22943. };
  22944. const storeSelectionAndOpenDialog = (openDialog) => {
  22945. editor.editorManager.setActive(editor);
  22946. store(editor);
  22947. editor.ui.show();
  22948. const dialog = openDialog();
  22949. addDialog(dialog);
  22950. return dialog;
  22951. };
  22952. const open = (args, params) => {
  22953. return storeSelectionAndOpenDialog(() =>
  22954. getImplementation().open(args, params, closeDialog)
  22955. );
  22956. };
  22957. const openUrl = (args) => {
  22958. return storeSelectionAndOpenDialog(() =>
  22959. getImplementation().openUrl(args, closeDialog)
  22960. );
  22961. };
  22962. const alert = (message, callback, scope) => {
  22963. const windowManagerImpl = getImplementation();
  22964. windowManagerImpl.alert(
  22965. message,
  22966. funcBind(scope ? scope : windowManagerImpl, callback)
  22967. );
  22968. };
  22969. const confirm = (message, callback, scope) => {
  22970. const windowManagerImpl = getImplementation();
  22971. windowManagerImpl.confirm(
  22972. message,
  22973. funcBind(scope ? scope : windowManagerImpl, callback)
  22974. );
  22975. };
  22976. const close = () => {
  22977. getTopDialog().each((dialog) => {
  22978. getImplementation().close(dialog);
  22979. closeDialog(dialog);
  22980. });
  22981. };
  22982. editor.on("remove", () => {
  22983. each$e(dialogs, (dialog) => {
  22984. getImplementation().close(dialog);
  22985. });
  22986. });
  22987. return {
  22988. open,
  22989. openUrl,
  22990. alert,
  22991. confirm,
  22992. close,
  22993. };
  22994. };
  22995. const displayNotification = (editor, message) => {
  22996. editor.notificationManager.open({
  22997. type: "error",
  22998. text: message,
  22999. });
  23000. };
  23001. const displayError = (editor, message) => {
  23002. if (editor._skinLoaded) {
  23003. displayNotification(editor, message);
  23004. } else {
  23005. editor.on("SkinLoaded", () => {
  23006. displayNotification(editor, message);
  23007. });
  23008. }
  23009. };
  23010. const uploadError = (editor, message) => {
  23011. displayError(
  23012. editor,
  23013. I18n.translate(["Failed to upload image: {0}", message])
  23014. );
  23015. };
  23016. const logError = (editor, errorType, msg) => {
  23017. fireError(editor, errorType, { message: msg });
  23018. console.error(msg);
  23019. };
  23020. const createLoadError = (type, url, name) =>
  23021. name
  23022. ? `Failed to load ${type}: ${name} from url ${url}`
  23023. : `Failed to load ${type} url: ${url}`;
  23024. const pluginLoadError = (editor, url, name) => {
  23025. logError(editor, "PluginLoadError", createLoadError("plugin", url, name));
  23026. };
  23027. const iconsLoadError = (editor, url, name) => {
  23028. logError(editor, "IconsLoadError", createLoadError("icons", url, name));
  23029. };
  23030. const languageLoadError = (editor, url, name) => {
  23031. logError(
  23032. editor,
  23033. "LanguageLoadError",
  23034. createLoadError("language", url, name)
  23035. );
  23036. };
  23037. const themeLoadError = (editor, url, name) => {
  23038. logError(editor, "ThemeLoadError", createLoadError("theme", url, name));
  23039. };
  23040. const modelLoadError = (editor, url, name) => {
  23041. logError(editor, "ModelLoadError", createLoadError("model", url, name));
  23042. };
  23043. const pluginInitError = (editor, name, err) => {
  23044. const message = I18n.translate(["Failed to initialize plugin: {0}", name]);
  23045. fireError(editor, "PluginLoadError", { message });
  23046. initError(message, err);
  23047. displayError(editor, message);
  23048. };
  23049. const initError = (message, ...x) => {
  23050. const console = window.console;
  23051. if (console) {
  23052. if (console.error) {
  23053. console.error(message, ...x);
  23054. } else {
  23055. //console.log(message, ...x);
  23056. }
  23057. }
  23058. };
  23059. const isContentCssSkinName = (url) => /^[a-z0-9\-]+$/i.test(url);
  23060. const getContentCssUrls = (editor) => {
  23061. return transformToUrls(editor, getContentCss(editor));
  23062. };
  23063. const getFontCssUrls = (editor) => {
  23064. return transformToUrls(editor, getFontCss(editor));
  23065. };
  23066. const transformToUrls = (editor, cssLinks) => {
  23067. const skinUrl = editor.editorManager.baseURL + "/skins/content";
  23068. const suffix = editor.editorManager.suffix;
  23069. const contentCssFile = `content${suffix}.css`;
  23070. return map$3(cssLinks, (url) => {
  23071. if (isContentCssSkinName(url) && !editor.inline) {
  23072. return `${skinUrl}/${url}/${contentCssFile}`;
  23073. } else {
  23074. return editor.documentBaseURI.toAbsolute(url);
  23075. }
  23076. });
  23077. };
  23078. const appendContentCssFromSettings = (editor) => {
  23079. editor.contentCSS = editor.contentCSS.concat(
  23080. getContentCssUrls(editor),
  23081. getFontCssUrls(editor)
  23082. );
  23083. };
  23084. const getAllImages = (elm) => {
  23085. return elm ? from(elm.getElementsByTagName("img")) : [];
  23086. };
  23087. const ImageScanner = (uploadStatus, blobCache) => {
  23088. const cachedPromises = {};
  23089. const findAll = (elm, predicate = always) => {
  23090. const images = filter$5(getAllImages(elm), (img) => {
  23091. const src = img.src;
  23092. if (img.hasAttribute("data-mce-bogus")) {
  23093. return false;
  23094. }
  23095. if (img.hasAttribute("data-mce-placeholder")) {
  23096. return false;
  23097. }
  23098. if (!src || src === Env.transparentSrc) {
  23099. return false;
  23100. }
  23101. if (startsWith(src, "blob:")) {
  23102. return !uploadStatus.isUploaded(src) && predicate(img);
  23103. }
  23104. if (startsWith(src, "data:")) {
  23105. return predicate(img);
  23106. }
  23107. return false;
  23108. });
  23109. const promises = map$3(images, (img) => {
  23110. const imageSrc = img.src;
  23111. if (has$2(cachedPromises, imageSrc)) {
  23112. return cachedPromises[imageSrc].then((imageInfo) => {
  23113. if (isString(imageInfo)) {
  23114. return imageInfo;
  23115. } else {
  23116. return {
  23117. image: img,
  23118. blobInfo: imageInfo.blobInfo,
  23119. };
  23120. }
  23121. });
  23122. } else {
  23123. const newPromise = imageToBlobInfo(blobCache, imageSrc)
  23124. .then((blobInfo) => {
  23125. delete cachedPromises[imageSrc];
  23126. return {
  23127. image: img,
  23128. blobInfo,
  23129. };
  23130. })
  23131. .catch((error) => {
  23132. delete cachedPromises[imageSrc];
  23133. return error;
  23134. });
  23135. cachedPromises[imageSrc] = newPromise;
  23136. return newPromise;
  23137. }
  23138. });
  23139. return Promise.all(promises);
  23140. };
  23141. return { findAll };
  23142. };
  23143. const UploadStatus = () => {
  23144. const PENDING = 1,
  23145. UPLOADED = 2;
  23146. let blobUriStatuses = {};
  23147. const createStatus = (status, resultUri) => {
  23148. return {
  23149. status,
  23150. resultUri,
  23151. };
  23152. };
  23153. const hasBlobUri = (blobUri) => {
  23154. return blobUri in blobUriStatuses;
  23155. };
  23156. const getResultUri = (blobUri) => {
  23157. const result = blobUriStatuses[blobUri];
  23158. return result ? result.resultUri : null;
  23159. };
  23160. const isPending = (blobUri) => {
  23161. return hasBlobUri(blobUri)
  23162. ? blobUriStatuses[blobUri].status === PENDING
  23163. : false;
  23164. };
  23165. const isUploaded = (blobUri) => {
  23166. return hasBlobUri(blobUri)
  23167. ? blobUriStatuses[blobUri].status === UPLOADED
  23168. : false;
  23169. };
  23170. const markPending = (blobUri) => {
  23171. blobUriStatuses[blobUri] = createStatus(PENDING, null);
  23172. };
  23173. const markUploaded = (blobUri, resultUri) => {
  23174. blobUriStatuses[blobUri] = createStatus(UPLOADED, resultUri);
  23175. };
  23176. const removeFailed = (blobUri) => {
  23177. delete blobUriStatuses[blobUri];
  23178. };
  23179. const destroy = () => {
  23180. blobUriStatuses = {};
  23181. };
  23182. return {
  23183. hasBlobUri,
  23184. getResultUri,
  23185. isPending,
  23186. isUploaded,
  23187. markPending,
  23188. markUploaded,
  23189. removeFailed,
  23190. destroy,
  23191. };
  23192. };
  23193. let count = 0;
  23194. const seed = () => {
  23195. const rnd = () => {
  23196. return Math.round(Math.random() * 4294967295).toString(36);
  23197. };
  23198. const now = new Date().getTime();
  23199. return "s" + now.toString(36) + rnd() + rnd() + rnd();
  23200. };
  23201. const uuid = (prefix) => {
  23202. return prefix + count++ + seed();
  23203. };
  23204. const BlobCache = () => {
  23205. let cache = [];
  23206. const mimeToExt = (mime) => {
  23207. const mimes = {
  23208. "image/jpeg": "jpg",
  23209. "image/jpg": "jpg",
  23210. "image/gif": "gif",
  23211. "image/png": "png",
  23212. "image/apng": "apng",
  23213. "image/avif": "avif",
  23214. "image/svg+xml": "svg",
  23215. "image/webp": "webp",
  23216. "image/bmp": "bmp",
  23217. "image/tiff": "tiff",
  23218. };
  23219. return mimes[mime.toLowerCase()] || "dat";
  23220. };
  23221. const create = (o, blob, base64, name, filename) => {
  23222. if (isString(o)) {
  23223. const id = o;
  23224. return toBlobInfo({
  23225. id,
  23226. name,
  23227. filename,
  23228. blob: blob,
  23229. base64: base64,
  23230. });
  23231. } else if (isObject(o)) {
  23232. return toBlobInfo(o);
  23233. } else {
  23234. throw new Error("Unknown input type");
  23235. }
  23236. };
  23237. const toBlobInfo = (o) => {
  23238. if (!o.blob || !o.base64) {
  23239. throw new Error(
  23240. "blob and base64 representations of the image are required for BlobInfo to be created"
  23241. );
  23242. }
  23243. const id = o.id || uuid("blobid");
  23244. const name = o.name || id;
  23245. const blob = o.blob;
  23246. return {
  23247. id: constant(id),
  23248. name: constant(name),
  23249. filename: constant(o.filename || name + "." + mimeToExt(blob.type)),
  23250. blob: constant(blob),
  23251. base64: constant(o.base64),
  23252. blobUri: constant(o.blobUri || URL.createObjectURL(blob)),
  23253. uri: constant(o.uri),
  23254. };
  23255. };
  23256. const add = (blobInfo) => {
  23257. if (!get(blobInfo.id())) {
  23258. cache.push(blobInfo);
  23259. }
  23260. };
  23261. const findFirst = (predicate) => find$2(cache, predicate).getOrUndefined();
  23262. const get = (id) =>
  23263. findFirst((cachedBlobInfo) => cachedBlobInfo.id() === id);
  23264. const getByUri = (blobUri) =>
  23265. findFirst((blobInfo) => blobInfo.blobUri() === blobUri);
  23266. const getByData = (base64, type) =>
  23267. findFirst(
  23268. (blobInfo) =>
  23269. blobInfo.base64() === base64 && blobInfo.blob().type === type
  23270. );
  23271. const removeByUri = (blobUri) => {
  23272. cache = filter$5(cache, (blobInfo) => {
  23273. if (blobInfo.blobUri() === blobUri) {
  23274. URL.revokeObjectURL(blobInfo.blobUri());
  23275. return false;
  23276. }
  23277. return true;
  23278. });
  23279. };
  23280. const destroy = () => {
  23281. each$e(cache, (cachedBlobInfo) => {
  23282. URL.revokeObjectURL(cachedBlobInfo.blobUri());
  23283. });
  23284. cache = [];
  23285. };
  23286. return {
  23287. create,
  23288. add,
  23289. get,
  23290. getByUri,
  23291. getByData,
  23292. findFirst,
  23293. removeByUri,
  23294. destroy,
  23295. };
  23296. };
  23297. const Uploader = (uploadStatus, settings) => {
  23298. const pendingPromises = {};
  23299. const pathJoin = (path1, path2) => {
  23300. if (path1) {
  23301. return path1.replace(/\/$/, "") + "/" + path2.replace(/^\//, "");
  23302. }
  23303. return path2;
  23304. };
  23305. const defaultHandler = (blobInfo, progress) =>
  23306. new Promise((success, failure) => {
  23307. const xhr = new XMLHttpRequest();
  23308. xhr.open("POST", settings.url);
  23309. xhr.withCredentials = settings.credentials;
  23310. xhr.upload.onprogress = (e) => {
  23311. progress((e.loaded / e.total) * 100);
  23312. };
  23313. xhr.onerror = () => {
  23314. failure(
  23315. "Image upload failed due to a XHR Transport error. Code: " +
  23316. xhr.status
  23317. );
  23318. };
  23319. xhr.onload = () => {
  23320. if (xhr.status < 200 || xhr.status >= 300) {
  23321. failure("HTTP Error: " + xhr.status);
  23322. return;
  23323. }
  23324. const json = JSON.parse(xhr.responseText);
  23325. if (!json || !isString(json.location)) {
  23326. failure("Invalid JSON: " + xhr.responseText);
  23327. return;
  23328. }
  23329. success(pathJoin(settings.basePath, json.location));
  23330. };
  23331. const formData = new FormData();
  23332. formData.append("file", blobInfo.blob(), blobInfo.filename());
  23333. xhr.send(formData);
  23334. });
  23335. const uploadHandler = isFunction(settings.handler)
  23336. ? settings.handler
  23337. : defaultHandler;
  23338. const noUpload = () =>
  23339. new Promise((resolve) => {
  23340. resolve([]);
  23341. });
  23342. const handlerSuccess = (blobInfo, url) => ({
  23343. url,
  23344. blobInfo,
  23345. status: true,
  23346. });
  23347. const handlerFailure = (blobInfo, error) => ({
  23348. url: "",
  23349. blobInfo,
  23350. status: false,
  23351. error,
  23352. });
  23353. const resolvePending = (blobUri, result) => {
  23354. Tools.each(pendingPromises[blobUri], (resolve) => {
  23355. resolve(result);
  23356. });
  23357. delete pendingPromises[blobUri];
  23358. };
  23359. const uploadBlobInfo = (blobInfo, handler, openNotification) => {
  23360. uploadStatus.markPending(blobInfo.blobUri());
  23361. return new Promise((resolve) => {
  23362. let notification;
  23363. let progress;
  23364. try {
  23365. const closeNotification = () => {
  23366. if (notification) {
  23367. notification.close();
  23368. progress = noop;
  23369. }
  23370. };
  23371. const success = (url) => {
  23372. closeNotification();
  23373. uploadStatus.markUploaded(blobInfo.blobUri(), url);
  23374. resolvePending(blobInfo.blobUri(), handlerSuccess(blobInfo, url));
  23375. resolve(handlerSuccess(blobInfo, url));
  23376. };
  23377. const failure = (error) => {
  23378. closeNotification();
  23379. uploadStatus.removeFailed(blobInfo.blobUri());
  23380. resolvePending(blobInfo.blobUri(), handlerFailure(blobInfo, error));
  23381. resolve(handlerFailure(blobInfo, error));
  23382. };
  23383. progress = (percent) => {
  23384. if (percent < 0 || percent > 100) {
  23385. return;
  23386. }
  23387. Optional.from(notification)
  23388. .orThunk(() => Optional.from(openNotification).map(apply$1))
  23389. .each((n) => {
  23390. notification = n;
  23391. n.progressBar.value(percent);
  23392. });
  23393. };
  23394. handler(blobInfo, progress).then(success, (err) => {
  23395. failure(isString(err) ? { message: err } : err);
  23396. });
  23397. } catch (ex) {
  23398. resolve(handlerFailure(blobInfo, ex));
  23399. }
  23400. });
  23401. };
  23402. const isDefaultHandler = (handler) => handler === defaultHandler;
  23403. const pendingUploadBlobInfo = (blobInfo) => {
  23404. const blobUri = blobInfo.blobUri();
  23405. return new Promise((resolve) => {
  23406. pendingPromises[blobUri] = pendingPromises[blobUri] || [];
  23407. pendingPromises[blobUri].push(resolve);
  23408. });
  23409. };
  23410. const uploadBlobs = (blobInfos, openNotification) => {
  23411. blobInfos = Tools.grep(
  23412. blobInfos,
  23413. (blobInfo) => !uploadStatus.isUploaded(blobInfo.blobUri())
  23414. );
  23415. return Promise.all(
  23416. Tools.map(blobInfos, (blobInfo) =>
  23417. uploadStatus.isPending(blobInfo.blobUri())
  23418. ? pendingUploadBlobInfo(blobInfo)
  23419. : uploadBlobInfo(blobInfo, uploadHandler, openNotification)
  23420. )
  23421. );
  23422. };
  23423. const upload = (blobInfos, openNotification) =>
  23424. !settings.url && isDefaultHandler(uploadHandler)
  23425. ? noUpload()
  23426. : uploadBlobs(blobInfos, openNotification);
  23427. return { upload };
  23428. };
  23429. const openNotification = (editor) => () =>
  23430. editor.notificationManager.open({
  23431. text: editor.translate("Image uploading..."),
  23432. type: "info",
  23433. timeout: -1,
  23434. progressBar: true,
  23435. });
  23436. const createUploader = (editor, uploadStatus) =>
  23437. Uploader(uploadStatus, {
  23438. url: getImageUploadUrl(editor),
  23439. basePath: getImageUploadBasePath(editor),
  23440. credentials: getImagesUploadCredentials(editor),
  23441. handler: getImagesUploadHandler(editor),
  23442. });
  23443. const ImageUploader = (editor) => {
  23444. const uploadStatus = UploadStatus();
  23445. const uploader = createUploader(editor, uploadStatus);
  23446. return {
  23447. upload: (blobInfos, showNotification = true) =>
  23448. uploader.upload(
  23449. blobInfos,
  23450. showNotification ? openNotification(editor) : undefined
  23451. ),
  23452. };
  23453. };
  23454. const isEmptyForPadding = (editor, element) =>
  23455. editor.dom.isEmpty(element.dom) &&
  23456. isNonNullable(editor.schema.getTextBlockElements()[name(element)]);
  23457. const addPaddingToEmpty = (editor) => (element) => {
  23458. if (isEmptyForPadding(editor, element)) {
  23459. append$1(element, SugarElement.fromHtml('<br data-mce-bogus="1" />'));
  23460. }
  23461. };
  23462. const EditorUpload = (editor) => {
  23463. const blobCache = BlobCache();
  23464. let uploader, imageScanner;
  23465. const uploadStatus = UploadStatus();
  23466. const urlFilters = [];
  23467. const aliveGuard = (callback) => {
  23468. return (result) => {
  23469. if (editor.selection) {
  23470. return callback(result);
  23471. }
  23472. return [];
  23473. };
  23474. };
  23475. const cacheInvalidator = (url) =>
  23476. url + (url.indexOf("?") === -1 ? "?" : "&") + new Date().getTime();
  23477. const replaceString = (content, search, replace) => {
  23478. let index = 0;
  23479. do {
  23480. index = content.indexOf(search, index);
  23481. if (index !== -1) {
  23482. content =
  23483. content.substring(0, index) +
  23484. replace +
  23485. content.substr(index + search.length);
  23486. index += replace.length - search.length + 1;
  23487. }
  23488. } while (index !== -1);
  23489. return content;
  23490. };
  23491. const replaceImageUrl = (content, targetUrl, replacementUrl) => {
  23492. const replacementString = `src="${replacementUrl}"${
  23493. replacementUrl === Env.transparentSrc ? ' data-mce-placeholder="1"' : ""
  23494. }`;
  23495. content = replaceString(content, `src="${targetUrl}"`, replacementString);
  23496. content = replaceString(
  23497. content,
  23498. 'data-mce-src="' + targetUrl + '"',
  23499. 'data-mce-src="' + replacementUrl + '"'
  23500. );
  23501. return content;
  23502. };
  23503. const replaceUrlInUndoStack = (targetUrl, replacementUrl) => {
  23504. each$e(editor.undoManager.data, (level) => {
  23505. if (level.type === "fragmented") {
  23506. level.fragments = map$3(level.fragments, (fragment) =>
  23507. replaceImageUrl(fragment, targetUrl, replacementUrl)
  23508. );
  23509. } else {
  23510. level.content = replaceImageUrl(
  23511. level.content,
  23512. targetUrl,
  23513. replacementUrl
  23514. );
  23515. }
  23516. });
  23517. };
  23518. const replaceImageUriInView = (image, resultUri) => {
  23519. const src = editor.convertURL(resultUri, "src");
  23520. replaceUrlInUndoStack(image.src, resultUri);
  23521. setAll$1(SugarElement.fromDom(image), {
  23522. src: shouldReuseFileName(editor)
  23523. ? cacheInvalidator(resultUri)
  23524. : resultUri,
  23525. "data-mce-src": src,
  23526. });
  23527. };
  23528. const uploadImages = () => {
  23529. if (!uploader) {
  23530. uploader = createUploader(editor, uploadStatus);
  23531. }
  23532. return scanForImages().then(
  23533. aliveGuard((imageInfos) => {
  23534. const blobInfos = map$3(
  23535. imageInfos,
  23536. (imageInfo) => imageInfo.blobInfo
  23537. );
  23538. return uploader.upload(blobInfos, openNotification(editor)).then(
  23539. aliveGuard((result) => {
  23540. const imagesToRemove = [];
  23541. let shouldDispatchChange = false;
  23542. const filteredResult = map$3(result, (uploadInfo, index) => {
  23543. const { blobInfo, image } = imageInfos[index];
  23544. let removed = false;
  23545. if (uploadInfo.status && shouldReplaceBlobUris(editor)) {
  23546. if (
  23547. uploadInfo.url &&
  23548. !contains$1(image.src, uploadInfo.url)
  23549. ) {
  23550. shouldDispatchChange = true;
  23551. }
  23552. blobCache.removeByUri(image.src);
  23553. if (isRtc(editor));
  23554. else {
  23555. replaceImageUriInView(image, uploadInfo.url);
  23556. }
  23557. } else if (uploadInfo.error) {
  23558. if (uploadInfo.error.remove) {
  23559. replaceUrlInUndoStack(image.src, Env.transparentSrc);
  23560. imagesToRemove.push(image);
  23561. removed = true;
  23562. }
  23563. uploadError(editor, uploadInfo.error.message);
  23564. }
  23565. return {
  23566. element: image,
  23567. status: uploadInfo.status,
  23568. uploadUri: uploadInfo.url,
  23569. blobInfo,
  23570. removed,
  23571. };
  23572. });
  23573. if (imagesToRemove.length > 0 && !isRtc(editor)) {
  23574. editor.undoManager.transact(() => {
  23575. each$e(fromDom$1(imagesToRemove), (sugarElement) => {
  23576. const parentOpt = parent(sugarElement);
  23577. remove$5(sugarElement);
  23578. parentOpt.each(addPaddingToEmpty(editor));
  23579. blobCache.removeByUri(sugarElement.dom.src);
  23580. });
  23581. });
  23582. } else if (shouldDispatchChange) {
  23583. editor.undoManager.dispatchChange();
  23584. }
  23585. return filteredResult;
  23586. })
  23587. );
  23588. })
  23589. );
  23590. };
  23591. const uploadImagesAuto = () =>
  23592. isAutomaticUploadsEnabled(editor) ? uploadImages() : Promise.resolve([]);
  23593. const isValidDataUriImage = (imgElm) =>
  23594. forall(urlFilters, (filter) => filter(imgElm));
  23595. const addFilter = (filter) => {
  23596. urlFilters.push(filter);
  23597. };
  23598. const scanForImages = () => {
  23599. if (!imageScanner) {
  23600. imageScanner = ImageScanner(uploadStatus, blobCache);
  23601. }
  23602. return imageScanner.findAll(editor.getBody(), isValidDataUriImage).then(
  23603. aliveGuard((result) => {
  23604. const filteredResult = filter$5(result, (resultItem) => {
  23605. if (isString(resultItem)) {
  23606. displayError(editor, resultItem);
  23607. return false;
  23608. } else if (resultItem.uriType === "blob") {
  23609. return false;
  23610. } else {
  23611. return true;
  23612. }
  23613. });
  23614. if (isRtc(editor));
  23615. else {
  23616. each$e(filteredResult, (resultItem) => {
  23617. replaceUrlInUndoStack(
  23618. resultItem.image.src,
  23619. resultItem.blobInfo.blobUri()
  23620. );
  23621. resultItem.image.src = resultItem.blobInfo.blobUri();
  23622. resultItem.image.removeAttribute("data-mce-src");
  23623. });
  23624. }
  23625. return filteredResult;
  23626. })
  23627. );
  23628. };
  23629. const destroy = () => {
  23630. blobCache.destroy();
  23631. uploadStatus.destroy();
  23632. imageScanner = uploader = null;
  23633. };
  23634. const replaceBlobUris = (content) => {
  23635. return content.replace(/src="(blob:[^"]+)"/g, (match, blobUri) => {
  23636. const resultUri = uploadStatus.getResultUri(blobUri);
  23637. if (resultUri) {
  23638. return 'src="' + resultUri + '"';
  23639. }
  23640. let blobInfo = blobCache.getByUri(blobUri);
  23641. if (!blobInfo) {
  23642. blobInfo = foldl(
  23643. editor.editorManager.get(),
  23644. (result, editor) => {
  23645. return (
  23646. result ||
  23647. (editor.editorUpload &&
  23648. editor.editorUpload.blobCache.getByUri(blobUri))
  23649. );
  23650. },
  23651. undefined
  23652. );
  23653. }
  23654. if (blobInfo) {
  23655. const blob = blobInfo.blob();
  23656. return (
  23657. 'src="data:' + blob.type + ";base64," + blobInfo.base64() + '"'
  23658. );
  23659. }
  23660. return match;
  23661. });
  23662. };
  23663. editor.on("SetContent", () => {
  23664. if (isAutomaticUploadsEnabled(editor)) {
  23665. uploadImagesAuto();
  23666. } else {
  23667. scanForImages();
  23668. }
  23669. });
  23670. editor.on("RawSaveContent", (e) => {
  23671. e.content = replaceBlobUris(e.content);
  23672. });
  23673. editor.on("GetContent", (e) => {
  23674. if (e.source_view || e.format === "raw" || e.format === "tree") {
  23675. return;
  23676. }
  23677. e.content = replaceBlobUris(e.content);
  23678. });
  23679. editor.on("PostRender", () => {
  23680. editor.parser.addNodeFilter("img", (images) => {
  23681. each$e(images, (img) => {
  23682. const src = img.attr("src");
  23683. if (!src || blobCache.getByUri(src)) {
  23684. return;
  23685. }
  23686. const resultUri = uploadStatus.getResultUri(src);
  23687. if (resultUri) {
  23688. img.attr("src", resultUri);
  23689. }
  23690. });
  23691. });
  23692. });
  23693. return {
  23694. blobCache,
  23695. addFilter,
  23696. uploadImages,
  23697. uploadImagesAuto,
  23698. scanForImages,
  23699. destroy,
  23700. };
  23701. };
  23702. const get$1 = (editor) => {
  23703. const dom = editor.dom;
  23704. const schemaType = editor.schema.type;
  23705. const formats = {
  23706. valigntop: [
  23707. {
  23708. selector: "td,th",
  23709. styles: { verticalAlign: "top" },
  23710. },
  23711. ],
  23712. valignmiddle: [
  23713. {
  23714. selector: "td,th",
  23715. styles: { verticalAlign: "middle" },
  23716. },
  23717. ],
  23718. valignbottom: [
  23719. {
  23720. selector: "td,th",
  23721. styles: { verticalAlign: "bottom" },
  23722. },
  23723. ],
  23724. alignleft: [
  23725. {
  23726. selector: "figure.image",
  23727. collapsed: false,
  23728. classes: "align-left",
  23729. ceFalseOverride: true,
  23730. preview: "font-family font-size",
  23731. },
  23732. {
  23733. selector: "figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre",
  23734. styles: { textAlign: "left" },
  23735. inherit: false,
  23736. preview: false,
  23737. },
  23738. {
  23739. selector: "img,audio,video",
  23740. collapsed: false,
  23741. styles: { float: "left" },
  23742. preview: "font-family font-size",
  23743. },
  23744. {
  23745. selector: "table",
  23746. collapsed: false,
  23747. styles: {
  23748. marginLeft: "0px",
  23749. marginRight: "auto",
  23750. },
  23751. onformat: (table) => {
  23752. dom.setStyle(table, "float", null);
  23753. },
  23754. preview: "font-family font-size",
  23755. },
  23756. {
  23757. selector: ".mce-preview-object,[data-ephox-embed-iri]",
  23758. ceFalseOverride: true,
  23759. styles: { float: "left" },
  23760. },
  23761. ],
  23762. aligncenter: [
  23763. {
  23764. selector: "figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre",
  23765. styles: { textAlign: "center" },
  23766. inherit: false,
  23767. preview: "font-family font-size",
  23768. },
  23769. {
  23770. selector: "figure.image",
  23771. collapsed: false,
  23772. classes: "align-center",
  23773. ceFalseOverride: true,
  23774. preview: "font-family font-size",
  23775. },
  23776. {
  23777. selector: "img,audio,video",
  23778. collapsed: false,
  23779. styles: {
  23780. display: "block",
  23781. marginLeft: "auto",
  23782. marginRight: "auto",
  23783. },
  23784. preview: false,
  23785. },
  23786. {
  23787. selector: "table",
  23788. collapsed: false,
  23789. styles: {
  23790. marginLeft: "auto",
  23791. marginRight: "auto",
  23792. },
  23793. preview: "font-family font-size",
  23794. },
  23795. {
  23796. selector: ".mce-preview-object",
  23797. ceFalseOverride: true,
  23798. styles: {
  23799. display: "table",
  23800. marginLeft: "auto",
  23801. marginRight: "auto",
  23802. },
  23803. preview: false,
  23804. },
  23805. {
  23806. selector: "[data-ephox-embed-iri]",
  23807. ceFalseOverride: true,
  23808. styles: {
  23809. marginLeft: "auto",
  23810. marginRight: "auto",
  23811. },
  23812. preview: false,
  23813. },
  23814. ],
  23815. alignright: [
  23816. {
  23817. selector: "figure.image",
  23818. collapsed: false,
  23819. classes: "align-right",
  23820. ceFalseOverride: true,
  23821. preview: "font-family font-size",
  23822. },
  23823. {
  23824. selector: "figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre",
  23825. styles: { textAlign: "right" },
  23826. inherit: false,
  23827. preview: "font-family font-size",
  23828. },
  23829. {
  23830. selector: "img,audio,video",
  23831. collapsed: false,
  23832. styles: { float: "right" },
  23833. preview: "font-family font-size",
  23834. },
  23835. {
  23836. selector: "table",
  23837. collapsed: false,
  23838. styles: {
  23839. marginRight: "0px",
  23840. marginLeft: "auto",
  23841. },
  23842. onformat: (table) => {
  23843. dom.setStyle(table, "float", null);
  23844. },
  23845. preview: "font-family font-size",
  23846. },
  23847. {
  23848. selector: ".mce-preview-object,[data-ephox-embed-iri]",
  23849. ceFalseOverride: true,
  23850. styles: { float: "right" },
  23851. preview: false,
  23852. },
  23853. ],
  23854. alignjustify: [
  23855. {
  23856. selector: "figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li,pre",
  23857. styles: { textAlign: "justify" },
  23858. inherit: false,
  23859. preview: "font-family font-size",
  23860. },
  23861. ],
  23862. bold: [
  23863. {
  23864. inline: "strong",
  23865. remove: "all",
  23866. preserve_attributes: ["class", "style"],
  23867. },
  23868. {
  23869. inline: "span",
  23870. styles: { fontWeight: "bold" },
  23871. },
  23872. {
  23873. inline: "b",
  23874. remove: "all",
  23875. preserve_attributes: ["class", "style"],
  23876. },
  23877. ],
  23878. italic: [
  23879. {
  23880. inline: "em",
  23881. remove: "all",
  23882. preserve_attributes: ["class", "style"],
  23883. },
  23884. {
  23885. inline: "span",
  23886. styles: { fontStyle: "italic" },
  23887. },
  23888. {
  23889. inline: "i",
  23890. remove: "all",
  23891. preserve_attributes: ["class", "style"],
  23892. },
  23893. ],
  23894. underline: [
  23895. {
  23896. inline: "span",
  23897. styles: { textDecoration: "underline" },
  23898. exact: true,
  23899. },
  23900. {
  23901. inline: "u",
  23902. remove: "all",
  23903. preserve_attributes: ["class", "style"],
  23904. },
  23905. ],
  23906. strikethrough: (() => {
  23907. const span = {
  23908. inline: "span",
  23909. styles: { textDecoration: "line-through" },
  23910. exact: true,
  23911. };
  23912. const strike = {
  23913. inline: "strike",
  23914. remove: "all",
  23915. preserve_attributes: ["class", "style"],
  23916. };
  23917. const s = {
  23918. inline: "s",
  23919. remove: "all",
  23920. preserve_attributes: ["class", "style"],
  23921. };
  23922. return schemaType !== "html4" ? [s, span, strike] : [span, s, strike];
  23923. })(),
  23924. forecolor: {
  23925. inline: "span",
  23926. styles: { color: "%value" },
  23927. links: true,
  23928. remove_similar: true,
  23929. clear_child_styles: true,
  23930. },
  23931. hilitecolor: {
  23932. inline: "span",
  23933. styles: { backgroundColor: "%value" },
  23934. links: true,
  23935. remove_similar: true,
  23936. clear_child_styles: true,
  23937. },
  23938. fontname: {
  23939. inline: "span",
  23940. toggle: false,
  23941. styles: { fontFamily: "%value" },
  23942. clear_child_styles: true,
  23943. },
  23944. fontsize: {
  23945. inline: "span",
  23946. toggle: false,
  23947. styles: { fontSize: "%value" },
  23948. clear_child_styles: true,
  23949. },
  23950. lineheight: {
  23951. selector: "h1,h2,h3,h4,h5,h6,p,li,td,th,div",
  23952. styles: { lineHeight: "%value" },
  23953. },
  23954. fontsize_class: {
  23955. inline: "span",
  23956. attributes: { class: "%value" },
  23957. },
  23958. blockquote: {
  23959. block: "blockquote",
  23960. wrapper: true,
  23961. remove: "all",
  23962. },
  23963. subscript: { inline: "sub" },
  23964. superscript: { inline: "sup" },
  23965. code: { inline: "code" },
  23966. link: {
  23967. inline: "a",
  23968. selector: "a",
  23969. remove: "all",
  23970. split: true,
  23971. deep: true,
  23972. onmatch: (node, _fmt, _itemName) => {
  23973. return isElement$6(node) && node.hasAttribute("href");
  23974. },
  23975. onformat: (elm, _fmt, vars) => {
  23976. Tools.each(vars, (value, key) => {
  23977. dom.setAttrib(elm, key, value);
  23978. });
  23979. },
  23980. },
  23981. lang: {
  23982. inline: "span",
  23983. clear_child_styles: true,
  23984. remove_similar: true,
  23985. attributes: {
  23986. lang: "%value",
  23987. "data-mce-lang": (vars) => {
  23988. var _a;
  23989. return (_a =
  23990. vars === null || vars === void 0 ? void 0 : vars.customValue) !==
  23991. null && _a !== void 0
  23992. ? _a
  23993. : null;
  23994. },
  23995. },
  23996. },
  23997. removeformat: [
  23998. {
  23999. selector:
  24000. "b,strong,em,i,font,u,strike,s,sub,sup,dfn,code,samp,kbd,var,cite,mark,q,del,ins,small",
  24001. remove: "all",
  24002. split: true,
  24003. expand: false,
  24004. block_expand: true,
  24005. deep: true,
  24006. },
  24007. {
  24008. selector: "span",
  24009. attributes: ["style", "class"],
  24010. remove: "empty",
  24011. split: true,
  24012. expand: false,
  24013. deep: true,
  24014. },
  24015. {
  24016. selector: "*",
  24017. attributes: ["style", "class"],
  24018. split: false,
  24019. expand: false,
  24020. deep: true,
  24021. },
  24022. ],
  24023. };
  24024. Tools.each(
  24025. "p h1 h2 h3 h4 h5 h6 div address pre dt dd samp".split(/\s/),
  24026. (name) => {
  24027. formats[name] = {
  24028. block: name,
  24029. remove: "all",
  24030. };
  24031. }
  24032. );
  24033. return formats;
  24034. };
  24035. const genericBase = {
  24036. remove_similar: true,
  24037. inherit: false,
  24038. };
  24039. const cellBase = {
  24040. selector: "td,th",
  24041. ...genericBase,
  24042. };
  24043. const cellFormats = {
  24044. tablecellbackgroundcolor: {
  24045. styles: { backgroundColor: "%value" },
  24046. ...cellBase,
  24047. },
  24048. tablecellverticalalign: {
  24049. styles: { "vertical-align": "%value" },
  24050. ...cellBase,
  24051. },
  24052. tablecellbordercolor: {
  24053. styles: { borderColor: "%value" },
  24054. ...cellBase,
  24055. },
  24056. tablecellclass: {
  24057. classes: ["%value"],
  24058. ...cellBase,
  24059. },
  24060. tableclass: {
  24061. selector: "table",
  24062. classes: ["%value"],
  24063. ...genericBase,
  24064. },
  24065. tablecellborderstyle: {
  24066. styles: { borderStyle: "%value" },
  24067. ...cellBase,
  24068. },
  24069. tablecellborderwidth: {
  24070. styles: { borderWidth: "%value" },
  24071. ...cellBase,
  24072. },
  24073. };
  24074. const get = constant(cellFormats);
  24075. const FormatRegistry = (editor) => {
  24076. const formats = {};
  24077. const get$2 = (name) => (isNonNullable(name) ? formats[name] : formats);
  24078. const has = (name) => has$2(formats, name);
  24079. const register = (name, format) => {
  24080. if (name) {
  24081. if (!isString(name)) {
  24082. each$d(name, (format, name) => {
  24083. register(name, format);
  24084. });
  24085. } else {
  24086. if (!isArray$1(format)) {
  24087. format = [format];
  24088. }
  24089. each$e(format, (format) => {
  24090. if (isUndefined(format.deep)) {
  24091. format.deep = !isSelectorFormat(format);
  24092. }
  24093. if (isUndefined(format.split)) {
  24094. format.split =
  24095. !isSelectorFormat(format) || isInlineFormat(format);
  24096. }
  24097. if (
  24098. isUndefined(format.remove) &&
  24099. isSelectorFormat(format) &&
  24100. !isInlineFormat(format)
  24101. ) {
  24102. format.remove = "none";
  24103. }
  24104. if (isSelectorFormat(format) && isInlineFormat(format)) {
  24105. format.mixed = true;
  24106. format.block_expand = true;
  24107. }
  24108. if (isString(format.classes)) {
  24109. format.classes = format.classes.split(/\s+/);
  24110. }
  24111. });
  24112. formats[name] = format;
  24113. }
  24114. }
  24115. };
  24116. const unregister = (name) => {
  24117. if (name && formats[name]) {
  24118. delete formats[name];
  24119. }
  24120. return formats;
  24121. };
  24122. register(get$1(editor));
  24123. register(get());
  24124. register(getFormats(editor));
  24125. return {
  24126. get: get$2,
  24127. has,
  24128. register,
  24129. unregister,
  24130. };
  24131. };
  24132. const each$3 = Tools.each;
  24133. const dom = DOMUtils.DOM;
  24134. const isPreviewItem = (item) => isNonNullable(item) && isObject(item);
  24135. const parsedSelectorToHtml = (ancestry, editor) => {
  24136. const schema = (editor && editor.schema) || Schema({});
  24137. const decorate = (elm, item) => {
  24138. if (item.classes.length > 0) {
  24139. dom.addClass(elm, item.classes.join(" "));
  24140. }
  24141. dom.setAttribs(elm, item.attrs);
  24142. };
  24143. const createElement = (sItem) => {
  24144. const item = isString(sItem)
  24145. ? {
  24146. name: sItem,
  24147. classes: [],
  24148. attrs: {},
  24149. }
  24150. : sItem;
  24151. const elm = dom.create(item.name);
  24152. decorate(elm, item);
  24153. return elm;
  24154. };
  24155. const getRequiredParent = (elm, candidate) => {
  24156. const elmRule = schema.getElementRule(elm.nodeName.toLowerCase());
  24157. const parentsRequired =
  24158. elmRule === null || elmRule === void 0
  24159. ? void 0
  24160. : elmRule.parentsRequired;
  24161. if (parentsRequired && parentsRequired.length) {
  24162. return candidate && contains$2(parentsRequired, candidate)
  24163. ? candidate
  24164. : parentsRequired[0];
  24165. } else {
  24166. return false;
  24167. }
  24168. };
  24169. const wrapInHtml = (elm, ancestors, siblings) => {
  24170. let parentCandidate;
  24171. const ancestor = ancestors[0];
  24172. const ancestorName = isPreviewItem(ancestor) ? ancestor.name : undefined;
  24173. const parentRequired = getRequiredParent(elm, ancestorName);
  24174. if (parentRequired) {
  24175. if (ancestorName === parentRequired) {
  24176. parentCandidate = ancestor;
  24177. ancestors = ancestors.slice(1);
  24178. } else {
  24179. parentCandidate = parentRequired;
  24180. }
  24181. } else if (ancestor) {
  24182. parentCandidate = ancestor;
  24183. ancestors = ancestors.slice(1);
  24184. } else if (!siblings) {
  24185. return elm;
  24186. }
  24187. const parent = parentCandidate
  24188. ? createElement(parentCandidate)
  24189. : dom.create("div");
  24190. parent.appendChild(elm);
  24191. if (siblings) {
  24192. Tools.each(siblings, (sibling) => {
  24193. const siblingElm = createElement(sibling);
  24194. parent.insertBefore(siblingElm, elm);
  24195. });
  24196. }
  24197. const parentSiblings = isPreviewItem(parentCandidate)
  24198. ? parentCandidate.siblings
  24199. : undefined;
  24200. return wrapInHtml(parent, ancestors, parentSiblings);
  24201. };
  24202. const fragment = dom.create("div");
  24203. if (ancestry.length > 0) {
  24204. const item = ancestry[0];
  24205. const elm = createElement(item);
  24206. const siblings = isPreviewItem(item) ? item.siblings : undefined;
  24207. fragment.appendChild(wrapInHtml(elm, ancestry.slice(1), siblings));
  24208. }
  24209. return fragment;
  24210. };
  24211. const parseSelectorItem = (item) => {
  24212. item = Tools.trim(item);
  24213. let tagName = "div";
  24214. const obj = {
  24215. name: tagName,
  24216. classes: [],
  24217. attrs: {},
  24218. selector: item,
  24219. };
  24220. if (item !== "*") {
  24221. tagName = item.replace(
  24222. /(?:([#\.]|::?)([\w\-]+)|(\[)([^\]]+)\]?)/g,
  24223. ($0, $1, $2, $3, $4) => {
  24224. switch ($1) {
  24225. case "#":
  24226. obj.attrs.id = $2;
  24227. break;
  24228. case ".":
  24229. obj.classes.push($2);
  24230. break;
  24231. case ":":
  24232. if (
  24233. Tools.inArray(
  24234. "checked disabled enabled read-only required".split(" "),
  24235. $2
  24236. ) !== -1
  24237. ) {
  24238. obj.attrs[$2] = $2;
  24239. }
  24240. break;
  24241. }
  24242. if ($3 === "[") {
  24243. const m = $4.match(/([\w\-]+)(?:\=\"([^\"]+))?/);
  24244. if (m) {
  24245. obj.attrs[m[1]] = m[2];
  24246. }
  24247. }
  24248. return "";
  24249. }
  24250. );
  24251. }
  24252. obj.name = tagName || "div";
  24253. return obj;
  24254. };
  24255. const parseSelector = (selector) => {
  24256. if (!isString(selector)) {
  24257. return [];
  24258. }
  24259. selector = selector.split(/\s*,\s*/)[0];
  24260. selector = selector.replace(/\s*(~\+|~|\+|>)\s*/g, "$1");
  24261. return Tools.map(selector.split(/(?:>|\s+(?![^\[\]]+\]))/), (item) => {
  24262. const siblings = Tools.map(item.split(/(?:~\+|~|\+)/), parseSelectorItem);
  24263. const obj = siblings.pop();
  24264. if (siblings.length) {
  24265. obj.siblings = siblings;
  24266. }
  24267. return obj;
  24268. }).reverse();
  24269. };
  24270. const getCssText = (editor, format) => {
  24271. let previewCss = "";
  24272. let previewStyles = getPreviewStyles(editor);
  24273. if (previewStyles === "") {
  24274. return "";
  24275. }
  24276. const removeVars = (val) => {
  24277. return isString(val) ? val.replace(/%(\w+)/g, "") : "";
  24278. };
  24279. const getComputedStyle = (name, elm) => {
  24280. return dom.getStyle(
  24281. elm !== null && elm !== void 0 ? elm : editor.getBody(),
  24282. name,
  24283. true
  24284. );
  24285. };
  24286. if (isString(format)) {
  24287. const formats = editor.formatter.get(format);
  24288. if (!formats) {
  24289. return "";
  24290. }
  24291. format = formats[0];
  24292. }
  24293. if ("preview" in format) {
  24294. const preview = format.preview;
  24295. if (preview === false) {
  24296. return "";
  24297. } else {
  24298. previewStyles = preview || previewStyles;
  24299. }
  24300. }
  24301. let name = format.block || format.inline || "span";
  24302. let previewFrag;
  24303. const items = parseSelector(format.selector);
  24304. if (items.length > 0) {
  24305. if (!items[0].name) {
  24306. items[0].name = name;
  24307. }
  24308. name = format.selector;
  24309. previewFrag = parsedSelectorToHtml(items, editor);
  24310. } else {
  24311. previewFrag = parsedSelectorToHtml([name], editor);
  24312. }
  24313. const previewElm =
  24314. dom.select(name, previewFrag)[0] || previewFrag.firstChild;
  24315. each$3(format.styles, (value, name) => {
  24316. const newValue = removeVars(value);
  24317. if (newValue) {
  24318. dom.setStyle(previewElm, name, newValue);
  24319. }
  24320. });
  24321. each$3(format.attributes, (value, name) => {
  24322. const newValue = removeVars(value);
  24323. if (newValue) {
  24324. dom.setAttrib(previewElm, name, newValue);
  24325. }
  24326. });
  24327. each$3(format.classes, (value) => {
  24328. const newValue = removeVars(value);
  24329. if (!dom.hasClass(previewElm, newValue)) {
  24330. dom.addClass(previewElm, newValue);
  24331. }
  24332. });
  24333. editor.dispatch("PreviewFormats");
  24334. dom.setStyles(previewFrag, {
  24335. position: "absolute",
  24336. left: -65535,
  24337. });
  24338. editor.getBody().appendChild(previewFrag);
  24339. const rawParentFontSize = getComputedStyle("fontSize");
  24340. const parentFontSize = /px$/.test(rawParentFontSize)
  24341. ? parseInt(rawParentFontSize, 10)
  24342. : 0;
  24343. each$3(previewStyles.split(" "), (name) => {
  24344. let value = getComputedStyle(name, previewElm);
  24345. if (
  24346. name === "background-color" &&
  24347. /transparent|rgba\s*\([^)]+,\s*0\)/.test(value)
  24348. ) {
  24349. value = getComputedStyle(name);
  24350. if (rgbaToHexString(value).toLowerCase() === "#ffffff") {
  24351. return;
  24352. }
  24353. }
  24354. if (name === "color") {
  24355. if (rgbaToHexString(value).toLowerCase() === "#000000") {
  24356. return;
  24357. }
  24358. }
  24359. if (name === "font-size") {
  24360. if (/em|%$/.test(value)) {
  24361. if (parentFontSize === 0) {
  24362. return;
  24363. }
  24364. const numValue = parseFloat(value) / (/%$/.test(value) ? 100 : 1);
  24365. value = numValue * parentFontSize + "px";
  24366. }
  24367. }
  24368. if (name === "border" && value) {
  24369. previewCss += "padding:0 2px;";
  24370. }
  24371. previewCss += name + ":" + value + ";";
  24372. });
  24373. editor.dispatch("AfterPreviewFormats");
  24374. dom.remove(previewFrag);
  24375. return previewCss;
  24376. };
  24377. const setup$r = (editor) => {
  24378. editor.addShortcut("meta+b", "", "Bold");
  24379. editor.addShortcut("meta+i", "", "Italic");
  24380. editor.addShortcut("meta+u", "", "Underline");
  24381. for (let i = 1; i <= 6; i++) {
  24382. editor.addShortcut("access+" + i, "", ["FormatBlock", false, "h" + i]);
  24383. }
  24384. editor.addShortcut("access+7", "", ["FormatBlock", false, "p"]);
  24385. editor.addShortcut("access+8", "", ["FormatBlock", false, "div"]);
  24386. editor.addShortcut("access+9", "", ["FormatBlock", false, "address"]);
  24387. };
  24388. const Formatter = (editor) => {
  24389. const formats = FormatRegistry(editor);
  24390. const formatChangeState = Cell({});
  24391. setup$r(editor);
  24392. setup$u(editor);
  24393. if (!isRtc(editor)) {
  24394. setup$t(formatChangeState, editor);
  24395. }
  24396. return {
  24397. get: formats.get,
  24398. has: formats.has,
  24399. register: formats.register,
  24400. unregister: formats.unregister,
  24401. apply: (name, vars, node) => {
  24402. applyFormat(editor, name, vars, node);
  24403. },
  24404. remove: (name, vars, node, similar) => {
  24405. removeFormat(editor, name, vars, node, similar);
  24406. },
  24407. toggle: (name, vars, node) => {
  24408. toggleFormat(editor, name, vars, node);
  24409. },
  24410. match: (name, vars, node, similar) =>
  24411. matchFormat(editor, name, vars, node, similar),
  24412. closest: (names) => closestFormat(editor, names),
  24413. matchAll: (names, vars) => matchAllFormats(editor, names, vars),
  24414. matchNode: (node, name, vars, similar) =>
  24415. matchNodeFormat(editor, node, name, vars, similar),
  24416. canApply: (name) => canApplyFormat(editor, name),
  24417. formatChanged: (formats, callback, similar, vars) =>
  24418. formatChanged(
  24419. editor,
  24420. formatChangeState,
  24421. formats,
  24422. callback,
  24423. similar,
  24424. vars
  24425. ),
  24426. getCssText: curry(getCssText, editor),
  24427. };
  24428. };
  24429. const shouldIgnoreCommand = (cmd) => {
  24430. switch (cmd.toLowerCase()) {
  24431. case "undo":
  24432. case "redo":
  24433. case "mcefocus":
  24434. return true;
  24435. default:
  24436. return false;
  24437. }
  24438. };
  24439. const registerEvents = (editor, undoManager, locks) => {
  24440. const isFirstTypedCharacter = Cell(false);
  24441. const addNonTypingUndoLevel = (e) => {
  24442. setTyping(undoManager, false, locks);
  24443. undoManager.add({}, e);
  24444. };
  24445. editor.on("init", () => {
  24446. undoManager.add();
  24447. });
  24448. editor.on("BeforeExecCommand", (e) => {
  24449. const cmd = e.command;
  24450. if (!shouldIgnoreCommand(cmd)) {
  24451. endTyping(undoManager, locks);
  24452. undoManager.beforeChange();
  24453. }
  24454. });
  24455. editor.on("ExecCommand", (e) => {
  24456. const cmd = e.command;
  24457. if (!shouldIgnoreCommand(cmd)) {
  24458. addNonTypingUndoLevel(e);
  24459. }
  24460. });
  24461. editor.on("ObjectResizeStart cut", () => {
  24462. undoManager.beforeChange();
  24463. });
  24464. editor.on("SaveContent ObjectResized blur", addNonTypingUndoLevel);
  24465. editor.on("dragend", addNonTypingUndoLevel);
  24466. editor.on("keyup", (e) => {
  24467. const keyCode = e.keyCode;
  24468. if (e.isDefaultPrevented()) {
  24469. return;
  24470. }
  24471. const isMeta = Env.os.isMacOS() && e.key === "Meta";
  24472. if (
  24473. (keyCode >= 33 && keyCode <= 36) ||
  24474. (keyCode >= 37 && keyCode <= 40) ||
  24475. keyCode === 45 ||
  24476. e.ctrlKey ||
  24477. isMeta
  24478. ) {
  24479. addNonTypingUndoLevel();
  24480. editor.nodeChanged();
  24481. }
  24482. if (keyCode === 46 || keyCode === 8) {
  24483. editor.nodeChanged();
  24484. }
  24485. if (
  24486. isFirstTypedCharacter.get() &&
  24487. undoManager.typing &&
  24488. !isEq$1(createFromEditor(editor), undoManager.data[0])
  24489. ) {
  24490. if (!editor.isDirty()) {
  24491. editor.setDirty(true);
  24492. }
  24493. editor.dispatch("TypingUndo");
  24494. isFirstTypedCharacter.set(false);
  24495. editor.nodeChanged();
  24496. }
  24497. });
  24498. editor.on("keydown", (e) => {
  24499. const keyCode = e.keyCode;
  24500. if (e.isDefaultPrevented()) {
  24501. return;
  24502. }
  24503. if (
  24504. (keyCode >= 33 && keyCode <= 36) ||
  24505. (keyCode >= 37 && keyCode <= 40) ||
  24506. keyCode === 45
  24507. ) {
  24508. if (undoManager.typing) {
  24509. addNonTypingUndoLevel(e);
  24510. }
  24511. return;
  24512. }
  24513. const modKey = (e.ctrlKey && !e.altKey) || e.metaKey;
  24514. if (
  24515. (keyCode < 16 || keyCode > 20) &&
  24516. keyCode !== 224 &&
  24517. keyCode !== 91 &&
  24518. !undoManager.typing &&
  24519. !modKey
  24520. ) {
  24521. undoManager.beforeChange();
  24522. setTyping(undoManager, true, locks);
  24523. undoManager.add({}, e);
  24524. isFirstTypedCharacter.set(true);
  24525. return;
  24526. }
  24527. const hasOnlyMetaOrCtrlModifier = Env.os.isMacOS()
  24528. ? e.metaKey
  24529. : e.ctrlKey && !e.altKey;
  24530. if (hasOnlyMetaOrCtrlModifier) {
  24531. undoManager.beforeChange();
  24532. }
  24533. });
  24534. editor.on("mousedown", (e) => {
  24535. if (undoManager.typing) {
  24536. addNonTypingUndoLevel(e);
  24537. }
  24538. });
  24539. const isInsertReplacementText = (event) =>
  24540. event.inputType === "insertReplacementText";
  24541. const isInsertTextDataNull = (event) =>
  24542. event.inputType === "insertText" && event.data === null;
  24543. const isInsertFromPasteOrDrop = (event) =>
  24544. event.inputType === "insertFromPaste" ||
  24545. event.inputType === "insertFromDrop";
  24546. editor.on("input", (e) => {
  24547. if (
  24548. e.inputType &&
  24549. (isInsertReplacementText(e) ||
  24550. isInsertTextDataNull(e) ||
  24551. isInsertFromPasteOrDrop(e))
  24552. ) {
  24553. addNonTypingUndoLevel(e);
  24554. }
  24555. });
  24556. editor.on("AddUndo Undo Redo ClearUndos", (e) => {
  24557. if (!e.isDefaultPrevented()) {
  24558. editor.nodeChanged();
  24559. }
  24560. });
  24561. };
  24562. const addKeyboardShortcuts = (editor) => {
  24563. editor.addShortcut("meta+z", "", "Undo");
  24564. editor.addShortcut("meta+y,meta+shift+z", "", "Redo");
  24565. };
  24566. const UndoManager = (editor) => {
  24567. const beforeBookmark = value$2();
  24568. const locks = Cell(0);
  24569. const index = Cell(0);
  24570. const undoManager = {
  24571. data: [],
  24572. typing: false,
  24573. beforeChange: () => {
  24574. beforeChange(editor, locks, beforeBookmark);
  24575. },
  24576. add: (level, event) => {
  24577. return addUndoLevel(
  24578. editor,
  24579. undoManager,
  24580. index,
  24581. locks,
  24582. beforeBookmark,
  24583. level,
  24584. event
  24585. );
  24586. },
  24587. dispatchChange: () => {
  24588. editor.setDirty(true);
  24589. const level = createFromEditor(editor);
  24590. level.bookmark = getUndoBookmark(editor.selection);
  24591. editor.dispatch("change", {
  24592. level,
  24593. lastLevel: get$b(undoManager.data, index.get()).getOrUndefined(),
  24594. });
  24595. },
  24596. undo: () => {
  24597. return undo(editor, undoManager, locks, index);
  24598. },
  24599. redo: () => {
  24600. return redo(editor, index, undoManager.data);
  24601. },
  24602. clear: () => {
  24603. clear(editor, undoManager, index);
  24604. },
  24605. reset: () => {
  24606. reset(editor, undoManager);
  24607. },
  24608. hasUndo: () => {
  24609. return hasUndo(editor, undoManager, index);
  24610. },
  24611. hasRedo: () => {
  24612. return hasRedo(editor, undoManager, index);
  24613. },
  24614. transact: (callback) => {
  24615. return transact(editor, undoManager, locks, callback);
  24616. },
  24617. ignore: (callback) => {
  24618. ignore(editor, locks, callback);
  24619. },
  24620. extra: (callback1, callback2) => {
  24621. extra(editor, undoManager, index, callback1, callback2);
  24622. },
  24623. };
  24624. if (!isRtc(editor)) {
  24625. registerEvents(editor, undoManager, locks);
  24626. }
  24627. addKeyboardShortcuts(editor);
  24628. return undoManager;
  24629. };
  24630. const nonTypingKeycodes = [
  24631. 9,
  24632. 27,
  24633. VK.HOME,
  24634. VK.END,
  24635. 19,
  24636. 20,
  24637. 44,
  24638. 144,
  24639. 145,
  24640. 33,
  24641. 34,
  24642. 45,
  24643. 16,
  24644. 17,
  24645. 18,
  24646. 91,
  24647. 92,
  24648. 93,
  24649. VK.DOWN,
  24650. VK.UP,
  24651. VK.LEFT,
  24652. VK.RIGHT,
  24653. ].concat(Env.browser.isFirefox() ? [224] : []);
  24654. const placeholderAttr = "data-mce-placeholder";
  24655. const isKeyboardEvent = (e) => e.type === "keydown" || e.type === "keyup";
  24656. const isDeleteEvent = (e) => {
  24657. const keyCode = e.keyCode;
  24658. return keyCode === VK.BACKSPACE || keyCode === VK.DELETE;
  24659. };
  24660. const isNonTypingKeyboardEvent = (e) => {
  24661. if (isKeyboardEvent(e)) {
  24662. const keyCode = e.keyCode;
  24663. return (
  24664. !isDeleteEvent(e) &&
  24665. (VK.metaKeyPressed(e) ||
  24666. e.altKey ||
  24667. (keyCode >= 112 && keyCode <= 123) ||
  24668. contains$2(nonTypingKeycodes, keyCode))
  24669. );
  24670. } else {
  24671. return false;
  24672. }
  24673. };
  24674. const isTypingKeyboardEvent = (e) =>
  24675. isKeyboardEvent(e) &&
  24676. !(isDeleteEvent(e) || (e.type === "keyup" && e.keyCode === 229));
  24677. const isVisuallyEmpty = (dom, rootElm, forcedRootBlock) => {
  24678. if (isEmpty$2(SugarElement.fromDom(rootElm), false)) {
  24679. const firstElement = rootElm.firstElementChild;
  24680. if (!firstElement) {
  24681. return true;
  24682. } else if (
  24683. dom.getStyle(rootElm.firstElementChild, "padding-left") ||
  24684. dom.getStyle(rootElm.firstElementChild, "padding-right")
  24685. ) {
  24686. return false;
  24687. } else {
  24688. return forcedRootBlock === firstElement.nodeName.toLowerCase();
  24689. }
  24690. } else {
  24691. return false;
  24692. }
  24693. };
  24694. const setup$q = (editor) => {
  24695. var _a;
  24696. const dom = editor.dom;
  24697. const rootBlock = getForcedRootBlock(editor);
  24698. const placeholder =
  24699. (_a = getPlaceholder(editor)) !== null && _a !== void 0 ? _a : "";
  24700. const updatePlaceholder = (e, initial) => {
  24701. if (isNonTypingKeyboardEvent(e)) {
  24702. return;
  24703. }
  24704. const body = editor.getBody();
  24705. const showPlaceholder = isTypingKeyboardEvent(e)
  24706. ? false
  24707. : isVisuallyEmpty(dom, body, rootBlock);
  24708. const isPlaceholderShown = dom.getAttrib(body, placeholderAttr) !== "";
  24709. if (isPlaceholderShown !== showPlaceholder || initial) {
  24710. dom.setAttrib(
  24711. body,
  24712. placeholderAttr,
  24713. showPlaceholder ? placeholder : null
  24714. );
  24715. dom.setAttrib(
  24716. body,
  24717. "aria-placeholder",
  24718. showPlaceholder ? placeholder : null
  24719. );
  24720. firePlaceholderToggle(editor, showPlaceholder);
  24721. editor.on(showPlaceholder ? "keydown" : "keyup", updatePlaceholder);
  24722. editor.off(showPlaceholder ? "keyup" : "keydown", updatePlaceholder);
  24723. }
  24724. };
  24725. if (isNotEmpty(placeholder)) {
  24726. editor.on("init", (e) => {
  24727. updatePlaceholder(e, true);
  24728. editor.on("change SetContent ExecCommand", updatePlaceholder);
  24729. editor.on("paste", (e) =>
  24730. Delay.setEditorTimeout(editor, () => updatePlaceholder(e))
  24731. );
  24732. });
  24733. }
  24734. };
  24735. const blockPosition = (block, position) => ({
  24736. block,
  24737. position,
  24738. });
  24739. const blockBoundary = (from, to) => ({
  24740. from,
  24741. to,
  24742. });
  24743. const getBlockPosition = (rootNode, pos) => {
  24744. const rootElm = SugarElement.fromDom(rootNode);
  24745. const containerElm = SugarElement.fromDom(pos.container());
  24746. return getParentBlock$2(rootElm, containerElm).map((block) =>
  24747. blockPosition(block, pos)
  24748. );
  24749. };
  24750. const isDifferentBlocks = (blockBoundary) =>
  24751. !eq(blockBoundary.from.block, blockBoundary.to.block);
  24752. const getClosestHost = (root, scope) => {
  24753. const isRoot = (node) => eq(node, root);
  24754. const isHost = (node) =>
  24755. isTableCell$2(node) || isContentEditableTrue$3(node.dom);
  24756. return closest$4(scope, isHost, isRoot).filter(isElement$7).getOr(root);
  24757. };
  24758. const hasSameHost = (rootNode, blockBoundary) => {
  24759. const root = SugarElement.fromDom(rootNode);
  24760. return eq(
  24761. getClosestHost(root, blockBoundary.from.block),
  24762. getClosestHost(root, blockBoundary.to.block)
  24763. );
  24764. };
  24765. const isEditable$1 = (blockBoundary) =>
  24766. isContentEditableFalse$b(blockBoundary.from.block.dom) === false &&
  24767. isContentEditableFalse$b(blockBoundary.to.block.dom) === false;
  24768. const hasValidBlocks = (blockBoundary) => {
  24769. const isValidBlock = (block) =>
  24770. isTextBlock$2(block) || hasBlockAttr(block.dom);
  24771. return (
  24772. isValidBlock(blockBoundary.from.block) &&
  24773. isValidBlock(blockBoundary.to.block)
  24774. );
  24775. };
  24776. const skipLastBr = (rootNode, forward, blockPosition) => {
  24777. if (
  24778. isBr$6(blockPosition.position.getNode()) &&
  24779. !isEmpty$2(blockPosition.block)
  24780. ) {
  24781. return positionIn(false, blockPosition.block.dom)
  24782. .bind((lastPositionInBlock) => {
  24783. if (lastPositionInBlock.isEqual(blockPosition.position)) {
  24784. return fromPosition(forward, rootNode, lastPositionInBlock).bind(
  24785. (to) => getBlockPosition(rootNode, to)
  24786. );
  24787. } else {
  24788. return Optional.some(blockPosition);
  24789. }
  24790. })
  24791. .getOr(blockPosition);
  24792. } else {
  24793. return blockPosition;
  24794. }
  24795. };
  24796. const readFromRange = (rootNode, forward, rng) => {
  24797. const fromBlockPos = getBlockPosition(
  24798. rootNode,
  24799. CaretPosition.fromRangeStart(rng)
  24800. );
  24801. const toBlockPos = fromBlockPos.bind((blockPos) =>
  24802. fromPosition(forward, rootNode, blockPos.position).bind((to) =>
  24803. getBlockPosition(rootNode, to).map((blockPos) =>
  24804. skipLastBr(rootNode, forward, blockPos)
  24805. )
  24806. )
  24807. );
  24808. return lift2(fromBlockPos, toBlockPos, blockBoundary).filter(
  24809. (blockBoundary) =>
  24810. isDifferentBlocks(blockBoundary) &&
  24811. hasSameHost(rootNode, blockBoundary) &&
  24812. isEditable$1(blockBoundary) &&
  24813. hasValidBlocks(blockBoundary)
  24814. );
  24815. };
  24816. const read$1 = (rootNode, forward, rng) =>
  24817. rng.collapsed ? readFromRange(rootNode, forward, rng) : Optional.none();
  24818. const getChildrenUntilBlockBoundary = (block) => {
  24819. const children = children$1(block);
  24820. return findIndex$2(children, isBlock$2).fold(constant(children), (index) =>
  24821. children.slice(0, index)
  24822. );
  24823. };
  24824. const extractChildren = (block) => {
  24825. const children = getChildrenUntilBlockBoundary(block);
  24826. each$e(children, remove$5);
  24827. return children;
  24828. };
  24829. const removeEmptyRoot = (rootNode, block) => {
  24830. const parents = parentsAndSelf(block, rootNode);
  24831. return find$2(parents.reverse(), (element) => isEmpty$2(element)).each(
  24832. remove$5
  24833. );
  24834. };
  24835. const isEmptyBefore = (el) =>
  24836. filter$5(prevSiblings(el), (el) => !isEmpty$2(el)).length === 0;
  24837. const nestedBlockMerge = (rootNode, fromBlock, toBlock, insertionPoint) => {
  24838. if (isEmpty$2(toBlock)) {
  24839. fillWithPaddingBr(toBlock);
  24840. return firstPositionIn(toBlock.dom);
  24841. }
  24842. if (isEmptyBefore(insertionPoint) && isEmpty$2(fromBlock)) {
  24843. before$3(insertionPoint, SugarElement.fromTag("br"));
  24844. }
  24845. const position = prevPosition(
  24846. toBlock.dom,
  24847. CaretPosition.before(insertionPoint.dom)
  24848. );
  24849. each$e(extractChildren(fromBlock), (child) => {
  24850. before$3(insertionPoint, child);
  24851. });
  24852. removeEmptyRoot(rootNode, fromBlock);
  24853. return position;
  24854. };
  24855. const sidelongBlockMerge = (rootNode, fromBlock, toBlock) => {
  24856. if (isEmpty$2(toBlock)) {
  24857. if (isEmpty$2(fromBlock)) {
  24858. const getInlineToBlockDescendants = (el) => {
  24859. const helper = (node, elements) =>
  24860. firstChild(node).fold(
  24861. () => elements,
  24862. (child) =>
  24863. isInline$1(child)
  24864. ? helper(child, elements.concat(shallow$1(child)))
  24865. : elements
  24866. );
  24867. return helper(el, []);
  24868. };
  24869. const newFromBlockDescendants = foldr(
  24870. getInlineToBlockDescendants(toBlock),
  24871. (element, descendant) => {
  24872. wrap$2(element, descendant);
  24873. return descendant;
  24874. },
  24875. createPaddingBr()
  24876. );
  24877. empty(fromBlock);
  24878. append$1(fromBlock, newFromBlockDescendants);
  24879. }
  24880. remove$5(toBlock);
  24881. return firstPositionIn(fromBlock.dom);
  24882. }
  24883. const position = lastPositionIn(toBlock.dom);
  24884. each$e(extractChildren(fromBlock), (child) => {
  24885. append$1(toBlock, child);
  24886. });
  24887. removeEmptyRoot(rootNode, fromBlock);
  24888. return position;
  24889. };
  24890. const findInsertionPoint = (toBlock, block) => {
  24891. const parentsAndSelf$1 = parentsAndSelf(block, toBlock);
  24892. return Optional.from(parentsAndSelf$1[parentsAndSelf$1.length - 1]);
  24893. };
  24894. const getInsertionPoint = (fromBlock, toBlock) =>
  24895. contains(toBlock, fromBlock)
  24896. ? findInsertionPoint(toBlock, fromBlock)
  24897. : Optional.none();
  24898. const trimBr = (first, block) => {
  24899. positionIn(first, block.dom)
  24900. .bind((position) => Optional.from(position.getNode()))
  24901. .map(SugarElement.fromDom)
  24902. .filter(isBr$5)
  24903. .each(remove$5);
  24904. };
  24905. const mergeBlockInto = (rootNode, fromBlock, toBlock) => {
  24906. trimBr(true, fromBlock);
  24907. trimBr(false, toBlock);
  24908. return getInsertionPoint(fromBlock, toBlock).fold(
  24909. curry(sidelongBlockMerge, rootNode, fromBlock, toBlock),
  24910. curry(nestedBlockMerge, rootNode, fromBlock, toBlock)
  24911. );
  24912. };
  24913. const mergeBlocks = (rootNode, forward, block1, block2) =>
  24914. forward
  24915. ? mergeBlockInto(rootNode, block2, block1)
  24916. : mergeBlockInto(rootNode, block1, block2);
  24917. const backspaceDelete$9 = (editor, forward) => {
  24918. const rootNode = SugarElement.fromDom(editor.getBody());
  24919. const position = read$1(
  24920. rootNode.dom,
  24921. forward,
  24922. editor.selection.getRng()
  24923. ).map((blockBoundary) => () => {
  24924. mergeBlocks(
  24925. rootNode,
  24926. forward,
  24927. blockBoundary.from.block,
  24928. blockBoundary.to.block
  24929. ).each((pos) => {
  24930. editor.selection.setRng(pos.toRange());
  24931. });
  24932. });
  24933. return position;
  24934. };
  24935. const deleteRangeMergeBlocks = (rootNode, selection) => {
  24936. const rng = selection.getRng();
  24937. return lift2(
  24938. getParentBlock$2(rootNode, SugarElement.fromDom(rng.startContainer)),
  24939. getParentBlock$2(rootNode, SugarElement.fromDom(rng.endContainer)),
  24940. (block1, block2) => {
  24941. if (!eq(block1, block2)) {
  24942. return Optional.some(() => {
  24943. rng.deleteContents();
  24944. mergeBlocks(rootNode, true, block1, block2).each((pos) => {
  24945. selection.setRng(pos.toRange());
  24946. });
  24947. });
  24948. } else {
  24949. return Optional.none();
  24950. }
  24951. }
  24952. ).getOr(Optional.none());
  24953. };
  24954. const isRawNodeInTable = (root, rawNode) => {
  24955. const node = SugarElement.fromDom(rawNode);
  24956. const isRoot = curry(eq, root);
  24957. return ancestor$4(node, isTableCell$2, isRoot).isSome();
  24958. };
  24959. const isSelectionInTable = (root, rng) =>
  24960. isRawNodeInTable(root, rng.startContainer) ||
  24961. isRawNodeInTable(root, rng.endContainer);
  24962. const isEverythingSelected = (root, rng) => {
  24963. const noPrevious = prevPosition(
  24964. root.dom,
  24965. CaretPosition.fromRangeStart(rng)
  24966. ).isNone();
  24967. const noNext = nextPosition(
  24968. root.dom,
  24969. CaretPosition.fromRangeEnd(rng)
  24970. ).isNone();
  24971. return !isSelectionInTable(root, rng) && noPrevious && noNext;
  24972. };
  24973. const emptyEditor = (editor) => {
  24974. return Optional.some(() => {
  24975. editor.setContent("");
  24976. editor.selection.setCursorLocation();
  24977. });
  24978. };
  24979. const deleteRange$2 = (editor) => {
  24980. const rootNode = SugarElement.fromDom(editor.getBody());
  24981. const rng = editor.selection.getRng();
  24982. return isEverythingSelected(rootNode, rng)
  24983. ? emptyEditor(editor)
  24984. : deleteRangeMergeBlocks(rootNode, editor.selection);
  24985. };
  24986. const backspaceDelete$8 = (editor, _forward) =>
  24987. editor.selection.isCollapsed() ? Optional.none() : deleteRange$2(editor);
  24988. const showCaret = (direction, editor, node, before, scrollIntoView) =>
  24989. Optional.from(
  24990. editor._selectionOverrides.showCaret(
  24991. direction,
  24992. node,
  24993. before,
  24994. scrollIntoView
  24995. )
  24996. );
  24997. const getNodeRange = (node) => {
  24998. const rng = node.ownerDocument.createRange();
  24999. rng.selectNode(node);
  25000. return rng;
  25001. };
  25002. const selectNode = (editor, node) => {
  25003. const e = editor.dispatch("BeforeObjectSelected", { target: node });
  25004. if (e.isDefaultPrevented()) {
  25005. return Optional.none();
  25006. }
  25007. return Optional.some(getNodeRange(node));
  25008. };
  25009. const renderCaretAtRange = (editor, range, scrollIntoView) => {
  25010. const normalizedRange = normalizeRange(1, editor.getBody(), range);
  25011. const caretPosition = CaretPosition.fromRangeStart(normalizedRange);
  25012. const caretPositionNode = caretPosition.getNode();
  25013. if (isInlineFakeCaretTarget(caretPositionNode)) {
  25014. return showCaret(
  25015. 1,
  25016. editor,
  25017. caretPositionNode,
  25018. !caretPosition.isAtEnd(),
  25019. false
  25020. );
  25021. }
  25022. const caretPositionBeforeNode = caretPosition.getNode(true);
  25023. if (isInlineFakeCaretTarget(caretPositionBeforeNode)) {
  25024. return showCaret(1, editor, caretPositionBeforeNode, false, false);
  25025. }
  25026. const ceRoot = getContentEditableRoot$1(
  25027. editor.dom.getRoot(),
  25028. caretPosition.getNode()
  25029. );
  25030. if (isInlineFakeCaretTarget(ceRoot)) {
  25031. return showCaret(1, editor, ceRoot, false, scrollIntoView);
  25032. }
  25033. return Optional.none();
  25034. };
  25035. const renderRangeCaret = (editor, range, scrollIntoView) =>
  25036. range.collapsed
  25037. ? renderCaretAtRange(editor, range, scrollIntoView).getOr(range)
  25038. : range;
  25039. const isBeforeBoundary = (pos) =>
  25040. isBeforeContentEditableFalse(pos) || isBeforeMedia(pos);
  25041. const isAfterBoundary = (pos) =>
  25042. isAfterContentEditableFalse(pos) || isAfterMedia(pos);
  25043. const trimEmptyTextNode = (dom, node) => {
  25044. if (isText$a(node) && node.data.length === 0) {
  25045. dom.remove(node);
  25046. }
  25047. };
  25048. const deleteContentAndShowCaret = (
  25049. editor,
  25050. range,
  25051. node,
  25052. direction,
  25053. forward,
  25054. peekCaretPosition
  25055. ) => {
  25056. showCaret(
  25057. direction,
  25058. editor,
  25059. peekCaretPosition.getNode(!forward),
  25060. forward,
  25061. true
  25062. ).each((caretRange) => {
  25063. if (range.collapsed) {
  25064. const deleteRange = range.cloneRange();
  25065. if (forward) {
  25066. deleteRange.setEnd(caretRange.startContainer, caretRange.startOffset);
  25067. } else {
  25068. deleteRange.setStart(caretRange.endContainer, caretRange.endOffset);
  25069. }
  25070. deleteRange.deleteContents();
  25071. } else {
  25072. range.deleteContents();
  25073. }
  25074. editor.selection.setRng(caretRange);
  25075. });
  25076. trimEmptyTextNode(editor.dom, node);
  25077. };
  25078. const deleteBoundaryText = (editor, forward) => {
  25079. const range = editor.selection.getRng();
  25080. if (!isText$a(range.commonAncestorContainer)) {
  25081. return Optional.none();
  25082. }
  25083. const direction = forward ? HDirection.Forwards : HDirection.Backwards;
  25084. const caretWalker = CaretWalker(editor.getBody());
  25085. const getNextPosFn = curry(
  25086. getVisualCaretPosition,
  25087. forward ? caretWalker.next : caretWalker.prev
  25088. );
  25089. const isBeforeFn = forward ? isBeforeBoundary : isAfterBoundary;
  25090. const caretPosition = getNormalizedRangeEndPoint(
  25091. direction,
  25092. editor.getBody(),
  25093. range
  25094. );
  25095. const nextCaretPosition = getNextPosFn(caretPosition);
  25096. const normalizedNextCaretPosition = nextCaretPosition
  25097. ? normalizePosition(forward, nextCaretPosition)
  25098. : nextCaretPosition;
  25099. if (
  25100. !normalizedNextCaretPosition ||
  25101. !isMoveInsideSameBlock(caretPosition, normalizedNextCaretPosition)
  25102. ) {
  25103. return Optional.none();
  25104. } else if (isBeforeFn(normalizedNextCaretPosition)) {
  25105. return Optional.some(() =>
  25106. deleteContentAndShowCaret(
  25107. editor,
  25108. range,
  25109. caretPosition.getNode(),
  25110. direction,
  25111. forward,
  25112. normalizedNextCaretPosition
  25113. )
  25114. );
  25115. }
  25116. const peekCaretPosition = getNextPosFn(normalizedNextCaretPosition);
  25117. if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
  25118. if (
  25119. isMoveInsideSameBlock(normalizedNextCaretPosition, peekCaretPosition)
  25120. ) {
  25121. return Optional.some(() =>
  25122. deleteContentAndShowCaret(
  25123. editor,
  25124. range,
  25125. caretPosition.getNode(),
  25126. direction,
  25127. forward,
  25128. peekCaretPosition
  25129. )
  25130. );
  25131. }
  25132. }
  25133. return Optional.none();
  25134. };
  25135. const backspaceDelete$7 = (editor, forward) =>
  25136. deleteBoundaryText(editor, forward);
  25137. const getEdgeCefPosition = (editor, atStart) => {
  25138. const root = editor.getBody();
  25139. return atStart
  25140. ? firstPositionIn(root).filter(isBeforeContentEditableFalse)
  25141. : lastPositionIn(root).filter(isAfterContentEditableFalse);
  25142. };
  25143. const isCefAtEdgeSelected = (editor) => {
  25144. const rng = editor.selection.getRng();
  25145. return (
  25146. !rng.collapsed &&
  25147. (getEdgeCefPosition(editor, true).exists((pos) =>
  25148. pos.isEqual(CaretPosition.fromRangeStart(rng))
  25149. ) ||
  25150. getEdgeCefPosition(editor, false).exists((pos) =>
  25151. pos.isEqual(CaretPosition.fromRangeEnd(rng))
  25152. ))
  25153. );
  25154. };
  25155. const isCompoundElement = (node) =>
  25156. isNonNullable(node) &&
  25157. (isTableCell$2(SugarElement.fromDom(node)) ||
  25158. isListItem$1(SugarElement.fromDom(node)));
  25159. const DeleteAction = Adt.generate([
  25160. { remove: ["element"] },
  25161. { moveToElement: ["element"] },
  25162. { moveToPosition: ["position"] },
  25163. ]);
  25164. const isAtContentEditableBlockCaret = (forward, from) => {
  25165. const elm = from.getNode(!forward);
  25166. const caretLocation = forward ? "after" : "before";
  25167. return (
  25168. isElement$6(elm) && elm.getAttribute("data-mce-caret") === caretLocation
  25169. );
  25170. };
  25171. const isDeleteFromCefDifferentBlocks = (root, forward, from, to) => {
  25172. const inSameBlock = (elm) =>
  25173. isInline$1(SugarElement.fromDom(elm)) && !isInSameBlock(from, to, root);
  25174. return getRelativeCefElm(!forward, from).fold(
  25175. () => getRelativeCefElm(forward, to).fold(never, inSameBlock),
  25176. inSameBlock
  25177. );
  25178. };
  25179. const deleteEmptyBlockOrMoveToCef = (root, forward, from, to) => {
  25180. const toCefElm = to.getNode(!forward);
  25181. return getParentBlock$2(
  25182. SugarElement.fromDom(root),
  25183. SugarElement.fromDom(from.getNode())
  25184. )
  25185. .map((blockElm) =>
  25186. isEmpty$2(blockElm)
  25187. ? DeleteAction.remove(blockElm.dom)
  25188. : DeleteAction.moveToElement(toCefElm)
  25189. )
  25190. .orThunk(() => Optional.some(DeleteAction.moveToElement(toCefElm)));
  25191. };
  25192. const findCefPosition = (root, forward, from) =>
  25193. fromPosition(forward, root, from).bind((to) => {
  25194. if (isCompoundElement(to.getNode())) {
  25195. return Optional.none();
  25196. } else if (isDeleteFromCefDifferentBlocks(root, forward, from, to)) {
  25197. return Optional.none();
  25198. } else if (forward && isContentEditableFalse$b(to.getNode())) {
  25199. return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
  25200. } else if (!forward && isContentEditableFalse$b(to.getNode(true))) {
  25201. return deleteEmptyBlockOrMoveToCef(root, forward, from, to);
  25202. } else if (forward && isAfterContentEditableFalse(from)) {
  25203. return Optional.some(DeleteAction.moveToPosition(to));
  25204. } else if (!forward && isBeforeContentEditableFalse(from)) {
  25205. return Optional.some(DeleteAction.moveToPosition(to));
  25206. } else {
  25207. return Optional.none();
  25208. }
  25209. });
  25210. const getContentEditableBlockAction = (forward, elm) => {
  25211. if (isNullable(elm)) {
  25212. return Optional.none();
  25213. } else if (forward && isContentEditableFalse$b(elm.nextSibling)) {
  25214. return Optional.some(DeleteAction.moveToElement(elm.nextSibling));
  25215. } else if (!forward && isContentEditableFalse$b(elm.previousSibling)) {
  25216. return Optional.some(DeleteAction.moveToElement(elm.previousSibling));
  25217. } else {
  25218. return Optional.none();
  25219. }
  25220. };
  25221. const skipMoveToActionFromInlineCefToContent = (root, from, deleteAction) =>
  25222. deleteAction.fold(
  25223. (elm) => Optional.some(DeleteAction.remove(elm)),
  25224. (elm) => Optional.some(DeleteAction.moveToElement(elm)),
  25225. (to) => {
  25226. if (isInSameBlock(from, to, root)) {
  25227. return Optional.none();
  25228. } else {
  25229. return Optional.some(DeleteAction.moveToPosition(to));
  25230. }
  25231. }
  25232. );
  25233. const getContentEditableAction = (root, forward, from) => {
  25234. if (isAtContentEditableBlockCaret(forward, from)) {
  25235. return getContentEditableBlockAction(
  25236. forward,
  25237. from.getNode(!forward)
  25238. ).orThunk(() => findCefPosition(root, forward, from));
  25239. } else {
  25240. return findCefPosition(root, forward, from).bind((deleteAction) =>
  25241. skipMoveToActionFromInlineCefToContent(root, from, deleteAction)
  25242. );
  25243. }
  25244. };
  25245. const read = (root, forward, rng) => {
  25246. const normalizedRange = normalizeRange(forward ? 1 : -1, root, rng);
  25247. const from = CaretPosition.fromRangeStart(normalizedRange);
  25248. const rootElement = SugarElement.fromDom(root);
  25249. if (!forward && isAfterContentEditableFalse(from)) {
  25250. return Optional.some(DeleteAction.remove(from.getNode(true)));
  25251. } else if (forward && isBeforeContentEditableFalse(from)) {
  25252. return Optional.some(DeleteAction.remove(from.getNode()));
  25253. } else if (
  25254. !forward &&
  25255. isBeforeContentEditableFalse(from) &&
  25256. isAfterBr(rootElement, from)
  25257. ) {
  25258. return findPreviousBr(rootElement, from).map((br) =>
  25259. DeleteAction.remove(br.getNode())
  25260. );
  25261. } else if (
  25262. forward &&
  25263. isAfterContentEditableFalse(from) &&
  25264. isBeforeBr$1(rootElement, from)
  25265. ) {
  25266. return findNextBr(rootElement, from).map((br) =>
  25267. DeleteAction.remove(br.getNode())
  25268. );
  25269. } else {
  25270. return getContentEditableAction(root, forward, from);
  25271. }
  25272. };
  25273. const deleteElement$1 = (editor, forward) => (element) => {
  25274. editor._selectionOverrides.hideFakeCaret();
  25275. deleteElement$2(editor, forward, SugarElement.fromDom(element));
  25276. return true;
  25277. };
  25278. const moveToElement = (editor, forward) => (element) => {
  25279. const pos = forward
  25280. ? CaretPosition.before(element)
  25281. : CaretPosition.after(element);
  25282. editor.selection.setRng(pos.toRange());
  25283. return true;
  25284. };
  25285. const moveToPosition = (editor) => (pos) => {
  25286. editor.selection.setRng(pos.toRange());
  25287. return true;
  25288. };
  25289. const getAncestorCe = (editor, node) =>
  25290. Optional.from(getContentEditableRoot$1(editor.getBody(), node));
  25291. const backspaceDeleteCaret = (editor, forward) => {
  25292. const selectedNode = editor.selection.getNode();
  25293. return getAncestorCe(editor, selectedNode)
  25294. .filter(isContentEditableFalse$b)
  25295. .fold(
  25296. () =>
  25297. read(editor.getBody(), forward, editor.selection.getRng()).map(
  25298. (deleteAction) => () =>
  25299. deleteAction.fold(
  25300. deleteElement$1(editor, forward),
  25301. moveToElement(editor, forward),
  25302. moveToPosition(editor)
  25303. )
  25304. ),
  25305. () => Optional.some(noop)
  25306. );
  25307. };
  25308. const deleteOffscreenSelection = (rootElement) => {
  25309. each$e(descendants(rootElement, ".mce-offscreen-selection"), remove$5);
  25310. };
  25311. const backspaceDeleteRange = (editor, forward) => {
  25312. const selectedNode = editor.selection.getNode();
  25313. if (
  25314. isContentEditableFalse$b(selectedNode) &&
  25315. !isTableCell$3(selectedNode)
  25316. ) {
  25317. const hasCefAncestor = getAncestorCe(
  25318. editor,
  25319. selectedNode.parentNode
  25320. ).filter(isContentEditableFalse$b);
  25321. return hasCefAncestor.fold(
  25322. () =>
  25323. Optional.some(() => {
  25324. deleteOffscreenSelection(SugarElement.fromDom(editor.getBody()));
  25325. deleteElement$2(
  25326. editor,
  25327. forward,
  25328. SugarElement.fromDom(editor.selection.getNode())
  25329. );
  25330. paddEmptyBody(editor);
  25331. }),
  25332. () => Optional.some(noop)
  25333. );
  25334. }
  25335. if (isCefAtEdgeSelected(editor)) {
  25336. return Optional.some(() => {
  25337. deleteRangeContents(
  25338. editor,
  25339. editor.selection.getRng(),
  25340. SugarElement.fromDom(editor.getBody())
  25341. );
  25342. });
  25343. }
  25344. return Optional.none();
  25345. };
  25346. const paddEmptyElement = (editor) => {
  25347. const dom = editor.dom,
  25348. selection = editor.selection;
  25349. const ceRoot = getContentEditableRoot$1(
  25350. editor.getBody(),
  25351. selection.getNode()
  25352. );
  25353. if (
  25354. isContentEditableTrue$3(ceRoot) &&
  25355. dom.isBlock(ceRoot) &&
  25356. dom.isEmpty(ceRoot)
  25357. ) {
  25358. const br = dom.create("br", { "data-mce-bogus": "1" });
  25359. dom.setHTML(ceRoot, "");
  25360. ceRoot.appendChild(br);
  25361. selection.setRng(CaretPosition.before(br).toRange());
  25362. }
  25363. return true;
  25364. };
  25365. const backspaceDelete$6 = (editor, forward) => {
  25366. if (editor.selection.isCollapsed()) {
  25367. return backspaceDeleteCaret(editor, forward);
  25368. } else {
  25369. return backspaceDeleteRange(editor, forward);
  25370. }
  25371. };
  25372. const deleteCaret$2 = (editor, forward) => {
  25373. const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
  25374. return fromPosition(forward, editor.getBody(), fromPos)
  25375. .filter((pos) =>
  25376. forward ? isBeforeImageBlock(pos) : isAfterImageBlock(pos)
  25377. )
  25378. .bind((pos) => getChildNodeAtRelativeOffset(forward ? 0 : -1, pos))
  25379. .map((elm) => () => editor.selection.select(elm));
  25380. };
  25381. const backspaceDelete$5 = (editor, forward) =>
  25382. editor.selection.isCollapsed()
  25383. ? deleteCaret$2(editor, forward)
  25384. : Optional.none();
  25385. const isText$2 = isText$a;
  25386. const startsWithCaretContainer = (node) =>
  25387. isText$2(node) && node.data[0] === ZWSP$1;
  25388. const endsWithCaretContainer = (node) =>
  25389. isText$2(node) && node.data[node.data.length - 1] === ZWSP$1;
  25390. const createZwsp = (node) => {
  25391. var _a;
  25392. const doc =
  25393. (_a = node.ownerDocument) !== null && _a !== void 0 ? _a : document;
  25394. return doc.createTextNode(ZWSP$1);
  25395. };
  25396. const insertBefore$1 = (node) => {
  25397. var _a;
  25398. if (isText$2(node.previousSibling)) {
  25399. if (endsWithCaretContainer(node.previousSibling)) {
  25400. return node.previousSibling;
  25401. } else {
  25402. node.previousSibling.appendData(ZWSP$1);
  25403. return node.previousSibling;
  25404. }
  25405. } else if (isText$2(node)) {
  25406. if (startsWithCaretContainer(node)) {
  25407. return node;
  25408. } else {
  25409. node.insertData(0, ZWSP$1);
  25410. return node;
  25411. }
  25412. } else {
  25413. const newNode = createZwsp(node);
  25414. (_a = node.parentNode) === null || _a === void 0
  25415. ? void 0
  25416. : _a.insertBefore(newNode, node);
  25417. return newNode;
  25418. }
  25419. };
  25420. const insertAfter$1 = (node) => {
  25421. var _a, _b;
  25422. if (isText$2(node.nextSibling)) {
  25423. if (startsWithCaretContainer(node.nextSibling)) {
  25424. return node.nextSibling;
  25425. } else {
  25426. node.nextSibling.insertData(0, ZWSP$1);
  25427. return node.nextSibling;
  25428. }
  25429. } else if (isText$2(node)) {
  25430. if (endsWithCaretContainer(node)) {
  25431. return node;
  25432. } else {
  25433. node.appendData(ZWSP$1);
  25434. return node;
  25435. }
  25436. } else {
  25437. const newNode = createZwsp(node);
  25438. if (node.nextSibling) {
  25439. (_a = node.parentNode) === null || _a === void 0
  25440. ? void 0
  25441. : _a.insertBefore(newNode, node.nextSibling);
  25442. } else {
  25443. (_b = node.parentNode) === null || _b === void 0
  25444. ? void 0
  25445. : _b.appendChild(newNode);
  25446. }
  25447. return newNode;
  25448. }
  25449. };
  25450. const insertInline = (before, node) =>
  25451. before ? insertBefore$1(node) : insertAfter$1(node);
  25452. const insertInlineBefore = curry(insertInline, true);
  25453. const insertInlineAfter = curry(insertInline, false);
  25454. const insertInlinePos = (pos, before) => {
  25455. if (isText$a(pos.container())) {
  25456. return insertInline(before, pos.container());
  25457. } else {
  25458. return insertInline(before, pos.getNode());
  25459. }
  25460. };
  25461. const isPosCaretContainer = (pos, caret) => {
  25462. const caretNode = caret.get();
  25463. return (
  25464. caretNode &&
  25465. pos.container() === caretNode &&
  25466. isCaretContainerInline(caretNode)
  25467. );
  25468. };
  25469. const renderCaret = (caret, location) =>
  25470. location.fold(
  25471. (element) => {
  25472. remove$3(caret.get());
  25473. const text = insertInlineBefore(element);
  25474. caret.set(text);
  25475. return Optional.some(CaretPosition(text, text.length - 1));
  25476. },
  25477. (element) =>
  25478. firstPositionIn(element).map((pos) => {
  25479. if (!isPosCaretContainer(pos, caret)) {
  25480. remove$3(caret.get());
  25481. const text = insertInlinePos(pos, true);
  25482. caret.set(text);
  25483. return CaretPosition(text, 1);
  25484. } else {
  25485. const node = caret.get();
  25486. return CaretPosition(node, 1);
  25487. }
  25488. }),
  25489. (element) =>
  25490. lastPositionIn(element).map((pos) => {
  25491. if (!isPosCaretContainer(pos, caret)) {
  25492. remove$3(caret.get());
  25493. const text = insertInlinePos(pos, false);
  25494. caret.set(text);
  25495. return CaretPosition(text, text.length - 1);
  25496. } else {
  25497. const node = caret.get();
  25498. return CaretPosition(node, node.length - 1);
  25499. }
  25500. }),
  25501. (element) => {
  25502. remove$3(caret.get());
  25503. const text = insertInlineAfter(element);
  25504. caret.set(text);
  25505. return Optional.some(CaretPosition(text, 1));
  25506. }
  25507. );
  25508. const evaluateUntil = (fns, args) => {
  25509. for (let i = 0; i < fns.length; i++) {
  25510. const result = fns[i].apply(null, args);
  25511. if (result.isSome()) {
  25512. return result;
  25513. }
  25514. }
  25515. return Optional.none();
  25516. };
  25517. const Location = Adt.generate([
  25518. { before: ["element"] },
  25519. { start: ["element"] },
  25520. { end: ["element"] },
  25521. { after: ["element"] },
  25522. ]);
  25523. const rescope$1 = (rootNode, node) => {
  25524. const parentBlock = getParentBlock$3(node, rootNode);
  25525. return parentBlock ? parentBlock : rootNode;
  25526. };
  25527. const before = (isInlineTarget, rootNode, pos) => {
  25528. const nPos = normalizeForwards(pos);
  25529. const scope = rescope$1(rootNode, nPos.container());
  25530. return findRootInline(isInlineTarget, scope, nPos).fold(
  25531. () =>
  25532. nextPosition(scope, nPos)
  25533. .bind(curry(findRootInline, isInlineTarget, scope))
  25534. .map((inline) => Location.before(inline)),
  25535. Optional.none
  25536. );
  25537. };
  25538. const isNotInsideFormatCaretContainer = (rootNode, elm) =>
  25539. getParentCaretContainer(rootNode, elm) === null;
  25540. const findInsideRootInline = (isInlineTarget, rootNode, pos) =>
  25541. findRootInline(isInlineTarget, rootNode, pos).filter(
  25542. curry(isNotInsideFormatCaretContainer, rootNode)
  25543. );
  25544. const start$1 = (isInlineTarget, rootNode, pos) => {
  25545. const nPos = normalizeBackwards(pos);
  25546. return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(
  25547. (inline) => {
  25548. const prevPos = prevPosition(inline, nPos);
  25549. return prevPos.isNone()
  25550. ? Optional.some(Location.start(inline))
  25551. : Optional.none();
  25552. }
  25553. );
  25554. };
  25555. const end = (isInlineTarget, rootNode, pos) => {
  25556. const nPos = normalizeForwards(pos);
  25557. return findInsideRootInline(isInlineTarget, rootNode, nPos).bind(
  25558. (inline) => {
  25559. const nextPos = nextPosition(inline, nPos);
  25560. return nextPos.isNone()
  25561. ? Optional.some(Location.end(inline))
  25562. : Optional.none();
  25563. }
  25564. );
  25565. };
  25566. const after = (isInlineTarget, rootNode, pos) => {
  25567. const nPos = normalizeBackwards(pos);
  25568. const scope = rescope$1(rootNode, nPos.container());
  25569. return findRootInline(isInlineTarget, scope, nPos).fold(
  25570. () =>
  25571. prevPosition(scope, nPos)
  25572. .bind(curry(findRootInline, isInlineTarget, scope))
  25573. .map((inline) => Location.after(inline)),
  25574. Optional.none
  25575. );
  25576. };
  25577. const isValidLocation = (location) => !isRtl(getElement(location));
  25578. const readLocation = (isInlineTarget, rootNode, pos) => {
  25579. const location = evaluateUntil(
  25580. [before, start$1, end, after],
  25581. [isInlineTarget, rootNode, pos]
  25582. );
  25583. return location.filter(isValidLocation);
  25584. };
  25585. const getElement = (location) =>
  25586. location.fold(identity, identity, identity, identity);
  25587. const getName = (location) =>
  25588. location.fold(
  25589. constant("before"),
  25590. constant("start"),
  25591. constant("end"),
  25592. constant("after")
  25593. );
  25594. const outside = (location) =>
  25595. location.fold(
  25596. Location.before,
  25597. Location.before,
  25598. Location.after,
  25599. Location.after
  25600. );
  25601. const inside = (location) =>
  25602. location.fold(Location.start, Location.start, Location.end, Location.end);
  25603. const isEq = (location1, location2) =>
  25604. getName(location1) === getName(location2) &&
  25605. getElement(location1) === getElement(location2);
  25606. const betweenInlines = (
  25607. forward,
  25608. isInlineTarget,
  25609. rootNode,
  25610. from,
  25611. to,
  25612. location
  25613. ) =>
  25614. lift2(
  25615. findRootInline(isInlineTarget, rootNode, from),
  25616. findRootInline(isInlineTarget, rootNode, to),
  25617. (fromInline, toInline) => {
  25618. if (
  25619. fromInline !== toInline &&
  25620. hasSameParentBlock(rootNode, fromInline, toInline)
  25621. ) {
  25622. return Location.after(forward ? fromInline : toInline);
  25623. } else {
  25624. return location;
  25625. }
  25626. }
  25627. ).getOr(location);
  25628. const skipNoMovement = (fromLocation, toLocation) =>
  25629. fromLocation.fold(
  25630. always,
  25631. (fromLocation) => !isEq(fromLocation, toLocation)
  25632. );
  25633. const findLocationTraverse = (
  25634. forward,
  25635. isInlineTarget,
  25636. rootNode,
  25637. fromLocation,
  25638. pos
  25639. ) => {
  25640. const from = normalizePosition(forward, pos);
  25641. const to = fromPosition(forward, rootNode, from).map(
  25642. curry(normalizePosition, forward)
  25643. );
  25644. const location = to.fold(
  25645. () => fromLocation.map(outside),
  25646. (to) =>
  25647. readLocation(isInlineTarget, rootNode, to)
  25648. .map(
  25649. curry(betweenInlines, forward, isInlineTarget, rootNode, from, to)
  25650. )
  25651. .filter(curry(skipNoMovement, fromLocation))
  25652. );
  25653. return location.filter(isValidLocation);
  25654. };
  25655. const findLocationSimple = (forward, location) => {
  25656. if (forward) {
  25657. return location.fold(
  25658. compose(Optional.some, Location.start),
  25659. Optional.none,
  25660. compose(Optional.some, Location.after),
  25661. Optional.none
  25662. );
  25663. } else {
  25664. return location.fold(
  25665. Optional.none,
  25666. compose(Optional.some, Location.before),
  25667. Optional.none,
  25668. compose(Optional.some, Location.end)
  25669. );
  25670. }
  25671. };
  25672. const findLocation$1 = (forward, isInlineTarget, rootNode, pos) => {
  25673. const from = normalizePosition(forward, pos);
  25674. const fromLocation = readLocation(isInlineTarget, rootNode, from);
  25675. return readLocation(isInlineTarget, rootNode, from)
  25676. .bind(curry(findLocationSimple, forward))
  25677. .orThunk(() =>
  25678. findLocationTraverse(
  25679. forward,
  25680. isInlineTarget,
  25681. rootNode,
  25682. fromLocation,
  25683. pos
  25684. )
  25685. );
  25686. };
  25687. const hasSelectionModifyApi = (editor) => {
  25688. return isFunction(editor.selection.getSel().modify);
  25689. };
  25690. const moveRel = (forward, selection, pos) => {
  25691. const delta = forward ? 1 : -1;
  25692. selection.setRng(
  25693. CaretPosition(pos.container(), pos.offset() + delta).toRange()
  25694. );
  25695. selection.getSel().modify("move", forward ? "forward" : "backward", "word");
  25696. return true;
  25697. };
  25698. const moveByWord = (forward, editor) => {
  25699. const rng = editor.selection.getRng();
  25700. const pos = forward
  25701. ? CaretPosition.fromRangeEnd(rng)
  25702. : CaretPosition.fromRangeStart(rng);
  25703. if (!hasSelectionModifyApi(editor)) {
  25704. return false;
  25705. } else if (forward && isBeforeInline(pos)) {
  25706. return moveRel(true, editor.selection, pos);
  25707. } else if (!forward && isAfterInline(pos)) {
  25708. return moveRel(false, editor.selection, pos);
  25709. } else {
  25710. return false;
  25711. }
  25712. };
  25713. var BreakType;
  25714. (function (BreakType) {
  25715. BreakType[(BreakType["Br"] = 0)] = "Br";
  25716. BreakType[(BreakType["Block"] = 1)] = "Block";
  25717. BreakType[(BreakType["Wrap"] = 2)] = "Wrap";
  25718. BreakType[(BreakType["Eol"] = 3)] = "Eol";
  25719. })(BreakType || (BreakType = {}));
  25720. const flip = (direction, positions) =>
  25721. direction === HDirection.Backwards ? reverse(positions) : positions;
  25722. const walk$1 = (direction, caretWalker, pos) =>
  25723. direction === HDirection.Forwards
  25724. ? caretWalker.next(pos)
  25725. : caretWalker.prev(pos);
  25726. const getBreakType = (scope, direction, currentPos, nextPos) => {
  25727. if (isBr$6(nextPos.getNode(direction === HDirection.Forwards))) {
  25728. return BreakType.Br;
  25729. } else if (isInSameBlock(currentPos, nextPos) === false) {
  25730. return BreakType.Block;
  25731. } else {
  25732. return BreakType.Wrap;
  25733. }
  25734. };
  25735. const getPositionsUntil = (predicate, direction, scope, start) => {
  25736. const caretWalker = CaretWalker(scope);
  25737. let currentPos = start;
  25738. const positions = [];
  25739. while (currentPos) {
  25740. const nextPos = walk$1(direction, caretWalker, currentPos);
  25741. if (!nextPos) {
  25742. break;
  25743. }
  25744. if (isBr$6(nextPos.getNode(false))) {
  25745. if (direction === HDirection.Forwards) {
  25746. return {
  25747. positions: flip(direction, positions).concat([nextPos]),
  25748. breakType: BreakType.Br,
  25749. breakAt: Optional.some(nextPos),
  25750. };
  25751. } else {
  25752. return {
  25753. positions: flip(direction, positions),
  25754. breakType: BreakType.Br,
  25755. breakAt: Optional.some(nextPos),
  25756. };
  25757. }
  25758. }
  25759. if (!nextPos.isVisible()) {
  25760. currentPos = nextPos;
  25761. continue;
  25762. }
  25763. if (predicate(currentPos, nextPos)) {
  25764. const breakType = getBreakType(scope, direction, currentPos, nextPos);
  25765. return {
  25766. positions: flip(direction, positions),
  25767. breakType,
  25768. breakAt: Optional.some(nextPos),
  25769. };
  25770. }
  25771. positions.push(nextPos);
  25772. currentPos = nextPos;
  25773. }
  25774. return {
  25775. positions: flip(direction, positions),
  25776. breakType: BreakType.Eol,
  25777. breakAt: Optional.none(),
  25778. };
  25779. };
  25780. const getAdjacentLinePositions = (
  25781. direction,
  25782. getPositionsUntilBreak,
  25783. scope,
  25784. start
  25785. ) =>
  25786. getPositionsUntilBreak(scope, start)
  25787. .breakAt.map((pos) => {
  25788. const positions = getPositionsUntilBreak(scope, pos).positions;
  25789. return direction === HDirection.Backwards
  25790. ? positions.concat(pos)
  25791. : [pos].concat(positions);
  25792. })
  25793. .getOr([]);
  25794. const findClosestHorizontalPositionFromPoint = (positions, x) =>
  25795. foldl(
  25796. positions,
  25797. (acc, newPos) =>
  25798. acc.fold(
  25799. () => Optional.some(newPos),
  25800. (lastPos) =>
  25801. lift2(
  25802. head(lastPos.getClientRects()),
  25803. head(newPos.getClientRects()),
  25804. (lastRect, newRect) => {
  25805. const lastDist = Math.abs(x - lastRect.left);
  25806. const newDist = Math.abs(x - newRect.left);
  25807. return newDist <= lastDist ? newPos : lastPos;
  25808. }
  25809. ).or(acc)
  25810. ),
  25811. Optional.none()
  25812. );
  25813. const findClosestHorizontalPosition = (positions, pos) =>
  25814. head(pos.getClientRects()).bind((targetRect) =>
  25815. findClosestHorizontalPositionFromPoint(positions, targetRect.left)
  25816. );
  25817. const getPositionsUntilPreviousLine = curry(
  25818. getPositionsUntil,
  25819. CaretPosition.isAbove,
  25820. -1
  25821. );
  25822. const getPositionsUntilNextLine = curry(
  25823. getPositionsUntil,
  25824. CaretPosition.isBelow,
  25825. 1
  25826. );
  25827. const getPositionsAbove = curry(
  25828. getAdjacentLinePositions,
  25829. -1,
  25830. getPositionsUntilPreviousLine
  25831. );
  25832. const getPositionsBelow = curry(
  25833. getAdjacentLinePositions,
  25834. 1,
  25835. getPositionsUntilNextLine
  25836. );
  25837. const isAtFirstLine = (scope, pos) =>
  25838. getPositionsUntilPreviousLine(scope, pos).breakAt.isNone();
  25839. const isAtLastLine = (scope, pos) =>
  25840. getPositionsUntilNextLine(scope, pos).breakAt.isNone();
  25841. const getFirstLinePositions = (scope) =>
  25842. firstPositionIn(scope)
  25843. .map((pos) =>
  25844. [pos].concat(getPositionsUntilNextLine(scope, pos).positions)
  25845. )
  25846. .getOr([]);
  25847. const getLastLinePositions = (scope) =>
  25848. lastPositionIn(scope)
  25849. .map((pos) =>
  25850. getPositionsUntilPreviousLine(scope, pos).positions.concat(pos)
  25851. )
  25852. .getOr([]);
  25853. const getClosestPositionAbove = (scope, pos) =>
  25854. findClosestHorizontalPosition(getPositionsAbove(scope, pos), pos);
  25855. const getClosestPositionBelow = (scope, pos) =>
  25856. findClosestHorizontalPosition(getPositionsBelow(scope, pos), pos);
  25857. const isContentEditableFalse$4 = isContentEditableFalse$b;
  25858. const distanceToRectLeft$1 = (clientRect, clientX) =>
  25859. Math.abs(clientRect.left - clientX);
  25860. const distanceToRectRight$1 = (clientRect, clientX) =>
  25861. Math.abs(clientRect.right - clientX);
  25862. const isNodeClientRect = (rect) => hasNonNullableKey(rect, "node");
  25863. const findClosestClientRect = (clientRects, clientX) =>
  25864. reduce(clientRects, (oldClientRect, clientRect) => {
  25865. const oldDistance = Math.min(
  25866. distanceToRectLeft$1(oldClientRect, clientX),
  25867. distanceToRectRight$1(oldClientRect, clientX)
  25868. );
  25869. const newDistance = Math.min(
  25870. distanceToRectLeft$1(clientRect, clientX),
  25871. distanceToRectRight$1(clientRect, clientX)
  25872. );
  25873. if (
  25874. newDistance === oldDistance &&
  25875. isNodeClientRect(clientRect) &&
  25876. isContentEditableFalse$4(clientRect.node)
  25877. ) {
  25878. return clientRect;
  25879. }
  25880. if (newDistance < oldDistance) {
  25881. return clientRect;
  25882. }
  25883. return oldClientRect;
  25884. });
  25885. const getNodeClientRects = (node) => {
  25886. const toArrayWithNode = (clientRects) => {
  25887. return map$3(clientRects, (rect) => {
  25888. const clientRect = clone$1(rect);
  25889. clientRect.node = node;
  25890. return clientRect;
  25891. });
  25892. };
  25893. if (isElement$6(node)) {
  25894. return toArrayWithNode(node.getClientRects());
  25895. } else if (isText$a(node)) {
  25896. const rng = node.ownerDocument.createRange();
  25897. rng.setStart(node, 0);
  25898. rng.setEnd(node, node.data.length);
  25899. return toArrayWithNode(rng.getClientRects());
  25900. } else {
  25901. return [];
  25902. }
  25903. };
  25904. const getClientRects = (nodes) => bind$3(nodes, getNodeClientRects);
  25905. var VDirection;
  25906. (function (VDirection) {
  25907. VDirection[(VDirection["Up"] = -1)] = "Up";
  25908. VDirection[(VDirection["Down"] = 1)] = "Down";
  25909. })(VDirection || (VDirection = {}));
  25910. const findUntil = (direction, root, predicateFn, node) => {
  25911. let currentNode = node;
  25912. while (
  25913. (currentNode = findNode(
  25914. currentNode,
  25915. direction,
  25916. isEditableCaretCandidate$1,
  25917. root
  25918. ))
  25919. ) {
  25920. if (predicateFn(currentNode)) {
  25921. return;
  25922. }
  25923. }
  25924. };
  25925. const walkUntil = (
  25926. direction,
  25927. isAboveFn,
  25928. isBeflowFn,
  25929. root,
  25930. predicateFn,
  25931. caretPosition
  25932. ) => {
  25933. let line = 0;
  25934. const result = [];
  25935. const add = (node) => {
  25936. let clientRects = getClientRects([node]);
  25937. if (direction === -1) {
  25938. clientRects = clientRects.reverse();
  25939. }
  25940. for (let i = 0; i < clientRects.length; i++) {
  25941. const clientRect = clientRects[i];
  25942. if (isBeflowFn(clientRect, targetClientRect)) {
  25943. continue;
  25944. }
  25945. if (result.length > 0 && isAboveFn(clientRect, last$2(result))) {
  25946. line++;
  25947. }
  25948. clientRect.line = line;
  25949. if (predicateFn(clientRect)) {
  25950. return true;
  25951. }
  25952. result.push(clientRect);
  25953. }
  25954. return false;
  25955. };
  25956. const targetClientRect = last$2(caretPosition.getClientRects());
  25957. if (!targetClientRect) {
  25958. return result;
  25959. }
  25960. const node = caretPosition.getNode();
  25961. if (node) {
  25962. add(node);
  25963. findUntil(direction, root, add, node);
  25964. }
  25965. return result;
  25966. };
  25967. const aboveLineNumber = (lineNumber, clientRect) =>
  25968. clientRect.line > lineNumber;
  25969. const isLineNumber = (lineNumber, clientRect) =>
  25970. clientRect.line === lineNumber;
  25971. const upUntil = curry(walkUntil, VDirection.Up, isAbove$1, isBelow$1);
  25972. const downUntil = curry(walkUntil, VDirection.Down, isBelow$1, isAbove$1);
  25973. const getLastClientRect = (caretPosition) => {
  25974. return last$2(caretPosition.getClientRects());
  25975. };
  25976. const positionsUntil = (direction, root, predicateFn, node) => {
  25977. const caretWalker = CaretWalker(root);
  25978. let walkFn;
  25979. let isBelowFn;
  25980. let isAboveFn;
  25981. let caretPosition;
  25982. const result = [];
  25983. let line = 0;
  25984. if (direction === 1) {
  25985. walkFn = caretWalker.next;
  25986. isBelowFn = isBelow$1;
  25987. isAboveFn = isAbove$1;
  25988. caretPosition = CaretPosition.after(node);
  25989. } else {
  25990. walkFn = caretWalker.prev;
  25991. isBelowFn = isAbove$1;
  25992. isAboveFn = isBelow$1;
  25993. caretPosition = CaretPosition.before(node);
  25994. }
  25995. const targetClientRect = getLastClientRect(caretPosition);
  25996. do {
  25997. if (!caretPosition.isVisible()) {
  25998. continue;
  25999. }
  26000. const rect = getLastClientRect(caretPosition);
  26001. if (isAboveFn(rect, targetClientRect)) {
  26002. continue;
  26003. }
  26004. if (result.length > 0 && isBelowFn(rect, last$2(result))) {
  26005. line++;
  26006. }
  26007. const clientRect = clone$1(rect);
  26008. clientRect.position = caretPosition;
  26009. clientRect.line = line;
  26010. if (predicateFn(clientRect)) {
  26011. return result;
  26012. }
  26013. result.push(clientRect);
  26014. } while ((caretPosition = walkFn(caretPosition)));
  26015. return result;
  26016. };
  26017. const isAboveLine = (lineNumber) => (clientRect) =>
  26018. aboveLineNumber(lineNumber, clientRect);
  26019. const isLine = (lineNumber) => (clientRect) =>
  26020. isLineNumber(lineNumber, clientRect);
  26021. const moveToRange = (editor, rng) => {
  26022. editor.selection.setRng(rng);
  26023. scrollRangeIntoView(editor, editor.selection.getRng());
  26024. };
  26025. const renderRangeCaretOpt = (editor, range, scrollIntoView) =>
  26026. Optional.some(renderRangeCaret(editor, range, scrollIntoView));
  26027. const moveHorizontally = (
  26028. editor,
  26029. direction,
  26030. range,
  26031. isBefore,
  26032. isAfter,
  26033. isElement
  26034. ) => {
  26035. const forwards = direction === HDirection.Forwards;
  26036. const caretWalker = CaretWalker(editor.getBody());
  26037. const getNextPosFn = curry(
  26038. getVisualCaretPosition,
  26039. forwards ? caretWalker.next : caretWalker.prev
  26040. );
  26041. const isBeforeFn = forwards ? isBefore : isAfter;
  26042. if (!range.collapsed) {
  26043. const node = getSelectedNode(range);
  26044. if (isElement(node)) {
  26045. return showCaret(
  26046. direction,
  26047. editor,
  26048. node,
  26049. direction === HDirection.Backwards,
  26050. false
  26051. );
  26052. } else if (isCefAtEdgeSelected(editor)) {
  26053. const newRange = range.cloneRange();
  26054. newRange.collapse(direction === HDirection.Backwards);
  26055. return Optional.from(newRange);
  26056. }
  26057. }
  26058. const caretPosition = getNormalizedRangeEndPoint(
  26059. direction,
  26060. editor.getBody(),
  26061. range
  26062. );
  26063. if (isBeforeFn(caretPosition)) {
  26064. return selectNode(editor, caretPosition.getNode(!forwards));
  26065. }
  26066. let nextCaretPosition = getNextPosFn(caretPosition);
  26067. const rangeIsInContainerBlock = isRangeInCaretContainerBlock(range);
  26068. if (!nextCaretPosition) {
  26069. return rangeIsInContainerBlock ? Optional.some(range) : Optional.none();
  26070. } else {
  26071. nextCaretPosition = normalizePosition(forwards, nextCaretPosition);
  26072. }
  26073. if (isBeforeFn(nextCaretPosition)) {
  26074. return showCaret(
  26075. direction,
  26076. editor,
  26077. nextCaretPosition.getNode(!forwards),
  26078. forwards,
  26079. false
  26080. );
  26081. }
  26082. const peekCaretPosition = getNextPosFn(nextCaretPosition);
  26083. if (peekCaretPosition && isBeforeFn(peekCaretPosition)) {
  26084. if (isMoveInsideSameBlock(nextCaretPosition, peekCaretPosition)) {
  26085. return showCaret(
  26086. direction,
  26087. editor,
  26088. peekCaretPosition.getNode(!forwards),
  26089. forwards,
  26090. false
  26091. );
  26092. }
  26093. }
  26094. if (rangeIsInContainerBlock) {
  26095. return renderRangeCaretOpt(editor, nextCaretPosition.toRange(), false);
  26096. }
  26097. return Optional.none();
  26098. };
  26099. const moveVertically = (
  26100. editor,
  26101. direction,
  26102. range,
  26103. isBefore,
  26104. isAfter,
  26105. isElement
  26106. ) => {
  26107. const caretPosition = getNormalizedRangeEndPoint(
  26108. direction,
  26109. editor.getBody(),
  26110. range
  26111. );
  26112. const caretClientRect = last$2(caretPosition.getClientRects());
  26113. const forwards = direction === VDirection.Down;
  26114. const root = editor.getBody();
  26115. if (!caretClientRect) {
  26116. return Optional.none();
  26117. }
  26118. if (isCefAtEdgeSelected(editor)) {
  26119. const caretPosition = forwards
  26120. ? CaretPosition.fromRangeEnd(range)
  26121. : CaretPosition.fromRangeStart(range);
  26122. const getClosestFn = !forwards
  26123. ? getClosestPositionAbove
  26124. : getClosestPositionBelow;
  26125. return getClosestFn(root, caretPosition)
  26126. .orThunk(() => Optional.from(caretPosition))
  26127. .map((pos) => pos.toRange());
  26128. }
  26129. const walkerFn = forwards ? downUntil : upUntil;
  26130. const linePositions = walkerFn(root, isAboveLine(1), caretPosition);
  26131. const nextLinePositions = filter$5(linePositions, isLine(1));
  26132. const clientX = caretClientRect.left;
  26133. const nextLineRect = findClosestClientRect(nextLinePositions, clientX);
  26134. if (nextLineRect && isElement(nextLineRect.node)) {
  26135. const dist1 = Math.abs(clientX - nextLineRect.left);
  26136. const dist2 = Math.abs(clientX - nextLineRect.right);
  26137. return showCaret(
  26138. direction,
  26139. editor,
  26140. nextLineRect.node,
  26141. dist1 < dist2,
  26142. false
  26143. );
  26144. }
  26145. let currentNode;
  26146. if (isBefore(caretPosition)) {
  26147. currentNode = caretPosition.getNode();
  26148. } else if (isAfter(caretPosition)) {
  26149. currentNode = caretPosition.getNode(true);
  26150. } else {
  26151. currentNode = getSelectedNode(range);
  26152. }
  26153. if (currentNode) {
  26154. const caretPositions = positionsUntil(
  26155. direction,
  26156. root,
  26157. isAboveLine(1),
  26158. currentNode
  26159. );
  26160. let closestNextLineRect = findClosestClientRect(
  26161. filter$5(caretPositions, isLine(1)),
  26162. clientX
  26163. );
  26164. if (closestNextLineRect) {
  26165. return renderRangeCaretOpt(
  26166. editor,
  26167. closestNextLineRect.position.toRange(),
  26168. false
  26169. );
  26170. }
  26171. closestNextLineRect = last$2(filter$5(caretPositions, isLine(0)));
  26172. if (closestNextLineRect) {
  26173. return renderRangeCaretOpt(
  26174. editor,
  26175. closestNextLineRect.position.toRange(),
  26176. false
  26177. );
  26178. }
  26179. }
  26180. if (nextLinePositions.length === 0) {
  26181. return getLineEndPoint(editor, forwards)
  26182. .filter(forwards ? isAfter : isBefore)
  26183. .map((pos) => renderRangeCaret(editor, pos.toRange(), false));
  26184. }
  26185. return Optional.none();
  26186. };
  26187. const getLineEndPoint = (editor, forward) => {
  26188. const rng = editor.selection.getRng();
  26189. const from = forward
  26190. ? CaretPosition.fromRangeEnd(rng)
  26191. : CaretPosition.fromRangeStart(rng);
  26192. const host = getEditingHost(from.container(), editor.getBody());
  26193. if (forward) {
  26194. const lineInfo = getPositionsUntilNextLine(host, from);
  26195. return last$3(lineInfo.positions);
  26196. } else {
  26197. const lineInfo = getPositionsUntilPreviousLine(host, from);
  26198. return head(lineInfo.positions);
  26199. }
  26200. };
  26201. const moveToLineEndPoint$3 = (editor, forward, isElementPosition) =>
  26202. getLineEndPoint(editor, forward)
  26203. .filter(isElementPosition)
  26204. .exists((pos) => {
  26205. editor.selection.setRng(pos.toRange());
  26206. return true;
  26207. });
  26208. const setCaretPosition = (editor, pos) => {
  26209. const rng = editor.dom.createRng();
  26210. rng.setStart(pos.container(), pos.offset());
  26211. rng.setEnd(pos.container(), pos.offset());
  26212. editor.selection.setRng(rng);
  26213. };
  26214. const setSelected = (state, elm) => {
  26215. if (state) {
  26216. elm.setAttribute("data-mce-selected", "inline-boundary");
  26217. } else {
  26218. elm.removeAttribute("data-mce-selected");
  26219. }
  26220. };
  26221. const renderCaretLocation = (editor, caret, location) =>
  26222. renderCaret(caret, location).map((pos) => {
  26223. setCaretPosition(editor, pos);
  26224. return location;
  26225. });
  26226. const getPositionFromRange = (range, root, forward) => {
  26227. const start = CaretPosition.fromRangeStart(range);
  26228. if (range.collapsed) {
  26229. return start;
  26230. } else {
  26231. const end = CaretPosition.fromRangeEnd(range);
  26232. return forward
  26233. ? prevPosition(root, end).getOr(end)
  26234. : nextPosition(root, start).getOr(start);
  26235. }
  26236. };
  26237. const findLocation = (editor, caret, forward) => {
  26238. const rootNode = editor.getBody();
  26239. const from = getPositionFromRange(
  26240. editor.selection.getRng(),
  26241. rootNode,
  26242. forward
  26243. );
  26244. const isInlineTarget$1 = curry(isInlineTarget, editor);
  26245. const location = findLocation$1(forward, isInlineTarget$1, rootNode, from);
  26246. return location.bind((location) =>
  26247. renderCaretLocation(editor, caret, location)
  26248. );
  26249. };
  26250. const toggleInlines = (isInlineTarget, dom, elms) => {
  26251. const inlineBoundaries = map$3(
  26252. descendants(
  26253. SugarElement.fromDom(dom.getRoot()),
  26254. '*[data-mce-selected="inline-boundary"]'
  26255. ),
  26256. (e) => e.dom
  26257. );
  26258. const selectedInlines = filter$5(inlineBoundaries, isInlineTarget);
  26259. const targetInlines = filter$5(elms, isInlineTarget);
  26260. each$e(
  26261. difference(selectedInlines, targetInlines),
  26262. curry(setSelected, false)
  26263. );
  26264. each$e(
  26265. difference(targetInlines, selectedInlines),
  26266. curry(setSelected, true)
  26267. );
  26268. };
  26269. const safeRemoveCaretContainer = (editor, caret) => {
  26270. const caretValue = caret.get();
  26271. if (editor.selection.isCollapsed() && !editor.composing && caretValue) {
  26272. const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
  26273. if (CaretPosition.isTextPosition(pos) && !isAtZwsp(pos)) {
  26274. setCaretPosition(editor, removeAndReposition(caretValue, pos));
  26275. caret.set(null);
  26276. }
  26277. }
  26278. };
  26279. const renderInsideInlineCaret = (isInlineTarget, editor, caret, elms) => {
  26280. if (editor.selection.isCollapsed()) {
  26281. const inlines = filter$5(elms, isInlineTarget);
  26282. each$e(inlines, (_inline) => {
  26283. const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
  26284. readLocation(isInlineTarget, editor.getBody(), pos).bind((location) =>
  26285. renderCaretLocation(editor, caret, location)
  26286. );
  26287. });
  26288. }
  26289. };
  26290. const move$3 = (editor, caret, forward) =>
  26291. isInlineBoundariesEnabled(editor)
  26292. ? findLocation(editor, caret, forward).isSome()
  26293. : false;
  26294. const moveWord = (forward, editor, _caret) =>
  26295. isInlineBoundariesEnabled(editor) ? moveByWord(forward, editor) : false;
  26296. const setupSelectedState = (editor) => {
  26297. const caret = Cell(null);
  26298. const isInlineTarget$1 = curry(isInlineTarget, editor);
  26299. editor.on("NodeChange", (e) => {
  26300. if (isInlineBoundariesEnabled(editor)) {
  26301. toggleInlines(isInlineTarget$1, editor.dom, e.parents);
  26302. safeRemoveCaretContainer(editor, caret);
  26303. renderInsideInlineCaret(isInlineTarget$1, editor, caret, e.parents);
  26304. }
  26305. });
  26306. return caret;
  26307. };
  26308. const moveNextWord = curry(moveWord, true);
  26309. const movePrevWord = curry(moveWord, false);
  26310. const moveToLineEndPoint$2 = (editor, forward, caret) => {
  26311. if (isInlineBoundariesEnabled(editor)) {
  26312. const linePoint = getLineEndPoint(editor, forward).getOrThunk(() => {
  26313. const rng = editor.selection.getRng();
  26314. return forward
  26315. ? CaretPosition.fromRangeEnd(rng)
  26316. : CaretPosition.fromRangeStart(rng);
  26317. });
  26318. return readLocation(
  26319. curry(isInlineTarget, editor),
  26320. editor.getBody(),
  26321. linePoint
  26322. ).exists((loc) => {
  26323. const outsideLoc = outside(loc);
  26324. return renderCaret(caret, outsideLoc).exists((pos) => {
  26325. setCaretPosition(editor, pos);
  26326. return true;
  26327. });
  26328. });
  26329. } else {
  26330. return false;
  26331. }
  26332. };
  26333. const rangeFromPositions = (from, to) => {
  26334. const range = document.createRange();
  26335. range.setStart(from.container(), from.offset());
  26336. range.setEnd(to.container(), to.offset());
  26337. return range;
  26338. };
  26339. const hasOnlyTwoOrLessPositionsLeft = (elm) =>
  26340. lift2(firstPositionIn(elm), lastPositionIn(elm), (firstPos, lastPos) => {
  26341. const normalizedFirstPos = normalizePosition(true, firstPos);
  26342. const normalizedLastPos = normalizePosition(false, lastPos);
  26343. return nextPosition(elm, normalizedFirstPos).forall((pos) =>
  26344. pos.isEqual(normalizedLastPos)
  26345. );
  26346. }).getOr(true);
  26347. const setCaretLocation = (editor, caret) => (location) =>
  26348. renderCaret(caret, location).map(
  26349. (pos) => () => setCaretPosition(editor, pos)
  26350. );
  26351. const deleteFromTo = (editor, caret, from, to) => {
  26352. const rootNode = editor.getBody();
  26353. const isInlineTarget$1 = curry(isInlineTarget, editor);
  26354. editor.undoManager.ignore(() => {
  26355. editor.selection.setRng(rangeFromPositions(from, to));
  26356. execNativeDeleteCommand(editor);
  26357. readLocation(
  26358. isInlineTarget$1,
  26359. rootNode,
  26360. CaretPosition.fromRangeStart(editor.selection.getRng())
  26361. )
  26362. .map(inside)
  26363. .bind(setCaretLocation(editor, caret))
  26364. .each(call);
  26365. });
  26366. editor.nodeChanged();
  26367. };
  26368. const rescope = (rootNode, node) => {
  26369. const parentBlock = getParentBlock$3(node, rootNode);
  26370. return parentBlock ? parentBlock : rootNode;
  26371. };
  26372. const backspaceDeleteCollapsed = (editor, caret, forward, from) => {
  26373. const rootNode = rescope(editor.getBody(), from.container());
  26374. const isInlineTarget$1 = curry(isInlineTarget, editor);
  26375. const fromLocation = readLocation(isInlineTarget$1, rootNode, from);
  26376. const location = fromLocation.bind((location) => {
  26377. if (forward) {
  26378. return location.fold(
  26379. constant(Optional.some(inside(location))),
  26380. Optional.none,
  26381. constant(Optional.some(outside(location))),
  26382. Optional.none
  26383. );
  26384. } else {
  26385. return location.fold(
  26386. Optional.none,
  26387. constant(Optional.some(outside(location))),
  26388. Optional.none,
  26389. constant(Optional.some(inside(location)))
  26390. );
  26391. }
  26392. });
  26393. return location.map(setCaretLocation(editor, caret)).getOrThunk(() => {
  26394. const toPosition = navigate(forward, rootNode, from);
  26395. const toLocation = toPosition.bind((pos) =>
  26396. readLocation(isInlineTarget$1, rootNode, pos)
  26397. );
  26398. return lift2(fromLocation, toLocation, () =>
  26399. findRootInline(isInlineTarget$1, rootNode, from).bind((elm) => {
  26400. if (hasOnlyTwoOrLessPositionsLeft(elm)) {
  26401. return Optional.some(() => {
  26402. deleteElement$2(editor, forward, SugarElement.fromDom(elm));
  26403. });
  26404. } else {
  26405. return Optional.none();
  26406. }
  26407. })
  26408. ).getOrThunk(() =>
  26409. toLocation.bind(() =>
  26410. toPosition.map((to) => {
  26411. return () => {
  26412. if (forward) {
  26413. deleteFromTo(editor, caret, from, to);
  26414. } else {
  26415. deleteFromTo(editor, caret, to, from);
  26416. }
  26417. };
  26418. })
  26419. )
  26420. );
  26421. });
  26422. };
  26423. const backspaceDelete$4 = (editor, caret, forward) => {
  26424. if (editor.selection.isCollapsed() && isInlineBoundariesEnabled(editor)) {
  26425. const from = CaretPosition.fromRangeStart(editor.selection.getRng());
  26426. return backspaceDeleteCollapsed(editor, caret, forward, from);
  26427. }
  26428. return Optional.none();
  26429. };
  26430. const hasMultipleChildren = (elm) => childNodesCount(elm) > 1;
  26431. const getParentsUntil = (editor, pred) => {
  26432. const rootElm = SugarElement.fromDom(editor.getBody());
  26433. const startElm = SugarElement.fromDom(editor.selection.getStart());
  26434. const parents = parentsAndSelf(startElm, rootElm);
  26435. return findIndex$2(parents, pred).fold(constant(parents), (index) =>
  26436. parents.slice(0, index)
  26437. );
  26438. };
  26439. const hasOnlyOneChild = (elm) => childNodesCount(elm) === 1;
  26440. const getParentInlinesUntilMultichildInline = (editor) =>
  26441. getParentsUntil(
  26442. editor,
  26443. (elm) => isBlock$2(elm) || hasMultipleChildren(elm)
  26444. );
  26445. const getParentInlines = (editor) => getParentsUntil(editor, isBlock$2);
  26446. const getFormatNodes = (editor, parentInlines) => {
  26447. const isFormatElement$1 = curry(isFormatElement, editor);
  26448. return bind$3(parentInlines, (elm) =>
  26449. isFormatElement$1(elm) ? [elm.dom] : []
  26450. );
  26451. };
  26452. const getFormatNodesAtStart = (editor) => {
  26453. const parentInlines = getParentInlines(editor);
  26454. return getFormatNodes(editor, parentInlines);
  26455. };
  26456. const deleteLastPosition = (forward, editor, target, parentInlines) => {
  26457. const formatNodes = getFormatNodes(editor, parentInlines);
  26458. if (formatNodes.length === 0) {
  26459. deleteElement$2(editor, forward, target);
  26460. } else {
  26461. const pos = replaceWithCaretFormat(target.dom, formatNodes);
  26462. editor.selection.setRng(pos.toRange());
  26463. }
  26464. };
  26465. const deleteCaret$1 = (editor, forward) => {
  26466. const parentInlines = filter$5(
  26467. getParentInlinesUntilMultichildInline(editor),
  26468. hasOnlyOneChild
  26469. );
  26470. return last$3(parentInlines).bind((target) => {
  26471. const fromPos = CaretPosition.fromRangeStart(editor.selection.getRng());
  26472. if (
  26473. willDeleteLastPositionInElement(forward, fromPos, target.dom) &&
  26474. !isEmptyCaretFormatElement(target)
  26475. ) {
  26476. return Optional.some(() =>
  26477. deleteLastPosition(forward, editor, target, parentInlines)
  26478. );
  26479. } else {
  26480. return Optional.none();
  26481. }
  26482. });
  26483. };
  26484. const isBrInEmptyElement = (editor, elm) => {
  26485. const parentElm = elm.parentElement;
  26486. return isBr$6(elm) && !isNull(parentElm) && editor.dom.isEmpty(parentElm);
  26487. };
  26488. const isEmptyCaret = (elm) =>
  26489. isEmptyCaretFormatElement(SugarElement.fromDom(elm));
  26490. const createCaretFormatAtStart = (editor, formatNodes) => {
  26491. const startElm = editor.selection.getStart();
  26492. const pos =
  26493. isBrInEmptyElement(editor, startElm) || isEmptyCaret(startElm)
  26494. ? replaceWithCaretFormat(startElm, formatNodes)
  26495. : createCaretFormatAtStart$1(editor.selection.getRng(), formatNodes);
  26496. editor.selection.setRng(pos.toRange());
  26497. };
  26498. const updateCaretFormat = (editor, updateFormats) => {
  26499. const missingFormats = difference(
  26500. updateFormats,
  26501. getFormatNodesAtStart(editor)
  26502. );
  26503. if (missingFormats.length > 0) {
  26504. createCaretFormatAtStart(editor, missingFormats);
  26505. }
  26506. };
  26507. const rangeStartsAtTextContainer = (rng) => isText$a(rng.startContainer);
  26508. const rangeStartsAtStartOfTextContainer = (rng) =>
  26509. rng.startOffset === 0 && rangeStartsAtTextContainer(rng);
  26510. const rangeStartParentIsFormatElement = (editor, rng) => {
  26511. const startParent = rng.startContainer.parentElement;
  26512. return (
  26513. !isNull(startParent) &&
  26514. isFormatElement(editor, SugarElement.fromDom(startParent))
  26515. );
  26516. };
  26517. const rangeStartAndEndHaveSameParent = (rng) => {
  26518. const startParent = rng.startContainer.parentNode;
  26519. const endParent = rng.endContainer.parentNode;
  26520. return (
  26521. !isNull(startParent) &&
  26522. !isNull(endParent) &&
  26523. startParent.isEqualNode(endParent)
  26524. );
  26525. };
  26526. const rangeEndsAtEndOfEndContainer = (rng) => {
  26527. const endContainer = rng.endContainer;
  26528. return (
  26529. rng.endOffset ===
  26530. (isText$a(endContainer)
  26531. ? endContainer.length
  26532. : endContainer.childNodes.length)
  26533. );
  26534. };
  26535. const rangeEndsAtEndOfStartContainer = (rng) =>
  26536. rangeStartAndEndHaveSameParent(rng) && rangeEndsAtEndOfEndContainer(rng);
  26537. const rangeEndsAfterEndOfStartContainer = (rng) =>
  26538. !rng.endContainer.isEqualNode(rng.commonAncestorContainer);
  26539. const rangeEndsAtOrAfterEndOfStartContainer = (rng) =>
  26540. rangeEndsAtEndOfStartContainer(rng) ||
  26541. rangeEndsAfterEndOfStartContainer(rng);
  26542. const requiresDeleteRangeOverride = (editor) => {
  26543. const rng = editor.selection.getRng();
  26544. return (
  26545. rangeStartsAtStartOfTextContainer(rng) &&
  26546. rangeStartParentIsFormatElement(editor, rng) &&
  26547. rangeEndsAtOrAfterEndOfStartContainer(rng)
  26548. );
  26549. };
  26550. const deleteRange$1 = (editor) => {
  26551. if (requiresDeleteRangeOverride(editor)) {
  26552. const formatNodes = getFormatNodesAtStart(editor);
  26553. return Optional.some(() => {
  26554. execNativeDeleteCommand(editor);
  26555. updateCaretFormat(editor, formatNodes);
  26556. });
  26557. } else {
  26558. return Optional.none();
  26559. }
  26560. };
  26561. const backspaceDelete$3 = (editor, forward) =>
  26562. editor.selection.isCollapsed()
  26563. ? deleteCaret$1(editor, forward)
  26564. : deleteRange$1(editor);
  26565. const hasAncestorInlineCaret = (elm) =>
  26566. ancestor$1(elm, (node) => isCaretNode(node.dom), isBlock$2);
  26567. const hasAncestorInlineCaretAtStart = (editor) =>
  26568. hasAncestorInlineCaret(SugarElement.fromDom(editor.selection.getStart()));
  26569. const requiresRefreshCaretOverride = (editor) => {
  26570. const rng = editor.selection.getRng();
  26571. return (
  26572. rng.collapsed &&
  26573. (rangeStartsAtTextContainer(rng) ||
  26574. editor.dom.isEmpty(rng.startContainer)) &&
  26575. !hasAncestorInlineCaretAtStart(editor)
  26576. );
  26577. };
  26578. const refreshCaret = (editor) => {
  26579. if (requiresRefreshCaretOverride(editor)) {
  26580. createCaretFormatAtStart(editor, []);
  26581. }
  26582. return true;
  26583. };
  26584. const deleteElement = (editor, forward, element) => {
  26585. if (isNonNullable(element)) {
  26586. return Optional.some(() => {
  26587. editor._selectionOverrides.hideFakeCaret();
  26588. deleteElement$2(editor, forward, SugarElement.fromDom(element));
  26589. });
  26590. } else {
  26591. return Optional.none();
  26592. }
  26593. };
  26594. const deleteCaret = (editor, forward) => {
  26595. const isNearMedia = forward ? isBeforeMedia : isAfterMedia;
  26596. const direction = forward ? HDirection.Forwards : HDirection.Backwards;
  26597. const fromPos = getNormalizedRangeEndPoint(
  26598. direction,
  26599. editor.getBody(),
  26600. editor.selection.getRng()
  26601. );
  26602. if (isNearMedia(fromPos)) {
  26603. return deleteElement(editor, forward, fromPos.getNode(!forward));
  26604. } else {
  26605. return Optional.from(normalizePosition(forward, fromPos))
  26606. .filter(
  26607. (pos) => isNearMedia(pos) && isMoveInsideSameBlock(fromPos, pos)
  26608. )
  26609. .bind((pos) => deleteElement(editor, forward, pos.getNode(!forward)));
  26610. }
  26611. };
  26612. const deleteRange = (editor, forward) => {
  26613. const selectedNode = editor.selection.getNode();
  26614. return isMedia$2(selectedNode)
  26615. ? deleteElement(editor, forward, selectedNode)
  26616. : Optional.none();
  26617. };
  26618. const backspaceDelete$2 = (editor, forward) =>
  26619. editor.selection.isCollapsed()
  26620. ? deleteCaret(editor, forward)
  26621. : deleteRange(editor, forward);
  26622. const isEditable = (target) =>
  26623. closest$4(
  26624. target,
  26625. (elm) =>
  26626. isContentEditableTrue$3(elm.dom) || isContentEditableFalse$b(elm.dom)
  26627. ).exists((elm) => isContentEditableTrue$3(elm.dom));
  26628. const parseIndentValue = (value) =>
  26629. toInt(value !== null && value !== void 0 ? value : "").getOr(0);
  26630. const getIndentStyleName = (useMargin, element) => {
  26631. const indentStyleName =
  26632. useMargin || isTable$1(element) ? "margin" : "padding";
  26633. const suffix = get$7(element, "direction") === "rtl" ? "-right" : "-left";
  26634. return indentStyleName + suffix;
  26635. };
  26636. const indentElement = (dom, command, useMargin, value, unit, element) => {
  26637. const indentStyleName = getIndentStyleName(
  26638. useMargin,
  26639. SugarElement.fromDom(element)
  26640. );
  26641. const parsedValue = parseIndentValue(
  26642. dom.getStyle(element, indentStyleName)
  26643. );
  26644. if (command === "outdent") {
  26645. const styleValue = Math.max(0, parsedValue - value);
  26646. dom.setStyle(
  26647. element,
  26648. indentStyleName,
  26649. styleValue ? styleValue + unit : ""
  26650. );
  26651. } else {
  26652. const styleValue = parsedValue + value + unit;
  26653. dom.setStyle(element, indentStyleName, styleValue);
  26654. }
  26655. };
  26656. const validateBlocks = (editor, blocks) =>
  26657. forall(blocks, (block) => {
  26658. const indentStyleName = getIndentStyleName(
  26659. shouldIndentUseMargin(editor),
  26660. block
  26661. );
  26662. const intentValue = getRaw(block, indentStyleName)
  26663. .map(parseIndentValue)
  26664. .getOr(0);
  26665. const contentEditable = editor.dom.getContentEditable(block.dom);
  26666. return contentEditable !== "false" && intentValue > 0;
  26667. });
  26668. const canOutdent = (editor) => {
  26669. const blocks = getBlocksToIndent(editor);
  26670. return (
  26671. !editor.mode.isReadOnly() &&
  26672. (blocks.length > 1 || validateBlocks(editor, blocks))
  26673. );
  26674. };
  26675. const isListComponent = (el) => isList(el) || isListItem$1(el);
  26676. const parentIsListComponent = (el) => parent(el).exists(isListComponent);
  26677. const getBlocksToIndent = (editor) =>
  26678. filter$5(
  26679. fromDom$1(editor.selection.getSelectedBlocks()),
  26680. (el) =>
  26681. !isListComponent(el) && !parentIsListComponent(el) && isEditable(el)
  26682. );
  26683. const handle = (editor, command) => {
  26684. var _a, _b;
  26685. const { dom } = editor;
  26686. const indentation = getIndentation(editor);
  26687. const indentUnit =
  26688. (_b =
  26689. (_a = /[a-z%]+$/i.exec(indentation)) === null || _a === void 0
  26690. ? void 0
  26691. : _a[0]) !== null && _b !== void 0
  26692. ? _b
  26693. : "px";
  26694. const indentValue = parseIndentValue(indentation);
  26695. const useMargin = shouldIndentUseMargin(editor);
  26696. each$e(getBlocksToIndent(editor), (block) => {
  26697. indentElement(
  26698. dom,
  26699. command,
  26700. useMargin,
  26701. indentValue,
  26702. indentUnit,
  26703. block.dom
  26704. );
  26705. });
  26706. };
  26707. const indent = (editor) => handle(editor, "indent");
  26708. const outdent = (editor) => handle(editor, "outdent");
  26709. const backspaceDelete$1 = (editor) => {
  26710. if (editor.selection.isCollapsed() && canOutdent(editor)) {
  26711. const dom = editor.dom;
  26712. const rng = editor.selection.getRng();
  26713. const pos = CaretPosition.fromRangeStart(rng);
  26714. const block = dom.getParent(rng.startContainer, dom.isBlock);
  26715. if (
  26716. block !== null &&
  26717. isAtStartOfBlock(SugarElement.fromDom(block), pos)
  26718. ) {
  26719. return Optional.some(() => outdent(editor));
  26720. }
  26721. }
  26722. return Optional.none();
  26723. };
  26724. const findAction = (editor, caret, forward) =>
  26725. findMap(
  26726. [
  26727. backspaceDelete$1,
  26728. backspaceDelete$6,
  26729. backspaceDelete$7,
  26730. (editor, forward) => backspaceDelete$4(editor, caret, forward),
  26731. backspaceDelete$9,
  26732. backspaceDelete$a,
  26733. backspaceDelete$5,
  26734. backspaceDelete$2,
  26735. backspaceDelete$8,
  26736. backspaceDelete$3,
  26737. ],
  26738. (item) => item(editor, forward)
  26739. ).filter((_) => editor.selection.isEditable());
  26740. const deleteCommand = (editor, caret) => {
  26741. const result = findAction(editor, caret, false);
  26742. result.fold(() => {
  26743. execNativeDeleteCommand(editor);
  26744. paddEmptyBody(editor);
  26745. }, call);
  26746. };
  26747. const forwardDeleteCommand = (editor, caret) => {
  26748. const result = findAction(editor, caret, true);
  26749. result.fold(() => execNativeForwardDeleteCommand(editor), call);
  26750. };
  26751. const setup$p = (editor, caret) => {
  26752. editor.addCommand("delete", () => {
  26753. deleteCommand(editor, caret);
  26754. });
  26755. editor.addCommand("forwardDelete", () => {
  26756. forwardDeleteCommand(editor, caret);
  26757. });
  26758. };
  26759. const SIGNIFICANT_MOVE = 5;
  26760. const LONGPRESS_DELAY = 400;
  26761. const getTouch = (event) => {
  26762. if (event.touches === undefined || event.touches.length !== 1) {
  26763. return Optional.none();
  26764. }
  26765. return Optional.some(event.touches[0]);
  26766. };
  26767. const isFarEnough = (touch, data) => {
  26768. const distX = Math.abs(touch.clientX - data.x);
  26769. const distY = Math.abs(touch.clientY - data.y);
  26770. return distX > SIGNIFICANT_MOVE || distY > SIGNIFICANT_MOVE;
  26771. };
  26772. const setup$o = (editor) => {
  26773. const startData = value$2();
  26774. const longpressFired = Cell(false);
  26775. const debounceLongpress = last$1((e) => {
  26776. editor.dispatch("longpress", {
  26777. ...e,
  26778. type: "longpress",
  26779. });
  26780. longpressFired.set(true);
  26781. }, LONGPRESS_DELAY);
  26782. editor.on(
  26783. "touchstart",
  26784. (e) => {
  26785. getTouch(e).each((touch) => {
  26786. debounceLongpress.cancel();
  26787. const data = {
  26788. x: touch.clientX,
  26789. y: touch.clientY,
  26790. target: e.target,
  26791. };
  26792. debounceLongpress.throttle(e);
  26793. longpressFired.set(false);
  26794. startData.set(data);
  26795. });
  26796. },
  26797. true
  26798. );
  26799. editor.on(
  26800. "touchmove",
  26801. (e) => {
  26802. debounceLongpress.cancel();
  26803. getTouch(e).each((touch) => {
  26804. startData.on((data) => {
  26805. if (isFarEnough(touch, data)) {
  26806. startData.clear();
  26807. longpressFired.set(false);
  26808. editor.dispatch("longpresscancel");
  26809. }
  26810. });
  26811. });
  26812. },
  26813. true
  26814. );
  26815. editor.on(
  26816. "touchend touchcancel",
  26817. (e) => {
  26818. debounceLongpress.cancel();
  26819. if (e.type === "touchcancel") {
  26820. return;
  26821. }
  26822. startData
  26823. .get()
  26824. .filter((data) => data.target.isEqualNode(e.target))
  26825. .each(() => {
  26826. if (longpressFired.get()) {
  26827. e.preventDefault();
  26828. } else {
  26829. editor.dispatch("tap", {
  26830. ...e,
  26831. type: "tap",
  26832. });
  26833. }
  26834. });
  26835. },
  26836. true
  26837. );
  26838. };
  26839. const isBlockElement = (blockElements, node) =>
  26840. has$2(blockElements, node.nodeName);
  26841. const isValidTarget = (schema, node) => {
  26842. if (isText$a(node)) {
  26843. return true;
  26844. } else if (isElement$6(node)) {
  26845. return (
  26846. !isBlockElement(schema.getBlockElements(), node) &&
  26847. !isBookmarkNode$1(node) &&
  26848. !isTransparentBlock(schema, node)
  26849. );
  26850. } else {
  26851. return false;
  26852. }
  26853. };
  26854. const hasBlockParent = (blockElements, root, node) => {
  26855. return exists(
  26856. parents(SugarElement.fromDom(node), SugarElement.fromDom(root)),
  26857. (elm) => {
  26858. return isBlockElement(blockElements, elm.dom);
  26859. }
  26860. );
  26861. };
  26862. const shouldRemoveTextNode = (blockElements, node) => {
  26863. if (isText$a(node)) {
  26864. if (node.data.length === 0) {
  26865. return true;
  26866. } else if (
  26867. /^\s+$/.test(node.data) &&
  26868. (!node.nextSibling || isBlockElement(blockElements, node.nextSibling))
  26869. ) {
  26870. return true;
  26871. }
  26872. }
  26873. return false;
  26874. };
  26875. const createRootBlock = (editor) =>
  26876. editor.dom.create(
  26877. getForcedRootBlock(editor),
  26878. getForcedRootBlockAttrs(editor)
  26879. );
  26880. const addRootBlocks = (editor) => {
  26881. const dom = editor.dom,
  26882. selection = editor.selection;
  26883. const schema = editor.schema;
  26884. const blockElements = schema.getBlockElements();
  26885. const startNode = selection.getStart();
  26886. const rootNode = editor.getBody();
  26887. let rootBlockNode;
  26888. let tempNode;
  26889. let wrapped = false;
  26890. const forcedRootBlock = getForcedRootBlock(editor);
  26891. if (!startNode || !isElement$6(startNode)) {
  26892. return;
  26893. }
  26894. const rootNodeName = rootNode.nodeName.toLowerCase();
  26895. if (
  26896. !schema.isValidChild(rootNodeName, forcedRootBlock.toLowerCase()) ||
  26897. hasBlockParent(blockElements, rootNode, startNode)
  26898. ) {
  26899. return;
  26900. }
  26901. const rng = selection.getRng();
  26902. const { startContainer, startOffset, endContainer, endOffset } = rng;
  26903. const restoreSelection = hasFocus(editor);
  26904. let node = rootNode.firstChild;
  26905. while (node) {
  26906. if (isElement$6(node)) {
  26907. updateElement(schema, node);
  26908. }
  26909. if (isValidTarget(schema, node)) {
  26910. if (shouldRemoveTextNode(blockElements, node)) {
  26911. tempNode = node;
  26912. node = node.nextSibling;
  26913. dom.remove(tempNode);
  26914. continue;
  26915. }
  26916. if (!rootBlockNode) {
  26917. rootBlockNode = createRootBlock(editor);
  26918. rootNode.insertBefore(rootBlockNode, node);
  26919. wrapped = true;
  26920. }
  26921. tempNode = node;
  26922. node = node.nextSibling;
  26923. rootBlockNode.appendChild(tempNode);
  26924. } else {
  26925. rootBlockNode = null;
  26926. node = node.nextSibling;
  26927. }
  26928. }
  26929. if (wrapped && restoreSelection) {
  26930. rng.setStart(startContainer, startOffset);
  26931. rng.setEnd(endContainer, endOffset);
  26932. selection.setRng(rng);
  26933. editor.nodeChanged();
  26934. }
  26935. };
  26936. const insertEmptyLine = (editor, root, insertBlock) => {
  26937. const block = SugarElement.fromDom(createRootBlock(editor));
  26938. const br = createPaddingBr();
  26939. append$1(block, br);
  26940. insertBlock(root, block);
  26941. const rng = document.createRange();
  26942. rng.setStartBefore(br.dom);
  26943. rng.setEndBefore(br.dom);
  26944. return rng;
  26945. };
  26946. const setup$n = (editor) => {
  26947. editor.on("NodeChange", curry(addRootBlocks, editor));
  26948. };
  26949. const hasClass = (checkClassName) => (node) =>
  26950. (" " + node.attr("class") + " ").indexOf(checkClassName) !== -1;
  26951. const replaceMatchWithSpan = (editor, content, cls) => {
  26952. return function (match) {
  26953. const args = arguments,
  26954. index = args[args.length - 2];
  26955. const prevChar = index > 0 ? content.charAt(index - 1) : "";
  26956. if (prevChar === '"') {
  26957. return match;
  26958. }
  26959. if (prevChar === ">") {
  26960. const findStartTagIndex = content.lastIndexOf("<", index);
  26961. if (findStartTagIndex !== -1) {
  26962. const tagHtml = content.substring(findStartTagIndex, index);
  26963. if (tagHtml.indexOf('contenteditable="false"') !== -1) {
  26964. return match;
  26965. }
  26966. }
  26967. }
  26968. return (
  26969. '<span class="' +
  26970. cls +
  26971. '" data-mce-content="' +
  26972. editor.dom.encode(args[0]) +
  26973. '">' +
  26974. editor.dom.encode(typeof args[1] === "string" ? args[1] : args[0]) +
  26975. "</span>"
  26976. );
  26977. };
  26978. };
  26979. const convertRegExpsToNonEditable = (editor, nonEditableRegExps, e) => {
  26980. let i = nonEditableRegExps.length,
  26981. content = e.content;
  26982. if (e.format === "raw") {
  26983. return;
  26984. }
  26985. while (i--) {
  26986. content = content.replace(
  26987. nonEditableRegExps[i],
  26988. replaceMatchWithSpan(editor, content, getNonEditableClass(editor))
  26989. );
  26990. }
  26991. e.content = content;
  26992. };
  26993. const setup$m = (editor) => {
  26994. const contentEditableAttrName = "contenteditable";
  26995. const editClass = " " + Tools.trim(getEditableClass(editor)) + " ";
  26996. const nonEditClass = " " + Tools.trim(getNonEditableClass(editor)) + " ";
  26997. const hasEditClass = hasClass(editClass);
  26998. const hasNonEditClass = hasClass(nonEditClass);
  26999. const nonEditableRegExps = getNonEditableRegExps(editor);
  27000. if (nonEditableRegExps.length > 0) {
  27001. editor.on("BeforeSetContent", (e) => {
  27002. convertRegExpsToNonEditable(editor, nonEditableRegExps, e);
  27003. });
  27004. }
  27005. editor.parser.addAttributeFilter("class", (nodes) => {
  27006. let i = nodes.length;
  27007. while (i--) {
  27008. const node = nodes[i];
  27009. if (hasEditClass(node)) {
  27010. node.attr(contentEditableAttrName, "true");
  27011. } else if (hasNonEditClass(node)) {
  27012. node.attr(contentEditableAttrName, "false");
  27013. }
  27014. }
  27015. });
  27016. editor.serializer.addAttributeFilter(contentEditableAttrName, (nodes) => {
  27017. let i = nodes.length;
  27018. while (i--) {
  27019. const node = nodes[i];
  27020. if (!hasEditClass(node) && !hasNonEditClass(node)) {
  27021. continue;
  27022. }
  27023. if (nonEditableRegExps.length > 0 && node.attr("data-mce-content")) {
  27024. node.name = "#text";
  27025. node.type = 3;
  27026. node.raw = true;
  27027. node.value = node.attr("data-mce-content");
  27028. } else {
  27029. node.attr(contentEditableAttrName, null);
  27030. }
  27031. }
  27032. });
  27033. };
  27034. const findBlockCaretContainer = (editor) =>
  27035. descendant(SugarElement.fromDom(editor.getBody()), "*[data-mce-caret]")
  27036. .map((elm) => elm.dom)
  27037. .getOrNull();
  27038. const showBlockCaretContainer = (editor, blockCaretContainer) => {
  27039. if (blockCaretContainer.hasAttribute("data-mce-caret")) {
  27040. showCaretContainerBlock(blockCaretContainer);
  27041. editor.selection.setRng(editor.selection.getRng());
  27042. editor.selection.scrollIntoView(blockCaretContainer);
  27043. }
  27044. };
  27045. const handleBlockContainer = (editor, e) => {
  27046. const blockCaretContainer = findBlockCaretContainer(editor);
  27047. if (!blockCaretContainer) {
  27048. return;
  27049. }
  27050. if (e.type === "compositionstart") {
  27051. e.preventDefault();
  27052. e.stopPropagation();
  27053. showBlockCaretContainer(editor, blockCaretContainer);
  27054. return;
  27055. }
  27056. if (hasContent(blockCaretContainer)) {
  27057. showBlockCaretContainer(editor, blockCaretContainer);
  27058. editor.undoManager.add();
  27059. }
  27060. };
  27061. const setup$l = (editor) => {
  27062. editor.on("keyup compositionstart", curry(handleBlockContainer, editor));
  27063. };
  27064. const isContentEditableFalse$3 = isContentEditableFalse$b;
  27065. const moveToCeFalseHorizontally = (direction, editor, range) =>
  27066. moveHorizontally(
  27067. editor,
  27068. direction,
  27069. range,
  27070. isBeforeContentEditableFalse,
  27071. isAfterContentEditableFalse,
  27072. isContentEditableFalse$3
  27073. );
  27074. const moveToCeFalseVertically = (direction, editor, range) => {
  27075. const isBefore = (caretPosition) =>
  27076. isBeforeContentEditableFalse(caretPosition) ||
  27077. isBeforeTable(caretPosition);
  27078. const isAfter = (caretPosition) =>
  27079. isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition);
  27080. return moveVertically(
  27081. editor,
  27082. direction,
  27083. range,
  27084. isBefore,
  27085. isAfter,
  27086. isContentEditableFalse$3
  27087. );
  27088. };
  27089. const createTextBlock = (editor) => {
  27090. const textBlock = editor.dom.create(getForcedRootBlock(editor));
  27091. textBlock.innerHTML = '<br data-mce-bogus="1">';
  27092. return textBlock;
  27093. };
  27094. const exitPreBlock = (editor, direction, range) => {
  27095. const caretWalker = CaretWalker(editor.getBody());
  27096. const getVisualCaretPosition$1 = curry(
  27097. getVisualCaretPosition,
  27098. direction === 1 ? caretWalker.next : caretWalker.prev
  27099. );
  27100. if (range.collapsed) {
  27101. const pre = editor.dom.getParent(range.startContainer, "PRE");
  27102. if (!pre) {
  27103. return;
  27104. }
  27105. const caretPos = getVisualCaretPosition$1(
  27106. CaretPosition.fromRangeStart(range)
  27107. );
  27108. if (!caretPos) {
  27109. const newBlock = SugarElement.fromDom(createTextBlock(editor));
  27110. if (direction === 1) {
  27111. after$4(SugarElement.fromDom(pre), newBlock);
  27112. } else {
  27113. before$3(SugarElement.fromDom(pre), newBlock);
  27114. }
  27115. editor.selection.select(newBlock.dom, true);
  27116. editor.selection.collapse();
  27117. }
  27118. }
  27119. };
  27120. const getHorizontalRange = (editor, forward) => {
  27121. const direction = forward ? HDirection.Forwards : HDirection.Backwards;
  27122. const range = editor.selection.getRng();
  27123. return moveToCeFalseHorizontally(direction, editor, range).orThunk(() => {
  27124. exitPreBlock(editor, direction, range);
  27125. return Optional.none();
  27126. });
  27127. };
  27128. const getVerticalRange = (editor, down) => {
  27129. const direction = down ? 1 : -1;
  27130. const range = editor.selection.getRng();
  27131. return moveToCeFalseVertically(direction, editor, range).orThunk(() => {
  27132. exitPreBlock(editor, direction, range);
  27133. return Optional.none();
  27134. });
  27135. };
  27136. const flipDirection = (selection, forward) => {
  27137. const elm = forward ? selection.getEnd(true) : selection.getStart(true);
  27138. return isRtl(elm) ? !forward : forward;
  27139. };
  27140. const moveH$2 = (editor, forward) =>
  27141. getHorizontalRange(editor, flipDirection(editor.selection, forward)).exists(
  27142. (newRange) => {
  27143. moveToRange(editor, newRange);
  27144. return true;
  27145. }
  27146. );
  27147. const moveV$4 = (editor, down) =>
  27148. getVerticalRange(editor, down).exists((newRange) => {
  27149. moveToRange(editor, newRange);
  27150. return true;
  27151. });
  27152. const moveToLineEndPoint$1 = (editor, forward) => {
  27153. const isCefPosition = forward
  27154. ? isAfterContentEditableFalse
  27155. : isBeforeContentEditableFalse;
  27156. return moveToLineEndPoint$3(editor, forward, isCefPosition);
  27157. };
  27158. const selectToEndPoint = (editor, forward) =>
  27159. getEdgeCefPosition(editor, !forward)
  27160. .map((pos) => {
  27161. const rng = pos.toRange();
  27162. const curRng = editor.selection.getRng();
  27163. if (forward) {
  27164. rng.setStart(curRng.startContainer, curRng.startOffset);
  27165. } else {
  27166. rng.setEnd(curRng.endContainer, curRng.endOffset);
  27167. }
  27168. return rng;
  27169. })
  27170. .exists((rng) => {
  27171. moveToRange(editor, rng);
  27172. return true;
  27173. });
  27174. const isTarget = (node) => contains$2(["figcaption"], name(node));
  27175. const getClosestTargetBlock = (pos, root) => {
  27176. const isRoot = curry(eq, root);
  27177. return closest$4(
  27178. SugarElement.fromDom(pos.container()),
  27179. isBlock$2,
  27180. isRoot
  27181. ).filter(isTarget);
  27182. };
  27183. const isAtFirstOrLastLine = (root, forward, pos) =>
  27184. forward ? isAtLastLine(root.dom, pos) : isAtFirstLine(root.dom, pos);
  27185. const moveCaretToNewEmptyLine = (editor, forward) => {
  27186. const root = SugarElement.fromDom(editor.getBody());
  27187. const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
  27188. return getClosestTargetBlock(pos, root).exists(() => {
  27189. if (isAtFirstOrLastLine(root, forward, pos)) {
  27190. const insertFn = forward ? append$1 : prepend;
  27191. const rng = insertEmptyLine(editor, root, insertFn);
  27192. editor.selection.setRng(rng);
  27193. return true;
  27194. } else {
  27195. return false;
  27196. }
  27197. });
  27198. };
  27199. const moveV$3 = (editor, forward) => {
  27200. if (editor.selection.isCollapsed()) {
  27201. return moveCaretToNewEmptyLine(editor, forward);
  27202. } else {
  27203. return false;
  27204. }
  27205. };
  27206. const moveUp = (editor, details, summary) => {
  27207. const rng = editor.selection.getRng();
  27208. const pos = CaretPosition.fromRangeStart(rng);
  27209. const root = editor.getBody();
  27210. if (root.firstChild === details && isAtFirstLine(summary, pos)) {
  27211. editor.execCommand("InsertNewBlockBefore");
  27212. return true;
  27213. } else {
  27214. return false;
  27215. }
  27216. };
  27217. const moveDown = (editor, details) => {
  27218. const rng = editor.selection.getRng();
  27219. const pos = CaretPosition.fromRangeStart(rng);
  27220. const root = editor.getBody();
  27221. if (root.lastChild === details && isAtLastLine(details, pos)) {
  27222. editor.execCommand("InsertNewBlockAfter");
  27223. return true;
  27224. } else {
  27225. return false;
  27226. }
  27227. };
  27228. const move$2 = (editor, forward) => {
  27229. if (forward) {
  27230. return Optional.from(
  27231. editor.dom.getParent(editor.selection.getNode(), "details")
  27232. )
  27233. .map((details) => moveDown(editor, details))
  27234. .getOr(false);
  27235. } else {
  27236. return Optional.from(
  27237. editor.dom.getParent(editor.selection.getNode(), "summary")
  27238. )
  27239. .bind((summary) =>
  27240. Optional.from(editor.dom.getParent(summary, "details")).map(
  27241. (details) => moveUp(editor, details, summary)
  27242. )
  27243. )
  27244. .getOr(false);
  27245. }
  27246. };
  27247. const moveV$2 = (editor, forward) => move$2(editor, forward);
  27248. const baseKeyPattern = {
  27249. shiftKey: false,
  27250. altKey: false,
  27251. ctrlKey: false,
  27252. metaKey: false,
  27253. keyCode: 0,
  27254. };
  27255. const defaultPatterns = (patterns) =>
  27256. map$3(patterns, (pattern) => ({
  27257. ...baseKeyPattern,
  27258. ...pattern,
  27259. }));
  27260. const defaultDelayedPatterns = (patterns) =>
  27261. map$3(patterns, (pattern) => ({
  27262. ...baseKeyPattern,
  27263. ...pattern,
  27264. }));
  27265. const matchesEvent = (pattern, evt) =>
  27266. evt.keyCode === pattern.keyCode &&
  27267. evt.shiftKey === pattern.shiftKey &&
  27268. evt.altKey === pattern.altKey &&
  27269. evt.ctrlKey === pattern.ctrlKey &&
  27270. evt.metaKey === pattern.metaKey;
  27271. const match$1 = (patterns, evt) =>
  27272. bind$3(defaultPatterns(patterns), (pattern) =>
  27273. matchesEvent(pattern, evt) ? [pattern] : []
  27274. );
  27275. const matchDelayed = (patterns, evt) =>
  27276. bind$3(defaultDelayedPatterns(patterns), (pattern) =>
  27277. matchesEvent(pattern, evt) ? [pattern] : []
  27278. );
  27279. const action =
  27280. (f, ...x) =>
  27281. () =>
  27282. f.apply(null, x);
  27283. const execute = (patterns, evt) =>
  27284. find$2(match$1(patterns, evt), (pattern) => pattern.action());
  27285. const executeWithDelayedAction = (patterns, evt) =>
  27286. findMap(matchDelayed(patterns, evt), (pattern) => pattern.action());
  27287. const moveH$1 = (editor, forward) => {
  27288. const direction = forward ? HDirection.Forwards : HDirection.Backwards;
  27289. const range = editor.selection.getRng();
  27290. return moveHorizontally(
  27291. editor,
  27292. direction,
  27293. range,
  27294. isBeforeMedia,
  27295. isAfterMedia,
  27296. isMedia$2
  27297. ).exists((newRange) => {
  27298. moveToRange(editor, newRange);
  27299. return true;
  27300. });
  27301. };
  27302. const moveV$1 = (editor, down) => {
  27303. const direction = down ? 1 : -1;
  27304. const range = editor.selection.getRng();
  27305. return moveVertically(
  27306. editor,
  27307. direction,
  27308. range,
  27309. isBeforeMedia,
  27310. isAfterMedia,
  27311. isMedia$2
  27312. ).exists((newRange) => {
  27313. moveToRange(editor, newRange);
  27314. return true;
  27315. });
  27316. };
  27317. const moveToLineEndPoint = (editor, forward) => {
  27318. const isNearMedia = forward ? isAfterMedia : isBeforeMedia;
  27319. return moveToLineEndPoint$3(editor, forward, isNearMedia);
  27320. };
  27321. const adt = Adt.generate([
  27322. { none: ["current"] },
  27323. { first: ["current"] },
  27324. {
  27325. middle: ["current", "target"],
  27326. },
  27327. { last: ["current"] },
  27328. ]);
  27329. const none = (current) => adt.none(current);
  27330. const CellLocation = {
  27331. ...adt,
  27332. none,
  27333. };
  27334. const firstLayer = (scope, selector) => {
  27335. return filterFirstLayer(scope, selector, always);
  27336. };
  27337. const filterFirstLayer = (scope, selector, predicate) => {
  27338. return bind$3(children$1(scope), (x) => {
  27339. if (is$1(x, selector)) {
  27340. return predicate(x) ? [x] : [];
  27341. } else {
  27342. return filterFirstLayer(x, selector, predicate);
  27343. }
  27344. });
  27345. };
  27346. const lookup$1 = (tags, element, isRoot = never) => {
  27347. if (isRoot(element)) {
  27348. return Optional.none();
  27349. }
  27350. if (contains$2(tags, name(element))) {
  27351. return Optional.some(element);
  27352. }
  27353. const isRootOrUpperTable = (elm) => is$1(elm, "table") || isRoot(elm);
  27354. return ancestor$3(element, tags.join(","), isRootOrUpperTable);
  27355. };
  27356. const cell = (element, isRoot) => lookup$1(["td", "th"], element, isRoot);
  27357. const cells = (ancestor) => firstLayer(ancestor, "th,td");
  27358. const table = (element, isRoot) => closest$3(element, "table", isRoot);
  27359. const walk = (all, current, index, direction, isEligible = always) => {
  27360. const forwards = direction === 1;
  27361. if (!forwards && index <= 0) {
  27362. return CellLocation.first(all[0]);
  27363. } else if (forwards && index >= all.length - 1) {
  27364. return CellLocation.last(all[all.length - 1]);
  27365. } else {
  27366. const newIndex = index + direction;
  27367. const elem = all[newIndex];
  27368. return isEligible(elem)
  27369. ? CellLocation.middle(current, elem)
  27370. : walk(all, current, newIndex, direction, isEligible);
  27371. }
  27372. };
  27373. const detect = (current, isRoot) => {
  27374. return table(current, isRoot).bind((table) => {
  27375. const all = cells(table);
  27376. const index = findIndex$2(all, (x) => eq(current, x));
  27377. return index.map((index) => ({
  27378. index,
  27379. all,
  27380. }));
  27381. });
  27382. };
  27383. const next = (current, isEligible, isRoot) => {
  27384. const detection = detect(current, isRoot);
  27385. return detection.fold(
  27386. () => {
  27387. return CellLocation.none(current);
  27388. },
  27389. (info) => {
  27390. return walk(info.all, current, info.index, 1, isEligible);
  27391. }
  27392. );
  27393. };
  27394. const prev = (current, isEligible, isRoot) => {
  27395. const detection = detect(current, isRoot);
  27396. return detection.fold(
  27397. () => {
  27398. return CellLocation.none();
  27399. },
  27400. (info) => {
  27401. return walk(info.all, current, info.index, -1, isEligible);
  27402. }
  27403. );
  27404. };
  27405. const deflate = (rect, delta) => ({
  27406. left: rect.left - delta,
  27407. top: rect.top - delta,
  27408. right: rect.right + delta * 2,
  27409. bottom: rect.bottom + delta * 2,
  27410. width: rect.width + delta,
  27411. height: rect.height + delta,
  27412. });
  27413. const getCorners = (getYAxisValue, tds) =>
  27414. bind$3(tds, (td) => {
  27415. const rect = deflate(clone$1(td.getBoundingClientRect()), -1);
  27416. return [
  27417. {
  27418. x: rect.left,
  27419. y: getYAxisValue(rect),
  27420. cell: td,
  27421. },
  27422. {
  27423. x: rect.right,
  27424. y: getYAxisValue(rect),
  27425. cell: td,
  27426. },
  27427. ];
  27428. });
  27429. const findClosestCorner = (corners, x, y) =>
  27430. foldl(
  27431. corners,
  27432. (acc, newCorner) =>
  27433. acc.fold(
  27434. () => Optional.some(newCorner),
  27435. (oldCorner) => {
  27436. const oldDist = Math.sqrt(
  27437. Math.abs(oldCorner.x - x) + Math.abs(oldCorner.y - y)
  27438. );
  27439. const newDist = Math.sqrt(
  27440. Math.abs(newCorner.x - x) + Math.abs(newCorner.y - y)
  27441. );
  27442. return Optional.some(newDist < oldDist ? newCorner : oldCorner);
  27443. }
  27444. ),
  27445. Optional.none()
  27446. );
  27447. const getClosestCell = (getYAxisValue, isTargetCorner, table, x, y) => {
  27448. const cells = descendants(SugarElement.fromDom(table), "td,th,caption").map(
  27449. (e) => e.dom
  27450. );
  27451. const corners = filter$5(getCorners(getYAxisValue, cells), (corner) =>
  27452. isTargetCorner(corner, y)
  27453. );
  27454. return findClosestCorner(corners, x, y).map((corner) => corner.cell);
  27455. };
  27456. const getBottomValue = (rect) => rect.bottom;
  27457. const getTopValue = (rect) => rect.top;
  27458. const isAbove = (corner, y) => corner.y < y;
  27459. const isBelow = (corner, y) => corner.y > y;
  27460. const getClosestCellAbove = curry(getClosestCell, getBottomValue, isAbove);
  27461. const getClosestCellBelow = curry(getClosestCell, getTopValue, isBelow);
  27462. const findClosestPositionInAboveCell = (table, pos) =>
  27463. head(pos.getClientRects())
  27464. .bind((rect) => getClosestCellAbove(table, rect.left, rect.top))
  27465. .bind((cell) =>
  27466. findClosestHorizontalPosition(getLastLinePositions(cell), pos)
  27467. );
  27468. const findClosestPositionInBelowCell = (table, pos) =>
  27469. last$3(pos.getClientRects())
  27470. .bind((rect) => getClosestCellBelow(table, rect.left, rect.top))
  27471. .bind((cell) =>
  27472. findClosestHorizontalPosition(getFirstLinePositions(cell), pos)
  27473. );
  27474. const hasNextBreak = (getPositionsUntil, scope, lineInfo) =>
  27475. lineInfo.breakAt.exists((breakPos) =>
  27476. getPositionsUntil(scope, breakPos).breakAt.isSome()
  27477. );
  27478. const startsWithWrapBreak = (lineInfo) =>
  27479. lineInfo.breakType === BreakType.Wrap && lineInfo.positions.length === 0;
  27480. const startsWithBrBreak = (lineInfo) =>
  27481. lineInfo.breakType === BreakType.Br && lineInfo.positions.length === 1;
  27482. const isAtTableCellLine = (getPositionsUntil, scope, pos) => {
  27483. const lineInfo = getPositionsUntil(scope, pos);
  27484. if (
  27485. startsWithWrapBreak(lineInfo) ||
  27486. (!isBr$6(pos.getNode()) && startsWithBrBreak(lineInfo))
  27487. ) {
  27488. return !hasNextBreak(getPositionsUntil, scope, lineInfo);
  27489. } else {
  27490. return lineInfo.breakAt.isNone();
  27491. }
  27492. };
  27493. const isAtFirstTableCellLine = curry(
  27494. isAtTableCellLine,
  27495. getPositionsUntilPreviousLine
  27496. );
  27497. const isAtLastTableCellLine = curry(
  27498. isAtTableCellLine,
  27499. getPositionsUntilNextLine
  27500. );
  27501. const isCaretAtStartOrEndOfTable = (forward, rng, table) => {
  27502. const caretPos = CaretPosition.fromRangeStart(rng);
  27503. return positionIn(!forward, table).exists((pos) => pos.isEqual(caretPos));
  27504. };
  27505. const navigateHorizontally = (editor, forward, table, _td) => {
  27506. const rng = editor.selection.getRng();
  27507. const direction = forward ? 1 : -1;
  27508. if (
  27509. isFakeCaretTableBrowser() &&
  27510. isCaretAtStartOrEndOfTable(forward, rng, table)
  27511. ) {
  27512. showCaret(direction, editor, table, !forward, false).each((newRng) => {
  27513. moveToRange(editor, newRng);
  27514. });
  27515. return true;
  27516. }
  27517. return false;
  27518. };
  27519. const getClosestAbovePosition = (root, table, start) =>
  27520. findClosestPositionInAboveCell(table, start)
  27521. .orThunk(() =>
  27522. head(start.getClientRects()).bind((rect) =>
  27523. findClosestHorizontalPositionFromPoint(
  27524. getPositionsAbove(root, CaretPosition.before(table)),
  27525. rect.left
  27526. )
  27527. )
  27528. )
  27529. .getOr(CaretPosition.before(table));
  27530. const getClosestBelowPosition = (root, table, start) =>
  27531. findClosestPositionInBelowCell(table, start)
  27532. .orThunk(() =>
  27533. head(start.getClientRects()).bind((rect) =>
  27534. findClosestHorizontalPositionFromPoint(
  27535. getPositionsBelow(root, CaretPosition.after(table)),
  27536. rect.left
  27537. )
  27538. )
  27539. )
  27540. .getOr(CaretPosition.after(table));
  27541. const getTable = (previous, pos) => {
  27542. const node = pos.getNode(previous);
  27543. return isTable$2(node) ? Optional.some(node) : Optional.none();
  27544. };
  27545. const renderBlock = (down, editor, table) => {
  27546. editor.undoManager.transact(() => {
  27547. const insertFn = down ? after$4 : before$3;
  27548. const rng = insertEmptyLine(
  27549. editor,
  27550. SugarElement.fromDom(table),
  27551. insertFn
  27552. );
  27553. moveToRange(editor, rng);
  27554. });
  27555. };
  27556. const moveCaret = (editor, down, pos) => {
  27557. const table = down ? getTable(true, pos) : getTable(false, pos);
  27558. const last = down === false;
  27559. table.fold(
  27560. () => moveToRange(editor, pos.toRange()),
  27561. (table) =>
  27562. positionIn(last, editor.getBody())
  27563. .filter((lastPos) => lastPos.isEqual(pos))
  27564. .fold(
  27565. () => moveToRange(editor, pos.toRange()),
  27566. (_) => renderBlock(down, editor, table)
  27567. )
  27568. );
  27569. };
  27570. const navigateVertically = (editor, down, table, td) => {
  27571. const rng = editor.selection.getRng();
  27572. const pos = CaretPosition.fromRangeStart(rng);
  27573. const root = editor.getBody();
  27574. if (!down && isAtFirstTableCellLine(td, pos)) {
  27575. const newPos = getClosestAbovePosition(root, table, pos);
  27576. moveCaret(editor, down, newPos);
  27577. return true;
  27578. } else if (down && isAtLastTableCellLine(td, pos)) {
  27579. const newPos = getClosestBelowPosition(root, table, pos);
  27580. moveCaret(editor, down, newPos);
  27581. return true;
  27582. } else {
  27583. return false;
  27584. }
  27585. };
  27586. const move$1 = (editor, forward, mover) =>
  27587. Optional.from(editor.dom.getParent(editor.selection.getNode(), "td,th"))
  27588. .bind((td) =>
  27589. Optional.from(editor.dom.getParent(td, "table")).map((table) =>
  27590. mover(editor, forward, table, td)
  27591. )
  27592. )
  27593. .getOr(false);
  27594. const moveH = (editor, forward) =>
  27595. move$1(editor, forward, navigateHorizontally);
  27596. const moveV = (editor, forward) =>
  27597. move$1(editor, forward, navigateVertically);
  27598. const getCellFirstCursorPosition = (cell) => {
  27599. const selection = SimSelection.exact(cell, 0, cell, 0);
  27600. return toNative(selection);
  27601. };
  27602. const tabGo = (editor, isRoot, cell) => {
  27603. return cell.fold(
  27604. Optional.none,
  27605. Optional.none,
  27606. (_current, next) => {
  27607. return first(next).map((cell) => {
  27608. return getCellFirstCursorPosition(cell);
  27609. });
  27610. },
  27611. (current) => {
  27612. editor.execCommand("mceTableInsertRowAfter");
  27613. return tabForward(editor, isRoot, current);
  27614. }
  27615. );
  27616. };
  27617. const tabForward = (editor, isRoot, cell) =>
  27618. tabGo(editor, isRoot, next(cell, isEditable$3));
  27619. const tabBackward = (editor, isRoot, cell) =>
  27620. tabGo(editor, isRoot, prev(cell, isEditable$3));
  27621. const handleTab = (editor, forward) => {
  27622. const rootElements = ["table", "li", "dl"];
  27623. const body = SugarElement.fromDom(editor.getBody());
  27624. const isRoot = (element) => {
  27625. const name$1 = name(element);
  27626. return eq(element, body) || contains$2(rootElements, name$1);
  27627. };
  27628. const rng = editor.selection.getRng();
  27629. const container = SugarElement.fromDom(
  27630. !forward ? rng.startContainer : rng.endContainer
  27631. );
  27632. return cell(container, isRoot)
  27633. .map((cell) => {
  27634. table(cell, isRoot).each((table) => {
  27635. editor.model.table.clearSelectedCells(table.dom);
  27636. });
  27637. editor.selection.collapse(!forward);
  27638. const navigation = !forward ? tabBackward : tabForward;
  27639. const rng = navigation(editor, isRoot, cell);
  27640. rng.each((range) => {
  27641. editor.selection.setRng(range);
  27642. });
  27643. return true;
  27644. })
  27645. .getOr(false);
  27646. };
  27647. const executeKeydownOverride$4 = (editor, caret, evt) => {
  27648. const isMac = Env.os.isMacOS() || Env.os.isiOS();
  27649. execute(
  27650. [
  27651. {
  27652. keyCode: VK.RIGHT,
  27653. action: action(moveH$2, editor, true),
  27654. },
  27655. {
  27656. keyCode: VK.LEFT,
  27657. action: action(moveH$2, editor, false),
  27658. },
  27659. {
  27660. keyCode: VK.UP,
  27661. action: action(moveV$4, editor, false),
  27662. },
  27663. {
  27664. keyCode: VK.DOWN,
  27665. action: action(moveV$4, editor, true),
  27666. },
  27667. ...(isMac
  27668. ? [
  27669. {
  27670. keyCode: VK.UP,
  27671. action: action(selectToEndPoint, editor, false),
  27672. metaKey: true,
  27673. shiftKey: true,
  27674. },
  27675. {
  27676. keyCode: VK.DOWN,
  27677. action: action(selectToEndPoint, editor, true),
  27678. metaKey: true,
  27679. shiftKey: true,
  27680. },
  27681. ]
  27682. : []),
  27683. {
  27684. keyCode: VK.RIGHT,
  27685. action: action(moveH, editor, true),
  27686. },
  27687. {
  27688. keyCode: VK.LEFT,
  27689. action: action(moveH, editor, false),
  27690. },
  27691. {
  27692. keyCode: VK.UP,
  27693. action: action(moveV, editor, false),
  27694. },
  27695. {
  27696. keyCode: VK.DOWN,
  27697. action: action(moveV, editor, true),
  27698. },
  27699. {
  27700. keyCode: VK.UP,
  27701. action: action(moveV, editor, false),
  27702. },
  27703. {
  27704. keyCode: VK.UP,
  27705. action: action(moveV$2, editor, false),
  27706. },
  27707. {
  27708. keyCode: VK.DOWN,
  27709. action: action(moveV$2, editor, true),
  27710. },
  27711. {
  27712. keyCode: VK.RIGHT,
  27713. action: action(moveH$1, editor, true),
  27714. },
  27715. {
  27716. keyCode: VK.LEFT,
  27717. action: action(moveH$1, editor, false),
  27718. },
  27719. {
  27720. keyCode: VK.UP,
  27721. action: action(moveV$1, editor, false),
  27722. },
  27723. {
  27724. keyCode: VK.DOWN,
  27725. action: action(moveV$1, editor, true),
  27726. },
  27727. {
  27728. keyCode: VK.RIGHT,
  27729. action: action(move$3, editor, caret, true),
  27730. },
  27731. {
  27732. keyCode: VK.LEFT,
  27733. action: action(move$3, editor, caret, false),
  27734. },
  27735. {
  27736. keyCode: VK.RIGHT,
  27737. ctrlKey: !isMac,
  27738. altKey: isMac,
  27739. action: action(moveNextWord, editor, caret),
  27740. },
  27741. {
  27742. keyCode: VK.LEFT,
  27743. ctrlKey: !isMac,
  27744. altKey: isMac,
  27745. action: action(movePrevWord, editor, caret),
  27746. },
  27747. {
  27748. keyCode: VK.UP,
  27749. action: action(moveV$3, editor, false),
  27750. },
  27751. {
  27752. keyCode: VK.DOWN,
  27753. action: action(moveV$3, editor, true),
  27754. },
  27755. ],
  27756. evt
  27757. ).each((_) => {
  27758. evt.preventDefault();
  27759. });
  27760. };
  27761. const setup$k = (editor, caret) => {
  27762. editor.on("keydown", (evt) => {
  27763. if (!evt.isDefaultPrevented()) {
  27764. executeKeydownOverride$4(editor, caret, evt);
  27765. }
  27766. });
  27767. };
  27768. const point = (container, offset) => ({
  27769. container,
  27770. offset,
  27771. });
  27772. const DOM$7 = DOMUtils.DOM;
  27773. const alwaysNext = (startNode) => (node) => startNode === node ? -1 : 0;
  27774. const isBoundary = (dom) => (node) =>
  27775. dom.isBlock(node) ||
  27776. contains$2(["BR", "IMG", "HR", "INPUT"], node.nodeName) ||
  27777. dom.getContentEditable(node) === "false";
  27778. const textBefore = (node, offset, rootNode) => {
  27779. if (isText$a(node) && offset >= 0) {
  27780. return Optional.some(point(node, offset));
  27781. } else {
  27782. const textSeeker = TextSeeker(DOM$7);
  27783. return Optional.from(
  27784. textSeeker.backwards(node, offset, alwaysNext(node), rootNode)
  27785. ).map((prev) => point(prev.container, prev.container.data.length));
  27786. }
  27787. };
  27788. const textAfter = (node, offset, rootNode) => {
  27789. if (isText$a(node) && offset >= node.length) {
  27790. return Optional.some(point(node, offset));
  27791. } else {
  27792. const textSeeker = TextSeeker(DOM$7);
  27793. return Optional.from(
  27794. textSeeker.forwards(node, offset, alwaysNext(node), rootNode)
  27795. ).map((prev) => point(prev.container, 0));
  27796. }
  27797. };
  27798. const scanLeft = (node, offset, rootNode) => {
  27799. if (!isText$a(node)) {
  27800. return Optional.none();
  27801. }
  27802. const text = node.data;
  27803. if (offset >= 0 && offset <= text.length) {
  27804. return Optional.some(point(node, offset));
  27805. } else {
  27806. const textSeeker = TextSeeker(DOM$7);
  27807. return Optional.from(
  27808. textSeeker.backwards(node, offset, alwaysNext(node), rootNode)
  27809. ).bind((prev) => {
  27810. const prevText = prev.container.data;
  27811. return scanLeft(prev.container, offset + prevText.length, rootNode);
  27812. });
  27813. }
  27814. };
  27815. const scanRight = (node, offset, rootNode) => {
  27816. if (!isText$a(node)) {
  27817. return Optional.none();
  27818. }
  27819. const text = node.data;
  27820. if (offset <= text.length) {
  27821. return Optional.some(point(node, offset));
  27822. } else {
  27823. const textSeeker = TextSeeker(DOM$7);
  27824. return Optional.from(
  27825. textSeeker.forwards(node, offset, alwaysNext(node), rootNode)
  27826. ).bind((next) =>
  27827. scanRight(next.container, offset - text.length, rootNode)
  27828. );
  27829. }
  27830. };
  27831. const repeatLeft = (dom, node, offset, process, rootNode) => {
  27832. const search = TextSeeker(dom, isBoundary(dom));
  27833. return Optional.from(search.backwards(node, offset, process, rootNode));
  27834. };
  27835. const isValidTextRange = (rng) =>
  27836. rng.collapsed && isText$a(rng.startContainer);
  27837. const getText = (rng) => trim$1(rng.toString().replace(/\u00A0/g, " "));
  27838. const isWhitespace = (chr) =>
  27839. chr !== "" && " \xA0\f\n\r\t\x0B".indexOf(chr) !== -1;
  27840. const stripTrigger = (text, trigger) => text.substring(trigger.length);
  27841. const findTrigger = (text, index, trigger) => {
  27842. let i;
  27843. const firstChar = trigger.charAt(0);
  27844. for (i = index - 1; i >= 0; i--) {
  27845. const char = text.charAt(i);
  27846. if (isWhitespace(char)) {
  27847. return Optional.none();
  27848. }
  27849. if (firstChar === char && contains$1(text, trigger, i, index)) {
  27850. break;
  27851. }
  27852. }
  27853. return Optional.some(i);
  27854. };
  27855. const findStart = (dom, initRange, trigger, minChars = 0) => {
  27856. if (!isValidTextRange(initRange)) {
  27857. return Optional.none();
  27858. }
  27859. const buffer = {
  27860. text: "",
  27861. offset: 0,
  27862. };
  27863. const findTriggerIndex = (element, offset, text) => {
  27864. buffer.text = text + buffer.text;
  27865. buffer.offset += offset;
  27866. return findTrigger(buffer.text, buffer.offset, trigger).getOr(offset);
  27867. };
  27868. const root =
  27869. dom.getParent(initRange.startContainer, dom.isBlock) || dom.getRoot();
  27870. return repeatLeft(
  27871. dom,
  27872. initRange.startContainer,
  27873. initRange.startOffset,
  27874. findTriggerIndex,
  27875. root
  27876. ).bind((spot) => {
  27877. const range = initRange.cloneRange();
  27878. range.setStart(spot.container, spot.offset);
  27879. range.setEnd(initRange.endContainer, initRange.endOffset);
  27880. if (range.collapsed) {
  27881. return Optional.none();
  27882. }
  27883. const text = getText(range);
  27884. const triggerIndex = text.lastIndexOf(trigger);
  27885. if (triggerIndex !== 0 || stripTrigger(text, trigger).length < minChars) {
  27886. return Optional.none();
  27887. } else {
  27888. return Optional.some({
  27889. text: stripTrigger(text, trigger),
  27890. range,
  27891. trigger,
  27892. });
  27893. }
  27894. });
  27895. };
  27896. const getContext = (dom, initRange, trigger, minChars = 0) =>
  27897. detect$1(SugarElement.fromDom(initRange.startContainer)).fold(
  27898. () => findStart(dom, initRange, trigger, minChars),
  27899. (elm) => {
  27900. const range = dom.createRng();
  27901. range.selectNode(elm.dom);
  27902. const text = getText(range);
  27903. return Optional.some({
  27904. range,
  27905. text: stripTrigger(text, trigger),
  27906. trigger,
  27907. });
  27908. }
  27909. );
  27910. const isText$1 = (node) => node.nodeType === TEXT;
  27911. const isElement = (node) => node.nodeType === ELEMENT;
  27912. const toLast = (node) => {
  27913. if (isText$1(node)) {
  27914. return point(node, node.data.length);
  27915. } else {
  27916. const children = node.childNodes;
  27917. return children.length > 0
  27918. ? toLast(children[children.length - 1])
  27919. : point(node, children.length);
  27920. }
  27921. };
  27922. const toLeaf = (node, offset) => {
  27923. const children = node.childNodes;
  27924. if (children.length > 0 && offset < children.length) {
  27925. return toLeaf(children[offset], 0);
  27926. } else if (
  27927. children.length > 0 &&
  27928. isElement(node) &&
  27929. children.length === offset
  27930. ) {
  27931. return toLast(children[children.length - 1]);
  27932. } else {
  27933. return point(node, offset);
  27934. }
  27935. };
  27936. const isPreviousCharContent = (dom, leaf) => {
  27937. var _a;
  27938. const root =
  27939. (_a = dom.getParent(leaf.container, dom.isBlock)) !== null &&
  27940. _a !== void 0
  27941. ? _a
  27942. : dom.getRoot();
  27943. return repeatLeft(
  27944. dom,
  27945. leaf.container,
  27946. leaf.offset,
  27947. (_element, offset) => (offset === 0 ? -1 : offset),
  27948. root
  27949. )
  27950. .filter((spot) => {
  27951. const char = spot.container.data.charAt(spot.offset - 1);
  27952. return !isWhitespace(char);
  27953. })
  27954. .isSome();
  27955. };
  27956. const isStartOfWord = (dom) => (rng) => {
  27957. const leaf = toLeaf(rng.startContainer, rng.startOffset);
  27958. return !isPreviousCharContent(dom, leaf);
  27959. };
  27960. const getTriggerContext = (dom, initRange, database) =>
  27961. findMap(database.triggers, (trigger) =>
  27962. getContext(dom, initRange, trigger)
  27963. );
  27964. const lookup = (editor, getDatabase) => {
  27965. const database = getDatabase();
  27966. const rng = editor.selection.getRng();
  27967. return getTriggerContext(editor.dom, rng, database).bind((context) =>
  27968. lookupWithContext(editor, getDatabase, context)
  27969. );
  27970. };
  27971. const lookupWithContext = (
  27972. editor,
  27973. getDatabase,
  27974. context,
  27975. fetchOptions = {}
  27976. ) => {
  27977. var _a;
  27978. const database = getDatabase();
  27979. const rng = editor.selection.getRng();
  27980. const startText =
  27981. (_a = rng.startContainer.nodeValue) !== null && _a !== void 0 ? _a : "";
  27982. const autocompleters = filter$5(
  27983. database.lookupByTrigger(context.trigger),
  27984. (autocompleter) =>
  27985. context.text.length >= autocompleter.minChars &&
  27986. autocompleter.matches.getOrThunk(() => isStartOfWord(editor.dom))(
  27987. context.range,
  27988. startText,
  27989. context.text
  27990. )
  27991. );
  27992. if (autocompleters.length === 0) {
  27993. return Optional.none();
  27994. }
  27995. const lookupData = Promise.all(
  27996. map$3(autocompleters, (ac) => {
  27997. const fetchResult = ac.fetch(context.text, ac.maxResults, fetchOptions);
  27998. return fetchResult.then((results) => ({
  27999. matchText: context.text,
  28000. items: results,
  28001. columns: ac.columns,
  28002. onAction: ac.onAction,
  28003. highlightOn: ac.highlightOn,
  28004. }));
  28005. })
  28006. );
  28007. return Optional.some({
  28008. lookupData,
  28009. context,
  28010. });
  28011. };
  28012. var SimpleResultType;
  28013. (function (SimpleResultType) {
  28014. SimpleResultType[(SimpleResultType["Error"] = 0)] = "Error";
  28015. SimpleResultType[(SimpleResultType["Value"] = 1)] = "Value";
  28016. })(SimpleResultType || (SimpleResultType = {}));
  28017. const fold$1 = (res, onError, onValue) =>
  28018. res.stype === SimpleResultType.Error
  28019. ? onError(res.serror)
  28020. : onValue(res.svalue);
  28021. const partition = (results) => {
  28022. const values = [];
  28023. const errors = [];
  28024. each$e(results, (obj) => {
  28025. fold$1(
  28026. obj,
  28027. (err) => errors.push(err),
  28028. (val) => values.push(val)
  28029. );
  28030. });
  28031. return {
  28032. values,
  28033. errors,
  28034. };
  28035. };
  28036. const mapError = (res, f) => {
  28037. if (res.stype === SimpleResultType.Error) {
  28038. return {
  28039. stype: SimpleResultType.Error,
  28040. serror: f(res.serror),
  28041. };
  28042. } else {
  28043. return res;
  28044. }
  28045. };
  28046. const map = (res, f) => {
  28047. if (res.stype === SimpleResultType.Value) {
  28048. return {
  28049. stype: SimpleResultType.Value,
  28050. svalue: f(res.svalue),
  28051. };
  28052. } else {
  28053. return res;
  28054. }
  28055. };
  28056. const bind$1 = (res, f) => {
  28057. if (res.stype === SimpleResultType.Value) {
  28058. return f(res.svalue);
  28059. } else {
  28060. return res;
  28061. }
  28062. };
  28063. const bindError = (res, f) => {
  28064. if (res.stype === SimpleResultType.Error) {
  28065. return f(res.serror);
  28066. } else {
  28067. return res;
  28068. }
  28069. };
  28070. const svalue = (v) => ({
  28071. stype: SimpleResultType.Value,
  28072. svalue: v,
  28073. });
  28074. const serror = (e) => ({
  28075. stype: SimpleResultType.Error,
  28076. serror: e,
  28077. });
  28078. const toResult = (res) => fold$1(res, Result.error, Result.value);
  28079. const fromResult = (res) => res.fold(serror, svalue);
  28080. const SimpleResult = {
  28081. fromResult,
  28082. toResult,
  28083. svalue,
  28084. partition,
  28085. serror,
  28086. bind: bind$1,
  28087. bindError,
  28088. map,
  28089. mapError,
  28090. fold: fold$1,
  28091. };
  28092. const formatObj = (input) => {
  28093. return isObject(input) && keys(input).length > 100
  28094. ? " removed due to size"
  28095. : JSON.stringify(input, null, 2);
  28096. };
  28097. const formatErrors = (errors) => {
  28098. const es =
  28099. errors.length > 10
  28100. ? errors.slice(0, 10).concat([
  28101. {
  28102. path: [],
  28103. getErrorInfo: constant("... (only showing first ten failures)"),
  28104. },
  28105. ])
  28106. : errors;
  28107. return map$3(es, (e) => {
  28108. return "Failed path: (" + e.path.join(" > ") + ")\n" + e.getErrorInfo();
  28109. });
  28110. };
  28111. const nu = (path, getErrorInfo) => {
  28112. return SimpleResult.serror([
  28113. {
  28114. path,
  28115. getErrorInfo,
  28116. },
  28117. ]);
  28118. };
  28119. const missingRequired = (path, key, obj) =>
  28120. nu(
  28121. path,
  28122. () =>
  28123. 'Could not find valid *required* value for "' +
  28124. key +
  28125. '" in ' +
  28126. formatObj(obj)
  28127. );
  28128. const missingKey = (path, key) =>
  28129. nu(path, () => 'Choice schema did not contain choice key: "' + key + '"');
  28130. const missingBranch = (path, branches, branch) =>
  28131. nu(
  28132. path,
  28133. () =>
  28134. 'The chosen schema: "' +
  28135. branch +
  28136. '" did not exist in branches: ' +
  28137. formatObj(branches)
  28138. );
  28139. const custom = (path, err) => nu(path, constant(err));
  28140. const chooseFrom = (path, input, branches, ch) => {
  28141. const fields = get$a(branches, ch);
  28142. return fields.fold(
  28143. () => missingBranch(path, branches, ch),
  28144. (vp) => vp.extract(path.concat(["branch: " + ch]), input)
  28145. );
  28146. };
  28147. const choose$1 = (key, branches) => {
  28148. const extract = (path, input) => {
  28149. const choice = get$a(input, key);
  28150. return choice.fold(
  28151. () => missingKey(path, key),
  28152. (chosen) => chooseFrom(path, input, branches, chosen)
  28153. );
  28154. };
  28155. const toString = () =>
  28156. "chooseOn(" + key + "). Possible values: " + keys(branches);
  28157. return {
  28158. extract,
  28159. toString,
  28160. };
  28161. };
  28162. const shallow = (old, nu) => {
  28163. return nu;
  28164. };
  28165. const deep = (old, nu) => {
  28166. const bothObjects = isPlainObject(old) && isPlainObject(nu);
  28167. return bothObjects ? deepMerge(old, nu) : nu;
  28168. };
  28169. const baseMerge = (merger) => {
  28170. return (...objects) => {
  28171. if (objects.length === 0) {
  28172. throw new Error(`Can't merge zero objects`);
  28173. }
  28174. const ret = {};
  28175. for (let j = 0; j < objects.length; j++) {
  28176. const curObject = objects[j];
  28177. for (const key in curObject) {
  28178. if (has$2(curObject, key)) {
  28179. ret[key] = merger(ret[key], curObject[key]);
  28180. }
  28181. }
  28182. }
  28183. return ret;
  28184. };
  28185. };
  28186. const deepMerge = baseMerge(deep);
  28187. const merge = baseMerge(shallow);
  28188. const required = () => ({
  28189. tag: "required",
  28190. process: {},
  28191. });
  28192. const defaultedThunk = (fallbackThunk) => ({
  28193. tag: "defaultedThunk",
  28194. process: fallbackThunk,
  28195. });
  28196. const defaulted$1 = (fallback) => defaultedThunk(constant(fallback));
  28197. const asOption = () => ({
  28198. tag: "option",
  28199. process: {},
  28200. });
  28201. const mergeValues = (values, base) =>
  28202. values.length > 0
  28203. ? SimpleResult.svalue(deepMerge(base, merge.apply(undefined, values)))
  28204. : SimpleResult.svalue(base);
  28205. const mergeErrors = (errors) => compose(SimpleResult.serror, flatten)(errors);
  28206. const consolidateObj = (objects, base) => {
  28207. const partition = SimpleResult.partition(objects);
  28208. return partition.errors.length > 0
  28209. ? mergeErrors(partition.errors)
  28210. : mergeValues(partition.values, base);
  28211. };
  28212. const consolidateArr = (objects) => {
  28213. const partitions = SimpleResult.partition(objects);
  28214. return partitions.errors.length > 0
  28215. ? mergeErrors(partitions.errors)
  28216. : SimpleResult.svalue(partitions.values);
  28217. };
  28218. const ResultCombine = {
  28219. consolidateObj,
  28220. consolidateArr,
  28221. };
  28222. const field$1 = (key, newKey, presence, prop) => ({
  28223. tag: "field",
  28224. key,
  28225. newKey,
  28226. presence,
  28227. prop,
  28228. });
  28229. const customField$1 = (newKey, instantiator) => ({
  28230. tag: "custom",
  28231. newKey,
  28232. instantiator,
  28233. });
  28234. const fold = (value, ifField, ifCustom) => {
  28235. switch (value.tag) {
  28236. case "field":
  28237. return ifField(value.key, value.newKey, value.presence, value.prop);
  28238. case "custom":
  28239. return ifCustom(value.newKey, value.instantiator);
  28240. }
  28241. };
  28242. const value = (validator) => {
  28243. const extract = (path, val) => {
  28244. return SimpleResult.bindError(validator(val), (err) => custom(path, err));
  28245. };
  28246. const toString = constant("val");
  28247. return {
  28248. extract,
  28249. toString,
  28250. };
  28251. };
  28252. const anyValue$1 = value(SimpleResult.svalue);
  28253. const requiredAccess = (path, obj, key, bundle) =>
  28254. get$a(obj, key).fold(() => missingRequired(path, key, obj), bundle);
  28255. const fallbackAccess = (obj, key, fallback, bundle) => {
  28256. const v = get$a(obj, key).getOrThunk(() => fallback(obj));
  28257. return bundle(v);
  28258. };
  28259. const optionAccess = (obj, key, bundle) => bundle(get$a(obj, key));
  28260. const optionDefaultedAccess = (obj, key, fallback, bundle) => {
  28261. const opt = get$a(obj, key).map((val) =>
  28262. val === true ? fallback(obj) : val
  28263. );
  28264. return bundle(opt);
  28265. };
  28266. const extractField = (field, path, obj, key, prop) => {
  28267. const bundle = (av) => prop.extract(path.concat([key]), av);
  28268. const bundleAsOption = (optValue) =>
  28269. optValue.fold(
  28270. () => SimpleResult.svalue(Optional.none()),
  28271. (ov) => {
  28272. const result = prop.extract(path.concat([key]), ov);
  28273. return SimpleResult.map(result, Optional.some);
  28274. }
  28275. );
  28276. switch (field.tag) {
  28277. case "required":
  28278. return requiredAccess(path, obj, key, bundle);
  28279. case "defaultedThunk":
  28280. return fallbackAccess(obj, key, field.process, bundle);
  28281. case "option":
  28282. return optionAccess(obj, key, bundleAsOption);
  28283. case "defaultedOptionThunk":
  28284. return optionDefaultedAccess(obj, key, field.process, bundleAsOption);
  28285. case "mergeWithThunk": {
  28286. return fallbackAccess(obj, key, constant({}), (v) => {
  28287. const result = deepMerge(field.process(obj), v);
  28288. return bundle(result);
  28289. });
  28290. }
  28291. }
  28292. };
  28293. const extractFields = (path, obj, fields) => {
  28294. const success = {};
  28295. const errors = [];
  28296. for (const field of fields) {
  28297. fold(
  28298. field,
  28299. (key, newKey, presence, prop) => {
  28300. const result = extractField(presence, path, obj, key, prop);
  28301. SimpleResult.fold(
  28302. result,
  28303. (err) => {
  28304. errors.push(...err);
  28305. },
  28306. (res) => {
  28307. success[newKey] = res;
  28308. }
  28309. );
  28310. },
  28311. (newKey, instantiator) => {
  28312. success[newKey] = instantiator(obj);
  28313. }
  28314. );
  28315. }
  28316. return errors.length > 0
  28317. ? SimpleResult.serror(errors)
  28318. : SimpleResult.svalue(success);
  28319. };
  28320. const objOf = (values) => {
  28321. const extract = (path, o) => extractFields(path, o, values);
  28322. const toString = () => {
  28323. const fieldStrings = map$3(values, (value) =>
  28324. fold(
  28325. value,
  28326. (key, _okey, _presence, prop) => key + " -> " + prop.toString(),
  28327. (newKey, _instantiator) => "state(" + newKey + ")"
  28328. )
  28329. );
  28330. return "obj{\n" + fieldStrings.join("\n") + "}";
  28331. };
  28332. return {
  28333. extract,
  28334. toString,
  28335. };
  28336. };
  28337. const arrOf = (prop) => {
  28338. const extract = (path, array) => {
  28339. const results = map$3(array, (a, i) =>
  28340. prop.extract(path.concat(["[" + i + "]"]), a)
  28341. );
  28342. return ResultCombine.consolidateArr(results);
  28343. };
  28344. const toString = () => "array(" + prop.toString() + ")";
  28345. return {
  28346. extract,
  28347. toString,
  28348. };
  28349. };
  28350. const valueOf = (validator) =>
  28351. value((v) => validator(v).fold(SimpleResult.serror, SimpleResult.svalue));
  28352. const extractValue = (label, prop, obj) => {
  28353. const res = prop.extract([label], obj);
  28354. return SimpleResult.mapError(res, (errs) => ({
  28355. input: obj,
  28356. errors: errs,
  28357. }));
  28358. };
  28359. const asRaw = (label, prop, obj) =>
  28360. SimpleResult.toResult(extractValue(label, prop, obj));
  28361. const formatError = (errInfo) => {
  28362. return (
  28363. "Errors: \n" +
  28364. formatErrors(errInfo.errors).join("\n") +
  28365. "\n\nInput object: " +
  28366. formatObj(errInfo.input)
  28367. );
  28368. };
  28369. const choose = (key, branches) => choose$1(key, map$2(branches, objOf));
  28370. const anyValue = constant(anyValue$1);
  28371. const typedValue = (validator, expectedType) =>
  28372. value((a) => {
  28373. const actualType = typeof a;
  28374. return validator(a)
  28375. ? SimpleResult.svalue(a)
  28376. : SimpleResult.serror(
  28377. `Expected type: ${expectedType} but got: ${actualType}`
  28378. );
  28379. });
  28380. const number = typedValue(isNumber, "number");
  28381. const string = typedValue(isString, "string");
  28382. const boolean = typedValue(isBoolean, "boolean");
  28383. const functionProcessor = typedValue(isFunction, "function");
  28384. const field = field$1;
  28385. const customField = customField$1;
  28386. const validateEnum = (values) =>
  28387. valueOf((value) =>
  28388. contains$2(values, value)
  28389. ? Result.value(value)
  28390. : Result.error(
  28391. `Unsupported value: "${value}", choose one of "${values.join(
  28392. ", "
  28393. )}".`
  28394. )
  28395. );
  28396. const requiredOf = (key, schema) => field(key, key, required(), schema);
  28397. const requiredString = (key) => requiredOf(key, string);
  28398. const requiredFunction = (key) => requiredOf(key, functionProcessor);
  28399. const requiredArrayOf = (key, schema) =>
  28400. field(key, key, required(), arrOf(schema));
  28401. const optionOf = (key, schema) => field(key, key, asOption(), schema);
  28402. const optionString = (key) => optionOf(key, string);
  28403. const optionFunction = (key) => optionOf(key, functionProcessor);
  28404. const defaulted = (key, fallback) =>
  28405. field(key, key, defaulted$1(fallback), anyValue());
  28406. const defaultedOf = (key, fallback, schema) =>
  28407. field(key, key, defaulted$1(fallback), schema);
  28408. const defaultedNumber = (key, fallback) => defaultedOf(key, fallback, number);
  28409. const defaultedString = (key, fallback) => defaultedOf(key, fallback, string);
  28410. const defaultedStringEnum = (key, fallback, values) =>
  28411. defaultedOf(key, fallback, validateEnum(values));
  28412. const defaultedBoolean = (key, fallback) =>
  28413. defaultedOf(key, fallback, boolean);
  28414. const defaultedFunction = (key, fallback) =>
  28415. defaultedOf(key, fallback, functionProcessor);
  28416. const defaultedArrayOf = (key, fallback, schema) =>
  28417. defaultedOf(key, fallback, arrOf(schema));
  28418. const type = requiredString("type");
  28419. const fetch$1 = requiredFunction("fetch");
  28420. const onAction = requiredFunction("onAction");
  28421. const onSetup = defaultedFunction("onSetup", () => noop);
  28422. const optionalText = optionString("text");
  28423. const optionalIcon = optionString("icon");
  28424. const optionalTooltip = optionString("tooltip");
  28425. const optionalLabel = optionString("label");
  28426. const active = defaultedBoolean("active", false);
  28427. const enabled = defaultedBoolean("enabled", true);
  28428. const primary = defaultedBoolean("primary", false);
  28429. const defaultedColumns = (num) => defaulted("columns", num);
  28430. const defaultedType = (type) => defaultedString("type", type);
  28431. const autocompleterSchema = objOf([
  28432. type,
  28433. requiredString("trigger"),
  28434. defaultedNumber("minChars", 1),
  28435. defaultedColumns(1),
  28436. defaultedNumber("maxResults", 10),
  28437. optionFunction("matches"),
  28438. fetch$1,
  28439. onAction,
  28440. defaultedArrayOf("highlightOn", [], string),
  28441. ]);
  28442. const createAutocompleter = (spec) =>
  28443. asRaw("Autocompleter", autocompleterSchema, {
  28444. trigger: spec.ch,
  28445. ...spec,
  28446. });
  28447. const baseToolbarButtonFields = [
  28448. enabled,
  28449. optionalTooltip,
  28450. optionalIcon,
  28451. optionalText,
  28452. onSetup,
  28453. ];
  28454. const baseToolbarToggleButtonFields = [active].concat(
  28455. baseToolbarButtonFields
  28456. );
  28457. const contextBarFields = [
  28458. defaultedFunction("predicate", never),
  28459. defaultedStringEnum("scope", "node", ["node", "editor"]),
  28460. defaultedStringEnum("position", "selection", ["node", "selection", "line"]),
  28461. ];
  28462. const contextButtonFields = baseToolbarButtonFields.concat([
  28463. defaultedType("contextformbutton"),
  28464. primary,
  28465. onAction,
  28466. customField("original", identity),
  28467. ]);
  28468. const contextToggleButtonFields = baseToolbarToggleButtonFields.concat([
  28469. defaultedType("contextformbutton"),
  28470. primary,
  28471. onAction,
  28472. customField("original", identity),
  28473. ]);
  28474. const launchButtonFields = baseToolbarButtonFields.concat([
  28475. defaultedType("contextformbutton"),
  28476. ]);
  28477. const launchToggleButtonFields = baseToolbarToggleButtonFields.concat([
  28478. defaultedType("contextformtogglebutton"),
  28479. ]);
  28480. const toggleOrNormal = choose("type", {
  28481. contextformbutton: contextButtonFields,
  28482. contextformtogglebutton: contextToggleButtonFields,
  28483. });
  28484. objOf(
  28485. [
  28486. defaultedType("contextform"),
  28487. defaultedFunction("initValue", constant("")),
  28488. optionalLabel,
  28489. requiredArrayOf("commands", toggleOrNormal),
  28490. optionOf(
  28491. "launch",
  28492. choose("type", {
  28493. contextformbutton: launchButtonFields,
  28494. contextformtogglebutton: launchToggleButtonFields,
  28495. })
  28496. ),
  28497. ].concat(contextBarFields)
  28498. );
  28499. const register$2 = (editor) => {
  28500. const popups = editor.ui.registry.getAll().popups;
  28501. const dataset = map$2(popups, (popup) =>
  28502. createAutocompleter(popup).fold((err) => {
  28503. throw new Error(formatError(err));
  28504. }, identity)
  28505. );
  28506. const triggers = stringArray(mapToArray(dataset, (v) => v.trigger));
  28507. const datasetValues = values(dataset);
  28508. const lookupByTrigger = (trigger) =>
  28509. filter$5(datasetValues, (dv) => dv.trigger === trigger);
  28510. return {
  28511. dataset,
  28512. triggers,
  28513. lookupByTrigger,
  28514. };
  28515. };
  28516. const setupEditorInput = (editor, api) => {
  28517. const update = last$1(api.load, 50);
  28518. editor.on("keypress compositionend", (e) => {
  28519. if (e.which === 27) {
  28520. return;
  28521. }
  28522. update.throttle();
  28523. });
  28524. editor.on("keydown", (e) => {
  28525. const keyCode = e.which;
  28526. if (keyCode === 8) {
  28527. update.throttle();
  28528. } else if (keyCode === 27) {
  28529. api.cancelIfNecessary();
  28530. }
  28531. });
  28532. editor.on("remove", update.cancel);
  28533. };
  28534. const setup$j = (editor) => {
  28535. const activeAutocompleter = value$2();
  28536. const uiActive = Cell(false);
  28537. const isActive = activeAutocompleter.isSet;
  28538. const cancelIfNecessary = () => {
  28539. if (isActive()) {
  28540. removeAutocompleterDecoration(editor);
  28541. fireAutocompleterEnd(editor);
  28542. uiActive.set(false);
  28543. activeAutocompleter.clear();
  28544. }
  28545. };
  28546. const commenceIfNecessary = (context) => {
  28547. if (!isActive()) {
  28548. addAutocompleterDecoration(editor, context.range);
  28549. activeAutocompleter.set({
  28550. trigger: context.trigger,
  28551. matchLength: context.text.length,
  28552. });
  28553. }
  28554. };
  28555. const getAutocompleters = cached(() => register$2(editor));
  28556. const doLookup = (fetchOptions) =>
  28557. activeAutocompleter
  28558. .get()
  28559. .map((ac) =>
  28560. getContext(editor.dom, editor.selection.getRng(), ac.trigger).bind(
  28561. (newContext) =>
  28562. lookupWithContext(
  28563. editor,
  28564. getAutocompleters,
  28565. newContext,
  28566. fetchOptions
  28567. )
  28568. )
  28569. )
  28570. .getOrThunk(() => lookup(editor, getAutocompleters));
  28571. const load = (fetchOptions) => {
  28572. doLookup(fetchOptions).fold(cancelIfNecessary, (lookupInfo) => {
  28573. commenceIfNecessary(lookupInfo.context);
  28574. lookupInfo.lookupData.then((lookupData) => {
  28575. activeAutocompleter.get().map((ac) => {
  28576. const context = lookupInfo.context;
  28577. if (ac.trigger === context.trigger) {
  28578. if (context.text.length - ac.matchLength >= 10) {
  28579. cancelIfNecessary();
  28580. } else {
  28581. activeAutocompleter.set({
  28582. ...ac,
  28583. matchLength: context.text.length,
  28584. });
  28585. if (uiActive.get()) {
  28586. fireAutocompleterUpdate(editor, { lookupData });
  28587. } else {
  28588. uiActive.set(true);
  28589. fireAutocompleterStart(editor, { lookupData });
  28590. }
  28591. }
  28592. }
  28593. });
  28594. });
  28595. });
  28596. };
  28597. editor.addCommand("mceAutocompleterReload", (_ui, value) => {
  28598. const fetchOptions = isObject(value) ? value.fetchOptions : {};
  28599. load(fetchOptions);
  28600. });
  28601. editor.addCommand("mceAutocompleterClose", cancelIfNecessary);
  28602. setupEditorInput(editor, {
  28603. cancelIfNecessary,
  28604. load,
  28605. });
  28606. };
  28607. const browser$1 = detect$2().browser;
  28608. const isSafari = browser$1.isSafari();
  28609. const emptyNodeContents = (node) =>
  28610. fillWithPaddingBr(SugarElement.fromDom(node));
  28611. const isEntireNodeSelected = (rng, node) => {
  28612. var _a;
  28613. return (
  28614. rng.startOffset === 0 &&
  28615. rng.endOffset ===
  28616. ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length)
  28617. );
  28618. };
  28619. const getParentDetailsElementAtPos = (dom, pos) =>
  28620. Optional.from(dom.getParent(pos.container(), "details"));
  28621. const isInDetailsElement = (dom, pos) =>
  28622. getParentDetailsElementAtPos(dom, pos).isSome();
  28623. const getDetailsElements = (dom, rng) => {
  28624. const startDetails = Optional.from(
  28625. dom.getParent(rng.startContainer, "details")
  28626. );
  28627. const endDetails = Optional.from(
  28628. dom.getParent(rng.endContainer, "details")
  28629. );
  28630. if (startDetails.isSome() || endDetails.isSome()) {
  28631. const startSummary = startDetails.bind((details) =>
  28632. Optional.from(dom.select("summary", details)[0])
  28633. );
  28634. return Optional.some({
  28635. startSummary,
  28636. startDetails,
  28637. endDetails,
  28638. });
  28639. } else {
  28640. return Optional.none();
  28641. }
  28642. };
  28643. const isCaretInTheBeginningOf = (caretPos, element) =>
  28644. firstPositionIn(element).exists((pos) => pos.isEqual(caretPos));
  28645. const isCaretInTheEndOf = (caretPos, element) => {
  28646. return lastPositionIn(element).exists((pos) => {
  28647. if (isBr$6(pos.getNode())) {
  28648. return (
  28649. prevPosition(element, pos).exists((pos2) => pos2.isEqual(caretPos)) ||
  28650. pos.isEqual(caretPos)
  28651. );
  28652. } else {
  28653. return pos.isEqual(caretPos);
  28654. }
  28655. });
  28656. };
  28657. const isCaretAtStartOfSummary = (caretPos, detailsElements) =>
  28658. detailsElements.startSummary.exists((summary) =>
  28659. isCaretInTheBeginningOf(caretPos, summary)
  28660. );
  28661. const isCaretAtEndOfSummary = (caretPos, detailsElements) =>
  28662. detailsElements.startSummary.exists((summary) =>
  28663. isCaretInTheEndOf(caretPos, summary)
  28664. );
  28665. const isCaretInFirstPositionInBody = (caretPos, detailsElements) =>
  28666. detailsElements.startDetails.exists((details) =>
  28667. prevPosition(details, caretPos).forall((pos) =>
  28668. detailsElements.startSummary.exists(
  28669. (summary) =>
  28670. !summary.contains(caretPos.container()) &&
  28671. summary.contains(pos.container())
  28672. )
  28673. )
  28674. );
  28675. const isCaretInLastPositionInBody = (root, caretPos, detailsElements) =>
  28676. detailsElements.startDetails.exists((details) =>
  28677. nextPosition(root, caretPos).forall(
  28678. (pos) => !details.contains(pos.container())
  28679. )
  28680. );
  28681. const setCaretToPosition = (editor, position) => {
  28682. const node = position.getNode();
  28683. if (!isUndefined(node)) {
  28684. editor.selection.setCursorLocation(node, position.offset());
  28685. }
  28686. };
  28687. const moveCaretToDetailsPos = (editor, pos, forward) => {
  28688. const details = editor.dom.getParent(pos.container(), "details");
  28689. if (details && !details.open) {
  28690. const summary = editor.dom.select("summary", details)[0];
  28691. if (summary) {
  28692. const newPos = forward
  28693. ? firstPositionIn(summary)
  28694. : lastPositionIn(summary);
  28695. newPos.each((pos) => setCaretToPosition(editor, pos));
  28696. }
  28697. } else {
  28698. setCaretToPosition(editor, pos);
  28699. }
  28700. };
  28701. const isPartialDelete = (rng, detailsElements) => {
  28702. const containsStart = (element) => element.contains(rng.startContainer);
  28703. const containsEnd = (element) => element.contains(rng.endContainer);
  28704. const startInSummary = detailsElements.startSummary.exists(containsStart);
  28705. const endInSummary = detailsElements.startSummary.exists(containsEnd);
  28706. const isPartiallySelectedDetailsElements =
  28707. detailsElements.startDetails.forall((startDetails) =>
  28708. detailsElements.endDetails.forall(
  28709. (endDetails) => startDetails !== endDetails
  28710. )
  28711. );
  28712. const isInPartiallySelectedSummary =
  28713. (startInSummary || endInSummary) && !(startInSummary && endInSummary);
  28714. return isInPartiallySelectedSummary || isPartiallySelectedDetailsElements;
  28715. };
  28716. const shouldPreventDeleteIntoDetails = (editor, forward, granularity) => {
  28717. const { dom, selection } = editor;
  28718. const root = editor.getBody();
  28719. if (granularity === "character") {
  28720. const caretPos = CaretPosition.fromRangeStart(selection.getRng());
  28721. const parentBlock = dom.getParent(caretPos.container(), dom.isBlock);
  28722. const parentDetailsAtCaret = getParentDetailsElementAtPos(dom, caretPos);
  28723. const inEmptyParentBlock = parentBlock && dom.isEmpty(parentBlock);
  28724. const isFirstBlock = isNull(
  28725. parentBlock === null || parentBlock === void 0
  28726. ? void 0
  28727. : parentBlock.previousSibling
  28728. );
  28729. const isLastBlock = isNull(
  28730. parentBlock === null || parentBlock === void 0
  28731. ? void 0
  28732. : parentBlock.nextSibling
  28733. );
  28734. if (inEmptyParentBlock) {
  28735. const firstOrLast = forward ? isLastBlock : isFirstBlock;
  28736. if (firstOrLast) {
  28737. const isBeforeAfterDetails = navigate(
  28738. !forward,
  28739. root,
  28740. caretPos
  28741. ).exists((pos) => {
  28742. return (
  28743. isInDetailsElement(dom, pos) &&
  28744. !equals(
  28745. parentDetailsAtCaret,
  28746. getParentDetailsElementAtPos(dom, pos)
  28747. )
  28748. );
  28749. });
  28750. if (isBeforeAfterDetails) {
  28751. return true;
  28752. }
  28753. }
  28754. }
  28755. return navigate(forward, root, caretPos).fold(never, (pos) => {
  28756. const parentDetailsAtNewPos = getParentDetailsElementAtPos(dom, pos);
  28757. if (
  28758. isInDetailsElement(dom, pos) &&
  28759. !equals(parentDetailsAtCaret, parentDetailsAtNewPos)
  28760. ) {
  28761. if (!forward) {
  28762. moveCaretToDetailsPos(editor, pos, false);
  28763. }
  28764. if (parentBlock && inEmptyParentBlock) {
  28765. if (forward && isFirstBlock) {
  28766. return true;
  28767. } else if (!forward && isLastBlock) {
  28768. return true;
  28769. }
  28770. moveCaretToDetailsPos(editor, pos, forward);
  28771. editor.dom.remove(parentBlock);
  28772. }
  28773. return true;
  28774. } else {
  28775. return false;
  28776. }
  28777. });
  28778. } else {
  28779. return false;
  28780. }
  28781. };
  28782. const shouldPreventDeleteSummaryAction = (
  28783. editor,
  28784. detailElements,
  28785. forward,
  28786. granularity
  28787. ) => {
  28788. const selection = editor.selection;
  28789. const rng = selection.getRng();
  28790. const caretPos = CaretPosition.fromRangeStart(rng);
  28791. const root = editor.getBody();
  28792. if (granularity === "selection") {
  28793. return isPartialDelete(rng, detailElements);
  28794. } else if (forward) {
  28795. return (
  28796. isCaretAtEndOfSummary(caretPos, detailElements) ||
  28797. isCaretInLastPositionInBody(root, caretPos, detailElements)
  28798. );
  28799. } else {
  28800. return (
  28801. isCaretAtStartOfSummary(caretPos, detailElements) ||
  28802. isCaretInFirstPositionInBody(caretPos, detailElements)
  28803. );
  28804. }
  28805. };
  28806. const shouldPreventDeleteAction = (editor, forward, granularity) =>
  28807. getDetailsElements(editor.dom, editor.selection.getRng()).fold(
  28808. () => shouldPreventDeleteIntoDetails(editor, forward, granularity),
  28809. (detailsElements) =>
  28810. shouldPreventDeleteSummaryAction(
  28811. editor,
  28812. detailsElements,
  28813. forward,
  28814. granularity
  28815. ) || shouldPreventDeleteIntoDetails(editor, forward, granularity)
  28816. );
  28817. const handleDeleteActionSafari = (editor, forward, granularity) => {
  28818. const selection = editor.selection;
  28819. const node = selection.getNode();
  28820. const rng = selection.getRng();
  28821. const caretPos = CaretPosition.fromRangeStart(rng);
  28822. if (isSummary(node)) {
  28823. if (
  28824. (granularity === "selection" && isEntireNodeSelected(rng, node)) ||
  28825. willDeleteLastPositionInElement(forward, caretPos, node)
  28826. ) {
  28827. emptyNodeContents(node);
  28828. } else {
  28829. editor.undoManager.transact(() => {
  28830. const sel = selection.getSel();
  28831. let { anchorNode, anchorOffset, focusNode, focusOffset } =
  28832. sel !== null && sel !== void 0 ? sel : {};
  28833. const applySelection = () => {
  28834. if (
  28835. isNonNullable(anchorNode) &&
  28836. isNonNullable(anchorOffset) &&
  28837. isNonNullable(focusNode) &&
  28838. isNonNullable(focusOffset)
  28839. ) {
  28840. sel === null || sel === void 0
  28841. ? void 0
  28842. : sel.setBaseAndExtent(
  28843. anchorNode,
  28844. anchorOffset,
  28845. focusNode,
  28846. focusOffset
  28847. );
  28848. }
  28849. };
  28850. const updateSelection = () => {
  28851. anchorNode =
  28852. sel === null || sel === void 0 ? void 0 : sel.anchorNode;
  28853. anchorOffset =
  28854. sel === null || sel === void 0 ? void 0 : sel.anchorOffset;
  28855. focusNode = sel === null || sel === void 0 ? void 0 : sel.focusNode;
  28856. focusOffset =
  28857. sel === null || sel === void 0 ? void 0 : sel.focusOffset;
  28858. };
  28859. const appendAllChildNodes = (from, to) => {
  28860. each$e(from.childNodes, (child) => {
  28861. if (isNode(child)) {
  28862. to.appendChild(child);
  28863. }
  28864. });
  28865. };
  28866. const container = editor.dom.create("span", {
  28867. "data-mce-bogus": "1",
  28868. });
  28869. appendAllChildNodes(node, container);
  28870. node.appendChild(container);
  28871. applySelection();
  28872. if (granularity === "word" || granularity === "line") {
  28873. sel === null || sel === void 0
  28874. ? void 0
  28875. : sel.modify("extend", forward ? "right" : "left", granularity);
  28876. }
  28877. if (
  28878. !selection.isCollapsed() &&
  28879. isEntireNodeSelected(selection.getRng(), container)
  28880. ) {
  28881. emptyNodeContents(node);
  28882. } else {
  28883. editor.execCommand(forward ? "ForwardDelete" : "Delete");
  28884. updateSelection();
  28885. appendAllChildNodes(container, node);
  28886. applySelection();
  28887. }
  28888. editor.dom.remove(container);
  28889. });
  28890. }
  28891. return true;
  28892. } else {
  28893. return false;
  28894. }
  28895. };
  28896. const backspaceDelete = (editor, forward, granularity) =>
  28897. shouldPreventDeleteAction(editor, forward, granularity) ||
  28898. (isSafari && handleDeleteActionSafari(editor, forward, granularity))
  28899. ? Optional.some(noop)
  28900. : Optional.none();
  28901. const createAndFireInputEvent =
  28902. (eventType) =>
  28903. (editor, inputType, specifics = {}) => {
  28904. const target = editor.getBody();
  28905. const overrides = {
  28906. bubbles: true,
  28907. composed: true,
  28908. data: null,
  28909. isComposing: false,
  28910. detail: 0,
  28911. view: null,
  28912. target,
  28913. currentTarget: target,
  28914. eventPhase: Event.AT_TARGET,
  28915. originalTarget: target,
  28916. explicitOriginalTarget: target,
  28917. isTrusted: false,
  28918. srcElement: target,
  28919. cancelable: false,
  28920. preventDefault: noop,
  28921. inputType,
  28922. };
  28923. const input = clone$3(new InputEvent(eventType));
  28924. return editor.dispatch(eventType, {
  28925. ...input,
  28926. ...overrides,
  28927. ...specifics,
  28928. });
  28929. };
  28930. const fireInputEvent = createAndFireInputEvent("input");
  28931. const fireBeforeInputEvent = createAndFireInputEvent("beforeinput");
  28932. const platform$2 = detect$2();
  28933. const os = platform$2.os;
  28934. const isMacOSOriOS = os.isMacOS() || os.isiOS();
  28935. const browser = platform$2.browser;
  28936. const isFirefox = browser.isFirefox();
  28937. const executeKeydownOverride$3 = (editor, caret, evt) => {
  28938. const inputType =
  28939. evt.keyCode === VK.BACKSPACE
  28940. ? "deleteContentBackward"
  28941. : "deleteContentForward";
  28942. const isCollapsed = editor.selection.isCollapsed();
  28943. const unmodifiedGranularity = isCollapsed ? "character" : "selection";
  28944. const getModifiedGranularity = (isWord) => {
  28945. if (isCollapsed) {
  28946. return isWord ? "word" : "line";
  28947. } else {
  28948. return "selection";
  28949. }
  28950. };
  28951. executeWithDelayedAction(
  28952. [
  28953. {
  28954. keyCode: VK.BACKSPACE,
  28955. action: action(backspaceDelete$1, editor),
  28956. },
  28957. {
  28958. keyCode: VK.BACKSPACE,
  28959. action: action(backspaceDelete$6, editor, false),
  28960. },
  28961. {
  28962. keyCode: VK.DELETE,
  28963. action: action(backspaceDelete$6, editor, true),
  28964. },
  28965. {
  28966. keyCode: VK.BACKSPACE,
  28967. action: action(backspaceDelete$7, editor, false),
  28968. },
  28969. {
  28970. keyCode: VK.DELETE,
  28971. action: action(backspaceDelete$7, editor, true),
  28972. },
  28973. {
  28974. keyCode: VK.BACKSPACE,
  28975. action: action(backspaceDelete$4, editor, caret, false),
  28976. },
  28977. {
  28978. keyCode: VK.DELETE,
  28979. action: action(backspaceDelete$4, editor, caret, true),
  28980. },
  28981. {
  28982. keyCode: VK.BACKSPACE,
  28983. action: action(backspaceDelete$a, editor, false),
  28984. },
  28985. {
  28986. keyCode: VK.DELETE,
  28987. action: action(backspaceDelete$a, editor, true),
  28988. },
  28989. {
  28990. keyCode: VK.BACKSPACE,
  28991. action: action(backspaceDelete, editor, false, unmodifiedGranularity),
  28992. },
  28993. {
  28994. keyCode: VK.DELETE,
  28995. action: action(backspaceDelete, editor, true, unmodifiedGranularity),
  28996. },
  28997. ...(isMacOSOriOS
  28998. ? [
  28999. {
  29000. keyCode: VK.BACKSPACE,
  29001. altKey: true,
  29002. action: action(
  29003. backspaceDelete,
  29004. editor,
  29005. false,
  29006. getModifiedGranularity(true)
  29007. ),
  29008. },
  29009. {
  29010. keyCode: VK.DELETE,
  29011. altKey: true,
  29012. action: action(
  29013. backspaceDelete,
  29014. editor,
  29015. true,
  29016. getModifiedGranularity(true)
  29017. ),
  29018. },
  29019. {
  29020. keyCode: VK.BACKSPACE,
  29021. metaKey: true,
  29022. action: action(
  29023. backspaceDelete,
  29024. editor,
  29025. false,
  29026. getModifiedGranularity(false)
  29027. ),
  29028. },
  29029. ]
  29030. : [
  29031. {
  29032. keyCode: VK.BACKSPACE,
  29033. ctrlKey: true,
  29034. action: action(
  29035. backspaceDelete,
  29036. editor,
  29037. false,
  29038. getModifiedGranularity(true)
  29039. ),
  29040. },
  29041. {
  29042. keyCode: VK.DELETE,
  29043. ctrlKey: true,
  29044. action: action(
  29045. backspaceDelete,
  29046. editor,
  29047. true,
  29048. getModifiedGranularity(true)
  29049. ),
  29050. },
  29051. ]),
  29052. {
  29053. keyCode: VK.BACKSPACE,
  29054. action: action(backspaceDelete$5, editor, false),
  29055. },
  29056. {
  29057. keyCode: VK.DELETE,
  29058. action: action(backspaceDelete$5, editor, true),
  29059. },
  29060. {
  29061. keyCode: VK.BACKSPACE,
  29062. action: action(backspaceDelete$2, editor, false),
  29063. },
  29064. {
  29065. keyCode: VK.DELETE,
  29066. action: action(backspaceDelete$2, editor, true),
  29067. },
  29068. {
  29069. keyCode: VK.BACKSPACE,
  29070. action: action(backspaceDelete$8, editor, false),
  29071. },
  29072. {
  29073. keyCode: VK.DELETE,
  29074. action: action(backspaceDelete$8, editor, true),
  29075. },
  29076. {
  29077. keyCode: VK.BACKSPACE,
  29078. action: action(backspaceDelete$9, editor, false),
  29079. },
  29080. {
  29081. keyCode: VK.DELETE,
  29082. action: action(backspaceDelete$9, editor, true),
  29083. },
  29084. {
  29085. keyCode: VK.BACKSPACE,
  29086. action: action(backspaceDelete$3, editor, false),
  29087. },
  29088. {
  29089. keyCode: VK.DELETE,
  29090. action: action(backspaceDelete$3, editor, true),
  29091. },
  29092. ],
  29093. evt
  29094. )
  29095. .filter((_) => editor.selection.isEditable())
  29096. .each((applyAction) => {
  29097. evt.preventDefault();
  29098. const beforeInput = fireBeforeInputEvent(editor, inputType);
  29099. if (!beforeInput.isDefaultPrevented()) {
  29100. applyAction();
  29101. fireInputEvent(editor, inputType);
  29102. }
  29103. });
  29104. };
  29105. const executeKeyupOverride = (editor, evt, isBackspaceKeydown) =>
  29106. execute(
  29107. [
  29108. {
  29109. keyCode: VK.BACKSPACE,
  29110. action: action(paddEmptyElement, editor),
  29111. },
  29112. {
  29113. keyCode: VK.DELETE,
  29114. action: action(paddEmptyElement, editor),
  29115. },
  29116. ...(isMacOSOriOS
  29117. ? [
  29118. {
  29119. keyCode: VK.BACKSPACE,
  29120. altKey: true,
  29121. action: action(refreshCaret, editor),
  29122. },
  29123. {
  29124. keyCode: VK.DELETE,
  29125. altKey: true,
  29126. action: action(refreshCaret, editor),
  29127. },
  29128. ...(isBackspaceKeydown
  29129. ? [
  29130. {
  29131. keyCode: isFirefox ? 224 : 91,
  29132. action: action(refreshCaret, editor),
  29133. },
  29134. ]
  29135. : []),
  29136. ]
  29137. : [
  29138. {
  29139. keyCode: VK.BACKSPACE,
  29140. ctrlKey: true,
  29141. action: action(refreshCaret, editor),
  29142. },
  29143. {
  29144. keyCode: VK.DELETE,
  29145. ctrlKey: true,
  29146. action: action(refreshCaret, editor),
  29147. },
  29148. ]),
  29149. ],
  29150. evt
  29151. );
  29152. const setup$i = (editor, caret) => {
  29153. let isBackspaceKeydown = false;
  29154. editor.on("keydown", (evt) => {
  29155. isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
  29156. if (!evt.isDefaultPrevented()) {
  29157. executeKeydownOverride$3(editor, caret, evt);
  29158. }
  29159. });
  29160. editor.on("keyup", (evt) => {
  29161. if (!evt.isDefaultPrevented()) {
  29162. executeKeyupOverride(editor, evt, isBackspaceKeydown);
  29163. }
  29164. isBackspaceKeydown = false;
  29165. });
  29166. };
  29167. const firstNonWhiteSpaceNodeSibling = (node) => {
  29168. while (node) {
  29169. if (
  29170. isElement$6(node) ||
  29171. (isText$a(node) && node.data && /[\r\n\s]/.test(node.data))
  29172. ) {
  29173. return node;
  29174. }
  29175. node = node.nextSibling;
  29176. }
  29177. return null;
  29178. };
  29179. const moveToCaretPosition = (editor, root) => {
  29180. const dom = editor.dom;
  29181. const moveCaretBeforeOnEnterElementsMap =
  29182. editor.schema.getMoveCaretBeforeOnEnterElements();
  29183. if (!root) {
  29184. return;
  29185. }
  29186. if (/^(LI|DT|DD)$/.test(root.nodeName)) {
  29187. const firstChild = firstNonWhiteSpaceNodeSibling(root.firstChild);
  29188. if (firstChild && /^(UL|OL|DL)$/.test(firstChild.nodeName)) {
  29189. root.insertBefore(dom.doc.createTextNode(nbsp), root.firstChild);
  29190. }
  29191. }
  29192. const rng = dom.createRng();
  29193. root.normalize();
  29194. if (root.hasChildNodes()) {
  29195. const walker = new DomTreeWalker(root, root);
  29196. let lastNode = root;
  29197. let node;
  29198. while ((node = walker.current())) {
  29199. if (isText$a(node)) {
  29200. rng.setStart(node, 0);
  29201. rng.setEnd(node, 0);
  29202. break;
  29203. }
  29204. if (moveCaretBeforeOnEnterElementsMap[node.nodeName.toLowerCase()]) {
  29205. rng.setStartBefore(node);
  29206. rng.setEndBefore(node);
  29207. break;
  29208. }
  29209. lastNode = node;
  29210. node = walker.next();
  29211. }
  29212. if (!node) {
  29213. rng.setStart(lastNode, 0);
  29214. rng.setEnd(lastNode, 0);
  29215. }
  29216. } else {
  29217. if (isBr$6(root)) {
  29218. if (root.nextSibling && dom.isBlock(root.nextSibling)) {
  29219. rng.setStartBefore(root);
  29220. rng.setEndBefore(root);
  29221. } else {
  29222. rng.setStartAfter(root);
  29223. rng.setEndAfter(root);
  29224. }
  29225. } else {
  29226. rng.setStart(root, 0);
  29227. rng.setEnd(root, 0);
  29228. }
  29229. }
  29230. editor.selection.setRng(rng);
  29231. scrollRangeIntoView(editor, rng);
  29232. };
  29233. const getEditableRoot = (dom, node) => {
  29234. const root = dom.getRoot();
  29235. let editableRoot;
  29236. let parent = node;
  29237. while (
  29238. parent !== root &&
  29239. parent &&
  29240. dom.getContentEditable(parent) !== "false"
  29241. ) {
  29242. if (dom.getContentEditable(parent) === "true") {
  29243. editableRoot = parent;
  29244. break;
  29245. }
  29246. parent = parent.parentNode;
  29247. }
  29248. return parent !== root ? editableRoot : root;
  29249. };
  29250. const getParentBlock$1 = (editor) => {
  29251. return Optional.from(
  29252. editor.dom.getParent(editor.selection.getStart(true), editor.dom.isBlock)
  29253. );
  29254. };
  29255. const getParentBlockName = (editor) => {
  29256. return getParentBlock$1(editor).fold(constant(""), (parentBlock) => {
  29257. return parentBlock.nodeName.toUpperCase();
  29258. });
  29259. };
  29260. const isListItemParentBlock = (editor) => {
  29261. return getParentBlock$1(editor)
  29262. .filter((elm) => {
  29263. return isListItem$1(SugarElement.fromDom(elm));
  29264. })
  29265. .isSome();
  29266. };
  29267. const emptyBlock = (elm) => {
  29268. elm.innerHTML = '<br data-mce-bogus="1">';
  29269. };
  29270. const applyAttributes = (editor, node, forcedRootBlockAttrs) => {
  29271. const dom = editor.dom;
  29272. Optional.from(forcedRootBlockAttrs.style)
  29273. .map(dom.parseStyle)
  29274. .each((attrStyles) => {
  29275. const currentStyles = getAllRaw(SugarElement.fromDom(node));
  29276. const newStyles = {
  29277. ...currentStyles,
  29278. ...attrStyles,
  29279. };
  29280. dom.setStyles(node, newStyles);
  29281. });
  29282. const attrClassesOpt = Optional.from(forcedRootBlockAttrs.class).map(
  29283. (attrClasses) => attrClasses.split(/\s+/)
  29284. );
  29285. const currentClassesOpt = Optional.from(node.className).map(
  29286. (currentClasses) =>
  29287. filter$5(currentClasses.split(/\s+/), (clazz) => clazz !== "")
  29288. );
  29289. lift2(attrClassesOpt, currentClassesOpt, (attrClasses, currentClasses) => {
  29290. const filteredClasses = filter$5(
  29291. currentClasses,
  29292. (clazz) => !contains$2(attrClasses, clazz)
  29293. );
  29294. const newClasses = [...attrClasses, ...filteredClasses];
  29295. dom.setAttrib(node, "class", newClasses.join(" "));
  29296. });
  29297. const appliedAttrs = ["style", "class"];
  29298. const remainingAttrs = filter$4(
  29299. forcedRootBlockAttrs,
  29300. (_, attrs) => !contains$2(appliedAttrs, attrs)
  29301. );
  29302. dom.setAttribs(node, remainingAttrs);
  29303. };
  29304. const setForcedBlockAttrs = (editor, node) => {
  29305. const forcedRootBlockName = getForcedRootBlock(editor);
  29306. if (forcedRootBlockName.toLowerCase() === node.tagName.toLowerCase()) {
  29307. const forcedRootBlockAttrs = getForcedRootBlockAttrs(editor);
  29308. applyAttributes(editor, node, forcedRootBlockAttrs);
  29309. }
  29310. };
  29311. const createNewBlock = (
  29312. editor,
  29313. container,
  29314. parentBlock,
  29315. editableRoot,
  29316. keepStyles = true,
  29317. name
  29318. ) => {
  29319. const dom = editor.dom;
  29320. const schema = editor.schema;
  29321. const newBlockName = getForcedRootBlock(editor);
  29322. const parentBlockName = parentBlock
  29323. ? parentBlock.nodeName.toUpperCase()
  29324. : "";
  29325. let node = container;
  29326. const textInlineElements = schema.getTextInlineElements();
  29327. let block;
  29328. if (name || parentBlockName === "TABLE" || parentBlockName === "HR") {
  29329. block = dom.create(name || newBlockName);
  29330. } else {
  29331. block = parentBlock.cloneNode(false);
  29332. }
  29333. let caretNode = block;
  29334. if (!keepStyles) {
  29335. dom.setAttrib(block, "style", null);
  29336. dom.setAttrib(block, "class", null);
  29337. } else {
  29338. do {
  29339. if (textInlineElements[node.nodeName]) {
  29340. if (isCaretNode(node) || isBookmarkNode$1(node)) {
  29341. continue;
  29342. }
  29343. const clonedNode = node.cloneNode(false);
  29344. dom.setAttrib(clonedNode, "id", "");
  29345. if (block.hasChildNodes()) {
  29346. clonedNode.appendChild(block.firstChild);
  29347. block.appendChild(clonedNode);
  29348. } else {
  29349. caretNode = clonedNode;
  29350. block.appendChild(clonedNode);
  29351. }
  29352. }
  29353. } while ((node = node.parentNode) && node !== editableRoot);
  29354. }
  29355. setForcedBlockAttrs(editor, block);
  29356. emptyBlock(caretNode);
  29357. return block;
  29358. };
  29359. const getDetailsRoot = (editor, element) =>
  29360. editor.dom.getParent(element, isDetails);
  29361. const isAtDetailsEdge = (root, element, isTextBlock) => {
  29362. let node = element;
  29363. while (node && node !== root && isNull(node.nextSibling)) {
  29364. const parent = node.parentElement;
  29365. if (!parent || !isTextBlock(parent)) {
  29366. return isDetails(parent);
  29367. }
  29368. node = parent;
  29369. }
  29370. return false;
  29371. };
  29372. const isLastEmptyBlockInDetails = (editor, shiftKey, element) =>
  29373. !shiftKey &&
  29374. element.nodeName.toLowerCase() === getForcedRootBlock(editor) &&
  29375. editor.dom.isEmpty(element) &&
  29376. isAtDetailsEdge(editor.getBody(), element, (el) =>
  29377. has$2(editor.schema.getTextBlockElements(), el.nodeName.toLowerCase())
  29378. );
  29379. const insertNewLine = (editor, createNewBlock, parentBlock) => {
  29380. var _a, _b, _c;
  29381. const newBlock = createNewBlock(getForcedRootBlock(editor));
  29382. const root = getDetailsRoot(editor, parentBlock);
  29383. if (!root) {
  29384. return;
  29385. }
  29386. editor.dom.insertAfter(newBlock, root);
  29387. moveToCaretPosition(editor, newBlock);
  29388. if (
  29389. ((_c =
  29390. (_b =
  29391. (_a = parentBlock.parentElement) === null || _a === void 0
  29392. ? void 0
  29393. : _a.childNodes) === null || _b === void 0
  29394. ? void 0
  29395. : _b.length) !== null && _c !== void 0
  29396. ? _c
  29397. : 0) > 1
  29398. ) {
  29399. editor.dom.remove(parentBlock);
  29400. }
  29401. };
  29402. const hasFirstChild = (elm, name) => {
  29403. return elm.firstChild && elm.firstChild.nodeName === name;
  29404. };
  29405. const isFirstChild = (elm) => {
  29406. var _a;
  29407. return (
  29408. ((_a = elm.parentNode) === null || _a === void 0
  29409. ? void 0
  29410. : _a.firstChild) === elm
  29411. );
  29412. };
  29413. const hasParent = (elm, parentName) => {
  29414. const parentNode = elm === null || elm === void 0 ? void 0 : elm.parentNode;
  29415. return isNonNullable(parentNode) && parentNode.nodeName === parentName;
  29416. };
  29417. const isListBlock = (elm) => {
  29418. return isNonNullable(elm) && /^(OL|UL|LI)$/.test(elm.nodeName);
  29419. };
  29420. const isListItem = (elm) => {
  29421. return isNonNullable(elm) && /^(LI|DT|DD)$/.test(elm.nodeName);
  29422. };
  29423. const isNestedList = (elm) => {
  29424. return isListBlock(elm) && isListBlock(elm.parentNode);
  29425. };
  29426. const getContainerBlock = (containerBlock) => {
  29427. const containerBlockParent = containerBlock.parentNode;
  29428. return isListItem(containerBlockParent)
  29429. ? containerBlockParent
  29430. : containerBlock;
  29431. };
  29432. const isFirstOrLastLi = (containerBlock, parentBlock, first) => {
  29433. let node = containerBlock[first ? "firstChild" : "lastChild"];
  29434. while (node) {
  29435. if (isElement$6(node)) {
  29436. break;
  29437. }
  29438. node = node[first ? "nextSibling" : "previousSibling"];
  29439. }
  29440. return node === parentBlock;
  29441. };
  29442. const insert$4 = (
  29443. editor,
  29444. createNewBlock,
  29445. containerBlock,
  29446. parentBlock,
  29447. newBlockName
  29448. ) => {
  29449. const dom = editor.dom;
  29450. const rng = editor.selection.getRng();
  29451. const containerParent = containerBlock.parentNode;
  29452. if (containerBlock === editor.getBody() || !containerParent) {
  29453. return;
  29454. }
  29455. if (isNestedList(containerBlock)) {
  29456. newBlockName = "LI";
  29457. }
  29458. let newBlock = createNewBlock(newBlockName);
  29459. if (
  29460. isFirstOrLastLi(containerBlock, parentBlock, true) &&
  29461. isFirstOrLastLi(containerBlock, parentBlock, false)
  29462. ) {
  29463. if (hasParent(containerBlock, "LI")) {
  29464. const containerBlockParent = getContainerBlock(containerBlock);
  29465. dom.insertAfter(newBlock, containerBlockParent);
  29466. if (isFirstChild(containerBlock)) {
  29467. dom.remove(containerBlockParent);
  29468. } else {
  29469. dom.remove(containerBlock);
  29470. }
  29471. } else {
  29472. dom.replace(newBlock, containerBlock);
  29473. }
  29474. } else if (isFirstOrLastLi(containerBlock, parentBlock, true)) {
  29475. if (hasParent(containerBlock, "LI")) {
  29476. dom.insertAfter(newBlock, getContainerBlock(containerBlock));
  29477. newBlock.appendChild(dom.doc.createTextNode(" "));
  29478. newBlock.appendChild(containerBlock);
  29479. } else {
  29480. containerParent.insertBefore(newBlock, containerBlock);
  29481. }
  29482. dom.remove(parentBlock);
  29483. } else if (isFirstOrLastLi(containerBlock, parentBlock, false)) {
  29484. dom.insertAfter(newBlock, getContainerBlock(containerBlock));
  29485. dom.remove(parentBlock);
  29486. } else {
  29487. containerBlock = getContainerBlock(containerBlock);
  29488. const tmpRng = rng.cloneRange();
  29489. tmpRng.setStartAfter(parentBlock);
  29490. tmpRng.setEndAfter(containerBlock);
  29491. const fragment = tmpRng.extractContents();
  29492. if (newBlockName === "LI" && hasFirstChild(fragment, "LI")) {
  29493. newBlock = fragment.firstChild;
  29494. dom.insertAfter(fragment, containerBlock);
  29495. } else {
  29496. dom.insertAfter(fragment, containerBlock);
  29497. dom.insertAfter(newBlock, containerBlock);
  29498. }
  29499. dom.remove(parentBlock);
  29500. }
  29501. moveToCaretPosition(editor, newBlock);
  29502. };
  29503. const trimZwsp = (fragment) => {
  29504. each$e(descendants$1(SugarElement.fromDom(fragment), isText$b), (text) => {
  29505. const rawNode = text.dom;
  29506. rawNode.nodeValue = trim$1(rawNode.data);
  29507. });
  29508. };
  29509. const isWithinNonEditableList = (editor, node) => {
  29510. const parentList = editor.dom.getParent(node, "ol,ul,dl");
  29511. return (
  29512. parentList !== null &&
  29513. editor.dom.getContentEditableParent(parentList) === "false"
  29514. );
  29515. };
  29516. const isEmptyAnchor = (dom, elm) => {
  29517. return elm && elm.nodeName === "A" && dom.isEmpty(elm);
  29518. };
  29519. const containerAndSiblingName = (container, nodeName) => {
  29520. return (
  29521. container.nodeName === nodeName ||
  29522. (container.previousSibling &&
  29523. container.previousSibling.nodeName === nodeName)
  29524. );
  29525. };
  29526. const canSplitBlock = (dom, node) => {
  29527. return (
  29528. isNonNullable(node) &&
  29529. dom.isBlock(node) &&
  29530. !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) &&
  29531. !/^(fixed|absolute)/i.test(node.style.position) &&
  29532. dom.isEditable(node.parentNode) &&
  29533. dom.getContentEditable(node) !== "false"
  29534. );
  29535. };
  29536. const trimInlineElementsOnLeftSideOfBlock = (
  29537. dom,
  29538. nonEmptyElementsMap,
  29539. block
  29540. ) => {
  29541. var _a;
  29542. const firstChilds = [];
  29543. if (!block) {
  29544. return;
  29545. }
  29546. let currentNode = block;
  29547. while ((currentNode = currentNode.firstChild)) {
  29548. if (dom.isBlock(currentNode)) {
  29549. return;
  29550. }
  29551. if (
  29552. isElement$6(currentNode) &&
  29553. !nonEmptyElementsMap[currentNode.nodeName.toLowerCase()]
  29554. ) {
  29555. firstChilds.push(currentNode);
  29556. }
  29557. }
  29558. let i = firstChilds.length;
  29559. while (i--) {
  29560. currentNode = firstChilds[i];
  29561. if (
  29562. !currentNode.hasChildNodes() ||
  29563. (currentNode.firstChild === currentNode.lastChild &&
  29564. ((_a = currentNode.firstChild) === null || _a === void 0
  29565. ? void 0
  29566. : _a.nodeValue) === "")
  29567. ) {
  29568. dom.remove(currentNode);
  29569. } else {
  29570. if (isEmptyAnchor(dom, currentNode)) {
  29571. dom.remove(currentNode);
  29572. }
  29573. }
  29574. }
  29575. };
  29576. const normalizeZwspOffset = (start, container, offset) => {
  29577. if (!isText$a(container)) {
  29578. return offset;
  29579. } else if (start) {
  29580. return offset === 1 && container.data.charAt(offset - 1) === ZWSP$1
  29581. ? 0
  29582. : offset;
  29583. } else {
  29584. return offset === container.data.length - 1 &&
  29585. container.data.charAt(offset) === ZWSP$1
  29586. ? container.data.length
  29587. : offset;
  29588. }
  29589. };
  29590. const includeZwspInRange = (rng) => {
  29591. const newRng = rng.cloneRange();
  29592. newRng.setStart(
  29593. rng.startContainer,
  29594. normalizeZwspOffset(true, rng.startContainer, rng.startOffset)
  29595. );
  29596. newRng.setEnd(
  29597. rng.endContainer,
  29598. normalizeZwspOffset(false, rng.endContainer, rng.endOffset)
  29599. );
  29600. return newRng;
  29601. };
  29602. const trimLeadingLineBreaks = (node) => {
  29603. let currentNode = node;
  29604. do {
  29605. if (isText$a(currentNode)) {
  29606. currentNode.data = currentNode.data.replace(/^[\r\n]+/, "");
  29607. }
  29608. currentNode = currentNode.firstChild;
  29609. } while (currentNode);
  29610. };
  29611. const wrapSelfAndSiblingsInDefaultBlock = (
  29612. editor,
  29613. newBlockName,
  29614. rng,
  29615. container,
  29616. offset
  29617. ) => {
  29618. var _a, _b;
  29619. const dom = editor.dom;
  29620. const editableRoot =
  29621. (_a = getEditableRoot(dom, container)) !== null && _a !== void 0
  29622. ? _a
  29623. : dom.getRoot();
  29624. let parentBlock = dom.getParent(container, dom.isBlock);
  29625. if (!parentBlock || !canSplitBlock(dom, parentBlock)) {
  29626. parentBlock = parentBlock || editableRoot;
  29627. if (!parentBlock.hasChildNodes()) {
  29628. const newBlock = dom.create(newBlockName);
  29629. setForcedBlockAttrs(editor, newBlock);
  29630. parentBlock.appendChild(newBlock);
  29631. rng.setStart(newBlock, 0);
  29632. rng.setEnd(newBlock, 0);
  29633. return newBlock;
  29634. }
  29635. let node = container;
  29636. while (node && node.parentNode !== parentBlock) {
  29637. node = node.parentNode;
  29638. }
  29639. let startNode;
  29640. while (node && !dom.isBlock(node)) {
  29641. startNode = node;
  29642. node = node.previousSibling;
  29643. }
  29644. const startNodeName =
  29645. (_b =
  29646. startNode === null || startNode === void 0
  29647. ? void 0
  29648. : startNode.parentElement) === null || _b === void 0
  29649. ? void 0
  29650. : _b.nodeName;
  29651. if (
  29652. startNode &&
  29653. startNodeName &&
  29654. editor.schema.isValidChild(startNodeName, newBlockName.toLowerCase())
  29655. ) {
  29656. const startNodeParent = startNode.parentNode;
  29657. const newBlock = dom.create(newBlockName);
  29658. setForcedBlockAttrs(editor, newBlock);
  29659. startNodeParent.insertBefore(newBlock, startNode);
  29660. node = startNode;
  29661. while (node && !dom.isBlock(node)) {
  29662. const next = node.nextSibling;
  29663. newBlock.appendChild(node);
  29664. node = next;
  29665. }
  29666. rng.setStart(container, offset);
  29667. rng.setEnd(container, offset);
  29668. }
  29669. }
  29670. return container;
  29671. };
  29672. const addBrToBlockIfNeeded = (dom, block) => {
  29673. block.normalize();
  29674. const lastChild = block.lastChild;
  29675. if (
  29676. !lastChild ||
  29677. (isElement$6(lastChild) &&
  29678. /^(left|right)$/gi.test(dom.getStyle(lastChild, "float", true)))
  29679. ) {
  29680. dom.add(block, "br");
  29681. }
  29682. };
  29683. const shouldEndContainer = (editor, container) => {
  29684. const optionValue = shouldEndContainerOnEmptyBlock(editor);
  29685. if (isNullable(container)) {
  29686. return false;
  29687. } else if (isString(optionValue)) {
  29688. return contains$2(
  29689. Tools.explode(optionValue),
  29690. container.nodeName.toLowerCase()
  29691. );
  29692. } else {
  29693. return optionValue;
  29694. }
  29695. };
  29696. const insert$3 = (editor, evt) => {
  29697. let container;
  29698. let offset;
  29699. let parentBlockName;
  29700. let containerBlock;
  29701. let isAfterLastNodeInContainer = false;
  29702. const dom = editor.dom;
  29703. const schema = editor.schema,
  29704. nonEmptyElementsMap = schema.getNonEmptyElements();
  29705. const rng = editor.selection.getRng();
  29706. const newBlockName = getForcedRootBlock(editor);
  29707. const start = SugarElement.fromDom(rng.startContainer);
  29708. const child = child$1(start, rng.startOffset);
  29709. const isCef = child.exists(
  29710. (element) => isHTMLElement(element) && !isEditable$3(element)
  29711. );
  29712. const collapsedAndCef = rng.collapsed && isCef;
  29713. const createNewBlock$1 = (name) => {
  29714. return createNewBlock(
  29715. editor,
  29716. container,
  29717. parentBlock,
  29718. editableRoot,
  29719. shouldKeepStyles(editor),
  29720. name
  29721. );
  29722. };
  29723. const isCaretAtStartOrEndOfBlock = (start) => {
  29724. const normalizedOffset = normalizeZwspOffset(start, container, offset);
  29725. if (
  29726. isText$a(container) &&
  29727. (start
  29728. ? normalizedOffset > 0
  29729. : normalizedOffset < container.data.length)
  29730. ) {
  29731. return false;
  29732. }
  29733. if (
  29734. container.parentNode === parentBlock &&
  29735. isAfterLastNodeInContainer &&
  29736. !start
  29737. ) {
  29738. return true;
  29739. }
  29740. if (
  29741. start &&
  29742. isElement$6(container) &&
  29743. container === parentBlock.firstChild
  29744. ) {
  29745. return true;
  29746. }
  29747. if (
  29748. containerAndSiblingName(container, "TABLE") ||
  29749. containerAndSiblingName(container, "HR")
  29750. ) {
  29751. return (
  29752. (isAfterLastNodeInContainer && !start) ||
  29753. (!isAfterLastNodeInContainer && start)
  29754. );
  29755. }
  29756. const walker = new DomTreeWalker(container, parentBlock);
  29757. if (isText$a(container)) {
  29758. if (start && normalizedOffset === 0) {
  29759. walker.prev();
  29760. } else if (!start && normalizedOffset === container.data.length) {
  29761. walker.next();
  29762. }
  29763. }
  29764. let node;
  29765. while ((node = walker.current())) {
  29766. if (isElement$6(node)) {
  29767. if (!node.getAttribute("data-mce-bogus")) {
  29768. const name = node.nodeName.toLowerCase();
  29769. if (nonEmptyElementsMap[name] && name !== "br") {
  29770. return false;
  29771. }
  29772. }
  29773. } else if (isText$a(node) && !isWhitespaceText(node.data)) {
  29774. return false;
  29775. }
  29776. if (start) {
  29777. walker.prev();
  29778. } else {
  29779. walker.next();
  29780. }
  29781. }
  29782. return true;
  29783. };
  29784. const insertNewBlockAfter = () => {
  29785. let block;
  29786. if (
  29787. /^(H[1-6]|PRE|FIGURE)$/.test(parentBlockName) &&
  29788. containerBlockName !== "HGROUP"
  29789. ) {
  29790. block = createNewBlock$1(newBlockName);
  29791. } else {
  29792. block = createNewBlock$1();
  29793. }
  29794. if (
  29795. shouldEndContainer(editor, containerBlock) &&
  29796. canSplitBlock(dom, containerBlock) &&
  29797. dom.isEmpty(parentBlock, undefined, { includeZwsp: true })
  29798. ) {
  29799. block = dom.split(containerBlock, parentBlock);
  29800. } else {
  29801. dom.insertAfter(block, parentBlock);
  29802. }
  29803. moveToCaretPosition(editor, block);
  29804. return block;
  29805. };
  29806. normalize$2(dom, rng).each((normRng) => {
  29807. rng.setStart(normRng.startContainer, normRng.startOffset);
  29808. rng.setEnd(normRng.endContainer, normRng.endOffset);
  29809. });
  29810. container = rng.startContainer;
  29811. offset = rng.startOffset;
  29812. const shiftKey = !!(evt && evt.shiftKey);
  29813. const ctrlKey = !!(evt && evt.ctrlKey);
  29814. if (
  29815. isElement$6(container) &&
  29816. container.hasChildNodes() &&
  29817. !collapsedAndCef
  29818. ) {
  29819. isAfterLastNodeInContainer = offset > container.childNodes.length - 1;
  29820. container =
  29821. container.childNodes[
  29822. Math.min(offset, container.childNodes.length - 1)
  29823. ] || container;
  29824. if (isAfterLastNodeInContainer && isText$a(container)) {
  29825. offset = container.data.length;
  29826. } else {
  29827. offset = 0;
  29828. }
  29829. }
  29830. const editableRoot = getEditableRoot(dom, container);
  29831. if (!editableRoot || isWithinNonEditableList(editor, container)) {
  29832. return;
  29833. }
  29834. if (!shiftKey) {
  29835. container = wrapSelfAndSiblingsInDefaultBlock(
  29836. editor,
  29837. newBlockName,
  29838. rng,
  29839. container,
  29840. offset
  29841. );
  29842. }
  29843. let parentBlock = dom.getParent(container, dom.isBlock) || dom.getRoot();
  29844. containerBlock = isNonNullable(
  29845. parentBlock === null || parentBlock === void 0
  29846. ? void 0
  29847. : parentBlock.parentNode
  29848. )
  29849. ? dom.getParent(parentBlock.parentNode, dom.isBlock)
  29850. : null;
  29851. parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : "";
  29852. const containerBlockName = containerBlock
  29853. ? containerBlock.nodeName.toUpperCase()
  29854. : "";
  29855. if (containerBlockName === "LI" && !ctrlKey) {
  29856. const liBlock = containerBlock;
  29857. parentBlock = liBlock;
  29858. containerBlock = liBlock.parentNode;
  29859. parentBlockName = containerBlockName;
  29860. }
  29861. if (
  29862. isElement$6(containerBlock) &&
  29863. isLastEmptyBlockInDetails(editor, shiftKey, parentBlock)
  29864. ) {
  29865. return insertNewLine(editor, createNewBlock$1, parentBlock);
  29866. }
  29867. if (/^(LI|DT|DD)$/.test(parentBlockName) && isElement$6(containerBlock)) {
  29868. if (dom.isEmpty(parentBlock)) {
  29869. insert$4(
  29870. editor,
  29871. createNewBlock$1,
  29872. containerBlock,
  29873. parentBlock,
  29874. newBlockName
  29875. );
  29876. return;
  29877. }
  29878. }
  29879. if (
  29880. !collapsedAndCef &&
  29881. (parentBlock === editor.getBody() || !canSplitBlock(dom, parentBlock))
  29882. ) {
  29883. return;
  29884. }
  29885. const parentBlockParent = parentBlock.parentNode;
  29886. let newBlock;
  29887. if (collapsedAndCef) {
  29888. newBlock = createNewBlock$1(newBlockName);
  29889. child.fold(
  29890. () => {
  29891. append$1(start, SugarElement.fromDom(newBlock));
  29892. },
  29893. (child) => {
  29894. before$3(child, SugarElement.fromDom(newBlock));
  29895. }
  29896. );
  29897. editor.selection.setCursorLocation(newBlock, 0);
  29898. } else if (isCaretContainerBlock$1(parentBlock)) {
  29899. newBlock = showCaretContainerBlock(parentBlock);
  29900. if (dom.isEmpty(parentBlock)) {
  29901. emptyBlock(parentBlock);
  29902. }
  29903. setForcedBlockAttrs(editor, newBlock);
  29904. moveToCaretPosition(editor, newBlock);
  29905. } else if (isCaretAtStartOrEndOfBlock(false)) {
  29906. newBlock = insertNewBlockAfter();
  29907. } else if (isCaretAtStartOrEndOfBlock(true) && parentBlockParent) {
  29908. newBlock = parentBlockParent.insertBefore(
  29909. createNewBlock$1(),
  29910. parentBlock
  29911. );
  29912. const isNearChildren =
  29913. hasChildNodes(SugarElement.fromDom(rng.startContainer)) &&
  29914. rng.collapsed;
  29915. moveToCaretPosition(
  29916. editor,
  29917. containerAndSiblingName(parentBlock, "HR") || isNearChildren
  29918. ? newBlock
  29919. : parentBlock
  29920. );
  29921. } else {
  29922. const tmpRng = includeZwspInRange(rng).cloneRange();
  29923. tmpRng.setEndAfter(parentBlock);
  29924. const fragment = tmpRng.extractContents();
  29925. trimZwsp(fragment);
  29926. trimLeadingLineBreaks(fragment);
  29927. newBlock = fragment.firstChild;
  29928. dom.insertAfter(fragment, parentBlock);
  29929. trimInlineElementsOnLeftSideOfBlock(dom, nonEmptyElementsMap, newBlock);
  29930. addBrToBlockIfNeeded(dom, parentBlock);
  29931. if (dom.isEmpty(parentBlock)) {
  29932. emptyBlock(parentBlock);
  29933. }
  29934. newBlock.normalize();
  29935. if (dom.isEmpty(newBlock)) {
  29936. dom.remove(newBlock);
  29937. insertNewBlockAfter();
  29938. } else {
  29939. setForcedBlockAttrs(editor, newBlock);
  29940. moveToCaretPosition(editor, newBlock);
  29941. }
  29942. }
  29943. dom.setAttrib(newBlock, "id", "");
  29944. editor.dispatch("NewBlock", { newBlock });
  29945. };
  29946. const fakeEventName$1 = "insertParagraph";
  29947. const blockbreak = {
  29948. insert: insert$3,
  29949. fakeEventName: fakeEventName$1,
  29950. };
  29951. const hasRightSideContent = (schema, container, parentBlock) => {
  29952. const walker = new DomTreeWalker(container, parentBlock);
  29953. let node;
  29954. const nonEmptyElementsMap = schema.getNonEmptyElements();
  29955. while ((node = walker.next())) {
  29956. if (
  29957. nonEmptyElementsMap[node.nodeName.toLowerCase()] ||
  29958. (isText$a(node) && node.length > 0)
  29959. ) {
  29960. return true;
  29961. }
  29962. }
  29963. return false;
  29964. };
  29965. const moveSelectionToBr = (editor, brElm, extraBr) => {
  29966. const rng = editor.dom.createRng();
  29967. if (!extraBr) {
  29968. rng.setStartAfter(brElm);
  29969. rng.setEndAfter(brElm);
  29970. } else {
  29971. rng.setStartBefore(brElm);
  29972. rng.setEndBefore(brElm);
  29973. }
  29974. editor.selection.setRng(rng);
  29975. scrollRangeIntoView(editor, rng);
  29976. };
  29977. const insertBrAtCaret = (editor, evt) => {
  29978. const selection = editor.selection;
  29979. const dom = editor.dom;
  29980. const rng = selection.getRng();
  29981. let brElm;
  29982. let extraBr = false;
  29983. normalize$2(dom, rng).each((normRng) => {
  29984. rng.setStart(normRng.startContainer, normRng.startOffset);
  29985. rng.setEnd(normRng.endContainer, normRng.endOffset);
  29986. });
  29987. let offset = rng.startOffset;
  29988. let container = rng.startContainer;
  29989. if (isElement$6(container) && container.hasChildNodes()) {
  29990. const isAfterLastNodeInContainer =
  29991. offset > container.childNodes.length - 1;
  29992. container =
  29993. container.childNodes[
  29994. Math.min(offset, container.childNodes.length - 1)
  29995. ] || container;
  29996. if (isAfterLastNodeInContainer && isText$a(container)) {
  29997. offset = container.data.length;
  29998. } else {
  29999. offset = 0;
  30000. }
  30001. }
  30002. let parentBlock = dom.getParent(container, dom.isBlock);
  30003. const containerBlock =
  30004. parentBlock && parentBlock.parentNode
  30005. ? dom.getParent(parentBlock.parentNode, dom.isBlock)
  30006. : null;
  30007. const containerBlockName = containerBlock
  30008. ? containerBlock.nodeName.toUpperCase()
  30009. : "";
  30010. const isControlKey = !!(evt && evt.ctrlKey);
  30011. if (containerBlockName === "LI" && !isControlKey) {
  30012. parentBlock = containerBlock;
  30013. }
  30014. if (isText$a(container) && offset >= container.data.length) {
  30015. if (
  30016. !hasRightSideContent(
  30017. editor.schema,
  30018. container,
  30019. parentBlock || dom.getRoot()
  30020. )
  30021. ) {
  30022. brElm = dom.create("br");
  30023. rng.insertNode(brElm);
  30024. rng.setStartAfter(brElm);
  30025. rng.setEndAfter(brElm);
  30026. extraBr = true;
  30027. }
  30028. }
  30029. brElm = dom.create("br");
  30030. rangeInsertNode(dom, rng, brElm);
  30031. moveSelectionToBr(editor, brElm, extraBr);
  30032. editor.undoManager.add();
  30033. };
  30034. const insertBrBefore = (editor, inline) => {
  30035. const br = SugarElement.fromTag("br");
  30036. before$3(SugarElement.fromDom(inline), br);
  30037. editor.undoManager.add();
  30038. };
  30039. const insertBrAfter = (editor, inline) => {
  30040. if (!hasBrAfter(editor.getBody(), inline)) {
  30041. after$4(SugarElement.fromDom(inline), SugarElement.fromTag("br"));
  30042. }
  30043. const br = SugarElement.fromTag("br");
  30044. after$4(SugarElement.fromDom(inline), br);
  30045. moveSelectionToBr(editor, br.dom, false);
  30046. editor.undoManager.add();
  30047. };
  30048. const isBeforeBr = (pos) => {
  30049. return isBr$6(pos.getNode());
  30050. };
  30051. const hasBrAfter = (rootNode, startNode) => {
  30052. if (isBeforeBr(CaretPosition.after(startNode))) {
  30053. return true;
  30054. } else {
  30055. return nextPosition(rootNode, CaretPosition.after(startNode))
  30056. .map((pos) => {
  30057. return isBr$6(pos.getNode());
  30058. })
  30059. .getOr(false);
  30060. }
  30061. };
  30062. const isAnchorLink = (elm) => {
  30063. return elm && elm.nodeName === "A" && "href" in elm;
  30064. };
  30065. const isInsideAnchor = (location) => {
  30066. return location.fold(never, isAnchorLink, isAnchorLink, never);
  30067. };
  30068. const readInlineAnchorLocation = (editor) => {
  30069. const isInlineTarget$1 = curry(isInlineTarget, editor);
  30070. const position = CaretPosition.fromRangeStart(editor.selection.getRng());
  30071. return readLocation(isInlineTarget$1, editor.getBody(), position).filter(
  30072. isInsideAnchor
  30073. );
  30074. };
  30075. const insertBrOutsideAnchor = (editor, location) => {
  30076. location.fold(
  30077. noop,
  30078. curry(insertBrBefore, editor),
  30079. curry(insertBrAfter, editor),
  30080. noop
  30081. );
  30082. };
  30083. const insert$2 = (editor, evt) => {
  30084. const anchorLocation = readInlineAnchorLocation(editor);
  30085. if (anchorLocation.isSome()) {
  30086. anchorLocation.each(curry(insertBrOutsideAnchor, editor));
  30087. } else {
  30088. insertBrAtCaret(editor, evt);
  30089. }
  30090. };
  30091. const fakeEventName = "insertLineBreak";
  30092. const linebreak = {
  30093. insert: insert$2,
  30094. fakeEventName,
  30095. };
  30096. const matchesSelector = (editor, selector) => {
  30097. return getParentBlock$1(editor)
  30098. .filter((parentBlock) => {
  30099. return (
  30100. selector.length > 0 &&
  30101. is$1(SugarElement.fromDom(parentBlock), selector)
  30102. );
  30103. })
  30104. .isSome();
  30105. };
  30106. const shouldInsertBr = (editor) => {
  30107. return matchesSelector(editor, getBrNewLineSelector(editor));
  30108. };
  30109. const shouldBlockNewLine$1 = (editor) => {
  30110. return matchesSelector(editor, getNoNewLineSelector(editor));
  30111. };
  30112. const newLineAction = Adt.generate([{ br: [] }, { block: [] }, { none: [] }]);
  30113. const shouldBlockNewLine = (editor, _shiftKey) => {
  30114. return shouldBlockNewLine$1(editor);
  30115. };
  30116. const inListBlock = (requiredState) => {
  30117. return (editor, _shiftKey) => {
  30118. return isListItemParentBlock(editor) === requiredState;
  30119. };
  30120. };
  30121. const inBlock = (blockName, requiredState) => (editor, _shiftKey) => {
  30122. const state = getParentBlockName(editor) === blockName.toUpperCase();
  30123. return state === requiredState;
  30124. };
  30125. const inCefBlock = (editor) => {
  30126. const editableRoot = getEditableRoot(
  30127. editor.dom,
  30128. editor.selection.getStart()
  30129. );
  30130. return isNullable(editableRoot);
  30131. };
  30132. const inPreBlock = (requiredState) => inBlock("pre", requiredState);
  30133. const inSummaryBlock = () => inBlock("summary", true);
  30134. const shouldPutBrInPre = (requiredState) => {
  30135. return (editor, _shiftKey) => {
  30136. return shouldPutBrInPre$1(editor) === requiredState;
  30137. };
  30138. };
  30139. const inBrContext = (editor, _shiftKey) => {
  30140. return shouldInsertBr(editor);
  30141. };
  30142. const hasShiftKey = (_editor, shiftKey) => {
  30143. return shiftKey;
  30144. };
  30145. const canInsertIntoEditableRoot = (editor) => {
  30146. const forcedRootBlock = getForcedRootBlock(editor);
  30147. const rootEditable = getEditableRoot(
  30148. editor.dom,
  30149. editor.selection.getStart()
  30150. );
  30151. return (
  30152. isNonNullable(rootEditable) &&
  30153. editor.schema.isValidChild(rootEditable.nodeName, forcedRootBlock)
  30154. );
  30155. };
  30156. const isInRootWithEmptyOrCEF = (editor) => {
  30157. const rng = editor.selection.getRng();
  30158. const start = SugarElement.fromDom(rng.startContainer);
  30159. const child = child$1(start, rng.startOffset);
  30160. const isCefOpt = child.map(
  30161. (element) => isHTMLElement(element) && !isEditable$3(element)
  30162. );
  30163. return rng.collapsed && isCefOpt.getOr(true);
  30164. };
  30165. const match = (predicates, action) => {
  30166. return (editor, shiftKey) => {
  30167. const isMatch = foldl(
  30168. predicates,
  30169. (res, p) => {
  30170. return res && p(editor, shiftKey);
  30171. },
  30172. true
  30173. );
  30174. return isMatch ? Optional.some(action) : Optional.none();
  30175. };
  30176. };
  30177. const getAction = (editor, evt) => {
  30178. return evaluateUntil(
  30179. [
  30180. match([shouldBlockNewLine], newLineAction.none()),
  30181. match([inPreBlock(true), inCefBlock], newLineAction.none()),
  30182. match([inSummaryBlock()], newLineAction.br()),
  30183. match(
  30184. [inPreBlock(true), shouldPutBrInPre(false), hasShiftKey],
  30185. newLineAction.br()
  30186. ),
  30187. match(
  30188. [inPreBlock(true), shouldPutBrInPre(false)],
  30189. newLineAction.block()
  30190. ),
  30191. match(
  30192. [inPreBlock(true), shouldPutBrInPre(true), hasShiftKey],
  30193. newLineAction.block()
  30194. ),
  30195. match([inPreBlock(true), shouldPutBrInPre(true)], newLineAction.br()),
  30196. match([inListBlock(true), hasShiftKey], newLineAction.br()),
  30197. match([inListBlock(true)], newLineAction.block()),
  30198. match([inBrContext], newLineAction.br()),
  30199. match([hasShiftKey], newLineAction.br()),
  30200. match([canInsertIntoEditableRoot], newLineAction.block()),
  30201. match([isInRootWithEmptyOrCEF], newLineAction.block()),
  30202. ],
  30203. [editor, !!(evt && evt.shiftKey)]
  30204. ).getOr(newLineAction.none());
  30205. };
  30206. const insertBreak = (breakType, editor, evt) => {
  30207. if (!editor.selection.isCollapsed()) {
  30208. execEditorDeleteCommand(editor);
  30209. }
  30210. if (isNonNullable(evt)) {
  30211. const event = fireBeforeInputEvent(editor, breakType.fakeEventName);
  30212. if (event.isDefaultPrevented()) {
  30213. return;
  30214. }
  30215. }
  30216. breakType.insert(editor, evt);
  30217. if (isNonNullable(evt)) {
  30218. fireInputEvent(editor, breakType.fakeEventName);
  30219. }
  30220. };
  30221. const insert$1 = (editor, evt) => {
  30222. const br = () => insertBreak(linebreak, editor, evt);
  30223. const block = () => insertBreak(blockbreak, editor, evt);
  30224. const logicalAction = getAction(editor, evt);
  30225. switch (getNewlineBehavior(editor)) {
  30226. case "linebreak":
  30227. logicalAction.fold(br, br, noop);
  30228. break;
  30229. case "block":
  30230. logicalAction.fold(block, block, noop);
  30231. break;
  30232. case "invert":
  30233. logicalAction.fold(block, br, noop);
  30234. break;
  30235. default:
  30236. logicalAction.fold(br, block, noop);
  30237. break;
  30238. }
  30239. };
  30240. const platform$1 = detect$2();
  30241. const isIOSSafari = platform$1.os.isiOS() && platform$1.browser.isSafari();
  30242. const handleEnterKeyEvent = (editor, event) => {
  30243. if (event.isDefaultPrevented()) {
  30244. return;
  30245. }
  30246. event.preventDefault();
  30247. endTypingLevelIgnoreLocks(editor.undoManager);
  30248. editor.undoManager.transact(() => {
  30249. insert$1(editor, event);
  30250. });
  30251. };
  30252. const isCaretAfterKoreanCharacter = (rng) => {
  30253. if (!rng.collapsed) {
  30254. return false;
  30255. }
  30256. const startContainer = rng.startContainer;
  30257. if (isText$a(startContainer)) {
  30258. const koreanCharRegex =
  30259. /^[\uAC00-\uD7AF\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uD7B0-\uD7FF]$/;
  30260. const char = startContainer.data.charAt(rng.startOffset - 1);
  30261. return koreanCharRegex.test(char);
  30262. } else {
  30263. return false;
  30264. }
  30265. };
  30266. const setup$h = (editor) => {
  30267. let iOSSafariKeydownBookmark = Optional.none();
  30268. const iOSSafariKeydownOverride = (editor) => {
  30269. iOSSafariKeydownBookmark = Optional.some(editor.selection.getBookmark());
  30270. editor.undoManager.add();
  30271. };
  30272. const iOSSafariKeyupOverride = (editor, event) => {
  30273. editor.undoManager.undo();
  30274. iOSSafariKeydownBookmark.fold(noop, (b) =>
  30275. editor.selection.moveToBookmark(b)
  30276. );
  30277. handleEnterKeyEvent(editor, event);
  30278. iOSSafariKeydownBookmark = Optional.none();
  30279. };
  30280. editor.on("keydown", (event) => {
  30281. if (event.keyCode === VK.ENTER) {
  30282. if (
  30283. isIOSSafari &&
  30284. isCaretAfterKoreanCharacter(editor.selection.getRng())
  30285. ) {
  30286. iOSSafariKeydownOverride(editor);
  30287. } else {
  30288. handleEnterKeyEvent(editor, event);
  30289. }
  30290. }
  30291. });
  30292. editor.on("keyup", (event) => {
  30293. if (event.keyCode === VK.ENTER) {
  30294. iOSSafariKeydownBookmark.each(() =>
  30295. iOSSafariKeyupOverride(editor, event)
  30296. );
  30297. }
  30298. });
  30299. };
  30300. const executeKeydownOverride$2 = (editor, caret, evt) => {
  30301. const isMac = Env.os.isMacOS() || Env.os.isiOS();
  30302. execute(
  30303. [
  30304. {
  30305. keyCode: VK.END,
  30306. action: action(moveToLineEndPoint$1, editor, true),
  30307. },
  30308. {
  30309. keyCode: VK.HOME,
  30310. action: action(moveToLineEndPoint$1, editor, false),
  30311. },
  30312. ...(!isMac
  30313. ? [
  30314. {
  30315. keyCode: VK.HOME,
  30316. action: action(selectToEndPoint, editor, false),
  30317. ctrlKey: true,
  30318. shiftKey: true,
  30319. },
  30320. {
  30321. keyCode: VK.END,
  30322. action: action(selectToEndPoint, editor, true),
  30323. ctrlKey: true,
  30324. shiftKey: true,
  30325. },
  30326. ]
  30327. : []),
  30328. {
  30329. keyCode: VK.END,
  30330. action: action(moveToLineEndPoint, editor, true),
  30331. },
  30332. {
  30333. keyCode: VK.HOME,
  30334. action: action(moveToLineEndPoint, editor, false),
  30335. },
  30336. {
  30337. keyCode: VK.END,
  30338. action: action(moveToLineEndPoint$2, editor, true, caret),
  30339. },
  30340. {
  30341. keyCode: VK.HOME,
  30342. action: action(moveToLineEndPoint$2, editor, false, caret),
  30343. },
  30344. ],
  30345. evt
  30346. ).each((_) => {
  30347. evt.preventDefault();
  30348. });
  30349. };
  30350. const setup$g = (editor, caret) => {
  30351. editor.on("keydown", (evt) => {
  30352. if (!evt.isDefaultPrevented()) {
  30353. executeKeydownOverride$2(editor, caret, evt);
  30354. }
  30355. });
  30356. };
  30357. const setup$f = (editor) => {
  30358. editor.on("input", (e) => {
  30359. if (!e.isComposing) {
  30360. normalizeNbspsInEditor(editor);
  30361. }
  30362. });
  30363. };
  30364. const platform = detect$2();
  30365. const executeKeyupAction = (editor, caret, evt) => {
  30366. execute(
  30367. [
  30368. {
  30369. keyCode: VK.PAGE_UP,
  30370. action: action(moveToLineEndPoint$2, editor, false, caret),
  30371. },
  30372. {
  30373. keyCode: VK.PAGE_DOWN,
  30374. action: action(moveToLineEndPoint$2, editor, true, caret),
  30375. },
  30376. ],
  30377. evt
  30378. );
  30379. };
  30380. const stopImmediatePropagation = (e) => e.stopImmediatePropagation();
  30381. const isPageUpDown = (evt) =>
  30382. evt.keyCode === VK.PAGE_UP || evt.keyCode === VK.PAGE_DOWN;
  30383. const setNodeChangeBlocker = (blocked, editor, block) => {
  30384. if (block && !blocked.get()) {
  30385. editor.on("NodeChange", stopImmediatePropagation, true);
  30386. } else if (!block && blocked.get()) {
  30387. editor.off("NodeChange", stopImmediatePropagation);
  30388. }
  30389. blocked.set(block);
  30390. };
  30391. const setup$e = (editor, caret) => {
  30392. if (platform.os.isMacOS()) {
  30393. return;
  30394. }
  30395. const blocked = Cell(false);
  30396. editor.on("keydown", (evt) => {
  30397. if (isPageUpDown(evt)) {
  30398. setNodeChangeBlocker(blocked, editor, true);
  30399. }
  30400. });
  30401. editor.on("keyup", (evt) => {
  30402. if (!evt.isDefaultPrevented()) {
  30403. executeKeyupAction(editor, caret, evt);
  30404. }
  30405. if (isPageUpDown(evt) && blocked.get()) {
  30406. setNodeChangeBlocker(blocked, editor, false);
  30407. editor.nodeChanged();
  30408. }
  30409. });
  30410. };
  30411. const insertTextAtPosition = (text, pos) => {
  30412. const container = pos.container();
  30413. const offset = pos.offset();
  30414. if (isText$a(container)) {
  30415. container.insertData(offset, text);
  30416. return Optional.some(CaretPosition(container, offset + text.length));
  30417. } else {
  30418. return getElementFromPosition(pos).map((elm) => {
  30419. const textNode = SugarElement.fromText(text);
  30420. if (pos.isAtEnd()) {
  30421. after$4(elm, textNode);
  30422. } else {
  30423. before$3(elm, textNode);
  30424. }
  30425. return CaretPosition(textNode.dom, text.length);
  30426. });
  30427. }
  30428. };
  30429. const insertNbspAtPosition = curry(insertTextAtPosition, nbsp);
  30430. const insertSpaceAtPosition = curry(insertTextAtPosition, " ");
  30431. const insertSpaceOrNbspAtPosition = (root, pos) =>
  30432. needsToHaveNbsp(root, pos)
  30433. ? insertNbspAtPosition(pos)
  30434. : insertSpaceAtPosition(pos);
  30435. const locationToCaretPosition = (root) => (location) =>
  30436. location.fold(
  30437. (element) => prevPosition(root.dom, CaretPosition.before(element)),
  30438. (element) => firstPositionIn(element),
  30439. (element) => lastPositionIn(element),
  30440. (element) => nextPosition(root.dom, CaretPosition.after(element))
  30441. );
  30442. const insertInlineBoundarySpaceOrNbsp = (root, pos) => (checkPos) =>
  30443. needsToHaveNbsp(root, checkPos)
  30444. ? insertNbspAtPosition(pos)
  30445. : insertSpaceAtPosition(pos);
  30446. const setSelection = (editor) => (pos) => {
  30447. editor.selection.setRng(pos.toRange());
  30448. editor.nodeChanged();
  30449. };
  30450. const isInsideSummary = (domUtils, node) =>
  30451. domUtils.isEditable(domUtils.getParent(node, "summary"));
  30452. const insertSpaceOrNbspAtSelection = (editor) => {
  30453. const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
  30454. const root = SugarElement.fromDom(editor.getBody());
  30455. if (editor.selection.isCollapsed()) {
  30456. const isInlineTarget$1 = curry(isInlineTarget, editor);
  30457. const caretPosition = CaretPosition.fromRangeStart(
  30458. editor.selection.getRng()
  30459. );
  30460. return readLocation(isInlineTarget$1, editor.getBody(), caretPosition)
  30461. .bind(locationToCaretPosition(root))
  30462. .map(
  30463. (checkPos) => () =>
  30464. insertInlineBoundarySpaceOrNbsp(
  30465. root,
  30466. pos
  30467. )(checkPos).each(setSelection(editor))
  30468. );
  30469. } else {
  30470. return Optional.none();
  30471. }
  30472. };
  30473. const insertSpaceInSummaryAtSelectionOnFirefox = (editor) => {
  30474. const insertSpaceThunk = () => {
  30475. const root = SugarElement.fromDom(editor.getBody());
  30476. if (!editor.selection.isCollapsed()) {
  30477. editor.getDoc().execCommand("Delete");
  30478. }
  30479. const pos = CaretPosition.fromRangeStart(editor.selection.getRng());
  30480. insertSpaceOrNbspAtPosition(root, pos).each(setSelection(editor));
  30481. };
  30482. return someIf(
  30483. Env.browser.isFirefox() &&
  30484. editor.selection.isEditable() &&
  30485. isInsideSummary(editor.dom, editor.selection.getRng().startContainer),
  30486. insertSpaceThunk
  30487. );
  30488. };
  30489. const executeKeydownOverride$1 = (editor, evt) => {
  30490. executeWithDelayedAction(
  30491. [
  30492. {
  30493. keyCode: VK.SPACEBAR,
  30494. action: action(insertSpaceOrNbspAtSelection, editor),
  30495. },
  30496. {
  30497. keyCode: VK.SPACEBAR,
  30498. action: action(insertSpaceInSummaryAtSelectionOnFirefox, editor),
  30499. },
  30500. ],
  30501. evt
  30502. ).each((applyAction) => {
  30503. evt.preventDefault();
  30504. const event = fireBeforeInputEvent(editor, "insertText", { data: " " });
  30505. if (!event.isDefaultPrevented()) {
  30506. applyAction();
  30507. fireInputEvent(editor, "insertText", { data: " " });
  30508. }
  30509. });
  30510. };
  30511. const setup$d = (editor) => {
  30512. editor.on("keydown", (evt) => {
  30513. if (!evt.isDefaultPrevented()) {
  30514. executeKeydownOverride$1(editor, evt);
  30515. }
  30516. });
  30517. };
  30518. const tableTabNavigation = (editor) => {
  30519. if (hasTableTabNavigation(editor)) {
  30520. return [
  30521. {
  30522. keyCode: VK.TAB,
  30523. action: action(handleTab, editor, true),
  30524. },
  30525. {
  30526. keyCode: VK.TAB,
  30527. shiftKey: true,
  30528. action: action(handleTab, editor, false),
  30529. },
  30530. ];
  30531. } else {
  30532. return [];
  30533. }
  30534. };
  30535. const executeKeydownOverride = (editor, evt) => {
  30536. execute([...tableTabNavigation(editor)], evt).each((_) => {
  30537. evt.preventDefault();
  30538. });
  30539. };
  30540. const setup$c = (editor) => {
  30541. editor.on("keydown", (evt) => {
  30542. if (!evt.isDefaultPrevented()) {
  30543. executeKeydownOverride(editor, evt);
  30544. }
  30545. });
  30546. };
  30547. const setup$b = (editor) => {
  30548. editor.addShortcut("Meta+P", "", "mcePrint");
  30549. setup$j(editor);
  30550. if (isRtc(editor)) {
  30551. return Cell(null);
  30552. } else {
  30553. const caret = setupSelectedState(editor);
  30554. setup$l(editor);
  30555. setup$k(editor, caret);
  30556. setup$i(editor, caret);
  30557. setup$h(editor);
  30558. setup$d(editor);
  30559. setup$f(editor);
  30560. setup$c(editor);
  30561. setup$g(editor, caret);
  30562. setup$e(editor, caret);
  30563. return caret;
  30564. }
  30565. };
  30566. class NodeChange {
  30567. constructor(editor) {
  30568. this.lastPath = [];
  30569. this.editor = editor;
  30570. let lastRng;
  30571. const self = this;
  30572. if (!("onselectionchange" in editor.getDoc())) {
  30573. editor.on("NodeChange click mouseup keyup focus", (e) => {
  30574. const nativeRng = editor.selection.getRng();
  30575. const fakeRng = {
  30576. startContainer: nativeRng.startContainer,
  30577. startOffset: nativeRng.startOffset,
  30578. endContainer: nativeRng.endContainer,
  30579. endOffset: nativeRng.endOffset,
  30580. };
  30581. if (e.type === "nodechange" || !isEq$4(fakeRng, lastRng)) {
  30582. editor.dispatch("SelectionChange");
  30583. }
  30584. lastRng = fakeRng;
  30585. });
  30586. }
  30587. editor.on("contextmenu", () => {
  30588. editor.dispatch("SelectionChange");
  30589. });
  30590. editor.on("SelectionChange", () => {
  30591. const startElm = editor.selection.getStart(true);
  30592. if (!startElm) {
  30593. return;
  30594. }
  30595. if (
  30596. hasAnyRanges(editor) &&
  30597. !self.isSameElementPath(startElm) &&
  30598. editor.dom.isChildOf(startElm, editor.getBody())
  30599. ) {
  30600. editor.nodeChanged({ selectionChange: true });
  30601. }
  30602. });
  30603. editor.on("mouseup", (e) => {
  30604. if (!e.isDefaultPrevented() && hasAnyRanges(editor)) {
  30605. if (editor.selection.getNode().nodeName === "IMG") {
  30606. Delay.setEditorTimeout(editor, () => {
  30607. editor.nodeChanged();
  30608. });
  30609. } else {
  30610. editor.nodeChanged();
  30611. }
  30612. }
  30613. });
  30614. }
  30615. nodeChanged(args = {}) {
  30616. const selection = this.editor.selection;
  30617. let node;
  30618. if (
  30619. this.editor.initialized &&
  30620. selection &&
  30621. !shouldDisableNodeChange(this.editor) &&
  30622. !this.editor.mode.isReadOnly()
  30623. ) {
  30624. const root = this.editor.getBody();
  30625. node = selection.getStart(true) || root;
  30626. if (
  30627. node.ownerDocument !== this.editor.getDoc() ||
  30628. !this.editor.dom.isChildOf(node, root)
  30629. ) {
  30630. node = root;
  30631. }
  30632. const parents = [];
  30633. this.editor.dom.getParent(node, (node) => {
  30634. if (node === root) {
  30635. return true;
  30636. } else {
  30637. parents.push(node);
  30638. return false;
  30639. }
  30640. });
  30641. this.editor.dispatch("NodeChange", {
  30642. ...args,
  30643. element: node,
  30644. parents,
  30645. });
  30646. }
  30647. }
  30648. isSameElementPath(startElm) {
  30649. let i;
  30650. const editor = this.editor;
  30651. const currentPath = reverse(
  30652. editor.dom.getParents(startElm, always, editor.getBody())
  30653. );
  30654. if (currentPath.length === this.lastPath.length) {
  30655. for (i = currentPath.length; i >= 0; i--) {
  30656. if (currentPath[i] !== this.lastPath[i]) {
  30657. break;
  30658. }
  30659. }
  30660. if (i === -1) {
  30661. this.lastPath = currentPath;
  30662. return true;
  30663. }
  30664. }
  30665. this.lastPath = currentPath;
  30666. return false;
  30667. }
  30668. }
  30669. const imageId = generate$1("image");
  30670. const getDragImage = (transfer) => {
  30671. const dt = transfer;
  30672. return Optional.from(dt[imageId]);
  30673. };
  30674. const setDragImage = (transfer, imageData) => {
  30675. const dt = transfer;
  30676. dt[imageId] = imageData;
  30677. };
  30678. const eventId = generate$1("event");
  30679. const getEvent = (transfer) => {
  30680. const dt = transfer;
  30681. return Optional.from(dt[eventId]);
  30682. };
  30683. const mkSetEventFn = (type) => (transfer) => {
  30684. const dt = transfer;
  30685. dt[eventId] = type;
  30686. };
  30687. const setEvent = (transfer, type) => mkSetEventFn(type)(transfer);
  30688. const setDragstartEvent = mkSetEventFn(0);
  30689. const setDropEvent = mkSetEventFn(2);
  30690. const setDragendEvent = mkSetEventFn(1);
  30691. const checkEvent = (expectedType) => (transfer) => {
  30692. const dt = transfer;
  30693. return Optional.from(dt[eventId]).exists((type) => type === expectedType);
  30694. };
  30695. const isInDragStartEvent = checkEvent(0);
  30696. const createEmptyFileList = () =>
  30697. Object.freeze({
  30698. length: 0,
  30699. item: (_) => null,
  30700. });
  30701. const modeId = generate$1("mode");
  30702. const getMode = (transfer) => {
  30703. const dt = transfer;
  30704. return Optional.from(dt[modeId]);
  30705. };
  30706. const mkSetModeFn = (mode) => (transfer) => {
  30707. const dt = transfer;
  30708. dt[modeId] = mode;
  30709. };
  30710. const setMode$1 = (transfer, mode) => mkSetModeFn(mode)(transfer);
  30711. const setReadWriteMode = mkSetModeFn(0);
  30712. const setReadOnlyMode = mkSetModeFn(2);
  30713. const setProtectedMode = mkSetModeFn(1);
  30714. const checkMode = (expectedMode) => (transfer) => {
  30715. const dt = transfer;
  30716. return Optional.from(dt[modeId]).exists((mode) => mode === expectedMode);
  30717. };
  30718. const isInReadWriteMode = checkMode(0);
  30719. const isInProtectedMode = checkMode(1);
  30720. const normalizeItems = (dataTransfer, itemsImpl) => ({
  30721. ...itemsImpl,
  30722. get length() {
  30723. return itemsImpl.length;
  30724. },
  30725. add: (data, type) => {
  30726. if (isInReadWriteMode(dataTransfer)) {
  30727. if (isString(data)) {
  30728. if (!isUndefined(type)) {
  30729. return itemsImpl.add(data, type);
  30730. }
  30731. } else {
  30732. return itemsImpl.add(data);
  30733. }
  30734. }
  30735. return null;
  30736. },
  30737. remove: (idx) => {
  30738. if (isInReadWriteMode(dataTransfer)) {
  30739. itemsImpl.remove(idx);
  30740. }
  30741. },
  30742. clear: () => {
  30743. if (isInReadWriteMode(dataTransfer)) {
  30744. itemsImpl.clear();
  30745. }
  30746. },
  30747. });
  30748. const validDropEffects = ["none", "copy", "link", "move"];
  30749. const validEffectAlloweds = [
  30750. "none",
  30751. "copy",
  30752. "copyLink",
  30753. "copyMove",
  30754. "link",
  30755. "linkMove",
  30756. "move",
  30757. "all",
  30758. "uninitialized",
  30759. ];
  30760. const createDataTransfer = () => {
  30761. const dataTransferImpl = new window.DataTransfer();
  30762. let dropEffect = "move";
  30763. let effectAllowed = "all";
  30764. const dataTransfer = {
  30765. get dropEffect() {
  30766. return dropEffect;
  30767. },
  30768. set dropEffect(effect) {
  30769. if (contains$2(validDropEffects, effect)) {
  30770. dropEffect = effect;
  30771. }
  30772. },
  30773. get effectAllowed() {
  30774. return effectAllowed;
  30775. },
  30776. set effectAllowed(allowed) {
  30777. if (
  30778. isInDragStartEvent(dataTransfer) &&
  30779. contains$2(validEffectAlloweds, allowed)
  30780. ) {
  30781. effectAllowed = allowed;
  30782. }
  30783. },
  30784. get items() {
  30785. return normalizeItems(dataTransfer, dataTransferImpl.items);
  30786. },
  30787. get files() {
  30788. if (isInProtectedMode(dataTransfer)) {
  30789. return createEmptyFileList();
  30790. } else {
  30791. return dataTransferImpl.files;
  30792. }
  30793. },
  30794. get types() {
  30795. return dataTransferImpl.types;
  30796. },
  30797. setDragImage: (image, x, y) => {
  30798. if (isInReadWriteMode(dataTransfer)) {
  30799. setDragImage(dataTransfer, {
  30800. image,
  30801. x,
  30802. y,
  30803. });
  30804. dataTransferImpl.setDragImage(image, x, y);
  30805. }
  30806. },
  30807. getData: (format) => {
  30808. if (isInProtectedMode(dataTransfer)) {
  30809. return "";
  30810. } else {
  30811. return dataTransferImpl.getData(format);
  30812. }
  30813. },
  30814. setData: (format, data) => {
  30815. if (isInReadWriteMode(dataTransfer)) {
  30816. dataTransferImpl.setData(format, data);
  30817. }
  30818. },
  30819. clearData: (format) => {
  30820. if (isInReadWriteMode(dataTransfer)) {
  30821. dataTransferImpl.clearData(format);
  30822. }
  30823. },
  30824. };
  30825. setReadWriteMode(dataTransfer);
  30826. return dataTransfer;
  30827. };
  30828. const cloneDataTransfer = (original) => {
  30829. const clone = createDataTransfer();
  30830. const originalMode = getMode(original);
  30831. setReadOnlyMode(original);
  30832. setDragstartEvent(clone);
  30833. clone.dropEffect = original.dropEffect;
  30834. clone.effectAllowed = original.effectAllowed;
  30835. getDragImage(original).each((imageData) =>
  30836. clone.setDragImage(imageData.image, imageData.x, imageData.y)
  30837. );
  30838. each$e(original.types, (type) => {
  30839. if (type !== "Files") {
  30840. clone.setData(type, original.getData(type));
  30841. }
  30842. });
  30843. each$e(original.files, (file) => clone.items.add(file));
  30844. getEvent(original).each((type) => {
  30845. setEvent(clone, type);
  30846. });
  30847. originalMode.each((mode) => {
  30848. setMode$1(original, mode);
  30849. setMode$1(clone, mode);
  30850. });
  30851. return clone;
  30852. };
  30853. const getHtmlData = (dataTransfer) => {
  30854. const html = dataTransfer.getData("text/html");
  30855. return html === "" ? Optional.none() : Optional.some(html);
  30856. };
  30857. const setHtmlData = (dataTransfer, html) =>
  30858. dataTransfer.setData("text/html", html);
  30859. const internalMimeType = "x-tinymce/html";
  30860. const internalHtmlMime = constant(internalMimeType);
  30861. const internalMark = "<!-- " + internalMimeType + " -->";
  30862. const mark = (html) => internalMark + html;
  30863. const unmark = (html) => html.replace(internalMark, "");
  30864. const isMarked = (html) => html.indexOf(internalMark) !== -1;
  30865. const isPlainText = (text) => {
  30866. return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(
  30867. text
  30868. );
  30869. };
  30870. const openContainer = (rootTag, rootAttrs) => {
  30871. let tag = "<" + rootTag;
  30872. const attrs = mapToArray(
  30873. rootAttrs,
  30874. (value, key) => key + '="' + Entities.encodeAllRaw(value) + '"'
  30875. );
  30876. if (attrs.length) {
  30877. tag += " " + attrs.join(" ");
  30878. }
  30879. return tag + ">";
  30880. };
  30881. const toBlockElements = (text, rootTag, rootAttrs) => {
  30882. const blocks = text.split(/\n\n/);
  30883. const tagOpen = openContainer(rootTag, rootAttrs);
  30884. const tagClose = "</" + rootTag + ">";
  30885. const paragraphs = map$3(blocks, (p) => {
  30886. return p.split(/\n/).join("<br />");
  30887. });
  30888. const stitch = (p) => {
  30889. return tagOpen + p + tagClose;
  30890. };
  30891. return paragraphs.length === 1
  30892. ? paragraphs[0]
  30893. : map$3(paragraphs, stitch).join("");
  30894. };
  30895. const pasteBinDefaultContent = "%MCEPASTEBIN%";
  30896. const create$6 = (editor, lastRngCell) => {
  30897. const { dom, selection } = editor;
  30898. const body = editor.getBody();
  30899. lastRngCell.set(selection.getRng());
  30900. const pasteBinElm = dom.add(
  30901. editor.getBody(),
  30902. "div",
  30903. {
  30904. id: "mcepastebin",
  30905. class: "mce-pastebin",
  30906. contentEditable: true,
  30907. "data-mce-bogus": "all",
  30908. style:
  30909. "position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0",
  30910. },
  30911. pasteBinDefaultContent
  30912. );
  30913. if (Env.browser.isFirefox()) {
  30914. dom.setStyle(
  30915. pasteBinElm,
  30916. "left",
  30917. dom.getStyle(body, "direction", true) === "rtl" ? 65535 : -65535
  30918. );
  30919. }
  30920. dom.bind(pasteBinElm, "beforedeactivate focusin focusout", (e) => {
  30921. e.stopPropagation();
  30922. });
  30923. pasteBinElm.focus();
  30924. selection.select(pasteBinElm, true);
  30925. };
  30926. const remove = (editor, lastRngCell) => {
  30927. const dom = editor.dom;
  30928. if (getEl(editor)) {
  30929. let pasteBinClone;
  30930. const lastRng = lastRngCell.get();
  30931. while ((pasteBinClone = getEl(editor))) {
  30932. dom.remove(pasteBinClone);
  30933. dom.unbind(pasteBinClone);
  30934. }
  30935. if (lastRng) {
  30936. editor.selection.setRng(lastRng);
  30937. }
  30938. }
  30939. lastRngCell.set(null);
  30940. };
  30941. const getEl = (editor) => editor.dom.get("mcepastebin");
  30942. const isPasteBin = (elm) => isNonNullable(elm) && elm.id === "mcepastebin";
  30943. const getHtml = (editor) => {
  30944. const dom = editor.dom;
  30945. const copyAndRemove = (toElm, fromElm) => {
  30946. toElm.appendChild(fromElm);
  30947. dom.remove(fromElm, true);
  30948. };
  30949. const [pasteBinElm, ...pasteBinClones] = filter$5(
  30950. editor.getBody().childNodes,
  30951. isPasteBin
  30952. );
  30953. each$e(pasteBinClones, (pasteBinClone) => {
  30954. copyAndRemove(pasteBinElm, pasteBinClone);
  30955. });
  30956. const dirtyWrappers = dom.select("div[id=mcepastebin]", pasteBinElm);
  30957. for (let i = dirtyWrappers.length - 1; i >= 0; i--) {
  30958. const cleanWrapper = dom.create("div");
  30959. pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]);
  30960. copyAndRemove(cleanWrapper, dirtyWrappers[i]);
  30961. }
  30962. return pasteBinElm ? pasteBinElm.innerHTML : "";
  30963. };
  30964. const isDefaultPasteBinContent = (content) =>
  30965. content === pasteBinDefaultContent;
  30966. const PasteBin = (editor) => {
  30967. const lastRng = Cell(null);
  30968. return {
  30969. create: () => create$6(editor, lastRng),
  30970. remove: () => remove(editor, lastRng),
  30971. getEl: () => getEl(editor),
  30972. getHtml: () => getHtml(editor),
  30973. getLastRng: lastRng.get,
  30974. };
  30975. };
  30976. const filter$1 = (content, items) => {
  30977. Tools.each(items, (v) => {
  30978. if (is$4(v, RegExp)) {
  30979. content = content.replace(v, "");
  30980. } else {
  30981. content = content.replace(v[0], v[1]);
  30982. }
  30983. });
  30984. return content;
  30985. };
  30986. const innerText = (html) => {
  30987. const schema = Schema();
  30988. const domParser = DomParser({}, schema);
  30989. let text = "";
  30990. const voidElements = schema.getVoidElements();
  30991. const ignoreElements = Tools.makeMap(
  30992. "script noscript style textarea video audio iframe object",
  30993. " "
  30994. );
  30995. const blockElements = schema.getBlockElements();
  30996. const walk = (node) => {
  30997. const name = node.name,
  30998. currentNode = node;
  30999. if (name === "br") {
  31000. text += "\n";
  31001. return;
  31002. }
  31003. if (name === "wbr") {
  31004. return;
  31005. }
  31006. if (voidElements[name]) {
  31007. text += " ";
  31008. }
  31009. if (ignoreElements[name]) {
  31010. text += " ";
  31011. return;
  31012. }
  31013. if (node.type === 3) {
  31014. text += node.value;
  31015. }
  31016. if (!(node.name in schema.getVoidElements())) {
  31017. let currentNode = node.firstChild;
  31018. if (currentNode) {
  31019. do {
  31020. walk(currentNode);
  31021. } while ((currentNode = currentNode.next));
  31022. }
  31023. }
  31024. if (blockElements[name] && currentNode.next) {
  31025. text += "\n";
  31026. if (name === "p") {
  31027. text += "\n";
  31028. }
  31029. }
  31030. };
  31031. html = filter$1(html, [/<!\[[^\]]+\]>/g]);
  31032. walk(domParser.parse(html));
  31033. return text;
  31034. };
  31035. const trimHtml = (html) => {
  31036. const trimSpaces = (all, s1, s2) => {
  31037. if (!s1 && !s2) {
  31038. return " ";
  31039. }
  31040. return nbsp;
  31041. };
  31042. html = filter$1(html, [
  31043. /^[\s\S]*<body[^>]*>\s*|\s*<\/body[^>]*>[\s\S]*$/gi,
  31044. /<!--StartFragment-->|<!--EndFragment-->/g,
  31045. [
  31046. /( ?)<span class="Apple-converted-space">\u00a0<\/span>( ?)/g,
  31047. trimSpaces,
  31048. ],
  31049. /<br class="Apple-interchange-newline">/g,
  31050. /<br>$/i,
  31051. ]);
  31052. return html;
  31053. };
  31054. const createIdGenerator = (prefix) => {
  31055. let count = 0;
  31056. return () => {
  31057. return prefix + count++;
  31058. };
  31059. };
  31060. const getImageMimeType = (ext) => {
  31061. const lowerExt = ext.toLowerCase();
  31062. const mimeOverrides = {
  31063. jpg: "jpeg",
  31064. jpe: "jpeg",
  31065. jfi: "jpeg",
  31066. jif: "jpeg",
  31067. jfif: "jpeg",
  31068. pjpeg: "jpeg",
  31069. pjp: "jpeg",
  31070. svg: "svg+xml",
  31071. };
  31072. return Tools.hasOwn(mimeOverrides, lowerExt)
  31073. ? "image/" + mimeOverrides[lowerExt]
  31074. : "image/" + lowerExt;
  31075. };
  31076. const preProcess = (editor, html) => {
  31077. const parser = DomParser(
  31078. { sanitize: shouldSanitizeXss(editor) },
  31079. editor.schema
  31080. );
  31081. parser.addNodeFilter("meta", (nodes) => {
  31082. Tools.each(nodes, (node) => {
  31083. node.remove();
  31084. });
  31085. });
  31086. const fragment = parser.parse(html, {
  31087. forced_root_block: false,
  31088. isRootContent: true,
  31089. });
  31090. return HtmlSerializer({ validate: true }, editor.schema).serialize(
  31091. fragment
  31092. );
  31093. };
  31094. const processResult = (content, cancelled) => ({
  31095. content,
  31096. cancelled,
  31097. });
  31098. const postProcessFilter = (editor, html, internal) => {
  31099. const tempBody = editor.dom.create("div", { style: "display:none" }, html);
  31100. const postProcessArgs = firePastePostProcess(editor, tempBody, internal);
  31101. return processResult(
  31102. postProcessArgs.node.innerHTML,
  31103. postProcessArgs.isDefaultPrevented()
  31104. );
  31105. };
  31106. const filterContent = (editor, content, internal) => {
  31107. const preProcessArgs = firePastePreProcess(editor, content, internal);
  31108. const filteredContent = preProcess(editor, preProcessArgs.content);
  31109. if (
  31110. editor.hasEventListeners("PastePostProcess") &&
  31111. !preProcessArgs.isDefaultPrevented()
  31112. ) {
  31113. return postProcessFilter(editor, filteredContent, internal);
  31114. } else {
  31115. return processResult(
  31116. filteredContent,
  31117. preProcessArgs.isDefaultPrevented()
  31118. );
  31119. }
  31120. };
  31121. const process = (editor, html, internal) => {
  31122. return filterContent(editor, html, internal);
  31123. };
  31124. const pasteHtml$1 = (editor, html) => {
  31125. editor.insertContent(html, {
  31126. merge: shouldPasteMergeFormats(editor),
  31127. paste: true,
  31128. });
  31129. return true;
  31130. };
  31131. const isAbsoluteUrl = (url) =>
  31132. /^https?:\/\/[\w\-\/+=.,!;:&%@^~(){}?#]+$/i.test(url);
  31133. const isImageUrl = (editor, url) => {
  31134. return (
  31135. isAbsoluteUrl(url) &&
  31136. exists(getAllowedImageFileTypes(editor), (type) =>
  31137. endsWith(url.toLowerCase(), `.${type.toLowerCase()}`)
  31138. )
  31139. );
  31140. };
  31141. const createImage = (editor, url, pasteHtmlFn) => {
  31142. editor.undoManager.extra(
  31143. () => {
  31144. pasteHtmlFn(editor, url);
  31145. },
  31146. () => {
  31147. editor.insertContent('<img src="' + url + '">');
  31148. }
  31149. );
  31150. return true;
  31151. };
  31152. const createLink = (editor, url, pasteHtmlFn) => {
  31153. editor.undoManager.extra(
  31154. () => {
  31155. pasteHtmlFn(editor, url);
  31156. },
  31157. () => {
  31158. editor.execCommand("mceInsertLink", false, url);
  31159. }
  31160. );
  31161. return true;
  31162. };
  31163. const linkSelection = (editor, html, pasteHtmlFn) =>
  31164. !editor.selection.isCollapsed() && isAbsoluteUrl(html)
  31165. ? createLink(editor, html, pasteHtmlFn)
  31166. : false;
  31167. const insertImage = (editor, html, pasteHtmlFn) =>
  31168. isImageUrl(editor, html) ? createImage(editor, html, pasteHtmlFn) : false;
  31169. const smartInsertContent = (editor, html) => {
  31170. Tools.each([linkSelection, insertImage, pasteHtml$1], (action) => {
  31171. return !action(editor, html, pasteHtml$1);
  31172. });
  31173. };
  31174. const insertContent = (editor, html, pasteAsText) => {
  31175. if (pasteAsText || !isSmartPasteEnabled(editor)) {
  31176. pasteHtml$1(editor, html);
  31177. } else {
  31178. smartInsertContent(editor, html);
  31179. }
  31180. };
  31181. const uniqueId = createIdGenerator("mceclip");
  31182. const createPasteDataTransfer = (html) => {
  31183. const dataTransfer = createDataTransfer();
  31184. setHtmlData(dataTransfer, html);
  31185. setReadOnlyMode(dataTransfer);
  31186. return dataTransfer;
  31187. };
  31188. const doPaste = (
  31189. editor,
  31190. content,
  31191. internal,
  31192. pasteAsText,
  31193. shouldSimulateInputEvent
  31194. ) => {
  31195. const res = process(editor, content, internal);
  31196. if (!res.cancelled) {
  31197. const content = res.content;
  31198. const doPasteAction = () => insertContent(editor, content, pasteAsText);
  31199. if (shouldSimulateInputEvent) {
  31200. const args = fireBeforeInputEvent(editor, "insertFromPaste", {
  31201. dataTransfer: createPasteDataTransfer(content),
  31202. });
  31203. if (!args.isDefaultPrevented()) {
  31204. doPasteAction();
  31205. fireInputEvent(editor, "insertFromPaste");
  31206. }
  31207. } else {
  31208. doPasteAction();
  31209. }
  31210. }
  31211. };
  31212. const pasteHtml = (editor, html, internalFlag, shouldSimulateInputEvent) => {
  31213. const internal = internalFlag ? internalFlag : isMarked(html);
  31214. doPaste(editor, unmark(html), internal, false, shouldSimulateInputEvent);
  31215. };
  31216. const pasteText = (editor, text, shouldSimulateInputEvent) => {
  31217. const encodedText = editor.dom.encode(text).replace(/\r\n/g, "\n");
  31218. const normalizedText = normalize$4(encodedText, getPasteTabSpaces(editor));
  31219. const html = toBlockElements(
  31220. normalizedText,
  31221. getForcedRootBlock(editor),
  31222. getForcedRootBlockAttrs(editor)
  31223. );
  31224. doPaste(editor, html, false, true, shouldSimulateInputEvent);
  31225. };
  31226. const getDataTransferItems = (dataTransfer) => {
  31227. const items = {};
  31228. if (dataTransfer && dataTransfer.types) {
  31229. for (let i = 0; i < dataTransfer.types.length; i++) {
  31230. const contentType = dataTransfer.types[i];
  31231. try {
  31232. items[contentType] = dataTransfer.getData(contentType);
  31233. } catch (ex) {
  31234. items[contentType] = "";
  31235. }
  31236. }
  31237. }
  31238. return items;
  31239. };
  31240. const hasContentType = (clipboardContent, mimeType) =>
  31241. mimeType in clipboardContent && clipboardContent[mimeType].length > 0;
  31242. const hasHtmlOrText = (content) =>
  31243. hasContentType(content, "text/html") ||
  31244. hasContentType(content, "text/plain");
  31245. const extractFilename = (editor, str) => {
  31246. const m = str.match(/([\s\S]+?)(?:\.[a-z0-9.]+)$/i);
  31247. return isNonNullable(m) ? editor.dom.encode(m[1]) : undefined;
  31248. };
  31249. const createBlobInfo = (editor, blobCache, file, base64) => {
  31250. const id = uniqueId();
  31251. const useFileName = shouldReuseFileName(editor) && isNonNullable(file.name);
  31252. const name = useFileName ? extractFilename(editor, file.name) : id;
  31253. const filename = useFileName ? file.name : undefined;
  31254. const blobInfo = blobCache.create(id, file, base64, name, filename);
  31255. blobCache.add(blobInfo);
  31256. return blobInfo;
  31257. };
  31258. const pasteImage = (editor, imageItem) => {
  31259. parseDataUri(imageItem.uri).each(({ data, type, base64Encoded }) => {
  31260. const base64 = base64Encoded ? data : btoa(data);
  31261. const file = imageItem.file;
  31262. const blobCache = editor.editorUpload.blobCache;
  31263. const existingBlobInfo = blobCache.getByData(base64, type);
  31264. const blobInfo =
  31265. existingBlobInfo !== null && existingBlobInfo !== void 0
  31266. ? existingBlobInfo
  31267. : createBlobInfo(editor, blobCache, file, base64);
  31268. pasteHtml(editor, `<img src="${blobInfo.blobUri()}">`, false, true);
  31269. });
  31270. };
  31271. const isClipboardEvent = (event) => event.type === "paste";
  31272. const readFilesAsDataUris = (items) =>
  31273. Promise.all(
  31274. map$3(items, (file) => {
  31275. return blobToDataUri(file).then((uri) => ({
  31276. file,
  31277. uri,
  31278. }));
  31279. })
  31280. );
  31281. const isImage = (editor) => {
  31282. const allowedExtensions = getAllowedImageFileTypes(editor);
  31283. return (file) =>
  31284. startsWith(file.type, "image/") &&
  31285. exists(allowedExtensions, (extension) => {
  31286. return getImageMimeType(extension) === file.type;
  31287. });
  31288. };
  31289. const getImagesFromDataTransfer = (editor, dataTransfer) => {
  31290. const items = dataTransfer.items
  31291. ? bind$3(from(dataTransfer.items), (item) => {
  31292. return item.kind === "file" ? [item.getAsFile()] : [];
  31293. })
  31294. : [];
  31295. const files = dataTransfer.files ? from(dataTransfer.files) : [];
  31296. return filter$5(items.length > 0 ? items : files, isImage(editor));
  31297. };
  31298. const pasteImageData = (editor, e, rng) => {
  31299. const dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer;
  31300. if (shouldPasteDataImages(editor) && dataTransfer) {
  31301. const images = getImagesFromDataTransfer(editor, dataTransfer);
  31302. if (images.length > 0) {
  31303. e.preventDefault();
  31304. readFilesAsDataUris(images).then((fileResults) => {
  31305. if (rng) {
  31306. editor.selection.setRng(rng);
  31307. }
  31308. each$e(fileResults, (result) => {
  31309. pasteImage(editor, result);
  31310. });
  31311. });
  31312. return true;
  31313. }
  31314. }
  31315. return false;
  31316. };
  31317. const isBrokenAndroidClipboardEvent = (e) => {
  31318. var _a, _b;
  31319. return (
  31320. Env.os.isAndroid() &&
  31321. ((_b =
  31322. (_a = e.clipboardData) === null || _a === void 0
  31323. ? void 0
  31324. : _a.items) === null || _b === void 0
  31325. ? void 0
  31326. : _b.length) === 0
  31327. );
  31328. };
  31329. const isKeyboardPasteEvent = (e) =>
  31330. (VK.metaKeyPressed(e) && e.keyCode === 86) ||
  31331. (e.shiftKey && e.keyCode === 45);
  31332. const insertClipboardContent = (
  31333. editor,
  31334. clipboardContent,
  31335. html,
  31336. plainTextMode,
  31337. shouldSimulateInputEvent
  31338. ) => {
  31339. let content = trimHtml(html);
  31340. const isInternal =
  31341. hasContentType(clipboardContent, internalHtmlMime()) || isMarked(html);
  31342. const isPlainTextHtml = !isInternal && isPlainText(content);
  31343. const isAbsoluteUrl$1 = isAbsoluteUrl(content);
  31344. if (
  31345. isDefaultPasteBinContent(content) ||
  31346. !content.length ||
  31347. (isPlainTextHtml && !isAbsoluteUrl$1)
  31348. ) {
  31349. plainTextMode = true;
  31350. }
  31351. if (plainTextMode || isAbsoluteUrl$1) {
  31352. if (hasContentType(clipboardContent, "text/plain") && isPlainTextHtml) {
  31353. content = clipboardContent["text/plain"];
  31354. } else {
  31355. content = innerText(content);
  31356. }
  31357. }
  31358. if (isDefaultPasteBinContent(content)) {
  31359. return;
  31360. }
  31361. if (plainTextMode) {
  31362. pasteText(editor, content, shouldSimulateInputEvent);
  31363. } else {
  31364. pasteHtml(editor, content, isInternal, shouldSimulateInputEvent);
  31365. }
  31366. };
  31367. const registerEventHandlers = (editor, pasteBin, pasteFormat) => {
  31368. let keyboardPastePlainTextState;
  31369. const getLastRng = () => pasteBin.getLastRng() || editor.selection.getRng();
  31370. editor.on("keydown", (e) => {
  31371. if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) {
  31372. keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86;
  31373. }
  31374. });
  31375. editor.on("paste", (e) => {
  31376. if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) {
  31377. return;
  31378. }
  31379. const plainTextMode =
  31380. pasteFormat.get() === "text" || keyboardPastePlainTextState;
  31381. keyboardPastePlainTextState = false;
  31382. const clipboardContent = getDataTransferItems(e.clipboardData);
  31383. if (
  31384. !hasHtmlOrText(clipboardContent) &&
  31385. pasteImageData(editor, e, getLastRng())
  31386. ) {
  31387. return;
  31388. }
  31389. if (hasContentType(clipboardContent, "text/html")) {
  31390. e.preventDefault();
  31391. insertClipboardContent(
  31392. editor,
  31393. clipboardContent,
  31394. clipboardContent["text/html"],
  31395. plainTextMode,
  31396. true
  31397. );
  31398. } else if (
  31399. hasContentType(clipboardContent, "text/plain") &&
  31400. hasContentType(clipboardContent, "text/uri-list")
  31401. ) {
  31402. e.preventDefault();
  31403. insertClipboardContent(
  31404. editor,
  31405. clipboardContent,
  31406. clipboardContent["text/plain"],
  31407. plainTextMode,
  31408. true
  31409. );
  31410. } else {
  31411. pasteBin.create();
  31412. Delay.setEditorTimeout(
  31413. editor,
  31414. () => {
  31415. const html = pasteBin.getHtml();
  31416. pasteBin.remove();
  31417. insertClipboardContent(
  31418. editor,
  31419. clipboardContent,
  31420. html,
  31421. plainTextMode,
  31422. false
  31423. );
  31424. },
  31425. 0
  31426. );
  31427. }
  31428. });
  31429. };
  31430. const registerDataImageFilter = (editor) => {
  31431. const isWebKitFakeUrl = (src) => startsWith(src, "webkit-fake-url");
  31432. const isDataUri = (src) => startsWith(src, "data:");
  31433. const isPasteInsert = (args) => {
  31434. var _a;
  31435. return (
  31436. ((_a = args.data) === null || _a === void 0 ? void 0 : _a.paste) ===
  31437. true
  31438. );
  31439. };
  31440. editor.parser.addNodeFilter("img", (nodes, name, args) => {
  31441. if (!shouldPasteDataImages(editor) && isPasteInsert(args)) {
  31442. for (const node of nodes) {
  31443. const src = node.attr("src");
  31444. if (
  31445. isString(src) &&
  31446. !node.attr("data-mce-object") &&
  31447. src !== Env.transparentSrc
  31448. ) {
  31449. if (isWebKitFakeUrl(src)) {
  31450. node.remove();
  31451. } else if (!shouldAllowHtmlDataUrls(editor) && isDataUri(src)) {
  31452. node.remove();
  31453. }
  31454. }
  31455. }
  31456. }
  31457. });
  31458. };
  31459. const registerEventsAndFilters = (editor, pasteBin, pasteFormat) => {
  31460. registerEventHandlers(editor, pasteBin, pasteFormat);
  31461. registerDataImageFilter(editor);
  31462. };
  31463. const togglePlainTextPaste = (editor, pasteFormat) => {
  31464. if (pasteFormat.get() === "text") {
  31465. pasteFormat.set("html");
  31466. firePastePlainTextToggle(editor, false);
  31467. } else {
  31468. pasteFormat.set("text");
  31469. firePastePlainTextToggle(editor, true);
  31470. }
  31471. editor.focus();
  31472. };
  31473. const register$1 = (editor, pasteFormat) => {
  31474. editor.addCommand("mceTogglePlainTextPaste", () => {
  31475. togglePlainTextPaste(editor, pasteFormat);
  31476. });
  31477. editor.addCommand("mceInsertClipboardContent", (ui, value) => {
  31478. if (value.html) {
  31479. pasteHtml(editor, value.html, value.internal, false);
  31480. }
  31481. if (value.text) {
  31482. pasteText(editor, value.text, false);
  31483. }
  31484. });
  31485. };
  31486. const setHtml5Clipboard = (clipboardData, html, text) => {
  31487. if (clipboardData) {
  31488. try {
  31489. clipboardData.clearData();
  31490. clipboardData.setData("text/html", html);
  31491. clipboardData.setData("text/plain", text);
  31492. clipboardData.setData(internalHtmlMime(), html);
  31493. return true;
  31494. } catch (e) {
  31495. return false;
  31496. }
  31497. } else {
  31498. return false;
  31499. }
  31500. };
  31501. const setClipboardData = (evt, data, fallback, done) => {
  31502. if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) {
  31503. evt.preventDefault();
  31504. done();
  31505. } else {
  31506. fallback(data.html, done);
  31507. }
  31508. };
  31509. const fallback = (editor) => (html, done) => {
  31510. const { dom, selection } = editor;
  31511. const outer = dom.create("div", {
  31512. contenteditable: "false",
  31513. "data-mce-bogus": "all",
  31514. });
  31515. const inner = dom.create("div", { contenteditable: "true" }, html);
  31516. dom.setStyles(outer, {
  31517. position: "fixed",
  31518. top: "0",
  31519. left: "-3000px",
  31520. width: "1000px",
  31521. overflow: "hidden",
  31522. });
  31523. outer.appendChild(inner);
  31524. dom.add(editor.getBody(), outer);
  31525. const range = selection.getRng();
  31526. inner.focus();
  31527. const offscreenRange = dom.createRng();
  31528. offscreenRange.selectNodeContents(inner);
  31529. selection.setRng(offscreenRange);
  31530. Delay.setEditorTimeout(
  31531. editor,
  31532. () => {
  31533. selection.setRng(range);
  31534. dom.remove(outer);
  31535. done();
  31536. },
  31537. 0
  31538. );
  31539. };
  31540. const getData = (editor) => ({
  31541. html: mark(editor.selection.getContent({ contextual: true })),
  31542. text: editor.selection.getContent({ format: "text" }),
  31543. });
  31544. const isTableSelection = (editor) =>
  31545. !!editor.dom.getParent(
  31546. editor.selection.getStart(),
  31547. "td[data-mce-selected],th[data-mce-selected]",
  31548. editor.getBody()
  31549. );
  31550. const hasSelectedContent = (editor) =>
  31551. !editor.selection.isCollapsed() || isTableSelection(editor);
  31552. const cut = (editor) => (evt) => {
  31553. if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
  31554. setClipboardData(evt, getData(editor), fallback(editor), () => {
  31555. if (Env.browser.isChromium() || Env.browser.isFirefox()) {
  31556. const rng = editor.selection.getRng();
  31557. Delay.setEditorTimeout(
  31558. editor,
  31559. () => {
  31560. editor.selection.setRng(rng);
  31561. editor.execCommand("Delete");
  31562. },
  31563. 0
  31564. );
  31565. } else {
  31566. editor.execCommand("Delete");
  31567. }
  31568. });
  31569. }
  31570. };
  31571. const copy = (editor) => (evt) => {
  31572. if (!evt.isDefaultPrevented() && hasSelectedContent(editor)) {
  31573. setClipboardData(evt, getData(editor), fallback(editor), noop);
  31574. }
  31575. };
  31576. const register = (editor) => {
  31577. editor.on("cut", cut(editor));
  31578. editor.on("copy", copy(editor));
  31579. };
  31580. const getCaretRangeFromEvent = (editor, e) => {
  31581. var _a, _b;
  31582. return RangeUtils.getCaretRangeFromPoint(
  31583. (_a = e.clientX) !== null && _a !== void 0 ? _a : 0,
  31584. (_b = e.clientY) !== null && _b !== void 0 ? _b : 0,
  31585. editor.getDoc()
  31586. );
  31587. };
  31588. const isPlainTextFileUrl = (content) => {
  31589. const plainTextContent = content["text/plain"];
  31590. return plainTextContent ? plainTextContent.indexOf("file://") === 0 : false;
  31591. };
  31592. const setFocusedRange = (editor, rng) => {
  31593. editor.focus();
  31594. if (rng) {
  31595. editor.selection.setRng(rng);
  31596. }
  31597. };
  31598. const hasImage = (dataTransfer) =>
  31599. exists(dataTransfer.files, (file) => /^image\//.test(file.type));
  31600. const needsCustomInternalDrop = (dom, schema, target, dropContent) => {
  31601. const parentTransparent = dom.getParent(target, (node) =>
  31602. isTransparentBlock(schema, node)
  31603. );
  31604. const inSummary = !isNull(dom.getParent(target, "summary"));
  31605. if (inSummary) {
  31606. return true;
  31607. } else if (parentTransparent && has$2(dropContent, "text/html")) {
  31608. const fragment = new DOMParser().parseFromString(
  31609. dropContent["text/html"],
  31610. "text/html"
  31611. ).body;
  31612. return !isNull(
  31613. fragment.querySelector(parentTransparent.nodeName.toLowerCase())
  31614. );
  31615. } else {
  31616. return false;
  31617. }
  31618. };
  31619. const setupSummaryDeleteByDragFix = (editor) => {
  31620. editor.on("input", (e) => {
  31621. const hasNoSummary = (el) => isNull(el.querySelector("summary"));
  31622. if (e.inputType === "deleteByDrag") {
  31623. const brokenDetailElements = filter$5(
  31624. editor.dom.select("details"),
  31625. hasNoSummary
  31626. );
  31627. each$e(brokenDetailElements, (details) => {
  31628. if (isBr$6(details.firstChild)) {
  31629. details.firstChild.remove();
  31630. }
  31631. const summary = editor.dom.create("summary");
  31632. summary.appendChild(createPaddingBr().dom);
  31633. details.prepend(summary);
  31634. });
  31635. }
  31636. });
  31637. };
  31638. const setup$a = (editor, draggingInternallyState) => {
  31639. if (shouldPasteBlockDrop(editor)) {
  31640. editor.on("dragend dragover draggesture dragdrop drop drag", (e) => {
  31641. e.preventDefault();
  31642. e.stopPropagation();
  31643. });
  31644. }
  31645. if (!shouldPasteDataImages(editor)) {
  31646. editor.on("drop", (e) => {
  31647. const dataTransfer = e.dataTransfer;
  31648. if (dataTransfer && hasImage(dataTransfer)) {
  31649. e.preventDefault();
  31650. }
  31651. });
  31652. }
  31653. editor.on("drop", (e) => {
  31654. if (e.isDefaultPrevented()) {
  31655. return;
  31656. }
  31657. const rng = getCaretRangeFromEvent(editor, e);
  31658. if (isNullable(rng)) {
  31659. return;
  31660. }
  31661. const dropContent = getDataTransferItems(e.dataTransfer);
  31662. const internal = hasContentType(dropContent, internalHtmlMime());
  31663. if (
  31664. (!hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) &&
  31665. pasteImageData(editor, e, rng)
  31666. ) {
  31667. return;
  31668. }
  31669. const internalContent = dropContent[internalHtmlMime()];
  31670. const content =
  31671. internalContent ||
  31672. dropContent["text/html"] ||
  31673. dropContent["text/plain"];
  31674. const needsInternalDrop = needsCustomInternalDrop(
  31675. editor.dom,
  31676. editor.schema,
  31677. rng.startContainer,
  31678. dropContent
  31679. );
  31680. const isInternalDrop = draggingInternallyState.get();
  31681. if (isInternalDrop && !needsInternalDrop) {
  31682. return;
  31683. }
  31684. if (content) {
  31685. e.preventDefault();
  31686. Delay.setEditorTimeout(editor, () => {
  31687. editor.undoManager.transact(() => {
  31688. if (internalContent || (isInternalDrop && needsInternalDrop)) {
  31689. editor.execCommand("Delete");
  31690. }
  31691. setFocusedRange(editor, rng);
  31692. const trimmedContent = trimHtml(content);
  31693. if (dropContent["text/html"]) {
  31694. pasteHtml(editor, trimmedContent, internal, true);
  31695. } else {
  31696. pasteText(editor, trimmedContent, true);
  31697. }
  31698. });
  31699. });
  31700. }
  31701. });
  31702. editor.on("dragstart", (_e) => {
  31703. draggingInternallyState.set(true);
  31704. });
  31705. editor.on("dragover dragend", (e) => {
  31706. if (shouldPasteDataImages(editor) && !draggingInternallyState.get()) {
  31707. e.preventDefault();
  31708. setFocusedRange(editor, getCaretRangeFromEvent(editor, e));
  31709. }
  31710. if (e.type === "dragend") {
  31711. draggingInternallyState.set(false);
  31712. }
  31713. });
  31714. setupSummaryDeleteByDragFix(editor);
  31715. };
  31716. const setup$9 = (editor) => {
  31717. const processEvent = (f) => (e) => {
  31718. f(editor, e);
  31719. };
  31720. const preProcess = getPastePreProcess(editor);
  31721. if (isFunction(preProcess)) {
  31722. editor.on("PastePreProcess", processEvent(preProcess));
  31723. }
  31724. const postProcess = getPastePostProcess(editor);
  31725. if (isFunction(postProcess)) {
  31726. editor.on("PastePostProcess", processEvent(postProcess));
  31727. }
  31728. };
  31729. const addPreProcessFilter = (editor, filterFunc) => {
  31730. editor.on("PastePreProcess", (e) => {
  31731. e.content = filterFunc(editor, e.content, e.internal);
  31732. });
  31733. };
  31734. const rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi;
  31735. const rgbToHex = (value) =>
  31736. Tools.trim(value).replace(rgbRegExp, rgbaToHexString).toLowerCase();
  31737. const removeWebKitStyles = (editor, content, internal) => {
  31738. const webKitStylesOption = getPasteWebkitStyles(editor);
  31739. if (
  31740. internal ||
  31741. webKitStylesOption === "all" ||
  31742. !shouldPasteRemoveWebKitStyles(editor)
  31743. ) {
  31744. return content;
  31745. }
  31746. const webKitStyles = webKitStylesOption
  31747. ? webKitStylesOption.split(/[, ]/)
  31748. : [];
  31749. if (webKitStyles && webKitStylesOption !== "none") {
  31750. const dom = editor.dom,
  31751. node = editor.selection.getNode();
  31752. content = content.replace(
  31753. /(<[^>]+) style="([^"]*)"([^>]*>)/gi,
  31754. (all, before, value, after) => {
  31755. const inputStyles = dom.parseStyle(dom.decode(value));
  31756. const outputStyles = {};
  31757. for (let i = 0; i < webKitStyles.length; i++) {
  31758. const inputValue = inputStyles[webKitStyles[i]];
  31759. let compareInput = inputValue;
  31760. let currentValue = dom.getStyle(node, webKitStyles[i], true);
  31761. if (/color/.test(webKitStyles[i])) {
  31762. compareInput = rgbToHex(compareInput);
  31763. currentValue = rgbToHex(currentValue);
  31764. }
  31765. if (currentValue !== compareInput) {
  31766. outputStyles[webKitStyles[i]] = inputValue;
  31767. }
  31768. }
  31769. const outputStyle = dom.serializeStyle(outputStyles, "span");
  31770. if (outputStyle) {
  31771. return before + ' style="' + outputStyle + '"' + after;
  31772. }
  31773. return before + after;
  31774. }
  31775. );
  31776. } else {
  31777. content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, "$1$3");
  31778. }
  31779. content = content.replace(
  31780. /(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,
  31781. (all, before, value, after) => {
  31782. return before + ' style="' + value + '"' + after;
  31783. }
  31784. );
  31785. return content;
  31786. };
  31787. const setup$8 = (editor) => {
  31788. if (Env.browser.isChromium() || Env.browser.isSafari()) {
  31789. addPreProcessFilter(editor, removeWebKitStyles);
  31790. }
  31791. };
  31792. const setup$7 = (editor) => {
  31793. const draggingInternallyState = Cell(false);
  31794. const pasteFormat = Cell(isPasteAsTextEnabled(editor) ? "text" : "html");
  31795. const pasteBin = PasteBin(editor);
  31796. setup$8(editor);
  31797. register$1(editor, pasteFormat);
  31798. setup$9(editor);
  31799. editor.on("PreInit", () => {
  31800. register(editor);
  31801. setup$a(editor, draggingInternallyState);
  31802. registerEventsAndFilters(editor, pasteBin, pasteFormat);
  31803. });
  31804. };
  31805. const preventSummaryToggle = (editor) => {
  31806. editor.on("click", (e) => {
  31807. if (editor.dom.getParent(e.target, "details")) {
  31808. e.preventDefault();
  31809. }
  31810. });
  31811. };
  31812. const filterDetails = (editor) => {
  31813. editor.parser.addNodeFilter("details", (elms) => {
  31814. const initialStateOption = getDetailsInitialState(editor);
  31815. each$e(elms, (details) => {
  31816. if (initialStateOption === "expanded") {
  31817. details.attr("open", "open");
  31818. } else if (initialStateOption === "collapsed") {
  31819. details.attr("open", null);
  31820. }
  31821. });
  31822. });
  31823. editor.serializer.addNodeFilter("details", (elms) => {
  31824. const serializedStateOption = getDetailsSerializedState(editor);
  31825. each$e(elms, (details) => {
  31826. if (serializedStateOption === "expanded") {
  31827. details.attr("open", "open");
  31828. } else if (serializedStateOption === "collapsed") {
  31829. details.attr("open", null);
  31830. }
  31831. });
  31832. });
  31833. };
  31834. const setup$6 = (editor) => {
  31835. preventSummaryToggle(editor);
  31836. filterDetails(editor);
  31837. };
  31838. const isBr = isBr$6;
  31839. const isText = isText$a;
  31840. const isContentEditableFalse$2 = (elm) => isContentEditableFalse$b(elm.dom);
  31841. const isContentEditableTrue = (elm) => isContentEditableTrue$3(elm.dom);
  31842. const isRoot = (rootNode) => (elm) => eq(SugarElement.fromDom(rootNode), elm);
  31843. const getClosestScope = (node, rootNode) =>
  31844. closest$4(
  31845. SugarElement.fromDom(node),
  31846. (elm) => isContentEditableTrue(elm) || isBlock$2(elm),
  31847. isRoot(rootNode)
  31848. ).getOr(SugarElement.fromDom(rootNode)).dom;
  31849. const getClosestCef = (node, rootNode) =>
  31850. closest$4(
  31851. SugarElement.fromDom(node),
  31852. isContentEditableFalse$2,
  31853. isRoot(rootNode)
  31854. );
  31855. const findEdgeCaretCandidate = (startNode, scope, forward) => {
  31856. const walker = new DomTreeWalker(startNode, scope);
  31857. const next = forward ? walker.next.bind(walker) : walker.prev.bind(walker);
  31858. let result = startNode;
  31859. for (
  31860. let current = forward ? startNode : next();
  31861. current && !isBr(current);
  31862. current = next()
  31863. ) {
  31864. if (isCaretCandidate$3(current)) {
  31865. result = current;
  31866. }
  31867. }
  31868. return result;
  31869. };
  31870. const findClosestBlockRange = (startRng, rootNode) => {
  31871. const startPos = CaretPosition.fromRangeStart(startRng);
  31872. const clickNode = startPos.getNode();
  31873. const scope = getClosestScope(clickNode, rootNode);
  31874. const startNode = findEdgeCaretCandidate(clickNode, scope, false);
  31875. const endNode = findEdgeCaretCandidate(clickNode, scope, true);
  31876. const rng = document.createRange();
  31877. getClosestCef(startNode, scope).fold(
  31878. () => {
  31879. if (isText(startNode)) {
  31880. rng.setStart(startNode, 0);
  31881. } else {
  31882. rng.setStartBefore(startNode);
  31883. }
  31884. },
  31885. (cef) => rng.setStartBefore(cef.dom)
  31886. );
  31887. getClosestCef(endNode, scope).fold(
  31888. () => {
  31889. if (isText(endNode)) {
  31890. rng.setEnd(endNode, endNode.data.length);
  31891. } else {
  31892. rng.setEndAfter(endNode);
  31893. }
  31894. },
  31895. (cef) => rng.setEndAfter(cef.dom)
  31896. );
  31897. return rng;
  31898. };
  31899. const onTripleClickSelect = (editor) => {
  31900. const rng = findClosestBlockRange(
  31901. editor.selection.getRng(),
  31902. editor.getBody()
  31903. );
  31904. editor.selection.setRng(normalize(rng));
  31905. };
  31906. const setup$5 = (editor) => {
  31907. editor.on("mousedown", (e) => {
  31908. if (e.detail >= 3) {
  31909. e.preventDefault();
  31910. onTripleClickSelect(editor);
  31911. }
  31912. });
  31913. };
  31914. var FakeCaretPosition;
  31915. (function (FakeCaretPosition) {
  31916. FakeCaretPosition["Before"] = "before";
  31917. FakeCaretPosition["After"] = "after";
  31918. })(FakeCaretPosition || (FakeCaretPosition = {}));
  31919. const distanceToRectLeft = (clientRect, clientX) =>
  31920. Math.abs(clientRect.left - clientX);
  31921. const distanceToRectRight = (clientRect, clientX) =>
  31922. Math.abs(clientRect.right - clientX);
  31923. const isInsideY = (clientY, clientRect) =>
  31924. clientY >= clientRect.top && clientY <= clientRect.bottom;
  31925. const collidesY = (r1, r2) => r1.top < r2.bottom && r1.bottom > r2.top;
  31926. const isOverlapping = (r1, r2) => {
  31927. const overlap = overlapY(r1, r2) / Math.min(r1.height, r2.height);
  31928. return collidesY(r1, r2) && overlap > 0.5;
  31929. };
  31930. const splitRectsPerAxis = (rects, y) => {
  31931. const intersectingRects = filter$5(rects, (rect) => isInsideY(y, rect));
  31932. return boundingClientRectFromRects(intersectingRects).fold(
  31933. () => [[], rects],
  31934. (boundingRect) => {
  31935. const { pass: horizontal, fail: vertical } = partition$2(
  31936. rects,
  31937. (rect) => isOverlapping(rect, boundingRect)
  31938. );
  31939. return [horizontal, vertical];
  31940. }
  31941. );
  31942. };
  31943. const clientInfo = (rect, clientX) => {
  31944. return {
  31945. node: rect.node,
  31946. position:
  31947. distanceToRectLeft(rect, clientX) < distanceToRectRight(rect, clientX)
  31948. ? FakeCaretPosition.Before
  31949. : FakeCaretPosition.After,
  31950. };
  31951. };
  31952. const horizontalDistance = (rect, x, _y) =>
  31953. x > rect.left && x < rect.right
  31954. ? 0
  31955. : Math.min(Math.abs(rect.left - x), Math.abs(rect.right - x));
  31956. const closestChildCaretCandidateNodeRect = (children, clientX, clientY) => {
  31957. const caretCandidateRect = (rect) => {
  31958. if (isCaretCandidate$3(rect.node)) {
  31959. return Optional.some(rect);
  31960. } else if (isElement$6(rect.node)) {
  31961. return closestChildCaretCandidateNodeRect(
  31962. from(rect.node.childNodes),
  31963. clientX,
  31964. clientY
  31965. );
  31966. } else {
  31967. return Optional.none();
  31968. }
  31969. };
  31970. const getClosestTextNode = (rects, distance) => {
  31971. if (rects.length >= 2) {
  31972. const r1 = caretCandidateRect(rects[0]).getOr(rects[0]);
  31973. const r2 = caretCandidateRect(rects[1]).getOr(rects[1]);
  31974. const deltaDistance = Math.abs(
  31975. distance(r1, clientX, clientY) - distance(r2, clientX, clientY)
  31976. );
  31977. if (deltaDistance < 2) {
  31978. if (isText$a(r1.node)) {
  31979. return Optional.some(r1);
  31980. } else if (isText$a(r2.node)) {
  31981. return Optional.some(r2);
  31982. }
  31983. }
  31984. }
  31985. return Optional.none();
  31986. };
  31987. const findClosestCaretCandidateNodeRect = (rects, distance) => {
  31988. const sortedRects = sort(
  31989. rects,
  31990. (r1, r2) =>
  31991. distance(r1, clientX, clientY) - distance(r2, clientX, clientY)
  31992. );
  31993. return getClosestTextNode(sortedRects, distance).orThunk(() =>
  31994. findMap(sortedRects, caretCandidateRect)
  31995. );
  31996. };
  31997. const [horizontalRects, verticalRects] = splitRectsPerAxis(
  31998. getClientRects(children),
  31999. clientY
  32000. );
  32001. const { pass: above, fail: below } = partition$2(
  32002. verticalRects,
  32003. (rect) => rect.top < clientY
  32004. );
  32005. return findClosestCaretCandidateNodeRect(
  32006. horizontalRects,
  32007. horizontalDistance
  32008. )
  32009. .orThunk(() =>
  32010. findClosestCaretCandidateNodeRect(below, distanceToRectEdgeFromXY)
  32011. )
  32012. .orThunk(() =>
  32013. findClosestCaretCandidateNodeRect(above, distanceToRectEdgeFromXY)
  32014. );
  32015. };
  32016. const traverseUp = (rootElm, scope, clientX, clientY) => {
  32017. const helper = (scope, prevScope) => {
  32018. const isDragGhostContainer = (node) =>
  32019. isElement$6(node) && node.classList.contains("mce-drag-container");
  32020. const childNodesWithoutGhost = filter$5(
  32021. scope.dom.childNodes,
  32022. not(isDragGhostContainer)
  32023. );
  32024. return prevScope
  32025. .fold(
  32026. () =>
  32027. closestChildCaretCandidateNodeRect(
  32028. childNodesWithoutGhost,
  32029. clientX,
  32030. clientY
  32031. ),
  32032. (prevScope) => {
  32033. const uncheckedChildren = filter$5(
  32034. childNodesWithoutGhost,
  32035. (node) => node !== prevScope.dom
  32036. );
  32037. return closestChildCaretCandidateNodeRect(
  32038. uncheckedChildren,
  32039. clientX,
  32040. clientY
  32041. );
  32042. }
  32043. )
  32044. .orThunk(() => {
  32045. const parent = eq(scope, rootElm)
  32046. ? Optional.none()
  32047. : parentElement(scope);
  32048. return parent.bind((newScope) =>
  32049. helper(newScope, Optional.some(scope))
  32050. );
  32051. });
  32052. };
  32053. return helper(scope, Optional.none());
  32054. };
  32055. const closestCaretCandidateNodeRect = (root, clientX, clientY) => {
  32056. const rootElm = SugarElement.fromDom(root);
  32057. const ownerDoc = documentOrOwner(rootElm);
  32058. const elementAtPoint = SugarElement.fromPoint(
  32059. ownerDoc,
  32060. clientX,
  32061. clientY
  32062. ).filter((elm) => contains(rootElm, elm));
  32063. const element = elementAtPoint.getOr(rootElm);
  32064. return traverseUp(rootElm, element, clientX, clientY);
  32065. };
  32066. const closestFakeCaretCandidate = (root, clientX, clientY) =>
  32067. closestCaretCandidateNodeRect(root, clientX, clientY)
  32068. .filter((rect) => isFakeCaretTarget(rect.node))
  32069. .map((rect) => clientInfo(rect, clientX));
  32070. const getAbsolutePosition = (elm) => {
  32071. var _a, _b;
  32072. const clientRect = elm.getBoundingClientRect();
  32073. const doc = elm.ownerDocument;
  32074. const docElem = doc.documentElement;
  32075. const win = doc.defaultView;
  32076. return {
  32077. top:
  32078. clientRect.top +
  32079. ((_a = win === null || win === void 0 ? void 0 : win.scrollY) !==
  32080. null && _a !== void 0
  32081. ? _a
  32082. : 0) -
  32083. docElem.clientTop,
  32084. left:
  32085. clientRect.left +
  32086. ((_b = win === null || win === void 0 ? void 0 : win.scrollX) !==
  32087. null && _b !== void 0
  32088. ? _b
  32089. : 0) -
  32090. docElem.clientLeft,
  32091. };
  32092. };
  32093. const getBodyPosition = (editor) =>
  32094. editor.inline
  32095. ? getAbsolutePosition(editor.getBody())
  32096. : {
  32097. left: 0,
  32098. top: 0,
  32099. };
  32100. const getScrollPosition = (editor) => {
  32101. const body = editor.getBody();
  32102. return editor.inline
  32103. ? {
  32104. left: body.scrollLeft,
  32105. top: body.scrollTop,
  32106. }
  32107. : {
  32108. left: 0,
  32109. top: 0,
  32110. };
  32111. };
  32112. const getBodyScroll = (editor) => {
  32113. const body = editor.getBody(),
  32114. docElm = editor.getDoc().documentElement;
  32115. const inlineScroll = {
  32116. left: body.scrollLeft,
  32117. top: body.scrollTop,
  32118. };
  32119. const iframeScroll = {
  32120. left: body.scrollLeft || docElm.scrollLeft,
  32121. top: body.scrollTop || docElm.scrollTop,
  32122. };
  32123. return editor.inline ? inlineScroll : iframeScroll;
  32124. };
  32125. const getMousePosition = (editor, event) => {
  32126. if (event.target.ownerDocument !== editor.getDoc()) {
  32127. const iframePosition = getAbsolutePosition(
  32128. editor.getContentAreaContainer()
  32129. );
  32130. const scrollPosition = getBodyScroll(editor);
  32131. return {
  32132. left: event.pageX - iframePosition.left + scrollPosition.left,
  32133. top: event.pageY - iframePosition.top + scrollPosition.top,
  32134. };
  32135. }
  32136. return {
  32137. left: event.pageX,
  32138. top: event.pageY,
  32139. };
  32140. };
  32141. const calculatePosition = (bodyPosition, scrollPosition, mousePosition) => ({
  32142. pageX: mousePosition.left - bodyPosition.left + scrollPosition.left,
  32143. pageY: mousePosition.top - bodyPosition.top + scrollPosition.top,
  32144. });
  32145. const calc = (editor, event) =>
  32146. calculatePosition(
  32147. getBodyPosition(editor),
  32148. getScrollPosition(editor),
  32149. getMousePosition(editor, event)
  32150. );
  32151. const getTargetProps = (target) => ({
  32152. target,
  32153. srcElement: target,
  32154. });
  32155. const makeDndEventFromMouseEvent = (
  32156. type,
  32157. mouseEvent,
  32158. target,
  32159. dataTransfer
  32160. ) => ({
  32161. ...mouseEvent,
  32162. dataTransfer,
  32163. type,
  32164. ...getTargetProps(target),
  32165. });
  32166. const makeDndEvent = (type, target, dataTransfer) => {
  32167. const fail = die("Function not supported on simulated event.");
  32168. const event = {
  32169. bubbles: true,
  32170. cancelBubble: false,
  32171. cancelable: true,
  32172. composed: false,
  32173. currentTarget: null,
  32174. defaultPrevented: false,
  32175. eventPhase: 0,
  32176. isTrusted: true,
  32177. returnValue: false,
  32178. timeStamp: 0,
  32179. type,
  32180. composedPath: fail,
  32181. initEvent: fail,
  32182. preventDefault: noop,
  32183. stopImmediatePropagation: noop,
  32184. stopPropagation: noop,
  32185. AT_TARGET: window.Event.AT_TARGET,
  32186. BUBBLING_PHASE: window.Event.BUBBLING_PHASE,
  32187. CAPTURING_PHASE: window.Event.CAPTURING_PHASE,
  32188. NONE: window.Event.NONE,
  32189. altKey: false,
  32190. button: 0,
  32191. buttons: 0,
  32192. clientX: 0,
  32193. clientY: 0,
  32194. ctrlKey: false,
  32195. metaKey: false,
  32196. movementX: 0,
  32197. movementY: 0,
  32198. offsetX: 0,
  32199. offsetY: 0,
  32200. pageX: 0,
  32201. pageY: 0,
  32202. relatedTarget: null,
  32203. screenX: 0,
  32204. screenY: 0,
  32205. shiftKey: false,
  32206. x: 0,
  32207. y: 0,
  32208. detail: 0,
  32209. view: null,
  32210. which: 0,
  32211. initUIEvent: fail,
  32212. initMouseEvent: fail,
  32213. getModifierState: fail,
  32214. dataTransfer,
  32215. ...getTargetProps(target),
  32216. };
  32217. return event;
  32218. };
  32219. const makeDataTransferCopyForDragEvent = (dataTransfer, eventType) => {
  32220. const copy = cloneDataTransfer(dataTransfer);
  32221. if (eventType === "dragstart") {
  32222. setDragstartEvent(copy);
  32223. setReadWriteMode(copy);
  32224. } else if (eventType === "drop") {
  32225. setDropEvent(copy);
  32226. setReadOnlyMode(copy);
  32227. } else {
  32228. setDragendEvent(copy);
  32229. setProtectedMode(copy);
  32230. }
  32231. return copy;
  32232. };
  32233. const makeDragEvent = (type, target, dataTransfer, mouseEvent) => {
  32234. const dataTransferForDispatch = makeDataTransferCopyForDragEvent(
  32235. dataTransfer,
  32236. type
  32237. );
  32238. return isUndefined(mouseEvent)
  32239. ? makeDndEvent(type, target, dataTransferForDispatch)
  32240. : makeDndEventFromMouseEvent(
  32241. type,
  32242. mouseEvent,
  32243. target,
  32244. dataTransferForDispatch
  32245. );
  32246. };
  32247. const scrollPixelsPerInterval = 32;
  32248. const scrollIntervalValue = 100;
  32249. const mouseRangeToTriggerScrollInsideEditor = 8;
  32250. const mouseRangeToTriggerScrollOutsideEditor = 16;
  32251. const isContentEditableFalse$1 = isContentEditableFalse$b;
  32252. const isContentEditable = or(
  32253. isContentEditableFalse$1,
  32254. isContentEditableTrue$3
  32255. );
  32256. const isDraggable = (dom, rootElm, elm) =>
  32257. isContentEditableFalse$1(elm) &&
  32258. elm !== rootElm &&
  32259. dom.isEditable(elm.parentElement);
  32260. const isValidDropTarget = (editor, targetElement, dragElement) => {
  32261. if (isNullable(targetElement)) {
  32262. return false;
  32263. } else if (
  32264. targetElement === dragElement ||
  32265. editor.dom.isChildOf(targetElement, dragElement)
  32266. ) {
  32267. return false;
  32268. } else {
  32269. return editor.dom.isEditable(targetElement);
  32270. }
  32271. };
  32272. const createGhost = (editor, elm, width, height) => {
  32273. const dom = editor.dom;
  32274. const clonedElm = elm.cloneNode(true);
  32275. dom.setStyles(clonedElm, {
  32276. width,
  32277. height,
  32278. });
  32279. dom.setAttrib(clonedElm, "data-mce-selected", null);
  32280. const ghostElm = dom.create("div", {
  32281. class: "mce-drag-container",
  32282. "data-mce-bogus": "all",
  32283. unselectable: "on",
  32284. contenteditable: "false",
  32285. });
  32286. dom.setStyles(ghostElm, {
  32287. position: "absolute",
  32288. opacity: 0.5,
  32289. overflow: "hidden",
  32290. border: 0,
  32291. padding: 0,
  32292. margin: 0,
  32293. width,
  32294. height,
  32295. });
  32296. dom.setStyles(clonedElm, {
  32297. margin: 0,
  32298. boxSizing: "border-box",
  32299. });
  32300. ghostElm.appendChild(clonedElm);
  32301. return ghostElm;
  32302. };
  32303. const appendGhostToBody = (ghostElm, bodyElm) => {
  32304. if (ghostElm.parentNode !== bodyElm) {
  32305. bodyElm.appendChild(ghostElm);
  32306. }
  32307. };
  32308. const scrollEditor = (direction, amount) => (win) => () => {
  32309. const current = direction === "left" ? win.scrollX : win.scrollY;
  32310. win.scroll({
  32311. [direction]: current + amount,
  32312. behavior: "smooth",
  32313. });
  32314. };
  32315. const scrollLeft = scrollEditor("left", -scrollPixelsPerInterval);
  32316. const scrollRight = scrollEditor("left", scrollPixelsPerInterval);
  32317. const scrollUp = scrollEditor("top", -scrollPixelsPerInterval);
  32318. const scrollDown = scrollEditor("top", scrollPixelsPerInterval);
  32319. const moveGhost = (
  32320. ghostElm,
  32321. position,
  32322. width,
  32323. height,
  32324. maxX,
  32325. maxY,
  32326. mouseY,
  32327. mouseX,
  32328. contentAreaContainer,
  32329. win,
  32330. state,
  32331. mouseEventOriginatedFromWithinTheEditor
  32332. ) => {
  32333. let overflowX = 0,
  32334. overflowY = 0;
  32335. ghostElm.style.left = position.pageX + "px";
  32336. ghostElm.style.top = position.pageY + "px";
  32337. if (position.pageX + width > maxX) {
  32338. overflowX = position.pageX + width - maxX;
  32339. }
  32340. if (position.pageY + height > maxY) {
  32341. overflowY = position.pageY + height - maxY;
  32342. }
  32343. ghostElm.style.width = width - overflowX + "px";
  32344. ghostElm.style.height = height - overflowY + "px";
  32345. const clientHeight = contentAreaContainer.clientHeight;
  32346. const clientWidth = contentAreaContainer.clientWidth;
  32347. const outerMouseY =
  32348. mouseY + contentAreaContainer.getBoundingClientRect().top;
  32349. const outerMouseX =
  32350. mouseX + contentAreaContainer.getBoundingClientRect().left;
  32351. state.on((state) => {
  32352. state.intervalId.clear();
  32353. if (state.dragging && mouseEventOriginatedFromWithinTheEditor) {
  32354. if (mouseY + mouseRangeToTriggerScrollInsideEditor >= clientHeight) {
  32355. state.intervalId.set(scrollDown(win));
  32356. } else if (mouseY - mouseRangeToTriggerScrollInsideEditor <= 0) {
  32357. state.intervalId.set(scrollUp(win));
  32358. } else if (
  32359. mouseX + mouseRangeToTriggerScrollInsideEditor >=
  32360. clientWidth
  32361. ) {
  32362. state.intervalId.set(scrollRight(win));
  32363. } else if (mouseX - mouseRangeToTriggerScrollInsideEditor <= 0) {
  32364. state.intervalId.set(scrollLeft(win));
  32365. } else if (
  32366. outerMouseY + mouseRangeToTriggerScrollOutsideEditor >=
  32367. window.innerHeight
  32368. ) {
  32369. state.intervalId.set(scrollDown(window));
  32370. } else if (outerMouseY - mouseRangeToTriggerScrollOutsideEditor <= 0) {
  32371. state.intervalId.set(scrollUp(window));
  32372. } else if (
  32373. outerMouseX + mouseRangeToTriggerScrollOutsideEditor >=
  32374. window.innerWidth
  32375. ) {
  32376. state.intervalId.set(scrollRight(window));
  32377. } else if (outerMouseX - mouseRangeToTriggerScrollOutsideEditor <= 0) {
  32378. state.intervalId.set(scrollLeft(window));
  32379. }
  32380. }
  32381. });
  32382. };
  32383. const removeElement = (elm) => {
  32384. if (elm && elm.parentNode) {
  32385. elm.parentNode.removeChild(elm);
  32386. }
  32387. };
  32388. const removeElementWithPadding = (dom, elm) => {
  32389. const parentBlock = dom.getParent(elm.parentNode, dom.isBlock);
  32390. removeElement(elm);
  32391. if (
  32392. parentBlock &&
  32393. parentBlock !== dom.getRoot() &&
  32394. dom.isEmpty(parentBlock)
  32395. ) {
  32396. fillWithPaddingBr(SugarElement.fromDom(parentBlock));
  32397. }
  32398. };
  32399. const isLeftMouseButtonPressed = (e) => e.button === 0;
  32400. const applyRelPos = (state, position) => ({
  32401. pageX: position.pageX - state.relX,
  32402. pageY: position.pageY + 5,
  32403. });
  32404. const start = (state, editor) => (e) => {
  32405. if (isLeftMouseButtonPressed(e)) {
  32406. const ceElm = find$2(
  32407. editor.dom.getParents(e.target),
  32408. isContentEditable
  32409. ).getOr(null);
  32410. if (
  32411. isNonNullable(ceElm) &&
  32412. isDraggable(editor.dom, editor.getBody(), ceElm)
  32413. ) {
  32414. const elmPos = editor.dom.getPos(ceElm);
  32415. const bodyElm = editor.getBody();
  32416. const docElm = editor.getDoc().documentElement;
  32417. state.set({
  32418. element: ceElm,
  32419. dataTransfer: createDataTransfer(),
  32420. dragging: false,
  32421. screenX: e.screenX,
  32422. screenY: e.screenY,
  32423. maxX: (editor.inline ? bodyElm.scrollWidth : docElm.offsetWidth) - 2,
  32424. maxY:
  32425. (editor.inline ? bodyElm.scrollHeight : docElm.offsetHeight) - 2,
  32426. relX: e.pageX - elmPos.x,
  32427. relY: e.pageY - elmPos.y,
  32428. width: ceElm.offsetWidth,
  32429. height: ceElm.offsetHeight,
  32430. ghost: createGhost(
  32431. editor,
  32432. ceElm,
  32433. ceElm.offsetWidth,
  32434. ceElm.offsetHeight
  32435. ),
  32436. intervalId: repeatable(scrollIntervalValue),
  32437. });
  32438. }
  32439. }
  32440. };
  32441. const placeCaretAt = (editor, clientX, clientY) => {
  32442. editor._selectionOverrides.hideFakeCaret();
  32443. closestFakeCaretCandidate(editor.getBody(), clientX, clientY).fold(
  32444. () => editor.selection.placeCaretAt(clientX, clientY),
  32445. (caretInfo) => {
  32446. const range = editor._selectionOverrides.showCaret(
  32447. 1,
  32448. caretInfo.node,
  32449. caretInfo.position === FakeCaretPosition.Before,
  32450. false
  32451. );
  32452. if (range) {
  32453. editor.selection.setRng(range);
  32454. } else {
  32455. editor.selection.placeCaretAt(clientX, clientY);
  32456. }
  32457. }
  32458. );
  32459. };
  32460. const dispatchDragEvent = (
  32461. editor,
  32462. type,
  32463. target,
  32464. dataTransfer,
  32465. mouseEvent
  32466. ) => {
  32467. if (type === "dragstart") {
  32468. setHtmlData(dataTransfer, editor.dom.getOuterHTML(target));
  32469. }
  32470. const event = makeDragEvent(type, target, dataTransfer, mouseEvent);
  32471. const args = editor.dispatch(type, event);
  32472. return args;
  32473. };
  32474. const move = (state, editor) => {
  32475. const throttledPlaceCaretAt = first$1(
  32476. (clientX, clientY) => placeCaretAt(editor, clientX, clientY),
  32477. 0
  32478. );
  32479. editor.on("remove", throttledPlaceCaretAt.cancel);
  32480. const state_ = state;
  32481. return (e) =>
  32482. state.on((state) => {
  32483. const movement = Math.max(
  32484. Math.abs(e.screenX - state.screenX),
  32485. Math.abs(e.screenY - state.screenY)
  32486. );
  32487. if (!state.dragging && movement > 10) {
  32488. const args = dispatchDragEvent(
  32489. editor,
  32490. "dragstart",
  32491. state.element,
  32492. state.dataTransfer,
  32493. e
  32494. );
  32495. if (isNonNullable(args.dataTransfer)) {
  32496. state.dataTransfer = args.dataTransfer;
  32497. }
  32498. if (args.isDefaultPrevented()) {
  32499. return;
  32500. }
  32501. state.dragging = true;
  32502. editor.focus();
  32503. }
  32504. if (state.dragging) {
  32505. const mouseEventOriginatedFromWithinTheEditor =
  32506. e.currentTarget === editor.getDoc().documentElement;
  32507. const targetPos = applyRelPos(state, calc(editor, e));
  32508. appendGhostToBody(state.ghost, editor.getBody());
  32509. moveGhost(
  32510. state.ghost,
  32511. targetPos,
  32512. state.width,
  32513. state.height,
  32514. state.maxX,
  32515. state.maxY,
  32516. e.clientY,
  32517. e.clientX,
  32518. editor.getContentAreaContainer(),
  32519. editor.getWin(),
  32520. state_,
  32521. mouseEventOriginatedFromWithinTheEditor
  32522. );
  32523. throttledPlaceCaretAt.throttle(e.clientX, e.clientY);
  32524. }
  32525. });
  32526. };
  32527. const getRawTarget = (selection) => {
  32528. const sel = selection.getSel();
  32529. if (isNonNullable(sel)) {
  32530. const rng = sel.getRangeAt(0);
  32531. const startContainer = rng.startContainer;
  32532. return isText$a(startContainer)
  32533. ? startContainer.parentNode
  32534. : startContainer;
  32535. } else {
  32536. return null;
  32537. }
  32538. };
  32539. const drop = (state, editor) => (e) => {
  32540. state.on((state) => {
  32541. var _a;
  32542. state.intervalId.clear();
  32543. if (state.dragging) {
  32544. if (
  32545. isValidDropTarget(
  32546. editor,
  32547. getRawTarget(editor.selection),
  32548. state.element
  32549. )
  32550. ) {
  32551. const dropTarget =
  32552. (_a = editor.getDoc().elementFromPoint(e.clientX, e.clientY)) !==
  32553. null && _a !== void 0
  32554. ? _a
  32555. : editor.getBody();
  32556. const args = dispatchDragEvent(
  32557. editor,
  32558. "drop",
  32559. dropTarget,
  32560. state.dataTransfer,
  32561. e
  32562. );
  32563. if (!args.isDefaultPrevented()) {
  32564. editor.undoManager.transact(() => {
  32565. removeElementWithPadding(editor.dom, state.element);
  32566. getHtmlData(state.dataTransfer).each((content) =>
  32567. editor.insertContent(content)
  32568. );
  32569. editor._selectionOverrides.hideFakeCaret();
  32570. });
  32571. }
  32572. }
  32573. dispatchDragEvent(
  32574. editor,
  32575. "dragend",
  32576. editor.getBody(),
  32577. state.dataTransfer,
  32578. e
  32579. );
  32580. }
  32581. });
  32582. removeDragState(state);
  32583. };
  32584. const stopDragging = (state, editor, e) => {
  32585. state.on((state) => {
  32586. state.intervalId.clear();
  32587. if (state.dragging) {
  32588. e.fold(
  32589. () =>
  32590. dispatchDragEvent(
  32591. editor,
  32592. "dragend",
  32593. state.element,
  32594. state.dataTransfer
  32595. ),
  32596. (mouseEvent) =>
  32597. dispatchDragEvent(
  32598. editor,
  32599. "dragend",
  32600. state.element,
  32601. state.dataTransfer,
  32602. mouseEvent
  32603. )
  32604. );
  32605. }
  32606. });
  32607. removeDragState(state);
  32608. };
  32609. const stop = (state, editor) => (e) =>
  32610. stopDragging(state, editor, Optional.some(e));
  32611. const removeDragState = (state) => {
  32612. state.on((state) => {
  32613. state.intervalId.clear();
  32614. removeElement(state.ghost);
  32615. });
  32616. state.clear();
  32617. };
  32618. const bindFakeDragEvents = (editor) => {
  32619. const state = value$2();
  32620. const pageDom = DOMUtils.DOM;
  32621. const rootDocument = document;
  32622. const dragStartHandler = start(state, editor);
  32623. const dragHandler = move(state, editor);
  32624. const dropHandler = drop(state, editor);
  32625. const dragEndHandler = stop(state, editor);
  32626. editor.on("mousedown", dragStartHandler);
  32627. editor.on("mousemove", dragHandler);
  32628. editor.on("mouseup", dropHandler);
  32629. pageDom.bind(rootDocument, "mousemove", dragHandler);
  32630. pageDom.bind(rootDocument, "mouseup", dragEndHandler);
  32631. editor.on("remove", () => {
  32632. pageDom.unbind(rootDocument, "mousemove", dragHandler);
  32633. pageDom.unbind(rootDocument, "mouseup", dragEndHandler);
  32634. });
  32635. editor.on("keydown", (e) => {
  32636. if (e.keyCode === VK.ESC) {
  32637. stopDragging(state, editor, Optional.none());
  32638. }
  32639. });
  32640. };
  32641. const blockUnsupportedFileDrop = (editor) => {
  32642. const preventFileDrop = (e) => {
  32643. if (!e.isDefaultPrevented()) {
  32644. const dataTransfer = e.dataTransfer;
  32645. if (
  32646. dataTransfer &&
  32647. (contains$2(dataTransfer.types, "Files") ||
  32648. dataTransfer.files.length > 0)
  32649. ) {
  32650. e.preventDefault();
  32651. if (e.type === "drop") {
  32652. displayError(editor, "Dropped file type is not supported");
  32653. }
  32654. }
  32655. }
  32656. };
  32657. const preventFileDropIfUIElement = (e) => {
  32658. if (isUIElement(editor, e.target)) {
  32659. preventFileDrop(e);
  32660. }
  32661. };
  32662. const setup = () => {
  32663. const pageDom = DOMUtils.DOM;
  32664. const dom = editor.dom;
  32665. const doc = document;
  32666. const editorRoot = editor.inline ? editor.getBody() : editor.getDoc();
  32667. const eventNames = ["drop", "dragover"];
  32668. each$e(eventNames, (name) => {
  32669. pageDom.bind(doc, name, preventFileDropIfUIElement);
  32670. dom.bind(editorRoot, name, preventFileDrop);
  32671. });
  32672. editor.on("remove", () => {
  32673. each$e(eventNames, (name) => {
  32674. pageDom.unbind(doc, name, preventFileDropIfUIElement);
  32675. dom.unbind(editorRoot, name, preventFileDrop);
  32676. });
  32677. });
  32678. };
  32679. editor.on("init", () => {
  32680. Delay.setEditorTimeout(editor, setup, 0);
  32681. });
  32682. };
  32683. const init$2 = (editor) => {
  32684. bindFakeDragEvents(editor);
  32685. if (shouldBlockUnsupportedDrop(editor)) {
  32686. blockUnsupportedFileDrop(editor);
  32687. }
  32688. };
  32689. const setup$4 = (editor) => {
  32690. const renderFocusCaret = first$1(() => {
  32691. if (
  32692. !editor.removed &&
  32693. editor.getBody().contains(document.activeElement)
  32694. ) {
  32695. const rng = editor.selection.getRng();
  32696. if (rng.collapsed) {
  32697. const caretRange = renderRangeCaret(editor, rng, false);
  32698. editor.selection.setRng(caretRange);
  32699. }
  32700. }
  32701. }, 0);
  32702. editor.on("focus", () => {
  32703. renderFocusCaret.throttle();
  32704. });
  32705. editor.on("blur", () => {
  32706. renderFocusCaret.cancel();
  32707. });
  32708. };
  32709. const setup$3 = (editor) => {
  32710. editor.on("init", () => {
  32711. editor.on("focusin", (e) => {
  32712. const target = e.target;
  32713. if (isMedia$2(target)) {
  32714. const ceRoot = getContentEditableRoot$1(editor.getBody(), target);
  32715. const node = isContentEditableFalse$b(ceRoot) ? ceRoot : target;
  32716. if (editor.selection.getNode() !== node) {
  32717. selectNode(editor, node).each((rng) =>
  32718. editor.selection.setRng(rng)
  32719. );
  32720. }
  32721. }
  32722. });
  32723. });
  32724. };
  32725. const isContentEditableFalse = isContentEditableFalse$b;
  32726. const getContentEditableRoot = (editor, node) =>
  32727. getContentEditableRoot$1(editor.getBody(), node);
  32728. const SelectionOverrides = (editor) => {
  32729. const selection = editor.selection,
  32730. dom = editor.dom;
  32731. const rootNode = editor.getBody();
  32732. const fakeCaret = FakeCaret(editor, rootNode, dom.isBlock, () =>
  32733. hasFocus(editor)
  32734. );
  32735. const realSelectionId = "sel-" + dom.uniqueId();
  32736. const elementSelectionAttr = "data-mce-selected";
  32737. let selectedElement;
  32738. const isFakeSelectionElement = (node) =>
  32739. isNonNullable(node) && dom.hasClass(node, "mce-offscreen-selection");
  32740. const isFakeSelectionTargetElement = (node) =>
  32741. node !== rootNode &&
  32742. (isContentEditableFalse(node) || isMedia$2(node)) &&
  32743. dom.isChildOf(node, rootNode) &&
  32744. dom.isEditable(node.parentNode);
  32745. const setRange = (range) => {
  32746. if (range) {
  32747. selection.setRng(range);
  32748. }
  32749. };
  32750. const showCaret = (direction, node, before, scrollIntoView = true) => {
  32751. const e = editor.dispatch("ShowCaret", {
  32752. target: node,
  32753. direction,
  32754. before,
  32755. });
  32756. if (e.isDefaultPrevented()) {
  32757. return null;
  32758. }
  32759. if (scrollIntoView) {
  32760. selection.scrollIntoView(node, direction === -1);
  32761. }
  32762. return fakeCaret.show(before, node);
  32763. };
  32764. const showBlockCaretContainer = (blockCaretContainer) => {
  32765. if (blockCaretContainer.hasAttribute("data-mce-caret")) {
  32766. showCaretContainerBlock(blockCaretContainer);
  32767. selection.scrollIntoView(blockCaretContainer);
  32768. }
  32769. };
  32770. const registerEvents = () => {
  32771. editor.on("click", (e) => {
  32772. if (!dom.isEditable(e.target)) {
  32773. e.preventDefault();
  32774. editor.focus();
  32775. }
  32776. });
  32777. editor.on("blur NewBlock", removeElementSelection);
  32778. editor.on("ResizeWindow FullscreenStateChanged", fakeCaret.reposition);
  32779. editor.on(
  32780. "tap",
  32781. (e) => {
  32782. const targetElm = e.target;
  32783. const contentEditableRoot = getContentEditableRoot(editor, targetElm);
  32784. if (isContentEditableFalse(contentEditableRoot)) {
  32785. e.preventDefault();
  32786. selectNode(editor, contentEditableRoot).each(setElementSelection);
  32787. } else if (isFakeSelectionTargetElement(targetElm)) {
  32788. selectNode(editor, targetElm).each(setElementSelection);
  32789. }
  32790. },
  32791. true
  32792. );
  32793. editor.on("mousedown", (e) => {
  32794. const targetElm = e.target;
  32795. if (
  32796. targetElm !== rootNode &&
  32797. targetElm.nodeName !== "HTML" &&
  32798. !dom.isChildOf(targetElm, rootNode)
  32799. ) {
  32800. return;
  32801. }
  32802. if (!isXYInContentArea(editor, e.clientX, e.clientY)) {
  32803. return;
  32804. }
  32805. removeElementSelection();
  32806. hideFakeCaret();
  32807. const closestContentEditable = getContentEditableRoot(
  32808. editor,
  32809. targetElm
  32810. );
  32811. if (isContentEditableFalse(closestContentEditable)) {
  32812. e.preventDefault();
  32813. selectNode(editor, closestContentEditable).each(setElementSelection);
  32814. } else {
  32815. closestFakeCaretCandidate(rootNode, e.clientX, e.clientY).each(
  32816. (caretInfo) => {
  32817. e.preventDefault();
  32818. const range = showCaret(
  32819. 1,
  32820. caretInfo.node,
  32821. caretInfo.position === FakeCaretPosition.Before,
  32822. false
  32823. );
  32824. setRange(range);
  32825. if (isElement$6(closestContentEditable)) {
  32826. closestContentEditable.focus();
  32827. } else {
  32828. editor.getBody().focus();
  32829. }
  32830. }
  32831. );
  32832. }
  32833. });
  32834. editor.on("keypress", (e) => {
  32835. if (VK.modifierPressed(e)) {
  32836. return;
  32837. }
  32838. if (isContentEditableFalse(selection.getNode())) {
  32839. e.preventDefault();
  32840. }
  32841. });
  32842. editor.on("GetSelectionRange", (e) => {
  32843. let rng = e.range;
  32844. if (selectedElement) {
  32845. if (!selectedElement.parentNode) {
  32846. selectedElement = null;
  32847. return;
  32848. }
  32849. rng = rng.cloneRange();
  32850. rng.selectNode(selectedElement);
  32851. e.range = rng;
  32852. }
  32853. });
  32854. editor.on("SetSelectionRange", (e) => {
  32855. e.range = normalizeVoidElementSelection(e.range);
  32856. const rng = setElementSelection(e.range, e.forward);
  32857. if (rng) {
  32858. e.range = rng;
  32859. }
  32860. });
  32861. const isPasteBin = (node) =>
  32862. isElement$6(node) && node.id === "mcepastebin";
  32863. editor.on("AfterSetSelectionRange", (e) => {
  32864. const rng = e.range;
  32865. const parent = rng.startContainer.parentElement;
  32866. if (!isRangeInCaretContainer(rng) && !isPasteBin(parent)) {
  32867. hideFakeCaret();
  32868. }
  32869. if (!isFakeSelectionElement(parent)) {
  32870. removeElementSelection();
  32871. }
  32872. });
  32873. init$2(editor);
  32874. setup$4(editor);
  32875. setup$3(editor);
  32876. };
  32877. const isWithinCaretContainer = (node) =>
  32878. isCaretContainer$2(node) ||
  32879. startsWithCaretContainer$1(node) ||
  32880. endsWithCaretContainer$1(node);
  32881. const isRangeInCaretContainer = (rng) =>
  32882. isWithinCaretContainer(rng.startContainer) ||
  32883. isWithinCaretContainer(rng.endContainer);
  32884. const normalizeVoidElementSelection = (rng) => {
  32885. const voidElements = editor.schema.getVoidElements();
  32886. const newRng = dom.createRng();
  32887. const startContainer = rng.startContainer;
  32888. const startOffset = rng.startOffset;
  32889. const endContainer = rng.endContainer;
  32890. const endOffset = rng.endOffset;
  32891. if (has$2(voidElements, startContainer.nodeName.toLowerCase())) {
  32892. if (startOffset === 0) {
  32893. newRng.setStartBefore(startContainer);
  32894. } else {
  32895. newRng.setStartAfter(startContainer);
  32896. }
  32897. } else {
  32898. newRng.setStart(startContainer, startOffset);
  32899. }
  32900. if (has$2(voidElements, endContainer.nodeName.toLowerCase())) {
  32901. if (endOffset === 0) {
  32902. newRng.setEndBefore(endContainer);
  32903. } else {
  32904. newRng.setEndAfter(endContainer);
  32905. }
  32906. } else {
  32907. newRng.setEnd(endContainer, endOffset);
  32908. }
  32909. return newRng;
  32910. };
  32911. const setupOffscreenSelection = (node, targetClone) => {
  32912. const body = SugarElement.fromDom(editor.getBody());
  32913. const doc = editor.getDoc();
  32914. const realSelectionContainer = descendant(
  32915. body,
  32916. "#" + realSelectionId
  32917. ).getOrThunk(() => {
  32918. const newContainer = SugarElement.fromHtml(
  32919. '<div data-mce-bogus="all" class="mce-offscreen-selection"></div>',
  32920. doc
  32921. );
  32922. set$3(newContainer, "id", realSelectionId);
  32923. append$1(body, newContainer);
  32924. return newContainer;
  32925. });
  32926. const newRange = dom.createRng();
  32927. empty(realSelectionContainer);
  32928. append(realSelectionContainer, [
  32929. SugarElement.fromText(nbsp, doc),
  32930. SugarElement.fromDom(targetClone),
  32931. SugarElement.fromText(nbsp, doc),
  32932. ]);
  32933. newRange.setStart(realSelectionContainer.dom.firstChild, 1);
  32934. newRange.setEnd(realSelectionContainer.dom.lastChild, 0);
  32935. setAll(realSelectionContainer, {
  32936. top: dom.getPos(node, editor.getBody()).y + "px",
  32937. });
  32938. focus$1(realSelectionContainer);
  32939. const sel = selection.getSel();
  32940. if (sel) {
  32941. sel.removeAllRanges();
  32942. sel.addRange(newRange);
  32943. }
  32944. return newRange;
  32945. };
  32946. const selectElement = (elm) => {
  32947. const targetClone = elm.cloneNode(true);
  32948. const e = editor.dispatch("ObjectSelected", {
  32949. target: elm,
  32950. targetClone,
  32951. });
  32952. if (e.isDefaultPrevented()) {
  32953. return null;
  32954. }
  32955. const range = setupOffscreenSelection(elm, e.targetClone);
  32956. const nodeElm = SugarElement.fromDom(elm);
  32957. each$e(
  32958. descendants(
  32959. SugarElement.fromDom(editor.getBody()),
  32960. `*[${elementSelectionAttr}]`
  32961. ),
  32962. (elm) => {
  32963. if (!eq(nodeElm, elm)) {
  32964. remove$a(elm, elementSelectionAttr);
  32965. }
  32966. }
  32967. );
  32968. if (!dom.getAttrib(elm, elementSelectionAttr)) {
  32969. elm.setAttribute(elementSelectionAttr, "1");
  32970. }
  32971. selectedElement = elm;
  32972. hideFakeCaret();
  32973. return range;
  32974. };
  32975. const setElementSelection = (range, forward) => {
  32976. if (!range) {
  32977. return null;
  32978. }
  32979. if (range.collapsed) {
  32980. if (!isRangeInCaretContainer(range)) {
  32981. const dir = forward ? 1 : -1;
  32982. const caretPosition = getNormalizedRangeEndPoint(
  32983. dir,
  32984. rootNode,
  32985. range
  32986. );
  32987. const beforeNode = caretPosition.getNode(!forward);
  32988. if (isNonNullable(beforeNode)) {
  32989. if (isFakeCaretTarget(beforeNode)) {
  32990. return showCaret(
  32991. dir,
  32992. beforeNode,
  32993. forward ? !caretPosition.isAtEnd() : false,
  32994. false
  32995. );
  32996. }
  32997. if (
  32998. isCaretContainerInline(beforeNode) &&
  32999. isContentEditableFalse$b(beforeNode.nextSibling)
  33000. ) {
  33001. const rng = dom.createRng();
  33002. rng.setStart(beforeNode, 0);
  33003. rng.setEnd(beforeNode, 0);
  33004. return rng;
  33005. }
  33006. }
  33007. const afterNode = caretPosition.getNode(forward);
  33008. if (isNonNullable(afterNode)) {
  33009. if (isFakeCaretTarget(afterNode)) {
  33010. return showCaret(
  33011. dir,
  33012. afterNode,
  33013. forward ? false : !caretPosition.isAtEnd(),
  33014. false
  33015. );
  33016. }
  33017. if (
  33018. isCaretContainerInline(afterNode) &&
  33019. isContentEditableFalse$b(afterNode.previousSibling)
  33020. ) {
  33021. const rng = dom.createRng();
  33022. rng.setStart(afterNode, 1);
  33023. rng.setEnd(afterNode, 1);
  33024. return rng;
  33025. }
  33026. }
  33027. }
  33028. return null;
  33029. }
  33030. let startContainer = range.startContainer;
  33031. let startOffset = range.startOffset;
  33032. const endOffset = range.endOffset;
  33033. if (
  33034. isText$a(startContainer) &&
  33035. startOffset === 0 &&
  33036. isContentEditableFalse(startContainer.parentNode)
  33037. ) {
  33038. startContainer = startContainer.parentNode;
  33039. startOffset = dom.nodeIndex(startContainer);
  33040. startContainer = startContainer.parentNode;
  33041. }
  33042. if (!isElement$6(startContainer)) {
  33043. return null;
  33044. }
  33045. if (
  33046. endOffset === startOffset + 1 &&
  33047. startContainer === range.endContainer
  33048. ) {
  33049. const node = startContainer.childNodes[startOffset];
  33050. if (isFakeSelectionTargetElement(node)) {
  33051. return selectElement(node);
  33052. }
  33053. }
  33054. return null;
  33055. };
  33056. const removeElementSelection = () => {
  33057. if (selectedElement) {
  33058. selectedElement.removeAttribute(elementSelectionAttr);
  33059. }
  33060. descendant(
  33061. SugarElement.fromDom(editor.getBody()),
  33062. "#" + realSelectionId
  33063. ).each(remove$5);
  33064. selectedElement = null;
  33065. };
  33066. const destroy = () => {
  33067. fakeCaret.destroy();
  33068. selectedElement = null;
  33069. };
  33070. const hideFakeCaret = () => {
  33071. fakeCaret.hide();
  33072. };
  33073. if (!isRtc(editor)) {
  33074. registerEvents();
  33075. }
  33076. return {
  33077. showCaret,
  33078. showBlockCaretContainer,
  33079. hideFakeCaret,
  33080. destroy,
  33081. };
  33082. };
  33083. const getNormalizedTextOffset = (container, offset) => {
  33084. let normalizedOffset = offset;
  33085. for (
  33086. let node = container.previousSibling;
  33087. isText$a(node);
  33088. node = node.previousSibling
  33089. ) {
  33090. normalizedOffset += node.data.length;
  33091. }
  33092. return normalizedOffset;
  33093. };
  33094. const generatePath = (dom, root, node, offset, normalized) => {
  33095. if (isText$a(node) && (offset < 0 || offset > node.data.length)) {
  33096. return [];
  33097. }
  33098. const p =
  33099. normalized && isText$a(node)
  33100. ? [getNormalizedTextOffset(node, offset)]
  33101. : [offset];
  33102. let current = node;
  33103. while (current !== root && current.parentNode) {
  33104. p.push(dom.nodeIndex(current, normalized));
  33105. current = current.parentNode;
  33106. }
  33107. return current === root ? p.reverse() : [];
  33108. };
  33109. const generatePathRange = (
  33110. dom,
  33111. root,
  33112. startNode,
  33113. startOffset,
  33114. endNode,
  33115. endOffset,
  33116. normalized = false
  33117. ) => {
  33118. const start = generatePath(dom, root, startNode, startOffset, normalized);
  33119. const end = generatePath(dom, root, endNode, endOffset, normalized);
  33120. return {
  33121. start,
  33122. end,
  33123. };
  33124. };
  33125. const resolvePath = (root, path) => {
  33126. const nodePath = path.slice();
  33127. const offset = nodePath.pop();
  33128. if (!isNumber(offset)) {
  33129. return Optional.none();
  33130. } else {
  33131. const resolvedNode = foldl(
  33132. nodePath,
  33133. (optNode, index) =>
  33134. optNode.bind((node) => Optional.from(node.childNodes[index])),
  33135. Optional.some(root)
  33136. );
  33137. return resolvedNode.bind((node) => {
  33138. if (isText$a(node) && (offset < 0 || offset > node.data.length)) {
  33139. return Optional.none();
  33140. } else {
  33141. return Optional.some({
  33142. node,
  33143. offset,
  33144. });
  33145. }
  33146. });
  33147. }
  33148. };
  33149. const resolvePathRange = (root, range) =>
  33150. resolvePath(root, range.start).bind(
  33151. ({ node: startNode, offset: startOffset }) =>
  33152. resolvePath(root, range.end).map(
  33153. ({ node: endNode, offset: endOffset }) => {
  33154. const rng = document.createRange();
  33155. rng.setStart(startNode, startOffset);
  33156. rng.setEnd(endNode, endOffset);
  33157. return rng;
  33158. }
  33159. )
  33160. );
  33161. const generatePathRangeFromRange = (dom, root, range, normalized = false) =>
  33162. generatePathRange(
  33163. dom,
  33164. root,
  33165. range.startContainer,
  33166. range.startOffset,
  33167. range.endContainer,
  33168. range.endOffset,
  33169. normalized
  33170. );
  33171. const cleanEmptyNodes = (dom, node, isRoot) => {
  33172. if (node && dom.isEmpty(node) && !isRoot(node)) {
  33173. const parent = node.parentNode;
  33174. dom.remove(
  33175. node,
  33176. isText$a(node.firstChild) && isWhitespaceText(node.firstChild.data)
  33177. );
  33178. cleanEmptyNodes(dom, parent, isRoot);
  33179. }
  33180. };
  33181. const deleteRng = (dom, rng, isRoot, clean = true) => {
  33182. const startParent = rng.startContainer.parentNode;
  33183. const endParent = rng.endContainer.parentNode;
  33184. rng.deleteContents();
  33185. if (clean && !isRoot(rng.startContainer)) {
  33186. if (
  33187. isText$a(rng.startContainer) &&
  33188. rng.startContainer.data.length === 0
  33189. ) {
  33190. dom.remove(rng.startContainer);
  33191. }
  33192. if (isText$a(rng.endContainer) && rng.endContainer.data.length === 0) {
  33193. dom.remove(rng.endContainer);
  33194. }
  33195. cleanEmptyNodes(dom, startParent, isRoot);
  33196. if (startParent !== endParent) {
  33197. cleanEmptyNodes(dom, endParent, isRoot);
  33198. }
  33199. }
  33200. };
  33201. const getParentBlock = (editor, rng) =>
  33202. Optional.from(editor.dom.getParent(rng.startContainer, editor.dom.isBlock));
  33203. const resolveFromDynamicPatterns = (patternSet, block, beforeText) => {
  33204. const dynamicPatterns = patternSet.dynamicPatternsLookup({
  33205. text: beforeText,
  33206. block,
  33207. });
  33208. return {
  33209. ...patternSet,
  33210. blockPatterns: getBlockPatterns(dynamicPatterns).concat(
  33211. patternSet.blockPatterns
  33212. ),
  33213. inlinePatterns: getInlinePatterns(dynamicPatterns).concat(
  33214. patternSet.inlinePatterns
  33215. ),
  33216. };
  33217. };
  33218. const getBeforeText = (dom, block, node, offset) => {
  33219. const rng = dom.createRng();
  33220. rng.setStart(block, 0);
  33221. rng.setEnd(node, offset);
  33222. return rng.toString();
  33223. };
  33224. const startsWithSingleSpace = (s) => /^\s[^\s]/.test(s);
  33225. const stripPattern = (dom, block, pattern) => {
  33226. const firstTextNode = textAfter(block, 0, block);
  33227. firstTextNode.each((spot) => {
  33228. const node = spot.container;
  33229. scanRight(node, pattern.start.length, block).each((end) => {
  33230. const rng = dom.createRng();
  33231. rng.setStart(node, 0);
  33232. rng.setEnd(end.container, end.offset);
  33233. deleteRng(dom, rng, (e) => e === block);
  33234. });
  33235. const text = SugarElement.fromDom(node);
  33236. const textContent = get$3(text);
  33237. if (startsWithSingleSpace(textContent)) {
  33238. set(text, textContent.slice(1));
  33239. }
  33240. });
  33241. };
  33242. const applyPattern$1 = (editor, match) => {
  33243. const dom = editor.dom;
  33244. const pattern = match.pattern;
  33245. const rng = resolvePathRange(dom.getRoot(), match.range).getOrDie(
  33246. "Unable to resolve path range"
  33247. );
  33248. const isBlockFormatName = (name, formatter) => {
  33249. const formatSet = formatter.get(name);
  33250. return (
  33251. isArray$1(formatSet) &&
  33252. head(formatSet).exists((format) => has$2(format, "block"))
  33253. );
  33254. };
  33255. getParentBlock(editor, rng).each((block) => {
  33256. if (pattern.type === "block-format") {
  33257. if (isBlockFormatName(pattern.format, editor.formatter)) {
  33258. editor.undoManager.transact(() => {
  33259. stripPattern(editor.dom, block, pattern);
  33260. editor.formatter.apply(pattern.format);
  33261. });
  33262. }
  33263. } else if (pattern.type === "block-command") {
  33264. editor.undoManager.transact(() => {
  33265. stripPattern(editor.dom, block, pattern);
  33266. editor.execCommand(pattern.cmd, false, pattern.value);
  33267. });
  33268. }
  33269. });
  33270. return true;
  33271. };
  33272. const sortPatterns$1 = (patterns) =>
  33273. sort(patterns, (a, b) => b.start.length - a.start.length);
  33274. const findPattern$1 = (patterns, text) => {
  33275. const sortedPatterns = sortPatterns$1(patterns);
  33276. const nuText = text.replace(nbsp, " ");
  33277. return find$2(
  33278. sortedPatterns,
  33279. (pattern) =>
  33280. text.indexOf(pattern.start) === 0 || nuText.indexOf(pattern.start) === 0
  33281. );
  33282. };
  33283. const findPatterns$1 = (editor, block, patternSet, normalizedMatches) => {
  33284. var _a;
  33285. const dom = editor.dom;
  33286. const forcedRootBlock = getForcedRootBlock(editor);
  33287. if (!dom.is(block, forcedRootBlock)) {
  33288. return [];
  33289. }
  33290. const blockText =
  33291. (_a = block.textContent) !== null && _a !== void 0 ? _a : "";
  33292. return findPattern$1(patternSet.blockPatterns, blockText)
  33293. .map((pattern) => {
  33294. if (Tools.trim(blockText).length === pattern.start.length) {
  33295. return [];
  33296. }
  33297. return [
  33298. {
  33299. pattern,
  33300. range: generatePathRange(
  33301. dom,
  33302. dom.getRoot(),
  33303. block,
  33304. 0,
  33305. block,
  33306. 0,
  33307. normalizedMatches
  33308. ),
  33309. },
  33310. ];
  33311. })
  33312. .getOr([]);
  33313. };
  33314. const applyMatches$1 = (editor, matches) => {
  33315. if (matches.length === 0) {
  33316. return;
  33317. }
  33318. const bookmark = editor.selection.getBookmark();
  33319. each$e(matches, (match) => applyPattern$1(editor, match));
  33320. editor.selection.moveToBookmark(bookmark);
  33321. };
  33322. const newMarker = (dom, id) =>
  33323. dom.create("span", {
  33324. "data-mce-type": "bookmark",
  33325. id,
  33326. });
  33327. const rangeFromMarker = (dom, marker) => {
  33328. const rng = dom.createRng();
  33329. rng.setStartAfter(marker.start);
  33330. rng.setEndBefore(marker.end);
  33331. return rng;
  33332. };
  33333. const createMarker = (dom, markerPrefix, pathRange) => {
  33334. const rng = resolvePathRange(dom.getRoot(), pathRange).getOrDie(
  33335. "Unable to resolve path range"
  33336. );
  33337. const startNode = rng.startContainer;
  33338. const endNode = rng.endContainer;
  33339. const textEnd =
  33340. rng.endOffset === 0 ? endNode : endNode.splitText(rng.endOffset);
  33341. const textStart =
  33342. rng.startOffset === 0 ? startNode : startNode.splitText(rng.startOffset);
  33343. const startParentNode = textStart.parentNode;
  33344. const endParentNode = textEnd.parentNode;
  33345. return {
  33346. prefix: markerPrefix,
  33347. end: endParentNode.insertBefore(
  33348. newMarker(dom, markerPrefix + "-end"),
  33349. textEnd
  33350. ),
  33351. start: startParentNode.insertBefore(
  33352. newMarker(dom, markerPrefix + "-start"),
  33353. textStart
  33354. ),
  33355. };
  33356. };
  33357. const removeMarker = (dom, marker, isRoot) => {
  33358. cleanEmptyNodes(dom, dom.get(marker.prefix + "-end"), isRoot);
  33359. cleanEmptyNodes(dom, dom.get(marker.prefix + "-start"), isRoot);
  33360. };
  33361. const isReplacementPattern = (pattern) => pattern.start.length === 0;
  33362. const matchesPattern = (patternContent) => (element, offset) => {
  33363. const text = element.data;
  33364. const searchText = text.substring(0, offset);
  33365. const startEndIndex = searchText.lastIndexOf(
  33366. patternContent.charAt(patternContent.length - 1)
  33367. );
  33368. const startIndex = searchText.lastIndexOf(patternContent);
  33369. if (startIndex !== -1) {
  33370. return startIndex + patternContent.length;
  33371. } else if (startEndIndex !== -1) {
  33372. return startEndIndex + 1;
  33373. } else {
  33374. return -1;
  33375. }
  33376. };
  33377. const findPatternStartFromSpot = (dom, pattern, block, spot) => {
  33378. const startPattern = pattern.start;
  33379. const startSpot = repeatLeft(
  33380. dom,
  33381. spot.container,
  33382. spot.offset,
  33383. matchesPattern(startPattern),
  33384. block
  33385. );
  33386. return startSpot.bind((spot) => {
  33387. var _a, _b;
  33388. const startPatternIndex =
  33389. (_b =
  33390. (_a = block.textContent) === null || _a === void 0
  33391. ? void 0
  33392. : _a.indexOf(startPattern)) !== null && _b !== void 0
  33393. ? _b
  33394. : -1;
  33395. const isCompleteMatch =
  33396. startPatternIndex !== -1 &&
  33397. spot.offset >= startPatternIndex + startPattern.length;
  33398. if (isCompleteMatch) {
  33399. const rng = dom.createRng();
  33400. rng.setStart(spot.container, spot.offset - startPattern.length);
  33401. rng.setEnd(spot.container, spot.offset);
  33402. return Optional.some(rng);
  33403. } else {
  33404. const offset = spot.offset - startPattern.length;
  33405. return scanLeft(spot.container, offset, block)
  33406. .map((nextSpot) => {
  33407. const rng = dom.createRng();
  33408. rng.setStart(nextSpot.container, nextSpot.offset);
  33409. rng.setEnd(spot.container, spot.offset);
  33410. return rng;
  33411. })
  33412. .filter((rng) => rng.toString() === startPattern)
  33413. .orThunk(() =>
  33414. findPatternStartFromSpot(
  33415. dom,
  33416. pattern,
  33417. block,
  33418. point(spot.container, 0)
  33419. )
  33420. );
  33421. }
  33422. });
  33423. };
  33424. const findPatternStart = (
  33425. dom,
  33426. pattern,
  33427. node,
  33428. offset,
  33429. block,
  33430. requireGap = false
  33431. ) => {
  33432. if (pattern.start.length === 0 && !requireGap) {
  33433. const rng = dom.createRng();
  33434. rng.setStart(node, offset);
  33435. rng.setEnd(node, offset);
  33436. return Optional.some(rng);
  33437. }
  33438. return textBefore(node, offset, block).bind((spot) => {
  33439. const start = findPatternStartFromSpot(dom, pattern, block, spot);
  33440. return start.bind((startRange) => {
  33441. var _a;
  33442. if (requireGap) {
  33443. if (
  33444. startRange.endContainer === spot.container &&
  33445. startRange.endOffset === spot.offset
  33446. ) {
  33447. return Optional.none();
  33448. } else if (
  33449. spot.offset === 0 &&
  33450. ((_a = startRange.endContainer.textContent) === null ||
  33451. _a === void 0
  33452. ? void 0
  33453. : _a.length) === startRange.endOffset
  33454. ) {
  33455. return Optional.none();
  33456. }
  33457. }
  33458. return Optional.some(startRange);
  33459. });
  33460. });
  33461. };
  33462. const findPattern = (editor, block, details, normalizedMatches) => {
  33463. const dom = editor.dom;
  33464. const root = dom.getRoot();
  33465. const pattern = details.pattern;
  33466. const endNode = details.position.container;
  33467. const endOffset = details.position.offset;
  33468. return scanLeft(
  33469. endNode,
  33470. endOffset - details.pattern.end.length,
  33471. block
  33472. ).bind((spot) => {
  33473. const endPathRng = generatePathRange(
  33474. dom,
  33475. root,
  33476. spot.container,
  33477. spot.offset,
  33478. endNode,
  33479. endOffset,
  33480. normalizedMatches
  33481. );
  33482. if (isReplacementPattern(pattern)) {
  33483. return Optional.some({
  33484. matches: [
  33485. {
  33486. pattern,
  33487. startRng: endPathRng,
  33488. endRng: endPathRng,
  33489. },
  33490. ],
  33491. position: spot,
  33492. });
  33493. } else {
  33494. const resultsOpt = findPatternsRec(
  33495. editor,
  33496. details.remainingPatterns,
  33497. spot.container,
  33498. spot.offset,
  33499. block,
  33500. normalizedMatches
  33501. );
  33502. const results = resultsOpt.getOr({
  33503. matches: [],
  33504. position: spot,
  33505. });
  33506. const pos = results.position;
  33507. const start = findPatternStart(
  33508. dom,
  33509. pattern,
  33510. pos.container,
  33511. pos.offset,
  33512. block,
  33513. resultsOpt.isNone()
  33514. );
  33515. return start.map((startRng) => {
  33516. const startPathRng = generatePathRangeFromRange(
  33517. dom,
  33518. root,
  33519. startRng,
  33520. normalizedMatches
  33521. );
  33522. return {
  33523. matches: results.matches.concat([
  33524. {
  33525. pattern,
  33526. startRng: startPathRng,
  33527. endRng: endPathRng,
  33528. },
  33529. ]),
  33530. position: point(startRng.startContainer, startRng.startOffset),
  33531. };
  33532. });
  33533. }
  33534. });
  33535. };
  33536. const findPatternsRec = (
  33537. editor,
  33538. patterns,
  33539. node,
  33540. offset,
  33541. block,
  33542. normalizedMatches
  33543. ) => {
  33544. const dom = editor.dom;
  33545. return textBefore(node, offset, dom.getRoot()).bind((endSpot) => {
  33546. const text = getBeforeText(dom, block, node, offset);
  33547. for (let i = 0; i < patterns.length; i++) {
  33548. const pattern = patterns[i];
  33549. if (!endsWith(text, pattern.end)) {
  33550. continue;
  33551. }
  33552. const patternsWithoutCurrent = patterns.slice();
  33553. patternsWithoutCurrent.splice(i, 1);
  33554. const result = findPattern(
  33555. editor,
  33556. block,
  33557. {
  33558. pattern,
  33559. remainingPatterns: patternsWithoutCurrent,
  33560. position: endSpot,
  33561. },
  33562. normalizedMatches
  33563. );
  33564. if (result.isNone() && offset > 0) {
  33565. return findPatternsRec(
  33566. editor,
  33567. patterns,
  33568. node,
  33569. offset - 1,
  33570. block,
  33571. normalizedMatches
  33572. );
  33573. }
  33574. if (result.isSome()) {
  33575. return result;
  33576. }
  33577. }
  33578. return Optional.none();
  33579. });
  33580. };
  33581. const applyPattern = (editor, pattern, patternRange) => {
  33582. editor.selection.setRng(patternRange);
  33583. if (pattern.type === "inline-format") {
  33584. each$e(pattern.format, (format) => {
  33585. editor.formatter.apply(format);
  33586. });
  33587. } else {
  33588. editor.execCommand(pattern.cmd, false, pattern.value);
  33589. }
  33590. };
  33591. const applyReplacementPattern = (editor, pattern, marker, isRoot) => {
  33592. const markerRange = rangeFromMarker(editor.dom, marker);
  33593. deleteRng(editor.dom, markerRange, isRoot);
  33594. applyPattern(editor, pattern, markerRange);
  33595. };
  33596. const applyPatternWithContent = (
  33597. editor,
  33598. pattern,
  33599. startMarker,
  33600. endMarker,
  33601. isRoot
  33602. ) => {
  33603. const dom = editor.dom;
  33604. const markerEndRange = rangeFromMarker(dom, endMarker);
  33605. const markerStartRange = rangeFromMarker(dom, startMarker);
  33606. deleteRng(dom, markerStartRange, isRoot);
  33607. deleteRng(dom, markerEndRange, isRoot);
  33608. const patternMarker = {
  33609. prefix: startMarker.prefix,
  33610. start: startMarker.end,
  33611. end: endMarker.start,
  33612. };
  33613. const patternRange = rangeFromMarker(dom, patternMarker);
  33614. applyPattern(editor, pattern, patternRange);
  33615. };
  33616. const addMarkers = (dom, matches) => {
  33617. const markerPrefix = generate$1("mce_textpattern");
  33618. const matchesWithEnds = foldr(
  33619. matches,
  33620. (acc, match) => {
  33621. const endMarker = createMarker(
  33622. dom,
  33623. markerPrefix + `_end${acc.length}`,
  33624. match.endRng
  33625. );
  33626. return acc.concat([
  33627. {
  33628. ...match,
  33629. endMarker,
  33630. },
  33631. ]);
  33632. },
  33633. []
  33634. );
  33635. return foldr(
  33636. matchesWithEnds,
  33637. (acc, match) => {
  33638. const idx = matchesWithEnds.length - acc.length - 1;
  33639. const startMarker = isReplacementPattern(match.pattern)
  33640. ? match.endMarker
  33641. : createMarker(dom, markerPrefix + `_start${idx}`, match.startRng);
  33642. return acc.concat([
  33643. {
  33644. ...match,
  33645. startMarker,
  33646. },
  33647. ]);
  33648. },
  33649. []
  33650. );
  33651. };
  33652. const sortPatterns = (patterns) =>
  33653. sort(patterns, (a, b) => b.end.length - a.end.length);
  33654. const getBestMatches = (matches, matchesWithSortedPatterns) => {
  33655. const hasSameMatches = forall(matches, (match) =>
  33656. exists(
  33657. matchesWithSortedPatterns,
  33658. (sortedMatch) =>
  33659. match.pattern.start === sortedMatch.pattern.start &&
  33660. match.pattern.end === sortedMatch.pattern.end
  33661. )
  33662. );
  33663. if (matches.length === matchesWithSortedPatterns.length) {
  33664. if (hasSameMatches) {
  33665. return matches;
  33666. } else {
  33667. return matchesWithSortedPatterns;
  33668. }
  33669. }
  33670. return matches.length > matchesWithSortedPatterns.length
  33671. ? matches
  33672. : matchesWithSortedPatterns;
  33673. };
  33674. const findPatterns = (
  33675. editor,
  33676. block,
  33677. node,
  33678. offset,
  33679. patternSet,
  33680. normalizedMatches
  33681. ) => {
  33682. const matches = findPatternsRec(
  33683. editor,
  33684. patternSet.inlinePatterns,
  33685. node,
  33686. offset,
  33687. block,
  33688. normalizedMatches
  33689. ).fold(
  33690. () => [],
  33691. (result) => result.matches
  33692. );
  33693. const matchesWithSortedPatterns = findPatternsRec(
  33694. editor,
  33695. sortPatterns(patternSet.inlinePatterns),
  33696. node,
  33697. offset,
  33698. block,
  33699. normalizedMatches
  33700. ).fold(
  33701. () => [],
  33702. (result) => result.matches
  33703. );
  33704. return getBestMatches(matches, matchesWithSortedPatterns);
  33705. };
  33706. const applyMatches = (editor, matches) => {
  33707. if (matches.length === 0) {
  33708. return;
  33709. }
  33710. const dom = editor.dom;
  33711. const bookmark = editor.selection.getBookmark();
  33712. const matchesWithMarkers = addMarkers(dom, matches);
  33713. each$e(matchesWithMarkers, (match) => {
  33714. const block = dom.getParent(match.startMarker.start, dom.isBlock);
  33715. const isRoot = (node) => node === block;
  33716. if (isReplacementPattern(match.pattern)) {
  33717. applyReplacementPattern(editor, match.pattern, match.endMarker, isRoot);
  33718. } else {
  33719. applyPatternWithContent(
  33720. editor,
  33721. match.pattern,
  33722. match.startMarker,
  33723. match.endMarker,
  33724. isRoot
  33725. );
  33726. }
  33727. removeMarker(dom, match.endMarker, isRoot);
  33728. removeMarker(dom, match.startMarker, isRoot);
  33729. });
  33730. editor.selection.moveToBookmark(bookmark);
  33731. };
  33732. const handleEnter = (editor, patternSet) => {
  33733. const rng = editor.selection.getRng();
  33734. return getParentBlock(editor, rng)
  33735. .map((block) => {
  33736. var _a;
  33737. const offset = Math.max(0, rng.startOffset);
  33738. const dynamicPatternSet = resolveFromDynamicPatterns(
  33739. patternSet,
  33740. block,
  33741. (_a = block.textContent) !== null && _a !== void 0 ? _a : ""
  33742. );
  33743. const inlineMatches = findPatterns(
  33744. editor,
  33745. block,
  33746. rng.startContainer,
  33747. offset,
  33748. dynamicPatternSet,
  33749. true
  33750. );
  33751. const blockMatches = findPatterns$1(
  33752. editor,
  33753. block,
  33754. dynamicPatternSet,
  33755. true
  33756. );
  33757. if (blockMatches.length > 0 || inlineMatches.length > 0) {
  33758. editor.undoManager.add();
  33759. editor.undoManager.extra(
  33760. () => {
  33761. editor.execCommand("mceInsertNewLine");
  33762. },
  33763. () => {
  33764. editor.insertContent(zeroWidth);
  33765. applyMatches(editor, inlineMatches);
  33766. applyMatches$1(editor, blockMatches);
  33767. const range = editor.selection.getRng();
  33768. const spot = textBefore(
  33769. range.startContainer,
  33770. range.startOffset,
  33771. editor.dom.getRoot()
  33772. );
  33773. editor.execCommand("mceInsertNewLine");
  33774. spot.each((s) => {
  33775. const node = s.container;
  33776. if (node.data.charAt(s.offset - 1) === zeroWidth) {
  33777. node.deleteData(s.offset - 1, 1);
  33778. cleanEmptyNodes(
  33779. editor.dom,
  33780. node.parentNode,
  33781. (e) => e === editor.dom.getRoot()
  33782. );
  33783. }
  33784. });
  33785. }
  33786. );
  33787. return true;
  33788. }
  33789. return false;
  33790. })
  33791. .getOr(false);
  33792. };
  33793. const handleInlineKey = (editor, patternSet) => {
  33794. const rng = editor.selection.getRng();
  33795. getParentBlock(editor, rng).map((block) => {
  33796. const offset = Math.max(0, rng.startOffset - 1);
  33797. const beforeText = getBeforeText(
  33798. editor.dom,
  33799. block,
  33800. rng.startContainer,
  33801. offset
  33802. );
  33803. const dynamicPatternSet = resolveFromDynamicPatterns(
  33804. patternSet,
  33805. block,
  33806. beforeText
  33807. );
  33808. const inlineMatches = findPatterns(
  33809. editor,
  33810. block,
  33811. rng.startContainer,
  33812. offset,
  33813. dynamicPatternSet,
  33814. false
  33815. );
  33816. if (inlineMatches.length > 0) {
  33817. editor.undoManager.transact(() => {
  33818. applyMatches(editor, inlineMatches);
  33819. });
  33820. }
  33821. });
  33822. };
  33823. const checkKeyEvent = (codes, event, predicate) => {
  33824. for (let i = 0; i < codes.length; i++) {
  33825. if (predicate(codes[i], event)) {
  33826. return true;
  33827. }
  33828. }
  33829. return false;
  33830. };
  33831. const checkKeyCode = (codes, event) =>
  33832. checkKeyEvent(codes, event, (code, event) => {
  33833. return code === event.keyCode && !VK.modifierPressed(event);
  33834. });
  33835. const checkCharCode = (chars, event) =>
  33836. checkKeyEvent(chars, event, (chr, event) => {
  33837. return chr.charCodeAt(0) === event.charCode;
  33838. });
  33839. const setup$2 = (editor) => {
  33840. const charCodes = [",", ".", ";", ":", "!", "?"];
  33841. const keyCodes = [32];
  33842. const getPatternSet = () =>
  33843. createPatternSet(getTextPatterns(editor), getTextPatternsLookup(editor));
  33844. const hasDynamicPatterns = () => hasTextPatternsLookup(editor);
  33845. editor.on(
  33846. "keydown",
  33847. (e) => {
  33848. if (
  33849. e.keyCode === 13 &&
  33850. !VK.modifierPressed(e) &&
  33851. editor.selection.isCollapsed()
  33852. ) {
  33853. const patternSet = getPatternSet();
  33854. const hasPatterns =
  33855. patternSet.inlinePatterns.length > 0 ||
  33856. patternSet.blockPatterns.length > 0 ||
  33857. hasDynamicPatterns();
  33858. if (hasPatterns && handleEnter(editor, patternSet)) {
  33859. e.preventDefault();
  33860. }
  33861. }
  33862. },
  33863. true
  33864. );
  33865. const handleInlineTrigger = () => {
  33866. if (editor.selection.isCollapsed()) {
  33867. const patternSet = getPatternSet();
  33868. const hasPatterns =
  33869. patternSet.inlinePatterns.length > 0 || hasDynamicPatterns();
  33870. if (hasPatterns) {
  33871. handleInlineKey(editor, patternSet);
  33872. }
  33873. }
  33874. };
  33875. editor.on("keyup", (e) => {
  33876. if (checkKeyCode(keyCodes, e)) {
  33877. handleInlineTrigger();
  33878. }
  33879. });
  33880. editor.on("keypress", (e) => {
  33881. if (checkCharCode(charCodes, e)) {
  33882. Delay.setEditorTimeout(editor, handleInlineTrigger);
  33883. }
  33884. });
  33885. };
  33886. const setup$1 = (editor) => {
  33887. setup$2(editor);
  33888. };
  33889. const Quirks = (editor) => {
  33890. const each = Tools.each;
  33891. const BACKSPACE = VK.BACKSPACE,
  33892. DELETE = VK.DELETE,
  33893. dom = editor.dom,
  33894. selection = editor.selection,
  33895. parser = editor.parser;
  33896. const browser = Env.browser;
  33897. const isGecko = browser.isFirefox();
  33898. const isWebKit = browser.isChromium() || browser.isSafari();
  33899. const isiOS = Env.deviceType.isiPhone() || Env.deviceType.isiPad();
  33900. const isMac = Env.os.isMacOS() || Env.os.isiOS();
  33901. const setEditorCommandState = (cmd, state) => {
  33902. try {
  33903. editor.getDoc().execCommand(cmd, false, String(state));
  33904. } catch (ex) {}
  33905. };
  33906. const isDefaultPrevented = (e) => {
  33907. return e.isDefaultPrevented();
  33908. };
  33909. const emptyEditorWhenDeleting = () => {
  33910. const serializeRng = (rng) => {
  33911. const body = dom.create("body");
  33912. const contents = rng.cloneContents();
  33913. body.appendChild(contents);
  33914. return selection.serializer.serialize(body, { format: "html" });
  33915. };
  33916. const allContentsSelected = (rng) => {
  33917. const selection = serializeRng(rng);
  33918. const allRng = dom.createRng();
  33919. allRng.selectNode(editor.getBody());
  33920. const allSelection = serializeRng(allRng);
  33921. return selection === allSelection;
  33922. };
  33923. const hasPreservedEmptyElements = (elm) => {
  33924. const scope = SugarElement.fromDom(elm);
  33925. const isEditableHost = (elm) =>
  33926. parentElement(elm).exists((elm) => !isEditable$3(elm));
  33927. return exists(
  33928. descendants(scope, '[contenteditable="true"]'),
  33929. isEditableHost
  33930. );
  33931. };
  33932. editor.on("keydown", (e) => {
  33933. const keyCode = e.keyCode;
  33934. if (
  33935. !isDefaultPrevented(e) &&
  33936. (keyCode === DELETE || keyCode === BACKSPACE) &&
  33937. editor.selection.isEditable()
  33938. ) {
  33939. const isCollapsed = editor.selection.isCollapsed();
  33940. const body = editor.getBody();
  33941. if (
  33942. isCollapsed &&
  33943. (!dom.isEmpty(body) || hasPreservedEmptyElements(body))
  33944. ) {
  33945. return;
  33946. }
  33947. if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {
  33948. return;
  33949. }
  33950. e.preventDefault();
  33951. editor.setContent("");
  33952. if (body.firstChild && dom.isBlock(body.firstChild)) {
  33953. editor.selection.setCursorLocation(body.firstChild, 0);
  33954. } else {
  33955. editor.selection.setCursorLocation(body, 0);
  33956. }
  33957. editor.nodeChanged();
  33958. }
  33959. });
  33960. };
  33961. const selectAll = () => {
  33962. editor.shortcuts.add("meta+a", null, "SelectAll");
  33963. };
  33964. const documentElementEditingFocus = () => {
  33965. if (!editor.inline) {
  33966. dom.bind(editor.getDoc(), "mousedown mouseup", (e) => {
  33967. let rng;
  33968. if (e.target === editor.getDoc().documentElement) {
  33969. rng = selection.getRng();
  33970. editor.getBody().focus();
  33971. if (e.type === "mousedown") {
  33972. if (isCaretContainer$2(rng.startContainer)) {
  33973. return;
  33974. }
  33975. selection.placeCaretAt(e.clientX, e.clientY);
  33976. } else {
  33977. selection.setRng(rng);
  33978. }
  33979. }
  33980. });
  33981. }
  33982. };
  33983. const removeHrOnBackspace = () => {
  33984. editor.on("keydown", (e) => {
  33985. if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
  33986. if (!editor.getBody().getElementsByTagName("hr").length) {
  33987. return;
  33988. }
  33989. if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
  33990. const node = selection.getNode();
  33991. const previousSibling = node.previousSibling;
  33992. if (node.nodeName === "HR") {
  33993. dom.remove(node);
  33994. e.preventDefault();
  33995. return;
  33996. }
  33997. if (
  33998. previousSibling &&
  33999. previousSibling.nodeName &&
  34000. previousSibling.nodeName.toLowerCase() === "hr"
  34001. ) {
  34002. dom.remove(previousSibling);
  34003. e.preventDefault();
  34004. }
  34005. }
  34006. }
  34007. });
  34008. };
  34009. const focusBody = () => {
  34010. if (!Range.prototype.getClientRects) {
  34011. editor.on("mousedown", (e) => {
  34012. if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {
  34013. const body = editor.getBody();
  34014. body.blur();
  34015. Delay.setEditorTimeout(editor, () => {
  34016. body.focus();
  34017. });
  34018. }
  34019. });
  34020. }
  34021. };
  34022. const selectControlElements = () => {
  34023. const visualAidsAnchorClass = getVisualAidsAnchorClass(editor);
  34024. editor.on("click", (e) => {
  34025. const target = e.target;
  34026. if (
  34027. /^(IMG|HR)$/.test(target.nodeName) &&
  34028. dom.isEditable(target.parentNode)
  34029. ) {
  34030. e.preventDefault();
  34031. editor.selection.select(target);
  34032. editor.nodeChanged();
  34033. }
  34034. if (
  34035. target.nodeName === "A" &&
  34036. dom.hasClass(target, visualAidsAnchorClass) &&
  34037. target.childNodes.length === 0 &&
  34038. dom.isEditable(target.parentNode)
  34039. ) {
  34040. e.preventDefault();
  34041. selection.select(target);
  34042. }
  34043. });
  34044. };
  34045. const removeStylesWhenDeletingAcrossBlockElements = () => {
  34046. const getAttributeApplyFunction = () => {
  34047. const template = dom.getAttribs(selection.getStart().cloneNode(false));
  34048. return () => {
  34049. const target = selection.getStart();
  34050. if (target !== editor.getBody()) {
  34051. dom.setAttrib(target, "style", null);
  34052. each(template, (attr) => {
  34053. target.setAttributeNode(attr.cloneNode(true));
  34054. });
  34055. }
  34056. };
  34057. };
  34058. const isSelectionAcrossElements = () => {
  34059. return (
  34060. !selection.isCollapsed() &&
  34061. dom.getParent(selection.getStart(), dom.isBlock) !==
  34062. dom.getParent(selection.getEnd(), dom.isBlock)
  34063. );
  34064. };
  34065. editor.on("keypress", (e) => {
  34066. let applyAttributes;
  34067. if (
  34068. !isDefaultPrevented(e) &&
  34069. (e.keyCode === 8 || e.keyCode === 46) &&
  34070. isSelectionAcrossElements()
  34071. ) {
  34072. applyAttributes = getAttributeApplyFunction();
  34073. editor.getDoc().execCommand("delete", false);
  34074. applyAttributes();
  34075. e.preventDefault();
  34076. return false;
  34077. } else {
  34078. return true;
  34079. }
  34080. });
  34081. dom.bind(editor.getDoc(), "cut", (e) => {
  34082. if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {
  34083. const applyAttributes = getAttributeApplyFunction();
  34084. Delay.setEditorTimeout(editor, () => {
  34085. applyAttributes();
  34086. });
  34087. }
  34088. });
  34089. };
  34090. const disableBackspaceIntoATable = () => {
  34091. editor.on("keydown", (e) => {
  34092. if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {
  34093. if (selection.isCollapsed() && selection.getRng().startOffset === 0) {
  34094. const previousSibling = selection.getNode().previousSibling;
  34095. if (
  34096. previousSibling &&
  34097. previousSibling.nodeName &&
  34098. previousSibling.nodeName.toLowerCase() === "table"
  34099. ) {
  34100. e.preventDefault();
  34101. return false;
  34102. }
  34103. }
  34104. }
  34105. return true;
  34106. });
  34107. };
  34108. const removeBlockQuoteOnBackSpace = () => {
  34109. editor.on("keydown", (e) => {
  34110. if (isDefaultPrevented(e) || e.keyCode !== VK.BACKSPACE) {
  34111. return;
  34112. }
  34113. let rng = selection.getRng();
  34114. const container = rng.startContainer;
  34115. const offset = rng.startOffset;
  34116. const root = dom.getRoot();
  34117. let parent = container;
  34118. if (!rng.collapsed || offset !== 0) {
  34119. return;
  34120. }
  34121. while (
  34122. parent.parentNode &&
  34123. parent.parentNode.firstChild === parent &&
  34124. parent.parentNode !== root
  34125. ) {
  34126. parent = parent.parentNode;
  34127. }
  34128. if (parent.nodeName === "BLOCKQUOTE") {
  34129. editor.formatter.toggle("blockquote", undefined, parent);
  34130. rng = dom.createRng();
  34131. rng.setStart(container, 0);
  34132. rng.setEnd(container, 0);
  34133. selection.setRng(rng);
  34134. }
  34135. });
  34136. };
  34137. const setGeckoEditingOptions = () => {
  34138. const setOpts = () => {
  34139. setEditorCommandState("StyleWithCSS", false);
  34140. setEditorCommandState("enableInlineTableEditing", false);
  34141. if (!getObjectResizing(editor)) {
  34142. setEditorCommandState("enableObjectResizing", false);
  34143. }
  34144. };
  34145. if (!isReadOnly$1(editor)) {
  34146. editor.on("BeforeExecCommand mousedown", setOpts);
  34147. }
  34148. };
  34149. const addBrAfterLastLinks = () => {
  34150. const fixLinks = () => {
  34151. each(dom.select("a:not([data-mce-block])"), (node) => {
  34152. var _a;
  34153. let parentNode = node.parentNode;
  34154. const root = dom.getRoot();
  34155. if (
  34156. (parentNode === null || parentNode === void 0
  34157. ? void 0
  34158. : parentNode.lastChild) === node
  34159. ) {
  34160. while (parentNode && !dom.isBlock(parentNode)) {
  34161. if (
  34162. ((_a = parentNode.parentNode) === null || _a === void 0
  34163. ? void 0
  34164. : _a.lastChild) !== parentNode ||
  34165. parentNode === root
  34166. ) {
  34167. return;
  34168. }
  34169. parentNode = parentNode.parentNode;
  34170. }
  34171. dom.add(parentNode, "br", { "data-mce-bogus": 1 });
  34172. }
  34173. });
  34174. };
  34175. editor.on("SetContent ExecCommand", (e) => {
  34176. if (e.type === "setcontent" || e.command === "mceInsertLink") {
  34177. fixLinks();
  34178. }
  34179. });
  34180. };
  34181. const setDefaultBlockType = () => {
  34182. editor.on("init", () => {
  34183. setEditorCommandState(
  34184. "DefaultParagraphSeparator",
  34185. getForcedRootBlock(editor)
  34186. );
  34187. });
  34188. };
  34189. const isAllContentSelected = (editor) => {
  34190. const body = editor.getBody();
  34191. const rng = editor.selection.getRng();
  34192. return (
  34193. rng.startContainer === rng.endContainer &&
  34194. rng.startContainer === body &&
  34195. rng.startOffset === 0 &&
  34196. rng.endOffset === body.childNodes.length
  34197. );
  34198. };
  34199. const normalizeSelection = () => {
  34200. editor.on(
  34201. "keyup focusin mouseup",
  34202. (e) => {
  34203. if (!VK.modifierPressed(e) && !isAllContentSelected(editor)) {
  34204. selection.normalize();
  34205. }
  34206. },
  34207. true
  34208. );
  34209. };
  34210. const showBrokenImageIcon = () => {
  34211. editor.contentStyles.push(
  34212. "img:-moz-broken {" +
  34213. "-moz-force-broken-image-icon:1;" +
  34214. "min-width:24px;" +
  34215. "min-height:24px" +
  34216. "}"
  34217. );
  34218. };
  34219. const restoreFocusOnKeyDown = () => {
  34220. if (!editor.inline) {
  34221. editor.on("keydown", () => {
  34222. if (document.activeElement === document.body) {
  34223. editor.getWin().focus();
  34224. }
  34225. });
  34226. }
  34227. };
  34228. const bodyHeight = () => {
  34229. if (!editor.inline) {
  34230. editor.contentStyles.push("body {min-height: 150px}");
  34231. editor.on("click", (e) => {
  34232. let rng;
  34233. if (e.target.nodeName === "HTML") {
  34234. rng = editor.selection.getRng();
  34235. editor.getBody().focus();
  34236. editor.selection.setRng(rng);
  34237. editor.selection.normalize();
  34238. editor.nodeChanged();
  34239. }
  34240. });
  34241. }
  34242. };
  34243. const blockCmdArrowNavigation = () => {
  34244. if (isMac) {
  34245. editor.on("keydown", (e) => {
  34246. if (
  34247. VK.metaKeyPressed(e) &&
  34248. !e.shiftKey &&
  34249. (e.keyCode === 37 || e.keyCode === 39)
  34250. ) {
  34251. e.preventDefault();
  34252. const selection = editor.selection.getSel();
  34253. selection.modify(
  34254. "move",
  34255. e.keyCode === 37 ? "backward" : "forward",
  34256. "lineboundary"
  34257. );
  34258. }
  34259. });
  34260. }
  34261. };
  34262. const tapLinksAndImages = () => {
  34263. editor.on("click", (e) => {
  34264. let elm = e.target;
  34265. do {
  34266. if (elm.tagName === "A") {
  34267. e.preventDefault();
  34268. return;
  34269. }
  34270. } while ((elm = elm.parentNode));
  34271. });
  34272. editor.contentStyles.push(
  34273. ".mce-content-body {-webkit-touch-callout: none}"
  34274. );
  34275. };
  34276. const blockFormSubmitInsideEditor = () => {
  34277. editor.on("init", () => {
  34278. editor.dom.bind(editor.getBody(), "submit", (e) => {
  34279. e.preventDefault();
  34280. });
  34281. });
  34282. };
  34283. const removeAppleInterchangeBrs = () => {
  34284. parser.addNodeFilter("br", (nodes) => {
  34285. let i = nodes.length;
  34286. while (i--) {
  34287. if (nodes[i].attr("class") === "Apple-interchange-newline") {
  34288. nodes[i].remove();
  34289. }
  34290. }
  34291. });
  34292. };
  34293. const refreshContentEditable = noop;
  34294. const isHidden = () => {
  34295. if (!isGecko || editor.removed) {
  34296. return false;
  34297. }
  34298. const sel = editor.selection.getSel();
  34299. return !sel || !sel.rangeCount || sel.rangeCount === 0;
  34300. };
  34301. const setupRtc = () => {
  34302. if (isWebKit) {
  34303. documentElementEditingFocus();
  34304. selectControlElements();
  34305. blockFormSubmitInsideEditor();
  34306. selectAll();
  34307. if (isiOS) {
  34308. restoreFocusOnKeyDown();
  34309. bodyHeight();
  34310. tapLinksAndImages();
  34311. }
  34312. }
  34313. if (isGecko) {
  34314. focusBody();
  34315. setGeckoEditingOptions();
  34316. showBrokenImageIcon();
  34317. blockCmdArrowNavigation();
  34318. }
  34319. };
  34320. const dropDragEndEvent = () => {
  34321. editor.on("drop", (event) => {
  34322. var _a;
  34323. const data =
  34324. (_a = event.dataTransfer) === null || _a === void 0
  34325. ? void 0
  34326. : _a.getData("text/html");
  34327. if (isString(data) && /^<img[^>]*>$/.test(data)) {
  34328. editor.dispatch("dragend", new window.DragEvent("dragend", event));
  34329. }
  34330. });
  34331. };
  34332. const setup = () => {
  34333. removeBlockQuoteOnBackSpace();
  34334. emptyEditorWhenDeleting();
  34335. if (!Env.windowsPhone) {
  34336. normalizeSelection();
  34337. }
  34338. if (isWebKit) {
  34339. documentElementEditingFocus();
  34340. selectControlElements();
  34341. setDefaultBlockType();
  34342. blockFormSubmitInsideEditor();
  34343. disableBackspaceIntoATable();
  34344. removeAppleInterchangeBrs();
  34345. if (isiOS) {
  34346. restoreFocusOnKeyDown();
  34347. bodyHeight();
  34348. tapLinksAndImages();
  34349. } else {
  34350. selectAll();
  34351. }
  34352. }
  34353. if (isGecko) {
  34354. removeHrOnBackspace();
  34355. focusBody();
  34356. removeStylesWhenDeletingAcrossBlockElements();
  34357. setGeckoEditingOptions();
  34358. addBrAfterLastLinks();
  34359. showBrokenImageIcon();
  34360. blockCmdArrowNavigation();
  34361. disableBackspaceIntoATable();
  34362. dropDragEndEvent();
  34363. }
  34364. };
  34365. if (isRtc(editor)) {
  34366. setupRtc();
  34367. } else {
  34368. setup();
  34369. }
  34370. return {
  34371. refreshContentEditable,
  34372. isHidden,
  34373. };
  34374. };
  34375. const DOM$6 = DOMUtils.DOM;
  34376. const appendStyle = (editor, text) => {
  34377. const body = SugarElement.fromDom(editor.getBody());
  34378. const container = getStyleContainer(getRootNode(body));
  34379. const style = SugarElement.fromTag("style");
  34380. set$3(style, "type", "text/css");
  34381. append$1(style, SugarElement.fromText(text));
  34382. append$1(container, style);
  34383. editor.on("remove", () => {
  34384. remove$5(style);
  34385. });
  34386. };
  34387. const getRootName = (editor) =>
  34388. editor.inline ? editor.getElement().nodeName.toLowerCase() : undefined;
  34389. const removeUndefined = (obj) =>
  34390. filter$4(obj, (v) => isUndefined(v) === false);
  34391. const mkParserSettings = (editor) => {
  34392. const getOption = editor.options.get;
  34393. const blobCache = editor.editorUpload.blobCache;
  34394. return removeUndefined({
  34395. allow_conditional_comments: getOption("allow_conditional_comments"),
  34396. allow_html_data_urls: getOption("allow_html_data_urls"),
  34397. allow_svg_data_urls: getOption("allow_svg_data_urls"),
  34398. allow_html_in_named_anchor: getOption("allow_html_in_named_anchor"),
  34399. allow_script_urls: getOption("allow_script_urls"),
  34400. allow_unsafe_link_target: getOption("allow_unsafe_link_target"),
  34401. convert_fonts_to_spans: getOption("convert_fonts_to_spans"),
  34402. fix_list_elements: getOption("fix_list_elements"),
  34403. font_size_legacy_values: getOption("font_size_legacy_values"),
  34404. forced_root_block: getOption("forced_root_block"),
  34405. forced_root_block_attrs: getOption("forced_root_block_attrs"),
  34406. preserve_cdata: getOption("preserve_cdata"),
  34407. inline_styles: getOption("inline_styles"),
  34408. root_name: getRootName(editor),
  34409. sanitize: getOption("xss_sanitization"),
  34410. validate: true,
  34411. blob_cache: blobCache,
  34412. document: editor.getDoc(),
  34413. });
  34414. };
  34415. const mkSchemaSettings = (editor) => {
  34416. const getOption = editor.options.get;
  34417. return removeUndefined({
  34418. custom_elements: getOption("custom_elements"),
  34419. extended_valid_elements: getOption("extended_valid_elements"),
  34420. invalid_elements: getOption("invalid_elements"),
  34421. invalid_styles: getOption("invalid_styles"),
  34422. schema: getOption("schema"),
  34423. valid_children: getOption("valid_children"),
  34424. valid_classes: getOption("valid_classes"),
  34425. valid_elements: getOption("valid_elements"),
  34426. valid_styles: getOption("valid_styles"),
  34427. verify_html: getOption("verify_html"),
  34428. padd_empty_block_inline_children: getOption("format_empty_lines"),
  34429. });
  34430. };
  34431. const mkSerializerSettings = (editor) => {
  34432. const getOption = editor.options.get;
  34433. return {
  34434. ...mkParserSettings(editor),
  34435. ...mkSchemaSettings(editor),
  34436. ...removeUndefined({
  34437. remove_trailing_brs: getOption("remove_trailing_brs"),
  34438. pad_empty_with_br: getOption("pad_empty_with_br"),
  34439. url_converter: getOption("url_converter"),
  34440. url_converter_scope: getOption("url_converter_scope"),
  34441. element_format: getOption("element_format"),
  34442. entities: getOption("entities"),
  34443. entity_encoding: getOption("entity_encoding"),
  34444. indent: getOption("indent"),
  34445. indent_after: getOption("indent_after"),
  34446. indent_before: getOption("indent_before"),
  34447. }),
  34448. };
  34449. };
  34450. const createParser = (editor) => {
  34451. const parser = DomParser(mkParserSettings(editor), editor.schema);
  34452. parser.addAttributeFilter("src,href,style,tabindex", (nodes, name) => {
  34453. const dom = editor.dom;
  34454. const internalName = "data-mce-" + name;
  34455. let i = nodes.length;
  34456. while (i--) {
  34457. const node = nodes[i];
  34458. let value = node.attr(name);
  34459. if (value && !node.attr(internalName)) {
  34460. if (value.indexOf("data:") === 0 || value.indexOf("blob:") === 0) {
  34461. continue;
  34462. }
  34463. if (name === "style") {
  34464. value = dom.serializeStyle(dom.parseStyle(value), node.name);
  34465. if (!value.length) {
  34466. value = null;
  34467. }
  34468. node.attr(internalName, value);
  34469. node.attr(name, value);
  34470. } else if (name === "tabindex") {
  34471. node.attr(internalName, value);
  34472. node.attr(name, null);
  34473. } else {
  34474. node.attr(internalName, editor.convertURL(value, name, node.name));
  34475. }
  34476. }
  34477. }
  34478. });
  34479. parser.addNodeFilter("script", (nodes) => {
  34480. let i = nodes.length;
  34481. while (i--) {
  34482. const node = nodes[i];
  34483. const type = node.attr("type") || "no/type";
  34484. if (type.indexOf("mce-") !== 0) {
  34485. node.attr("type", "mce-" + type);
  34486. }
  34487. }
  34488. });
  34489. if (shouldPreserveCData(editor)) {
  34490. parser.addNodeFilter("#cdata", (nodes) => {
  34491. var _a;
  34492. let i = nodes.length;
  34493. while (i--) {
  34494. const node = nodes[i];
  34495. node.type = 8;
  34496. node.name = "#comment";
  34497. node.value =
  34498. "[CDATA[" +
  34499. editor.dom.encode(
  34500. (_a = node.value) !== null && _a !== void 0 ? _a : ""
  34501. ) +
  34502. "]]";
  34503. }
  34504. });
  34505. }
  34506. parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div", (nodes) => {
  34507. let i = nodes.length;
  34508. const nonEmptyElements = editor.schema.getNonEmptyElements();
  34509. while (i--) {
  34510. const node = nodes[i];
  34511. if (node.isEmpty(nonEmptyElements) && node.getAll("br").length === 0) {
  34512. node.append(new AstNode("br", 1));
  34513. }
  34514. }
  34515. });
  34516. return parser;
  34517. };
  34518. const autoFocus = (editor) => {
  34519. const autoFocus = getAutoFocus(editor);
  34520. if (autoFocus) {
  34521. Delay.setEditorTimeout(
  34522. editor,
  34523. () => {
  34524. let focusEditor;
  34525. if (autoFocus === true) {
  34526. focusEditor = editor;
  34527. } else {
  34528. focusEditor = editor.editorManager.get(autoFocus);
  34529. }
  34530. if (focusEditor && !focusEditor.destroyed) {
  34531. focusEditor.focus();
  34532. focusEditor.selection.scrollIntoView();
  34533. }
  34534. },
  34535. 100
  34536. );
  34537. }
  34538. };
  34539. const moveSelectionToFirstCaretPosition = (editor) => {
  34540. const root = editor.dom.getRoot();
  34541. if (
  34542. !editor.inline &&
  34543. (!hasAnyRanges(editor) || editor.selection.getStart(true) === root)
  34544. ) {
  34545. firstPositionIn(root).each((pos) => {
  34546. const node = pos.getNode();
  34547. const caretPos = isTable$2(node)
  34548. ? firstPositionIn(node).getOr(pos)
  34549. : pos;
  34550. editor.selection.setRng(caretPos.toRange());
  34551. });
  34552. }
  34553. };
  34554. const initEditor = (editor) => {
  34555. editor.bindPendingEventDelegates();
  34556. editor.initialized = true;
  34557. fireInit(editor);
  34558. editor.focus(true);
  34559. moveSelectionToFirstCaretPosition(editor);
  34560. editor.nodeChanged({ initial: true });
  34561. const initInstanceCallback = getInitInstanceCallback(editor);
  34562. if (isFunction(initInstanceCallback)) {
  34563. initInstanceCallback.call(editor, editor);
  34564. }
  34565. autoFocus(editor);
  34566. };
  34567. const getStyleSheetLoader$1 = (editor) =>
  34568. editor.inline ? editor.ui.styleSheetLoader : editor.dom.styleSheetLoader;
  34569. const makeStylesheetLoadingPromises = (editor, css, framedFonts) => {
  34570. const promises = [getStyleSheetLoader$1(editor).loadAll(css)];
  34571. if (editor.inline) {
  34572. return promises;
  34573. } else {
  34574. return promises.concat([editor.ui.styleSheetLoader.loadAll(framedFonts)]);
  34575. }
  34576. };
  34577. const loadContentCss = (editor) => {
  34578. const styleSheetLoader = getStyleSheetLoader$1(editor);
  34579. const fontCss = getFontCss(editor);
  34580. const css = editor.contentCSS;
  34581. const removeCss = () => {
  34582. styleSheetLoader.unloadAll(css);
  34583. if (!editor.inline) {
  34584. editor.ui.styleSheetLoader.unloadAll(fontCss);
  34585. }
  34586. };
  34587. const loaded = () => {
  34588. if (editor.removed) {
  34589. removeCss();
  34590. } else {
  34591. editor.on("remove", removeCss);
  34592. }
  34593. };
  34594. if (editor.contentStyles.length > 0) {
  34595. let contentCssText = "";
  34596. Tools.each(editor.contentStyles, (style) => {
  34597. contentCssText += style + "\r\n";
  34598. });
  34599. editor.dom.addStyle(contentCssText);
  34600. }
  34601. const allStylesheets = Promise.all(
  34602. makeStylesheetLoadingPromises(editor, css, fontCss)
  34603. )
  34604. .then(loaded)
  34605. .catch(loaded);
  34606. const contentStyle = getContentStyle(editor);
  34607. if (contentStyle) {
  34608. appendStyle(editor, contentStyle);
  34609. }
  34610. return allStylesheets;
  34611. };
  34612. const preInit = (editor) => {
  34613. const doc = editor.getDoc(),
  34614. body = editor.getBody();
  34615. firePreInit(editor);
  34616. if (!shouldBrowserSpellcheck(editor)) {
  34617. doc.body.spellcheck = false;
  34618. DOM$6.setAttrib(body, "spellcheck", "false");
  34619. }
  34620. editor.quirks = Quirks(editor);
  34621. firePostRender(editor);
  34622. const directionality = getDirectionality(editor);
  34623. if (directionality !== undefined) {
  34624. body.dir = directionality;
  34625. }
  34626. const protect = getProtect(editor);
  34627. if (protect) {
  34628. editor.on("BeforeSetContent", (e) => {
  34629. Tools.each(protect, (pattern) => {
  34630. e.content = e.content.replace(pattern, (str) => {
  34631. return "<!--mce:protected " + escape(str) + "-->";
  34632. });
  34633. });
  34634. });
  34635. }
  34636. editor.on("SetContent", () => {
  34637. editor.addVisual(editor.getBody());
  34638. });
  34639. editor.on("compositionstart compositionend", (e) => {
  34640. editor.composing = e.type === "compositionstart";
  34641. });
  34642. };
  34643. const loadInitialContent = (editor) => {
  34644. if (!isRtc(editor)) {
  34645. editor.load({
  34646. initial: true,
  34647. format: "html",
  34648. });
  34649. }
  34650. editor.startContent = editor.getContent({ format: "raw" });
  34651. };
  34652. const initEditorWithInitialContent = (editor) => {
  34653. if (editor.removed !== true) {
  34654. loadInitialContent(editor);
  34655. initEditor(editor);
  34656. }
  34657. };
  34658. const startProgress = (editor) => {
  34659. let canceled = false;
  34660. const progressTimeout = setTimeout(() => {
  34661. if (!canceled) {
  34662. editor.setProgressState(true);
  34663. }
  34664. }, 500);
  34665. return () => {
  34666. clearTimeout(progressTimeout);
  34667. canceled = true;
  34668. editor.setProgressState(false);
  34669. };
  34670. };
  34671. const contentBodyLoaded = (editor) => {
  34672. const targetElm = editor.getElement();
  34673. let doc = editor.getDoc();
  34674. if (editor.inline) {
  34675. DOM$6.addClass(targetElm, "mce-content-body");
  34676. editor.contentDocument = doc = document;
  34677. editor.contentWindow = window;
  34678. editor.bodyElement = targetElm;
  34679. editor.contentAreaContainer = targetElm;
  34680. }
  34681. const body = editor.getBody();
  34682. body.disabled = true;
  34683. editor.readonly = isReadOnly$1(editor);
  34684. editor._editableRoot = hasEditableRoot$1(editor);
  34685. if (!editor.readonly && editor.hasEditableRoot()) {
  34686. if (
  34687. editor.inline &&
  34688. DOM$6.getStyle(body, "position", true) === "static"
  34689. ) {
  34690. body.style.position = "relative";
  34691. }
  34692. body.contentEditable = "true";
  34693. }
  34694. body.disabled = false;
  34695. editor.editorUpload = EditorUpload(editor);
  34696. editor.schema = Schema(mkSchemaSettings(editor));
  34697. editor.dom = DOMUtils(doc, {
  34698. keep_values: true,
  34699. url_converter: editor.convertURL,
  34700. url_converter_scope: editor,
  34701. update_styles: true,
  34702. root_element: editor.inline ? editor.getBody() : null,
  34703. collect: editor.inline,
  34704. schema: editor.schema,
  34705. contentCssCors: shouldUseContentCssCors(editor),
  34706. referrerPolicy: getReferrerPolicy(editor),
  34707. onSetAttrib: (e) => {
  34708. editor.dispatch("SetAttrib", e);
  34709. },
  34710. });
  34711. editor.parser = createParser(editor);
  34712. editor.serializer = DomSerializer(mkSerializerSettings(editor), editor);
  34713. editor.selection = EditorSelection(
  34714. editor.dom,
  34715. editor.getWin(),
  34716. editor.serializer,
  34717. editor
  34718. );
  34719. editor.annotator = Annotator(editor);
  34720. editor.formatter = Formatter(editor);
  34721. editor.undoManager = UndoManager(editor);
  34722. editor._nodeChangeDispatcher = new NodeChange(editor);
  34723. editor._selectionOverrides = SelectionOverrides(editor);
  34724. setup$o(editor);
  34725. setup$6(editor);
  34726. setup$m(editor);
  34727. if (!isRtc(editor)) {
  34728. setup$5(editor);
  34729. setup$1(editor);
  34730. }
  34731. const caret = setup$b(editor);
  34732. setup$p(editor, caret);
  34733. setup$n(editor);
  34734. setup$q(editor);
  34735. setup$7(editor);
  34736. const setupRtcThunk = setup$s(editor);
  34737. preInit(editor);
  34738. setupRtcThunk.fold(
  34739. () => {
  34740. const cancelProgress = startProgress(editor);
  34741. loadContentCss(editor).then(() => {
  34742. initEditorWithInitialContent(editor);
  34743. cancelProgress();
  34744. });
  34745. },
  34746. (setupRtc) => {
  34747. editor.setProgressState(true);
  34748. loadContentCss(editor).then(() => {
  34749. setupRtc().then(
  34750. (_rtcMode) => {
  34751. editor.setProgressState(false);
  34752. initEditorWithInitialContent(editor);
  34753. bindEvents(editor);
  34754. },
  34755. (err) => {
  34756. editor.notificationManager.open({
  34757. type: "error",
  34758. text: String(err),
  34759. });
  34760. initEditorWithInitialContent(editor);
  34761. bindEvents(editor);
  34762. }
  34763. );
  34764. });
  34765. }
  34766. );
  34767. };
  34768. const filter = always;
  34769. const bind = (element, event, handler) =>
  34770. bind$2(element, event, filter, handler);
  34771. const DOM$5 = DOMUtils.DOM;
  34772. const createIframeElement = (id, title, customAttrs, tabindex) => {
  34773. const iframe = SugarElement.fromTag("iframe");
  34774. tabindex.each((t) => set$3(iframe, "tabindex", t));
  34775. setAll$1(iframe, customAttrs);
  34776. setAll$1(iframe, {
  34777. id: id + "_ifr",
  34778. frameBorder: "0",
  34779. allowTransparency: "true",
  34780. title,
  34781. });
  34782. add$2(iframe, "tox-edit-area__iframe");
  34783. return iframe;
  34784. };
  34785. const getIframeHtml = (editor) => {
  34786. let iframeHTML = getDocType(editor) + "<html><head>";
  34787. if (getDocumentBaseUrl(editor) !== editor.documentBaseUrl) {
  34788. iframeHTML += '<base href="' + editor.documentBaseURI.getURI() + '" />';
  34789. }
  34790. iframeHTML +=
  34791. '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
  34792. const bodyId = getBodyId(editor);
  34793. const bodyClass = getBodyClass(editor);
  34794. const translatedAriaText = editor.translate(getIframeAriaText(editor));
  34795. if (getContentSecurityPolicy(editor)) {
  34796. iframeHTML +=
  34797. '<meta http-equiv="Content-Security-Policy" content="' +
  34798. getContentSecurityPolicy(editor) +
  34799. '" />';
  34800. }
  34801. iframeHTML +=
  34802. "</head>" +
  34803. `<body id="${bodyId}" class="mce-content-body ${bodyClass}" data-id="${editor.id}" aria-label="${translatedAriaText}">` +
  34804. "<br>" +
  34805. "</body></html>";
  34806. return iframeHTML;
  34807. };
  34808. const createIframe = (editor, boxInfo) => {
  34809. const iframeTitle = editor.translate("Rich Text Area");
  34810. const tabindex = getOpt(
  34811. SugarElement.fromDom(editor.getElement()),
  34812. "tabindex"
  34813. ).bind(toInt);
  34814. const ifr = createIframeElement(
  34815. editor.id,
  34816. iframeTitle,
  34817. getIframeAttrs(editor),
  34818. tabindex
  34819. ).dom;
  34820. ifr.onload = () => {
  34821. ifr.onload = null;
  34822. editor.dispatch("load");
  34823. };
  34824. editor.contentAreaContainer = boxInfo.iframeContainer;
  34825. editor.iframeElement = ifr;
  34826. editor.iframeHTML = getIframeHtml(editor);
  34827. DOM$5.add(boxInfo.iframeContainer, ifr);
  34828. };
  34829. const setupIframeBody = (editor) => {
  34830. const iframe = editor.iframeElement;
  34831. const ready = () => {
  34832. editor.contentDocument = iframe.contentDocument;
  34833. contentBodyLoaded(editor);
  34834. };
  34835. if (shouldUseDocumentWrite(editor) || Env.browser.isFirefox()) {
  34836. const doc = editor.getDoc();
  34837. doc.open();
  34838. doc.write(editor.iframeHTML);
  34839. doc.close();
  34840. ready();
  34841. } else {
  34842. const binder = bind(SugarElement.fromDom(iframe), "load", () => {
  34843. binder.unbind();
  34844. ready();
  34845. });
  34846. iframe.srcdoc = editor.iframeHTML;
  34847. }
  34848. };
  34849. const init$1 = (editor, boxInfo) => {
  34850. createIframe(editor, boxInfo);
  34851. if (boxInfo.editorContainer) {
  34852. boxInfo.editorContainer.style.display = editor.orgDisplay;
  34853. editor.hidden = DOM$5.isHidden(boxInfo.editorContainer);
  34854. }
  34855. editor.getElement().style.display = "none";
  34856. DOM$5.setAttrib(editor.id, "aria-hidden", "true");
  34857. editor.getElement().style.visibility = editor.orgVisibility;
  34858. setupIframeBody(editor);
  34859. };
  34860. const DOM$4 = DOMUtils.DOM;
  34861. const initPlugin = (editor, initializedPlugins, plugin) => {
  34862. const Plugin = PluginManager.get(plugin);
  34863. const pluginUrl =
  34864. PluginManager.urls[plugin] || editor.documentBaseUrl.replace(/\/$/, "");
  34865. plugin = Tools.trim(plugin);
  34866. if (Plugin && Tools.inArray(initializedPlugins, plugin) === -1) {
  34867. if (editor.plugins[plugin]) {
  34868. return;
  34869. }
  34870. try {
  34871. const pluginInstance = Plugin(editor, pluginUrl) || {};
  34872. editor.plugins[plugin] = pluginInstance;
  34873. if (isFunction(pluginInstance.init)) {
  34874. pluginInstance.init(editor, pluginUrl);
  34875. initializedPlugins.push(plugin);
  34876. }
  34877. } catch (e) {
  34878. pluginInitError(editor, plugin, e);
  34879. }
  34880. }
  34881. };
  34882. const trimLegacyPrefix = (name) => {
  34883. return name.replace(/^\-/, "");
  34884. };
  34885. const initPlugins = (editor) => {
  34886. const initializedPlugins = [];
  34887. each$e(getPlugins(editor), (name) => {
  34888. initPlugin(editor, initializedPlugins, trimLegacyPrefix(name));
  34889. });
  34890. };
  34891. const initIcons = (editor) => {
  34892. const iconPackName = Tools.trim(getIconPackName(editor));
  34893. const currentIcons = editor.ui.registry.getAll().icons;
  34894. const loadIcons = {
  34895. ...IconManager.get("default").icons,
  34896. ...IconManager.get(iconPackName).icons,
  34897. };
  34898. each$d(loadIcons, (svgData, icon) => {
  34899. if (!has$2(currentIcons, icon)) {
  34900. editor.ui.registry.addIcon(icon, svgData);
  34901. }
  34902. });
  34903. };
  34904. const initTheme = (editor) => {
  34905. const theme = getTheme(editor);
  34906. if (isString(theme)) {
  34907. const Theme = ThemeManager.get(theme);
  34908. editor.theme = Theme(editor, ThemeManager.urls[theme]) || {};
  34909. if (isFunction(editor.theme.init)) {
  34910. editor.theme.init(
  34911. editor,
  34912. ThemeManager.urls[theme] || editor.documentBaseUrl.replace(/\/$/, "")
  34913. );
  34914. }
  34915. } else {
  34916. editor.theme = {};
  34917. }
  34918. };
  34919. const initModel = (editor) => {
  34920. const model = getModel(editor);
  34921. const Model = ModelManager.get(model);
  34922. editor.model = Model(editor, ModelManager.urls[model]);
  34923. };
  34924. const renderFromLoadedTheme = (editor) => {
  34925. const render = editor.theme.renderUI;
  34926. return render ? render() : renderThemeFalse(editor);
  34927. };
  34928. const renderFromThemeFunc = (editor) => {
  34929. const elm = editor.getElement();
  34930. const theme = getTheme(editor);
  34931. const info = theme(editor, elm);
  34932. if (info.editorContainer.nodeType) {
  34933. info.editorContainer.id =
  34934. info.editorContainer.id || editor.id + "_parent";
  34935. }
  34936. if (info.iframeContainer && info.iframeContainer.nodeType) {
  34937. info.iframeContainer.id =
  34938. info.iframeContainer.id || editor.id + "_iframecontainer";
  34939. }
  34940. info.height = info.iframeHeight ? info.iframeHeight : elm.offsetHeight;
  34941. return info;
  34942. };
  34943. const createThemeFalseResult = (element, iframe) => {
  34944. return {
  34945. editorContainer: element,
  34946. iframeContainer: iframe,
  34947. api: {},
  34948. };
  34949. };
  34950. const renderThemeFalseIframe = (targetElement) => {
  34951. const iframeContainer = DOM$4.create("div");
  34952. DOM$4.insertAfter(iframeContainer, targetElement);
  34953. return createThemeFalseResult(iframeContainer, iframeContainer);
  34954. };
  34955. const renderThemeFalse = (editor) => {
  34956. const targetElement = editor.getElement();
  34957. return editor.inline
  34958. ? createThemeFalseResult(null)
  34959. : renderThemeFalseIframe(targetElement);
  34960. };
  34961. const renderThemeUi = (editor) => {
  34962. const elm = editor.getElement();
  34963. editor.orgDisplay = elm.style.display;
  34964. if (isString(getTheme(editor))) {
  34965. return renderFromLoadedTheme(editor);
  34966. } else if (isFunction(getTheme(editor))) {
  34967. return renderFromThemeFunc(editor);
  34968. } else {
  34969. return renderThemeFalse(editor);
  34970. }
  34971. };
  34972. const augmentEditorUiApi = (editor, api) => {
  34973. const uiApiFacade = {
  34974. show: Optional.from(api.show).getOr(noop),
  34975. hide: Optional.from(api.hide).getOr(noop),
  34976. isEnabled: Optional.from(api.isEnabled).getOr(always),
  34977. setEnabled: (state) => {
  34978. if (!editor.mode.isReadOnly()) {
  34979. Optional.from(api.setEnabled).each((f) => f(state));
  34980. }
  34981. },
  34982. };
  34983. editor.ui = {
  34984. ...editor.ui,
  34985. ...uiApiFacade,
  34986. };
  34987. };
  34988. const init = async (editor) => {
  34989. editor.dispatch("ScriptsLoaded");
  34990. initIcons(editor);
  34991. initTheme(editor);
  34992. initModel(editor);
  34993. initPlugins(editor);
  34994. const renderInfo = await renderThemeUi(editor);
  34995. augmentEditorUiApi(editor, Optional.from(renderInfo.api).getOr({}));
  34996. editor.editorContainer = renderInfo.editorContainer;
  34997. appendContentCssFromSettings(editor);
  34998. if (editor.inline) {
  34999. contentBodyLoaded(editor);
  35000. } else {
  35001. init$1(editor, {
  35002. editorContainer: renderInfo.editorContainer,
  35003. iframeContainer: renderInfo.iframeContainer,
  35004. });
  35005. }
  35006. };
  35007. const DOM$3 = DOMUtils.DOM;
  35008. const hasSkipLoadPrefix = (name) => name.charAt(0) === "-";
  35009. const loadLanguage = (scriptLoader, editor) => {
  35010. const languageCode = getLanguageCode(editor);
  35011. const languageUrl = getLanguageUrl(editor);
  35012. if (!I18n.hasCode(languageCode) && languageCode !== "en") {
  35013. const url = isNotEmpty(languageUrl)
  35014. ? languageUrl
  35015. : `${editor.editorManager.baseURL}/langs/${languageCode}.js`;
  35016. scriptLoader.add(url).catch(() => {
  35017. languageLoadError(editor, url, languageCode);
  35018. });
  35019. }
  35020. };
  35021. const loadTheme = (editor, suffix) => {
  35022. const theme = getTheme(editor);
  35023. if (
  35024. isString(theme) &&
  35025. !hasSkipLoadPrefix(theme) &&
  35026. !has$2(ThemeManager.urls, theme)
  35027. ) {
  35028. const themeUrl = getThemeUrl(editor);
  35029. const url = themeUrl
  35030. ? editor.documentBaseURI.toAbsolute(themeUrl)
  35031. : `themes/${theme}/theme${suffix}.js`;
  35032. ThemeManager.load(theme, url).catch(() => {
  35033. themeLoadError(editor, url, theme);
  35034. });
  35035. }
  35036. };
  35037. const loadModel = (editor, suffix) => {
  35038. const model = getModel(editor);
  35039. if (model !== "plugin" && !has$2(ModelManager.urls, model)) {
  35040. const modelUrl = getModelUrl(editor);
  35041. const url = isString(modelUrl)
  35042. ? editor.documentBaseURI.toAbsolute(modelUrl)
  35043. : `models/${model}/model${suffix}.js`;
  35044. ModelManager.load(model, url).catch(() => {
  35045. modelLoadError(editor, url, model);
  35046. });
  35047. }
  35048. };
  35049. const getIconsUrlMetaFromUrl = (editor) =>
  35050. Optional.from(getIconsUrl(editor))
  35051. .filter(isNotEmpty)
  35052. .map((url) => ({
  35053. url,
  35054. name: Optional.none(),
  35055. }));
  35056. const getIconsUrlMetaFromName = (editor, name, suffix) =>
  35057. Optional.from(name)
  35058. .filter((name) => isNotEmpty(name) && !IconManager.has(name))
  35059. .map((name) => ({
  35060. url: `${editor.editorManager.baseURL}/icons/${name}/icons${suffix}.js`,
  35061. name: Optional.some(name),
  35062. }));
  35063. const loadIcons = (scriptLoader, editor, suffix) => {
  35064. const defaultIconsUrl = getIconsUrlMetaFromName(editor, "default", suffix);
  35065. const customIconsUrl = getIconsUrlMetaFromUrl(editor).orThunk(() =>
  35066. getIconsUrlMetaFromName(editor, getIconPackName(editor), "")
  35067. );
  35068. each$e(cat([defaultIconsUrl, customIconsUrl]), (urlMeta) => {
  35069. scriptLoader.add(urlMeta.url).catch(() => {
  35070. iconsLoadError(editor, urlMeta.url, urlMeta.name.getOrUndefined());
  35071. });
  35072. });
  35073. };
  35074. const loadPlugins = (editor, suffix) => {
  35075. const loadPlugin = (name, url) => {
  35076. PluginManager.load(name, url).catch(() => {
  35077. pluginLoadError(editor, url, name);
  35078. });
  35079. };
  35080. each$d(getExternalPlugins$1(editor), (url, name) => {
  35081. loadPlugin(name, url);
  35082. editor.options.set("plugins", getPlugins(editor).concat(name));
  35083. });
  35084. each$e(getPlugins(editor), (plugin) => {
  35085. plugin = Tools.trim(plugin);
  35086. if (plugin && !PluginManager.urls[plugin] && !hasSkipLoadPrefix(plugin)) {
  35087. loadPlugin(plugin, `plugins/${plugin}/plugin${suffix}.js`);
  35088. }
  35089. });
  35090. };
  35091. const isThemeLoaded = (editor) => {
  35092. const theme = getTheme(editor);
  35093. return !isString(theme) || isNonNullable(ThemeManager.get(theme));
  35094. };
  35095. const isModelLoaded = (editor) => {
  35096. const model = getModel(editor);
  35097. return isNonNullable(ModelManager.get(model));
  35098. };
  35099. const loadScripts = (editor, suffix) => {
  35100. const scriptLoader = ScriptLoader.ScriptLoader;
  35101. const initEditor = () => {
  35102. if (!editor.removed && isThemeLoaded(editor) && isModelLoaded(editor)) {
  35103. init(editor);
  35104. }
  35105. };
  35106. loadTheme(editor, suffix);
  35107. loadModel(editor, suffix);
  35108. loadLanguage(scriptLoader, editor);
  35109. loadIcons(scriptLoader, editor, suffix);
  35110. loadPlugins(editor, suffix);
  35111. scriptLoader.loadQueue().then(initEditor, initEditor);
  35112. };
  35113. const getStyleSheetLoader = (element, editor) =>
  35114. instance.forElement(element, {
  35115. contentCssCors: hasContentCssCors(editor),
  35116. referrerPolicy: getReferrerPolicy(editor),
  35117. });
  35118. const render = (editor) => {
  35119. const id = editor.id;
  35120. I18n.setCode(getLanguageCode(editor));
  35121. const readyHandler = () => {
  35122. DOM$3.unbind(window, "ready", readyHandler);
  35123. editor.render();
  35124. };
  35125. if (!EventUtils.Event.domLoaded) {
  35126. DOM$3.bind(window, "ready", readyHandler);
  35127. return;
  35128. }
  35129. if (!editor.getElement()) {
  35130. return;
  35131. }
  35132. const element = SugarElement.fromDom(editor.getElement());
  35133. const snapshot = clone$4(element);
  35134. editor.on("remove", () => {
  35135. eachr(element.dom.attributes, (attr) => remove$a(element, attr.name));
  35136. setAll$1(element, snapshot);
  35137. });
  35138. editor.ui.styleSheetLoader = getStyleSheetLoader(element, editor);
  35139. if (!isInline(editor)) {
  35140. editor.orgVisibility = editor.getElement().style.visibility;
  35141. editor.getElement().style.visibility = "hidden";
  35142. } else {
  35143. editor.inline = true;
  35144. }
  35145. const form = editor.getElement().form || DOM$3.getParent(id, "form");
  35146. if (form) {
  35147. editor.formElement = form;
  35148. if (hasHiddenInput(editor) && !isTextareaOrInput(editor.getElement())) {
  35149. DOM$3.insertAfter(
  35150. DOM$3.create("input", {
  35151. type: "hidden",
  35152. name: id,
  35153. }),
  35154. id
  35155. );
  35156. editor.hasHiddenInput = true;
  35157. }
  35158. editor.formEventDelegate = (e) => {
  35159. editor.dispatch(e.type, e);
  35160. };
  35161. DOM$3.bind(form, "submit reset", editor.formEventDelegate);
  35162. editor.on("reset", () => {
  35163. editor.resetContent();
  35164. });
  35165. if (
  35166. shouldPatchSubmit(editor) &&
  35167. !form.submit.nodeType &&
  35168. !form.submit.length &&
  35169. !form._mceOldSubmit
  35170. ) {
  35171. form._mceOldSubmit = form.submit;
  35172. form.submit = () => {
  35173. editor.editorManager.triggerSave();
  35174. editor.setDirty(false);
  35175. return form._mceOldSubmit(form);
  35176. };
  35177. }
  35178. }
  35179. editor.windowManager = WindowManager(editor);
  35180. editor.notificationManager = NotificationManager(editor);
  35181. if (isEncodingXml(editor)) {
  35182. editor.on("GetContent", (e) => {
  35183. if (e.save) {
  35184. e.content = DOM$3.encode(e.content);
  35185. }
  35186. });
  35187. }
  35188. if (shouldAddFormSubmitTrigger(editor)) {
  35189. editor.on("submit", () => {
  35190. if (editor.initialized) {
  35191. editor.save();
  35192. }
  35193. });
  35194. }
  35195. if (shouldAddUnloadTrigger(editor)) {
  35196. editor._beforeUnload = () => {
  35197. if (editor.initialized && !editor.destroyed && !editor.isHidden()) {
  35198. editor.save({
  35199. format: "raw",
  35200. no_events: true,
  35201. set_dirty: false,
  35202. });
  35203. }
  35204. };
  35205. editor.editorManager.on("BeforeUnload", editor._beforeUnload);
  35206. }
  35207. editor.editorManager.add(editor);
  35208. loadScripts(editor, editor.suffix);
  35209. };
  35210. const setEditableRoot = (editor, state) => {
  35211. if (editor._editableRoot !== state) {
  35212. editor._editableRoot = state;
  35213. if (!editor.readonly) {
  35214. editor.getBody().contentEditable = String(editor.hasEditableRoot());
  35215. editor.nodeChanged();
  35216. }
  35217. fireEditableRootStateChange(editor, state);
  35218. }
  35219. };
  35220. const hasEditableRoot = (editor) => editor._editableRoot;
  35221. const sectionResult = (sections, settings) => ({
  35222. sections: constant(sections),
  35223. options: constant(settings),
  35224. });
  35225. const deviceDetection = detect$2().deviceType;
  35226. const isPhone = deviceDetection.isPhone();
  35227. const isTablet = deviceDetection.isTablet();
  35228. const normalizePlugins = (plugins) => {
  35229. if (isNullable(plugins)) {
  35230. return [];
  35231. } else {
  35232. const pluginNames = isArray$1(plugins) ? plugins : plugins.split(/[ ,]/);
  35233. const trimmedPlugins = map$3(pluginNames, trim$3);
  35234. return filter$5(trimmedPlugins, isNotEmpty);
  35235. }
  35236. };
  35237. const extractSections = (keys, options) => {
  35238. const result = bifilter(options, (value, key) => {
  35239. return contains$2(keys, key);
  35240. });
  35241. return sectionResult(result.t, result.f);
  35242. };
  35243. const getSection = (sectionResult, name, defaults = {}) => {
  35244. const sections = sectionResult.sections();
  35245. const sectionOptions = get$a(sections, name).getOr({});
  35246. return Tools.extend({}, defaults, sectionOptions);
  35247. };
  35248. const hasSection = (sectionResult, name) => {
  35249. return has$2(sectionResult.sections(), name);
  35250. };
  35251. const getSectionConfig = (sectionResult, name) => {
  35252. return hasSection(sectionResult, name)
  35253. ? sectionResult.sections()[name]
  35254. : {};
  35255. };
  35256. const getMobileOverrideOptions = (mobileOptions, isPhone) => {
  35257. const defaultMobileOptions = {
  35258. table_grid: false,
  35259. object_resizing: false,
  35260. resize: false,
  35261. toolbar_mode: get$a(mobileOptions, "toolbar_mode").getOr("scrolling"),
  35262. toolbar_sticky: false,
  35263. };
  35264. const defaultPhoneOptions = { menubar: false };
  35265. return {
  35266. ...defaultMobileOptions,
  35267. ...(isPhone ? defaultPhoneOptions : {}),
  35268. };
  35269. };
  35270. const getExternalPlugins = (overrideOptions, options) => {
  35271. var _a;
  35272. const userDefinedExternalPlugins =
  35273. (_a = options.external_plugins) !== null && _a !== void 0 ? _a : {};
  35274. if (overrideOptions && overrideOptions.external_plugins) {
  35275. return Tools.extend(
  35276. {},
  35277. overrideOptions.external_plugins,
  35278. userDefinedExternalPlugins
  35279. );
  35280. } else {
  35281. return userDefinedExternalPlugins;
  35282. }
  35283. };
  35284. const combinePlugins = (forcedPlugins, plugins) => [
  35285. ...normalizePlugins(forcedPlugins),
  35286. ...normalizePlugins(plugins),
  35287. ];
  35288. const getPlatformPlugins = (
  35289. isMobileDevice,
  35290. sectionResult,
  35291. desktopPlugins,
  35292. mobilePlugins
  35293. ) => {
  35294. if (isMobileDevice && hasSection(sectionResult, "mobile")) {
  35295. return mobilePlugins;
  35296. } else {
  35297. return desktopPlugins;
  35298. }
  35299. };
  35300. const processPlugins = (
  35301. isMobileDevice,
  35302. sectionResult,
  35303. defaultOverrideOptions,
  35304. options
  35305. ) => {
  35306. const forcedPlugins = normalizePlugins(
  35307. defaultOverrideOptions.forced_plugins
  35308. );
  35309. const desktopPlugins = normalizePlugins(options.plugins);
  35310. const mobileConfig = getSectionConfig(sectionResult, "mobile");
  35311. const mobilePlugins = mobileConfig.plugins
  35312. ? normalizePlugins(mobileConfig.plugins)
  35313. : desktopPlugins;
  35314. const platformPlugins = getPlatformPlugins(
  35315. isMobileDevice,
  35316. sectionResult,
  35317. desktopPlugins,
  35318. mobilePlugins
  35319. );
  35320. const combinedPlugins = combinePlugins(forcedPlugins, platformPlugins);
  35321. return Tools.extend(options, {
  35322. forced_plugins: forcedPlugins,
  35323. plugins: combinedPlugins,
  35324. });
  35325. };
  35326. const isOnMobile = (isMobileDevice, sectionResult) => {
  35327. return isMobileDevice && hasSection(sectionResult, "mobile");
  35328. };
  35329. const combineOptions = (
  35330. isMobileDevice,
  35331. isPhone,
  35332. defaultOptions,
  35333. defaultOverrideOptions,
  35334. options
  35335. ) => {
  35336. var _a;
  35337. const deviceOverrideOptions = isMobileDevice
  35338. ? {
  35339. mobile: getMobileOverrideOptions(
  35340. (_a = options.mobile) !== null && _a !== void 0 ? _a : {},
  35341. isPhone
  35342. ),
  35343. }
  35344. : {};
  35345. const sectionResult = extractSections(
  35346. ["mobile"],
  35347. deepMerge(deviceOverrideOptions, options)
  35348. );
  35349. const extendedOptions = Tools.extend(
  35350. defaultOptions,
  35351. defaultOverrideOptions,
  35352. sectionResult.options(),
  35353. isOnMobile(isMobileDevice, sectionResult)
  35354. ? getSection(sectionResult, "mobile")
  35355. : {},
  35356. {
  35357. external_plugins: getExternalPlugins(
  35358. defaultOverrideOptions,
  35359. sectionResult.options()
  35360. ),
  35361. }
  35362. );
  35363. return processPlugins(
  35364. isMobileDevice,
  35365. sectionResult,
  35366. defaultOverrideOptions,
  35367. extendedOptions
  35368. );
  35369. };
  35370. const normalizeOptions = (defaultOverrideOptions, options) =>
  35371. combineOptions(
  35372. isPhone || isTablet,
  35373. isPhone,
  35374. options,
  35375. defaultOverrideOptions,
  35376. options
  35377. );
  35378. const addVisual = (editor, elm) => addVisual$1(editor, elm);
  35379. const registerExecCommands$3 = (editor) => {
  35380. const toggleFormat = (name, value) => {
  35381. editor.formatter.toggle(name, value);
  35382. editor.nodeChanged();
  35383. };
  35384. const toggleAlign = (align) => () => {
  35385. each$e("left,center,right,justify".split(","), (name) => {
  35386. if (align !== name) {
  35387. editor.formatter.remove("align" + name);
  35388. }
  35389. });
  35390. if (align !== "none") {
  35391. toggleFormat("align" + align);
  35392. }
  35393. };
  35394. editor.editorCommands.addCommands({
  35395. JustifyLeft: toggleAlign("left"),
  35396. JustifyCenter: toggleAlign("center"),
  35397. JustifyRight: toggleAlign("right"),
  35398. JustifyFull: toggleAlign("justify"),
  35399. JustifyNone: toggleAlign("none"),
  35400. });
  35401. };
  35402. const registerQueryStateCommands$1 = (editor) => {
  35403. const alignStates = (name) => () => {
  35404. const selection = editor.selection;
  35405. const nodes = selection.isCollapsed()
  35406. ? [editor.dom.getParent(selection.getNode(), editor.dom.isBlock)]
  35407. : selection.getSelectedBlocks();
  35408. return exists(nodes, (node) =>
  35409. isNonNullable(editor.formatter.matchNode(node, name))
  35410. );
  35411. };
  35412. editor.editorCommands.addCommands(
  35413. {
  35414. JustifyLeft: alignStates("alignleft"),
  35415. JustifyCenter: alignStates("aligncenter"),
  35416. JustifyRight: alignStates("alignright"),
  35417. JustifyFull: alignStates("alignjustify"),
  35418. },
  35419. "state"
  35420. );
  35421. };
  35422. const registerCommands$b = (editor) => {
  35423. registerExecCommands$3(editor);
  35424. registerQueryStateCommands$1(editor);
  35425. };
  35426. const registerCommands$a = (editor) => {
  35427. editor.editorCommands.addCommands({
  35428. "Cut,Copy,Paste": (command) => {
  35429. const doc = editor.getDoc();
  35430. let failed;
  35431. try {
  35432. doc.execCommand(command);
  35433. } catch (ex) {
  35434. failed = true;
  35435. }
  35436. if (command === "paste" && !doc.queryCommandEnabled(command)) {
  35437. failed = true;
  35438. }
  35439. if (failed || !doc.queryCommandSupported(command)) {
  35440. let msg = editor.translate(
  35441. `Your browser doesn't support direct access to the clipboard. ` +
  35442. "Please use the Ctrl+X/C/V keyboard shortcuts instead."
  35443. );
  35444. if (Env.os.isMacOS() || Env.os.isiOS()) {
  35445. msg = msg.replace(/Ctrl\+/g, "\u2318+");
  35446. }
  35447. editor.notificationManager.open({
  35448. text: msg,
  35449. type: "error",
  35450. });
  35451. }
  35452. },
  35453. });
  35454. };
  35455. const trimOrPadLeftRight = (dom, rng, html) => {
  35456. const root = SugarElement.fromDom(dom.getRoot());
  35457. if (needsToBeNbspLeft(root, CaretPosition.fromRangeStart(rng))) {
  35458. html = html.replace(/^ /, "&nbsp;");
  35459. } else {
  35460. html = html.replace(/^&nbsp;/, " ");
  35461. }
  35462. if (needsToBeNbspRight(root, CaretPosition.fromRangeEnd(rng))) {
  35463. html = html.replace(/(&nbsp;| )(<br( \/)>)?$/, "&nbsp;");
  35464. } else {
  35465. html = html.replace(/&nbsp;(<br( \/)?>)?$/, " ");
  35466. }
  35467. return html;
  35468. };
  35469. const processValue$1 = (value) => {
  35470. if (typeof value !== "string") {
  35471. const details = Tools.extend(
  35472. {
  35473. paste: value.paste,
  35474. data: { paste: value.paste },
  35475. },
  35476. value
  35477. );
  35478. return {
  35479. content: value.content,
  35480. details,
  35481. };
  35482. }
  35483. return {
  35484. content: value,
  35485. details: {},
  35486. };
  35487. };
  35488. const trimOrPad = (editor, value) => {
  35489. const selection = editor.selection;
  35490. const dom = editor.dom;
  35491. if (/^ | $/.test(value)) {
  35492. return trimOrPadLeftRight(dom, selection.getRng(), value);
  35493. } else {
  35494. return value;
  35495. }
  35496. };
  35497. const insertAtCaret = (editor, value) => {
  35498. if (editor.selection.isEditable()) {
  35499. const { content, details } = processValue$1(value);
  35500. preProcessSetContent(editor, {
  35501. ...details,
  35502. content: trimOrPad(editor, content),
  35503. format: "html",
  35504. set: false,
  35505. selection: true,
  35506. }).each((args) => {
  35507. const insertedContent = insertContent$1(editor, args.content, details);
  35508. postProcessSetContent(editor, insertedContent, args);
  35509. editor.addVisual();
  35510. });
  35511. }
  35512. };
  35513. const registerCommands$9 = (editor) => {
  35514. editor.editorCommands.addCommands({
  35515. mceCleanup: () => {
  35516. const bm = editor.selection.getBookmark();
  35517. editor.setContent(editor.getContent());
  35518. editor.selection.moveToBookmark(bm);
  35519. },
  35520. insertImage: (_command, _ui, value) => {
  35521. insertAtCaret(editor, editor.dom.createHTML("img", { src: value }));
  35522. },
  35523. insertHorizontalRule: () => {
  35524. editor.execCommand("mceInsertContent", false, "<hr>");
  35525. },
  35526. insertText: (_command, _ui, value) => {
  35527. insertAtCaret(editor, editor.dom.encode(value));
  35528. },
  35529. insertHTML: (_command, _ui, value) => {
  35530. insertAtCaret(editor, value);
  35531. },
  35532. mceInsertContent: (_command, _ui, value) => {
  35533. insertAtCaret(editor, value);
  35534. },
  35535. mceSetContent: (_command, _ui, value) => {
  35536. editor.setContent(value);
  35537. },
  35538. mceReplaceContent: (_command, _ui, value) => {
  35539. editor.execCommand(
  35540. "mceInsertContent",
  35541. false,
  35542. value.replace(
  35543. /\{\$selection\}/g,
  35544. editor.selection.getContent({ format: "text" })
  35545. )
  35546. );
  35547. },
  35548. mceNewDocument: () => {
  35549. editor.setContent(getNewDocumentContent(editor));
  35550. },
  35551. });
  35552. };
  35553. const legacyPropNames = {
  35554. "font-size": "size",
  35555. "font-family": "face",
  35556. };
  35557. const isFont = isTag("font");
  35558. const getSpecifiedFontProp = (propName, rootElm, elm) => {
  35559. const getProperty = (elm) =>
  35560. getRaw(elm, propName).orThunk(() => {
  35561. if (isFont(elm)) {
  35562. return get$a(legacyPropNames, propName).bind((legacyPropName) =>
  35563. getOpt(elm, legacyPropName)
  35564. );
  35565. } else {
  35566. return Optional.none();
  35567. }
  35568. });
  35569. const isRoot = (elm) => eq(SugarElement.fromDom(rootElm), elm);
  35570. return closest$1(
  35571. SugarElement.fromDom(elm),
  35572. (elm) => getProperty(elm),
  35573. isRoot
  35574. );
  35575. };
  35576. const normalizeFontFamily = (fontFamily) =>
  35577. fontFamily.replace(/[\'\"\\]/g, "").replace(/,\s+/g, ",");
  35578. const getComputedFontProp = (propName, elm) =>
  35579. Optional.from(DOMUtils.DOM.getStyle(elm, propName, true));
  35580. const getFontProp = (propName) => (rootElm, elm) =>
  35581. Optional.from(elm)
  35582. .map(SugarElement.fromDom)
  35583. .filter(isElement$7)
  35584. .bind((element) =>
  35585. getSpecifiedFontProp(propName, rootElm, element.dom).or(
  35586. getComputedFontProp(propName, element.dom)
  35587. )
  35588. )
  35589. .getOr("");
  35590. const getFontSize = getFontProp("font-size");
  35591. const getFontFamily = compose(
  35592. normalizeFontFamily,
  35593. getFontProp("font-family")
  35594. );
  35595. const findFirstCaretElement = (editor) =>
  35596. firstPositionIn(editor.getBody()).bind((caret) => {
  35597. const container = caret.container();
  35598. return Optional.from(
  35599. isText$a(container) ? container.parentNode : container
  35600. );
  35601. });
  35602. const getCaretElement = (editor) =>
  35603. Optional.from(editor.selection.getRng()).bind((rng) => {
  35604. const root = editor.getBody();
  35605. const atStartOfNode =
  35606. rng.startContainer === root && rng.startOffset === 0;
  35607. return atStartOfNode
  35608. ? Optional.none()
  35609. : Optional.from(editor.selection.getStart(true));
  35610. });
  35611. const bindRange = (editor, binder) =>
  35612. getCaretElement(editor)
  35613. .orThunk(curry(findFirstCaretElement, editor))
  35614. .map(SugarElement.fromDom)
  35615. .filter(isElement$7)
  35616. .bind(binder);
  35617. const mapRange = (editor, mapper) =>
  35618. bindRange(editor, compose1(Optional.some, mapper));
  35619. const fromFontSizeNumber = (editor, value) => {
  35620. if (/^[0-9.]+$/.test(value)) {
  35621. const fontSizeNumber = parseInt(value, 10);
  35622. if (fontSizeNumber >= 1 && fontSizeNumber <= 7) {
  35623. const fontSizes = getFontStyleValues(editor);
  35624. const fontClasses = getFontSizeClasses(editor);
  35625. if (fontClasses.length > 0) {
  35626. return fontClasses[fontSizeNumber - 1] || value;
  35627. } else {
  35628. return fontSizes[fontSizeNumber - 1] || value;
  35629. }
  35630. } else {
  35631. return value;
  35632. }
  35633. } else {
  35634. return value;
  35635. }
  35636. };
  35637. const normalizeFontNames = (font) => {
  35638. const fonts = font.split(/\s*,\s*/);
  35639. return map$3(fonts, (font) => {
  35640. if (
  35641. font.indexOf(" ") !== -1 &&
  35642. !(startsWith(font, '"') || startsWith(font, `'`))
  35643. ) {
  35644. return `'${font}'`;
  35645. } else {
  35646. return font;
  35647. }
  35648. }).join(",");
  35649. };
  35650. const fontNameAction = (editor, value) => {
  35651. const font = fromFontSizeNumber(editor, value);
  35652. editor.formatter.toggle("fontname", { value: normalizeFontNames(font) });
  35653. editor.nodeChanged();
  35654. };
  35655. const fontNameQuery = (editor) =>
  35656. mapRange(editor, (elm) => getFontFamily(editor.getBody(), elm.dom)).getOr(
  35657. ""
  35658. );
  35659. const fontSizeAction = (editor, value) => {
  35660. editor.formatter.toggle("fontsize", {
  35661. value: fromFontSizeNumber(editor, value),
  35662. });
  35663. editor.nodeChanged();
  35664. };
  35665. const fontSizeQuery = (editor) =>
  35666. mapRange(editor, (elm) => getFontSize(editor.getBody(), elm.dom)).getOr("");
  35667. const lineHeightQuery = (editor) =>
  35668. mapRange(editor, (elm) => {
  35669. const root = SugarElement.fromDom(editor.getBody());
  35670. const specifiedStyle = closest$1(
  35671. elm,
  35672. (elm) => getRaw(elm, "line-height"),
  35673. curry(eq, root)
  35674. );
  35675. const computedStyle = () => {
  35676. const lineHeight = parseFloat(get$7(elm, "line-height"));
  35677. const fontSize = parseFloat(get$7(elm, "font-size"));
  35678. return String(lineHeight / fontSize);
  35679. };
  35680. return specifiedStyle.getOrThunk(computedStyle);
  35681. }).getOr("");
  35682. const lineHeightAction = (editor, lineHeight) => {
  35683. editor.formatter.toggle("lineheight", { value: String(lineHeight) });
  35684. editor.nodeChanged();
  35685. };
  35686. const registerExecCommands$2 = (editor) => {
  35687. const toggleFormat = (name, value) => {
  35688. editor.formatter.toggle(name, value);
  35689. editor.nodeChanged();
  35690. };
  35691. editor.editorCommands.addCommands({
  35692. "Bold,Italic,Underline,Strikethrough,Superscript,Subscript": (
  35693. command
  35694. ) => {
  35695. toggleFormat(command);
  35696. },
  35697. "ForeColor,HiliteColor": (command, _ui, value) => {
  35698. toggleFormat(command, { value });
  35699. },
  35700. BackColor: (_command, _ui, value) => {
  35701. toggleFormat("hilitecolor", { value });
  35702. },
  35703. FontName: (_command, _ui, value) => {
  35704. fontNameAction(editor, value);
  35705. },
  35706. FontSize: (_command, _ui, value) => {
  35707. fontSizeAction(editor, value);
  35708. },
  35709. LineHeight: (_command, _ui, value) => {
  35710. lineHeightAction(editor, value);
  35711. },
  35712. Lang: (command, _ui, lang) => {
  35713. var _a;
  35714. toggleFormat(command, {
  35715. value: lang.code,
  35716. customValue:
  35717. (_a = lang.customCode) !== null && _a !== void 0 ? _a : null,
  35718. });
  35719. },
  35720. RemoveFormat: (command) => {
  35721. editor.formatter.remove(command);
  35722. },
  35723. mceBlockQuote: () => {
  35724. toggleFormat("blockquote");
  35725. },
  35726. FormatBlock: (_command, _ui, value) => {
  35727. toggleFormat(isString(value) ? value : "p");
  35728. },
  35729. mceToggleFormat: (_command, _ui, value) => {
  35730. toggleFormat(value);
  35731. },
  35732. });
  35733. };
  35734. const registerQueryValueCommands = (editor) => {
  35735. const isFormatMatch = (name) => editor.formatter.match(name);
  35736. editor.editorCommands.addCommands(
  35737. {
  35738. "Bold,Italic,Underline,Strikethrough,Superscript,Subscript": (
  35739. command
  35740. ) => isFormatMatch(command),
  35741. mceBlockQuote: () => isFormatMatch("blockquote"),
  35742. },
  35743. "state"
  35744. );
  35745. editor.editorCommands.addQueryValueHandler("FontName", () =>
  35746. fontNameQuery(editor)
  35747. );
  35748. editor.editorCommands.addQueryValueHandler("FontSize", () =>
  35749. fontSizeQuery(editor)
  35750. );
  35751. editor.editorCommands.addQueryValueHandler("LineHeight", () =>
  35752. lineHeightQuery(editor)
  35753. );
  35754. };
  35755. const registerCommands$8 = (editor) => {
  35756. registerExecCommands$2(editor);
  35757. registerQueryValueCommands(editor);
  35758. };
  35759. const registerCommands$7 = (editor) => {
  35760. editor.editorCommands.addCommands({
  35761. mceAddUndoLevel: () => {
  35762. editor.undoManager.add();
  35763. },
  35764. mceEndUndoLevel: () => {
  35765. editor.undoManager.add();
  35766. },
  35767. Undo: () => {
  35768. editor.undoManager.undo();
  35769. },
  35770. Redo: () => {
  35771. editor.undoManager.redo();
  35772. },
  35773. });
  35774. };
  35775. const registerCommands$6 = (editor) => {
  35776. editor.editorCommands.addCommands({
  35777. Indent: () => {
  35778. indent(editor);
  35779. },
  35780. Outdent: () => {
  35781. outdent(editor);
  35782. },
  35783. });
  35784. editor.editorCommands.addCommands(
  35785. { Outdent: () => canOutdent(editor) },
  35786. "state"
  35787. );
  35788. };
  35789. const registerCommands$5 = (editor) => {
  35790. const applyLinkToSelection = (_command, _ui, value) => {
  35791. const linkDetails = isString(value) ? { href: value } : value;
  35792. const anchor = editor.dom.getParent(editor.selection.getNode(), "a");
  35793. if (isObject(linkDetails) && isString(linkDetails.href)) {
  35794. linkDetails.href = linkDetails.href.replace(/ /g, "%20");
  35795. if (!anchor || !linkDetails.href) {
  35796. editor.formatter.remove("link");
  35797. }
  35798. if (linkDetails.href) {
  35799. editor.formatter.apply("link", linkDetails, anchor);
  35800. }
  35801. }
  35802. };
  35803. editor.editorCommands.addCommands({
  35804. unlink: () => {
  35805. if (editor.selection.isEditable()) {
  35806. if (editor.selection.isCollapsed()) {
  35807. const elm = editor.dom.getParent(editor.selection.getStart(), "a");
  35808. if (elm) {
  35809. editor.dom.remove(elm, true);
  35810. }
  35811. return;
  35812. }
  35813. editor.formatter.remove("link");
  35814. }
  35815. },
  35816. mceInsertLink: applyLinkToSelection,
  35817. createLink: applyLinkToSelection,
  35818. });
  35819. };
  35820. const registerExecCommands$1 = (editor) => {
  35821. editor.editorCommands.addCommands({
  35822. "InsertUnorderedList,InsertOrderedList": (command) => {
  35823. editor.getDoc().execCommand(command);
  35824. const listElm = editor.dom.getParent(
  35825. editor.selection.getNode(),
  35826. "ol,ul"
  35827. );
  35828. if (listElm) {
  35829. const listParent = listElm.parentNode;
  35830. if (
  35831. listParent &&
  35832. /^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)
  35833. ) {
  35834. const bm = editor.selection.getBookmark();
  35835. editor.dom.split(listParent, listElm);
  35836. editor.selection.moveToBookmark(bm);
  35837. }
  35838. }
  35839. },
  35840. });
  35841. };
  35842. const registerQueryStateCommands = (editor) => {
  35843. editor.editorCommands.addCommands(
  35844. {
  35845. "InsertUnorderedList,InsertOrderedList": (command) => {
  35846. const list = editor.dom.getParent(
  35847. editor.selection.getNode(),
  35848. "ul,ol"
  35849. );
  35850. return (
  35851. list &&
  35852. ((command === "insertunorderedlist" && list.tagName === "UL") ||
  35853. (command === "insertorderedlist" && list.tagName === "OL"))
  35854. );
  35855. },
  35856. },
  35857. "state"
  35858. );
  35859. };
  35860. const registerCommands$4 = (editor) => {
  35861. registerExecCommands$1(editor);
  35862. registerQueryStateCommands(editor);
  35863. };
  35864. const getTopParentBlock = (editor, node, root, container) => {
  35865. const dom = editor.dom;
  35866. const selector = (node) => dom.isBlock(node) && node.parentElement === root;
  35867. const topParentBlock = selector(node)
  35868. ? node
  35869. : dom.getParent(container, selector, root);
  35870. return Optional.from(topParentBlock).map(SugarElement.fromDom);
  35871. };
  35872. const insert = (editor, before) => {
  35873. const dom = editor.dom;
  35874. const rng = editor.selection.getRng();
  35875. const node = before
  35876. ? editor.selection.getStart()
  35877. : editor.selection.getEnd();
  35878. const container = before ? rng.startContainer : rng.endContainer;
  35879. const root = getEditableRoot(dom, container);
  35880. if (!root || !root.isContentEditable) {
  35881. return;
  35882. }
  35883. const insertFn = before ? before$3 : after$4;
  35884. const newBlockName = getForcedRootBlock(editor);
  35885. getTopParentBlock(editor, node, root, container).each((parentBlock) => {
  35886. const newBlock = createNewBlock(
  35887. editor,
  35888. container,
  35889. parentBlock.dom,
  35890. root,
  35891. false,
  35892. newBlockName
  35893. );
  35894. insertFn(parentBlock, SugarElement.fromDom(newBlock));
  35895. editor.selection.setCursorLocation(newBlock, 0);
  35896. editor.dispatch("NewBlock", { newBlock });
  35897. fireInputEvent(editor, "insertParagraph");
  35898. });
  35899. };
  35900. const insertBefore = (editor) => insert(editor, true);
  35901. const insertAfter = (editor) => insert(editor, false);
  35902. const registerCommands$3 = (editor) => {
  35903. editor.editorCommands.addCommands({
  35904. InsertNewBlockBefore: () => {
  35905. insertBefore(editor);
  35906. },
  35907. InsertNewBlockAfter: () => {
  35908. insertAfter(editor);
  35909. },
  35910. });
  35911. };
  35912. const registerCommands$2 = (editor) => {
  35913. editor.editorCommands.addCommands({
  35914. insertParagraph: () => {
  35915. insertBreak(blockbreak, editor);
  35916. },
  35917. mceInsertNewLine: (_command, _ui, value) => {
  35918. insert$1(editor, value);
  35919. },
  35920. InsertLineBreak: (_command, _ui, _value) => {
  35921. insertBreak(linebreak, editor);
  35922. },
  35923. });
  35924. };
  35925. const registerCommands$1 = (editor) => {
  35926. editor.editorCommands.addCommands({
  35927. mceSelectNodeDepth: (_command, _ui, value) => {
  35928. let counter = 0;
  35929. editor.dom.getParent(
  35930. editor.selection.getNode(),
  35931. (node) => {
  35932. if (isElement$6(node) && counter++ === value) {
  35933. editor.selection.select(node);
  35934. return false;
  35935. } else {
  35936. return true;
  35937. }
  35938. },
  35939. editor.getBody()
  35940. );
  35941. },
  35942. mceSelectNode: (_command, _ui, value) => {
  35943. editor.selection.select(value);
  35944. },
  35945. selectAll: () => {
  35946. const editingHost = editor.dom.getParent(
  35947. editor.selection.getStart(),
  35948. isContentEditableTrue$3
  35949. );
  35950. if (editingHost) {
  35951. const rng = editor.dom.createRng();
  35952. rng.selectNodeContents(editingHost);
  35953. editor.selection.setRng(rng);
  35954. }
  35955. },
  35956. });
  35957. };
  35958. const registerExecCommands = (editor) => {
  35959. editor.editorCommands.addCommands({
  35960. mceRemoveNode: (_command, _ui, value) => {
  35961. const node =
  35962. value !== null && value !== void 0
  35963. ? value
  35964. : editor.selection.getNode();
  35965. if (node !== editor.getBody()) {
  35966. const bm = editor.selection.getBookmark();
  35967. editor.dom.remove(node, true);
  35968. editor.selection.moveToBookmark(bm);
  35969. }
  35970. },
  35971. mcePrint: () => {
  35972. editor.getWin().print();
  35973. },
  35974. mceFocus: (_command, _ui, value) => {
  35975. focus(editor, value === true);
  35976. },
  35977. mceToggleVisualAid: () => {
  35978. editor.hasVisual = !editor.hasVisual;
  35979. editor.addVisual();
  35980. },
  35981. });
  35982. };
  35983. const registerCommands = (editor) => {
  35984. registerCommands$b(editor);
  35985. registerCommands$a(editor);
  35986. registerCommands$7(editor);
  35987. registerCommands$1(editor);
  35988. registerCommands$9(editor);
  35989. registerCommands$5(editor);
  35990. registerCommands$6(editor);
  35991. registerCommands$3(editor);
  35992. registerCommands$2(editor);
  35993. registerCommands$4(editor);
  35994. registerCommands$8(editor);
  35995. registerExecCommands(editor);
  35996. };
  35997. const selectionSafeCommands = ["toggleview"];
  35998. const isSelectionSafeCommand = (command) =>
  35999. contains$2(selectionSafeCommands, command.toLowerCase());
  36000. class EditorCommands {
  36001. constructor(editor) {
  36002. this.commands = {
  36003. state: {},
  36004. exec: {},
  36005. value: {},
  36006. };
  36007. this.editor = editor;
  36008. }
  36009. execCommand(command, ui = false, value, args) {
  36010. const editor = this.editor;
  36011. const lowerCaseCommand = command.toLowerCase();
  36012. const skipFocus =
  36013. args === null || args === void 0 ? void 0 : args.skip_focus;
  36014. if (editor.removed) {
  36015. return false;
  36016. }
  36017. if (lowerCaseCommand !== "mcefocus") {
  36018. if (
  36019. !/^(mceAddUndoLevel|mceEndUndoLevel)$/i.test(lowerCaseCommand) &&
  36020. !skipFocus
  36021. ) {
  36022. editor.focus();
  36023. } else {
  36024. restore(editor);
  36025. }
  36026. }
  36027. const eventArgs = editor.dispatch("BeforeExecCommand", {
  36028. command,
  36029. ui,
  36030. value,
  36031. });
  36032. if (eventArgs.isDefaultPrevented()) {
  36033. return false;
  36034. }
  36035. const func = this.commands.exec[lowerCaseCommand];
  36036. if (isFunction(func)) {
  36037. func(lowerCaseCommand, ui, value);
  36038. editor.dispatch("ExecCommand", {
  36039. command,
  36040. ui,
  36041. value,
  36042. });
  36043. return true;
  36044. }
  36045. return false;
  36046. }
  36047. queryCommandState(command) {
  36048. if (
  36049. (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden()) ||
  36050. this.editor.removed
  36051. ) {
  36052. return false;
  36053. }
  36054. const lowerCaseCommand = command.toLowerCase();
  36055. const func = this.commands.state[lowerCaseCommand];
  36056. if (isFunction(func)) {
  36057. return func(lowerCaseCommand);
  36058. }
  36059. return false;
  36060. }
  36061. queryCommandValue(command) {
  36062. if (
  36063. (!isSelectionSafeCommand(command) && this.editor.quirks.isHidden()) ||
  36064. this.editor.removed
  36065. ) {
  36066. return "";
  36067. }
  36068. const lowerCaseCommand = command.toLowerCase();
  36069. const func = this.commands.value[lowerCaseCommand];
  36070. if (isFunction(func)) {
  36071. return func(lowerCaseCommand);
  36072. }
  36073. return "";
  36074. }
  36075. addCommands(commandList, type = "exec") {
  36076. const commands = this.commands;
  36077. each$d(commandList, (callback, command) => {
  36078. each$e(command.toLowerCase().split(","), (command) => {
  36079. commands[type][command] = callback;
  36080. });
  36081. });
  36082. }
  36083. addCommand(command, callback, scope) {
  36084. const lowerCaseCommand = command.toLowerCase();
  36085. this.commands.exec[lowerCaseCommand] = (_command, ui, value) =>
  36086. callback.call(
  36087. scope !== null && scope !== void 0 ? scope : this.editor,
  36088. ui,
  36089. value
  36090. );
  36091. }
  36092. queryCommandSupported(command) {
  36093. const lowerCaseCommand = command.toLowerCase();
  36094. if (this.commands.exec[lowerCaseCommand]) {
  36095. return true;
  36096. } else {
  36097. return false;
  36098. }
  36099. }
  36100. addQueryStateHandler(command, callback, scope) {
  36101. this.commands.state[command.toLowerCase()] = () =>
  36102. callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
  36103. }
  36104. addQueryValueHandler(command, callback, scope) {
  36105. this.commands.value[command.toLowerCase()] = () =>
  36106. callback.call(scope !== null && scope !== void 0 ? scope : this.editor);
  36107. }
  36108. }
  36109. const internalContentEditableAttr = "data-mce-contenteditable";
  36110. const toggleClass = (elm, cls, state) => {
  36111. if (has(elm, cls) && !state) {
  36112. remove$7(elm, cls);
  36113. } else if (state) {
  36114. add$2(elm, cls);
  36115. }
  36116. };
  36117. const setEditorCommandState = (editor, cmd, state) => {
  36118. try {
  36119. editor.getDoc().execCommand(cmd, false, String(state));
  36120. } catch (ex) {}
  36121. };
  36122. const setContentEditable = (elm, state) => {
  36123. elm.dom.contentEditable = state ? "true" : "false";
  36124. };
  36125. const switchOffContentEditableTrue = (elm) => {
  36126. each$e(descendants(elm, '*[contenteditable="true"]'), (elm) => {
  36127. set$3(elm, internalContentEditableAttr, "true");
  36128. setContentEditable(elm, false);
  36129. });
  36130. };
  36131. const switchOnContentEditableTrue = (elm) => {
  36132. each$e(
  36133. descendants(elm, `*[${internalContentEditableAttr}="true"]`),
  36134. (elm) => {
  36135. remove$a(elm, internalContentEditableAttr);
  36136. setContentEditable(elm, true);
  36137. }
  36138. );
  36139. };
  36140. const removeFakeSelection = (editor) => {
  36141. Optional.from(editor.selection.getNode()).each((elm) => {
  36142. elm.removeAttribute("data-mce-selected");
  36143. });
  36144. };
  36145. const restoreFakeSelection = (editor) => {
  36146. editor.selection.setRng(editor.selection.getRng());
  36147. };
  36148. const toggleReadOnly = (editor, state) => {
  36149. const body = SugarElement.fromDom(editor.getBody());
  36150. toggleClass(body, "mce-content-readonly", state);
  36151. if (state) {
  36152. editor.selection.controlSelection.hideResizeRect();
  36153. editor._selectionOverrides.hideFakeCaret();
  36154. removeFakeSelection(editor);
  36155. editor.readonly = true;
  36156. setContentEditable(body, false);
  36157. switchOffContentEditableTrue(body);
  36158. } else {
  36159. editor.readonly = false;
  36160. if (editor.hasEditableRoot()) {
  36161. setContentEditable(body, true);
  36162. }
  36163. switchOnContentEditableTrue(body);
  36164. setEditorCommandState(editor, "StyleWithCSS", false);
  36165. setEditorCommandState(editor, "enableInlineTableEditing", false);
  36166. setEditorCommandState(editor, "enableObjectResizing", false);
  36167. if (hasEditorOrUiFocus(editor)) {
  36168. editor.focus();
  36169. }
  36170. restoreFakeSelection(editor);
  36171. editor.nodeChanged();
  36172. }
  36173. };
  36174. const isReadOnly = (editor) => editor.readonly;
  36175. const registerFilters = (editor) => {
  36176. editor.parser.addAttributeFilter("contenteditable", (nodes) => {
  36177. if (isReadOnly(editor)) {
  36178. each$e(nodes, (node) => {
  36179. node.attr(internalContentEditableAttr, node.attr("contenteditable"));
  36180. node.attr("contenteditable", "false");
  36181. });
  36182. }
  36183. });
  36184. editor.serializer.addAttributeFilter(
  36185. internalContentEditableAttr,
  36186. (nodes) => {
  36187. if (isReadOnly(editor)) {
  36188. each$e(nodes, (node) => {
  36189. node.attr(
  36190. "contenteditable",
  36191. node.attr(internalContentEditableAttr)
  36192. );
  36193. });
  36194. }
  36195. }
  36196. );
  36197. editor.serializer.addTempAttr(internalContentEditableAttr);
  36198. };
  36199. const registerReadOnlyContentFilters = (editor) => {
  36200. if (editor.serializer) {
  36201. registerFilters(editor);
  36202. } else {
  36203. editor.on("PreInit", () => {
  36204. registerFilters(editor);
  36205. });
  36206. }
  36207. };
  36208. const isClickEvent = (e) => e.type === "click";
  36209. const allowedEvents = ["copy"];
  36210. const isReadOnlyAllowedEvent = (e) => contains$2(allowedEvents, e.type);
  36211. const getAnchorHrefOpt = (editor, elm) => {
  36212. const isRoot = (elm) => eq(elm, SugarElement.fromDom(editor.getBody()));
  36213. return closest$3(elm, "a", isRoot).bind((a) => getOpt(a, "href"));
  36214. };
  36215. const processReadonlyEvents = (editor, e) => {
  36216. if (isClickEvent(e) && !VK.metaKeyPressed(e)) {
  36217. const elm = SugarElement.fromDom(e.target);
  36218. getAnchorHrefOpt(editor, elm).each((href) => {
  36219. e.preventDefault();
  36220. if (/^#/.test(href)) {
  36221. const targetEl = editor.dom.select(
  36222. `${href},[name="${removeLeading(href, "#")}"]`
  36223. );
  36224. if (targetEl.length) {
  36225. editor.selection.scrollIntoView(targetEl[0], true);
  36226. }
  36227. } else {
  36228. window.open(
  36229. href,
  36230. "_blank",
  36231. "rel=noopener noreferrer,menubar=yes,toolbar=yes,location=yes,status=yes,resizable=yes,scrollbars=yes"
  36232. );
  36233. }
  36234. });
  36235. } else if (isReadOnlyAllowedEvent(e)) {
  36236. editor.dispatch(e.type, e);
  36237. }
  36238. };
  36239. const registerReadOnlySelectionBlockers = (editor) => {
  36240. editor.on("ShowCaret", (e) => {
  36241. if (isReadOnly(editor)) {
  36242. e.preventDefault();
  36243. }
  36244. });
  36245. editor.on("ObjectSelected", (e) => {
  36246. if (isReadOnly(editor)) {
  36247. e.preventDefault();
  36248. }
  36249. });
  36250. };
  36251. const nativeEvents = Tools.makeMap(
  36252. "focus blur focusin focusout click dblclick mousedown mouseup mousemove mouseover beforepaste paste cut copy selectionchange " +
  36253. "mouseout mouseenter mouseleave wheel keydown keypress keyup input beforeinput contextmenu dragstart dragend dragover " +
  36254. "draggesture dragdrop drop drag submit " +
  36255. "compositionstart compositionend compositionupdate touchstart touchmove touchend touchcancel",
  36256. " "
  36257. );
  36258. class EventDispatcher {
  36259. static isNative(name) {
  36260. return !!nativeEvents[name.toLowerCase()];
  36261. }
  36262. constructor(settings) {
  36263. this.bindings = {};
  36264. this.settings = settings || {};
  36265. this.scope = this.settings.scope || this;
  36266. this.toggleEvent = this.settings.toggleEvent || never;
  36267. }
  36268. fire(name, args) {
  36269. return this.dispatch(name, args);
  36270. }
  36271. dispatch(name, args) {
  36272. const lcName = name.toLowerCase();
  36273. const event = normalize$3(
  36274. lcName,
  36275. args !== null && args !== void 0 ? args : {},
  36276. this.scope
  36277. );
  36278. if (this.settings.beforeFire) {
  36279. this.settings.beforeFire(event);
  36280. }
  36281. const handlers = this.bindings[lcName];
  36282. if (handlers) {
  36283. for (let i = 0, l = handlers.length; i < l; i++) {
  36284. const callback = handlers[i];
  36285. if (callback.removed) {
  36286. continue;
  36287. }
  36288. if (callback.once) {
  36289. this.off(lcName, callback.func);
  36290. }
  36291. if (event.isImmediatePropagationStopped()) {
  36292. return event;
  36293. }
  36294. if (callback.func.call(this.scope, event) === false) {
  36295. event.preventDefault();
  36296. return event;
  36297. }
  36298. }
  36299. }
  36300. return event;
  36301. }
  36302. on(name, callback, prepend, extra) {
  36303. if (callback === false) {
  36304. callback = never;
  36305. }
  36306. if (callback) {
  36307. const wrappedCallback = {
  36308. func: callback,
  36309. removed: false,
  36310. };
  36311. if (extra) {
  36312. Tools.extend(wrappedCallback, extra);
  36313. }
  36314. const names = name.toLowerCase().split(" ");
  36315. let i = names.length;
  36316. while (i--) {
  36317. const currentName = names[i];
  36318. let handlers = this.bindings[currentName];
  36319. if (!handlers) {
  36320. handlers = [];
  36321. this.toggleEvent(currentName, true);
  36322. }
  36323. if (prepend) {
  36324. handlers = [wrappedCallback, ...handlers];
  36325. } else {
  36326. handlers = [...handlers, wrappedCallback];
  36327. }
  36328. this.bindings[currentName] = handlers;
  36329. }
  36330. }
  36331. return this;
  36332. }
  36333. off(name, callback) {
  36334. if (name) {
  36335. const names = name.toLowerCase().split(" ");
  36336. let i = names.length;
  36337. while (i--) {
  36338. const currentName = names[i];
  36339. let handlers = this.bindings[currentName];
  36340. if (!currentName) {
  36341. each$d(this.bindings, (_value, bindingName) => {
  36342. this.toggleEvent(bindingName, false);
  36343. delete this.bindings[bindingName];
  36344. });
  36345. return this;
  36346. }
  36347. if (handlers) {
  36348. if (!callback) {
  36349. handlers.length = 0;
  36350. } else {
  36351. const filteredHandlers = partition$2(
  36352. handlers,
  36353. (handler) => handler.func === callback
  36354. );
  36355. handlers = filteredHandlers.fail;
  36356. this.bindings[currentName] = handlers;
  36357. each$e(filteredHandlers.pass, (handler) => {
  36358. handler.removed = true;
  36359. });
  36360. }
  36361. if (!handlers.length) {
  36362. this.toggleEvent(name, false);
  36363. delete this.bindings[currentName];
  36364. }
  36365. }
  36366. }
  36367. } else {
  36368. each$d(this.bindings, (_value, name) => {
  36369. this.toggleEvent(name, false);
  36370. });
  36371. this.bindings = {};
  36372. }
  36373. return this;
  36374. }
  36375. once(name, callback, prepend) {
  36376. return this.on(name, callback, prepend, { once: true });
  36377. }
  36378. has(name) {
  36379. name = name.toLowerCase();
  36380. const binding = this.bindings[name];
  36381. return !(!binding || binding.length === 0);
  36382. }
  36383. }
  36384. const getEventDispatcher = (obj) => {
  36385. if (!obj._eventDispatcher) {
  36386. obj._eventDispatcher = new EventDispatcher({
  36387. scope: obj,
  36388. toggleEvent: (name, state) => {
  36389. if (EventDispatcher.isNative(name) && obj.toggleNativeEvent) {
  36390. obj.toggleNativeEvent(name, state);
  36391. }
  36392. },
  36393. });
  36394. }
  36395. return obj._eventDispatcher;
  36396. };
  36397. const Observable = {
  36398. fire(name, args, bubble) {
  36399. return this.dispatch(name, args, bubble);
  36400. },
  36401. dispatch(name, args, bubble) {
  36402. const self = this;
  36403. if (self.removed && name !== "remove" && name !== "detach") {
  36404. return normalize$3(
  36405. name.toLowerCase(),
  36406. args !== null && args !== void 0 ? args : {},
  36407. self
  36408. );
  36409. }
  36410. const dispatcherArgs = getEventDispatcher(self).dispatch(name, args);
  36411. if (bubble !== false && self.parent) {
  36412. let parent = self.parent();
  36413. while (parent && !dispatcherArgs.isPropagationStopped()) {
  36414. parent.dispatch(name, dispatcherArgs, false);
  36415. parent = parent.parent ? parent.parent() : undefined;
  36416. }
  36417. }
  36418. return dispatcherArgs;
  36419. },
  36420. on(name, callback, prepend) {
  36421. return getEventDispatcher(this).on(name, callback, prepend);
  36422. },
  36423. off(name, callback) {
  36424. return getEventDispatcher(this).off(name, callback);
  36425. },
  36426. once(name, callback) {
  36427. return getEventDispatcher(this).once(name, callback);
  36428. },
  36429. hasEventListeners(name) {
  36430. return getEventDispatcher(this).has(name);
  36431. },
  36432. };
  36433. const DOM$2 = DOMUtils.DOM;
  36434. let customEventRootDelegates;
  36435. const getEventTarget = (editor, eventName) => {
  36436. if (eventName === "selectionchange") {
  36437. return editor.getDoc();
  36438. }
  36439. if (
  36440. !editor.inline &&
  36441. /^(?:mouse|touch|click|contextmenu|drop|dragover|dragend)/.test(eventName)
  36442. ) {
  36443. return editor.getDoc().documentElement;
  36444. }
  36445. const eventRoot = getEventRoot(editor);
  36446. if (eventRoot) {
  36447. if (!editor.eventRoot) {
  36448. editor.eventRoot = DOM$2.select(eventRoot)[0];
  36449. }
  36450. return editor.eventRoot;
  36451. }
  36452. return editor.getBody();
  36453. };
  36454. const isListening = (editor) => !editor.hidden && !isReadOnly(editor);
  36455. const fireEvent = (editor, eventName, e) => {
  36456. if (isListening(editor)) {
  36457. editor.dispatch(eventName, e);
  36458. } else if (isReadOnly(editor)) {
  36459. processReadonlyEvents(editor, e);
  36460. }
  36461. };
  36462. const bindEventDelegate = (editor, eventName) => {
  36463. if (!editor.delegates) {
  36464. editor.delegates = {};
  36465. }
  36466. if (editor.delegates[eventName] || editor.removed) {
  36467. return;
  36468. }
  36469. const eventRootElm = getEventTarget(editor, eventName);
  36470. if (getEventRoot(editor)) {
  36471. if (!customEventRootDelegates) {
  36472. customEventRootDelegates = {};
  36473. editor.editorManager.on("removeEditor", () => {
  36474. if (!editor.editorManager.activeEditor) {
  36475. if (customEventRootDelegates) {
  36476. each$d(customEventRootDelegates, (_value, name) => {
  36477. editor.dom.unbind(getEventTarget(editor, name));
  36478. });
  36479. customEventRootDelegates = null;
  36480. }
  36481. }
  36482. });
  36483. }
  36484. if (customEventRootDelegates[eventName]) {
  36485. return;
  36486. }
  36487. const delegate = (e) => {
  36488. const target = e.target;
  36489. const editors = editor.editorManager.get();
  36490. let i = editors.length;
  36491. while (i--) {
  36492. const body = editors[i].getBody();
  36493. if (body === target || DOM$2.isChildOf(target, body)) {
  36494. fireEvent(editors[i], eventName, e);
  36495. }
  36496. }
  36497. };
  36498. customEventRootDelegates[eventName] = delegate;
  36499. DOM$2.bind(eventRootElm, eventName, delegate);
  36500. } else {
  36501. const delegate = (e) => {
  36502. fireEvent(editor, eventName, e);
  36503. };
  36504. DOM$2.bind(eventRootElm, eventName, delegate);
  36505. editor.delegates[eventName] = delegate;
  36506. }
  36507. };
  36508. const EditorObservable = {
  36509. ...Observable,
  36510. bindPendingEventDelegates() {
  36511. const self = this;
  36512. Tools.each(self._pendingNativeEvents, (name) => {
  36513. bindEventDelegate(self, name);
  36514. });
  36515. },
  36516. toggleNativeEvent(name, state) {
  36517. const self = this;
  36518. if (name === "focus" || name === "blur") {
  36519. return;
  36520. }
  36521. if (self.removed) {
  36522. return;
  36523. }
  36524. if (state) {
  36525. if (self.initialized) {
  36526. bindEventDelegate(self, name);
  36527. } else {
  36528. if (!self._pendingNativeEvents) {
  36529. self._pendingNativeEvents = [name];
  36530. } else {
  36531. self._pendingNativeEvents.push(name);
  36532. }
  36533. }
  36534. } else if (self.initialized && self.delegates) {
  36535. self.dom.unbind(getEventTarget(self, name), name, self.delegates[name]);
  36536. delete self.delegates[name];
  36537. }
  36538. },
  36539. unbindAllNativeEvents() {
  36540. const self = this;
  36541. const body = self.getBody();
  36542. const dom = self.dom;
  36543. if (self.delegates) {
  36544. each$d(self.delegates, (value, name) => {
  36545. self.dom.unbind(getEventTarget(self, name), name, value);
  36546. });
  36547. delete self.delegates;
  36548. }
  36549. if (!self.inline && body && dom) {
  36550. body.onload = null;
  36551. dom.unbind(self.getWin());
  36552. dom.unbind(self.getDoc());
  36553. }
  36554. if (dom) {
  36555. dom.unbind(body);
  36556. dom.unbind(self.getContainer());
  36557. }
  36558. },
  36559. };
  36560. const stringListProcessor = (value) => {
  36561. if (isString(value)) {
  36562. return {
  36563. value: value.split(/[ ,]/),
  36564. valid: true,
  36565. };
  36566. } else if (isArrayOf(value, isString)) {
  36567. return {
  36568. value,
  36569. valid: true,
  36570. };
  36571. } else {
  36572. return {
  36573. valid: false,
  36574. message: `The value must be a string[] or a comma/space separated string.`,
  36575. };
  36576. }
  36577. };
  36578. const getBuiltInProcessor = (type) => {
  36579. const validator = (() => {
  36580. switch (type) {
  36581. case "array":
  36582. return isArray$1;
  36583. case "boolean":
  36584. return isBoolean;
  36585. case "function":
  36586. return isFunction;
  36587. case "number":
  36588. return isNumber;
  36589. case "object":
  36590. return isObject;
  36591. case "string":
  36592. return isString;
  36593. case "string[]":
  36594. return stringListProcessor;
  36595. case "object[]":
  36596. return (val) => isArrayOf(val, isObject);
  36597. case "regexp":
  36598. return (val) => is$4(val, RegExp);
  36599. default:
  36600. return always;
  36601. }
  36602. })();
  36603. return (value) =>
  36604. processValue(value, validator, `The value must be a ${type}.`);
  36605. };
  36606. const isBuiltInSpec = (spec) => isString(spec.processor);
  36607. const getErrorMessage = (message, result) => {
  36608. const additionalText = isEmpty$3(result.message)
  36609. ? ""
  36610. : `. ${result.message}`;
  36611. return message + additionalText;
  36612. };
  36613. const isValidResult = (result) => result.valid;
  36614. const processValue = (value, processor, message = "") => {
  36615. const result = processor(value);
  36616. if (isBoolean(result)) {
  36617. return result
  36618. ? {
  36619. value: value,
  36620. valid: true,
  36621. }
  36622. : {
  36623. valid: false,
  36624. message,
  36625. };
  36626. } else {
  36627. return result;
  36628. }
  36629. };
  36630. const processDefaultValue = (name, defaultValue, processor) => {
  36631. if (!isUndefined(defaultValue)) {
  36632. const result = processValue(defaultValue, processor);
  36633. if (isValidResult(result)) {
  36634. return result.value;
  36635. } else {
  36636. console.error(
  36637. getErrorMessage(
  36638. `Invalid default value passed for the "${name}" option`,
  36639. result
  36640. )
  36641. );
  36642. }
  36643. }
  36644. return undefined;
  36645. };
  36646. const create$5 = (editor, initialOptions) => {
  36647. const registry = {};
  36648. const values = {};
  36649. const setValue = (name, value, processor) => {
  36650. const result = processValue(value, processor);
  36651. if (isValidResult(result)) {
  36652. values[name] = result.value;
  36653. return true;
  36654. } else {
  36655. console.warn(
  36656. getErrorMessage(`Invalid value passed for the ${name} option`, result)
  36657. );
  36658. return false;
  36659. }
  36660. };
  36661. const register = (name, spec) => {
  36662. const processor = isBuiltInSpec(spec)
  36663. ? getBuiltInProcessor(spec.processor)
  36664. : spec.processor;
  36665. const defaultValue = processDefaultValue(name, spec.default, processor);
  36666. registry[name] = {
  36667. ...spec,
  36668. default: defaultValue,
  36669. processor,
  36670. };
  36671. const initValue = get$a(values, name).orThunk(() =>
  36672. get$a(initialOptions, name)
  36673. );
  36674. initValue.each((value) => setValue(name, value, processor));
  36675. };
  36676. const isRegistered = (name) => has$2(registry, name);
  36677. const get = (name) =>
  36678. get$a(values, name)
  36679. .orThunk(() => get$a(registry, name).map((spec) => spec.default))
  36680. .getOrUndefined();
  36681. const set = (name, value) => {
  36682. if (!isRegistered(name)) {
  36683. console.warn(
  36684. `"${name}" is not a registered option. Ensure the option has been registered before setting a value.`
  36685. );
  36686. return false;
  36687. } else {
  36688. const spec = registry[name];
  36689. if (spec.immutable) {
  36690. console.error(
  36691. `"${name}" is an immutable option and cannot be updated`
  36692. );
  36693. return false;
  36694. } else {
  36695. return setValue(name, value, spec.processor);
  36696. }
  36697. }
  36698. };
  36699. const unset = (name) => {
  36700. const registered = isRegistered(name);
  36701. if (registered) {
  36702. delete values[name];
  36703. }
  36704. return registered;
  36705. };
  36706. const isSet = (name) => has$2(values, name);
  36707. return {
  36708. register,
  36709. isRegistered,
  36710. get,
  36711. set,
  36712. unset,
  36713. isSet,
  36714. };
  36715. };
  36716. const defaultModes = ["design", "readonly"];
  36717. const switchToMode = (editor, activeMode, availableModes, mode) => {
  36718. const oldMode = availableModes[activeMode.get()];
  36719. const newMode = availableModes[mode];
  36720. try {
  36721. newMode.activate();
  36722. } catch (e) {
  36723. console.error(`problem while activating editor mode ${mode}:`, e);
  36724. return;
  36725. }
  36726. oldMode.deactivate();
  36727. if (oldMode.editorReadOnly !== newMode.editorReadOnly) {
  36728. toggleReadOnly(editor, newMode.editorReadOnly);
  36729. }
  36730. activeMode.set(mode);
  36731. fireSwitchMode(editor, mode);
  36732. };
  36733. const setMode = (editor, availableModes, activeMode, mode) => {
  36734. if (mode === activeMode.get()) {
  36735. return;
  36736. } else if (!has$2(availableModes, mode)) {
  36737. throw new Error(`Editor mode '${mode}' is invalid`);
  36738. }
  36739. if (editor.initialized) {
  36740. switchToMode(editor, activeMode, availableModes, mode);
  36741. } else {
  36742. editor.on("init", () =>
  36743. switchToMode(editor, activeMode, availableModes, mode)
  36744. );
  36745. }
  36746. };
  36747. const registerMode = (availableModes, mode, api) => {
  36748. if (contains$2(defaultModes, mode)) {
  36749. throw new Error(`Cannot override default mode ${mode}`);
  36750. }
  36751. return {
  36752. ...availableModes,
  36753. [mode]: {
  36754. ...api,
  36755. deactivate: () => {
  36756. try {
  36757. api.deactivate();
  36758. } catch (e) {
  36759. console.error(`problem while deactivating editor mode ${mode}:`, e);
  36760. }
  36761. },
  36762. },
  36763. };
  36764. };
  36765. const create$4 = (editor) => {
  36766. const activeMode = Cell("design");
  36767. const availableModes = Cell({
  36768. design: {
  36769. activate: noop,
  36770. deactivate: noop,
  36771. editorReadOnly: false,
  36772. },
  36773. readonly: {
  36774. activate: noop,
  36775. deactivate: noop,
  36776. editorReadOnly: true,
  36777. },
  36778. });
  36779. registerReadOnlyContentFilters(editor);
  36780. registerReadOnlySelectionBlockers(editor);
  36781. return {
  36782. isReadOnly: () => isReadOnly(editor),
  36783. set: (mode) => setMode(editor, availableModes.get(), activeMode, mode),
  36784. get: () => activeMode.get(),
  36785. register: (mode, api) => {
  36786. availableModes.set(registerMode(availableModes.get(), mode, api));
  36787. },
  36788. };
  36789. };
  36790. const each$2 = Tools.each,
  36791. explode = Tools.explode;
  36792. const keyCodeLookup = {
  36793. f1: 112,
  36794. f2: 113,
  36795. f3: 114,
  36796. f4: 115,
  36797. f5: 116,
  36798. f6: 117,
  36799. f7: 118,
  36800. f8: 119,
  36801. f9: 120,
  36802. f10: 121,
  36803. f11: 122,
  36804. f12: 123,
  36805. };
  36806. const modifierNames = Tools.makeMap("alt,ctrl,shift,meta,access");
  36807. const isModifier = (key) => key in modifierNames;
  36808. const parseShortcut = (pattern) => {
  36809. const shortcut = {};
  36810. const isMac = Env.os.isMacOS() || Env.os.isiOS();
  36811. each$2(explode(pattern.toLowerCase(), "+"), (value) => {
  36812. if (isModifier(value)) {
  36813. shortcut[value] = true;
  36814. } else {
  36815. if (/^[0-9]{2,}$/.test(value)) {
  36816. shortcut.keyCode = parseInt(value, 10);
  36817. } else {
  36818. shortcut.charCode = value.charCodeAt(0);
  36819. shortcut.keyCode =
  36820. keyCodeLookup[value] || value.toUpperCase().charCodeAt(0);
  36821. }
  36822. }
  36823. });
  36824. const id = [shortcut.keyCode];
  36825. let key;
  36826. for (key in modifierNames) {
  36827. if (shortcut[key]) {
  36828. id.push(key);
  36829. } else {
  36830. shortcut[key] = false;
  36831. }
  36832. }
  36833. shortcut.id = id.join(",");
  36834. if (shortcut.access) {
  36835. shortcut.alt = true;
  36836. if (isMac) {
  36837. shortcut.ctrl = true;
  36838. } else {
  36839. shortcut.shift = true;
  36840. }
  36841. }
  36842. if (shortcut.meta) {
  36843. if (isMac) {
  36844. shortcut.meta = true;
  36845. } else {
  36846. shortcut.ctrl = true;
  36847. shortcut.meta = false;
  36848. }
  36849. }
  36850. return shortcut;
  36851. };
  36852. class Shortcuts {
  36853. constructor(editor) {
  36854. this.shortcuts = {};
  36855. this.pendingPatterns = [];
  36856. this.editor = editor;
  36857. const self = this;
  36858. editor.on("keyup keypress keydown", (e) => {
  36859. if (
  36860. (self.hasModifier(e) || self.isFunctionKey(e)) &&
  36861. !e.isDefaultPrevented()
  36862. ) {
  36863. each$2(self.shortcuts, (shortcut) => {
  36864. if (self.matchShortcut(e, shortcut)) {
  36865. self.pendingPatterns = shortcut.subpatterns.slice(0);
  36866. if (e.type === "keydown") {
  36867. self.executeShortcutAction(shortcut);
  36868. }
  36869. }
  36870. });
  36871. if (self.matchShortcut(e, self.pendingPatterns[0])) {
  36872. if (self.pendingPatterns.length === 1) {
  36873. if (e.type === "keydown") {
  36874. self.executeShortcutAction(self.pendingPatterns[0]);
  36875. }
  36876. }
  36877. self.pendingPatterns.shift();
  36878. }
  36879. }
  36880. });
  36881. }
  36882. add(pattern, desc, cmdFunc, scope) {
  36883. const self = this;
  36884. const func = self.normalizeCommandFunc(cmdFunc);
  36885. each$2(explode(Tools.trim(pattern)), (pattern) => {
  36886. const shortcut = self.createShortcut(pattern, desc, func, scope);
  36887. self.shortcuts[shortcut.id] = shortcut;
  36888. });
  36889. return true;
  36890. }
  36891. remove(pattern) {
  36892. const shortcut = this.createShortcut(pattern);
  36893. if (this.shortcuts[shortcut.id]) {
  36894. delete this.shortcuts[shortcut.id];
  36895. return true;
  36896. }
  36897. return false;
  36898. }
  36899. normalizeCommandFunc(cmdFunc) {
  36900. const self = this;
  36901. const cmd = cmdFunc;
  36902. if (typeof cmd === "string") {
  36903. return () => {
  36904. self.editor.execCommand(cmd, false, null);
  36905. };
  36906. } else if (Tools.isArray(cmd)) {
  36907. return () => {
  36908. self.editor.execCommand(cmd[0], cmd[1], cmd[2]);
  36909. };
  36910. } else {
  36911. return cmd;
  36912. }
  36913. }
  36914. createShortcut(pattern, desc, cmdFunc, scope) {
  36915. const shortcuts = Tools.map(explode(pattern, ">"), parseShortcut);
  36916. shortcuts[shortcuts.length - 1] = Tools.extend(
  36917. shortcuts[shortcuts.length - 1],
  36918. {
  36919. func: cmdFunc,
  36920. scope: scope || this.editor,
  36921. }
  36922. );
  36923. return Tools.extend(shortcuts[0], {
  36924. desc: this.editor.translate(desc),
  36925. subpatterns: shortcuts.slice(1),
  36926. });
  36927. }
  36928. hasModifier(e) {
  36929. return e.altKey || e.ctrlKey || e.metaKey;
  36930. }
  36931. isFunctionKey(e) {
  36932. return e.type === "keydown" && e.keyCode >= 112 && e.keyCode <= 123;
  36933. }
  36934. matchShortcut(e, shortcut) {
  36935. if (!shortcut) {
  36936. return false;
  36937. }
  36938. if (shortcut.ctrl !== e.ctrlKey || shortcut.meta !== e.metaKey) {
  36939. return false;
  36940. }
  36941. if (shortcut.alt !== e.altKey || shortcut.shift !== e.shiftKey) {
  36942. return false;
  36943. }
  36944. if (
  36945. e.keyCode === shortcut.keyCode ||
  36946. (e.charCode && e.charCode === shortcut.charCode)
  36947. ) {
  36948. e.preventDefault();
  36949. return true;
  36950. }
  36951. return false;
  36952. }
  36953. executeShortcutAction(shortcut) {
  36954. return shortcut.func ? shortcut.func.call(shortcut.scope) : null;
  36955. }
  36956. }
  36957. const create$3 = () => {
  36958. const buttons = {};
  36959. const menuItems = {};
  36960. const popups = {};
  36961. const icons = {};
  36962. const contextMenus = {};
  36963. const contextToolbars = {};
  36964. const sidebars = {};
  36965. const views = {};
  36966. const add = (collection, type) => (name, spec) => {
  36967. collection[name.toLowerCase()] = {
  36968. ...spec,
  36969. type,
  36970. };
  36971. };
  36972. const addIcon = (name, svgData) => (icons[name.toLowerCase()] = svgData);
  36973. return {
  36974. addButton: add(buttons, "button"),
  36975. addGroupToolbarButton: add(buttons, "grouptoolbarbutton"),
  36976. addToggleButton: add(buttons, "togglebutton"),
  36977. addMenuButton: add(buttons, "menubutton"),
  36978. addSplitButton: add(buttons, "splitbutton"),
  36979. addMenuItem: add(menuItems, "menuitem"),
  36980. addNestedMenuItem: add(menuItems, "nestedmenuitem"),
  36981. addToggleMenuItem: add(menuItems, "togglemenuitem"),
  36982. addAutocompleter: add(popups, "autocompleter"),
  36983. addContextMenu: add(contextMenus, "contextmenu"),
  36984. addContextToolbar: add(contextToolbars, "contexttoolbar"),
  36985. addContextForm: add(contextToolbars, "contextform"),
  36986. addSidebar: add(sidebars, "sidebar"),
  36987. addView: add(views, "views"),
  36988. addIcon,
  36989. getAll: () => ({
  36990. buttons,
  36991. menuItems,
  36992. icons,
  36993. popups,
  36994. contextMenus,
  36995. contextToolbars,
  36996. sidebars,
  36997. views,
  36998. }),
  36999. };
  37000. };
  37001. const registry = () => {
  37002. const bridge = create$3();
  37003. return {
  37004. addAutocompleter: bridge.addAutocompleter,
  37005. addButton: bridge.addButton,
  37006. addContextForm: bridge.addContextForm,
  37007. addContextMenu: bridge.addContextMenu,
  37008. addContextToolbar: bridge.addContextToolbar,
  37009. addIcon: bridge.addIcon,
  37010. addMenuButton: bridge.addMenuButton,
  37011. addMenuItem: bridge.addMenuItem,
  37012. addNestedMenuItem: bridge.addNestedMenuItem,
  37013. addSidebar: bridge.addSidebar,
  37014. addSplitButton: bridge.addSplitButton,
  37015. addToggleButton: bridge.addToggleButton,
  37016. addGroupToolbarButton: bridge.addGroupToolbarButton,
  37017. addToggleMenuItem: bridge.addToggleMenuItem,
  37018. addView: bridge.addView,
  37019. getAll: bridge.getAll,
  37020. };
  37021. };
  37022. const DOM$1 = DOMUtils.DOM;
  37023. const extend = Tools.extend,
  37024. each$1 = Tools.each;
  37025. class Editor {
  37026. constructor(id, options, editorManager) {
  37027. this.plugins = {};
  37028. this.contentCSS = [];
  37029. this.contentStyles = [];
  37030. this.loadedCSS = {};
  37031. this.isNotDirty = false;
  37032. this.composing = false;
  37033. this.destroyed = false;
  37034. this.hasHiddenInput = false;
  37035. this.iframeElement = null;
  37036. this.initialized = false;
  37037. this.readonly = false;
  37038. this.removed = false;
  37039. this.startContent = "";
  37040. this._pendingNativeEvents = [];
  37041. this._skinLoaded = false;
  37042. this._editableRoot = true;
  37043. this.editorManager = editorManager;
  37044. this.documentBaseUrl = editorManager.documentBaseURL;
  37045. extend(this, EditorObservable);
  37046. const self = this;
  37047. this.id = id;
  37048. this.hidden = false;
  37049. const normalizedOptions = normalizeOptions(
  37050. editorManager.defaultOptions,
  37051. options
  37052. );
  37053. this.options = create$5(self, normalizedOptions);
  37054. register$7(self);
  37055. const getOption = this.options.get;
  37056. if (getOption("deprecation_warnings")) {
  37057. logWarnings(options, normalizedOptions);
  37058. }
  37059. const suffix = getOption("suffix");
  37060. if (suffix) {
  37061. editorManager.suffix = suffix;
  37062. }
  37063. this.suffix = editorManager.suffix;
  37064. const baseUrl = getOption("base_url");
  37065. if (baseUrl) {
  37066. editorManager._setBaseUrl(baseUrl);
  37067. }
  37068. this.baseUri = editorManager.baseURI;
  37069. const referrerPolicy = getReferrerPolicy(self);
  37070. if (referrerPolicy) {
  37071. ScriptLoader.ScriptLoader._setReferrerPolicy(referrerPolicy);
  37072. DOMUtils.DOM.styleSheetLoader._setReferrerPolicy(referrerPolicy);
  37073. }
  37074. const contentCssCors = hasContentCssCors(self);
  37075. if (isNonNullable(contentCssCors)) {
  37076. DOMUtils.DOM.styleSheetLoader._setContentCssCors(contentCssCors);
  37077. }
  37078. AddOnManager.languageLoad = getOption("language_load");
  37079. AddOnManager.baseURL = editorManager.baseURL;
  37080. this.setDirty(false);
  37081. this.documentBaseURI = new URI(getDocumentBaseUrl(self), {
  37082. base_uri: this.baseUri,
  37083. });
  37084. this.baseURI = this.baseUri;
  37085. this.inline = isInline(self);
  37086. this.hasVisual = isVisualAidsEnabled(self);
  37087. this.shortcuts = new Shortcuts(this);
  37088. this.editorCommands = new EditorCommands(this);
  37089. registerCommands(this);
  37090. const cacheSuffix = getOption("cache_suffix");
  37091. if (cacheSuffix) {
  37092. Env.cacheSuffix = cacheSuffix.replace(/^[\?\&]+/, "");
  37093. }
  37094. this.ui = {
  37095. registry: registry(),
  37096. styleSheetLoader: undefined,
  37097. show: noop,
  37098. hide: noop,
  37099. setEnabled: noop,
  37100. isEnabled: always,
  37101. };
  37102. this.mode = create$4(self);
  37103. editorManager.dispatch("SetupEditor", { editor: this });
  37104. const setupCallback = getSetupCallback(self);
  37105. if (isFunction(setupCallback)) {
  37106. setupCallback.call(self, self);
  37107. }
  37108. }
  37109. render() {
  37110. render(this);
  37111. }
  37112. focus(skipFocus) {
  37113. this.execCommand("mceFocus", false, skipFocus);
  37114. }
  37115. hasFocus() {
  37116. return hasFocus(this);
  37117. }
  37118. translate(text) {
  37119. return I18n.translate(text);
  37120. }
  37121. getParam(name, defaultVal, type) {
  37122. const options = this.options;
  37123. if (!options.isRegistered(name)) {
  37124. if (isNonNullable(type)) {
  37125. options.register(name, {
  37126. processor: type,
  37127. default: defaultVal,
  37128. });
  37129. } else {
  37130. options.register(name, {
  37131. processor: always,
  37132. default: defaultVal,
  37133. });
  37134. }
  37135. }
  37136. return !options.isSet(name) && !isUndefined(defaultVal)
  37137. ? defaultVal
  37138. : options.get(name);
  37139. }
  37140. hasPlugin(name, loaded) {
  37141. const hasPlugin = contains$2(getPlugins(this), name);
  37142. if (hasPlugin) {
  37143. return loaded ? PluginManager.get(name) !== undefined : true;
  37144. } else {
  37145. return false;
  37146. }
  37147. }
  37148. nodeChanged(args) {
  37149. this._nodeChangeDispatcher.nodeChanged(args);
  37150. }
  37151. addCommand(name, callback, scope) {
  37152. this.editorCommands.addCommand(name, callback, scope);
  37153. }
  37154. addQueryStateHandler(name, callback, scope) {
  37155. this.editorCommands.addQueryStateHandler(name, callback, scope);
  37156. }
  37157. addQueryValueHandler(name, callback, scope) {
  37158. this.editorCommands.addQueryValueHandler(name, callback, scope);
  37159. }
  37160. addShortcut(pattern, desc, cmdFunc, scope) {
  37161. this.shortcuts.add(pattern, desc, cmdFunc, scope);
  37162. }
  37163. execCommand(cmd, ui, value, args) {
  37164. return this.editorCommands.execCommand(cmd, ui, value, args);
  37165. }
  37166. queryCommandState(cmd) {
  37167. return this.editorCommands.queryCommandState(cmd);
  37168. }
  37169. queryCommandValue(cmd) {
  37170. return this.editorCommands.queryCommandValue(cmd);
  37171. }
  37172. queryCommandSupported(cmd) {
  37173. return this.editorCommands.queryCommandSupported(cmd);
  37174. }
  37175. show() {
  37176. const self = this;
  37177. if (self.hidden) {
  37178. self.hidden = false;
  37179. if (self.inline) {
  37180. self.getBody().contentEditable = "true";
  37181. } else {
  37182. DOM$1.show(self.getContainer());
  37183. DOM$1.hide(self.id);
  37184. }
  37185. self.load();
  37186. self.dispatch("show");
  37187. }
  37188. }
  37189. hide() {
  37190. const self = this;
  37191. if (!self.hidden) {
  37192. self.save();
  37193. if (self.inline) {
  37194. self.getBody().contentEditable = "false";
  37195. if (self === self.editorManager.focusedEditor) {
  37196. self.editorManager.focusedEditor = null;
  37197. }
  37198. } else {
  37199. DOM$1.hide(self.getContainer());
  37200. DOM$1.setStyle(self.id, "display", self.orgDisplay);
  37201. }
  37202. self.hidden = true;
  37203. self.dispatch("hide");
  37204. }
  37205. }
  37206. isHidden() {
  37207. return this.hidden;
  37208. }
  37209. setProgressState(state, time) {
  37210. this.dispatch("ProgressState", {
  37211. state,
  37212. time,
  37213. });
  37214. }
  37215. load(args = {}) {
  37216. const self = this;
  37217. const elm = self.getElement();
  37218. if (self.removed) {
  37219. return "";
  37220. }
  37221. if (elm) {
  37222. const loadArgs = {
  37223. ...args,
  37224. load: true,
  37225. };
  37226. const value = isTextareaOrInput(elm) ? elm.value : elm.innerHTML;
  37227. const html = self.setContent(value, loadArgs);
  37228. if (!loadArgs.no_events) {
  37229. self.dispatch("LoadContent", {
  37230. ...loadArgs,
  37231. element: elm,
  37232. });
  37233. }
  37234. return html;
  37235. } else {
  37236. return "";
  37237. }
  37238. }
  37239. save(args = {}) {
  37240. const self = this;
  37241. let elm = self.getElement();
  37242. if (!elm || !self.initialized || self.removed) {
  37243. return "";
  37244. }
  37245. const getArgs = {
  37246. ...args,
  37247. save: true,
  37248. element: elm,
  37249. };
  37250. let html = self.getContent(getArgs);
  37251. const saveArgs = {
  37252. ...getArgs,
  37253. content: html,
  37254. };
  37255. if (!saveArgs.no_events) {
  37256. self.dispatch("SaveContent", saveArgs);
  37257. }
  37258. if (saveArgs.format === "raw") {
  37259. self.dispatch("RawSaveContent", saveArgs);
  37260. }
  37261. html = saveArgs.content;
  37262. if (!isTextareaOrInput(elm)) {
  37263. if (args.is_removing || !self.inline) {
  37264. elm.innerHTML = html;
  37265. }
  37266. const form = DOM$1.getParent(self.id, "form");
  37267. if (form) {
  37268. each$1(form.elements, (elm) => {
  37269. if (elm.name === self.id) {
  37270. elm.value = html;
  37271. return false;
  37272. } else {
  37273. return true;
  37274. }
  37275. });
  37276. }
  37277. } else {
  37278. elm.value = html;
  37279. }
  37280. saveArgs.element = getArgs.element = elm = null;
  37281. if (saveArgs.set_dirty !== false) {
  37282. self.setDirty(false);
  37283. }
  37284. return html;
  37285. }
  37286. setContent(content, args) {
  37287. return setContent(this, content, args);
  37288. }
  37289. getContent(args) {
  37290. return getContent(this, args);
  37291. }
  37292. insertContent(content, args) {
  37293. if (args) {
  37294. content = extend({ content }, args);
  37295. }
  37296. this.execCommand("mceInsertContent", false, content);
  37297. }
  37298. resetContent(initialContent) {
  37299. if (initialContent === undefined) {
  37300. setContent(this, this.startContent, { format: "raw" });
  37301. } else {
  37302. setContent(this, initialContent);
  37303. }
  37304. this.undoManager.reset();
  37305. this.setDirty(false);
  37306. this.nodeChanged();
  37307. }
  37308. isDirty() {
  37309. return !this.isNotDirty;
  37310. }
  37311. setDirty(state) {
  37312. const oldState = !this.isNotDirty;
  37313. this.isNotDirty = !state;
  37314. if (state && state !== oldState) {
  37315. this.dispatch("dirty");
  37316. }
  37317. }
  37318. getContainer() {
  37319. const self = this;
  37320. if (!self.container) {
  37321. self.container = self.editorContainer || DOM$1.get(self.id + "_parent");
  37322. }
  37323. return self.container;
  37324. }
  37325. getContentAreaContainer() {
  37326. return this.contentAreaContainer;
  37327. }
  37328. getElement() {
  37329. if (!this.targetElm) {
  37330. this.targetElm = DOM$1.get(this.id);
  37331. }
  37332. return this.targetElm;
  37333. }
  37334. getWin() {
  37335. const self = this;
  37336. if (!self.contentWindow) {
  37337. const elm = self.iframeElement;
  37338. if (elm) {
  37339. self.contentWindow = elm.contentWindow;
  37340. }
  37341. }
  37342. return self.contentWindow;
  37343. }
  37344. getDoc() {
  37345. const self = this;
  37346. if (!self.contentDocument) {
  37347. const win = self.getWin();
  37348. if (win) {
  37349. self.contentDocument = win.document;
  37350. }
  37351. }
  37352. return self.contentDocument;
  37353. }
  37354. getBody() {
  37355. var _a, _b;
  37356. const doc = this.getDoc();
  37357. return (_b =
  37358. (_a = this.bodyElement) !== null && _a !== void 0
  37359. ? _a
  37360. : doc === null || doc === void 0
  37361. ? void 0
  37362. : doc.body) !== null && _b !== void 0
  37363. ? _b
  37364. : null;
  37365. }
  37366. convertURL(url, name, elm) {
  37367. const self = this,
  37368. getOption = self.options.get;
  37369. const urlConverterCallback = getUrlConverterCallback(self);
  37370. if (isFunction(urlConverterCallback)) {
  37371. return urlConverterCallback.call(self, url, elm, true, name);
  37372. }
  37373. if (
  37374. !getOption("convert_urls") ||
  37375. elm === "link" ||
  37376. (isObject(elm) && elm.nodeName === "LINK") ||
  37377. url.indexOf("file:") === 0 ||
  37378. url.length === 0
  37379. ) {
  37380. return url;
  37381. }
  37382. if (getOption("relative_urls")) {
  37383. return self.documentBaseURI.toRelative(url);
  37384. }
  37385. url = self.documentBaseURI.toAbsolute(
  37386. url,
  37387. getOption("remove_script_host")
  37388. );
  37389. return url;
  37390. }
  37391. addVisual(elm) {
  37392. addVisual(this, elm);
  37393. }
  37394. setEditableRoot(state) {
  37395. setEditableRoot(this, state);
  37396. }
  37397. hasEditableRoot() {
  37398. return hasEditableRoot(this);
  37399. }
  37400. remove() {
  37401. remove$1(this);
  37402. }
  37403. destroy(automatic) {
  37404. destroy(this, automatic);
  37405. }
  37406. uploadImages() {
  37407. return this.editorUpload.uploadImages();
  37408. }
  37409. _scanForImages() {
  37410. return this.editorUpload.scanForImages();
  37411. }
  37412. }
  37413. const DOM = DOMUtils.DOM;
  37414. const each = Tools.each;
  37415. let boundGlobalEvents = false;
  37416. let beforeUnloadDelegate;
  37417. let editors = [];
  37418. const globalEventDelegate = (e) => {
  37419. const type = e.type;
  37420. each(EditorManager.get(), (editor) => {
  37421. switch (type) {
  37422. case "scroll":
  37423. editor.dispatch("ScrollWindow", e);
  37424. break;
  37425. case "resize":
  37426. editor.dispatch("ResizeWindow", e);
  37427. break;
  37428. }
  37429. });
  37430. };
  37431. const toggleGlobalEvents = (state) => {
  37432. if (state !== boundGlobalEvents) {
  37433. const DOM = DOMUtils.DOM;
  37434. if (state) {
  37435. DOM.bind(window, "resize", globalEventDelegate);
  37436. DOM.bind(window, "scroll", globalEventDelegate);
  37437. } else {
  37438. DOM.unbind(window, "resize", globalEventDelegate);
  37439. DOM.unbind(window, "scroll", globalEventDelegate);
  37440. }
  37441. boundGlobalEvents = state;
  37442. }
  37443. };
  37444. const removeEditorFromList = (targetEditor) => {
  37445. const oldEditors = editors;
  37446. editors = filter$5(editors, (editor) => {
  37447. return targetEditor !== editor;
  37448. });
  37449. if (EditorManager.activeEditor === targetEditor) {
  37450. EditorManager.activeEditor = editors.length > 0 ? editors[0] : null;
  37451. }
  37452. if (EditorManager.focusedEditor === targetEditor) {
  37453. EditorManager.focusedEditor = null;
  37454. }
  37455. return oldEditors.length !== editors.length;
  37456. };
  37457. const purgeDestroyedEditor = (editor) => {
  37458. if (
  37459. editor &&
  37460. editor.initialized &&
  37461. !(editor.getContainer() || editor.getBody()).parentNode
  37462. ) {
  37463. removeEditorFromList(editor);
  37464. editor.unbindAllNativeEvents();
  37465. editor.destroy(true);
  37466. editor.removed = true;
  37467. }
  37468. };
  37469. const isQuirksMode = document.compatMode !== "CSS1Compat";
  37470. const EditorManager = {
  37471. ...Observable,
  37472. baseURI: null,
  37473. baseURL: null,
  37474. defaultOptions: {},
  37475. documentBaseURL: null,
  37476. suffix: null,
  37477. majorVersion: "6",
  37478. minorVersion: "7.0",
  37479. releaseDate: "2023-08-30",
  37480. i18n: I18n,
  37481. activeEditor: null,
  37482. focusedEditor: null,
  37483. setup() {
  37484. const self = this;
  37485. let baseURL = "";
  37486. let suffix = "";
  37487. let documentBaseURL = URI.getDocumentBaseUrl(document.location);
  37488. if (/^[^:]+:\/\/\/?[^\/]+\//.test(documentBaseURL)) {
  37489. documentBaseURL = documentBaseURL
  37490. .replace(/[\?#].*$/, "")
  37491. .replace(/[\/\\][^\/]+$/, "");
  37492. if (!/[\/\\]$/.test(documentBaseURL)) {
  37493. documentBaseURL += "/";
  37494. }
  37495. }
  37496. const preInit = window.tinymce || window.tinyMCEPreInit;
  37497. if (preInit) {
  37498. baseURL = preInit.base || preInit.baseURL;
  37499. suffix = preInit.suffix;
  37500. } else {
  37501. const scripts = document.getElementsByTagName("script");
  37502. for (let i = 0; i < scripts.length; i++) {
  37503. const src = scripts[i].src || "";
  37504. if (src === "") {
  37505. continue;
  37506. }
  37507. const srcScript = src.substring(src.lastIndexOf("/"));
  37508. if (/tinymce(\.full|\.jquery|)(\.min|\.dev|)\.js/.test(src)) {
  37509. if (srcScript.indexOf(".min") !== -1) {
  37510. suffix = ".min";
  37511. }
  37512. baseURL = src.substring(0, src.lastIndexOf("/"));
  37513. break;
  37514. }
  37515. }
  37516. if (!baseURL && document.currentScript) {
  37517. const src = document.currentScript.src;
  37518. if (src.indexOf(".min") !== -1) {
  37519. suffix = ".min";
  37520. }
  37521. baseURL = src.substring(0, src.lastIndexOf("/"));
  37522. }
  37523. }
  37524. self.baseURL = new URI(documentBaseURL).toAbsolute(baseURL);
  37525. self.documentBaseURL = documentBaseURL;
  37526. self.baseURI = new URI(self.baseURL);
  37527. self.suffix = suffix;
  37528. setup$v(self);
  37529. },
  37530. overrideDefaults(defaultOptions) {
  37531. const baseUrl = defaultOptions.base_url;
  37532. if (baseUrl) {
  37533. this._setBaseUrl(baseUrl);
  37534. }
  37535. const suffix = defaultOptions.suffix;
  37536. if (suffix) {
  37537. this.suffix = suffix;
  37538. }
  37539. this.defaultOptions = defaultOptions;
  37540. const pluginBaseUrls = defaultOptions.plugin_base_urls;
  37541. if (pluginBaseUrls !== undefined) {
  37542. each$d(pluginBaseUrls, (pluginBaseUrl, pluginName) => {
  37543. AddOnManager.PluginManager.urls[pluginName] = pluginBaseUrl;
  37544. });
  37545. }
  37546. },
  37547. init(options) {
  37548. const self = this;
  37549. let result;
  37550. const invalidInlineTargets = Tools.makeMap(
  37551. "area base basefont br col frame hr img input isindex link meta param embed source wbr track " +
  37552. "colgroup option table tbody tfoot thead tr th td script noscript style textarea video audio iframe object menu",
  37553. " "
  37554. );
  37555. const isInvalidInlineTarget = (options, elm) =>
  37556. options.inline && elm.tagName.toLowerCase() in invalidInlineTargets;
  37557. const createId = (elm) => {
  37558. let id = elm.id;
  37559. if (!id) {
  37560. id = get$a(elm, "name")
  37561. .filter((name) => !DOM.get(name))
  37562. .getOrThunk(DOM.uniqueId);
  37563. elm.setAttribute("id", id);
  37564. }
  37565. return id;
  37566. };
  37567. const execCallback = (name) => {
  37568. const callback = options[name];
  37569. if (!callback) {
  37570. return;
  37571. }
  37572. return callback.apply(self, []);
  37573. };
  37574. const findTargets = (options) => {
  37575. if (Env.browser.isIE() || Env.browser.isEdge()) {
  37576. initError(
  37577. "TinyMCE does not support the browser you are using. For a list of supported" +
  37578. " browsers please see: https://www.tiny.cloud/docs/tinymce/6/support/#supportedwebbrowsers"
  37579. );
  37580. return [];
  37581. } else if (isQuirksMode) {
  37582. initError(
  37583. "Failed to initialize the editor as the document is not in standards mode. " +
  37584. "TinyMCE requires standards mode."
  37585. );
  37586. return [];
  37587. } else if (isString(options.selector)) {
  37588. return DOM.select(options.selector);
  37589. } else if (isNonNullable(options.target)) {
  37590. return [options.target];
  37591. } else {
  37592. return [];
  37593. }
  37594. };
  37595. let provideResults = (editors) => {
  37596. result = editors;
  37597. };
  37598. const initEditors = () => {
  37599. let initCount = 0;
  37600. const editors = [];
  37601. let targets;
  37602. const createEditor = (id, options, targetElm) => {
  37603. const editor = new Editor(id, options, self);
  37604. editors.push(editor);
  37605. editor.on("init", () => {
  37606. if (++initCount === targets.length) {
  37607. provideResults(editors);
  37608. }
  37609. });
  37610. editor.targetElm = editor.targetElm || targetElm;
  37611. editor.render();
  37612. };
  37613. DOM.unbind(window, "ready", initEditors);
  37614. execCallback("onpageload");
  37615. targets = unique$1(findTargets(options));
  37616. Tools.each(targets, (elm) => {
  37617. purgeDestroyedEditor(self.get(elm.id));
  37618. });
  37619. targets = Tools.grep(targets, (elm) => {
  37620. return !self.get(elm.id);
  37621. });
  37622. if (targets.length === 0) {
  37623. provideResults([]);
  37624. } else {
  37625. each(targets, (elm) => {
  37626. if (isInvalidInlineTarget(options, elm)) {
  37627. initError(
  37628. "Could not initialize inline editor on invalid inline target element",
  37629. elm
  37630. );
  37631. } else {
  37632. createEditor(createId(elm), options, elm);
  37633. }
  37634. });
  37635. }
  37636. };
  37637. DOM.bind(window, "ready", initEditors);
  37638. return new Promise((resolve) => {
  37639. if (result) {
  37640. resolve(result);
  37641. } else {
  37642. provideResults = (editors) => {
  37643. resolve(editors);
  37644. };
  37645. }
  37646. });
  37647. },
  37648. get(id) {
  37649. if (arguments.length === 0) {
  37650. return editors.slice(0);
  37651. } else if (isString(id)) {
  37652. return find$2(editors, (editor) => {
  37653. return editor.id === id;
  37654. }).getOr(null);
  37655. } else if (isNumber(id)) {
  37656. return editors[id] ? editors[id] : null;
  37657. } else {
  37658. return null;
  37659. }
  37660. },
  37661. add(editor) {
  37662. const self = this;
  37663. const existingEditor = self.get(editor.id);
  37664. if (existingEditor === editor) {
  37665. return editor;
  37666. }
  37667. if (existingEditor === null) {
  37668. editors.push(editor);
  37669. }
  37670. toggleGlobalEvents(true);
  37671. self.activeEditor = editor;
  37672. self.dispatch("AddEditor", { editor });
  37673. if (!beforeUnloadDelegate) {
  37674. beforeUnloadDelegate = (e) => {
  37675. const event = self.dispatch("BeforeUnload");
  37676. if (event.returnValue) {
  37677. e.preventDefault();
  37678. e.returnValue = event.returnValue;
  37679. return event.returnValue;
  37680. }
  37681. };
  37682. window.addEventListener("beforeunload", beforeUnloadDelegate);
  37683. }
  37684. return editor;
  37685. },
  37686. createEditor(id, options) {
  37687. return this.add(new Editor(id, options, this));
  37688. },
  37689. remove(selector) {
  37690. const self = this;
  37691. let editor;
  37692. if (!selector) {
  37693. for (let i = editors.length - 1; i >= 0; i--) {
  37694. self.remove(editors[i]);
  37695. }
  37696. return;
  37697. }
  37698. if (isString(selector)) {
  37699. each(DOM.select(selector), (elm) => {
  37700. editor = self.get(elm.id);
  37701. if (editor) {
  37702. self.remove(editor);
  37703. }
  37704. });
  37705. return;
  37706. }
  37707. editor = selector;
  37708. if (isNull(self.get(editor.id))) {
  37709. return null;
  37710. }
  37711. if (removeEditorFromList(editor)) {
  37712. self.dispatch("RemoveEditor", { editor });
  37713. }
  37714. if (editors.length === 0) {
  37715. window.removeEventListener("beforeunload", beforeUnloadDelegate);
  37716. }
  37717. editor.remove();
  37718. toggleGlobalEvents(editors.length > 0);
  37719. return editor;
  37720. },
  37721. execCommand(cmd, ui, value) {
  37722. var _a;
  37723. const self = this;
  37724. const editorId = isObject(value)
  37725. ? (_a = value.id) !== null && _a !== void 0
  37726. ? _a
  37727. : value.index
  37728. : value;
  37729. switch (cmd) {
  37730. case "mceAddEditor": {
  37731. if (!self.get(editorId)) {
  37732. const editorOptions = value.options;
  37733. new Editor(editorId, editorOptions, self).render();
  37734. }
  37735. return true;
  37736. }
  37737. case "mceRemoveEditor": {
  37738. const editor = self.get(editorId);
  37739. if (editor) {
  37740. editor.remove();
  37741. }
  37742. return true;
  37743. }
  37744. case "mceToggleEditor": {
  37745. const editor = self.get(editorId);
  37746. if (!editor) {
  37747. self.execCommand("mceAddEditor", false, value);
  37748. return true;
  37749. }
  37750. if (editor.isHidden()) {
  37751. editor.show();
  37752. } else {
  37753. editor.hide();
  37754. }
  37755. return true;
  37756. }
  37757. }
  37758. if (self.activeEditor) {
  37759. return self.activeEditor.execCommand(cmd, ui, value);
  37760. }
  37761. return false;
  37762. },
  37763. triggerSave: () => {
  37764. each(editors, (editor) => {
  37765. editor.save();
  37766. });
  37767. },
  37768. addI18n: (code, items) => {
  37769. I18n.add(code, items);
  37770. },
  37771. translate: (text) => {
  37772. return I18n.translate(text);
  37773. },
  37774. setActive(editor) {
  37775. const activeEditor = this.activeEditor;
  37776. if (this.activeEditor !== editor) {
  37777. if (activeEditor) {
  37778. activeEditor.dispatch("deactivate", { relatedTarget: editor });
  37779. }
  37780. editor.dispatch("activate", { relatedTarget: activeEditor });
  37781. }
  37782. this.activeEditor = editor;
  37783. },
  37784. _setBaseUrl(baseUrl) {
  37785. this.baseURL = new URI(this.documentBaseURL).toAbsolute(
  37786. baseUrl.replace(/\/+$/, "")
  37787. );
  37788. this.baseURI = new URI(this.baseURL);
  37789. },
  37790. };
  37791. EditorManager.setup();
  37792. const setup = () => {
  37793. const dataValue = value$2();
  37794. const FakeClipboardItem = (items) => ({
  37795. items,
  37796. types: keys(items),
  37797. getType: (type) => get$a(items, type).getOrUndefined(),
  37798. });
  37799. const write = (data) => {
  37800. dataValue.set(data);
  37801. };
  37802. const read = () => dataValue.get().getOrUndefined();
  37803. const clear = dataValue.clear;
  37804. return {
  37805. FakeClipboardItem,
  37806. write,
  37807. read,
  37808. clear,
  37809. };
  37810. };
  37811. const FakeClipboard = setup();
  37812. const min = Math.min,
  37813. max = Math.max,
  37814. round = Math.round;
  37815. const relativePosition = (rect, targetRect, rel) => {
  37816. let x = targetRect.x;
  37817. let y = targetRect.y;
  37818. const w = rect.w;
  37819. const h = rect.h;
  37820. const targetW = targetRect.w;
  37821. const targetH = targetRect.h;
  37822. const relChars = (rel || "").split("");
  37823. if (relChars[0] === "b") {
  37824. y += targetH;
  37825. }
  37826. if (relChars[1] === "r") {
  37827. x += targetW;
  37828. }
  37829. if (relChars[0] === "c") {
  37830. y += round(targetH / 2);
  37831. }
  37832. if (relChars[1] === "c") {
  37833. x += round(targetW / 2);
  37834. }
  37835. if (relChars[3] === "b") {
  37836. y -= h;
  37837. }
  37838. if (relChars[4] === "r") {
  37839. x -= w;
  37840. }
  37841. if (relChars[3] === "c") {
  37842. y -= round(h / 2);
  37843. }
  37844. if (relChars[4] === "c") {
  37845. x -= round(w / 2);
  37846. }
  37847. return create$2(x, y, w, h);
  37848. };
  37849. const findBestRelativePosition = (rect, targetRect, constrainRect, rels) => {
  37850. for (let i = 0; i < rels.length; i++) {
  37851. const pos = relativePosition(rect, targetRect, rels[i]);
  37852. if (
  37853. pos.x >= constrainRect.x &&
  37854. pos.x + pos.w <= constrainRect.w + constrainRect.x &&
  37855. pos.y >= constrainRect.y &&
  37856. pos.y + pos.h <= constrainRect.h + constrainRect.y
  37857. ) {
  37858. return rels[i];
  37859. }
  37860. }
  37861. return null;
  37862. };
  37863. const inflate = (rect, w, h) => {
  37864. return create$2(rect.x - w, rect.y - h, rect.w + w * 2, rect.h + h * 2);
  37865. };
  37866. const intersect = (rect, cropRect) => {
  37867. const x1 = max(rect.x, cropRect.x);
  37868. const y1 = max(rect.y, cropRect.y);
  37869. const x2 = min(rect.x + rect.w, cropRect.x + cropRect.w);
  37870. const y2 = min(rect.y + rect.h, cropRect.y + cropRect.h);
  37871. if (x2 - x1 < 0 || y2 - y1 < 0) {
  37872. return null;
  37873. }
  37874. return create$2(x1, y1, x2 - x1, y2 - y1);
  37875. };
  37876. const clamp = (rect, clampRect, fixedSize) => {
  37877. let x1 = rect.x;
  37878. let y1 = rect.y;
  37879. let x2 = rect.x + rect.w;
  37880. let y2 = rect.y + rect.h;
  37881. const cx2 = clampRect.x + clampRect.w;
  37882. const cy2 = clampRect.y + clampRect.h;
  37883. const underflowX1 = max(0, clampRect.x - x1);
  37884. const underflowY1 = max(0, clampRect.y - y1);
  37885. const overflowX2 = max(0, x2 - cx2);
  37886. const overflowY2 = max(0, y2 - cy2);
  37887. x1 += underflowX1;
  37888. y1 += underflowY1;
  37889. if (fixedSize) {
  37890. x2 += underflowX1;
  37891. y2 += underflowY1;
  37892. x1 -= overflowX2;
  37893. y1 -= overflowY2;
  37894. }
  37895. x2 -= overflowX2;
  37896. y2 -= overflowY2;
  37897. return create$2(x1, y1, x2 - x1, y2 - y1);
  37898. };
  37899. const create$2 = (x, y, w, h) => {
  37900. return {
  37901. x,
  37902. y,
  37903. w,
  37904. h,
  37905. };
  37906. };
  37907. const fromClientRect = (clientRect) => {
  37908. return create$2(
  37909. clientRect.left,
  37910. clientRect.top,
  37911. clientRect.width,
  37912. clientRect.height
  37913. );
  37914. };
  37915. const Rect = {
  37916. inflate,
  37917. relativePosition,
  37918. findBestRelativePosition,
  37919. intersect,
  37920. clamp,
  37921. create: create$2,
  37922. fromClientRect,
  37923. };
  37924. const awaiter = (resolveCb, rejectCb, timeout = 1000) => {
  37925. let done = false;
  37926. let timer = null;
  37927. const complete =
  37928. (completer) =>
  37929. (...args) => {
  37930. if (!done) {
  37931. done = true;
  37932. if (timer !== null) {
  37933. clearTimeout(timer);
  37934. timer = null;
  37935. }
  37936. completer.apply(null, args);
  37937. }
  37938. };
  37939. const resolve = complete(resolveCb);
  37940. const reject = complete(rejectCb);
  37941. const start = (...args) => {
  37942. if (!done && timer === null) {
  37943. timer = setTimeout(() => reject.apply(null, args), timeout);
  37944. }
  37945. };
  37946. return {
  37947. start,
  37948. resolve,
  37949. reject,
  37950. };
  37951. };
  37952. const create$1 = () => {
  37953. const tasks = {};
  37954. const resultFns = {};
  37955. const load = (id, url) => {
  37956. const loadErrMsg = `Script at URL "${url}" failed to load`;
  37957. const runErrMsg = `Script at URL "${url}" did not call \`tinymce.Resource.add('${id}', data)\` within 1 second`;
  37958. if (tasks[id] !== undefined) {
  37959. return tasks[id];
  37960. } else {
  37961. const task = new Promise((resolve, reject) => {
  37962. const waiter = awaiter(resolve, reject);
  37963. resultFns[id] = waiter.resolve;
  37964. ScriptLoader.ScriptLoader.loadScript(url).then(
  37965. () => waiter.start(runErrMsg),
  37966. () => waiter.reject(loadErrMsg)
  37967. );
  37968. });
  37969. tasks[id] = task;
  37970. return task;
  37971. }
  37972. };
  37973. const add = (id, data) => {
  37974. if (resultFns[id] !== undefined) {
  37975. resultFns[id](data);
  37976. delete resultFns[id];
  37977. }
  37978. tasks[id] = Promise.resolve(data);
  37979. };
  37980. const unload = (id) => {
  37981. delete tasks[id];
  37982. };
  37983. return {
  37984. load,
  37985. add,
  37986. unload,
  37987. };
  37988. };
  37989. const Resource = create$1();
  37990. const create = () =>
  37991. (() => {
  37992. let data = {};
  37993. let keys = [];
  37994. const storage = {
  37995. getItem: (key) => {
  37996. const item = data[key];
  37997. return item ? item : null;
  37998. },
  37999. setItem: (key, value) => {
  38000. keys.push(key);
  38001. data[key] = String(value);
  38002. },
  38003. key: (index) => {
  38004. return keys[index];
  38005. },
  38006. removeItem: (key) => {
  38007. keys = keys.filter((k) => k === key);
  38008. delete data[key];
  38009. },
  38010. clear: () => {
  38011. keys = [];
  38012. data = {};
  38013. },
  38014. length: 0,
  38015. };
  38016. Object.defineProperty(storage, "length", {
  38017. get: () => keys.length,
  38018. configurable: false,
  38019. enumerable: false,
  38020. });
  38021. return storage;
  38022. })();
  38023. let localStorage;
  38024. try {
  38025. const test = "__storage_test__";
  38026. localStorage = window.localStorage;
  38027. localStorage.setItem(test, test);
  38028. localStorage.removeItem(test);
  38029. } catch (e) {
  38030. localStorage = create();
  38031. }
  38032. var LocalStorage = localStorage;
  38033. const publicApi = {
  38034. geom: { Rect },
  38035. util: {
  38036. Delay,
  38037. Tools,
  38038. VK,
  38039. URI,
  38040. EventDispatcher,
  38041. Observable,
  38042. I18n,
  38043. LocalStorage,
  38044. ImageUploader,
  38045. },
  38046. dom: {
  38047. EventUtils,
  38048. TreeWalker: DomTreeWalker,
  38049. TextSeeker,
  38050. DOMUtils,
  38051. ScriptLoader,
  38052. RangeUtils,
  38053. Serializer: DomSerializer,
  38054. StyleSheetLoader,
  38055. ControlSelection,
  38056. BookmarkManager,
  38057. Selection: EditorSelection,
  38058. Event: EventUtils.Event,
  38059. },
  38060. html: {
  38061. Styles,
  38062. Entities,
  38063. Node: AstNode,
  38064. Schema,
  38065. DomParser,
  38066. Writer,
  38067. Serializer: HtmlSerializer,
  38068. },
  38069. Env,
  38070. AddOnManager,
  38071. Annotator,
  38072. Formatter,
  38073. UndoManager,
  38074. EditorCommands,
  38075. WindowManager,
  38076. NotificationManager,
  38077. EditorObservable,
  38078. Shortcuts,
  38079. Editor,
  38080. FocusManager,
  38081. EditorManager,
  38082. DOM: DOMUtils.DOM,
  38083. ScriptLoader: ScriptLoader.ScriptLoader,
  38084. PluginManager,
  38085. ThemeManager,
  38086. ModelManager,
  38087. IconManager,
  38088. Resource,
  38089. FakeClipboard,
  38090. trim: Tools.trim,
  38091. isArray: Tools.isArray,
  38092. is: Tools.is,
  38093. toArray: Tools.toArray,
  38094. makeMap: Tools.makeMap,
  38095. each: Tools.each,
  38096. map: Tools.map,
  38097. grep: Tools.grep,
  38098. inArray: Tools.inArray,
  38099. extend: Tools.extend,
  38100. walk: Tools.walk,
  38101. resolve: Tools.resolve,
  38102. explode: Tools.explode,
  38103. _addCacheSuffix: Tools._addCacheSuffix,
  38104. };
  38105. const tinymce = Tools.extend(EditorManager, publicApi);
  38106. const exportToModuleLoaders = (tinymce) => {
  38107. if (typeof module === "object") {
  38108. try {
  38109. module.exports = tinymce;
  38110. } catch (_) {}
  38111. }
  38112. };
  38113. const exportToWindowGlobal = (tinymce) => {
  38114. window.tinymce = tinymce;
  38115. window.tinyMCE = tinymce;
  38116. };
  38117. exportToWindowGlobal(tinymce);
  38118. exportToModuleLoaders(tinymce);
  38119. })();