2
0

converse-no-dependencies.js 1.7 MB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665206662066720668206692067020671206722067320674206752067620677206782067920680206812068220683206842068520686206872068820689206902069120692206932069420695206962069720698206992070020701207022070320704207052070620707207082070920710207112071220713207142071520716207172071820719207202072120722207232072420725207262072720728207292073020731207322073320734207352073620737207382073920740207412074220743207442074520746207472074820749207502075120752207532075420755207562075720758207592076020761207622076320764207652076620767207682076920770207712077220773207742077520776207772077820779207802078120782207832078420785207862078720788207892079020791207922079320794207952079620797207982079920800208012080220803208042080520806208072080820809208102081120812208132081420815208162081720818208192082020821208222082320824208252082620827208282082920830208312083220833208342083520836208372083820839208402084120842208432084420845208462084720848208492085020851208522085320854208552085620857208582085920860208612086220863208642086520866208672086820869208702087120872208732087420875208762087720878208792088020881208822088320884208852088620887208882088920890208912089220893208942089520896208972089820899209002090120902209032090420905209062090720908209092091020911209122091320914209152091620917209182091920920209212092220923209242092520926209272092820929209302093120932209332093420935209362093720938209392094020941209422094320944209452094620947209482094920950209512095220953209542095520956209572095820959209602096120962209632096420965209662096720968209692097020971209722097320974209752097620977209782097920980209812098220983209842098520986209872098820989209902099120992209932099420995209962099720998209992100021001210022100321004210052100621007210082100921010210112101221013210142101521016210172101821019210202102121022210232102421025210262102721028210292103021031210322103321034210352103621037210382103921040210412104221043210442104521046210472104821049210502105121052210532105421055210562105721058210592106021061210622106321064210652106621067210682106921070210712107221073210742107521076210772107821079210802108121082210832108421085210862108721088210892109021091210922109321094210952109621097210982109921100211012110221103211042110521106211072110821109211102111121112211132111421115211162111721118211192112021121211222112321124211252112621127211282112921130211312113221133211342113521136211372113821139211402114121142211432114421145211462114721148211492115021151211522115321154211552115621157211582115921160211612116221163211642116521166211672116821169211702117121172211732117421175211762117721178211792118021181211822118321184211852118621187211882118921190211912119221193211942119521196211972119821199212002120121202212032120421205212062120721208212092121021211212122121321214212152121621217212182121921220212212122221223212242122521226212272122821229212302123121232212332123421235212362123721238212392124021241212422124321244212452124621247212482124921250212512125221253212542125521256212572125821259212602126121262212632126421265212662126721268212692127021271212722127321274212752127621277212782127921280212812128221283212842128521286212872128821289212902129121292212932129421295212962129721298212992130021301213022130321304213052130621307213082130921310213112131221313213142131521316213172131821319213202132121322213232132421325213262132721328213292133021331213322133321334213352133621337213382133921340213412134221343213442134521346213472134821349213502135121352213532135421355213562135721358213592136021361213622136321364213652136621367213682136921370213712137221373213742137521376213772137821379213802138121382213832138421385213862138721388213892139021391213922139321394213952139621397213982139921400214012140221403214042140521406214072140821409214102141121412214132141421415214162141721418214192142021421214222142321424214252142621427214282142921430214312143221433214342143521436214372143821439214402144121442214432144421445214462144721448214492145021451214522145321454214552145621457214582145921460214612146221463214642146521466214672146821469214702147121472214732147421475214762147721478214792148021481214822148321484214852148621487214882148921490214912149221493214942149521496214972149821499215002150121502215032150421505215062150721508215092151021511215122151321514215152151621517215182151921520215212152221523215242152521526215272152821529215302153121532215332153421535215362153721538215392154021541215422154321544215452154621547215482154921550215512155221553215542155521556215572155821559215602156121562215632156421565215662156721568215692157021571215722157321574215752157621577215782157921580215812158221583215842158521586215872158821589215902159121592215932159421595215962159721598215992160021601216022160321604216052160621607216082160921610216112161221613216142161521616216172161821619216202162121622216232162421625216262162721628216292163021631216322163321634216352163621637216382163921640216412164221643216442164521646216472164821649216502165121652216532165421655216562165721658216592166021661216622166321664216652166621667216682166921670216712167221673216742167521676216772167821679216802168121682216832168421685216862168721688216892169021691216922169321694216952169621697216982169921700217012170221703217042170521706217072170821709217102171121712217132171421715217162171721718217192172021721217222172321724217252172621727217282172921730217312173221733217342173521736217372173821739217402174121742217432174421745217462174721748217492175021751217522175321754217552175621757217582175921760217612176221763217642176521766217672176821769217702177121772217732177421775217762177721778217792178021781217822178321784217852178621787217882178921790217912179221793217942179521796217972179821799218002180121802218032180421805218062180721808218092181021811218122181321814218152181621817218182181921820218212182221823218242182521826218272182821829218302183121832218332183421835218362183721838218392184021841218422184321844218452184621847218482184921850218512185221853218542185521856218572185821859218602186121862218632186421865218662186721868218692187021871218722187321874218752187621877218782187921880218812188221883218842188521886218872188821889218902189121892218932189421895218962189721898218992190021901219022190321904219052190621907219082190921910219112191221913219142191521916219172191821919219202192121922219232192421925219262192721928219292193021931219322193321934219352193621937219382193921940219412194221943219442194521946219472194821949219502195121952219532195421955219562195721958219592196021961219622196321964219652196621967219682196921970219712197221973219742197521976219772197821979219802198121982219832198421985219862198721988219892199021991219922199321994219952199621997219982199922000220012200222003220042200522006220072200822009220102201122012220132201422015220162201722018220192202022021220222202322024220252202622027220282202922030220312203222033220342203522036220372203822039220402204122042220432204422045220462204722048220492205022051220522205322054220552205622057220582205922060220612206222063220642206522066220672206822069220702207122072220732207422075220762207722078220792208022081220822208322084220852208622087220882208922090220912209222093220942209522096220972209822099221002210122102221032210422105221062210722108221092211022111221122211322114221152211622117221182211922120221212212222123221242212522126221272212822129221302213122132221332213422135221362213722138221392214022141221422214322144221452214622147221482214922150221512215222153221542215522156221572215822159221602216122162221632216422165221662216722168221692217022171221722217322174221752217622177221782217922180221812218222183221842218522186221872218822189221902219122192221932219422195221962219722198221992220022201222022220322204222052220622207222082220922210222112221222213222142221522216222172221822219222202222122222222232222422225222262222722228222292223022231222322223322234222352223622237222382223922240222412224222243222442224522246222472224822249222502225122252222532225422255222562225722258222592226022261222622226322264222652226622267222682226922270222712227222273222742227522276222772227822279222802228122282222832228422285222862228722288222892229022291222922229322294222952229622297222982229922300223012230222303223042230522306223072230822309223102231122312223132231422315223162231722318223192232022321223222232322324223252232622327223282232922330223312233222333223342233522336223372233822339223402234122342223432234422345223462234722348223492235022351223522235322354223552235622357223582235922360223612236222363223642236522366223672236822369223702237122372223732237422375223762237722378223792238022381223822238322384223852238622387223882238922390223912239222393223942239522396223972239822399224002240122402224032240422405224062240722408224092241022411224122241322414224152241622417224182241922420224212242222423224242242522426224272242822429224302243122432224332243422435224362243722438224392244022441224422244322444224452244622447224482244922450224512245222453224542245522456224572245822459224602246122462224632246422465224662246722468224692247022471224722247322474224752247622477224782247922480224812248222483224842248522486224872248822489224902249122492224932249422495224962249722498224992250022501225022250322504225052250622507225082250922510225112251222513225142251522516225172251822519225202252122522225232252422525225262252722528225292253022531225322253322534225352253622537225382253922540225412254222543225442254522546225472254822549225502255122552225532255422555225562255722558225592256022561225622256322564225652256622567225682256922570225712257222573225742257522576225772257822579225802258122582225832258422585225862258722588225892259022591225922259322594225952259622597225982259922600226012260222603226042260522606226072260822609226102261122612226132261422615226162261722618226192262022621226222262322624226252262622627226282262922630226312263222633226342263522636226372263822639226402264122642226432264422645226462264722648226492265022651226522265322654226552265622657226582265922660226612266222663226642266522666226672266822669226702267122672226732267422675226762267722678226792268022681226822268322684226852268622687226882268922690226912269222693226942269522696226972269822699227002270122702227032270422705227062270722708227092271022711227122271322714227152271622717227182271922720227212272222723227242272522726227272272822729227302273122732227332273422735227362273722738227392274022741227422274322744227452274622747227482274922750227512275222753227542275522756227572275822759227602276122762227632276422765227662276722768227692277022771227722277322774227752277622777227782277922780227812278222783227842278522786227872278822789227902279122792227932279422795227962279722798227992280022801228022280322804228052280622807228082280922810228112281222813228142281522816228172281822819228202282122822228232282422825228262282722828228292283022831228322283322834228352283622837228382283922840228412284222843228442284522846228472284822849228502285122852228532285422855228562285722858228592286022861228622286322864228652286622867228682286922870228712287222873228742287522876228772287822879228802288122882228832288422885228862288722888228892289022891228922289322894228952289622897228982289922900229012290222903229042290522906229072290822909229102291122912229132291422915229162291722918229192292022921229222292322924229252292622927229282292922930229312293222933229342293522936229372293822939229402294122942229432294422945229462294722948229492295022951229522295322954229552295622957229582295922960229612296222963229642296522966229672296822969229702297122972229732297422975229762297722978229792298022981229822298322984229852298622987229882298922990229912299222993229942299522996229972299822999230002300123002230032300423005230062300723008230092301023011230122301323014230152301623017230182301923020230212302223023230242302523026230272302823029230302303123032230332303423035230362303723038230392304023041230422304323044230452304623047230482304923050230512305223053230542305523056230572305823059230602306123062230632306423065230662306723068230692307023071230722307323074230752307623077230782307923080230812308223083230842308523086230872308823089230902309123092230932309423095230962309723098230992310023101231022310323104231052310623107231082310923110231112311223113231142311523116231172311823119231202312123122231232312423125231262312723128231292313023131231322313323134231352313623137231382313923140231412314223143231442314523146231472314823149231502315123152231532315423155231562315723158231592316023161231622316323164231652316623167231682316923170231712317223173231742317523176231772317823179231802318123182231832318423185231862318723188231892319023191231922319323194231952319623197231982319923200232012320223203232042320523206232072320823209232102321123212232132321423215232162321723218232192322023221232222322323224232252322623227232282322923230232312323223233232342323523236232372323823239232402324123242232432324423245232462324723248232492325023251232522325323254232552325623257232582325923260232612326223263232642326523266232672326823269232702327123272232732327423275232762327723278232792328023281232822328323284232852328623287232882328923290232912329223293232942329523296232972329823299233002330123302233032330423305233062330723308233092331023311233122331323314233152331623317233182331923320233212332223323233242332523326233272332823329233302333123332233332333423335233362333723338233392334023341233422334323344233452334623347233482334923350233512335223353233542335523356233572335823359233602336123362233632336423365233662336723368233692337023371233722337323374233752337623377233782337923380233812338223383233842338523386233872338823389233902339123392233932339423395233962339723398233992340023401234022340323404234052340623407234082340923410234112341223413234142341523416234172341823419234202342123422234232342423425234262342723428234292343023431234322343323434234352343623437234382343923440234412344223443234442344523446234472344823449234502345123452234532345423455234562345723458234592346023461234622346323464234652346623467234682346923470234712347223473234742347523476234772347823479234802348123482234832348423485234862348723488234892349023491234922349323494234952349623497234982349923500235012350223503235042350523506235072350823509235102351123512235132351423515235162351723518235192352023521235222352323524235252352623527235282352923530235312353223533235342353523536235372353823539235402354123542235432354423545235462354723548235492355023551235522355323554235552355623557235582355923560235612356223563235642356523566235672356823569235702357123572235732357423575235762357723578235792358023581235822358323584235852358623587235882358923590235912359223593235942359523596235972359823599236002360123602236032360423605236062360723608236092361023611236122361323614236152361623617236182361923620236212362223623236242362523626236272362823629236302363123632236332363423635236362363723638236392364023641236422364323644236452364623647236482364923650236512365223653236542365523656236572365823659236602366123662236632366423665236662366723668236692367023671236722367323674236752367623677236782367923680236812368223683236842368523686236872368823689236902369123692236932369423695236962369723698236992370023701237022370323704237052370623707237082370923710237112371223713237142371523716237172371823719237202372123722237232372423725237262372723728237292373023731237322373323734237352373623737237382373923740237412374223743237442374523746237472374823749237502375123752237532375423755237562375723758237592376023761237622376323764237652376623767237682376923770237712377223773237742377523776237772377823779237802378123782237832378423785237862378723788237892379023791237922379323794237952379623797237982379923800238012380223803238042380523806238072380823809238102381123812238132381423815238162381723818238192382023821238222382323824238252382623827238282382923830238312383223833238342383523836238372383823839238402384123842238432384423845238462384723848238492385023851238522385323854238552385623857238582385923860238612386223863238642386523866238672386823869238702387123872238732387423875238762387723878238792388023881238822388323884238852388623887238882388923890238912389223893238942389523896238972389823899239002390123902239032390423905239062390723908239092391023911239122391323914239152391623917239182391923920239212392223923239242392523926239272392823929239302393123932239332393423935239362393723938239392394023941239422394323944239452394623947239482394923950239512395223953239542395523956239572395823959239602396123962239632396423965239662396723968239692397023971239722397323974239752397623977239782397923980239812398223983239842398523986239872398823989239902399123992239932399423995239962399723998239992400024001240022400324004240052400624007240082400924010240112401224013240142401524016240172401824019240202402124022240232402424025240262402724028240292403024031240322403324034240352403624037240382403924040240412404224043240442404524046240472404824049240502405124052240532405424055240562405724058240592406024061240622406324064240652406624067240682406924070240712407224073240742407524076240772407824079240802408124082240832408424085240862408724088240892409024091240922409324094240952409624097240982409924100241012410224103241042410524106241072410824109241102411124112241132411424115241162411724118241192412024121241222412324124241252412624127241282412924130241312413224133241342413524136241372413824139241402414124142241432414424145241462414724148241492415024151241522415324154241552415624157241582415924160241612416224163241642416524166241672416824169241702417124172241732417424175241762417724178241792418024181241822418324184241852418624187241882418924190241912419224193241942419524196241972419824199242002420124202242032420424205242062420724208242092421024211242122421324214242152421624217242182421924220242212422224223242242422524226242272422824229242302423124232242332423424235242362423724238242392424024241242422424324244242452424624247242482424924250242512425224253242542425524256242572425824259242602426124262242632426424265242662426724268242692427024271242722427324274242752427624277242782427924280242812428224283242842428524286242872428824289242902429124292242932429424295242962429724298242992430024301243022430324304243052430624307243082430924310243112431224313243142431524316243172431824319243202432124322243232432424325243262432724328243292433024331243322433324334243352433624337243382433924340243412434224343243442434524346243472434824349243502435124352243532435424355243562435724358243592436024361243622436324364243652436624367243682436924370243712437224373243742437524376243772437824379243802438124382243832438424385243862438724388243892439024391243922439324394243952439624397243982439924400244012440224403244042440524406244072440824409244102441124412244132441424415244162441724418244192442024421244222442324424244252442624427244282442924430244312443224433244342443524436244372443824439244402444124442244432444424445244462444724448244492445024451244522445324454244552445624457244582445924460244612446224463244642446524466244672446824469244702447124472244732447424475244762447724478244792448024481244822448324484244852448624487244882448924490244912449224493244942449524496244972449824499245002450124502245032450424505245062450724508245092451024511245122451324514245152451624517245182451924520245212452224523245242452524526245272452824529245302453124532245332453424535245362453724538245392454024541245422454324544245452454624547245482454924550245512455224553245542455524556245572455824559245602456124562245632456424565245662456724568245692457024571245722457324574245752457624577245782457924580245812458224583245842458524586245872458824589245902459124592245932459424595245962459724598245992460024601246022460324604246052460624607246082460924610246112461224613246142461524616246172461824619246202462124622246232462424625246262462724628246292463024631246322463324634246352463624637246382463924640246412464224643246442464524646246472464824649246502465124652246532465424655246562465724658246592466024661246622466324664246652466624667246682466924670246712467224673246742467524676246772467824679246802468124682246832468424685246862468724688246892469024691246922469324694246952469624697246982469924700247012470224703247042470524706247072470824709247102471124712247132471424715247162471724718247192472024721247222472324724247252472624727247282472924730247312473224733247342473524736247372473824739247402474124742247432474424745247462474724748247492475024751247522475324754247552475624757247582475924760247612476224763247642476524766247672476824769247702477124772247732477424775247762477724778247792478024781247822478324784247852478624787247882478924790247912479224793247942479524796247972479824799248002480124802248032480424805248062480724808248092481024811248122481324814248152481624817248182481924820248212482224823248242482524826248272482824829248302483124832248332483424835248362483724838248392484024841248422484324844248452484624847248482484924850248512485224853248542485524856248572485824859248602486124862248632486424865248662486724868248692487024871248722487324874248752487624877248782487924880248812488224883248842488524886248872488824889248902489124892248932489424895248962489724898248992490024901249022490324904249052490624907249082490924910249112491224913249142491524916249172491824919249202492124922249232492424925249262492724928249292493024931249322493324934249352493624937249382493924940249412494224943249442494524946249472494824949249502495124952249532495424955249562495724958249592496024961249622496324964249652496624967249682496924970249712497224973249742497524976249772497824979249802498124982249832498424985249862498724988249892499024991249922499324994249952499624997249982499925000250012500225003250042500525006250072500825009250102501125012250132501425015250162501725018250192502025021250222502325024250252502625027250282502925030250312503225033250342503525036250372503825039250402504125042250432504425045250462504725048250492505025051250522505325054250552505625057250582505925060250612506225063250642506525066250672506825069250702507125072250732507425075250762507725078250792508025081250822508325084250852508625087250882508925090250912509225093250942509525096250972509825099251002510125102251032510425105251062510725108251092511025111251122511325114251152511625117251182511925120251212512225123251242512525126251272512825129251302513125132251332513425135251362513725138251392514025141251422514325144251452514625147251482514925150251512515225153251542515525156251572515825159251602516125162251632516425165251662516725168251692517025171251722517325174251752517625177251782517925180251812518225183251842518525186251872518825189251902519125192251932519425195251962519725198251992520025201252022520325204252052520625207252082520925210252112521225213252142521525216252172521825219252202522125222252232522425225252262522725228252292523025231252322523325234252352523625237252382523925240252412524225243252442524525246252472524825249252502525125252252532525425255252562525725258252592526025261252622526325264252652526625267252682526925270252712527225273252742527525276252772527825279252802528125282252832528425285252862528725288252892529025291252922529325294252952529625297252982529925300253012530225303253042530525306253072530825309253102531125312253132531425315253162531725318253192532025321253222532325324253252532625327253282532925330253312533225333253342533525336253372533825339253402534125342253432534425345253462534725348253492535025351253522535325354253552535625357253582535925360253612536225363253642536525366253672536825369253702537125372253732537425375253762537725378253792538025381253822538325384253852538625387253882538925390253912539225393253942539525396253972539825399254002540125402254032540425405254062540725408254092541025411254122541325414254152541625417254182541925420254212542225423254242542525426254272542825429254302543125432254332543425435254362543725438254392544025441254422544325444254452544625447254482544925450254512545225453254542545525456254572545825459254602546125462254632546425465254662546725468254692547025471254722547325474254752547625477254782547925480254812548225483254842548525486254872548825489254902549125492254932549425495254962549725498254992550025501255022550325504255052550625507255082550925510255112551225513255142551525516255172551825519255202552125522255232552425525255262552725528255292553025531255322553325534255352553625537255382553925540255412554225543255442554525546255472554825549255502555125552255532555425555255562555725558255592556025561255622556325564255652556625567255682556925570255712557225573255742557525576255772557825579255802558125582255832558425585255862558725588255892559025591255922559325594255952559625597255982559925600256012560225603256042560525606256072560825609256102561125612256132561425615256162561725618256192562025621256222562325624256252562625627256282562925630256312563225633256342563525636256372563825639256402564125642256432564425645256462564725648256492565025651256522565325654256552565625657256582565925660256612566225663256642566525666256672566825669256702567125672256732567425675256762567725678256792568025681256822568325684256852568625687256882568925690256912569225693256942569525696256972569825699257002570125702257032570425705257062570725708257092571025711257122571325714257152571625717257182571925720257212572225723257242572525726257272572825729257302573125732257332573425735257362573725738257392574025741257422574325744257452574625747257482574925750257512575225753257542575525756257572575825759257602576125762257632576425765257662576725768257692577025771257722577325774257752577625777257782577925780257812578225783257842578525786257872578825789257902579125792257932579425795257962579725798257992580025801258022580325804258052580625807258082580925810258112581225813258142581525816258172581825819258202582125822258232582425825258262582725828258292583025831258322583325834258352583625837258382583925840258412584225843258442584525846258472584825849258502585125852258532585425855258562585725858258592586025861258622586325864258652586625867258682586925870258712587225873258742587525876258772587825879258802588125882258832588425885258862588725888258892589025891258922589325894258952589625897258982589925900259012590225903259042590525906259072590825909259102591125912259132591425915259162591725918259192592025921259222592325924259252592625927259282592925930259312593225933259342593525936259372593825939259402594125942259432594425945259462594725948259492595025951259522595325954259552595625957259582595925960259612596225963259642596525966259672596825969259702597125972259732597425975259762597725978259792598025981259822598325984259852598625987259882598925990259912599225993259942599525996259972599825999260002600126002260032600426005260062600726008260092601026011260122601326014260152601626017260182601926020260212602226023260242602526026260272602826029260302603126032260332603426035260362603726038260392604026041260422604326044260452604626047260482604926050260512605226053260542605526056260572605826059260602606126062260632606426065260662606726068260692607026071260722607326074260752607626077260782607926080260812608226083260842608526086260872608826089260902609126092260932609426095260962609726098260992610026101261022610326104261052610626107261082610926110261112611226113261142611526116261172611826119261202612126122261232612426125261262612726128261292613026131261322613326134261352613626137261382613926140261412614226143261442614526146261472614826149261502615126152261532615426155261562615726158261592616026161261622616326164261652616626167261682616926170261712617226173261742617526176261772617826179261802618126182261832618426185261862618726188261892619026191261922619326194261952619626197261982619926200262012620226203262042620526206262072620826209262102621126212262132621426215262162621726218262192622026221262222622326224262252622626227262282622926230262312623226233262342623526236262372623826239262402624126242262432624426245262462624726248262492625026251262522625326254262552625626257262582625926260262612626226263262642626526266262672626826269262702627126272262732627426275262762627726278262792628026281262822628326284262852628626287262882628926290262912629226293262942629526296262972629826299263002630126302263032630426305263062630726308263092631026311263122631326314263152631626317263182631926320263212632226323263242632526326263272632826329263302633126332263332633426335263362633726338263392634026341263422634326344263452634626347263482634926350263512635226353263542635526356263572635826359263602636126362263632636426365263662636726368263692637026371263722637326374263752637626377263782637926380263812638226383263842638526386263872638826389263902639126392263932639426395263962639726398263992640026401264022640326404264052640626407264082640926410264112641226413264142641526416264172641826419264202642126422264232642426425264262642726428264292643026431264322643326434264352643626437264382643926440264412644226443264442644526446264472644826449264502645126452264532645426455264562645726458264592646026461264622646326464264652646626467264682646926470264712647226473264742647526476264772647826479264802648126482264832648426485264862648726488264892649026491264922649326494264952649626497264982649926500265012650226503265042650526506265072650826509265102651126512265132651426515265162651726518265192652026521265222652326524265252652626527265282652926530265312653226533265342653526536265372653826539265402654126542265432654426545265462654726548265492655026551265522655326554265552655626557265582655926560265612656226563265642656526566265672656826569265702657126572265732657426575265762657726578265792658026581265822658326584265852658626587265882658926590265912659226593265942659526596265972659826599266002660126602266032660426605266062660726608266092661026611266122661326614266152661626617266182661926620266212662226623266242662526626266272662826629266302663126632266332663426635266362663726638266392664026641266422664326644266452664626647266482664926650266512665226653266542665526656266572665826659266602666126662266632666426665266662666726668266692667026671266722667326674266752667626677266782667926680266812668226683266842668526686266872668826689266902669126692266932669426695266962669726698266992670026701267022670326704267052670626707267082670926710267112671226713267142671526716267172671826719267202672126722267232672426725267262672726728267292673026731267322673326734267352673626737267382673926740267412674226743267442674526746267472674826749267502675126752267532675426755267562675726758267592676026761267622676326764267652676626767267682676926770267712677226773267742677526776267772677826779267802678126782267832678426785267862678726788267892679026791267922679326794267952679626797267982679926800268012680226803268042680526806268072680826809268102681126812268132681426815268162681726818268192682026821268222682326824268252682626827268282682926830268312683226833268342683526836268372683826839268402684126842268432684426845268462684726848268492685026851268522685326854268552685626857268582685926860268612686226863268642686526866268672686826869268702687126872268732687426875268762687726878268792688026881268822688326884268852688626887268882688926890268912689226893268942689526896268972689826899269002690126902269032690426905269062690726908269092691026911269122691326914269152691626917269182691926920269212692226923269242692526926269272692826929269302693126932269332693426935269362693726938269392694026941269422694326944269452694626947269482694926950269512695226953269542695526956269572695826959269602696126962269632696426965269662696726968269692697026971269722697326974269752697626977269782697926980269812698226983269842698526986269872698826989269902699126992269932699426995269962699726998269992700027001270022700327004270052700627007270082700927010270112701227013270142701527016270172701827019270202702127022270232702427025270262702727028270292703027031270322703327034270352703627037270382703927040270412704227043270442704527046270472704827049270502705127052270532705427055270562705727058270592706027061270622706327064270652706627067270682706927070270712707227073270742707527076270772707827079270802708127082270832708427085270862708727088270892709027091270922709327094270952709627097270982709927100271012710227103271042710527106271072710827109271102711127112271132711427115271162711727118271192712027121271222712327124271252712627127271282712927130271312713227133271342713527136271372713827139271402714127142271432714427145271462714727148271492715027151271522715327154271552715627157271582715927160271612716227163271642716527166271672716827169271702717127172271732717427175271762717727178271792718027181271822718327184271852718627187271882718927190271912719227193271942719527196271972719827199272002720127202272032720427205272062720727208272092721027211272122721327214272152721627217272182721927220272212722227223272242722527226272272722827229272302723127232272332723427235272362723727238272392724027241272422724327244272452724627247272482724927250272512725227253272542725527256272572725827259272602726127262272632726427265272662726727268272692727027271272722727327274272752727627277272782727927280272812728227283272842728527286272872728827289272902729127292272932729427295272962729727298272992730027301273022730327304273052730627307273082730927310273112731227313273142731527316273172731827319273202732127322273232732427325273262732727328273292733027331273322733327334273352733627337273382733927340273412734227343273442734527346273472734827349273502735127352273532735427355273562735727358273592736027361273622736327364273652736627367273682736927370273712737227373273742737527376273772737827379273802738127382273832738427385273862738727388273892739027391273922739327394273952739627397273982739927400274012740227403274042740527406274072740827409274102741127412274132741427415274162741727418274192742027421274222742327424274252742627427274282742927430274312743227433274342743527436274372743827439274402744127442274432744427445274462744727448274492745027451274522745327454274552745627457274582745927460274612746227463274642746527466274672746827469274702747127472274732747427475274762747727478274792748027481274822748327484274852748627487274882748927490274912749227493274942749527496274972749827499275002750127502275032750427505275062750727508275092751027511275122751327514275152751627517275182751927520275212752227523275242752527526275272752827529275302753127532275332753427535275362753727538275392754027541275422754327544275452754627547275482754927550275512755227553275542755527556275572755827559275602756127562275632756427565275662756727568275692757027571275722757327574275752757627577275782757927580275812758227583275842758527586275872758827589275902759127592275932759427595275962759727598275992760027601276022760327604276052760627607276082760927610276112761227613276142761527616276172761827619276202762127622276232762427625276262762727628276292763027631276322763327634276352763627637276382763927640276412764227643276442764527646276472764827649276502765127652276532765427655276562765727658276592766027661276622766327664276652766627667276682766927670276712767227673276742767527676276772767827679276802768127682276832768427685276862768727688276892769027691276922769327694276952769627697276982769927700277012770227703277042770527706277072770827709277102771127712277132771427715277162771727718277192772027721277222772327724277252772627727277282772927730277312773227733277342773527736277372773827739277402774127742277432774427745277462774727748277492775027751277522775327754277552775627757277582775927760277612776227763277642776527766277672776827769277702777127772277732777427775277762777727778277792778027781277822778327784277852778627787277882778927790277912779227793277942779527796277972779827799278002780127802278032780427805278062780727808278092781027811278122781327814278152781627817278182781927820278212782227823278242782527826278272782827829278302783127832278332783427835278362783727838278392784027841278422784327844278452784627847278482784927850278512785227853278542785527856278572785827859278602786127862278632786427865278662786727868278692787027871278722787327874278752787627877278782787927880278812788227883278842788527886278872788827889278902789127892278932789427895278962789727898278992790027901279022790327904279052790627907279082790927910279112791227913279142791527916279172791827919279202792127922279232792427925279262792727928279292793027931279322793327934279352793627937279382793927940279412794227943279442794527946279472794827949279502795127952279532795427955279562795727958279592796027961279622796327964279652796627967279682796927970279712797227973279742797527976279772797827979279802798127982279832798427985279862798727988279892799027991279922799327994279952799627997279982799928000280012800228003280042800528006280072800828009280102801128012280132801428015280162801728018280192802028021280222802328024280252802628027280282802928030280312803228033280342803528036280372803828039280402804128042280432804428045280462804728048280492805028051280522805328054280552805628057280582805928060280612806228063280642806528066280672806828069280702807128072280732807428075280762807728078280792808028081280822808328084280852808628087280882808928090280912809228093280942809528096280972809828099281002810128102281032810428105281062810728108281092811028111281122811328114281152811628117281182811928120281212812228123281242812528126281272812828129281302813128132281332813428135281362813728138281392814028141281422814328144281452814628147281482814928150281512815228153281542815528156281572815828159281602816128162281632816428165
  1. /** Converse.js
  2. *
  3. * An XMPP chat client that runs in the browser.
  4. *
  5. * Version: 3.3.4
  6. */
  7. /* jshint ignore:start */
  8. (function (root, factory) {
  9. root.converse = factory();
  10. }(this, function () {
  11. //almond, and your modules will be inlined here
  12. /* jshint ignore:end */
  13. /**
  14. * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
  15. * Released under MIT license, http://github.com/requirejs/almond/LICENSE
  16. */
  17. //Going sloppy to avoid 'use strict' string cost, but strict practices should
  18. //be followed.
  19. /*global setTimeout: false */
  20. var requirejs, require, define;
  21. (function (undef) {
  22. var main, req, makeMap, handlers,
  23. defined = {},
  24. waiting = {},
  25. config = {},
  26. defining = {},
  27. hasOwn = Object.prototype.hasOwnProperty,
  28. aps = [].slice,
  29. jsSuffixRegExp = /\.js$/;
  30. function hasProp(obj, prop) {
  31. return hasOwn.call(obj, prop);
  32. }
  33. /**
  34. * Given a relative module name, like ./something, normalize it to
  35. * a real name that can be mapped to a path.
  36. * @param {String} name the relative name
  37. * @param {String} baseName a real name that the name arg is relative
  38. * to.
  39. * @returns {String} normalized name
  40. */
  41. function normalize(name, baseName) {
  42. var nameParts, nameSegment, mapValue, foundMap, lastIndex,
  43. foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
  44. baseParts = baseName && baseName.split("/"),
  45. map = config.map,
  46. starMap = (map && map['*']) || {};
  47. //Adjust any relative paths.
  48. if (name) {
  49. name = name.split('/');
  50. lastIndex = name.length - 1;
  51. // If wanting node ID compatibility, strip .js from end
  52. // of IDs. Have to do this here, and not in nameToUrl
  53. // because node allows either .js or non .js to map
  54. // to same file.
  55. if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
  56. name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
  57. }
  58. // Starts with a '.' so need the baseName
  59. if (name[0].charAt(0) === '.' && baseParts) {
  60. //Convert baseName to array, and lop off the last part,
  61. //so that . matches that 'directory' and not name of the baseName's
  62. //module. For instance, baseName of 'one/two/three', maps to
  63. //'one/two/three.js', but we want the directory, 'one/two' for
  64. //this normalization.
  65. normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
  66. name = normalizedBaseParts.concat(name);
  67. }
  68. //start trimDots
  69. for (i = 0; i < name.length; i++) {
  70. part = name[i];
  71. if (part === '.') {
  72. name.splice(i, 1);
  73. i -= 1;
  74. } else if (part === '..') {
  75. // If at the start, or previous value is still ..,
  76. // keep them so that when converted to a path it may
  77. // still work when converted to a path, even though
  78. // as an ID it is less than ideal. In larger point
  79. // releases, may be better to just kick out an error.
  80. if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
  81. continue;
  82. } else if (i > 0) {
  83. name.splice(i - 1, 2);
  84. i -= 2;
  85. }
  86. }
  87. }
  88. //end trimDots
  89. name = name.join('/');
  90. }
  91. //Apply map config if available.
  92. if ((baseParts || starMap) && map) {
  93. nameParts = name.split('/');
  94. for (i = nameParts.length; i > 0; i -= 1) {
  95. nameSegment = nameParts.slice(0, i).join("/");
  96. if (baseParts) {
  97. //Find the longest baseName segment match in the config.
  98. //So, do joins on the biggest to smallest lengths of baseParts.
  99. for (j = baseParts.length; j > 0; j -= 1) {
  100. mapValue = map[baseParts.slice(0, j).join('/')];
  101. //baseName segment has config, find if it has one for
  102. //this name.
  103. if (mapValue) {
  104. mapValue = mapValue[nameSegment];
  105. if (mapValue) {
  106. //Match, update name to the new value.
  107. foundMap = mapValue;
  108. foundI = i;
  109. break;
  110. }
  111. }
  112. }
  113. }
  114. if (foundMap) {
  115. break;
  116. }
  117. //Check for a star map match, but just hold on to it,
  118. //if there is a shorter segment match later in a matching
  119. //config, then favor over this star map.
  120. if (!foundStarMap && starMap && starMap[nameSegment]) {
  121. foundStarMap = starMap[nameSegment];
  122. starI = i;
  123. }
  124. }
  125. if (!foundMap && foundStarMap) {
  126. foundMap = foundStarMap;
  127. foundI = starI;
  128. }
  129. if (foundMap) {
  130. nameParts.splice(0, foundI, foundMap);
  131. name = nameParts.join('/');
  132. }
  133. }
  134. return name;
  135. }
  136. function makeRequire(relName, forceSync) {
  137. return function () {
  138. //A version of a require function that passes a moduleName
  139. //value for items that may need to
  140. //look up paths relative to the moduleName
  141. var args = aps.call(arguments, 0);
  142. //If first arg is not require('string'), and there is only
  143. //one arg, it is the array form without a callback. Insert
  144. //a null so that the following concat is correct.
  145. if (typeof args[0] !== 'string' && args.length === 1) {
  146. args.push(null);
  147. }
  148. return req.apply(undef, args.concat([relName, forceSync]));
  149. };
  150. }
  151. function makeNormalize(relName) {
  152. return function (name) {
  153. return normalize(name, relName);
  154. };
  155. }
  156. function makeLoad(depName) {
  157. return function (value) {
  158. defined[depName] = value;
  159. };
  160. }
  161. function callDep(name) {
  162. if (hasProp(waiting, name)) {
  163. var args = waiting[name];
  164. delete waiting[name];
  165. defining[name] = true;
  166. main.apply(undef, args);
  167. }
  168. if (!hasProp(defined, name) && !hasProp(defining, name)) {
  169. throw new Error('No ' + name);
  170. }
  171. return defined[name];
  172. }
  173. //Turns a plugin!resource to [plugin, resource]
  174. //with the plugin being undefined if the name
  175. //did not have a plugin prefix.
  176. function splitPrefix(name) {
  177. var prefix,
  178. index = name ? name.indexOf('!') : -1;
  179. if (index > -1) {
  180. prefix = name.substring(0, index);
  181. name = name.substring(index + 1, name.length);
  182. }
  183. return [prefix, name];
  184. }
  185. //Creates a parts array for a relName where first part is plugin ID,
  186. //second part is resource ID. Assumes relName has already been normalized.
  187. function makeRelParts(relName) {
  188. return relName ? splitPrefix(relName) : [];
  189. }
  190. /**
  191. * Makes a name map, normalizing the name, and using a plugin
  192. * for normalization if necessary. Grabs a ref to plugin
  193. * too, as an optimization.
  194. */
  195. makeMap = function (name, relParts) {
  196. var plugin,
  197. parts = splitPrefix(name),
  198. prefix = parts[0],
  199. relResourceName = relParts[1];
  200. name = parts[1];
  201. if (prefix) {
  202. prefix = normalize(prefix, relResourceName);
  203. plugin = callDep(prefix);
  204. }
  205. //Normalize according
  206. if (prefix) {
  207. if (plugin && plugin.normalize) {
  208. name = plugin.normalize(name, makeNormalize(relResourceName));
  209. } else {
  210. name = normalize(name, relResourceName);
  211. }
  212. } else {
  213. name = normalize(name, relResourceName);
  214. parts = splitPrefix(name);
  215. prefix = parts[0];
  216. name = parts[1];
  217. if (prefix) {
  218. plugin = callDep(prefix);
  219. }
  220. }
  221. //Using ridiculous property names for space reasons
  222. return {
  223. f: prefix ? prefix + '!' + name : name, //fullName
  224. n: name,
  225. pr: prefix,
  226. p: plugin
  227. };
  228. };
  229. function makeConfig(name) {
  230. return function () {
  231. return (config && config.config && config.config[name]) || {};
  232. };
  233. }
  234. handlers = {
  235. require: function (name) {
  236. return makeRequire(name);
  237. },
  238. exports: function (name) {
  239. var e = defined[name];
  240. if (typeof e !== 'undefined') {
  241. return e;
  242. } else {
  243. return (defined[name] = {});
  244. }
  245. },
  246. module: function (name) {
  247. return {
  248. id: name,
  249. uri: '',
  250. exports: defined[name],
  251. config: makeConfig(name)
  252. };
  253. }
  254. };
  255. main = function (name, deps, callback, relName) {
  256. var cjsModule, depName, ret, map, i, relParts,
  257. args = [],
  258. callbackType = typeof callback,
  259. usingExports;
  260. //Use name if no relName
  261. relName = relName || name;
  262. relParts = makeRelParts(relName);
  263. //Call the callback to define the module, if necessary.
  264. if (callbackType === 'undefined' || callbackType === 'function') {
  265. //Pull out the defined dependencies and pass the ordered
  266. //values to the callback.
  267. //Default to [require, exports, module] if no deps
  268. deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
  269. for (i = 0; i < deps.length; i += 1) {
  270. map = makeMap(deps[i], relParts);
  271. depName = map.f;
  272. //Fast path CommonJS standard dependencies.
  273. if (depName === "require") {
  274. args[i] = handlers.require(name);
  275. } else if (depName === "exports") {
  276. //CommonJS module spec 1.1
  277. args[i] = handlers.exports(name);
  278. usingExports = true;
  279. } else if (depName === "module") {
  280. //CommonJS module spec 1.1
  281. cjsModule = args[i] = handlers.module(name);
  282. } else if (hasProp(defined, depName) ||
  283. hasProp(waiting, depName) ||
  284. hasProp(defining, depName)) {
  285. args[i] = callDep(depName);
  286. } else if (map.p) {
  287. map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
  288. args[i] = defined[depName];
  289. } else {
  290. throw new Error(name + ' missing ' + depName);
  291. }
  292. }
  293. ret = callback ? callback.apply(defined[name], args) : undefined;
  294. if (name) {
  295. //If setting exports via "module" is in play,
  296. //favor that over return value and exports. After that,
  297. //favor a non-undefined return value over exports use.
  298. if (cjsModule && cjsModule.exports !== undef &&
  299. cjsModule.exports !== defined[name]) {
  300. defined[name] = cjsModule.exports;
  301. } else if (ret !== undef || !usingExports) {
  302. //Use the return value from the function.
  303. defined[name] = ret;
  304. }
  305. }
  306. } else if (name) {
  307. //May just be an object definition for the module. Only
  308. //worry about defining if have a module name.
  309. defined[name] = callback;
  310. }
  311. };
  312. requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
  313. if (typeof deps === "string") {
  314. if (handlers[deps]) {
  315. //callback in this case is really relName
  316. return handlers[deps](callback);
  317. }
  318. //Just return the module wanted. In this scenario, the
  319. //deps arg is the module name, and second arg (if passed)
  320. //is just the relName.
  321. //Normalize module name, if it contains . or ..
  322. return callDep(makeMap(deps, makeRelParts(callback)).f);
  323. } else if (!deps.splice) {
  324. //deps is a config object, not an array.
  325. config = deps;
  326. if (config.deps) {
  327. req(config.deps, config.callback);
  328. }
  329. if (!callback) {
  330. return;
  331. }
  332. if (callback.splice) {
  333. //callback is an array, which means it is a dependency list.
  334. //Adjust args if there are dependencies
  335. deps = callback;
  336. callback = relName;
  337. relName = null;
  338. } else {
  339. deps = undef;
  340. }
  341. }
  342. //Support require(['a'])
  343. callback = callback || function () {};
  344. //If relName is a function, it is an errback handler,
  345. //so remove it.
  346. if (typeof relName === 'function') {
  347. relName = forceSync;
  348. forceSync = alt;
  349. }
  350. //Simulate async callback;
  351. if (forceSync) {
  352. main(undef, deps, callback, relName);
  353. } else {
  354. //Using a non-zero value because of concern for what old browsers
  355. //do, and latest browsers "upgrade" to 4 if lower value is used:
  356. //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
  357. //If want a value immediately, use require('id') instead -- something
  358. //that works in almond on the global level, but not guaranteed and
  359. //unlikely to work in other AMD implementations.
  360. setTimeout(function () {
  361. main(undef, deps, callback, relName);
  362. }, 4);
  363. }
  364. return req;
  365. };
  366. /**
  367. * Just drops the config on the floor, but returns req in case
  368. * the config return value is used.
  369. */
  370. req.config = function (cfg) {
  371. return req(cfg);
  372. };
  373. /**
  374. * Expose module registry for debugging and tooling
  375. */
  376. requirejs._defined = defined;
  377. define = function (name, deps, callback) {
  378. if (typeof name !== 'string') {
  379. throw new Error('See almond README: incorrect module build, no module name');
  380. }
  381. //This module may not have dependencies
  382. if (!deps.splice) {
  383. //deps is not an array, so probably means
  384. //an object literal or factory function for
  385. //the value. Adjust args.
  386. callback = deps;
  387. deps = [];
  388. }
  389. if (!hasProp(defined, name) && !hasProp(waiting, name)) {
  390. waiting[name] = [name, deps, callback];
  391. }
  392. };
  393. define.amd = {
  394. jQuery: true
  395. };
  396. }());
  397. define("almond", function(){});
  398. /*!
  399. * Sizzle CSS Selector Engine v2.3.3
  400. * https://sizzlejs.com/
  401. *
  402. * Copyright jQuery Foundation and other contributors
  403. * Released under the MIT license
  404. * http://jquery.org/license
  405. *
  406. * Date: 2016-08-08
  407. */
  408. (function( window ) {
  409. var i,
  410. support,
  411. Expr,
  412. getText,
  413. isXML,
  414. tokenize,
  415. compile,
  416. select,
  417. outermostContext,
  418. sortInput,
  419. hasDuplicate,
  420. // Local document vars
  421. setDocument,
  422. document,
  423. docElem,
  424. documentIsHTML,
  425. rbuggyQSA,
  426. rbuggyMatches,
  427. matches,
  428. contains,
  429. // Instance-specific data
  430. expando = "sizzle" + 1 * new Date(),
  431. preferredDoc = window.document,
  432. dirruns = 0,
  433. done = 0,
  434. classCache = createCache(),
  435. tokenCache = createCache(),
  436. compilerCache = createCache(),
  437. sortOrder = function( a, b ) {
  438. if ( a === b ) {
  439. hasDuplicate = true;
  440. }
  441. return 0;
  442. },
  443. // Instance methods
  444. hasOwn = ({}).hasOwnProperty,
  445. arr = [],
  446. pop = arr.pop,
  447. push_native = arr.push,
  448. push = arr.push,
  449. slice = arr.slice,
  450. // Use a stripped-down indexOf as it's faster than native
  451. // https://jsperf.com/thor-indexof-vs-for/5
  452. indexOf = function( list, elem ) {
  453. var i = 0,
  454. len = list.length;
  455. for ( ; i < len; i++ ) {
  456. if ( list[i] === elem ) {
  457. return i;
  458. }
  459. }
  460. return -1;
  461. },
  462. booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  463. // Regular expressions
  464. // http://www.w3.org/TR/css3-selectors/#whitespace
  465. whitespace = "[\\x20\\t\\r\\n\\f]",
  466. // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  467. identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
  468. // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
  469. attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
  470. // Operator (capture 2)
  471. "*([*^$|!~]?=)" + whitespace +
  472. // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
  473. "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
  474. "*\\]",
  475. pseudos = ":(" + identifier + ")(?:\\((" +
  476. // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
  477. // 1. quoted (capture 3; capture 4 or capture 5)
  478. "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
  479. // 2. simple (capture 6)
  480. "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
  481. // 3. anything else (capture 2)
  482. ".*" +
  483. ")\\)|)",
  484. // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  485. rwhitespace = new RegExp( whitespace + "+", "g" ),
  486. rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
  487. rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
  488. rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
  489. rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
  490. rpseudo = new RegExp( pseudos ),
  491. ridentifier = new RegExp( "^" + identifier + "$" ),
  492. matchExpr = {
  493. "ID": new RegExp( "^#(" + identifier + ")" ),
  494. "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
  495. "TAG": new RegExp( "^(" + identifier + "|[*])" ),
  496. "ATTR": new RegExp( "^" + attributes ),
  497. "PSEUDO": new RegExp( "^" + pseudos ),
  498. "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  499. "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  500. "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
  501. "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
  502. // For use in libraries implementing .is()
  503. // We use this for POS matching in `select`
  504. "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  505. whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
  506. },
  507. rinputs = /^(?:input|select|textarea|button)$/i,
  508. rheader = /^h\d$/i,
  509. rnative = /^[^{]+\{\s*\[native \w/,
  510. // Easily-parseable/retrievable ID or TAG or CLASS selectors
  511. rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  512. rsibling = /[+~]/,
  513. // CSS escapes
  514. // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  515. runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
  516. funescape = function( _, escaped, escapedWhitespace ) {
  517. var high = "0x" + escaped - 0x10000;
  518. // NaN means non-codepoint
  519. // Support: Firefox<24
  520. // Workaround erroneous numeric interpretation of +"0x"
  521. return high !== high || escapedWhitespace ?
  522. escaped :
  523. high < 0 ?
  524. // BMP codepoint
  525. String.fromCharCode( high + 0x10000 ) :
  526. // Supplemental Plane codepoint (surrogate pair)
  527. String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
  528. },
  529. // CSS string/identifier serialization
  530. // https://drafts.csswg.org/cssom/#common-serializing-idioms
  531. rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
  532. fcssescape = function( ch, asCodePoint ) {
  533. if ( asCodePoint ) {
  534. // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
  535. if ( ch === "\0" ) {
  536. return "\uFFFD";
  537. }
  538. // Control characters and (dependent upon position) numbers get escaped as code points
  539. return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
  540. }
  541. // Other potentially-special ASCII characters get backslash-escaped
  542. return "\\" + ch;
  543. },
  544. // Used for iframes
  545. // See setDocument()
  546. // Removing the function wrapper causes a "Permission Denied"
  547. // error in IE
  548. unloadHandler = function() {
  549. setDocument();
  550. },
  551. disabledAncestor = addCombinator(
  552. function( elem ) {
  553. return elem.disabled === true && ("form" in elem || "label" in elem);
  554. },
  555. { dir: "parentNode", next: "legend" }
  556. );
  557. // Optimize for push.apply( _, NodeList )
  558. try {
  559. push.apply(
  560. (arr = slice.call( preferredDoc.childNodes )),
  561. preferredDoc.childNodes
  562. );
  563. // Support: Android<4.0
  564. // Detect silently failing push.apply
  565. arr[ preferredDoc.childNodes.length ].nodeType;
  566. } catch ( e ) {
  567. push = { apply: arr.length ?
  568. // Leverage slice if possible
  569. function( target, els ) {
  570. push_native.apply( target, slice.call(els) );
  571. } :
  572. // Support: IE<9
  573. // Otherwise append directly
  574. function( target, els ) {
  575. var j = target.length,
  576. i = 0;
  577. // Can't trust NodeList.length
  578. while ( (target[j++] = els[i++]) ) {}
  579. target.length = j - 1;
  580. }
  581. };
  582. }
  583. function Sizzle( selector, context, results, seed ) {
  584. var m, i, elem, nid, match, groups, newSelector,
  585. newContext = context && context.ownerDocument,
  586. // nodeType defaults to 9, since context defaults to document
  587. nodeType = context ? context.nodeType : 9;
  588. results = results || [];
  589. // Return early from calls with invalid selector or context
  590. if ( typeof selector !== "string" || !selector ||
  591. nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
  592. return results;
  593. }
  594. // Try to shortcut find operations (as opposed to filters) in HTML documents
  595. if ( !seed ) {
  596. if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
  597. setDocument( context );
  598. }
  599. context = context || document;
  600. if ( documentIsHTML ) {
  601. // If the selector is sufficiently simple, try using a "get*By*" DOM method
  602. // (excepting DocumentFragment context, where the methods don't exist)
  603. if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
  604. // ID selector
  605. if ( (m = match[1]) ) {
  606. // Document context
  607. if ( nodeType === 9 ) {
  608. if ( (elem = context.getElementById( m )) ) {
  609. // Support: IE, Opera, Webkit
  610. // TODO: identify versions
  611. // getElementById can match elements by name instead of ID
  612. if ( elem.id === m ) {
  613. results.push( elem );
  614. return results;
  615. }
  616. } else {
  617. return results;
  618. }
  619. // Element context
  620. } else {
  621. // Support: IE, Opera, Webkit
  622. // TODO: identify versions
  623. // getElementById can match elements by name instead of ID
  624. if ( newContext && (elem = newContext.getElementById( m )) &&
  625. contains( context, elem ) &&
  626. elem.id === m ) {
  627. results.push( elem );
  628. return results;
  629. }
  630. }
  631. // Type selector
  632. } else if ( match[2] ) {
  633. push.apply( results, context.getElementsByTagName( selector ) );
  634. return results;
  635. // Class selector
  636. } else if ( (m = match[3]) && support.getElementsByClassName &&
  637. context.getElementsByClassName ) {
  638. push.apply( results, context.getElementsByClassName( m ) );
  639. return results;
  640. }
  641. }
  642. // Take advantage of querySelectorAll
  643. if ( support.qsa &&
  644. !compilerCache[ selector + " " ] &&
  645. (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
  646. if ( nodeType !== 1 ) {
  647. newContext = context;
  648. newSelector = selector;
  649. // qSA looks outside Element context, which is not what we want
  650. // Thanks to Andrew Dupont for this workaround technique
  651. // Support: IE <=8
  652. // Exclude object elements
  653. } else if ( context.nodeName.toLowerCase() !== "object" ) {
  654. // Capture the context ID, setting it first if necessary
  655. if ( (nid = context.getAttribute( "id" )) ) {
  656. nid = nid.replace( rcssescape, fcssescape );
  657. } else {
  658. context.setAttribute( "id", (nid = expando) );
  659. }
  660. // Prefix every selector in the list
  661. groups = tokenize( selector );
  662. i = groups.length;
  663. while ( i-- ) {
  664. groups[i] = "#" + nid + " " + toSelector( groups[i] );
  665. }
  666. newSelector = groups.join( "," );
  667. // Expand context for sibling selectors
  668. newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
  669. context;
  670. }
  671. if ( newSelector ) {
  672. try {
  673. push.apply( results,
  674. newContext.querySelectorAll( newSelector )
  675. );
  676. return results;
  677. } catch ( qsaError ) {
  678. } finally {
  679. if ( nid === expando ) {
  680. context.removeAttribute( "id" );
  681. }
  682. }
  683. }
  684. }
  685. }
  686. }
  687. // All others
  688. return select( selector.replace( rtrim, "$1" ), context, results, seed );
  689. }
  690. /**
  691. * Create key-value caches of limited size
  692. * @returns {function(string, object)} Returns the Object data after storing it on itself with
  693. * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
  694. * deleting the oldest entry
  695. */
  696. function createCache() {
  697. var keys = [];
  698. function cache( key, value ) {
  699. // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  700. if ( keys.push( key + " " ) > Expr.cacheLength ) {
  701. // Only keep the most recent entries
  702. delete cache[ keys.shift() ];
  703. }
  704. return (cache[ key + " " ] = value);
  705. }
  706. return cache;
  707. }
  708. /**
  709. * Mark a function for special use by Sizzle
  710. * @param {Function} fn The function to mark
  711. */
  712. function markFunction( fn ) {
  713. fn[ expando ] = true;
  714. return fn;
  715. }
  716. /**
  717. * Support testing using an element
  718. * @param {Function} fn Passed the created element and returns a boolean result
  719. */
  720. function assert( fn ) {
  721. var el = document.createElement("fieldset");
  722. try {
  723. return !!fn( el );
  724. } catch (e) {
  725. return false;
  726. } finally {
  727. // Remove from its parent by default
  728. if ( el.parentNode ) {
  729. el.parentNode.removeChild( el );
  730. }
  731. // release memory in IE
  732. el = null;
  733. }
  734. }
  735. /**
  736. * Adds the same handler for all of the specified attrs
  737. * @param {String} attrs Pipe-separated list of attributes
  738. * @param {Function} handler The method that will be applied
  739. */
  740. function addHandle( attrs, handler ) {
  741. var arr = attrs.split("|"),
  742. i = arr.length;
  743. while ( i-- ) {
  744. Expr.attrHandle[ arr[i] ] = handler;
  745. }
  746. }
  747. /**
  748. * Checks document order of two siblings
  749. * @param {Element} a
  750. * @param {Element} b
  751. * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
  752. */
  753. function siblingCheck( a, b ) {
  754. var cur = b && a,
  755. diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  756. a.sourceIndex - b.sourceIndex;
  757. // Use IE sourceIndex if available on both nodes
  758. if ( diff ) {
  759. return diff;
  760. }
  761. // Check if b follows a
  762. if ( cur ) {
  763. while ( (cur = cur.nextSibling) ) {
  764. if ( cur === b ) {
  765. return -1;
  766. }
  767. }
  768. }
  769. return a ? 1 : -1;
  770. }
  771. /**
  772. * Returns a function to use in pseudos for input types
  773. * @param {String} type
  774. */
  775. function createInputPseudo( type ) {
  776. return function( elem ) {
  777. var name = elem.nodeName.toLowerCase();
  778. return name === "input" && elem.type === type;
  779. };
  780. }
  781. /**
  782. * Returns a function to use in pseudos for buttons
  783. * @param {String} type
  784. */
  785. function createButtonPseudo( type ) {
  786. return function( elem ) {
  787. var name = elem.nodeName.toLowerCase();
  788. return (name === "input" || name === "button") && elem.type === type;
  789. };
  790. }
  791. /**
  792. * Returns a function to use in pseudos for :enabled/:disabled
  793. * @param {Boolean} disabled true for :disabled; false for :enabled
  794. */
  795. function createDisabledPseudo( disabled ) {
  796. // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
  797. return function( elem ) {
  798. // Only certain elements can match :enabled or :disabled
  799. // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
  800. // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
  801. if ( "form" in elem ) {
  802. // Check for inherited disabledness on relevant non-disabled elements:
  803. // * listed form-associated elements in a disabled fieldset
  804. // https://html.spec.whatwg.org/multipage/forms.html#category-listed
  805. // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
  806. // * option elements in a disabled optgroup
  807. // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
  808. // All such elements have a "form" property.
  809. if ( elem.parentNode && elem.disabled === false ) {
  810. // Option elements defer to a parent optgroup if present
  811. if ( "label" in elem ) {
  812. if ( "label" in elem.parentNode ) {
  813. return elem.parentNode.disabled === disabled;
  814. } else {
  815. return elem.disabled === disabled;
  816. }
  817. }
  818. // Support: IE 6 - 11
  819. // Use the isDisabled shortcut property to check for disabled fieldset ancestors
  820. return elem.isDisabled === disabled ||
  821. // Where there is no isDisabled, check manually
  822. /* jshint -W018 */
  823. elem.isDisabled !== !disabled &&
  824. disabledAncestor( elem ) === disabled;
  825. }
  826. return elem.disabled === disabled;
  827. // Try to winnow out elements that can't be disabled before trusting the disabled property.
  828. // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
  829. // even exist on them, let alone have a boolean value.
  830. } else if ( "label" in elem ) {
  831. return elem.disabled === disabled;
  832. }
  833. // Remaining elements are neither :enabled nor :disabled
  834. return false;
  835. };
  836. }
  837. /**
  838. * Returns a function to use in pseudos for positionals
  839. * @param {Function} fn
  840. */
  841. function createPositionalPseudo( fn ) {
  842. return markFunction(function( argument ) {
  843. argument = +argument;
  844. return markFunction(function( seed, matches ) {
  845. var j,
  846. matchIndexes = fn( [], seed.length, argument ),
  847. i = matchIndexes.length;
  848. // Match elements found at the specified indexes
  849. while ( i-- ) {
  850. if ( seed[ (j = matchIndexes[i]) ] ) {
  851. seed[j] = !(matches[j] = seed[j]);
  852. }
  853. }
  854. });
  855. });
  856. }
  857. /**
  858. * Checks a node for validity as a Sizzle context
  859. * @param {Element|Object=} context
  860. * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
  861. */
  862. function testContext( context ) {
  863. return context && typeof context.getElementsByTagName !== "undefined" && context;
  864. }
  865. // Expose support vars for convenience
  866. support = Sizzle.support = {};
  867. /**
  868. * Detects XML nodes
  869. * @param {Element|Object} elem An element or a document
  870. * @returns {Boolean} True iff elem is a non-HTML XML node
  871. */
  872. isXML = Sizzle.isXML = function( elem ) {
  873. // documentElement is verified for cases where it doesn't yet exist
  874. // (such as loading iframes in IE - #4833)
  875. var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  876. return documentElement ? documentElement.nodeName !== "HTML" : false;
  877. };
  878. /**
  879. * Sets document-related variables once based on the current document
  880. * @param {Element|Object} [doc] An element or document object to use to set the document
  881. * @returns {Object} Returns the current document
  882. */
  883. setDocument = Sizzle.setDocument = function( node ) {
  884. var hasCompare, subWindow,
  885. doc = node ? node.ownerDocument || node : preferredDoc;
  886. // Return early if doc is invalid or already selected
  887. if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  888. return document;
  889. }
  890. // Update global variables
  891. document = doc;
  892. docElem = document.documentElement;
  893. documentIsHTML = !isXML( document );
  894. // Support: IE 9-11, Edge
  895. // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
  896. if ( preferredDoc !== document &&
  897. (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
  898. // Support: IE 11, Edge
  899. if ( subWindow.addEventListener ) {
  900. subWindow.addEventListener( "unload", unloadHandler, false );
  901. // Support: IE 9 - 10 only
  902. } else if ( subWindow.attachEvent ) {
  903. subWindow.attachEvent( "onunload", unloadHandler );
  904. }
  905. }
  906. /* Attributes
  907. ---------------------------------------------------------------------- */
  908. // Support: IE<8
  909. // Verify that getAttribute really returns attributes and not properties
  910. // (excepting IE8 booleans)
  911. support.attributes = assert(function( el ) {
  912. el.className = "i";
  913. return !el.getAttribute("className");
  914. });
  915. /* getElement(s)By*
  916. ---------------------------------------------------------------------- */
  917. // Check if getElementsByTagName("*") returns only elements
  918. support.getElementsByTagName = assert(function( el ) {
  919. el.appendChild( document.createComment("") );
  920. return !el.getElementsByTagName("*").length;
  921. });
  922. // Support: IE<9
  923. support.getElementsByClassName = rnative.test( document.getElementsByClassName );
  924. // Support: IE<10
  925. // Check if getElementById returns elements by name
  926. // The broken getElementById methods don't pick up programmatically-set names,
  927. // so use a roundabout getElementsByName test
  928. support.getById = assert(function( el ) {
  929. docElem.appendChild( el ).id = expando;
  930. return !document.getElementsByName || !document.getElementsByName( expando ).length;
  931. });
  932. // ID filter and find
  933. if ( support.getById ) {
  934. Expr.filter["ID"] = function( id ) {
  935. var attrId = id.replace( runescape, funescape );
  936. return function( elem ) {
  937. return elem.getAttribute("id") === attrId;
  938. };
  939. };
  940. Expr.find["ID"] = function( id, context ) {
  941. if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  942. var elem = context.getElementById( id );
  943. return elem ? [ elem ] : [];
  944. }
  945. };
  946. } else {
  947. Expr.filter["ID"] = function( id ) {
  948. var attrId = id.replace( runescape, funescape );
  949. return function( elem ) {
  950. var node = typeof elem.getAttributeNode !== "undefined" &&
  951. elem.getAttributeNode("id");
  952. return node && node.value === attrId;
  953. };
  954. };
  955. // Support: IE 6 - 7 only
  956. // getElementById is not reliable as a find shortcut
  957. Expr.find["ID"] = function( id, context ) {
  958. if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  959. var node, i, elems,
  960. elem = context.getElementById( id );
  961. if ( elem ) {
  962. // Verify the id attribute
  963. node = elem.getAttributeNode("id");
  964. if ( node && node.value === id ) {
  965. return [ elem ];
  966. }
  967. // Fall back on getElementsByName
  968. elems = context.getElementsByName( id );
  969. i = 0;
  970. while ( (elem = elems[i++]) ) {
  971. node = elem.getAttributeNode("id");
  972. if ( node && node.value === id ) {
  973. return [ elem ];
  974. }
  975. }
  976. }
  977. return [];
  978. }
  979. };
  980. }
  981. // Tag
  982. Expr.find["TAG"] = support.getElementsByTagName ?
  983. function( tag, context ) {
  984. if ( typeof context.getElementsByTagName !== "undefined" ) {
  985. return context.getElementsByTagName( tag );
  986. // DocumentFragment nodes don't have gEBTN
  987. } else if ( support.qsa ) {
  988. return context.querySelectorAll( tag );
  989. }
  990. } :
  991. function( tag, context ) {
  992. var elem,
  993. tmp = [],
  994. i = 0,
  995. // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
  996. results = context.getElementsByTagName( tag );
  997. // Filter out possible comments
  998. if ( tag === "*" ) {
  999. while ( (elem = results[i++]) ) {
  1000. if ( elem.nodeType === 1 ) {
  1001. tmp.push( elem );
  1002. }
  1003. }
  1004. return tmp;
  1005. }
  1006. return results;
  1007. };
  1008. // Class
  1009. Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  1010. if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
  1011. return context.getElementsByClassName( className );
  1012. }
  1013. };
  1014. /* QSA/matchesSelector
  1015. ---------------------------------------------------------------------- */
  1016. // QSA and matchesSelector support
  1017. // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  1018. rbuggyMatches = [];
  1019. // qSa(:focus) reports false when true (Chrome 21)
  1020. // We allow this because of a bug in IE8/9 that throws an error
  1021. // whenever `document.activeElement` is accessed on an iframe
  1022. // So, we allow :focus to pass through QSA all the time to avoid the IE error
  1023. // See https://bugs.jquery.com/ticket/13378
  1024. rbuggyQSA = [];
  1025. if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
  1026. // Build QSA regex
  1027. // Regex strategy adopted from Diego Perini
  1028. assert(function( el ) {
  1029. // Select is set to empty string on purpose
  1030. // This is to test IE's treatment of not explicitly
  1031. // setting a boolean content attribute,
  1032. // since its presence should be enough
  1033. // https://bugs.jquery.com/ticket/12359
  1034. docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
  1035. "<select id='" + expando + "-\r\\' msallowcapture=''>" +
  1036. "<option selected=''></option></select>";
  1037. // Support: IE8, Opera 11-12.16
  1038. // Nothing should be selected when empty strings follow ^= or $= or *=
  1039. // The test attribute must be unknown in Opera but "safe" for WinRT
  1040. // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  1041. if ( el.querySelectorAll("[msallowcapture^='']").length ) {
  1042. rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  1043. }
  1044. // Support: IE8
  1045. // Boolean attributes and "value" are not treated correctly
  1046. if ( !el.querySelectorAll("[selected]").length ) {
  1047. rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  1048. }
  1049. // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
  1050. if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
  1051. rbuggyQSA.push("~=");
  1052. }
  1053. // Webkit/Opera - :checked should return selected option elements
  1054. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1055. // IE8 throws error here and will not see later tests
  1056. if ( !el.querySelectorAll(":checked").length ) {
  1057. rbuggyQSA.push(":checked");
  1058. }
  1059. // Support: Safari 8+, iOS 8+
  1060. // https://bugs.webkit.org/show_bug.cgi?id=136851
  1061. // In-page `selector#id sibling-combinator selector` fails
  1062. if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
  1063. rbuggyQSA.push(".#.+[+~]");
  1064. }
  1065. });
  1066. assert(function( el ) {
  1067. el.innerHTML = "<a href='' disabled='disabled'></a>" +
  1068. "<select disabled='disabled'><option/></select>";
  1069. // Support: Windows 8 Native Apps
  1070. // The type and name attributes are restricted during .innerHTML assignment
  1071. var input = document.createElement("input");
  1072. input.setAttribute( "type", "hidden" );
  1073. el.appendChild( input ).setAttribute( "name", "D" );
  1074. // Support: IE8
  1075. // Enforce case-sensitivity of name attribute
  1076. if ( el.querySelectorAll("[name=d]").length ) {
  1077. rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
  1078. }
  1079. // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  1080. // IE8 throws error here and will not see later tests
  1081. if ( el.querySelectorAll(":enabled").length !== 2 ) {
  1082. rbuggyQSA.push( ":enabled", ":disabled" );
  1083. }
  1084. // Support: IE9-11+
  1085. // IE's :disabled selector does not pick up the children of disabled fieldsets
  1086. docElem.appendChild( el ).disabled = true;
  1087. if ( el.querySelectorAll(":disabled").length !== 2 ) {
  1088. rbuggyQSA.push( ":enabled", ":disabled" );
  1089. }
  1090. // Opera 10-11 does not throw on post-comma invalid pseudos
  1091. el.querySelectorAll("*,:x");
  1092. rbuggyQSA.push(",.*:");
  1093. });
  1094. }
  1095. if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
  1096. docElem.webkitMatchesSelector ||
  1097. docElem.mozMatchesSelector ||
  1098. docElem.oMatchesSelector ||
  1099. docElem.msMatchesSelector) )) ) {
  1100. assert(function( el ) {
  1101. // Check to see if it's possible to do matchesSelector
  1102. // on a disconnected node (IE 9)
  1103. support.disconnectedMatch = matches.call( el, "*" );
  1104. // This should fail with an exception
  1105. // Gecko does not error, returns false instead
  1106. matches.call( el, "[s!='']:x" );
  1107. rbuggyMatches.push( "!=", pseudos );
  1108. });
  1109. }
  1110. rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
  1111. rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
  1112. /* Contains
  1113. ---------------------------------------------------------------------- */
  1114. hasCompare = rnative.test( docElem.compareDocumentPosition );
  1115. // Element contains another
  1116. // Purposefully self-exclusive
  1117. // As in, an element does not contain itself
  1118. contains = hasCompare || rnative.test( docElem.contains ) ?
  1119. function( a, b ) {
  1120. var adown = a.nodeType === 9 ? a.documentElement : a,
  1121. bup = b && b.parentNode;
  1122. return a === bup || !!( bup && bup.nodeType === 1 && (
  1123. adown.contains ?
  1124. adown.contains( bup ) :
  1125. a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
  1126. ));
  1127. } :
  1128. function( a, b ) {
  1129. if ( b ) {
  1130. while ( (b = b.parentNode) ) {
  1131. if ( b === a ) {
  1132. return true;
  1133. }
  1134. }
  1135. }
  1136. return false;
  1137. };
  1138. /* Sorting
  1139. ---------------------------------------------------------------------- */
  1140. // Document order sorting
  1141. sortOrder = hasCompare ?
  1142. function( a, b ) {
  1143. // Flag for duplicate removal
  1144. if ( a === b ) {
  1145. hasDuplicate = true;
  1146. return 0;
  1147. }
  1148. // Sort on method existence if only one input has compareDocumentPosition
  1149. var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
  1150. if ( compare ) {
  1151. return compare;
  1152. }
  1153. // Calculate position if both inputs belong to the same document
  1154. compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
  1155. a.compareDocumentPosition( b ) :
  1156. // Otherwise we know they are disconnected
  1157. 1;
  1158. // Disconnected nodes
  1159. if ( compare & 1 ||
  1160. (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
  1161. // Choose the first element that is related to our preferred document
  1162. if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
  1163. return -1;
  1164. }
  1165. if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
  1166. return 1;
  1167. }
  1168. // Maintain original order
  1169. return sortInput ?
  1170. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1171. 0;
  1172. }
  1173. return compare & 4 ? -1 : 1;
  1174. } :
  1175. function( a, b ) {
  1176. // Exit early if the nodes are identical
  1177. if ( a === b ) {
  1178. hasDuplicate = true;
  1179. return 0;
  1180. }
  1181. var cur,
  1182. i = 0,
  1183. aup = a.parentNode,
  1184. bup = b.parentNode,
  1185. ap = [ a ],
  1186. bp = [ b ];
  1187. // Parentless nodes are either documents or disconnected
  1188. if ( !aup || !bup ) {
  1189. return a === document ? -1 :
  1190. b === document ? 1 :
  1191. aup ? -1 :
  1192. bup ? 1 :
  1193. sortInput ?
  1194. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1195. 0;
  1196. // If the nodes are siblings, we can do a quick check
  1197. } else if ( aup === bup ) {
  1198. return siblingCheck( a, b );
  1199. }
  1200. // Otherwise we need full lists of their ancestors for comparison
  1201. cur = a;
  1202. while ( (cur = cur.parentNode) ) {
  1203. ap.unshift( cur );
  1204. }
  1205. cur = b;
  1206. while ( (cur = cur.parentNode) ) {
  1207. bp.unshift( cur );
  1208. }
  1209. // Walk down the tree looking for a discrepancy
  1210. while ( ap[i] === bp[i] ) {
  1211. i++;
  1212. }
  1213. return i ?
  1214. // Do a sibling check if the nodes have a common ancestor
  1215. siblingCheck( ap[i], bp[i] ) :
  1216. // Otherwise nodes in our document sort first
  1217. ap[i] === preferredDoc ? -1 :
  1218. bp[i] === preferredDoc ? 1 :
  1219. 0;
  1220. };
  1221. return document;
  1222. };
  1223. Sizzle.matches = function( expr, elements ) {
  1224. return Sizzle( expr, null, null, elements );
  1225. };
  1226. Sizzle.matchesSelector = function( elem, expr ) {
  1227. // Set document vars if needed
  1228. if ( ( elem.ownerDocument || elem ) !== document ) {
  1229. setDocument( elem );
  1230. }
  1231. // Make sure that attribute selectors are quoted
  1232. expr = expr.replace( rattributeQuotes, "='$1']" );
  1233. if ( support.matchesSelector && documentIsHTML &&
  1234. !compilerCache[ expr + " " ] &&
  1235. ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
  1236. ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
  1237. try {
  1238. var ret = matches.call( elem, expr );
  1239. // IE 9's matchesSelector returns false on disconnected nodes
  1240. if ( ret || support.disconnectedMatch ||
  1241. // As well, disconnected nodes are said to be in a document
  1242. // fragment in IE 9
  1243. elem.document && elem.document.nodeType !== 11 ) {
  1244. return ret;
  1245. }
  1246. } catch (e) {}
  1247. }
  1248. return Sizzle( expr, document, null, [ elem ] ).length > 0;
  1249. };
  1250. Sizzle.contains = function( context, elem ) {
  1251. // Set document vars if needed
  1252. if ( ( context.ownerDocument || context ) !== document ) {
  1253. setDocument( context );
  1254. }
  1255. return contains( context, elem );
  1256. };
  1257. Sizzle.attr = function( elem, name ) {
  1258. // Set document vars if needed
  1259. if ( ( elem.ownerDocument || elem ) !== document ) {
  1260. setDocument( elem );
  1261. }
  1262. var fn = Expr.attrHandle[ name.toLowerCase() ],
  1263. // Don't get fooled by Object.prototype properties (jQuery #13807)
  1264. val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
  1265. fn( elem, name, !documentIsHTML ) :
  1266. undefined;
  1267. return val !== undefined ?
  1268. val :
  1269. support.attributes || !documentIsHTML ?
  1270. elem.getAttribute( name ) :
  1271. (val = elem.getAttributeNode(name)) && val.specified ?
  1272. val.value :
  1273. null;
  1274. };
  1275. Sizzle.escape = function( sel ) {
  1276. return (sel + "").replace( rcssescape, fcssescape );
  1277. };
  1278. Sizzle.error = function( msg ) {
  1279. throw new Error( "Syntax error, unrecognized expression: " + msg );
  1280. };
  1281. /**
  1282. * Document sorting and removing duplicates
  1283. * @param {ArrayLike} results
  1284. */
  1285. Sizzle.uniqueSort = function( results ) {
  1286. var elem,
  1287. duplicates = [],
  1288. j = 0,
  1289. i = 0;
  1290. // Unless we *know* we can detect duplicates, assume their presence
  1291. hasDuplicate = !support.detectDuplicates;
  1292. sortInput = !support.sortStable && results.slice( 0 );
  1293. results.sort( sortOrder );
  1294. if ( hasDuplicate ) {
  1295. while ( (elem = results[i++]) ) {
  1296. if ( elem === results[ i ] ) {
  1297. j = duplicates.push( i );
  1298. }
  1299. }
  1300. while ( j-- ) {
  1301. results.splice( duplicates[ j ], 1 );
  1302. }
  1303. }
  1304. // Clear input after sorting to release objects
  1305. // See https://github.com/jquery/sizzle/pull/225
  1306. sortInput = null;
  1307. return results;
  1308. };
  1309. /**
  1310. * Utility function for retrieving the text value of an array of DOM nodes
  1311. * @param {Array|Element} elem
  1312. */
  1313. getText = Sizzle.getText = function( elem ) {
  1314. var node,
  1315. ret = "",
  1316. i = 0,
  1317. nodeType = elem.nodeType;
  1318. if ( !nodeType ) {
  1319. // If no nodeType, this is expected to be an array
  1320. while ( (node = elem[i++]) ) {
  1321. // Do not traverse comment nodes
  1322. ret += getText( node );
  1323. }
  1324. } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
  1325. // Use textContent for elements
  1326. // innerText usage removed for consistency of new lines (jQuery #11153)
  1327. if ( typeof elem.textContent === "string" ) {
  1328. return elem.textContent;
  1329. } else {
  1330. // Traverse its children
  1331. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  1332. ret += getText( elem );
  1333. }
  1334. }
  1335. } else if ( nodeType === 3 || nodeType === 4 ) {
  1336. return elem.nodeValue;
  1337. }
  1338. // Do not include comment or processing instruction nodes
  1339. return ret;
  1340. };
  1341. Expr = Sizzle.selectors = {
  1342. // Can be adjusted by the user
  1343. cacheLength: 50,
  1344. createPseudo: markFunction,
  1345. match: matchExpr,
  1346. attrHandle: {},
  1347. find: {},
  1348. relative: {
  1349. ">": { dir: "parentNode", first: true },
  1350. " ": { dir: "parentNode" },
  1351. "+": { dir: "previousSibling", first: true },
  1352. "~": { dir: "previousSibling" }
  1353. },
  1354. preFilter: {
  1355. "ATTR": function( match ) {
  1356. match[1] = match[1].replace( runescape, funescape );
  1357. // Move the given value to match[3] whether quoted or unquoted
  1358. match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
  1359. if ( match[2] === "~=" ) {
  1360. match[3] = " " + match[3] + " ";
  1361. }
  1362. return match.slice( 0, 4 );
  1363. },
  1364. "CHILD": function( match ) {
  1365. /* matches from matchExpr["CHILD"]
  1366. 1 type (only|nth|...)
  1367. 2 what (child|of-type)
  1368. 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  1369. 4 xn-component of xn+y argument ([+-]?\d*n|)
  1370. 5 sign of xn-component
  1371. 6 x of xn-component
  1372. 7 sign of y-component
  1373. 8 y of y-component
  1374. */
  1375. match[1] = match[1].toLowerCase();
  1376. if ( match[1].slice( 0, 3 ) === "nth" ) {
  1377. // nth-* requires argument
  1378. if ( !match[3] ) {
  1379. Sizzle.error( match[0] );
  1380. }
  1381. // numeric x and y parameters for Expr.filter.CHILD
  1382. // remember that false/true cast respectively to 0/1
  1383. match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
  1384. match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
  1385. // other types prohibit arguments
  1386. } else if ( match[3] ) {
  1387. Sizzle.error( match[0] );
  1388. }
  1389. return match;
  1390. },
  1391. "PSEUDO": function( match ) {
  1392. var excess,
  1393. unquoted = !match[6] && match[2];
  1394. if ( matchExpr["CHILD"].test( match[0] ) ) {
  1395. return null;
  1396. }
  1397. // Accept quoted arguments as-is
  1398. if ( match[3] ) {
  1399. match[2] = match[4] || match[5] || "";
  1400. // Strip excess characters from unquoted arguments
  1401. } else if ( unquoted && rpseudo.test( unquoted ) &&
  1402. // Get excess from tokenize (recursively)
  1403. (excess = tokenize( unquoted, true )) &&
  1404. // advance to the next closing parenthesis
  1405. (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
  1406. // excess is a negative index
  1407. match[0] = match[0].slice( 0, excess );
  1408. match[2] = unquoted.slice( 0, excess );
  1409. }
  1410. // Return only captures needed by the pseudo filter method (type and argument)
  1411. return match.slice( 0, 3 );
  1412. }
  1413. },
  1414. filter: {
  1415. "TAG": function( nodeNameSelector ) {
  1416. var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
  1417. return nodeNameSelector === "*" ?
  1418. function() { return true; } :
  1419. function( elem ) {
  1420. return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  1421. };
  1422. },
  1423. "CLASS": function( className ) {
  1424. var pattern = classCache[ className + " " ];
  1425. return pattern ||
  1426. (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  1427. classCache( className, function( elem ) {
  1428. return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
  1429. });
  1430. },
  1431. "ATTR": function( name, operator, check ) {
  1432. return function( elem ) {
  1433. var result = Sizzle.attr( elem, name );
  1434. if ( result == null ) {
  1435. return operator === "!=";
  1436. }
  1437. if ( !operator ) {
  1438. return true;
  1439. }
  1440. result += "";
  1441. return operator === "=" ? result === check :
  1442. operator === "!=" ? result !== check :
  1443. operator === "^=" ? check && result.indexOf( check ) === 0 :
  1444. operator === "*=" ? check && result.indexOf( check ) > -1 :
  1445. operator === "$=" ? check && result.slice( -check.length ) === check :
  1446. operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
  1447. operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  1448. false;
  1449. };
  1450. },
  1451. "CHILD": function( type, what, argument, first, last ) {
  1452. var simple = type.slice( 0, 3 ) !== "nth",
  1453. forward = type.slice( -4 ) !== "last",
  1454. ofType = what === "of-type";
  1455. return first === 1 && last === 0 ?
  1456. // Shortcut for :nth-*(n)
  1457. function( elem ) {
  1458. return !!elem.parentNode;
  1459. } :
  1460. function( elem, context, xml ) {
  1461. var cache, uniqueCache, outerCache, node, nodeIndex, start,
  1462. dir = simple !== forward ? "nextSibling" : "previousSibling",
  1463. parent = elem.parentNode,
  1464. name = ofType && elem.nodeName.toLowerCase(),
  1465. useCache = !xml && !ofType,
  1466. diff = false;
  1467. if ( parent ) {
  1468. // :(first|last|only)-(child|of-type)
  1469. if ( simple ) {
  1470. while ( dir ) {
  1471. node = elem;
  1472. while ( (node = node[ dir ]) ) {
  1473. if ( ofType ?
  1474. node.nodeName.toLowerCase() === name :
  1475. node.nodeType === 1 ) {
  1476. return false;
  1477. }
  1478. }
  1479. // Reverse direction for :only-* (if we haven't yet done so)
  1480. start = dir = type === "only" && !start && "nextSibling";
  1481. }
  1482. return true;
  1483. }
  1484. start = [ forward ? parent.firstChild : parent.lastChild ];
  1485. // non-xml :nth-child(...) stores cache data on `parent`
  1486. if ( forward && useCache ) {
  1487. // Seek `elem` from a previously-cached index
  1488. // ...in a gzip-friendly way
  1489. node = parent;
  1490. outerCache = node[ expando ] || (node[ expando ] = {});
  1491. // Support: IE <9 only
  1492. // Defend against cloned attroperties (jQuery gh-1709)
  1493. uniqueCache = outerCache[ node.uniqueID ] ||
  1494. (outerCache[ node.uniqueID ] = {});
  1495. cache = uniqueCache[ type ] || [];
  1496. nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
  1497. diff = nodeIndex && cache[ 2 ];
  1498. node = nodeIndex && parent.childNodes[ nodeIndex ];
  1499. while ( (node = ++nodeIndex && node && node[ dir ] ||
  1500. // Fallback to seeking `elem` from the start
  1501. (diff = nodeIndex = 0) || start.pop()) ) {
  1502. // When found, cache indexes on `parent` and break
  1503. if ( node.nodeType === 1 && ++diff && node === elem ) {
  1504. uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
  1505. break;
  1506. }
  1507. }
  1508. } else {
  1509. // Use previously-cached element index if available
  1510. if ( useCache ) {
  1511. // ...in a gzip-friendly way
  1512. node = elem;
  1513. outerCache = node[ expando ] || (node[ expando ] = {});
  1514. // Support: IE <9 only
  1515. // Defend against cloned attroperties (jQuery gh-1709)
  1516. uniqueCache = outerCache[ node.uniqueID ] ||
  1517. (outerCache[ node.uniqueID ] = {});
  1518. cache = uniqueCache[ type ] || [];
  1519. nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
  1520. diff = nodeIndex;
  1521. }
  1522. // xml :nth-child(...)
  1523. // or :nth-last-child(...) or :nth(-last)?-of-type(...)
  1524. if ( diff === false ) {
  1525. // Use the same loop as above to seek `elem` from the start
  1526. while ( (node = ++nodeIndex && node && node[ dir ] ||
  1527. (diff = nodeIndex = 0) || start.pop()) ) {
  1528. if ( ( ofType ?
  1529. node.nodeName.toLowerCase() === name :
  1530. node.nodeType === 1 ) &&
  1531. ++diff ) {
  1532. // Cache the index of each encountered element
  1533. if ( useCache ) {
  1534. outerCache = node[ expando ] || (node[ expando ] = {});
  1535. // Support: IE <9 only
  1536. // Defend against cloned attroperties (jQuery gh-1709)
  1537. uniqueCache = outerCache[ node.uniqueID ] ||
  1538. (outerCache[ node.uniqueID ] = {});
  1539. uniqueCache[ type ] = [ dirruns, diff ];
  1540. }
  1541. if ( node === elem ) {
  1542. break;
  1543. }
  1544. }
  1545. }
  1546. }
  1547. }
  1548. // Incorporate the offset, then check against cycle size
  1549. diff -= last;
  1550. return diff === first || ( diff % first === 0 && diff / first >= 0 );
  1551. }
  1552. };
  1553. },
  1554. "PSEUDO": function( pseudo, argument ) {
  1555. // pseudo-class names are case-insensitive
  1556. // http://www.w3.org/TR/selectors/#pseudo-classes
  1557. // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  1558. // Remember that setFilters inherits from pseudos
  1559. var args,
  1560. fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
  1561. Sizzle.error( "unsupported pseudo: " + pseudo );
  1562. // The user may use createPseudo to indicate that
  1563. // arguments are needed to create the filter function
  1564. // just as Sizzle does
  1565. if ( fn[ expando ] ) {
  1566. return fn( argument );
  1567. }
  1568. // But maintain support for old signatures
  1569. if ( fn.length > 1 ) {
  1570. args = [ pseudo, pseudo, "", argument ];
  1571. return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
  1572. markFunction(function( seed, matches ) {
  1573. var idx,
  1574. matched = fn( seed, argument ),
  1575. i = matched.length;
  1576. while ( i-- ) {
  1577. idx = indexOf( seed, matched[i] );
  1578. seed[ idx ] = !( matches[ idx ] = matched[i] );
  1579. }
  1580. }) :
  1581. function( elem ) {
  1582. return fn( elem, 0, args );
  1583. };
  1584. }
  1585. return fn;
  1586. }
  1587. },
  1588. pseudos: {
  1589. // Potentially complex pseudos
  1590. "not": markFunction(function( selector ) {
  1591. // Trim the selector passed to compile
  1592. // to avoid treating leading and trailing
  1593. // spaces as combinators
  1594. var input = [],
  1595. results = [],
  1596. matcher = compile( selector.replace( rtrim, "$1" ) );
  1597. return matcher[ expando ] ?
  1598. markFunction(function( seed, matches, context, xml ) {
  1599. var elem,
  1600. unmatched = matcher( seed, null, xml, [] ),
  1601. i = seed.length;
  1602. // Match elements unmatched by `matcher`
  1603. while ( i-- ) {
  1604. if ( (elem = unmatched[i]) ) {
  1605. seed[i] = !(matches[i] = elem);
  1606. }
  1607. }
  1608. }) :
  1609. function( elem, context, xml ) {
  1610. input[0] = elem;
  1611. matcher( input, null, xml, results );
  1612. // Don't keep the element (issue #299)
  1613. input[0] = null;
  1614. return !results.pop();
  1615. };
  1616. }),
  1617. "has": markFunction(function( selector ) {
  1618. return function( elem ) {
  1619. return Sizzle( selector, elem ).length > 0;
  1620. };
  1621. }),
  1622. "contains": markFunction(function( text ) {
  1623. text = text.replace( runescape, funescape );
  1624. return function( elem ) {
  1625. return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  1626. };
  1627. }),
  1628. // "Whether an element is represented by a :lang() selector
  1629. // is based solely on the element's language value
  1630. // being equal to the identifier C,
  1631. // or beginning with the identifier C immediately followed by "-".
  1632. // The matching of C against the element's language value is performed case-insensitively.
  1633. // The identifier C does not have to be a valid language name."
  1634. // http://www.w3.org/TR/selectors/#lang-pseudo
  1635. "lang": markFunction( function( lang ) {
  1636. // lang value must be a valid identifier
  1637. if ( !ridentifier.test(lang || "") ) {
  1638. Sizzle.error( "unsupported lang: " + lang );
  1639. }
  1640. lang = lang.replace( runescape, funescape ).toLowerCase();
  1641. return function( elem ) {
  1642. var elemLang;
  1643. do {
  1644. if ( (elemLang = documentIsHTML ?
  1645. elem.lang :
  1646. elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
  1647. elemLang = elemLang.toLowerCase();
  1648. return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
  1649. }
  1650. } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
  1651. return false;
  1652. };
  1653. }),
  1654. // Miscellaneous
  1655. "target": function( elem ) {
  1656. var hash = window.location && window.location.hash;
  1657. return hash && hash.slice( 1 ) === elem.id;
  1658. },
  1659. "root": function( elem ) {
  1660. return elem === docElem;
  1661. },
  1662. "focus": function( elem ) {
  1663. return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  1664. },
  1665. // Boolean properties
  1666. "enabled": createDisabledPseudo( false ),
  1667. "disabled": createDisabledPseudo( true ),
  1668. "checked": function( elem ) {
  1669. // In CSS3, :checked should return both checked and selected elements
  1670. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1671. var nodeName = elem.nodeName.toLowerCase();
  1672. return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  1673. },
  1674. "selected": function( elem ) {
  1675. // Accessing this property makes selected-by-default
  1676. // options in Safari work properly
  1677. if ( elem.parentNode ) {
  1678. elem.parentNode.selectedIndex;
  1679. }
  1680. return elem.selected === true;
  1681. },
  1682. // Contents
  1683. "empty": function( elem ) {
  1684. // http://www.w3.org/TR/selectors/#empty-pseudo
  1685. // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
  1686. // but not by others (comment: 8; processing instruction: 7; etc.)
  1687. // nodeType < 6 works because attributes (2) do not appear as children
  1688. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  1689. if ( elem.nodeType < 6 ) {
  1690. return false;
  1691. }
  1692. }
  1693. return true;
  1694. },
  1695. "parent": function( elem ) {
  1696. return !Expr.pseudos["empty"]( elem );
  1697. },
  1698. // Element/input types
  1699. "header": function( elem ) {
  1700. return rheader.test( elem.nodeName );
  1701. },
  1702. "input": function( elem ) {
  1703. return rinputs.test( elem.nodeName );
  1704. },
  1705. "button": function( elem ) {
  1706. var name = elem.nodeName.toLowerCase();
  1707. return name === "input" && elem.type === "button" || name === "button";
  1708. },
  1709. "text": function( elem ) {
  1710. var attr;
  1711. return elem.nodeName.toLowerCase() === "input" &&
  1712. elem.type === "text" &&
  1713. // Support: IE<8
  1714. // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
  1715. ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
  1716. },
  1717. // Position-in-collection
  1718. "first": createPositionalPseudo(function() {
  1719. return [ 0 ];
  1720. }),
  1721. "last": createPositionalPseudo(function( matchIndexes, length ) {
  1722. return [ length - 1 ];
  1723. }),
  1724. "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1725. return [ argument < 0 ? argument + length : argument ];
  1726. }),
  1727. "even": createPositionalPseudo(function( matchIndexes, length ) {
  1728. var i = 0;
  1729. for ( ; i < length; i += 2 ) {
  1730. matchIndexes.push( i );
  1731. }
  1732. return matchIndexes;
  1733. }),
  1734. "odd": createPositionalPseudo(function( matchIndexes, length ) {
  1735. var i = 1;
  1736. for ( ; i < length; i += 2 ) {
  1737. matchIndexes.push( i );
  1738. }
  1739. return matchIndexes;
  1740. }),
  1741. "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1742. var i = argument < 0 ? argument + length : argument;
  1743. for ( ; --i >= 0; ) {
  1744. matchIndexes.push( i );
  1745. }
  1746. return matchIndexes;
  1747. }),
  1748. "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1749. var i = argument < 0 ? argument + length : argument;
  1750. for ( ; ++i < length; ) {
  1751. matchIndexes.push( i );
  1752. }
  1753. return matchIndexes;
  1754. })
  1755. }
  1756. };
  1757. Expr.pseudos["nth"] = Expr.pseudos["eq"];
  1758. // Add button/input type pseudos
  1759. for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
  1760. Expr.pseudos[ i ] = createInputPseudo( i );
  1761. }
  1762. for ( i in { submit: true, reset: true } ) {
  1763. Expr.pseudos[ i ] = createButtonPseudo( i );
  1764. }
  1765. // Easy API for creating new setFilters
  1766. function setFilters() {}
  1767. setFilters.prototype = Expr.filters = Expr.pseudos;
  1768. Expr.setFilters = new setFilters();
  1769. tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
  1770. var matched, match, tokens, type,
  1771. soFar, groups, preFilters,
  1772. cached = tokenCache[ selector + " " ];
  1773. if ( cached ) {
  1774. return parseOnly ? 0 : cached.slice( 0 );
  1775. }
  1776. soFar = selector;
  1777. groups = [];
  1778. preFilters = Expr.preFilter;
  1779. while ( soFar ) {
  1780. // Comma and first run
  1781. if ( !matched || (match = rcomma.exec( soFar )) ) {
  1782. if ( match ) {
  1783. // Don't consume trailing commas as valid
  1784. soFar = soFar.slice( match[0].length ) || soFar;
  1785. }
  1786. groups.push( (tokens = []) );
  1787. }
  1788. matched = false;
  1789. // Combinators
  1790. if ( (match = rcombinators.exec( soFar )) ) {
  1791. matched = match.shift();
  1792. tokens.push({
  1793. value: matched,
  1794. // Cast descendant combinators to space
  1795. type: match[0].replace( rtrim, " " )
  1796. });
  1797. soFar = soFar.slice( matched.length );
  1798. }
  1799. // Filters
  1800. for ( type in Expr.filter ) {
  1801. if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
  1802. (match = preFilters[ type ]( match ))) ) {
  1803. matched = match.shift();
  1804. tokens.push({
  1805. value: matched,
  1806. type: type,
  1807. matches: match
  1808. });
  1809. soFar = soFar.slice( matched.length );
  1810. }
  1811. }
  1812. if ( !matched ) {
  1813. break;
  1814. }
  1815. }
  1816. // Return the length of the invalid excess
  1817. // if we're just parsing
  1818. // Otherwise, throw an error or return tokens
  1819. return parseOnly ?
  1820. soFar.length :
  1821. soFar ?
  1822. Sizzle.error( selector ) :
  1823. // Cache the tokens
  1824. tokenCache( selector, groups ).slice( 0 );
  1825. };
  1826. function toSelector( tokens ) {
  1827. var i = 0,
  1828. len = tokens.length,
  1829. selector = "";
  1830. for ( ; i < len; i++ ) {
  1831. selector += tokens[i].value;
  1832. }
  1833. return selector;
  1834. }
  1835. function addCombinator( matcher, combinator, base ) {
  1836. var dir = combinator.dir,
  1837. skip = combinator.next,
  1838. key = skip || dir,
  1839. checkNonElements = base && key === "parentNode",
  1840. doneName = done++;
  1841. return combinator.first ?
  1842. // Check against closest ancestor/preceding element
  1843. function( elem, context, xml ) {
  1844. while ( (elem = elem[ dir ]) ) {
  1845. if ( elem.nodeType === 1 || checkNonElements ) {
  1846. return matcher( elem, context, xml );
  1847. }
  1848. }
  1849. return false;
  1850. } :
  1851. // Check against all ancestor/preceding elements
  1852. function( elem, context, xml ) {
  1853. var oldCache, uniqueCache, outerCache,
  1854. newCache = [ dirruns, doneName ];
  1855. // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
  1856. if ( xml ) {
  1857. while ( (elem = elem[ dir ]) ) {
  1858. if ( elem.nodeType === 1 || checkNonElements ) {
  1859. if ( matcher( elem, context, xml ) ) {
  1860. return true;
  1861. }
  1862. }
  1863. }
  1864. } else {
  1865. while ( (elem = elem[ dir ]) ) {
  1866. if ( elem.nodeType === 1 || checkNonElements ) {
  1867. outerCache = elem[ expando ] || (elem[ expando ] = {});
  1868. // Support: IE <9 only
  1869. // Defend against cloned attroperties (jQuery gh-1709)
  1870. uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
  1871. if ( skip && skip === elem.nodeName.toLowerCase() ) {
  1872. elem = elem[ dir ] || elem;
  1873. } else if ( (oldCache = uniqueCache[ key ]) &&
  1874. oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
  1875. // Assign to newCache so results back-propagate to previous elements
  1876. return (newCache[ 2 ] = oldCache[ 2 ]);
  1877. } else {
  1878. // Reuse newcache so results back-propagate to previous elements
  1879. uniqueCache[ key ] = newCache;
  1880. // A match means we're done; a fail means we have to keep checking
  1881. if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
  1882. return true;
  1883. }
  1884. }
  1885. }
  1886. }
  1887. }
  1888. return false;
  1889. };
  1890. }
  1891. function elementMatcher( matchers ) {
  1892. return matchers.length > 1 ?
  1893. function( elem, context, xml ) {
  1894. var i = matchers.length;
  1895. while ( i-- ) {
  1896. if ( !matchers[i]( elem, context, xml ) ) {
  1897. return false;
  1898. }
  1899. }
  1900. return true;
  1901. } :
  1902. matchers[0];
  1903. }
  1904. function multipleContexts( selector, contexts, results ) {
  1905. var i = 0,
  1906. len = contexts.length;
  1907. for ( ; i < len; i++ ) {
  1908. Sizzle( selector, contexts[i], results );
  1909. }
  1910. return results;
  1911. }
  1912. function condense( unmatched, map, filter, context, xml ) {
  1913. var elem,
  1914. newUnmatched = [],
  1915. i = 0,
  1916. len = unmatched.length,
  1917. mapped = map != null;
  1918. for ( ; i < len; i++ ) {
  1919. if ( (elem = unmatched[i]) ) {
  1920. if ( !filter || filter( elem, context, xml ) ) {
  1921. newUnmatched.push( elem );
  1922. if ( mapped ) {
  1923. map.push( i );
  1924. }
  1925. }
  1926. }
  1927. }
  1928. return newUnmatched;
  1929. }
  1930. function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
  1931. if ( postFilter && !postFilter[ expando ] ) {
  1932. postFilter = setMatcher( postFilter );
  1933. }
  1934. if ( postFinder && !postFinder[ expando ] ) {
  1935. postFinder = setMatcher( postFinder, postSelector );
  1936. }
  1937. return markFunction(function( seed, results, context, xml ) {
  1938. var temp, i, elem,
  1939. preMap = [],
  1940. postMap = [],
  1941. preexisting = results.length,
  1942. // Get initial elements from seed or context
  1943. elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
  1944. // Prefilter to get matcher input, preserving a map for seed-results synchronization
  1945. matcherIn = preFilter && ( seed || !selector ) ?
  1946. condense( elems, preMap, preFilter, context, xml ) :
  1947. elems,
  1948. matcherOut = matcher ?
  1949. // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  1950. postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
  1951. // ...intermediate processing is necessary
  1952. [] :
  1953. // ...otherwise use results directly
  1954. results :
  1955. matcherIn;
  1956. // Find primary matches
  1957. if ( matcher ) {
  1958. matcher( matcherIn, matcherOut, context, xml );
  1959. }
  1960. // Apply postFilter
  1961. if ( postFilter ) {
  1962. temp = condense( matcherOut, postMap );
  1963. postFilter( temp, [], context, xml );
  1964. // Un-match failing elements by moving them back to matcherIn
  1965. i = temp.length;
  1966. while ( i-- ) {
  1967. if ( (elem = temp[i]) ) {
  1968. matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
  1969. }
  1970. }
  1971. }
  1972. if ( seed ) {
  1973. if ( postFinder || preFilter ) {
  1974. if ( postFinder ) {
  1975. // Get the final matcherOut by condensing this intermediate into postFinder contexts
  1976. temp = [];
  1977. i = matcherOut.length;
  1978. while ( i-- ) {
  1979. if ( (elem = matcherOut[i]) ) {
  1980. // Restore matcherIn since elem is not yet a final match
  1981. temp.push( (matcherIn[i] = elem) );
  1982. }
  1983. }
  1984. postFinder( null, (matcherOut = []), temp, xml );
  1985. }
  1986. // Move matched elements from seed to results to keep them synchronized
  1987. i = matcherOut.length;
  1988. while ( i-- ) {
  1989. if ( (elem = matcherOut[i]) &&
  1990. (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
  1991. seed[temp] = !(results[temp] = elem);
  1992. }
  1993. }
  1994. }
  1995. // Add elements to results, through postFinder if defined
  1996. } else {
  1997. matcherOut = condense(
  1998. matcherOut === results ?
  1999. matcherOut.splice( preexisting, matcherOut.length ) :
  2000. matcherOut
  2001. );
  2002. if ( postFinder ) {
  2003. postFinder( null, results, matcherOut, xml );
  2004. } else {
  2005. push.apply( results, matcherOut );
  2006. }
  2007. }
  2008. });
  2009. }
  2010. function matcherFromTokens( tokens ) {
  2011. var checkContext, matcher, j,
  2012. len = tokens.length,
  2013. leadingRelative = Expr.relative[ tokens[0].type ],
  2014. implicitRelative = leadingRelative || Expr.relative[" "],
  2015. i = leadingRelative ? 1 : 0,
  2016. // The foundational matcher ensures that elements are reachable from top-level context(s)
  2017. matchContext = addCombinator( function( elem ) {
  2018. return elem === checkContext;
  2019. }, implicitRelative, true ),
  2020. matchAnyContext = addCombinator( function( elem ) {
  2021. return indexOf( checkContext, elem ) > -1;
  2022. }, implicitRelative, true ),
  2023. matchers = [ function( elem, context, xml ) {
  2024. var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  2025. (checkContext = context).nodeType ?
  2026. matchContext( elem, context, xml ) :
  2027. matchAnyContext( elem, context, xml ) );
  2028. // Avoid hanging onto element (issue #299)
  2029. checkContext = null;
  2030. return ret;
  2031. } ];
  2032. for ( ; i < len; i++ ) {
  2033. if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  2034. matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  2035. } else {
  2036. matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
  2037. // Return special upon seeing a positional matcher
  2038. if ( matcher[ expando ] ) {
  2039. // Find the next relative operator (if any) for proper handling
  2040. j = ++i;
  2041. for ( ; j < len; j++ ) {
  2042. if ( Expr.relative[ tokens[j].type ] ) {
  2043. break;
  2044. }
  2045. }
  2046. return setMatcher(
  2047. i > 1 && elementMatcher( matchers ),
  2048. i > 1 && toSelector(
  2049. // If the preceding token was a descendant combinator, insert an implicit any-element `*`
  2050. tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
  2051. ).replace( rtrim, "$1" ),
  2052. matcher,
  2053. i < j && matcherFromTokens( tokens.slice( i, j ) ),
  2054. j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
  2055. j < len && toSelector( tokens )
  2056. );
  2057. }
  2058. matchers.push( matcher );
  2059. }
  2060. }
  2061. return elementMatcher( matchers );
  2062. }
  2063. function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  2064. var bySet = setMatchers.length > 0,
  2065. byElement = elementMatchers.length > 0,
  2066. superMatcher = function( seed, context, xml, results, outermost ) {
  2067. var elem, j, matcher,
  2068. matchedCount = 0,
  2069. i = "0",
  2070. unmatched = seed && [],
  2071. setMatched = [],
  2072. contextBackup = outermostContext,
  2073. // We must always have either seed elements or outermost context
  2074. elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
  2075. // Use integer dirruns iff this is the outermost matcher
  2076. dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
  2077. len = elems.length;
  2078. if ( outermost ) {
  2079. outermostContext = context === document || context || outermost;
  2080. }
  2081. // Add elements passing elementMatchers directly to results
  2082. // Support: IE<9, Safari
  2083. // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
  2084. for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
  2085. if ( byElement && elem ) {
  2086. j = 0;
  2087. if ( !context && elem.ownerDocument !== document ) {
  2088. setDocument( elem );
  2089. xml = !documentIsHTML;
  2090. }
  2091. while ( (matcher = elementMatchers[j++]) ) {
  2092. if ( matcher( elem, context || document, xml) ) {
  2093. results.push( elem );
  2094. break;
  2095. }
  2096. }
  2097. if ( outermost ) {
  2098. dirruns = dirrunsUnique;
  2099. }
  2100. }
  2101. // Track unmatched elements for set filters
  2102. if ( bySet ) {
  2103. // They will have gone through all possible matchers
  2104. if ( (elem = !matcher && elem) ) {
  2105. matchedCount--;
  2106. }
  2107. // Lengthen the array for every element, matched or not
  2108. if ( seed ) {
  2109. unmatched.push( elem );
  2110. }
  2111. }
  2112. }
  2113. // `i` is now the count of elements visited above, and adding it to `matchedCount`
  2114. // makes the latter nonnegative.
  2115. matchedCount += i;
  2116. // Apply set filters to unmatched elements
  2117. // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
  2118. // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
  2119. // no element matchers and no seed.
  2120. // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
  2121. // case, which will result in a "00" `matchedCount` that differs from `i` but is also
  2122. // numerically zero.
  2123. if ( bySet && i !== matchedCount ) {
  2124. j = 0;
  2125. while ( (matcher = setMatchers[j++]) ) {
  2126. matcher( unmatched, setMatched, context, xml );
  2127. }
  2128. if ( seed ) {
  2129. // Reintegrate element matches to eliminate the need for sorting
  2130. if ( matchedCount > 0 ) {
  2131. while ( i-- ) {
  2132. if ( !(unmatched[i] || setMatched[i]) ) {
  2133. setMatched[i] = pop.call( results );
  2134. }
  2135. }
  2136. }
  2137. // Discard index placeholder values to get only actual matches
  2138. setMatched = condense( setMatched );
  2139. }
  2140. // Add matches to results
  2141. push.apply( results, setMatched );
  2142. // Seedless set matches succeeding multiple successful matchers stipulate sorting
  2143. if ( outermost && !seed && setMatched.length > 0 &&
  2144. ( matchedCount + setMatchers.length ) > 1 ) {
  2145. Sizzle.uniqueSort( results );
  2146. }
  2147. }
  2148. // Override manipulation of globals by nested matchers
  2149. if ( outermost ) {
  2150. dirruns = dirrunsUnique;
  2151. outermostContext = contextBackup;
  2152. }
  2153. return unmatched;
  2154. };
  2155. return bySet ?
  2156. markFunction( superMatcher ) :
  2157. superMatcher;
  2158. }
  2159. compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
  2160. var i,
  2161. setMatchers = [],
  2162. elementMatchers = [],
  2163. cached = compilerCache[ selector + " " ];
  2164. if ( !cached ) {
  2165. // Generate a function of recursive functions that can be used to check each element
  2166. if ( !match ) {
  2167. match = tokenize( selector );
  2168. }
  2169. i = match.length;
  2170. while ( i-- ) {
  2171. cached = matcherFromTokens( match[i] );
  2172. if ( cached[ expando ] ) {
  2173. setMatchers.push( cached );
  2174. } else {
  2175. elementMatchers.push( cached );
  2176. }
  2177. }
  2178. // Cache the compiled function
  2179. cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
  2180. // Save selector and tokenization
  2181. cached.selector = selector;
  2182. }
  2183. return cached;
  2184. };
  2185. /**
  2186. * A low-level selection function that works with Sizzle's compiled
  2187. * selector functions
  2188. * @param {String|Function} selector A selector or a pre-compiled
  2189. * selector function built with Sizzle.compile
  2190. * @param {Element} context
  2191. * @param {Array} [results]
  2192. * @param {Array} [seed] A set of elements to match against
  2193. */
  2194. select = Sizzle.select = function( selector, context, results, seed ) {
  2195. var i, tokens, token, type, find,
  2196. compiled = typeof selector === "function" && selector,
  2197. match = !seed && tokenize( (selector = compiled.selector || selector) );
  2198. results = results || [];
  2199. // Try to minimize operations if there is only one selector in the list and no seed
  2200. // (the latter of which guarantees us context)
  2201. if ( match.length === 1 ) {
  2202. // Reduce context if the leading compound selector is an ID
  2203. tokens = match[0] = match[0].slice( 0 );
  2204. if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  2205. context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
  2206. context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
  2207. if ( !context ) {
  2208. return results;
  2209. // Precompiled matchers will still verify ancestry, so step up a level
  2210. } else if ( compiled ) {
  2211. context = context.parentNode;
  2212. }
  2213. selector = selector.slice( tokens.shift().value.length );
  2214. }
  2215. // Fetch a seed set for right-to-left matching
  2216. i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
  2217. while ( i-- ) {
  2218. token = tokens[i];
  2219. // Abort if we hit a combinator
  2220. if ( Expr.relative[ (type = token.type) ] ) {
  2221. break;
  2222. }
  2223. if ( (find = Expr.find[ type ]) ) {
  2224. // Search, expanding context for leading sibling combinators
  2225. if ( (seed = find(
  2226. token.matches[0].replace( runescape, funescape ),
  2227. rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
  2228. )) ) {
  2229. // If seed is empty or no tokens remain, we can return early
  2230. tokens.splice( i, 1 );
  2231. selector = seed.length && toSelector( tokens );
  2232. if ( !selector ) {
  2233. push.apply( results, seed );
  2234. return results;
  2235. }
  2236. break;
  2237. }
  2238. }
  2239. }
  2240. }
  2241. // Compile and execute a filtering function if one is not provided
  2242. // Provide `match` to avoid retokenization if we modified the selector above
  2243. ( compiled || compile( selector, match ) )(
  2244. seed,
  2245. context,
  2246. !documentIsHTML,
  2247. results,
  2248. !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
  2249. );
  2250. return results;
  2251. };
  2252. // One-time assignments
  2253. // Sort stability
  2254. support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  2255. // Support: Chrome 14-35+
  2256. // Always assume duplicates if they aren't passed to the comparison function
  2257. support.detectDuplicates = !!hasDuplicate;
  2258. // Initialize against the default document
  2259. setDocument();
  2260. // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  2261. // Detached nodes confoundingly follow *each other*
  2262. support.sortDetached = assert(function( el ) {
  2263. // Should return 1, but returns 4 (following)
  2264. return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
  2265. });
  2266. // Support: IE<8
  2267. // Prevent attribute/property "interpolation"
  2268. // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  2269. if ( !assert(function( el ) {
  2270. el.innerHTML = "<a href='#'></a>";
  2271. return el.firstChild.getAttribute("href") === "#" ;
  2272. }) ) {
  2273. addHandle( "type|href|height|width", function( elem, name, isXML ) {
  2274. if ( !isXML ) {
  2275. return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
  2276. }
  2277. });
  2278. }
  2279. // Support: IE<9
  2280. // Use defaultValue in place of getAttribute("value")
  2281. if ( !support.attributes || !assert(function( el ) {
  2282. el.innerHTML = "<input/>";
  2283. el.firstChild.setAttribute( "value", "" );
  2284. return el.firstChild.getAttribute( "value" ) === "";
  2285. }) ) {
  2286. addHandle( "value", function( elem, name, isXML ) {
  2287. if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
  2288. return elem.defaultValue;
  2289. }
  2290. });
  2291. }
  2292. // Support: IE<9
  2293. // Use getAttributeNode to fetch booleans when getAttribute lies
  2294. if ( !assert(function( el ) {
  2295. return el.getAttribute("disabled") == null;
  2296. }) ) {
  2297. addHandle( booleans, function( elem, name, isXML ) {
  2298. var val;
  2299. if ( !isXML ) {
  2300. return elem[ name ] === true ? name.toLowerCase() :
  2301. (val = elem.getAttributeNode( name )) && val.specified ?
  2302. val.value :
  2303. null;
  2304. }
  2305. });
  2306. }
  2307. // EXPOSE
  2308. var _sizzle = window.Sizzle;
  2309. Sizzle.noConflict = function() {
  2310. if ( window.Sizzle === Sizzle ) {
  2311. window.Sizzle = _sizzle;
  2312. }
  2313. return Sizzle;
  2314. };
  2315. if ( typeof define === "function" && define.amd ) {
  2316. define('sizzle',[],function() { return Sizzle; });
  2317. // Sizzle requires that there be a global window in Common-JS like environments
  2318. } else if ( typeof module !== "undefined" && module.exports ) {
  2319. module.exports = Sizzle;
  2320. } else {
  2321. window.Sizzle = Sizzle;
  2322. }
  2323. // EXPOSE
  2324. })( window );
  2325. define('lodash.fp',['lodash', 'lodash.converter'], function (_, lodashConverter) {
  2326. var fp = lodashConverter(_.runInContext());
  2327. return fp;
  2328. });
  2329. function CustomEvent ( event, params ) {
  2330. params = params || { bubbles: false, cancelable: false, detail: undefined };
  2331. var evt = document.createEvent( 'CustomEvent' );
  2332. evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
  2333. return evt;
  2334. }
  2335. if ( typeof window.CustomEvent !== "function" ) {
  2336. CustomEvent.prototype = window.Event.prototype;
  2337. window.CustomEvent = CustomEvent;
  2338. }
  2339. if (!String.prototype.includes) {
  2340. String.prototype.includes = function(search, start) {
  2341. 'use strict';
  2342. if (typeof start !== 'number') {
  2343. start = 0;
  2344. }
  2345. if (start + search.length > this.length) {
  2346. return false;
  2347. } else {
  2348. return this.indexOf(search, start) !== -1; // eslint-disable-line lodash/prefer-includes
  2349. }
  2350. };
  2351. }
  2352. if (!String.prototype.endsWith) {
  2353. String.prototype.endsWith = function (searchString, position) {
  2354. var subjectString = this.toString();
  2355. if (position === undefined || position > subjectString.length) {
  2356. position = subjectString.length;
  2357. }
  2358. position -= searchString.length;
  2359. var lastIndex = subjectString.indexOf(searchString, position);
  2360. return lastIndex !== -1 && lastIndex === position;
  2361. };
  2362. }
  2363. if (!String.prototype.startsWith) {
  2364. String.prototype.startsWith = function (searchString, position) {
  2365. position = position || 0;
  2366. return this.substr(position, searchString.length) === searchString;
  2367. };
  2368. }
  2369. if (!String.prototype.splitOnce) {
  2370. String.prototype.splitOnce = function (delimiter) {
  2371. var components = this.split(delimiter);
  2372. return [components.shift(), components.join(delimiter)];
  2373. };
  2374. }
  2375. if (!String.prototype.trim) {
  2376. String.prototype.trim = function () {
  2377. return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  2378. };
  2379. }
  2380. ;
  2381. define("polyfill", function(){});
  2382. /**
  2383. * @preserve jed.js https://github.com/SlexAxton/Jed
  2384. */
  2385. /*
  2386. -----------
  2387. A gettext compatible i18n library for modern JavaScript Applications
  2388. by Alex Sexton - AlexSexton [at] gmail - @SlexAxton
  2389. MIT License
  2390. A jQuery Foundation project - requires CLA to contribute -
  2391. https://contribute.jquery.org/CLA/
  2392. Jed offers the entire applicable GNU gettext spec'd set of
  2393. functions, but also offers some nicer wrappers around them.
  2394. The api for gettext was written for a language with no function
  2395. overloading, so Jed allows a little more of that.
  2396. Many thanks to Joshua I. Miller - unrtst@cpan.org - who wrote
  2397. gettext.js back in 2008. I was able to vet a lot of my ideas
  2398. against his. I also made sure Jed passed against his tests
  2399. in order to offer easy upgrades -- jsgettext.berlios.de
  2400. */
  2401. (function (root, undef) {
  2402. // Set up some underscore-style functions, if you already have
  2403. // underscore, feel free to delete this section, and use it
  2404. // directly, however, the amount of functions used doesn't
  2405. // warrant having underscore as a full dependency.
  2406. // Underscore 1.3.0 was used to port and is licensed
  2407. // under the MIT License by Jeremy Ashkenas.
  2408. var ArrayProto = Array.prototype,
  2409. ObjProto = Object.prototype,
  2410. slice = ArrayProto.slice,
  2411. hasOwnProp = ObjProto.hasOwnProperty,
  2412. nativeForEach = ArrayProto.forEach,
  2413. breaker = {};
  2414. // We're not using the OOP style _ so we don't need the
  2415. // extra level of indirection. This still means that you
  2416. // sub out for real `_` though.
  2417. var _ = {
  2418. forEach : function( obj, iterator, context ) {
  2419. var i, l, key;
  2420. if ( obj === null ) {
  2421. return;
  2422. }
  2423. if ( nativeForEach && obj.forEach === nativeForEach ) {
  2424. obj.forEach( iterator, context );
  2425. }
  2426. else if ( obj.length === +obj.length ) {
  2427. for ( i = 0, l = obj.length; i < l; i++ ) {
  2428. if ( i in obj && iterator.call( context, obj[i], i, obj ) === breaker ) {
  2429. return;
  2430. }
  2431. }
  2432. }
  2433. else {
  2434. for ( key in obj) {
  2435. if ( hasOwnProp.call( obj, key ) ) {
  2436. if ( iterator.call (context, obj[key], key, obj ) === breaker ) {
  2437. return;
  2438. }
  2439. }
  2440. }
  2441. }
  2442. },
  2443. extend : function( obj ) {
  2444. this.forEach( slice.call( arguments, 1 ), function ( source ) {
  2445. for ( var prop in source ) {
  2446. obj[prop] = source[prop];
  2447. }
  2448. });
  2449. return obj;
  2450. }
  2451. };
  2452. // END Miniature underscore impl
  2453. // Jed is a constructor function
  2454. var Jed = function ( options ) {
  2455. // Some minimal defaults
  2456. this.defaults = {
  2457. "locale_data" : {
  2458. "messages" : {
  2459. "" : {
  2460. "domain" : "messages",
  2461. "lang" : "en",
  2462. "plural_forms" : "nplurals=2; plural=(n != 1);"
  2463. }
  2464. // There are no default keys, though
  2465. }
  2466. },
  2467. // The default domain if one is missing
  2468. "domain" : "messages",
  2469. // enable debug mode to log untranslated strings to the console
  2470. "debug" : false
  2471. };
  2472. // Mix in the sent options with the default options
  2473. this.options = _.extend( {}, this.defaults, options );
  2474. this.textdomain( this.options.domain );
  2475. if ( options.domain && ! this.options.locale_data[ this.options.domain ] ) {
  2476. throw new Error('Text domain set to non-existent domain: `' + options.domain + '`');
  2477. }
  2478. };
  2479. // The gettext spec sets this character as the default
  2480. // delimiter for context lookups.
  2481. // e.g.: context\u0004key
  2482. // If your translation company uses something different,
  2483. // just change this at any time and it will use that instead.
  2484. Jed.context_delimiter = String.fromCharCode( 4 );
  2485. function getPluralFormFunc ( plural_form_string ) {
  2486. return Jed.PF.compile( plural_form_string || "nplurals=2; plural=(n != 1);");
  2487. }
  2488. function Chain( key, i18n ){
  2489. this._key = key;
  2490. this._i18n = i18n;
  2491. }
  2492. // Create a chainable api for adding args prettily
  2493. _.extend( Chain.prototype, {
  2494. onDomain : function ( domain ) {
  2495. this._domain = domain;
  2496. return this;
  2497. },
  2498. withContext : function ( context ) {
  2499. this._context = context;
  2500. return this;
  2501. },
  2502. ifPlural : function ( num, pkey ) {
  2503. this._val = num;
  2504. this._pkey = pkey;
  2505. return this;
  2506. },
  2507. fetch : function ( sArr ) {
  2508. if ( {}.toString.call( sArr ) != '[object Array]' ) {
  2509. sArr = [].slice.call(arguments, 0);
  2510. }
  2511. return ( sArr && sArr.length ? Jed.sprintf : function(x){ return x; } )(
  2512. this._i18n.dcnpgettext(this._domain, this._context, this._key, this._pkey, this._val),
  2513. sArr
  2514. );
  2515. }
  2516. });
  2517. // Add functions to the Jed prototype.
  2518. // These will be the functions on the object that's returned
  2519. // from creating a `new Jed()`
  2520. // These seem redundant, but they gzip pretty well.
  2521. _.extend( Jed.prototype, {
  2522. // The sexier api start point
  2523. translate : function ( key ) {
  2524. return new Chain( key, this );
  2525. },
  2526. textdomain : function ( domain ) {
  2527. if ( ! domain ) {
  2528. return this._textdomain;
  2529. }
  2530. this._textdomain = domain;
  2531. },
  2532. gettext : function ( key ) {
  2533. return this.dcnpgettext.call( this, undef, undef, key );
  2534. },
  2535. dgettext : function ( domain, key ) {
  2536. return this.dcnpgettext.call( this, domain, undef, key );
  2537. },
  2538. dcgettext : function ( domain , key /*, category */ ) {
  2539. // Ignores the category anyways
  2540. return this.dcnpgettext.call( this, domain, undef, key );
  2541. },
  2542. ngettext : function ( skey, pkey, val ) {
  2543. return this.dcnpgettext.call( this, undef, undef, skey, pkey, val );
  2544. },
  2545. dngettext : function ( domain, skey, pkey, val ) {
  2546. return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );
  2547. },
  2548. dcngettext : function ( domain, skey, pkey, val/*, category */) {
  2549. return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );
  2550. },
  2551. pgettext : function ( context, key ) {
  2552. return this.dcnpgettext.call( this, undef, context, key );
  2553. },
  2554. dpgettext : function ( domain, context, key ) {
  2555. return this.dcnpgettext.call( this, domain, context, key );
  2556. },
  2557. dcpgettext : function ( domain, context, key/*, category */) {
  2558. return this.dcnpgettext.call( this, domain, context, key );
  2559. },
  2560. npgettext : function ( context, skey, pkey, val ) {
  2561. return this.dcnpgettext.call( this, undef, context, skey, pkey, val );
  2562. },
  2563. dnpgettext : function ( domain, context, skey, pkey, val ) {
  2564. return this.dcnpgettext.call( this, domain, context, skey, pkey, val );
  2565. },
  2566. // The most fully qualified gettext function. It has every option.
  2567. // Since it has every option, we can use it from every other method.
  2568. // This is the bread and butter.
  2569. // Technically there should be one more argument in this function for 'Category',
  2570. // but since we never use it, we might as well not waste the bytes to define it.
  2571. dcnpgettext : function ( domain, context, singular_key, plural_key, val ) {
  2572. // Set some defaults
  2573. plural_key = plural_key || singular_key;
  2574. // Use the global domain default if one
  2575. // isn't explicitly passed in
  2576. domain = domain || this._textdomain;
  2577. var fallback;
  2578. // Handle special cases
  2579. // No options found
  2580. if ( ! this.options ) {
  2581. // There's likely something wrong, but we'll return the correct key for english
  2582. // We do this by instantiating a brand new Jed instance with the default set
  2583. // for everything that could be broken.
  2584. fallback = new Jed();
  2585. return fallback.dcnpgettext.call( fallback, undefined, undefined, singular_key, plural_key, val );
  2586. }
  2587. // No translation data provided
  2588. if ( ! this.options.locale_data ) {
  2589. throw new Error('No locale data provided.');
  2590. }
  2591. if ( ! this.options.locale_data[ domain ] ) {
  2592. throw new Error('Domain `' + domain + '` was not found.');
  2593. }
  2594. if ( ! this.options.locale_data[ domain ][ "" ] ) {
  2595. throw new Error('No locale meta information provided.');
  2596. }
  2597. // Make sure we have a truthy key. Otherwise we might start looking
  2598. // into the empty string key, which is the options for the locale
  2599. // data.
  2600. if ( ! singular_key ) {
  2601. throw new Error('No translation key found.');
  2602. }
  2603. var key = context ? context + Jed.context_delimiter + singular_key : singular_key,
  2604. locale_data = this.options.locale_data,
  2605. dict = locale_data[ domain ],
  2606. defaultConf = (locale_data.messages || this.defaults.locale_data.messages)[""],
  2607. pluralForms = dict[""].plural_forms || dict[""]["Plural-Forms"] || dict[""]["plural-forms"] || defaultConf.plural_forms || defaultConf["Plural-Forms"] || defaultConf["plural-forms"],
  2608. val_list,
  2609. res;
  2610. var val_idx;
  2611. if (val === undefined) {
  2612. // No value passed in; assume singular key lookup.
  2613. val_idx = 0;
  2614. } else {
  2615. // Value has been passed in; use plural-forms calculations.
  2616. // Handle invalid numbers, but try casting strings for good measure
  2617. if ( typeof val != 'number' ) {
  2618. val = parseInt( val, 10 );
  2619. if ( isNaN( val ) ) {
  2620. throw new Error('The number that was passed in is not a number.');
  2621. }
  2622. }
  2623. val_idx = getPluralFormFunc(pluralForms)(val);
  2624. }
  2625. // Throw an error if a domain isn't found
  2626. if ( ! dict ) {
  2627. throw new Error('No domain named `' + domain + '` could be found.');
  2628. }
  2629. val_list = dict[ key ];
  2630. // If there is no match, then revert back to
  2631. // english style singular/plural with the keys passed in.
  2632. if ( ! val_list || val_idx > val_list.length ) {
  2633. if (this.options.missing_key_callback) {
  2634. this.options.missing_key_callback(key, domain);
  2635. }
  2636. res = [ singular_key, plural_key ];
  2637. // collect untranslated strings
  2638. if (this.options.debug===true) {
  2639. console.log(res[ getPluralFormFunc(pluralForms)( val ) ]);
  2640. }
  2641. return res[ getPluralFormFunc()( val ) ];
  2642. }
  2643. res = val_list[ val_idx ];
  2644. // This includes empty strings on purpose
  2645. if ( ! res ) {
  2646. res = [ singular_key, plural_key ];
  2647. return res[ getPluralFormFunc()( val ) ];
  2648. }
  2649. return res;
  2650. }
  2651. });
  2652. // We add in sprintf capabilities for post translation value interolation
  2653. // This is not internally used, so you can remove it if you have this
  2654. // available somewhere else, or want to use a different system.
  2655. // We _slightly_ modify the normal sprintf behavior to more gracefully handle
  2656. // undefined values.
  2657. /**
  2658. sprintf() for JavaScript 0.7-beta1
  2659. http://www.diveintojavascript.com/projects/javascript-sprintf
  2660. Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
  2661. All rights reserved.
  2662. Redistribution and use in source and binary forms, with or without
  2663. modification, are permitted provided that the following conditions are met:
  2664. * Redistributions of source code must retain the above copyright
  2665. notice, this list of conditions and the following disclaimer.
  2666. * Redistributions in binary form must reproduce the above copyright
  2667. notice, this list of conditions and the following disclaimer in the
  2668. documentation and/or other materials provided with the distribution.
  2669. * Neither the name of sprintf() for JavaScript nor the
  2670. names of its contributors may be used to endorse or promote products
  2671. derived from this software without specific prior written permission.
  2672. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  2673. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  2674. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  2675. DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
  2676. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  2677. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  2678. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  2679. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  2680. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  2681. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  2682. */
  2683. var sprintf = (function() {
  2684. function get_type(variable) {
  2685. return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
  2686. }
  2687. function str_repeat(input, multiplier) {
  2688. for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
  2689. return output.join('');
  2690. }
  2691. var str_format = function() {
  2692. if (!str_format.cache.hasOwnProperty(arguments[0])) {
  2693. str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
  2694. }
  2695. return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
  2696. };
  2697. str_format.format = function(parse_tree, argv) {
  2698. var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
  2699. for (i = 0; i < tree_length; i++) {
  2700. node_type = get_type(parse_tree[i]);
  2701. if (node_type === 'string') {
  2702. output.push(parse_tree[i]);
  2703. }
  2704. else if (node_type === 'array') {
  2705. match = parse_tree[i]; // convenience purposes only
  2706. if (match[2]) { // keyword argument
  2707. arg = argv[cursor];
  2708. for (k = 0; k < match[2].length; k++) {
  2709. if (!arg.hasOwnProperty(match[2][k])) {
  2710. throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
  2711. }
  2712. arg = arg[match[2][k]];
  2713. }
  2714. }
  2715. else if (match[1]) { // positional argument (explicit)
  2716. arg = argv[match[1]];
  2717. }
  2718. else { // positional argument (implicit)
  2719. arg = argv[cursor++];
  2720. }
  2721. if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
  2722. throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
  2723. }
  2724. // Jed EDIT
  2725. if ( typeof arg == 'undefined' || arg === null ) {
  2726. arg = '';
  2727. }
  2728. // Jed EDIT
  2729. switch (match[8]) {
  2730. case 'b': arg = arg.toString(2); break;
  2731. case 'c': arg = String.fromCharCode(arg); break;
  2732. case 'd': arg = parseInt(arg, 10); break;
  2733. case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
  2734. case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
  2735. case 'o': arg = arg.toString(8); break;
  2736. case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
  2737. case 'u': arg = Math.abs(arg); break;
  2738. case 'x': arg = arg.toString(16); break;
  2739. case 'X': arg = arg.toString(16).toUpperCase(); break;
  2740. }
  2741. arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
  2742. pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
  2743. pad_length = match[6] - String(arg).length;
  2744. pad = match[6] ? str_repeat(pad_character, pad_length) : '';
  2745. output.push(match[5] ? arg + pad : pad + arg);
  2746. }
  2747. }
  2748. return output.join('');
  2749. };
  2750. str_format.cache = {};
  2751. str_format.parse = function(fmt) {
  2752. var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
  2753. while (_fmt) {
  2754. if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
  2755. parse_tree.push(match[0]);
  2756. }
  2757. else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
  2758. parse_tree.push('%');
  2759. }
  2760. else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
  2761. if (match[2]) {
  2762. arg_names |= 1;
  2763. var field_list = [], replacement_field = match[2], field_match = [];
  2764. if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
  2765. field_list.push(field_match[1]);
  2766. while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
  2767. if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
  2768. field_list.push(field_match[1]);
  2769. }
  2770. else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
  2771. field_list.push(field_match[1]);
  2772. }
  2773. else {
  2774. throw('[sprintf] huh?');
  2775. }
  2776. }
  2777. }
  2778. else {
  2779. throw('[sprintf] huh?');
  2780. }
  2781. match[2] = field_list;
  2782. }
  2783. else {
  2784. arg_names |= 2;
  2785. }
  2786. if (arg_names === 3) {
  2787. throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
  2788. }
  2789. parse_tree.push(match);
  2790. }
  2791. else {
  2792. throw('[sprintf] huh?');
  2793. }
  2794. _fmt = _fmt.substring(match[0].length);
  2795. }
  2796. return parse_tree;
  2797. };
  2798. return str_format;
  2799. })();
  2800. var vsprintf = function(fmt, argv) {
  2801. argv.unshift(fmt);
  2802. return sprintf.apply(null, argv);
  2803. };
  2804. Jed.parse_plural = function ( plural_forms, n ) {
  2805. plural_forms = plural_forms.replace(/n/g, n);
  2806. return Jed.parse_expression(plural_forms);
  2807. };
  2808. Jed.sprintf = function ( fmt, args ) {
  2809. if ( {}.toString.call( args ) == '[object Array]' ) {
  2810. return vsprintf( fmt, [].slice.call(args) );
  2811. }
  2812. return sprintf.apply(this, [].slice.call(arguments) );
  2813. };
  2814. Jed.prototype.sprintf = function () {
  2815. return Jed.sprintf.apply(this, arguments);
  2816. };
  2817. // END sprintf Implementation
  2818. // Start the Plural forms section
  2819. // This is a full plural form expression parser. It is used to avoid
  2820. // running 'eval' or 'new Function' directly against the plural
  2821. // forms.
  2822. //
  2823. // This can be important if you get translations done through a 3rd
  2824. // party vendor. I encourage you to use this instead, however, I
  2825. // also will provide a 'precompiler' that you can use at build time
  2826. // to output valid/safe function representations of the plural form
  2827. // expressions. This means you can build this code out for the most
  2828. // part.
  2829. Jed.PF = {};
  2830. Jed.PF.parse = function ( p ) {
  2831. var plural_str = Jed.PF.extractPluralExpr( p );
  2832. return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str);
  2833. };
  2834. Jed.PF.compile = function ( p ) {
  2835. // Handle trues and falses as 0 and 1
  2836. function imply( val ) {
  2837. return (val === true ? 1 : val ? val : 0);
  2838. }
  2839. var ast = Jed.PF.parse( p );
  2840. return function ( n ) {
  2841. return imply( Jed.PF.interpreter( ast )( n ) );
  2842. };
  2843. };
  2844. Jed.PF.interpreter = function ( ast ) {
  2845. return function ( n ) {
  2846. var res;
  2847. switch ( ast.type ) {
  2848. case 'GROUP':
  2849. return Jed.PF.interpreter( ast.expr )( n );
  2850. case 'TERNARY':
  2851. if ( Jed.PF.interpreter( ast.expr )( n ) ) {
  2852. return Jed.PF.interpreter( ast.truthy )( n );
  2853. }
  2854. return Jed.PF.interpreter( ast.falsey )( n );
  2855. case 'OR':
  2856. return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n );
  2857. case 'AND':
  2858. return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n );
  2859. case 'LT':
  2860. return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n );
  2861. case 'GT':
  2862. return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n );
  2863. case 'LTE':
  2864. return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n );
  2865. case 'GTE':
  2866. return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n );
  2867. case 'EQ':
  2868. return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n );
  2869. case 'NEQ':
  2870. return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n );
  2871. case 'MOD':
  2872. return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n );
  2873. case 'VAR':
  2874. return n;
  2875. case 'NUM':
  2876. return ast.val;
  2877. default:
  2878. throw new Error("Invalid Token found.");
  2879. }
  2880. };
  2881. };
  2882. Jed.PF.extractPluralExpr = function ( p ) {
  2883. // trim first
  2884. p = p.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  2885. if (! /;\s*$/.test(p)) {
  2886. p = p.concat(';');
  2887. }
  2888. var nplurals_re = /nplurals\=(\d+);/,
  2889. plural_re = /plural\=(.*);/,
  2890. nplurals_matches = p.match( nplurals_re ),
  2891. res = {},
  2892. plural_matches;
  2893. // Find the nplurals number
  2894. if ( nplurals_matches.length > 1 ) {
  2895. res.nplurals = nplurals_matches[1];
  2896. }
  2897. else {
  2898. throw new Error('nplurals not found in plural_forms string: ' + p );
  2899. }
  2900. // remove that data to get to the formula
  2901. p = p.replace( nplurals_re, "" );
  2902. plural_matches = p.match( plural_re );
  2903. if (!( plural_matches && plural_matches.length > 1 ) ) {
  2904. throw new Error('`plural` expression not found: ' + p);
  2905. }
  2906. return plural_matches[ 1 ];
  2907. };
  2908. /* Jison generated parser */
  2909. Jed.PF.parser = (function(){
  2910. var parser = {trace: function trace() { },
  2911. yy: {},
  2912. symbols_: {"error":2,"expressions":3,"e":4,"EOF":5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,"n":19,"NUMBER":20,"$accept":0,"$end":1},
  2913. terminals_: {2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"},
  2914. productions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],
  2915. performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
  2916. var $0 = $$.length - 1;
  2917. switch (yystate) {
  2918. case 1: return { type : 'GROUP', expr: $$[$0-1] };
  2919. break;
  2920. case 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] };
  2921. break;
  2922. case 3:this.$ = { type: "OR", left: $$[$0-2], right: $$[$0] };
  2923. break;
  2924. case 4:this.$ = { type: "AND", left: $$[$0-2], right: $$[$0] };
  2925. break;
  2926. case 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] };
  2927. break;
  2928. case 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] };
  2929. break;
  2930. case 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] };
  2931. break;
  2932. case 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] };
  2933. break;
  2934. case 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] };
  2935. break;
  2936. case 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] };
  2937. break;
  2938. case 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] };
  2939. break;
  2940. case 12:this.$ = { type: 'GROUP', expr: $$[$0-1] };
  2941. break;
  2942. case 13:this.$ = { type: 'VAR' };
  2943. break;
  2944. case 14:this.$ = { type: 'NUM', val: Number(yytext) };
  2945. break;
  2946. }
  2947. },
  2948. table: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],
  2949. defaultActions: {6:[2,1]},
  2950. parseError: function parseError(str, hash) {
  2951. throw new Error(str);
  2952. },
  2953. parse: function parse(input) {
  2954. var self = this,
  2955. stack = [0],
  2956. vstack = [null], // semantic value stack
  2957. lstack = [], // location stack
  2958. table = this.table,
  2959. yytext = '',
  2960. yylineno = 0,
  2961. yyleng = 0,
  2962. recovering = 0,
  2963. TERROR = 2,
  2964. EOF = 1;
  2965. //this.reductionCount = this.shiftCount = 0;
  2966. this.lexer.setInput(input);
  2967. this.lexer.yy = this.yy;
  2968. this.yy.lexer = this.lexer;
  2969. if (typeof this.lexer.yylloc == 'undefined')
  2970. this.lexer.yylloc = {};
  2971. var yyloc = this.lexer.yylloc;
  2972. lstack.push(yyloc);
  2973. if (typeof this.yy.parseError === 'function')
  2974. this.parseError = this.yy.parseError;
  2975. function popStack (n) {
  2976. stack.length = stack.length - 2*n;
  2977. vstack.length = vstack.length - n;
  2978. lstack.length = lstack.length - n;
  2979. }
  2980. function lex() {
  2981. var token;
  2982. token = self.lexer.lex() || 1; // $end = 1
  2983. // if token isn't its numeric value, convert
  2984. if (typeof token !== 'number') {
  2985. token = self.symbols_[token] || token;
  2986. }
  2987. return token;
  2988. }
  2989. var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
  2990. while (true) {
  2991. // retreive state number from top of stack
  2992. state = stack[stack.length-1];
  2993. // use default actions if available
  2994. if (this.defaultActions[state]) {
  2995. action = this.defaultActions[state];
  2996. } else {
  2997. if (symbol == null)
  2998. symbol = lex();
  2999. // read action for current state and first input
  3000. action = table[state] && table[state][symbol];
  3001. }
  3002. // handle parse error
  3003. _handle_error:
  3004. if (typeof action === 'undefined' || !action.length || !action[0]) {
  3005. if (!recovering) {
  3006. // Report error
  3007. expected = [];
  3008. for (p in table[state]) if (this.terminals_[p] && p > 2) {
  3009. expected.push("'"+this.terminals_[p]+"'");
  3010. }
  3011. var errStr = '';
  3012. if (this.lexer.showPosition) {
  3013. errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
  3014. } else {
  3015. errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
  3016. (symbol == 1 /*EOF*/ ? "end of input" :
  3017. ("'"+(this.terminals_[symbol] || symbol)+"'"));
  3018. }
  3019. this.parseError(errStr,
  3020. {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
  3021. }
  3022. // just recovered from another error
  3023. if (recovering == 3) {
  3024. if (symbol == EOF) {
  3025. throw new Error(errStr || 'Parsing halted.');
  3026. }
  3027. // discard current lookahead and grab another
  3028. yyleng = this.lexer.yyleng;
  3029. yytext = this.lexer.yytext;
  3030. yylineno = this.lexer.yylineno;
  3031. yyloc = this.lexer.yylloc;
  3032. symbol = lex();
  3033. }
  3034. // try to recover from error
  3035. while (1) {
  3036. // check for error recovery rule in this state
  3037. if ((TERROR.toString()) in table[state]) {
  3038. break;
  3039. }
  3040. if (state == 0) {
  3041. throw new Error(errStr || 'Parsing halted.');
  3042. }
  3043. popStack(1);
  3044. state = stack[stack.length-1];
  3045. }
  3046. preErrorSymbol = symbol; // save the lookahead token
  3047. symbol = TERROR; // insert generic error symbol as new lookahead
  3048. state = stack[stack.length-1];
  3049. action = table[state] && table[state][TERROR];
  3050. recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
  3051. }
  3052. // this shouldn't happen, unless resolve defaults are off
  3053. if (action[0] instanceof Array && action.length > 1) {
  3054. throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
  3055. }
  3056. switch (action[0]) {
  3057. case 1: // shift
  3058. //this.shiftCount++;
  3059. stack.push(symbol);
  3060. vstack.push(this.lexer.yytext);
  3061. lstack.push(this.lexer.yylloc);
  3062. stack.push(action[1]); // push state
  3063. symbol = null;
  3064. if (!preErrorSymbol) { // normal execution/no error
  3065. yyleng = this.lexer.yyleng;
  3066. yytext = this.lexer.yytext;
  3067. yylineno = this.lexer.yylineno;
  3068. yyloc = this.lexer.yylloc;
  3069. if (recovering > 0)
  3070. recovering--;
  3071. } else { // error just occurred, resume old lookahead f/ before error
  3072. symbol = preErrorSymbol;
  3073. preErrorSymbol = null;
  3074. }
  3075. break;
  3076. case 2: // reduce
  3077. //this.reductionCount++;
  3078. len = this.productions_[action[1]][1];
  3079. // perform semantic action
  3080. yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
  3081. // default location, uses first token for firsts, last for lasts
  3082. yyval._$ = {
  3083. first_line: lstack[lstack.length-(len||1)].first_line,
  3084. last_line: lstack[lstack.length-1].last_line,
  3085. first_column: lstack[lstack.length-(len||1)].first_column,
  3086. last_column: lstack[lstack.length-1].last_column
  3087. };
  3088. r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
  3089. if (typeof r !== 'undefined') {
  3090. return r;
  3091. }
  3092. // pop off stack
  3093. if (len) {
  3094. stack = stack.slice(0,-1*len*2);
  3095. vstack = vstack.slice(0, -1*len);
  3096. lstack = lstack.slice(0, -1*len);
  3097. }
  3098. stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
  3099. vstack.push(yyval.$);
  3100. lstack.push(yyval._$);
  3101. // goto new state = table[STATE][NONTERMINAL]
  3102. newState = table[stack[stack.length-2]][stack[stack.length-1]];
  3103. stack.push(newState);
  3104. break;
  3105. case 3: // accept
  3106. return true;
  3107. }
  3108. }
  3109. return true;
  3110. }};/* Jison generated lexer */
  3111. var lexer = (function(){
  3112. var lexer = ({EOF:1,
  3113. parseError:function parseError(str, hash) {
  3114. if (this.yy.parseError) {
  3115. this.yy.parseError(str, hash);
  3116. } else {
  3117. throw new Error(str);
  3118. }
  3119. },
  3120. setInput:function (input) {
  3121. this._input = input;
  3122. this._more = this._less = this.done = false;
  3123. this.yylineno = this.yyleng = 0;
  3124. this.yytext = this.matched = this.match = '';
  3125. this.conditionStack = ['INITIAL'];
  3126. this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
  3127. return this;
  3128. },
  3129. input:function () {
  3130. var ch = this._input[0];
  3131. this.yytext+=ch;
  3132. this.yyleng++;
  3133. this.match+=ch;
  3134. this.matched+=ch;
  3135. var lines = ch.match(/\n/);
  3136. if (lines) this.yylineno++;
  3137. this._input = this._input.slice(1);
  3138. return ch;
  3139. },
  3140. unput:function (ch) {
  3141. this._input = ch + this._input;
  3142. return this;
  3143. },
  3144. more:function () {
  3145. this._more = true;
  3146. return this;
  3147. },
  3148. pastInput:function () {
  3149. var past = this.matched.substr(0, this.matched.length - this.match.length);
  3150. return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
  3151. },
  3152. upcomingInput:function () {
  3153. var next = this.match;
  3154. if (next.length < 20) {
  3155. next += this._input.substr(0, 20-next.length);
  3156. }
  3157. return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
  3158. },
  3159. showPosition:function () {
  3160. var pre = this.pastInput();
  3161. var c = new Array(pre.length + 1).join("-");
  3162. return pre + this.upcomingInput() + "\n" + c+"^";
  3163. },
  3164. next:function () {
  3165. if (this.done) {
  3166. return this.EOF;
  3167. }
  3168. if (!this._input) this.done = true;
  3169. var token,
  3170. match,
  3171. col,
  3172. lines;
  3173. if (!this._more) {
  3174. this.yytext = '';
  3175. this.match = '';
  3176. }
  3177. var rules = this._currentRules();
  3178. for (var i=0;i < rules.length; i++) {
  3179. match = this._input.match(this.rules[rules[i]]);
  3180. if (match) {
  3181. lines = match[0].match(/\n.*/g);
  3182. if (lines) this.yylineno += lines.length;
  3183. this.yylloc = {first_line: this.yylloc.last_line,
  3184. last_line: this.yylineno+1,
  3185. first_column: this.yylloc.last_column,
  3186. last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
  3187. this.yytext += match[0];
  3188. this.match += match[0];
  3189. this.matches = match;
  3190. this.yyleng = this.yytext.length;
  3191. this._more = false;
  3192. this._input = this._input.slice(match[0].length);
  3193. this.matched += match[0];
  3194. token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
  3195. if (token) return token;
  3196. else return;
  3197. }
  3198. }
  3199. if (this._input === "") {
  3200. return this.EOF;
  3201. } else {
  3202. this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
  3203. {text: "", token: null, line: this.yylineno});
  3204. }
  3205. },
  3206. lex:function lex() {
  3207. var r = this.next();
  3208. if (typeof r !== 'undefined') {
  3209. return r;
  3210. } else {
  3211. return this.lex();
  3212. }
  3213. },
  3214. begin:function begin(condition) {
  3215. this.conditionStack.push(condition);
  3216. },
  3217. popState:function popState() {
  3218. return this.conditionStack.pop();
  3219. },
  3220. _currentRules:function _currentRules() {
  3221. return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
  3222. },
  3223. topState:function () {
  3224. return this.conditionStack[this.conditionStack.length-2];
  3225. },
  3226. pushState:function begin(condition) {
  3227. this.begin(condition);
  3228. }});
  3229. lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
  3230. var YYSTATE=YY_START;
  3231. switch($avoiding_name_collisions) {
  3232. case 0:/* skip whitespace */
  3233. break;
  3234. case 1:return 20
  3235. break;
  3236. case 2:return 19
  3237. break;
  3238. case 3:return 8
  3239. break;
  3240. case 4:return 9
  3241. break;
  3242. case 5:return 6
  3243. break;
  3244. case 6:return 7
  3245. break;
  3246. case 7:return 11
  3247. break;
  3248. case 8:return 13
  3249. break;
  3250. case 9:return 10
  3251. break;
  3252. case 10:return 12
  3253. break;
  3254. case 11:return 14
  3255. break;
  3256. case 12:return 15
  3257. break;
  3258. case 13:return 16
  3259. break;
  3260. case 14:return 17
  3261. break;
  3262. case 15:return 18
  3263. break;
  3264. case 16:return 5
  3265. break;
  3266. case 17:return 'INVALID'
  3267. break;
  3268. }
  3269. };
  3270. lexer.rules = [/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^</,/^>/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./];
  3271. lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}};return lexer;})()
  3272. parser.lexer = lexer;
  3273. return parser;
  3274. })();
  3275. // End parser
  3276. // Handle node, amd, and global systems
  3277. if (typeof exports !== 'undefined') {
  3278. if (typeof module !== 'undefined' && module.exports) {
  3279. exports = module.exports = Jed;
  3280. }
  3281. exports.Jed = Jed;
  3282. }
  3283. else {
  3284. if (typeof define === 'function' && define.amd) {
  3285. define('jed',[],function() {
  3286. return Jed;
  3287. });
  3288. }
  3289. // Leak a global regardless of module system
  3290. root['Jed'] = Jed;
  3291. }
  3292. })(this);
  3293. //! moment.js locale configuration
  3294. //! locale : Afrikaans [af]
  3295. //! author : Werner Mollentze : https://github.com/wernerm
  3296. ;(function (global, factory) {
  3297. typeof exports === 'object' && typeof module !== 'undefined'
  3298. && typeof require === 'function' ? factory(require('../moment')) :
  3299. typeof define === 'function' && define.amd ? define('moment/locale/af',['../moment'], factory) :
  3300. factory(global.moment)
  3301. }(this, (function (moment) { 'use strict';
  3302. var af = moment.defineLocale('af', {
  3303. months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
  3304. monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
  3305. weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
  3306. weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
  3307. weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
  3308. meridiemParse: /vm|nm/i,
  3309. isPM : function (input) {
  3310. return /^nm$/i.test(input);
  3311. },
  3312. meridiem : function (hours, minutes, isLower) {
  3313. if (hours < 12) {
  3314. return isLower ? 'vm' : 'VM';
  3315. } else {
  3316. return isLower ? 'nm' : 'NM';
  3317. }
  3318. },
  3319. longDateFormat : {
  3320. LT : 'HH:mm',
  3321. LTS : 'HH:mm:ss',
  3322. L : 'DD/MM/YYYY',
  3323. LL : 'D MMMM YYYY',
  3324. LLL : 'D MMMM YYYY HH:mm',
  3325. LLLL : 'dddd, D MMMM YYYY HH:mm'
  3326. },
  3327. calendar : {
  3328. sameDay : '[Vandag om] LT',
  3329. nextDay : '[Môre om] LT',
  3330. nextWeek : 'dddd [om] LT',
  3331. lastDay : '[Gister om] LT',
  3332. lastWeek : '[Laas] dddd [om] LT',
  3333. sameElse : 'L'
  3334. },
  3335. relativeTime : {
  3336. future : 'oor %s',
  3337. past : '%s gelede',
  3338. s : '\'n paar sekondes',
  3339. m : '\'n minuut',
  3340. mm : '%d minute',
  3341. h : '\'n uur',
  3342. hh : '%d ure',
  3343. d : '\'n dag',
  3344. dd : '%d dae',
  3345. M : '\'n maand',
  3346. MM : '%d maande',
  3347. y : '\'n jaar',
  3348. yy : '%d jaar'
  3349. },
  3350. dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
  3351. ordinal : function (number) {
  3352. return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
  3353. },
  3354. week : {
  3355. dow : 1, // Maandag is die eerste dag van die week.
  3356. doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
  3357. }
  3358. });
  3359. return af;
  3360. })));
  3361. //! moment.js locale configuration
  3362. //! locale : Arabic [ar]
  3363. //! author : Abdel Said: https://github.com/abdelsaid
  3364. //! author : Ahmed Elkhatib
  3365. //! author : forabi https://github.com/forabi
  3366. ;(function (global, factory) {
  3367. typeof exports === 'object' && typeof module !== 'undefined'
  3368. && typeof require === 'function' ? factory(require('../moment')) :
  3369. typeof define === 'function' && define.amd ? define('moment/locale/ar',['../moment'], factory) :
  3370. factory(global.moment)
  3371. }(this, (function (moment) { 'use strict';
  3372. var symbolMap = {
  3373. '1': '١',
  3374. '2': '٢',
  3375. '3': '٣',
  3376. '4': '٤',
  3377. '5': '٥',
  3378. '6': '٦',
  3379. '7': '٧',
  3380. '8': '٨',
  3381. '9': '٩',
  3382. '0': '٠'
  3383. };
  3384. var numberMap = {
  3385. '١': '1',
  3386. '٢': '2',
  3387. '٣': '3',
  3388. '٤': '4',
  3389. '٥': '5',
  3390. '٦': '6',
  3391. '٧': '7',
  3392. '٨': '8',
  3393. '٩': '9',
  3394. '٠': '0'
  3395. };
  3396. var pluralForm = function (n) {
  3397. return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
  3398. };
  3399. var plurals = {
  3400. s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
  3401. m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
  3402. h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
  3403. d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
  3404. M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
  3405. y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
  3406. };
  3407. var pluralize = function (u) {
  3408. return function (number, withoutSuffix, string, isFuture) {
  3409. var f = pluralForm(number),
  3410. str = plurals[u][pluralForm(number)];
  3411. if (f === 2) {
  3412. str = str[withoutSuffix ? 0 : 1];
  3413. }
  3414. return str.replace(/%d/i, number);
  3415. };
  3416. };
  3417. var months = [
  3418. 'كانون الثاني يناير',
  3419. 'شباط فبراير',
  3420. 'آذار مارس',
  3421. 'نيسان أبريل',
  3422. 'أيار مايو',
  3423. 'حزيران يونيو',
  3424. 'تموز يوليو',
  3425. 'آب أغسطس',
  3426. 'أيلول سبتمبر',
  3427. 'تشرين الأول أكتوبر',
  3428. 'تشرين الثاني نوفمبر',
  3429. 'كانون الأول ديسمبر'
  3430. ];
  3431. var ar = moment.defineLocale('ar', {
  3432. months : months,
  3433. monthsShort : months,
  3434. weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
  3435. weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
  3436. weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
  3437. weekdaysParseExact : true,
  3438. longDateFormat : {
  3439. LT : 'HH:mm',
  3440. LTS : 'HH:mm:ss',
  3441. L : 'D/\u200FM/\u200FYYYY',
  3442. LL : 'D MMMM YYYY',
  3443. LLL : 'D MMMM YYYY HH:mm',
  3444. LLLL : 'dddd D MMMM YYYY HH:mm'
  3445. },
  3446. meridiemParse: /ص|م/,
  3447. isPM : function (input) {
  3448. return 'م' === input;
  3449. },
  3450. meridiem : function (hour, minute, isLower) {
  3451. if (hour < 12) {
  3452. return 'ص';
  3453. } else {
  3454. return 'م';
  3455. }
  3456. },
  3457. calendar : {
  3458. sameDay: '[اليوم عند الساعة] LT',
  3459. nextDay: '[غدًا عند الساعة] LT',
  3460. nextWeek: 'dddd [عند الساعة] LT',
  3461. lastDay: '[أمس عند الساعة] LT',
  3462. lastWeek: 'dddd [عند الساعة] LT',
  3463. sameElse: 'L'
  3464. },
  3465. relativeTime : {
  3466. future : 'بعد %s',
  3467. past : 'منذ %s',
  3468. s : pluralize('s'),
  3469. m : pluralize('m'),
  3470. mm : pluralize('m'),
  3471. h : pluralize('h'),
  3472. hh : pluralize('h'),
  3473. d : pluralize('d'),
  3474. dd : pluralize('d'),
  3475. M : pluralize('M'),
  3476. MM : pluralize('M'),
  3477. y : pluralize('y'),
  3478. yy : pluralize('y')
  3479. },
  3480. preparse: function (string) {
  3481. return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
  3482. return numberMap[match];
  3483. }).replace(/،/g, ',');
  3484. },
  3485. postformat: function (string) {
  3486. return string.replace(/\d/g, function (match) {
  3487. return symbolMap[match];
  3488. }).replace(/,/g, '،');
  3489. },
  3490. week : {
  3491. dow : 6, // Saturday is the first day of the week.
  3492. doy : 12 // The week that contains Jan 1st is the first week of the year.
  3493. }
  3494. });
  3495. return ar;
  3496. })));
  3497. //! moment.js locale configuration
  3498. //! locale : Bulgarian [bg]
  3499. //! author : Krasen Borisov : https://github.com/kraz
  3500. ;(function (global, factory) {
  3501. typeof exports === 'object' && typeof module !== 'undefined'
  3502. && typeof require === 'function' ? factory(require('../moment')) :
  3503. typeof define === 'function' && define.amd ? define('moment/locale/bg',['../moment'], factory) :
  3504. factory(global.moment)
  3505. }(this, (function (moment) { 'use strict';
  3506. var bg = moment.defineLocale('bg', {
  3507. months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
  3508. monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
  3509. weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
  3510. weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
  3511. weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
  3512. longDateFormat : {
  3513. LT : 'H:mm',
  3514. LTS : 'H:mm:ss',
  3515. L : 'D.MM.YYYY',
  3516. LL : 'D MMMM YYYY',
  3517. LLL : 'D MMMM YYYY H:mm',
  3518. LLLL : 'dddd, D MMMM YYYY H:mm'
  3519. },
  3520. calendar : {
  3521. sameDay : '[Днес в] LT',
  3522. nextDay : '[Утре в] LT',
  3523. nextWeek : 'dddd [в] LT',
  3524. lastDay : '[Вчера в] LT',
  3525. lastWeek : function () {
  3526. switch (this.day()) {
  3527. case 0:
  3528. case 3:
  3529. case 6:
  3530. return '[В изминалата] dddd [в] LT';
  3531. case 1:
  3532. case 2:
  3533. case 4:
  3534. case 5:
  3535. return '[В изминалия] dddd [в] LT';
  3536. }
  3537. },
  3538. sameElse : 'L'
  3539. },
  3540. relativeTime : {
  3541. future : 'след %s',
  3542. past : 'преди %s',
  3543. s : 'няколко секунди',
  3544. m : 'минута',
  3545. mm : '%d минути',
  3546. h : 'час',
  3547. hh : '%d часа',
  3548. d : 'ден',
  3549. dd : '%d дни',
  3550. M : 'месец',
  3551. MM : '%d месеца',
  3552. y : 'година',
  3553. yy : '%d години'
  3554. },
  3555. dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
  3556. ordinal : function (number) {
  3557. var lastDigit = number % 10,
  3558. last2Digits = number % 100;
  3559. if (number === 0) {
  3560. return number + '-ев';
  3561. } else if (last2Digits === 0) {
  3562. return number + '-ен';
  3563. } else if (last2Digits > 10 && last2Digits < 20) {
  3564. return number + '-ти';
  3565. } else if (lastDigit === 1) {
  3566. return number + '-ви';
  3567. } else if (lastDigit === 2) {
  3568. return number + '-ри';
  3569. } else if (lastDigit === 7 || lastDigit === 8) {
  3570. return number + '-ми';
  3571. } else {
  3572. return number + '-ти';
  3573. }
  3574. },
  3575. week : {
  3576. dow : 1, // Monday is the first day of the week.
  3577. doy : 7 // The week that contains Jan 1st is the first week of the year.
  3578. }
  3579. });
  3580. return bg;
  3581. })));
  3582. //! moment.js locale configuration
  3583. //! locale : Catalan [ca]
  3584. //! author : Juan G. Hurtado : https://github.com/juanghurtado
  3585. ;(function (global, factory) {
  3586. typeof exports === 'object' && typeof module !== 'undefined'
  3587. && typeof require === 'function' ? factory(require('../moment')) :
  3588. typeof define === 'function' && define.amd ? define('moment/locale/ca',['../moment'], factory) :
  3589. factory(global.moment)
  3590. }(this, (function (moment) { 'use strict';
  3591. var ca = moment.defineLocale('ca', {
  3592. months : {
  3593. standalone: 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
  3594. format: 'de gener_de febrer_de març_d\'abril_de maig_de juny_de juliol_d\'agost_de setembre_d\'octubre_de novembre_de desembre'.split('_'),
  3595. isFormat: /D[oD]?(\s)+MMMM/
  3596. },
  3597. monthsShort : 'gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.'.split('_'),
  3598. monthsParseExact : true,
  3599. weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
  3600. weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
  3601. weekdaysMin : 'dg_dl_dt_dc_dj_dv_ds'.split('_'),
  3602. weekdaysParseExact : true,
  3603. longDateFormat : {
  3604. LT : 'H:mm',
  3605. LTS : 'H:mm:ss',
  3606. L : 'DD/MM/YYYY',
  3607. LL : 'D MMMM [de] YYYY',
  3608. ll : 'D MMM YYYY',
  3609. LLL : 'D MMMM [de] YYYY [a les] H:mm',
  3610. lll : 'D MMM YYYY, H:mm',
  3611. LLLL : 'dddd D MMMM [de] YYYY [a les] H:mm',
  3612. llll : 'ddd D MMM YYYY, H:mm'
  3613. },
  3614. calendar : {
  3615. sameDay : function () {
  3616. return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
  3617. },
  3618. nextDay : function () {
  3619. return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
  3620. },
  3621. nextWeek : function () {
  3622. return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
  3623. },
  3624. lastDay : function () {
  3625. return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
  3626. },
  3627. lastWeek : function () {
  3628. return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
  3629. },
  3630. sameElse : 'L'
  3631. },
  3632. relativeTime : {
  3633. future : 'd\'aquí %s',
  3634. past : 'fa %s',
  3635. s : 'uns segons',
  3636. m : 'un minut',
  3637. mm : '%d minuts',
  3638. h : 'una hora',
  3639. hh : '%d hores',
  3640. d : 'un dia',
  3641. dd : '%d dies',
  3642. M : 'un mes',
  3643. MM : '%d mesos',
  3644. y : 'un any',
  3645. yy : '%d anys'
  3646. },
  3647. dayOfMonthOrdinalParse: /\d{1,2}(r|n|t|è|a)/,
  3648. ordinal : function (number, period) {
  3649. var output = (number === 1) ? 'r' :
  3650. (number === 2) ? 'n' :
  3651. (number === 3) ? 'r' :
  3652. (number === 4) ? 't' : 'è';
  3653. if (period === 'w' || period === 'W') {
  3654. output = 'a';
  3655. }
  3656. return number + output;
  3657. },
  3658. week : {
  3659. dow : 1, // Monday is the first day of the week.
  3660. doy : 4 // The week that contains Jan 4th is the first week of the year.
  3661. }
  3662. });
  3663. return ca;
  3664. })));
  3665. //! moment.js locale configuration
  3666. //! locale : German [de]
  3667. //! author : lluchs : https://github.com/lluchs
  3668. //! author: Menelion Elensúle: https://github.com/Oire
  3669. //! author : Mikolaj Dadela : https://github.com/mik01aj
  3670. ;(function (global, factory) {
  3671. typeof exports === 'object' && typeof module !== 'undefined'
  3672. && typeof require === 'function' ? factory(require('../moment')) :
  3673. typeof define === 'function' && define.amd ? define('moment/locale/de',['../moment'], factory) :
  3674. factory(global.moment)
  3675. }(this, (function (moment) { 'use strict';
  3676. function processRelativeTime(number, withoutSuffix, key, isFuture) {
  3677. var format = {
  3678. 'm': ['eine Minute', 'einer Minute'],
  3679. 'h': ['eine Stunde', 'einer Stunde'],
  3680. 'd': ['ein Tag', 'einem Tag'],
  3681. 'dd': [number + ' Tage', number + ' Tagen'],
  3682. 'M': ['ein Monat', 'einem Monat'],
  3683. 'MM': [number + ' Monate', number + ' Monaten'],
  3684. 'y': ['ein Jahr', 'einem Jahr'],
  3685. 'yy': [number + ' Jahre', number + ' Jahren']
  3686. };
  3687. return withoutSuffix ? format[key][0] : format[key][1];
  3688. }
  3689. var de = moment.defineLocale('de', {
  3690. months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
  3691. monthsShort : 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
  3692. monthsParseExact : true,
  3693. weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
  3694. weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
  3695. weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
  3696. weekdaysParseExact : true,
  3697. longDateFormat : {
  3698. LT: 'HH:mm',
  3699. LTS: 'HH:mm:ss',
  3700. L : 'DD.MM.YYYY',
  3701. LL : 'D. MMMM YYYY',
  3702. LLL : 'D. MMMM YYYY HH:mm',
  3703. LLLL : 'dddd, D. MMMM YYYY HH:mm'
  3704. },
  3705. calendar : {
  3706. sameDay: '[heute um] LT [Uhr]',
  3707. sameElse: 'L',
  3708. nextDay: '[morgen um] LT [Uhr]',
  3709. nextWeek: 'dddd [um] LT [Uhr]',
  3710. lastDay: '[gestern um] LT [Uhr]',
  3711. lastWeek: '[letzten] dddd [um] LT [Uhr]'
  3712. },
  3713. relativeTime : {
  3714. future : 'in %s',
  3715. past : 'vor %s',
  3716. s : 'ein paar Sekunden',
  3717. m : processRelativeTime,
  3718. mm : '%d Minuten',
  3719. h : processRelativeTime,
  3720. hh : '%d Stunden',
  3721. d : processRelativeTime,
  3722. dd : processRelativeTime,
  3723. M : processRelativeTime,
  3724. MM : processRelativeTime,
  3725. y : processRelativeTime,
  3726. yy : processRelativeTime
  3727. },
  3728. dayOfMonthOrdinalParse: /\d{1,2}\./,
  3729. ordinal : '%d.',
  3730. week : {
  3731. dow : 1, // Monday is the first day of the week.
  3732. doy : 4 // The week that contains Jan 4th is the first week of the year.
  3733. }
  3734. });
  3735. return de;
  3736. })));
  3737. //! moment.js locale configuration
  3738. //! locale : Spanish [es]
  3739. //! author : Julio Napurí : https://github.com/julionc
  3740. ;(function (global, factory) {
  3741. typeof exports === 'object' && typeof module !== 'undefined'
  3742. && typeof require === 'function' ? factory(require('../moment')) :
  3743. typeof define === 'function' && define.amd ? define('moment/locale/es',['../moment'], factory) :
  3744. factory(global.moment)
  3745. }(this, (function (moment) { 'use strict';
  3746. var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
  3747. var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
  3748. var monthsParse = [/^ene/i, /^feb/i, /^mar/i, /^abr/i, /^may/i, /^jun/i, /^jul/i, /^ago/i, /^sep/i, /^oct/i, /^nov/i, /^dic/i];
  3749. var monthsRegex = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
  3750. var es = moment.defineLocale('es', {
  3751. months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
  3752. monthsShort : function (m, format) {
  3753. if (!m) {
  3754. return monthsShortDot;
  3755. } else if (/-MMM-/.test(format)) {
  3756. return monthsShort[m.month()];
  3757. } else {
  3758. return monthsShortDot[m.month()];
  3759. }
  3760. },
  3761. monthsRegex : monthsRegex,
  3762. monthsShortRegex : monthsRegex,
  3763. monthsStrictRegex : /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
  3764. monthsShortStrictRegex : /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
  3765. monthsParse : monthsParse,
  3766. longMonthsParse : monthsParse,
  3767. shortMonthsParse : monthsParse,
  3768. weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
  3769. weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
  3770. weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
  3771. weekdaysParseExact : true,
  3772. longDateFormat : {
  3773. LT : 'H:mm',
  3774. LTS : 'H:mm:ss',
  3775. L : 'DD/MM/YYYY',
  3776. LL : 'D [de] MMMM [de] YYYY',
  3777. LLL : 'D [de] MMMM [de] YYYY H:mm',
  3778. LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
  3779. },
  3780. calendar : {
  3781. sameDay : function () {
  3782. return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
  3783. },
  3784. nextDay : function () {
  3785. return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
  3786. },
  3787. nextWeek : function () {
  3788. return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
  3789. },
  3790. lastDay : function () {
  3791. return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
  3792. },
  3793. lastWeek : function () {
  3794. return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
  3795. },
  3796. sameElse : 'L'
  3797. },
  3798. relativeTime : {
  3799. future : 'en %s',
  3800. past : 'hace %s',
  3801. s : 'unos segundos',
  3802. m : 'un minuto',
  3803. mm : '%d minutos',
  3804. h : 'una hora',
  3805. hh : '%d horas',
  3806. d : 'un día',
  3807. dd : '%d días',
  3808. M : 'un mes',
  3809. MM : '%d meses',
  3810. y : 'un año',
  3811. yy : '%d años'
  3812. },
  3813. dayOfMonthOrdinalParse : /\d{1,2}º/,
  3814. ordinal : '%dº',
  3815. week : {
  3816. dow : 1, // Monday is the first day of the week.
  3817. doy : 4 // The week that contains Jan 4th is the first week of the year.
  3818. }
  3819. });
  3820. return es;
  3821. })));
  3822. //! moment.js locale configuration
  3823. //! locale : French [fr]
  3824. //! author : John Fischer : https://github.com/jfroffice
  3825. ;(function (global, factory) {
  3826. typeof exports === 'object' && typeof module !== 'undefined'
  3827. && typeof require === 'function' ? factory(require('../moment')) :
  3828. typeof define === 'function' && define.amd ? define('moment/locale/fr',['../moment'], factory) :
  3829. factory(global.moment)
  3830. }(this, (function (moment) { 'use strict';
  3831. var fr = moment.defineLocale('fr', {
  3832. months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
  3833. monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
  3834. monthsParseExact : true,
  3835. weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
  3836. weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
  3837. weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
  3838. weekdaysParseExact : true,
  3839. longDateFormat : {
  3840. LT : 'HH:mm',
  3841. LTS : 'HH:mm:ss',
  3842. L : 'DD/MM/YYYY',
  3843. LL : 'D MMMM YYYY',
  3844. LLL : 'D MMMM YYYY HH:mm',
  3845. LLLL : 'dddd D MMMM YYYY HH:mm'
  3846. },
  3847. calendar : {
  3848. sameDay : '[Aujourd’hui à] LT',
  3849. nextDay : '[Demain à] LT',
  3850. nextWeek : 'dddd [à] LT',
  3851. lastDay : '[Hier à] LT',
  3852. lastWeek : 'dddd [dernier à] LT',
  3853. sameElse : 'L'
  3854. },
  3855. relativeTime : {
  3856. future : 'dans %s',
  3857. past : 'il y a %s',
  3858. s : 'quelques secondes',
  3859. m : 'une minute',
  3860. mm : '%d minutes',
  3861. h : 'une heure',
  3862. hh : '%d heures',
  3863. d : 'un jour',
  3864. dd : '%d jours',
  3865. M : 'un mois',
  3866. MM : '%d mois',
  3867. y : 'un an',
  3868. yy : '%d ans'
  3869. },
  3870. dayOfMonthOrdinalParse: /\d{1,2}(er|)/,
  3871. ordinal : function (number, period) {
  3872. switch (period) {
  3873. // TODO: Return 'e' when day of month > 1. Move this case inside
  3874. // block for masculine words below.
  3875. // See https://github.com/moment/moment/issues/3375
  3876. case 'D':
  3877. return number + (number === 1 ? 'er' : '');
  3878. // Words with masculine grammatical gender: mois, trimestre, jour
  3879. default:
  3880. case 'M':
  3881. case 'Q':
  3882. case 'DDD':
  3883. case 'd':
  3884. return number + (number === 1 ? 'er' : 'e');
  3885. // Words with feminine grammatical gender: semaine
  3886. case 'w':
  3887. case 'W':
  3888. return number + (number === 1 ? 're' : 'e');
  3889. }
  3890. },
  3891. week : {
  3892. dow : 1, // Monday is the first day of the week.
  3893. doy : 4 // The week that contains Jan 4th is the first week of the year.
  3894. }
  3895. });
  3896. return fr;
  3897. })));
  3898. //! moment.js locale configuration
  3899. //! locale : Hebrew [he]
  3900. //! author : Tomer Cohen : https://github.com/tomer
  3901. //! author : Moshe Simantov : https://github.com/DevelopmentIL
  3902. //! author : Tal Ater : https://github.com/TalAter
  3903. ;(function (global, factory) {
  3904. typeof exports === 'object' && typeof module !== 'undefined'
  3905. && typeof require === 'function' ? factory(require('../moment')) :
  3906. typeof define === 'function' && define.amd ? define('moment/locale/he',['../moment'], factory) :
  3907. factory(global.moment)
  3908. }(this, (function (moment) { 'use strict';
  3909. var he = moment.defineLocale('he', {
  3910. months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
  3911. monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
  3912. weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
  3913. weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
  3914. weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
  3915. longDateFormat : {
  3916. LT : 'HH:mm',
  3917. LTS : 'HH:mm:ss',
  3918. L : 'DD/MM/YYYY',
  3919. LL : 'D [ב]MMMM YYYY',
  3920. LLL : 'D [ב]MMMM YYYY HH:mm',
  3921. LLLL : 'dddd, D [ב]MMMM YYYY HH:mm',
  3922. l : 'D/M/YYYY',
  3923. ll : 'D MMM YYYY',
  3924. lll : 'D MMM YYYY HH:mm',
  3925. llll : 'ddd, D MMM YYYY HH:mm'
  3926. },
  3927. calendar : {
  3928. sameDay : '[היום ב־]LT',
  3929. nextDay : '[מחר ב־]LT',
  3930. nextWeek : 'dddd [בשעה] LT',
  3931. lastDay : '[אתמול ב־]LT',
  3932. lastWeek : '[ביום] dddd [האחרון בשעה] LT',
  3933. sameElse : 'L'
  3934. },
  3935. relativeTime : {
  3936. future : 'בעוד %s',
  3937. past : 'לפני %s',
  3938. s : 'מספר שניות',
  3939. m : 'דקה',
  3940. mm : '%d דקות',
  3941. h : 'שעה',
  3942. hh : function (number) {
  3943. if (number === 2) {
  3944. return 'שעתיים';
  3945. }
  3946. return number + ' שעות';
  3947. },
  3948. d : 'יום',
  3949. dd : function (number) {
  3950. if (number === 2) {
  3951. return 'יומיים';
  3952. }
  3953. return number + ' ימים';
  3954. },
  3955. M : 'חודש',
  3956. MM : function (number) {
  3957. if (number === 2) {
  3958. return 'חודשיים';
  3959. }
  3960. return number + ' חודשים';
  3961. },
  3962. y : 'שנה',
  3963. yy : function (number) {
  3964. if (number === 2) {
  3965. return 'שנתיים';
  3966. } else if (number % 10 === 0 && number !== 10) {
  3967. return number + ' שנה';
  3968. }
  3969. return number + ' שנים';
  3970. }
  3971. },
  3972. meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
  3973. isPM : function (input) {
  3974. return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
  3975. },
  3976. meridiem : function (hour, minute, isLower) {
  3977. if (hour < 5) {
  3978. return 'לפנות בוקר';
  3979. } else if (hour < 10) {
  3980. return 'בבוקר';
  3981. } else if (hour < 12) {
  3982. return isLower ? 'לפנה"צ' : 'לפני הצהריים';
  3983. } else if (hour < 18) {
  3984. return isLower ? 'אחה"צ' : 'אחרי הצהריים';
  3985. } else {
  3986. return 'בערב';
  3987. }
  3988. }
  3989. });
  3990. return he;
  3991. })));
  3992. //! moment.js locale configuration
  3993. //! locale : Hungarian [hu]
  3994. //! author : Adam Brunner : https://github.com/adambrunner
  3995. ;(function (global, factory) {
  3996. typeof exports === 'object' && typeof module !== 'undefined'
  3997. && typeof require === 'function' ? factory(require('../moment')) :
  3998. typeof define === 'function' && define.amd ? define('moment/locale/hu',['../moment'], factory) :
  3999. factory(global.moment)
  4000. }(this, (function (moment) { 'use strict';
  4001. var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
  4002. function translate(number, withoutSuffix, key, isFuture) {
  4003. var num = number;
  4004. switch (key) {
  4005. case 's':
  4006. return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
  4007. case 'm':
  4008. return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
  4009. case 'mm':
  4010. return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
  4011. case 'h':
  4012. return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
  4013. case 'hh':
  4014. return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
  4015. case 'd':
  4016. return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
  4017. case 'dd':
  4018. return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
  4019. case 'M':
  4020. return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
  4021. case 'MM':
  4022. return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
  4023. case 'y':
  4024. return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
  4025. case 'yy':
  4026. return num + (isFuture || withoutSuffix ? ' év' : ' éve');
  4027. }
  4028. return '';
  4029. }
  4030. function week(isFuture) {
  4031. return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
  4032. }
  4033. var hu = moment.defineLocale('hu', {
  4034. months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
  4035. monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
  4036. weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
  4037. weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
  4038. weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
  4039. longDateFormat : {
  4040. LT : 'H:mm',
  4041. LTS : 'H:mm:ss',
  4042. L : 'YYYY.MM.DD.',
  4043. LL : 'YYYY. MMMM D.',
  4044. LLL : 'YYYY. MMMM D. H:mm',
  4045. LLLL : 'YYYY. MMMM D., dddd H:mm'
  4046. },
  4047. meridiemParse: /de|du/i,
  4048. isPM: function (input) {
  4049. return input.charAt(1).toLowerCase() === 'u';
  4050. },
  4051. meridiem : function (hours, minutes, isLower) {
  4052. if (hours < 12) {
  4053. return isLower === true ? 'de' : 'DE';
  4054. } else {
  4055. return isLower === true ? 'du' : 'DU';
  4056. }
  4057. },
  4058. calendar : {
  4059. sameDay : '[ma] LT[-kor]',
  4060. nextDay : '[holnap] LT[-kor]',
  4061. nextWeek : function () {
  4062. return week.call(this, true);
  4063. },
  4064. lastDay : '[tegnap] LT[-kor]',
  4065. lastWeek : function () {
  4066. return week.call(this, false);
  4067. },
  4068. sameElse : 'L'
  4069. },
  4070. relativeTime : {
  4071. future : '%s múlva',
  4072. past : '%s',
  4073. s : translate,
  4074. m : translate,
  4075. mm : translate,
  4076. h : translate,
  4077. hh : translate,
  4078. d : translate,
  4079. dd : translate,
  4080. M : translate,
  4081. MM : translate,
  4082. y : translate,
  4083. yy : translate
  4084. },
  4085. dayOfMonthOrdinalParse: /\d{1,2}\./,
  4086. ordinal : '%d.',
  4087. week : {
  4088. dow : 1, // Monday is the first day of the week.
  4089. doy : 4 // The week that contains Jan 4th is the first week of the year.
  4090. }
  4091. });
  4092. return hu;
  4093. })));
  4094. //! moment.js locale configuration
  4095. //! locale : Indonesian [id]
  4096. //! author : Mohammad Satrio Utomo : https://github.com/tyok
  4097. //! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
  4098. ;(function (global, factory) {
  4099. typeof exports === 'object' && typeof module !== 'undefined'
  4100. && typeof require === 'function' ? factory(require('../moment')) :
  4101. typeof define === 'function' && define.amd ? define('moment/locale/id',['../moment'], factory) :
  4102. factory(global.moment)
  4103. }(this, (function (moment) { 'use strict';
  4104. var id = moment.defineLocale('id', {
  4105. months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
  4106. monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
  4107. weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
  4108. weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
  4109. weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
  4110. longDateFormat : {
  4111. LT : 'HH.mm',
  4112. LTS : 'HH.mm.ss',
  4113. L : 'DD/MM/YYYY',
  4114. LL : 'D MMMM YYYY',
  4115. LLL : 'D MMMM YYYY [pukul] HH.mm',
  4116. LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
  4117. },
  4118. meridiemParse: /pagi|siang|sore|malam/,
  4119. meridiemHour : function (hour, meridiem) {
  4120. if (hour === 12) {
  4121. hour = 0;
  4122. }
  4123. if (meridiem === 'pagi') {
  4124. return hour;
  4125. } else if (meridiem === 'siang') {
  4126. return hour >= 11 ? hour : hour + 12;
  4127. } else if (meridiem === 'sore' || meridiem === 'malam') {
  4128. return hour + 12;
  4129. }
  4130. },
  4131. meridiem : function (hours, minutes, isLower) {
  4132. if (hours < 11) {
  4133. return 'pagi';
  4134. } else if (hours < 15) {
  4135. return 'siang';
  4136. } else if (hours < 19) {
  4137. return 'sore';
  4138. } else {
  4139. return 'malam';
  4140. }
  4141. },
  4142. calendar : {
  4143. sameDay : '[Hari ini pukul] LT',
  4144. nextDay : '[Besok pukul] LT',
  4145. nextWeek : 'dddd [pukul] LT',
  4146. lastDay : '[Kemarin pukul] LT',
  4147. lastWeek : 'dddd [lalu pukul] LT',
  4148. sameElse : 'L'
  4149. },
  4150. relativeTime : {
  4151. future : 'dalam %s',
  4152. past : '%s yang lalu',
  4153. s : 'beberapa detik',
  4154. m : 'semenit',
  4155. mm : '%d menit',
  4156. h : 'sejam',
  4157. hh : '%d jam',
  4158. d : 'sehari',
  4159. dd : '%d hari',
  4160. M : 'sebulan',
  4161. MM : '%d bulan',
  4162. y : 'setahun',
  4163. yy : '%d tahun'
  4164. },
  4165. week : {
  4166. dow : 1, // Monday is the first day of the week.
  4167. doy : 7 // The week that contains Jan 1st is the first week of the year.
  4168. }
  4169. });
  4170. return id;
  4171. })));
  4172. //! moment.js locale configuration
  4173. //! locale : Italian [it]
  4174. //! author : Lorenzo : https://github.com/aliem
  4175. //! author: Mattia Larentis: https://github.com/nostalgiaz
  4176. ;(function (global, factory) {
  4177. typeof exports === 'object' && typeof module !== 'undefined'
  4178. && typeof require === 'function' ? factory(require('../moment')) :
  4179. typeof define === 'function' && define.amd ? define('moment/locale/it',['../moment'], factory) :
  4180. factory(global.moment)
  4181. }(this, (function (moment) { 'use strict';
  4182. var it = moment.defineLocale('it', {
  4183. months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
  4184. monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
  4185. weekdays : 'domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato'.split('_'),
  4186. weekdaysShort : 'dom_lun_mar_mer_gio_ven_sab'.split('_'),
  4187. weekdaysMin : 'do_lu_ma_me_gi_ve_sa'.split('_'),
  4188. longDateFormat : {
  4189. LT : 'HH:mm',
  4190. LTS : 'HH:mm:ss',
  4191. L : 'DD/MM/YYYY',
  4192. LL : 'D MMMM YYYY',
  4193. LLL : 'D MMMM YYYY HH:mm',
  4194. LLLL : 'dddd, D MMMM YYYY HH:mm'
  4195. },
  4196. calendar : {
  4197. sameDay: '[Oggi alle] LT',
  4198. nextDay: '[Domani alle] LT',
  4199. nextWeek: 'dddd [alle] LT',
  4200. lastDay: '[Ieri alle] LT',
  4201. lastWeek: function () {
  4202. switch (this.day()) {
  4203. case 0:
  4204. return '[la scorsa] dddd [alle] LT';
  4205. default:
  4206. return '[lo scorso] dddd [alle] LT';
  4207. }
  4208. },
  4209. sameElse: 'L'
  4210. },
  4211. relativeTime : {
  4212. future : function (s) {
  4213. return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
  4214. },
  4215. past : '%s fa',
  4216. s : 'alcuni secondi',
  4217. m : 'un minuto',
  4218. mm : '%d minuti',
  4219. h : 'un\'ora',
  4220. hh : '%d ore',
  4221. d : 'un giorno',
  4222. dd : '%d giorni',
  4223. M : 'un mese',
  4224. MM : '%d mesi',
  4225. y : 'un anno',
  4226. yy : '%d anni'
  4227. },
  4228. dayOfMonthOrdinalParse : /\d{1,2}º/,
  4229. ordinal: '%dº',
  4230. week : {
  4231. dow : 1, // Monday is the first day of the week.
  4232. doy : 4 // The week that contains Jan 4th is the first week of the year.
  4233. }
  4234. });
  4235. return it;
  4236. })));
  4237. //! moment.js locale configuration
  4238. //! locale : Japanese [ja]
  4239. //! author : LI Long : https://github.com/baryon
  4240. ;(function (global, factory) {
  4241. typeof exports === 'object' && typeof module !== 'undefined'
  4242. && typeof require === 'function' ? factory(require('../moment')) :
  4243. typeof define === 'function' && define.amd ? define('moment/locale/ja',['../moment'], factory) :
  4244. factory(global.moment)
  4245. }(this, (function (moment) { 'use strict';
  4246. var ja = moment.defineLocale('ja', {
  4247. months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
  4248. monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
  4249. weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
  4250. weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
  4251. weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
  4252. longDateFormat : {
  4253. LT : 'HH:mm',
  4254. LTS : 'HH:mm:ss',
  4255. L : 'YYYY/MM/DD',
  4256. LL : 'YYYY年M月D日',
  4257. LLL : 'YYYY年M月D日 HH:mm',
  4258. LLLL : 'YYYY年M月D日 HH:mm dddd',
  4259. l : 'YYYY/MM/DD',
  4260. ll : 'YYYY年M月D日',
  4261. lll : 'YYYY年M月D日 HH:mm',
  4262. llll : 'YYYY年M月D日 HH:mm dddd'
  4263. },
  4264. meridiemParse: /午前|午後/i,
  4265. isPM : function (input) {
  4266. return input === '午後';
  4267. },
  4268. meridiem : function (hour, minute, isLower) {
  4269. if (hour < 12) {
  4270. return '午前';
  4271. } else {
  4272. return '午後';
  4273. }
  4274. },
  4275. calendar : {
  4276. sameDay : '[今日] LT',
  4277. nextDay : '[明日] LT',
  4278. nextWeek : '[来週]dddd LT',
  4279. lastDay : '[昨日] LT',
  4280. lastWeek : '[前週]dddd LT',
  4281. sameElse : 'L'
  4282. },
  4283. dayOfMonthOrdinalParse : /\d{1,2}日/,
  4284. ordinal : function (number, period) {
  4285. switch (period) {
  4286. case 'd':
  4287. case 'D':
  4288. case 'DDD':
  4289. return number + '日';
  4290. default:
  4291. return number;
  4292. }
  4293. },
  4294. relativeTime : {
  4295. future : '%s後',
  4296. past : '%s前',
  4297. s : '数秒',
  4298. m : '1分',
  4299. mm : '%d分',
  4300. h : '1時間',
  4301. hh : '%d時間',
  4302. d : '1日',
  4303. dd : '%d日',
  4304. M : '1ヶ月',
  4305. MM : '%dヶ月',
  4306. y : '1年',
  4307. yy : '%d年'
  4308. }
  4309. });
  4310. return ja;
  4311. })));
  4312. //! moment.js locale configuration
  4313. //! locale : Norwegian Bokmål [nb]
  4314. //! authors : Espen Hovlandsdal : https://github.com/rexxars
  4315. //! Sigurd Gartmann : https://github.com/sigurdga
  4316. ;(function (global, factory) {
  4317. typeof exports === 'object' && typeof module !== 'undefined'
  4318. && typeof require === 'function' ? factory(require('../moment')) :
  4319. typeof define === 'function' && define.amd ? define('moment/locale/nb',['../moment'], factory) :
  4320. factory(global.moment)
  4321. }(this, (function (moment) { 'use strict';
  4322. var nb = moment.defineLocale('nb', {
  4323. months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
  4324. monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
  4325. monthsParseExact : true,
  4326. weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
  4327. weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
  4328. weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
  4329. weekdaysParseExact : true,
  4330. longDateFormat : {
  4331. LT : 'HH:mm',
  4332. LTS : 'HH:mm:ss',
  4333. L : 'DD.MM.YYYY',
  4334. LL : 'D. MMMM YYYY',
  4335. LLL : 'D. MMMM YYYY [kl.] HH:mm',
  4336. LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
  4337. },
  4338. calendar : {
  4339. sameDay: '[i dag kl.] LT',
  4340. nextDay: '[i morgen kl.] LT',
  4341. nextWeek: 'dddd [kl.] LT',
  4342. lastDay: '[i går kl.] LT',
  4343. lastWeek: '[forrige] dddd [kl.] LT',
  4344. sameElse: 'L'
  4345. },
  4346. relativeTime : {
  4347. future : 'om %s',
  4348. past : '%s siden',
  4349. s : 'noen sekunder',
  4350. m : 'ett minutt',
  4351. mm : '%d minutter',
  4352. h : 'en time',
  4353. hh : '%d timer',
  4354. d : 'en dag',
  4355. dd : '%d dager',
  4356. M : 'en måned',
  4357. MM : '%d måneder',
  4358. y : 'ett år',
  4359. yy : '%d år'
  4360. },
  4361. dayOfMonthOrdinalParse: /\d{1,2}\./,
  4362. ordinal : '%d.',
  4363. week : {
  4364. dow : 1, // Monday is the first day of the week.
  4365. doy : 4 // The week that contains Jan 4th is the first week of the year.
  4366. }
  4367. });
  4368. return nb;
  4369. })));
  4370. //! moment.js locale configuration
  4371. //! locale : Dutch [nl]
  4372. //! author : Joris Röling : https://github.com/jorisroling
  4373. //! author : Jacob Middag : https://github.com/middagj
  4374. ;(function (global, factory) {
  4375. typeof exports === 'object' && typeof module !== 'undefined'
  4376. && typeof require === 'function' ? factory(require('../moment')) :
  4377. typeof define === 'function' && define.amd ? define('moment/locale/nl',['../moment'], factory) :
  4378. factory(global.moment)
  4379. }(this, (function (moment) { 'use strict';
  4380. var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
  4381. var monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
  4382. var monthsParse = [/^jan/i, /^feb/i, /^maart|mrt.?$/i, /^apr/i, /^mei$/i, /^jun[i.]?$/i, /^jul[i.]?$/i, /^aug/i, /^sep/i, /^okt/i, /^nov/i, /^dec/i];
  4383. var monthsRegex = /^(januari|februari|maart|april|mei|april|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
  4384. var nl = moment.defineLocale('nl', {
  4385. months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
  4386. monthsShort : function (m, format) {
  4387. if (!m) {
  4388. return monthsShortWithDots;
  4389. } else if (/-MMM-/.test(format)) {
  4390. return monthsShortWithoutDots[m.month()];
  4391. } else {
  4392. return monthsShortWithDots[m.month()];
  4393. }
  4394. },
  4395. monthsRegex: monthsRegex,
  4396. monthsShortRegex: monthsRegex,
  4397. monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
  4398. monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
  4399. monthsParse : monthsParse,
  4400. longMonthsParse : monthsParse,
  4401. shortMonthsParse : monthsParse,
  4402. weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
  4403. weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
  4404. weekdaysMin : 'zo_ma_di_wo_do_vr_za'.split('_'),
  4405. weekdaysParseExact : true,
  4406. longDateFormat : {
  4407. LT : 'HH:mm',
  4408. LTS : 'HH:mm:ss',
  4409. L : 'DD-MM-YYYY',
  4410. LL : 'D MMMM YYYY',
  4411. LLL : 'D MMMM YYYY HH:mm',
  4412. LLLL : 'dddd D MMMM YYYY HH:mm'
  4413. },
  4414. calendar : {
  4415. sameDay: '[vandaag om] LT',
  4416. nextDay: '[morgen om] LT',
  4417. nextWeek: 'dddd [om] LT',
  4418. lastDay: '[gisteren om] LT',
  4419. lastWeek: '[afgelopen] dddd [om] LT',
  4420. sameElse: 'L'
  4421. },
  4422. relativeTime : {
  4423. future : 'over %s',
  4424. past : '%s geleden',
  4425. s : 'een paar seconden',
  4426. m : 'één minuut',
  4427. mm : '%d minuten',
  4428. h : 'één uur',
  4429. hh : '%d uur',
  4430. d : 'één dag',
  4431. dd : '%d dagen',
  4432. M : 'één maand',
  4433. MM : '%d maanden',
  4434. y : 'één jaar',
  4435. yy : '%d jaar'
  4436. },
  4437. dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
  4438. ordinal : function (number) {
  4439. return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
  4440. },
  4441. week : {
  4442. dow : 1, // Monday is the first day of the week.
  4443. doy : 4 // The week that contains Jan 4th is the first week of the year.
  4444. }
  4445. });
  4446. return nl;
  4447. })));
  4448. //! moment.js locale configuration
  4449. //! locale : Polish [pl]
  4450. //! author : Rafal Hirsz : https://github.com/evoL
  4451. ;(function (global, factory) {
  4452. typeof exports === 'object' && typeof module !== 'undefined'
  4453. && typeof require === 'function' ? factory(require('../moment')) :
  4454. typeof define === 'function' && define.amd ? define('moment/locale/pl',['../moment'], factory) :
  4455. factory(global.moment)
  4456. }(this, (function (moment) { 'use strict';
  4457. var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_');
  4458. var monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
  4459. function plural(n) {
  4460. return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
  4461. }
  4462. function translate(number, withoutSuffix, key) {
  4463. var result = number + ' ';
  4464. switch (key) {
  4465. case 'm':
  4466. return withoutSuffix ? 'minuta' : 'minutę';
  4467. case 'mm':
  4468. return result + (plural(number) ? 'minuty' : 'minut');
  4469. case 'h':
  4470. return withoutSuffix ? 'godzina' : 'godzinę';
  4471. case 'hh':
  4472. return result + (plural(number) ? 'godziny' : 'godzin');
  4473. case 'MM':
  4474. return result + (plural(number) ? 'miesiące' : 'miesięcy');
  4475. case 'yy':
  4476. return result + (plural(number) ? 'lata' : 'lat');
  4477. }
  4478. }
  4479. var pl = moment.defineLocale('pl', {
  4480. months : function (momentToFormat, format) {
  4481. if (!momentToFormat) {
  4482. return monthsNominative;
  4483. } else if (format === '') {
  4484. // Hack: if format empty we know this is used to generate
  4485. // RegExp by moment. Give then back both valid forms of months
  4486. // in RegExp ready format.
  4487. return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
  4488. } else if (/D MMMM/.test(format)) {
  4489. return monthsSubjective[momentToFormat.month()];
  4490. } else {
  4491. return monthsNominative[momentToFormat.month()];
  4492. }
  4493. },
  4494. monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
  4495. weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
  4496. weekdaysShort : 'ndz_pon_wt_śr_czw_pt_sob'.split('_'),
  4497. weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
  4498. longDateFormat : {
  4499. LT : 'HH:mm',
  4500. LTS : 'HH:mm:ss',
  4501. L : 'DD.MM.YYYY',
  4502. LL : 'D MMMM YYYY',
  4503. LLL : 'D MMMM YYYY HH:mm',
  4504. LLLL : 'dddd, D MMMM YYYY HH:mm'
  4505. },
  4506. calendar : {
  4507. sameDay: '[Dziś o] LT',
  4508. nextDay: '[Jutro o] LT',
  4509. nextWeek: function () {
  4510. switch (this.day()) {
  4511. case 0:
  4512. return '[W niedzielę o] LT';
  4513. case 2:
  4514. return '[We wtorek o] LT';
  4515. case 3:
  4516. return '[W środę o] LT';
  4517. case 6:
  4518. return '[W sobotę o] LT';
  4519. default:
  4520. return '[W] dddd [o] LT';
  4521. }
  4522. },
  4523. lastDay: '[Wczoraj o] LT',
  4524. lastWeek: function () {
  4525. switch (this.day()) {
  4526. case 0:
  4527. return '[W zeszłą niedzielę o] LT';
  4528. case 3:
  4529. return '[W zeszłą środę o] LT';
  4530. case 6:
  4531. return '[W zeszłą sobotę o] LT';
  4532. default:
  4533. return '[W zeszły] dddd [o] LT';
  4534. }
  4535. },
  4536. sameElse: 'L'
  4537. },
  4538. relativeTime : {
  4539. future : 'za %s',
  4540. past : '%s temu',
  4541. s : 'kilka sekund',
  4542. m : translate,
  4543. mm : translate,
  4544. h : translate,
  4545. hh : translate,
  4546. d : '1 dzień',
  4547. dd : '%d dni',
  4548. M : 'miesiąc',
  4549. MM : translate,
  4550. y : 'rok',
  4551. yy : translate
  4552. },
  4553. dayOfMonthOrdinalParse: /\d{1,2}\./,
  4554. ordinal : '%d.',
  4555. week : {
  4556. dow : 1, // Monday is the first day of the week.
  4557. doy : 4 // The week that contains Jan 4th is the first week of the year.
  4558. }
  4559. });
  4560. return pl;
  4561. })));
  4562. //! moment.js locale configuration
  4563. //! locale : Portuguese (Brazil) [pt-br]
  4564. //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
  4565. ;(function (global, factory) {
  4566. typeof exports === 'object' && typeof module !== 'undefined'
  4567. && typeof require === 'function' ? factory(require('../moment')) :
  4568. typeof define === 'function' && define.amd ? define('moment/locale/pt-br',['../moment'], factory) :
  4569. factory(global.moment)
  4570. }(this, (function (moment) { 'use strict';
  4571. var ptBr = moment.defineLocale('pt-br', {
  4572. months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
  4573. monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
  4574. weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
  4575. weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
  4576. weekdaysMin : 'Do_2ª_3ª_4ª_5ª_6ª_Sá'.split('_'),
  4577. weekdaysParseExact : true,
  4578. longDateFormat : {
  4579. LT : 'HH:mm',
  4580. LTS : 'HH:mm:ss',
  4581. L : 'DD/MM/YYYY',
  4582. LL : 'D [de] MMMM [de] YYYY',
  4583. LLL : 'D [de] MMMM [de] YYYY [às] HH:mm',
  4584. LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm'
  4585. },
  4586. calendar : {
  4587. sameDay: '[Hoje às] LT',
  4588. nextDay: '[Amanhã às] LT',
  4589. nextWeek: 'dddd [às] LT',
  4590. lastDay: '[Ontem às] LT',
  4591. lastWeek: function () {
  4592. return (this.day() === 0 || this.day() === 6) ?
  4593. '[Último] dddd [às] LT' : // Saturday + Sunday
  4594. '[Última] dddd [às] LT'; // Monday - Friday
  4595. },
  4596. sameElse: 'L'
  4597. },
  4598. relativeTime : {
  4599. future : 'em %s',
  4600. past : '%s atrás',
  4601. s : 'poucos segundos',
  4602. ss : '%d segundos',
  4603. m : 'um minuto',
  4604. mm : '%d minutos',
  4605. h : 'uma hora',
  4606. hh : '%d horas',
  4607. d : 'um dia',
  4608. dd : '%d dias',
  4609. M : 'um mês',
  4610. MM : '%d meses',
  4611. y : 'um ano',
  4612. yy : '%d anos'
  4613. },
  4614. dayOfMonthOrdinalParse: /\d{1,2}º/,
  4615. ordinal : '%dº'
  4616. });
  4617. return ptBr;
  4618. })));
  4619. //! moment.js locale configuration
  4620. //! locale : Russian [ru]
  4621. //! author : Viktorminator : https://github.com/Viktorminator
  4622. //! Author : Menelion Elensúle : https://github.com/Oire
  4623. //! author : Коренберг Марк : https://github.com/socketpair
  4624. ;(function (global, factory) {
  4625. typeof exports === 'object' && typeof module !== 'undefined'
  4626. && typeof require === 'function' ? factory(require('../moment')) :
  4627. typeof define === 'function' && define.amd ? define('moment/locale/ru',['../moment'], factory) :
  4628. factory(global.moment)
  4629. }(this, (function (moment) { 'use strict';
  4630. function plural(word, num) {
  4631. var forms = word.split('_');
  4632. return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
  4633. }
  4634. function relativeTimeWithPlural(number, withoutSuffix, key) {
  4635. var format = {
  4636. 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
  4637. 'hh': 'час_часа_часов',
  4638. 'dd': 'день_дня_дней',
  4639. 'MM': 'месяц_месяца_месяцев',
  4640. 'yy': 'год_года_лет'
  4641. };
  4642. if (key === 'm') {
  4643. return withoutSuffix ? 'минута' : 'минуту';
  4644. }
  4645. else {
  4646. return number + ' ' + plural(format[key], +number);
  4647. }
  4648. }
  4649. var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i];
  4650. // http://new.gramota.ru/spravka/rules/139-prop : § 103
  4651. // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
  4652. // CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
  4653. var ru = moment.defineLocale('ru', {
  4654. months : {
  4655. format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
  4656. standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
  4657. },
  4658. monthsShort : {
  4659. // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ?
  4660. format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'),
  4661. standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_')
  4662. },
  4663. weekdays : {
  4664. standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
  4665. format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'),
  4666. isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/
  4667. },
  4668. weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
  4669. weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
  4670. monthsParse : monthsParse,
  4671. longMonthsParse : monthsParse,
  4672. shortMonthsParse : monthsParse,
  4673. // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки
  4674. monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
  4675. // копия предыдущего
  4676. monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
  4677. // полные названия с падежами
  4678. monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,
  4679. // Выражение, которое соотвествует только сокращённым формам
  4680. monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,
  4681. longDateFormat : {
  4682. LT : 'HH:mm',
  4683. LTS : 'HH:mm:ss',
  4684. L : 'DD.MM.YYYY',
  4685. LL : 'D MMMM YYYY г.',
  4686. LLL : 'D MMMM YYYY г., HH:mm',
  4687. LLLL : 'dddd, D MMMM YYYY г., HH:mm'
  4688. },
  4689. calendar : {
  4690. sameDay: '[Сегодня в] LT',
  4691. nextDay: '[Завтра в] LT',
  4692. lastDay: '[Вчера в] LT',
  4693. nextWeek: function (now) {
  4694. if (now.week() !== this.week()) {
  4695. switch (this.day()) {
  4696. case 0:
  4697. return '[В следующее] dddd [в] LT';
  4698. case 1:
  4699. case 2:
  4700. case 4:
  4701. return '[В следующий] dddd [в] LT';
  4702. case 3:
  4703. case 5:
  4704. case 6:
  4705. return '[В следующую] dddd [в] LT';
  4706. }
  4707. } else {
  4708. if (this.day() === 2) {
  4709. return '[Во] dddd [в] LT';
  4710. } else {
  4711. return '[В] dddd [в] LT';
  4712. }
  4713. }
  4714. },
  4715. lastWeek: function (now) {
  4716. if (now.week() !== this.week()) {
  4717. switch (this.day()) {
  4718. case 0:
  4719. return '[В прошлое] dddd [в] LT';
  4720. case 1:
  4721. case 2:
  4722. case 4:
  4723. return '[В прошлый] dddd [в] LT';
  4724. case 3:
  4725. case 5:
  4726. case 6:
  4727. return '[В прошлую] dddd [в] LT';
  4728. }
  4729. } else {
  4730. if (this.day() === 2) {
  4731. return '[Во] dddd [в] LT';
  4732. } else {
  4733. return '[В] dddd [в] LT';
  4734. }
  4735. }
  4736. },
  4737. sameElse: 'L'
  4738. },
  4739. relativeTime : {
  4740. future : 'через %s',
  4741. past : '%s назад',
  4742. s : 'несколько секунд',
  4743. m : relativeTimeWithPlural,
  4744. mm : relativeTimeWithPlural,
  4745. h : 'час',
  4746. hh : relativeTimeWithPlural,
  4747. d : 'день',
  4748. dd : relativeTimeWithPlural,
  4749. M : 'месяц',
  4750. MM : relativeTimeWithPlural,
  4751. y : 'год',
  4752. yy : relativeTimeWithPlural
  4753. },
  4754. meridiemParse: /ночи|утра|дня|вечера/i,
  4755. isPM : function (input) {
  4756. return /^(дня|вечера)$/.test(input);
  4757. },
  4758. meridiem : function (hour, minute, isLower) {
  4759. if (hour < 4) {
  4760. return 'ночи';
  4761. } else if (hour < 12) {
  4762. return 'утра';
  4763. } else if (hour < 17) {
  4764. return 'дня';
  4765. } else {
  4766. return 'вечера';
  4767. }
  4768. },
  4769. dayOfMonthOrdinalParse: /\d{1,2}-(й|го|я)/,
  4770. ordinal: function (number, period) {
  4771. switch (period) {
  4772. case 'M':
  4773. case 'd':
  4774. case 'DDD':
  4775. return number + '-й';
  4776. case 'D':
  4777. return number + '-го';
  4778. case 'w':
  4779. case 'W':
  4780. return number + '-я';
  4781. default:
  4782. return number;
  4783. }
  4784. },
  4785. week : {
  4786. dow : 1, // Monday is the first day of the week.
  4787. doy : 4 // The week that contains Jan 4th is the first week of the year.
  4788. }
  4789. });
  4790. return ru;
  4791. })));
  4792. //! moment.js locale configuration
  4793. //! locale : Turkish [tr]
  4794. //! authors : Erhan Gundogan : https://github.com/erhangundogan,
  4795. //! Burak Yiğit Kaya: https://github.com/BYK
  4796. ;(function (global, factory) {
  4797. typeof exports === 'object' && typeof module !== 'undefined'
  4798. && typeof require === 'function' ? factory(require('../moment')) :
  4799. typeof define === 'function' && define.amd ? define('moment/locale/tr',['../moment'], factory) :
  4800. factory(global.moment)
  4801. }(this, (function (moment) { 'use strict';
  4802. var suffixes = {
  4803. 1: '\'inci',
  4804. 5: '\'inci',
  4805. 8: '\'inci',
  4806. 70: '\'inci',
  4807. 80: '\'inci',
  4808. 2: '\'nci',
  4809. 7: '\'nci',
  4810. 20: '\'nci',
  4811. 50: '\'nci',
  4812. 3: '\'üncü',
  4813. 4: '\'üncü',
  4814. 100: '\'üncü',
  4815. 6: '\'ncı',
  4816. 9: '\'uncu',
  4817. 10: '\'uncu',
  4818. 30: '\'uncu',
  4819. 60: '\'ıncı',
  4820. 90: '\'ıncı'
  4821. };
  4822. var tr = moment.defineLocale('tr', {
  4823. months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
  4824. monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
  4825. weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
  4826. weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
  4827. weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
  4828. longDateFormat : {
  4829. LT : 'HH:mm',
  4830. LTS : 'HH:mm:ss',
  4831. L : 'DD.MM.YYYY',
  4832. LL : 'D MMMM YYYY',
  4833. LLL : 'D MMMM YYYY HH:mm',
  4834. LLLL : 'dddd, D MMMM YYYY HH:mm'
  4835. },
  4836. calendar : {
  4837. sameDay : '[bugün saat] LT',
  4838. nextDay : '[yarın saat] LT',
  4839. nextWeek : '[gelecek] dddd [saat] LT',
  4840. lastDay : '[dün] LT',
  4841. lastWeek : '[geçen] dddd [saat] LT',
  4842. sameElse : 'L'
  4843. },
  4844. relativeTime : {
  4845. future : '%s sonra',
  4846. past : '%s önce',
  4847. s : 'birkaç saniye',
  4848. m : 'bir dakika',
  4849. mm : '%d dakika',
  4850. h : 'bir saat',
  4851. hh : '%d saat',
  4852. d : 'bir gün',
  4853. dd : '%d gün',
  4854. M : 'bir ay',
  4855. MM : '%d ay',
  4856. y : 'bir yıl',
  4857. yy : '%d yıl'
  4858. },
  4859. dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
  4860. ordinal : function (number) {
  4861. if (number === 0) { // special case for zero
  4862. return number + '\'ıncı';
  4863. }
  4864. var a = number % 10,
  4865. b = number % 100 - a,
  4866. c = number >= 100 ? 100 : null;
  4867. return number + (suffixes[a] || suffixes[b] || suffixes[c]);
  4868. },
  4869. week : {
  4870. dow : 1, // Monday is the first day of the week.
  4871. doy : 7 // The week that contains Jan 1st is the first week of the year.
  4872. }
  4873. });
  4874. return tr;
  4875. })));
  4876. //! moment.js locale configuration
  4877. //! locale : Ukrainian [uk]
  4878. //! author : zemlanin : https://github.com/zemlanin
  4879. //! Author : Menelion Elensúle : https://github.com/Oire
  4880. ;(function (global, factory) {
  4881. typeof exports === 'object' && typeof module !== 'undefined'
  4882. && typeof require === 'function' ? factory(require('../moment')) :
  4883. typeof define === 'function' && define.amd ? define('moment/locale/uk',['../moment'], factory) :
  4884. factory(global.moment)
  4885. }(this, (function (moment) { 'use strict';
  4886. function plural(word, num) {
  4887. var forms = word.split('_');
  4888. return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
  4889. }
  4890. function relativeTimeWithPlural(number, withoutSuffix, key) {
  4891. var format = {
  4892. 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
  4893. 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
  4894. 'dd': 'день_дні_днів',
  4895. 'MM': 'місяць_місяці_місяців',
  4896. 'yy': 'рік_роки_років'
  4897. };
  4898. if (key === 'm') {
  4899. return withoutSuffix ? 'хвилина' : 'хвилину';
  4900. }
  4901. else if (key === 'h') {
  4902. return withoutSuffix ? 'година' : 'годину';
  4903. }
  4904. else {
  4905. return number + ' ' + plural(format[key], +number);
  4906. }
  4907. }
  4908. function weekdaysCaseReplace(m, format) {
  4909. var weekdays = {
  4910. 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
  4911. 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
  4912. 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
  4913. };
  4914. if (!m) {
  4915. return weekdays['nominative'];
  4916. }
  4917. var nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
  4918. 'accusative' :
  4919. ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
  4920. 'genitive' :
  4921. 'nominative');
  4922. return weekdays[nounCase][m.day()];
  4923. }
  4924. function processHoursFunction(str) {
  4925. return function () {
  4926. return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
  4927. };
  4928. }
  4929. var uk = moment.defineLocale('uk', {
  4930. months : {
  4931. 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'),
  4932. 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_')
  4933. },
  4934. monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
  4935. weekdays : weekdaysCaseReplace,
  4936. weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
  4937. weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
  4938. longDateFormat : {
  4939. LT : 'HH:mm',
  4940. LTS : 'HH:mm:ss',
  4941. L : 'DD.MM.YYYY',
  4942. LL : 'D MMMM YYYY р.',
  4943. LLL : 'D MMMM YYYY р., HH:mm',
  4944. LLLL : 'dddd, D MMMM YYYY р., HH:mm'
  4945. },
  4946. calendar : {
  4947. sameDay: processHoursFunction('[Сьогодні '),
  4948. nextDay: processHoursFunction('[Завтра '),
  4949. lastDay: processHoursFunction('[Вчора '),
  4950. nextWeek: processHoursFunction('[У] dddd ['),
  4951. lastWeek: function () {
  4952. switch (this.day()) {
  4953. case 0:
  4954. case 3:
  4955. case 5:
  4956. case 6:
  4957. return processHoursFunction('[Минулої] dddd [').call(this);
  4958. case 1:
  4959. case 2:
  4960. case 4:
  4961. return processHoursFunction('[Минулого] dddd [').call(this);
  4962. }
  4963. },
  4964. sameElse: 'L'
  4965. },
  4966. relativeTime : {
  4967. future : 'за %s',
  4968. past : '%s тому',
  4969. s : 'декілька секунд',
  4970. m : relativeTimeWithPlural,
  4971. mm : relativeTimeWithPlural,
  4972. h : 'годину',
  4973. hh : relativeTimeWithPlural,
  4974. d : 'день',
  4975. dd : relativeTimeWithPlural,
  4976. M : 'місяць',
  4977. MM : relativeTimeWithPlural,
  4978. y : 'рік',
  4979. yy : relativeTimeWithPlural
  4980. },
  4981. // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
  4982. meridiemParse: /ночі|ранку|дня|вечора/,
  4983. isPM: function (input) {
  4984. return /^(дня|вечора)$/.test(input);
  4985. },
  4986. meridiem : function (hour, minute, isLower) {
  4987. if (hour < 4) {
  4988. return 'ночі';
  4989. } else if (hour < 12) {
  4990. return 'ранку';
  4991. } else if (hour < 17) {
  4992. return 'дня';
  4993. } else {
  4994. return 'вечора';
  4995. }
  4996. },
  4997. dayOfMonthOrdinalParse: /\d{1,2}-(й|го)/,
  4998. ordinal: function (number, period) {
  4999. switch (period) {
  5000. case 'M':
  5001. case 'd':
  5002. case 'DDD':
  5003. case 'w':
  5004. case 'W':
  5005. return number + '-й';
  5006. case 'D':
  5007. return number + '-го';
  5008. default:
  5009. return number;
  5010. }
  5011. },
  5012. week : {
  5013. dow : 1, // Monday is the first day of the week.
  5014. doy : 7 // The week that contains Jan 1st is the first week of the year.
  5015. }
  5016. });
  5017. return uk;
  5018. })));
  5019. //! moment.js locale configuration
  5020. //! locale : Chinese (China) [zh-cn]
  5021. //! author : suupic : https://github.com/suupic
  5022. //! author : Zeno Zeng : https://github.com/zenozeng
  5023. ;(function (global, factory) {
  5024. typeof exports === 'object' && typeof module !== 'undefined'
  5025. && typeof require === 'function' ? factory(require('../moment')) :
  5026. typeof define === 'function' && define.amd ? define('moment/locale/zh-cn',['../moment'], factory) :
  5027. factory(global.moment)
  5028. }(this, (function (moment) { 'use strict';
  5029. var zhCn = moment.defineLocale('zh-cn', {
  5030. months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
  5031. monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
  5032. weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
  5033. weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
  5034. weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
  5035. longDateFormat : {
  5036. LT : 'HH:mm',
  5037. LTS : 'HH:mm:ss',
  5038. L : 'YYYY年MMMD日',
  5039. LL : 'YYYY年MMMD日',
  5040. LLL : 'YYYY年MMMD日Ah点mm分',
  5041. LLLL : 'YYYY年MMMD日ddddAh点mm分',
  5042. l : 'YYYY年MMMD日',
  5043. ll : 'YYYY年MMMD日',
  5044. lll : 'YYYY年MMMD日 HH:mm',
  5045. llll : 'YYYY年MMMD日dddd HH:mm'
  5046. },
  5047. meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
  5048. meridiemHour: function (hour, meridiem) {
  5049. if (hour === 12) {
  5050. hour = 0;
  5051. }
  5052. if (meridiem === '凌晨' || meridiem === '早上' ||
  5053. meridiem === '上午') {
  5054. return hour;
  5055. } else if (meridiem === '下午' || meridiem === '晚上') {
  5056. return hour + 12;
  5057. } else {
  5058. // '中午'
  5059. return hour >= 11 ? hour : hour + 12;
  5060. }
  5061. },
  5062. meridiem : function (hour, minute, isLower) {
  5063. var hm = hour * 100 + minute;
  5064. if (hm < 600) {
  5065. return '凌晨';
  5066. } else if (hm < 900) {
  5067. return '早上';
  5068. } else if (hm < 1130) {
  5069. return '上午';
  5070. } else if (hm < 1230) {
  5071. return '中午';
  5072. } else if (hm < 1800) {
  5073. return '下午';
  5074. } else {
  5075. return '晚上';
  5076. }
  5077. },
  5078. calendar : {
  5079. sameDay : '[今天]LT',
  5080. nextDay : '[明天]LT',
  5081. nextWeek : '[下]ddddLT',
  5082. lastDay : '[昨天]LT',
  5083. lastWeek : '[上]ddddLT',
  5084. sameElse : 'L'
  5085. },
  5086. dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
  5087. ordinal : function (number, period) {
  5088. switch (period) {
  5089. case 'd':
  5090. case 'D':
  5091. case 'DDD':
  5092. return number + '日';
  5093. case 'M':
  5094. return number + '月';
  5095. case 'w':
  5096. case 'W':
  5097. return number + '周';
  5098. default:
  5099. return number;
  5100. }
  5101. },
  5102. relativeTime : {
  5103. future : '%s内',
  5104. past : '%s前',
  5105. s : '几秒',
  5106. m : '1 分钟',
  5107. mm : '%d 分钟',
  5108. h : '1 小时',
  5109. hh : '%d 小时',
  5110. d : '1 天',
  5111. dd : '%d 天',
  5112. M : '1 个月',
  5113. MM : '%d 个月',
  5114. y : '1 年',
  5115. yy : '%d 年'
  5116. },
  5117. week : {
  5118. // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
  5119. dow : 1, // Monday is the first day of the week.
  5120. doy : 4 // The week that contains Jan 4th is the first week of the year.
  5121. }
  5122. });
  5123. return zhCn;
  5124. })));
  5125. //! moment.js locale configuration
  5126. //! locale : Chinese (Taiwan) [zh-tw]
  5127. //! author : Ben : https://github.com/ben-lin
  5128. //! author : Chris Lam : https://github.com/hehachris
  5129. ;(function (global, factory) {
  5130. typeof exports === 'object' && typeof module !== 'undefined'
  5131. && typeof require === 'function' ? factory(require('../moment')) :
  5132. typeof define === 'function' && define.amd ? define('moment/locale/zh-tw',['../moment'], factory) :
  5133. factory(global.moment)
  5134. }(this, (function (moment) { 'use strict';
  5135. var zhTw = moment.defineLocale('zh-tw', {
  5136. months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
  5137. monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
  5138. weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
  5139. weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
  5140. weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
  5141. longDateFormat : {
  5142. LT : 'HH:mm',
  5143. LTS : 'HH:mm:ss',
  5144. L : 'YYYY年MMMD日',
  5145. LL : 'YYYY年MMMD日',
  5146. LLL : 'YYYY年MMMD日 HH:mm',
  5147. LLLL : 'YYYY年MMMD日dddd HH:mm',
  5148. l : 'YYYY年MMMD日',
  5149. ll : 'YYYY年MMMD日',
  5150. lll : 'YYYY年MMMD日 HH:mm',
  5151. llll : 'YYYY年MMMD日dddd HH:mm'
  5152. },
  5153. meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
  5154. meridiemHour : function (hour, meridiem) {
  5155. if (hour === 12) {
  5156. hour = 0;
  5157. }
  5158. if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
  5159. return hour;
  5160. } else if (meridiem === '中午') {
  5161. return hour >= 11 ? hour : hour + 12;
  5162. } else if (meridiem === '下午' || meridiem === '晚上') {
  5163. return hour + 12;
  5164. }
  5165. },
  5166. meridiem : function (hour, minute, isLower) {
  5167. var hm = hour * 100 + minute;
  5168. if (hm < 600) {
  5169. return '凌晨';
  5170. } else if (hm < 900) {
  5171. return '早上';
  5172. } else if (hm < 1130) {
  5173. return '上午';
  5174. } else if (hm < 1230) {
  5175. return '中午';
  5176. } else if (hm < 1800) {
  5177. return '下午';
  5178. } else {
  5179. return '晚上';
  5180. }
  5181. },
  5182. calendar : {
  5183. sameDay : '[今天]LT',
  5184. nextDay : '[明天]LT',
  5185. nextWeek : '[下]ddddLT',
  5186. lastDay : '[昨天]LT',
  5187. lastWeek : '[上]ddddLT',
  5188. sameElse : 'L'
  5189. },
  5190. dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
  5191. ordinal : function (number, period) {
  5192. switch (period) {
  5193. case 'd' :
  5194. case 'D' :
  5195. case 'DDD' :
  5196. return number + '日';
  5197. case 'M' :
  5198. return number + '月';
  5199. case 'w' :
  5200. case 'W' :
  5201. return number + '週';
  5202. default :
  5203. return number;
  5204. }
  5205. },
  5206. relativeTime : {
  5207. future : '%s內',
  5208. past : '%s前',
  5209. s : '幾秒',
  5210. m : '1 分鐘',
  5211. mm : '%d 分鐘',
  5212. h : '1 小時',
  5213. hh : '%d 小時',
  5214. d : '1 天',
  5215. dd : '%d 天',
  5216. M : '1 個月',
  5217. MM : '%d 個月',
  5218. y : '1 年',
  5219. yy : '%d 年'
  5220. }
  5221. });
  5222. return zhTw;
  5223. })));
  5224. // Converse.js (A browser based XMPP chat client)
  5225. // http://conversejs.org
  5226. //
  5227. // This is the internationalization module.
  5228. //
  5229. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  5230. // Licensed under the Mozilla Public License (MPLv2)
  5231. //
  5232. /*global define */
  5233. (function (root, factory) {
  5234. define('i18n',["es6-promise", "jed", "lodash.noconflict", "moment", 'moment/locale/af', 'moment/locale/ar', 'moment/locale/bg', 'moment/locale/ca', 'moment/locale/de', 'moment/locale/es', 'moment/locale/fr', 'moment/locale/he', 'moment/locale/hu', 'moment/locale/id', 'moment/locale/it', 'moment/locale/ja', 'moment/locale/nb', 'moment/locale/nl', 'moment/locale/pl', 'moment/locale/pt-br', 'moment/locale/ru', 'moment/locale/tr', 'moment/locale/uk', 'moment/locale/zh-cn', 'moment/locale/zh-tw'], factory);
  5235. })(void 0, function (Promise, Jed, _, moment) {
  5236. 'use strict';
  5237. function detectLocale(library_check) {
  5238. /* Determine which locale is supported by the user's system as well
  5239. * as by the relevant library (e.g. converse.js or moment.js).
  5240. *
  5241. * Parameters:
  5242. * (Function) library_check - Returns a boolean indicating whether
  5243. * the locale is supported.
  5244. */
  5245. var locale, i;
  5246. if (window.navigator.userLanguage) {
  5247. locale = isLocaleAvailable(window.navigator.userLanguage, library_check);
  5248. }
  5249. if (window.navigator.languages && !locale) {
  5250. for (i = 0; i < window.navigator.languages.length && !locale; i++) {
  5251. locale = isLocaleAvailable(window.navigator.languages[i], library_check);
  5252. }
  5253. }
  5254. if (window.navigator.browserLanguage && !locale) {
  5255. locale = isLocaleAvailable(window.navigator.browserLanguage, library_check);
  5256. }
  5257. if (window.navigator.language && !locale) {
  5258. locale = isLocaleAvailable(window.navigator.language, library_check);
  5259. }
  5260. if (window.navigator.systemLanguage && !locale) {
  5261. locale = isLocaleAvailable(window.navigator.systemLanguage, library_check);
  5262. }
  5263. return locale || 'en';
  5264. }
  5265. function isMomentLocale(locale) {
  5266. return _.isString(locale) && moment.locale() === moment.locale(locale);
  5267. }
  5268. function isConverseLocale(locale, supported_locales) {
  5269. return _.isString(locale) && _.includes(supported_locales, locale);
  5270. }
  5271. function getLocale(preferred_locale, isSupportedByLibrary) {
  5272. if (_.isString(preferred_locale)) {
  5273. if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
  5274. return preferred_locale;
  5275. }
  5276. }
  5277. return detectLocale(isSupportedByLibrary) || 'en';
  5278. }
  5279. function isLocaleAvailable(locale, available) {
  5280. /* Check whether the locale or sub locale (e.g. en-US, en) is supported.
  5281. *
  5282. * Parameters:
  5283. * (String) locale - The locale to check for
  5284. * (Function) available - returns a boolean indicating whether the locale is supported
  5285. */
  5286. if (available(locale)) {
  5287. return locale;
  5288. } else {
  5289. var sublocale = locale.split("-")[0];
  5290. if (sublocale !== locale && available(sublocale)) {
  5291. return sublocale;
  5292. }
  5293. }
  5294. }
  5295. var jed_instance;
  5296. return {
  5297. setLocales: function setLocales(preferred_locale, _converse) {
  5298. _converse.locale = getLocale(preferred_locale, _.partial(isConverseLocale, _, _converse.locales));
  5299. moment.locale(getLocale(preferred_locale, isMomentLocale));
  5300. },
  5301. translate: function translate(str) {
  5302. if (_.isNil(jed_instance)) {
  5303. return Jed.sprintf.apply(Jed, arguments);
  5304. }
  5305. var t = jed_instance.translate(str);
  5306. if (arguments.length > 1) {
  5307. return t.fetch.apply(t, [].slice.call(arguments, 1));
  5308. } else {
  5309. return t.fetch();
  5310. }
  5311. },
  5312. fetchTranslations: function fetchTranslations(locale, supported_locales, locale_url) {
  5313. /* Fetch the translations for the given local at the given URL.
  5314. *
  5315. * Parameters:
  5316. * (String) locale: The given i18n locale
  5317. * (Array) supported_locales: List of locales supported
  5318. * (String) locale_url: The URL from which the translations
  5319. * should be fetched.
  5320. */
  5321. return new Promise(function (resolve, reject) {
  5322. if (!isConverseLocale(locale, supported_locales) || locale === 'en') {
  5323. return resolve();
  5324. }
  5325. var xhr = new XMLHttpRequest();
  5326. xhr.open('GET', locale_url, true);
  5327. xhr.setRequestHeader('Accept', "application/json, text/javascript");
  5328. xhr.onload = function () {
  5329. if (xhr.status >= 200 && xhr.status < 400) {
  5330. jed_instance = new Jed(window.JSON.parse(xhr.responseText));
  5331. resolve();
  5332. } else {
  5333. xhr.onerror();
  5334. }
  5335. };
  5336. xhr.onerror = function () {
  5337. reject(xhr.statusText);
  5338. };
  5339. xhr.send();
  5340. });
  5341. }
  5342. };
  5343. });
  5344. //# sourceMappingURL=i18n.js.map;
  5345. function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  5346. // Converse.js (A browser based XMPP chat client)
  5347. // http://conversejs.org
  5348. //
  5349. // This is the utilities module.
  5350. //
  5351. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  5352. // Licensed under the Mozilla Public License (MPLv2)
  5353. //
  5354. /*global define, escape, window */
  5355. (function (root, factory) {
  5356. define('utils',["sizzle", "es6-promise", "lodash.noconflict", "strophe"], factory);
  5357. })(void 0, function (sizzle, Promise, _, Strophe) {
  5358. "use strict";
  5359. var b64_sha1 = Strophe.SHA1.b64_sha1;
  5360. Strophe = Strophe.Strophe;
  5361. var URL_REGEX = /\b(https?:\/\/|www\.|https?:\/\/www\.)[^\s<>]{2,200}\b\/?/g;
  5362. var logger = _.assign({
  5363. 'debug': _.get(console, 'log') ? console.log.bind(console) : _.noop,
  5364. 'error': _.get(console, 'log') ? console.log.bind(console) : _.noop,
  5365. 'info': _.get(console, 'log') ? console.log.bind(console) : _.noop,
  5366. 'warn': _.get(console, 'log') ? console.log.bind(console) : _.noop
  5367. }, console);
  5368. var unescapeHTML = function unescapeHTML(htmlEscapedText) {
  5369. /* Helper method that replace HTML-escaped symbols with equivalent characters
  5370. * (e.g. transform occurrences of '&amp;' to '&')
  5371. *
  5372. * Parameters:
  5373. * (String) htmlEscapedText: a String containing the HTML-escaped symbols.
  5374. */
  5375. var div = document.createElement('div');
  5376. div.innerHTML = htmlEscapedText;
  5377. return div.innerText;
  5378. };
  5379. var isImage = function isImage(url) {
  5380. return new Promise(function (resolve, reject) {
  5381. var img = new Image();
  5382. var timer = window.setTimeout(function () {
  5383. reject(new Error("Could not determine whether it's an image"));
  5384. img = null;
  5385. }, 3000);
  5386. img.onerror = img.onabort = function () {
  5387. clearTimeout(timer);
  5388. reject(new Error("Could not determine whether it's an image"));
  5389. };
  5390. img.onload = function () {
  5391. clearTimeout(timer);
  5392. resolve(img);
  5393. };
  5394. img.src = url;
  5395. });
  5396. };
  5397. function slideOutWrapup(el) {
  5398. /* Wrapup function for slideOut. */
  5399. el.removeAttribute('data-slider-marker');
  5400. el.classList.remove('collapsed');
  5401. el.style.overflow = "";
  5402. el.style.height = "";
  5403. }
  5404. var u = {};
  5405. u.getNextElement = function (el) {
  5406. var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
  5407. var next_el = el.nextElementSibling;
  5408. while (!_.isNull(next_el) && !sizzle.matchesSelector(next_el, selector)) {
  5409. next_el = next_el.nextElementSibling;
  5410. }
  5411. return next_el;
  5412. };
  5413. u.getPreviousElement = function (el) {
  5414. var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
  5415. var prev_el = el.previousSibling;
  5416. while (!_.isNull(prev_el) && !sizzle.matchesSelector(prev_el, selector)) {
  5417. prev_el = prev_el.previousSibling;
  5418. }
  5419. return prev_el;
  5420. };
  5421. u.getFirstChildElement = function (el) {
  5422. var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
  5423. var first_el = el.firstElementChild;
  5424. while (!_.isNull(first_el) && !sizzle.matchesSelector(first_el, selector)) {
  5425. first_el = first_el.nextSibling;
  5426. }
  5427. return first_el;
  5428. };
  5429. u.getLastChildElement = function (el) {
  5430. var selector = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '*';
  5431. var last_el = el.lastElementChild;
  5432. while (!_.isNull(last_el) && !sizzle.matchesSelector(last_el, selector)) {
  5433. last_el = last_el.previousSibling;
  5434. }
  5435. return last_el;
  5436. };
  5437. u.calculateElementHeight = function (el) {
  5438. /* Return the height of the passed in DOM element,
  5439. * based on the heights of its children.
  5440. */
  5441. return _.reduce(el.children, function (result, child) {
  5442. return result + child.offsetHeight;
  5443. }, 0);
  5444. };
  5445. u.addClass = function (className, el) {
  5446. if (el instanceof Element) {
  5447. el.classList.add(className);
  5448. }
  5449. };
  5450. u.removeClass = function (className, el) {
  5451. if (el instanceof Element) {
  5452. el.classList.remove(className);
  5453. }
  5454. return el;
  5455. };
  5456. u.removeElement = function (el) {
  5457. if (!_.isNil(el) && !_.isNil(el.parentNode)) {
  5458. el.parentNode.removeChild(el);
  5459. }
  5460. };
  5461. u.showElement = _.flow(_.partial(u.removeClass, 'collapsed'), _.partial(u.removeClass, 'hidden'));
  5462. u.hideElement = function (el) {
  5463. if (!_.isNil(el)) {
  5464. el.classList.add('hidden');
  5465. }
  5466. return el;
  5467. };
  5468. u.ancestor = function (el, selector) {
  5469. var parent = el;
  5470. while (!_.isNil(parent) && !sizzle.matchesSelector(parent, selector)) {
  5471. parent = parent.parentElement;
  5472. }
  5473. return parent;
  5474. };
  5475. u.nextUntil = function (el, selector) {
  5476. var include_self = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  5477. /* Return the element's siblings until one matches the selector. */
  5478. var matches = [];
  5479. var sibling_el = el.nextElementSibling;
  5480. while (!_.isNil(sibling_el) && !sibling_el.matches(selector)) {
  5481. matches.push(sibling_el);
  5482. sibling_el = sibling_el.nextElementSibling;
  5483. }
  5484. return matches;
  5485. };
  5486. u.addHyperlinks = function (text) {
  5487. var list = text.match(URL_REGEX) || [];
  5488. var links = [];
  5489. _.each(list, function (match) {
  5490. var prot = match.indexOf('http://') === 0 || match.indexOf('https://') === 0 ? '' : 'http://';
  5491. var url = prot + encodeURI(decodeURI(match)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
  5492. var a = '<a target="_blank" rel="noopener" href="' + url + '">' + _.escape(match) + '</a>'; // We first insert a hash of the code that will be inserted, and
  5493. // then later replace that with the code itself. That way we avoid
  5494. // issues when some matches are substrings of others.
  5495. links.push(a);
  5496. text = text.replace(match, b64_sha1(a));
  5497. });
  5498. while (links.length) {
  5499. var a = links.pop();
  5500. text = text.replace(b64_sha1(a), a);
  5501. }
  5502. return text;
  5503. };
  5504. u.renderImageURLs = function (obj) {
  5505. /* Returns a Promise which resolves once all images have been loaded.
  5506. */
  5507. var list = obj.textContent.match(URL_REGEX) || [];
  5508. return Promise.all(_.map(list, function (url) {
  5509. return new Promise(function (resolve, reject) {
  5510. return isImage(url).then(function (img) {
  5511. // XXX: need to create a new image, otherwise the event
  5512. // listener doesn't fire
  5513. var i = new Image();
  5514. i.className = 'chat-image';
  5515. i.src = img.src;
  5516. i.addEventListener('load', resolve); // We also resolve for non-images, otherwise the
  5517. // Promise.all resolves prematurely.
  5518. i.addEventListener('error', resolve);
  5519. var anchors = sizzle("a[href=\"".concat(url, "\"]"), obj);
  5520. _.each(anchors, function (a) {
  5521. a.replaceChild(i, a.firstChild);
  5522. });
  5523. }).catch(resolve);
  5524. });
  5525. }));
  5526. };
  5527. u.slideInAllElements = function (elements) {
  5528. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300;
  5529. return Promise.all(_.map(elements, _.partial(u.slideIn, _, duration)));
  5530. };
  5531. u.slideToggleElement = function (el, duration) {
  5532. if (_.includes(el.classList, 'collapsed') || _.includes(el.classList, 'hidden')) {
  5533. return u.slideOut(el, duration);
  5534. } else {
  5535. return u.slideIn(el, duration);
  5536. }
  5537. };
  5538. u.hasClass = function (className, el) {
  5539. return _.includes(el.classList, className);
  5540. };
  5541. u.slideOut = function (el) {
  5542. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
  5543. /* Shows/expands an element by sliding it out of itself
  5544. *
  5545. * Parameters:
  5546. * (HTMLElement) el - The HTML string
  5547. * (Number) duration - The duration amount in milliseconds
  5548. */
  5549. return new Promise(function (resolve, reject) {
  5550. if (_.isNil(el)) {
  5551. var err = "Undefined or null element passed into slideOut";
  5552. logger.warn(err);
  5553. reject(new Error(err));
  5554. return;
  5555. }
  5556. var marker = el.getAttribute('data-slider-marker');
  5557. if (marker) {
  5558. el.removeAttribute('data-slider-marker');
  5559. window.cancelAnimationFrame(marker);
  5560. }
  5561. var end_height = u.calculateElementHeight(el);
  5562. if (window.converse_disable_effects) {
  5563. // Effects are disabled (for tests)
  5564. el.style.height = end_height + 'px';
  5565. slideOutWrapup(el);
  5566. resolve();
  5567. return;
  5568. }
  5569. if (!u.hasClass('collapsed', el) && !u.hasClass('hidden', el)) {
  5570. resolve();
  5571. return;
  5572. }
  5573. var steps = duration / 17; // We assume 17ms per animation which is ~60FPS
  5574. var height = 0;
  5575. function draw() {
  5576. height += end_height / steps;
  5577. if (height < end_height) {
  5578. el.style.height = height + 'px';
  5579. el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw));
  5580. } else {
  5581. // We recalculate the height to work around an apparent
  5582. // browser bug where browsers don't know the correct
  5583. // offsetHeight beforehand.
  5584. el.removeAttribute('data-slider-marker');
  5585. el.style.height = u.calculateElementHeight(el) + 'px';
  5586. el.style.overflow = "";
  5587. el.style.height = "";
  5588. resolve();
  5589. }
  5590. }
  5591. el.style.height = '0';
  5592. el.style.overflow = 'hidden';
  5593. el.classList.remove('hidden');
  5594. el.classList.remove('collapsed');
  5595. el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw));
  5596. });
  5597. };
  5598. u.slideIn = function (el) {
  5599. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
  5600. /* Hides/collapses an element by sliding it into itself. */
  5601. return new Promise(function (resolve, reject) {
  5602. if (_.isNil(el)) {
  5603. var err = "Undefined or null element passed into slideIn";
  5604. logger.warn(err);
  5605. return reject(new Error(err));
  5606. } else if (_.includes(el.classList, 'collapsed')) {
  5607. return resolve(el);
  5608. } else if (window.converse_disable_effects) {
  5609. // Effects are disabled (for tests)
  5610. el.classList.add('collapsed');
  5611. el.style.height = "";
  5612. return resolve(el);
  5613. }
  5614. var marker = el.getAttribute('data-slider-marker');
  5615. if (marker) {
  5616. el.removeAttribute('data-slider-marker');
  5617. window.cancelAnimationFrame(marker);
  5618. }
  5619. var original_height = el.offsetHeight,
  5620. steps = duration / 17; // We assume 17ms per animation which is ~60FPS
  5621. var height = original_height;
  5622. el.style.overflow = 'hidden';
  5623. function draw() {
  5624. height -= original_height / steps;
  5625. if (height > 0) {
  5626. el.style.height = height + 'px';
  5627. el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw));
  5628. } else {
  5629. el.removeAttribute('data-slider-marker');
  5630. el.classList.add('collapsed');
  5631. el.style.height = "";
  5632. resolve(el);
  5633. }
  5634. }
  5635. el.setAttribute('data-slider-marker', window.requestAnimationFrame(draw));
  5636. });
  5637. };
  5638. function afterAnimationEnds(el, callback) {
  5639. el.classList.remove('visible');
  5640. if (_.isFunction(callback)) {
  5641. callback();
  5642. }
  5643. }
  5644. u.fadeIn = function (el, callback) {
  5645. if (_.isNil(el)) {
  5646. logger.warn("Undefined or null element passed into fadeIn");
  5647. }
  5648. if (window.converse_disable_effects) {
  5649. el.classList.remove('hidden');
  5650. return afterAnimationEnds(el, callback);
  5651. }
  5652. if (_.includes(el.classList, 'hidden')) {
  5653. el.classList.add('visible');
  5654. el.classList.remove('hidden');
  5655. el.addEventListener("webkitAnimationEnd", _.partial(afterAnimationEnds, el, callback));
  5656. el.addEventListener("animationend", _.partial(afterAnimationEnds, el, callback));
  5657. el.addEventListener("oanimationend", _.partial(afterAnimationEnds, el, callback));
  5658. } else {
  5659. afterAnimationEnds(el, callback);
  5660. }
  5661. };
  5662. u.isValidJID = function (jid) {
  5663. return _.compact(jid.split('@')).length === 2 && !jid.startsWith('@') && !jid.endsWith('@');
  5664. };
  5665. u.isValidMUCJID = function (jid) {
  5666. return !jid.startsWith('@') && !jid.endsWith('@');
  5667. };
  5668. u.isSameBareJID = function (jid1, jid2) {
  5669. return Strophe.getBareJidFromJid(jid1).toLowerCase() === Strophe.getBareJidFromJid(jid2).toLowerCase();
  5670. };
  5671. u.getMostRecentMessage = function (model) {
  5672. var messages = model.messages.filter('message');
  5673. return messages[messages.length - 1];
  5674. };
  5675. u.isNewMessage = function (message) {
  5676. /* Given a stanza, determine whether it's a new
  5677. * message, i.e. not a MAM archived one.
  5678. */
  5679. if (message instanceof Element) {
  5680. return !sizzle('result[xmlns="' + Strophe.NS.MAM + '"]', message).length && !sizzle('delay[xmlns="' + Strophe.NS.DELAY + '"]', message).length;
  5681. } else {
  5682. return !message.get('delayed');
  5683. }
  5684. };
  5685. u.isOTRMessage = function (message) {
  5686. var body = message.querySelector('body'),
  5687. text = !_.isNull(body) ? body.textContent : undefined;
  5688. return text && !!text.match(/^\?OTR/);
  5689. };
  5690. u.isHeadlineMessage = function (_converse, message) {
  5691. var from_jid = message.getAttribute('from');
  5692. if (message.getAttribute('type') === 'headline') {
  5693. return true;
  5694. }
  5695. var chatbox = _converse.chatboxes.get(Strophe.getBareJidFromJid(from_jid));
  5696. if (chatbox && chatbox.get('type') === 'chatroom') {
  5697. return false;
  5698. }
  5699. if (message.getAttribute('type') !== 'error' && !_.isNil(from_jid) && !_.includes(from_jid, '@')) {
  5700. // Some servers (I'm looking at you Prosody) don't set the message
  5701. // type to "headline" when sending server messages. For now we
  5702. // check if an @ signal is included, and if not, we assume it's
  5703. // a headline message.
  5704. return true;
  5705. }
  5706. return false;
  5707. };
  5708. u.merge = function merge(first, second) {
  5709. /* Merge the second object into the first one.
  5710. */
  5711. for (var k in second) {
  5712. if (_.isObject(first[k])) {
  5713. merge(first[k], second[k]);
  5714. } else {
  5715. first[k] = second[k];
  5716. }
  5717. }
  5718. };
  5719. u.applyUserSettings = function applyUserSettings(context, settings, user_settings) {
  5720. /* Configuration settings might be nested objects. We only want to
  5721. * add settings which are whitelisted.
  5722. */
  5723. for (var k in settings) {
  5724. if (_.isUndefined(user_settings[k])) {
  5725. continue;
  5726. }
  5727. if (_.isObject(settings[k]) && !_.isArray(settings[k])) {
  5728. applyUserSettings(context[k], settings[k], user_settings[k]);
  5729. } else {
  5730. context[k] = user_settings[k];
  5731. }
  5732. }
  5733. };
  5734. u.stringToNode = function (s) {
  5735. /* Converts an HTML string into a DOM Node.
  5736. * Expects that the HTML string has only one top-level element,
  5737. * i.e. not multiple ones.
  5738. *
  5739. * Parameters:
  5740. * (String) s - The HTML string
  5741. */
  5742. var div = document.createElement('div');
  5743. div.innerHTML = s;
  5744. return div.firstChild;
  5745. };
  5746. u.getOuterWidth = function (el) {
  5747. var include_margin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  5748. var width = el.offsetWidth;
  5749. if (!include_margin) {
  5750. return width;
  5751. }
  5752. var style = window.getComputedStyle(el);
  5753. width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10);
  5754. return width;
  5755. };
  5756. u.stringToElement = function (s) {
  5757. /* Converts an HTML string into a DOM element.
  5758. * Expects that the HTML string has only one top-level element,
  5759. * i.e. not multiple ones.
  5760. *
  5761. * Parameters:
  5762. * (String) s - The HTML string
  5763. */
  5764. var div = document.createElement('div');
  5765. div.innerHTML = s;
  5766. return div.firstElementChild;
  5767. };
  5768. u.matchesSelector = function (el, selector) {
  5769. /* Checks whether the DOM element matches the given selector.
  5770. *
  5771. * Parameters:
  5772. * (DOMElement) el - The DOM element
  5773. * (String) selector - The selector
  5774. */
  5775. return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
  5776. };
  5777. u.queryChildren = function (el, selector) {
  5778. /* Returns a list of children of the DOM element that match the
  5779. * selector.
  5780. *
  5781. * Parameters:
  5782. * (DOMElement) el - the DOM element
  5783. * (String) selector - the selector they should be matched
  5784. * against.
  5785. */
  5786. return _.filter(el.children, _.partial(u.matchesSelector, _, selector));
  5787. };
  5788. u.contains = function (attr, query) {
  5789. return function (item) {
  5790. if (_typeof(attr) === 'object') {
  5791. var value = false;
  5792. _.forEach(attr, function (a) {
  5793. value = value || _.includes(item.get(a).toLowerCase(), query.toLowerCase());
  5794. });
  5795. return value;
  5796. } else if (typeof attr === 'string') {
  5797. return _.includes(item.get(attr).toLowerCase(), query.toLowerCase());
  5798. } else {
  5799. throw new TypeError('contains: wrong attribute type. Must be string or array.');
  5800. }
  5801. };
  5802. };
  5803. u.isOfType = function (type, item) {
  5804. return item.get('type') == type;
  5805. };
  5806. u.isInstance = function (type, item) {
  5807. return item instanceof type;
  5808. };
  5809. u.getAttribute = function (key, item) {
  5810. return item.get(key);
  5811. };
  5812. u.contains.not = function (attr, query) {
  5813. return function (item) {
  5814. return !u.contains(attr, query)(item);
  5815. };
  5816. };
  5817. u.createFragmentFromText = function (markup) {
  5818. /* Returns a DocumentFragment containing DOM nodes based on the
  5819. * passed-in markup text.
  5820. */
  5821. // http://stackoverflow.com/questions/9334645/create-node-from-markup-string
  5822. var frag = document.createDocumentFragment(),
  5823. tmp = document.createElement('body'),
  5824. child;
  5825. tmp.innerHTML = markup; // Append elements in a loop to a DocumentFragment, so that the
  5826. // browser does not re-render the document for each node.
  5827. while (child = tmp.firstChild) {
  5828. // eslint-disable-line no-cond-assign
  5829. frag.appendChild(child);
  5830. }
  5831. return frag;
  5832. };
  5833. u.addEmoji = function (_converse, emojione, text) {
  5834. if (_converse.use_emojione) {
  5835. return emojione.toImage(text);
  5836. } else {
  5837. return emojione.shortnameToUnicode(text);
  5838. }
  5839. };
  5840. u.getEmojisByCategory = function (_converse, emojione) {
  5841. /* Return a dict of emojis with the categories as keys and
  5842. * lists of emojis in that category as values.
  5843. */
  5844. if (_.isUndefined(_converse.emojis_by_category)) {
  5845. var emojis = _.values(_.mapValues(emojione.emojioneList, function (value, key, o) {
  5846. value._shortname = key;
  5847. return value;
  5848. }));
  5849. var tones = [':tone1:', ':tone2:', ':tone3:', ':tone4:', ':tone5:'];
  5850. var excluded = [':kiss_ww:', ':kiss_mm:', ':kiss_woman_man:'];
  5851. var excluded_substrings = [':woman', ':man', ':women_', ':men_', '_man_', '_woman_', '_woman:', '_man:'];
  5852. var excluded_categories = ['modifier', 'regional'];
  5853. var categories = _.difference(_.uniq(_.map(emojis, _.partial(_.get, _, 'category'))), excluded_categories);
  5854. var emojis_by_category = {};
  5855. _.forEach(categories, function (cat) {
  5856. var list = _.sortBy(_.filter(emojis, ['category', cat]), ['uc_base']);
  5857. list = _.filter(list, function (item) {
  5858. return !_.includes(_.concat(tones, excluded), item._shortname) && !_.some(excluded_substrings, _.partial(_.includes, item._shortname));
  5859. });
  5860. if (cat === 'people') {
  5861. var idx = _.findIndex(list, ['uc_base', '1f600']);
  5862. list = _.union(_.slice(list, idx), _.slice(list, 0, idx + 1));
  5863. } else if (cat === 'activity') {
  5864. list = _.union(_.slice(list, 27 - 1), _.slice(list, 0, 27));
  5865. } else if (cat === 'objects') {
  5866. list = _.union(_.slice(list, 24 - 1), _.slice(list, 0, 24));
  5867. } else if (cat === 'travel') {
  5868. list = _.union(_.slice(list, 17 - 1), _.slice(list, 0, 17));
  5869. } else if (cat === 'symbols') {
  5870. list = _.union(_.slice(list, 60 - 1), _.slice(list, 0, 60));
  5871. }
  5872. emojis_by_category[cat] = list;
  5873. });
  5874. _converse.emojis_by_category = emojis_by_category;
  5875. }
  5876. return _converse.emojis_by_category;
  5877. };
  5878. u.getTonedEmojis = function (_converse) {
  5879. _converse.toned_emojis = _.uniq(_.map(_.filter(u.getEmojisByCategory(_converse).people, function (person) {
  5880. return _.includes(person._shortname, '_tone');
  5881. }), function (person) {
  5882. return person._shortname.replace(/_tone[1-5]/, '');
  5883. }));
  5884. return _converse.toned_emojis;
  5885. };
  5886. u.isPersistableModel = function (model) {
  5887. return model.collection && model.collection.browserStorage;
  5888. };
  5889. u.getResolveablePromise = function () {
  5890. /* Returns a promise object on which `resolve` or `reject` can be
  5891. * called.
  5892. */
  5893. var wrapper = {};
  5894. var promise = new Promise(function (resolve, reject) {
  5895. wrapper.resolve = resolve;
  5896. wrapper.reject = reject;
  5897. });
  5898. _.assign(promise, wrapper);
  5899. return promise;
  5900. };
  5901. u.interpolate = function (string, o) {
  5902. return string.replace(/{{{([^{}]*)}}}/g, function (a, b) {
  5903. var r = o[b];
  5904. return typeof r === 'string' || typeof r === 'number' ? r : a;
  5905. });
  5906. };
  5907. u.onMultipleEvents = function () {
  5908. var events = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  5909. var callback = arguments.length > 1 ? arguments[1] : undefined;
  5910. /* Call the callback once all the events have been triggered
  5911. *
  5912. * Parameters:
  5913. * (Array) events: An array of objects, with keys `object` and
  5914. * `event`, representing the event name and the object it's
  5915. * triggered upon.
  5916. * (Function) callback: The function to call once all events have
  5917. * been triggered.
  5918. */
  5919. var triggered = [];
  5920. function handler(result) {
  5921. triggered.push(result);
  5922. if (events.length === triggered.length) {
  5923. callback(triggered);
  5924. triggered = [];
  5925. }
  5926. }
  5927. _.each(events, function (map) {
  5928. return map.object.on(map.event, handler);
  5929. });
  5930. };
  5931. u.safeSave = function (model, attributes) {
  5932. if (u.isPersistableModel(model)) {
  5933. model.save(attributes);
  5934. } else {
  5935. model.set(attributes);
  5936. }
  5937. };
  5938. u.isVisible = function (el) {
  5939. if (u.hasClass('hidden', el)) {
  5940. return false;
  5941. } // XXX: Taken from jQuery's "visible" implementation
  5942. return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
  5943. };
  5944. u.triggerEvent = function (el, name) {
  5945. var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "Event";
  5946. var bubbles = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
  5947. var cancelable = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
  5948. var evt = document.createEvent(type);
  5949. evt.initEvent(name, bubbles, cancelable);
  5950. el.dispatchEvent(evt);
  5951. };
  5952. return u;
  5953. });
  5954. //# sourceMappingURL=utils.js.map;
  5955. (function (global, factory) {
  5956. if (typeof define === "function" && define.amd) {
  5957. define('pluggable',['exports', 'lodash'], factory);
  5958. } else if (typeof exports !== "undefined") {
  5959. factory(exports, require('lodash'));
  5960. } else {
  5961. var mod = {
  5962. exports: {}
  5963. };
  5964. factory(mod.exports, global._);
  5965. global.pluggable = mod.exports;
  5966. }
  5967. })(this, function (exports, _lodash) {
  5968. 'use strict';
  5969. Object.defineProperty(exports, "__esModule", {
  5970. value: true
  5971. });
  5972. exports.enable = undefined;
  5973. var _ = _interopRequireWildcard(_lodash);
  5974. function _interopRequireWildcard(obj) {
  5975. if (obj && obj.__esModule) {
  5976. return obj;
  5977. } else {
  5978. var newObj = {};
  5979. if (obj != null) {
  5980. for (var key in obj) {
  5981. if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
  5982. }
  5983. }
  5984. newObj.default = obj;
  5985. return newObj;
  5986. }
  5987. }
  5988. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  5989. return typeof obj;
  5990. } : function (obj) {
  5991. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  5992. };
  5993. // The `PluginSocket` class contains the plugin architecture, and gets
  5994. // created whenever `pluggable.enable(obj);` is called on the object
  5995. // that you want to make pluggable.
  5996. // You can also see it as the thing into which the plugins are plugged.
  5997. // It takes two parameters, first, the object being made pluggable, and
  5998. // then the name by which the pluggable object may be referenced on the
  5999. // __super__ object (inside overrides).
  6000. function PluginSocket(plugged, name) {
  6001. this.name = name;
  6002. this.plugged = plugged;
  6003. if (typeof this.plugged.__super__ === 'undefined') {
  6004. this.plugged.__super__ = {};
  6005. } else if (typeof this.plugged.__super__ === 'string') {
  6006. this.plugged.__super__ = { '__string__': this.plugged.__super__ };
  6007. }
  6008. this.plugged.__super__[name] = this.plugged;
  6009. this.plugins = {};
  6010. this.initialized_plugins = [];
  6011. }
  6012. // Now we add methods to the PluginSocket by adding them to its
  6013. // prototype.
  6014. _.extend(PluginSocket.prototype, {
  6015. // `wrappedOverride` creates a partially applied wrapper function
  6016. // that makes sure to set the proper super method when the
  6017. // overriding method is called. This is done to enable
  6018. // chaining of plugin methods, all the way up to the
  6019. // original method.
  6020. wrappedOverride: function wrappedOverride(key, value, super_method, default_super) {
  6021. if (typeof super_method === "function") {
  6022. if (typeof this.__super__ === "undefined") {
  6023. /* We're not on the context of the plugged object.
  6024. * This can happen when the overridden method is called via
  6025. * an event handler or when it's a constructor.
  6026. *
  6027. * In this case, we simply tack on the __super__ obj.
  6028. */
  6029. this.__super__ = default_super;
  6030. }
  6031. this.__super__[key] = super_method.bind(this);
  6032. }
  6033. return value.apply(this, _.drop(arguments, 4));
  6034. },
  6035. // `_overrideAttribute` overrides an attribute on the original object
  6036. // (the thing being plugged into).
  6037. //
  6038. // If the attribute being overridden is a function, then the original
  6039. // function will still be available via the `__super__` attribute.
  6040. //
  6041. // If the same function is being overridden multiple times, then
  6042. // the original function will be available at the end of a chain of
  6043. // functions, starting from the most recent override, all the way
  6044. // back to the original function, each being referenced by the
  6045. // previous' __super__ attribute.
  6046. //
  6047. // For example:
  6048. //
  6049. // `plugin2.MyFunc.__super__.myFunc => plugin1.MyFunc.__super__.myFunc => original.myFunc`
  6050. _overrideAttribute: function _overrideAttribute(key, plugin) {
  6051. var value = plugin.overrides[key];
  6052. if (typeof value === "function") {
  6053. var default_super = {};
  6054. default_super[this.name] = this.plugged;
  6055. var wrapped_function = _.partial(this.wrappedOverride, key, value, this.plugged[key], default_super);
  6056. this.plugged[key] = wrapped_function;
  6057. } else {
  6058. this.plugged[key] = value;
  6059. }
  6060. },
  6061. _extendObject: function _extendObject(obj, attributes) {
  6062. if (!obj.prototype.__super__) {
  6063. obj.prototype.__super__ = {};
  6064. obj.prototype.__super__[this.name] = this.plugged;
  6065. }
  6066. var that = this;
  6067. _.each(attributes, function (value, key) {
  6068. if (key === 'events') {
  6069. obj.prototype[key] = _.extend(value, obj.prototype[key]);
  6070. } else if (typeof value === 'function') {
  6071. // We create a partially applied wrapper function, that
  6072. // makes sure to set the proper super method when the
  6073. // overriding method is called. This is done to enable
  6074. // chaining of plugin methods, all the way up to the
  6075. // original method.
  6076. var default_super = {};
  6077. default_super[that.name] = that.plugged;
  6078. var wrapped_function = _.partial(that.wrappedOverride, key, value, obj.prototype[key], default_super);
  6079. obj.prototype[key] = wrapped_function;
  6080. } else {
  6081. obj.prototype[key] = value;
  6082. }
  6083. });
  6084. },
  6085. // Plugins can specify dependencies (by means of the
  6086. // `dependencies` list attribute) which refers to dependencies
  6087. // which will be initialized first, before the plugin itself gets initialized.
  6088. //
  6089. // If `strict_plugin_dependencies` is set to `false` (on the object being
  6090. // made pluggable), then no error will be thrown if any of these plugins aren't
  6091. // available.
  6092. loadPluginDependencies: function loadPluginDependencies(plugin) {
  6093. var _this = this;
  6094. _.each(plugin.dependencies, function (name) {
  6095. var dep = _this.plugins[name];
  6096. if (dep) {
  6097. if (_.includes(dep.dependencies, plugin.__name__)) {
  6098. /* FIXME: circular dependency checking is only one level deep. */
  6099. throw "Found a circular dependency between the plugins \"" + plugin.__name__ + "\" and \"" + name + "\"";
  6100. }
  6101. _this.initializePlugin(dep);
  6102. } else {
  6103. _this.throwUndefinedDependencyError("Could not find dependency \"" + name + "\" " + "for the plugin \"" + plugin.__name__ + "\". " + "If it's needed, make sure it's loaded by require.js");
  6104. }
  6105. });
  6106. },
  6107. throwUndefinedDependencyError: function throwUndefinedDependencyError(msg) {
  6108. if (this.plugged.strict_plugin_dependencies) {
  6109. throw msg;
  6110. } else {
  6111. console.log(msg);
  6112. return;
  6113. }
  6114. },
  6115. // `applyOverrides` is called by initializePlugin. It applies any
  6116. // and all overrides of methods or Backbone views and models that
  6117. // are defined on any of the plugins.
  6118. applyOverrides: function applyOverrides(plugin) {
  6119. var _this2 = this;
  6120. _.each(Object.keys(plugin.overrides || {}), function (key) {
  6121. var override = plugin.overrides[key];
  6122. if ((typeof override === 'undefined' ? 'undefined' : _typeof(override)) === "object") {
  6123. if (typeof _this2.plugged[key] === 'undefined') {
  6124. _this2.throwUndefinedDependencyError("Error: Plugin \"" + plugin.__name__ + "\" tried to override " + key + " but it's not found.");
  6125. } else {
  6126. _this2._extendObject(_this2.plugged[key], override);
  6127. }
  6128. } else {
  6129. _this2._overrideAttribute(key, plugin);
  6130. }
  6131. });
  6132. },
  6133. // `initializePlugin` applies the overrides (if any) defined on all
  6134. // the registered plugins and then calls the initialize method of the plugin
  6135. initializePlugin: function initializePlugin(plugin) {
  6136. if (!_.includes(_.keys(this.allowed_plugins), plugin.__name__)) {
  6137. /* Don't initialize disallowed plugins. */
  6138. return;
  6139. }
  6140. if (_.includes(this.initialized_plugins, plugin.__name__)) {
  6141. /* Don't initialize plugins twice, otherwise we get
  6142. * infinite recursion in overridden methods.
  6143. */
  6144. return;
  6145. }
  6146. if (_.isBoolean(plugin.enabled) && plugin.enabled || _.isFunction(plugin.enabled) && plugin.enabled(this.plugged) || _.isNil(plugin.enabled)) {
  6147. _.extend(plugin, this.properties);
  6148. if (plugin.dependencies) {
  6149. this.loadPluginDependencies(plugin);
  6150. }
  6151. this.applyOverrides(plugin);
  6152. if (typeof plugin.initialize === "function") {
  6153. plugin.initialize.bind(plugin)(this);
  6154. }
  6155. this.initialized_plugins.push(plugin.__name__);
  6156. }
  6157. },
  6158. // `registerPlugin` registers (or inserts, if you'd like) a plugin,
  6159. // by adding it to the `plugins` map on the PluginSocket instance.
  6160. registerPlugin: function registerPlugin(name, plugin) {
  6161. if (name in this.plugins) {
  6162. throw new Error('Error: Plugin name ' + name + ' is already taken');
  6163. }
  6164. plugin.__name__ = name;
  6165. this.plugins[name] = plugin;
  6166. },
  6167. // `initializePlugins` should get called once all plugins have been
  6168. // registered. It will then iterate through all the plugins, calling
  6169. // `initializePlugin` for each.
  6170. // The passed in properties variable is an object with attributes and methods
  6171. // which will be attached to the plugins.
  6172. initializePlugins: function initializePlugins() {
  6173. var properties = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  6174. var whitelist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  6175. var blacklist = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  6176. if (!_.size(this.plugins)) {
  6177. return;
  6178. }
  6179. this.properties = properties;
  6180. this.allowed_plugins = _.pickBy(this.plugins, function (plugin, key) {
  6181. return (!whitelist.length || whitelist.length && _.includes(whitelist, key)) && !_.includes(blacklist, key);
  6182. });
  6183. _.each(_.values(this.allowed_plugins), this.initializePlugin.bind(this));
  6184. }
  6185. });
  6186. function enable(object, name, attrname) {
  6187. // Call the `enable` method to make an object pluggable
  6188. //
  6189. // It takes three parameters:
  6190. // - `object`: The object that gets made pluggable.
  6191. // - `name`: The string name by which the now pluggable object
  6192. // may be referenced on the __super__ obj (in overrides).
  6193. // The default value is "plugged".
  6194. // - `attrname`: The string name of the attribute on the now
  6195. // pluggable object, which refers to the PluginSocket instance
  6196. // that gets created.
  6197. if (typeof attrname === "undefined") {
  6198. attrname = "pluginSocket";
  6199. }
  6200. if (typeof name === 'undefined') {
  6201. name = 'plugged';
  6202. }
  6203. var ref = {};
  6204. ref[attrname] = new PluginSocket(object, name);
  6205. return _.extend(object, ref);
  6206. }
  6207. exports.enable = enable;
  6208. exports.default = {
  6209. enable: enable
  6210. };
  6211. });
  6212. //# sourceMappingURL=pluggable.js.map;
  6213. // Converse.js (A browser based XMPP chat client)
  6214. // http://conversejs.org
  6215. //
  6216. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  6217. // Licensed under the Mozilla Public License (MPLv2)
  6218. //
  6219. /*global Backbone, define, window, JSON */
  6220. (function (root, factory) {
  6221. define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.fp", "polyfill", "i18n", "utils", "moment", "strophe", "pluggable", "backbone.noconflict", "backbone.nativeview", "backbone.browserStorage"], factory);
  6222. })(void 0, function (sizzle, Promise, _, f, polyfill, i18n, u, moment, Strophe, pluggable, Backbone) {
  6223. /* Cannot use this due to Safari bug.
  6224. * See https://github.com/jcbrand/converse.js/issues/196
  6225. */
  6226. // "use strict";
  6227. // Strophe globals
  6228. var _Strophe = Strophe,
  6229. $build = _Strophe.$build,
  6230. $iq = _Strophe.$iq,
  6231. $msg = _Strophe.$msg,
  6232. $pres = _Strophe.$pres;
  6233. var b64_sha1 = Strophe.SHA1.b64_sha1;
  6234. Strophe = Strophe.Strophe; // Add Strophe Namespaces
  6235. Strophe.addNamespace('CARBONS', 'urn:xmpp:carbons:2');
  6236. Strophe.addNamespace('CHATSTATES', 'http://jabber.org/protocol/chatstates');
  6237. Strophe.addNamespace('CSI', 'urn:xmpp:csi:0');
  6238. Strophe.addNamespace('DELAY', 'urn:xmpp:delay');
  6239. Strophe.addNamespace('FORWARD', 'urn:xmpp:forward:0');
  6240. Strophe.addNamespace('HINTS', 'urn:xmpp:hints');
  6241. Strophe.addNamespace('MAM', 'urn:xmpp:mam:2');
  6242. Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick');
  6243. Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub');
  6244. Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx');
  6245. Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm');
  6246. Strophe.addNamespace('SID', 'urn:xmpp:sid:0');
  6247. Strophe.addNamespace('SPOILER', 'urn:xmpp:spoiler:0');
  6248. Strophe.addNamespace('XFORM', 'jabber:x:data'); // Use Mustache style syntax for variable interpolation
  6249. /* Configuration of Lodash templates (this config is distinct to the
  6250. * config of requirejs-tpl in main.js). This one is for normal inline templates.
  6251. */
  6252. _.templateSettings = {
  6253. 'escape': /\{\{\{([\s\S]+?)\}\}\}/g,
  6254. 'evaluate': /\{\[([\s\S]+?)\]\}/g,
  6255. 'interpolate': /\{\{([\s\S]+?)\}\}/g,
  6256. 'imports': {
  6257. '_': _
  6258. }
  6259. };
  6260. var _converse = {
  6261. 'templates': {},
  6262. 'promises': {}
  6263. };
  6264. _.extend(_converse, Backbone.Events); // Core plugins are whitelisted automatically
  6265. _converse.core_plugins = ['converse-bookmarks', 'converse-chatboxes', 'converse-chatview', 'converse-controlbox', 'converse-core', 'converse-disco', 'converse-dragresize', 'converse-dropdown', 'converse-fullscreen', 'converse-headline', 'converse-mam', 'converse-minimize', 'converse-modal', 'converse-muc', 'converse-muc-embedded', 'converse-muc-views', 'converse-notification', 'converse-otr', 'converse-ping', 'converse-profile', 'converse-register', 'converse-roomslist', 'converse-rosterview', 'converse-singleton', 'converse-spoilers', 'converse-vcard']; // Make converse pluggable
  6266. pluggable.enable(_converse, '_converse', 'pluggable'); // Module-level constants
  6267. _converse.STATUS_WEIGHTS = {
  6268. 'offline': 6,
  6269. 'unavailable': 5,
  6270. 'xa': 4,
  6271. 'away': 3,
  6272. 'dnd': 2,
  6273. 'chat': 1,
  6274. // We currently don't differentiate between "chat" and "online"
  6275. 'online': 1
  6276. };
  6277. _converse.PRETTY_CHAT_STATUS = {
  6278. 'offline': 'Offline',
  6279. 'unavailable': 'Unavailable',
  6280. 'xa': 'Extended Away',
  6281. 'away': 'Away',
  6282. 'dnd': 'Do not disturb',
  6283. 'chat': 'Chattty',
  6284. 'online': 'Online'
  6285. };
  6286. _converse.ANONYMOUS = "anonymous";
  6287. _converse.CLOSED = 'closed';
  6288. _converse.EXTERNAL = "external";
  6289. _converse.LOGIN = "login";
  6290. _converse.LOGOUT = "logout";
  6291. _converse.OPENED = 'opened';
  6292. _converse.PREBIND = "prebind";
  6293. _converse.CONNECTION_STATUS = {
  6294. 0: 'ERROR',
  6295. 1: 'CONNECTING',
  6296. 2: 'CONNFAIL',
  6297. 3: 'AUTHENTICATING',
  6298. 4: 'AUTHFAIL',
  6299. 5: 'CONNECTED',
  6300. 6: 'DISCONNECTED',
  6301. 7: 'DISCONNECTING',
  6302. 8: 'ATTACHED',
  6303. 9: 'REDIRECT',
  6304. 10: 'RECONNECTING'
  6305. };
  6306. _converse.DEFAULT_IMAGE_TYPE = 'image/png';
  6307. _converse.DEFAULT_IMAGE = "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAIAAABt+uBvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwHCy455JBsggAABkJJREFUeNrtnM1PE1sUwHvvTD8otWLHST/Gimi1CEgr6M6FEWuIBo2pujDVsNDEP8GN/4MbN7oxrlipG2OCgZgYlxAbkRYw1KqkIDRCSkM7nXvvW8x7vjyNeQ9m7p1p3z1LQk/v/Dhz7vkEXL161cHl9wI5Ag6IA+KAOCAOiAPigDggLhwQB2S+iNZ+PcYY/SWEEP2HAAAIoSAIoihCCP+ngDDGtVotGAz29/cfOXJEUZSOjg6n06lp2sbGRqlUWlhYyGazS0tLbrdbEASrzgksyeYJId3d3el0uqenRxRFAAAA4KdfIIRgjD9+/Pj8+fOpqSndslofEIQwHA6Pjo4mEon//qmFhYXHjx8vLi4ihBgDEnp7e9l8E0Jo165dQ0NDd+/eDYVC2/qsJElDQ0OEkKWlpa2tLZamxAhQo9EIBoOjo6MXL17csZLe3l5FUT59+lQul5l5JRaAVFWNRqN37tw5ceKEQVWRSOTw4cOFQuHbt2+iKLYCIISQLMu3b99OJpOmKAwEAgcPHszn8+vr6wzsiG6UQQhxuVyXLl0aGBgwUW0sFstkMl6v90fo1KyAMMYDAwPnzp0zXfPg4GAqlWo0Gk0MiBAiy/L58+edTqf5Aa4onj59OhaLYYybFRCEMBaL0fNxBw4cSCQStN0QRUBut3t4eJjq6U+dOiVJElVPRBFQIBDo6+ujCqirqyscDlONGykC2lYyYSR6pBoQQapHZwAoHo/TuARYAOrs7GQASFEUqn6aIiBJkhgA6ujooFpUo6iaTa7koFwnaoWadLNe81tbWwzoaJrWrICWl5cZAFpbW6OabVAEtLi4yABQsVjUNK0pAWWzWQaAcrlcswKanZ1VVZUqHYRQEwOq1Wpv3ryhCmh6erpcLjdrNl+v1ycnJ+l5UELI27dvv3//3qxxEADgy5cvExMT9Mznw4cPtFtAdAPFarU6Pj5eKpVM17yxsfHy5cvV1VXazXu62gVBKBQKT58+rdVqJqrFGL948eLdu3dU8/g/H4FBUaJYLAqC0NPTY9brMD4+PjY25mDSracOCABACJmZmXE6nUePHjWu8NWrV48ePSKEsGlAs7Agfd5nenq6Wq0mk0kjDzY2NvbkyRMIIbP2PLvhBUEQ8vl8NpuNx+M+n29bzhVjvLKycv/+/YmJCcazQuwA6YzW1tYmJyf1SY+2trZ/rRk1Go1SqfT69esHDx4UCgVmNaa/zZ/9ABUhRFXVYDB48uTJeDweiUQkSfL7/T9MA2NcqVTK5fLy8vL8/PzU1FSxWHS5XJaM4wGr9sUwxqqqer3eUCgkSZJuUBBCfTRvc3OzXC6vrKxUKhWn02nhCJ5lM4oQQo/HgxD6+vXr58+fHf8sDOp+HQDg8XgclorFU676dKLlo6yWRdItIBwQB8QBcUCtfosRQjRNQwhhjPUC4w46WXryBSHU1zgEQWBz99EFhDGu1+t+v//48ePxeFxRlD179ng8nh0Efgiher2+vr6ur3HMzMysrq7uTJVdACGEurq6Ll++nEgkPB7Pj9jPoDHqOxyqqubz+WfPnuVyuV9XPeyeagAAAoHArVu3BgcHab8CuVzu4cOHpVKJUnfA5GweY+xyuc6cOXPv3r1IJMLAR8iyPDw8XK/Xi8Wiqqqmm5KZgBBC7e3tN27cuHbtGuPVpf7+/lAoNDs7W61WzfVKpgHSSzw3b95MpVKW3MfRaDQSiczNzVUqFRMZmQOIEOL1eq9fv3727FlL1t50URRFluX5+flqtWpWEGAOIFEUU6nUlStXLKSjy759+xwOx9zcnKZpphzGHMzhcDiTydgk9r1w4YIp7RPTAAmCkMlk2FeLf/tIEKbTab/fbwtAhJBoNGrutpNx6e7uPnTokC1eMU3T0um0DZPMkZER6wERQnw+n/FFSxpy7Nix3bt3WwwIIcRgIWnHkkwmjecfRgGx7DtuV/r6+iwGhDHev3+/bQF1dnYaH6E2CkiWZdsC2rt3r8WAHA5HW1ubbQGZcjajgOwTH/4qNko1Wlg4IA6IA+KAOKBWBUQIsfNojyliKIoRRfH9+/dut9umf3wzpoUNNQ4BAJubmwz+ic+OxefzWWlBhJD29nbug7iT5sIBcUAcEAfEAXFAHBAHxOVn+QMrmWpuPZx12gAAAABJRU5ErkJggg==";
  6308. _converse.log = function (message, level) {
  6309. var style = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
  6310. /* Logs messages to the browser's developer console.
  6311. *
  6312. * Parameters:
  6313. * (String) message - The message to be logged.
  6314. * (Integer) level - The loglevel which allows for filtering of log
  6315. * messages.
  6316. *
  6317. * Available loglevels are 0 for 'debug', 1 for 'info', 2 for 'warn',
  6318. * 3 for 'error' and 4 for 'fatal'.
  6319. *
  6320. * When using the 'error' or 'warn' loglevels, a full stacktrace will be
  6321. * logged as well.
  6322. */
  6323. if (level === Strophe.LogLevel.ERROR || level === Strophe.LogLevel.FATAL) {
  6324. style = style || 'color: maroon';
  6325. }
  6326. if (message instanceof Error) {
  6327. message = message.stack;
  6328. }
  6329. var prefix = style ? '%c' : '';
  6330. var logger = _.assign({
  6331. 'debug': _.get(console, 'log') ? console.log.bind(console) : _.noop,
  6332. 'error': _.get(console, 'log') ? console.log.bind(console) : _.noop,
  6333. 'info': _.get(console, 'log') ? console.log.bind(console) : _.noop,
  6334. 'warn': _.get(console, 'log') ? console.log.bind(console) : _.noop
  6335. }, console);
  6336. if (level === Strophe.LogLevel.ERROR) {
  6337. logger.error("".concat(prefix, " ERROR: ").concat(message), style);
  6338. } else if (level === Strophe.LogLevel.WARN) {
  6339. if (_converse.debug) {
  6340. logger.warn("".concat(prefix, " ").concat(moment().format(), " WARNING: ").concat(message), style);
  6341. }
  6342. } else if (level === Strophe.LogLevel.FATAL) {
  6343. logger.error("".concat(prefix, " FATAL: ").concat(message), style);
  6344. } else if (_converse.debug) {
  6345. if (level === Strophe.LogLevel.DEBUG) {
  6346. logger.debug("".concat(prefix, " ").concat(moment().format(), " DEBUG: ").concat(message), style);
  6347. } else {
  6348. logger.info("".concat(prefix, " ").concat(moment().format(), " INFO: ").concat(message), style);
  6349. }
  6350. }
  6351. };
  6352. Strophe.log = function (level, msg) {
  6353. _converse.log(level + ' ' + msg, level);
  6354. };
  6355. Strophe.error = function (msg) {
  6356. _converse.log(msg, Strophe.LogLevel.ERROR);
  6357. };
  6358. _converse.__ = function (str) {
  6359. /* Translate the given string based on the current locale.
  6360. *
  6361. * Parameters:
  6362. * (String) str - The string to translate.
  6363. */
  6364. if (_.isUndefined(i18n)) {
  6365. return str;
  6366. }
  6367. return i18n.translate.apply(i18n, arguments);
  6368. };
  6369. var __ = _converse.__;
  6370. var PROMISES = ['initialized', 'cachedRoster', 'connectionInitialized', 'pluginsInitialized', 'roster', 'rosterContactsFetched', 'rosterGroupsFetched', 'rosterInitialized', 'statusInitialized'];
  6371. function addPromise(promise) {
  6372. /* Private function, used to add a new promise to the ones already
  6373. * available via the `waitUntil` api method.
  6374. */
  6375. _converse.promises[promise] = u.getResolveablePromise();
  6376. }
  6377. _converse.emit = function (name) {
  6378. /* Event emitter and promise resolver */
  6379. _converse.trigger.apply(this, arguments);
  6380. var promise = _converse.promises[name];
  6381. if (!_.isUndefined(promise)) {
  6382. promise.resolve();
  6383. }
  6384. };
  6385. _converse.router = new Backbone.Router();
  6386. _converse.initialize = function (settings, callback) {
  6387. "use strict";
  6388. var _this = this;
  6389. settings = !_.isUndefined(settings) ? settings : {};
  6390. var init_promise = u.getResolveablePromise();
  6391. _.each(PROMISES, addPromise);
  6392. if (!_.isUndefined(_converse.connection)) {
  6393. // Looks like _converse.initialized was called again without logging
  6394. // out or disconnecting in the previous session.
  6395. // This happens in tests. We therefore first clean up.
  6396. Backbone.history.stop();
  6397. _converse.chatboxviews.closeAllChatBoxes();
  6398. delete _converse.controlboxtoggle;
  6399. delete _converse.chatboxviews;
  6400. _converse.connection.reset();
  6401. _converse.off();
  6402. _converse.stopListening();
  6403. _converse._tearDown();
  6404. }
  6405. var unloadevent;
  6406. if ('onpagehide' in window) {
  6407. // Pagehide gets thrown in more cases than unload. Specifically it
  6408. // gets thrown when the page is cached and not just
  6409. // closed/destroyed. It's the only viable event on mobile Safari.
  6410. // https://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
  6411. unloadevent = 'pagehide';
  6412. } else if ('onbeforeunload' in window) {
  6413. unloadevent = 'beforeunload';
  6414. } else if ('onunload' in window) {
  6415. unloadevent = 'unload';
  6416. } // Instance level constants
  6417. this.TIMEOUTS = {
  6418. // Set as module attr so that we can override in tests.
  6419. 'PAUSED': 10000,
  6420. 'INACTIVE': 90000
  6421. }; // XEP-0085 Chat states
  6422. // http://xmpp.org/extensions/xep-0085.html
  6423. this.INACTIVE = 'inactive';
  6424. this.ACTIVE = 'active';
  6425. this.COMPOSING = 'composing';
  6426. this.PAUSED = 'paused';
  6427. this.GONE = 'gone'; // Default configuration values
  6428. // ----------------------------
  6429. this.default_settings = {
  6430. allow_contact_requests: true,
  6431. allow_non_roster_messaging: false,
  6432. animate: true,
  6433. authentication: 'login',
  6434. // Available values are "login", "prebind", "anonymous" and "external".
  6435. auto_away: 0,
  6436. // Seconds after which user status is set to 'away'
  6437. auto_login: false,
  6438. // Currently only used in connection with anonymous login
  6439. auto_reconnect: true,
  6440. auto_subscribe: false,
  6441. auto_xa: 0,
  6442. // Seconds after which user status is set to 'xa'
  6443. blacklisted_plugins: [],
  6444. bosh_service_url: undefined,
  6445. connection_options: {},
  6446. credentials_url: null,
  6447. // URL from where login credentials can be fetched
  6448. csi_waiting_time: 0,
  6449. // Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
  6450. debug: false,
  6451. default_state: 'online',
  6452. expose_rid_and_sid: false,
  6453. filter_by_resource: false,
  6454. forward_messages: false,
  6455. hide_offline_users: false,
  6456. include_offline_state: false,
  6457. jid: undefined,
  6458. keepalive: true,
  6459. locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
  6460. locales: ['af', 'ar', 'bg', 'ca', 'de', 'es', 'en', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'],
  6461. message_carbons: true,
  6462. message_storage: 'session',
  6463. password: undefined,
  6464. prebind_url: null,
  6465. priority: 0,
  6466. registration_domain: '',
  6467. rid: undefined,
  6468. root: window.document,
  6469. roster_groups: true,
  6470. show_only_online_users: false,
  6471. show_send_button: false,
  6472. sid: undefined,
  6473. storage: 'session',
  6474. strict_plugin_dependencies: false,
  6475. synchronize_availability: true,
  6476. view_mode: 'overlayed',
  6477. // Choices are 'overlayed', 'fullscreen', 'mobile'
  6478. websocket_url: undefined,
  6479. whitelisted_plugins: []
  6480. };
  6481. _.assignIn(this, this.default_settings); // Allow only whitelisted configuration attributes to be overwritten
  6482. _.assignIn(this, _.pick(settings, _.keys(this.default_settings)));
  6483. if (this.authentication === _converse.ANONYMOUS) {
  6484. if (this.auto_login && !this.jid) {
  6485. throw new Error("Config Error: you need to provide the server's " + "domain via the 'jid' option when using anonymous " + "authentication with auto_login.");
  6486. }
  6487. }
  6488. /* Localisation */
  6489. if (!_.isUndefined(i18n)) {
  6490. i18n.setLocales(settings.i18n, _converse);
  6491. } else {
  6492. _converse.locale = 'en';
  6493. } // Module-level variables
  6494. // ----------------------
  6495. this.callback = callback || _.noop;
  6496. /* When reloading the page:
  6497. * For new sessions, we need to send out a presence stanza to notify
  6498. * the server/network that we're online.
  6499. * When re-attaching to an existing session (e.g. via the keepalive
  6500. * option), we don't need to again send out a presence stanza, because
  6501. * it's as if "we never left" (see onConnectStatusChanged).
  6502. * https://github.com/jcbrand/converse.js/issues/521
  6503. */
  6504. this.send_initial_presence = true;
  6505. this.msg_counter = 0;
  6506. this.user_settings = settings; // Save the user settings so that they can be used by plugins
  6507. // Module-level functions
  6508. // ----------------------
  6509. this.generateResource = function () {
  6510. return "/converse.js-".concat(Math.floor(Math.random() * 139749528).toString());
  6511. };
  6512. this.sendCSI = function (stat) {
  6513. /* Send out a Chat Status Notification (XEP-0352)
  6514. *
  6515. * Parameters:
  6516. * (String) stat: The user's chat status
  6517. */
  6518. /* Send out a Chat Status Notification (XEP-0352) */
  6519. // XXX if (converse.features[Strophe.NS.CSI] || true) {
  6520. _converse.connection.send($build(stat, {
  6521. xmlns: Strophe.NS.CSI
  6522. }));
  6523. _converse.inactive = stat === _converse.INACTIVE ? true : false;
  6524. };
  6525. this.onUserActivity = function () {
  6526. /* Resets counters and flags relating to CSI and auto_away/auto_xa */
  6527. if (_converse.idle_seconds > 0) {
  6528. _converse.idle_seconds = 0;
  6529. }
  6530. if (!_converse.connection.authenticated) {
  6531. // We can't send out any stanzas when there's no authenticated connection.
  6532. // converse can happen when the connection reconnects.
  6533. return;
  6534. }
  6535. if (_converse.inactive) {
  6536. _converse.sendCSI(_converse.ACTIVE);
  6537. }
  6538. if (_converse.auto_changed_status === true) {
  6539. _converse.auto_changed_status = false; // XXX: we should really remember the original state here, and
  6540. // then set it back to that...
  6541. _converse.xmppstatus.set('status', _converse.default_state);
  6542. }
  6543. };
  6544. this.onEverySecond = function () {
  6545. /* An interval handler running every second.
  6546. * Used for CSI and the auto_away and auto_xa features.
  6547. */
  6548. if (!_converse.connection.authenticated) {
  6549. // We can't send out any stanzas when there's no authenticated connection.
  6550. // This can happen when the connection reconnects.
  6551. return;
  6552. }
  6553. var stat = _converse.xmppstatus.get('status');
  6554. _converse.idle_seconds++;
  6555. if (_converse.csi_waiting_time > 0 && _converse.idle_seconds > _converse.csi_waiting_time && !_converse.inactive) {
  6556. _converse.sendCSI(_converse.INACTIVE);
  6557. }
  6558. if (_converse.auto_away > 0 && _converse.idle_seconds > _converse.auto_away && stat !== 'away' && stat !== 'xa' && stat !== 'dnd') {
  6559. _converse.auto_changed_status = true;
  6560. _converse.xmppstatus.set('status', 'away');
  6561. } else if (_converse.auto_xa > 0 && _converse.idle_seconds > _converse.auto_xa && stat !== 'xa' && stat !== 'dnd') {
  6562. _converse.auto_changed_status = true;
  6563. _converse.xmppstatus.set('status', 'xa');
  6564. }
  6565. };
  6566. this.registerIntervalHandler = function () {
  6567. /* Set an interval of one second and register a handler for it.
  6568. * Required for the auto_away, auto_xa and csi_waiting_time features.
  6569. */
  6570. if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1) {
  6571. // Waiting time of less then one second means features aren't used.
  6572. return;
  6573. }
  6574. _converse.idle_seconds = 0;
  6575. _converse.auto_changed_status = false; // Was the user's status changed by _converse.js?
  6576. window.addEventListener('click', _converse.onUserActivity);
  6577. window.addEventListener('focus', _converse.onUserActivity);
  6578. window.addEventListener('keypress', _converse.onUserActivity);
  6579. window.addEventListener('mousemove', _converse.onUserActivity);
  6580. window.addEventListener(unloadevent, _converse.onUserActivity);
  6581. _converse.everySecondTrigger = window.setInterval(_converse.onEverySecond, 1000);
  6582. };
  6583. this.setConnectionStatus = function (connection_status, message) {
  6584. _converse.connfeedback.set({
  6585. 'connection_status': connection_status,
  6586. 'message': message
  6587. });
  6588. };
  6589. this.rejectPresenceSubscription = function (jid, message) {
  6590. /* Reject or cancel another user's subscription to our presence updates.
  6591. *
  6592. * Parameters:
  6593. * (String) jid - The Jabber ID of the user whose subscription
  6594. * is being canceled.
  6595. * (String) message - An optional message to the user
  6596. */
  6597. var pres = $pres({
  6598. to: jid,
  6599. type: "unsubscribed"
  6600. });
  6601. if (message && message !== "") {
  6602. pres.c("status").t(message);
  6603. }
  6604. _converse.connection.send(pres);
  6605. };
  6606. this.reconnect = _.debounce(function () {
  6607. _converse.log('RECONNECTING');
  6608. _converse.log('The connection has dropped, attempting to reconnect.');
  6609. _converse.setConnectionStatus(Strophe.Status.RECONNECTING, __('The connection has dropped, attempting to reconnect.'));
  6610. _converse.connection.reconnecting = true;
  6611. _converse._tearDown();
  6612. _converse.logIn(null, true);
  6613. }, 3000, {
  6614. 'leading': true
  6615. });
  6616. this.disconnect = function () {
  6617. _converse.log('DISCONNECTED');
  6618. delete _converse.connection.reconnecting;
  6619. _converse.connection.reset();
  6620. _converse._tearDown();
  6621. _converse.emit('disconnected');
  6622. };
  6623. this.onDisconnected = function () {
  6624. /* Gets called once strophe's status reaches Strophe.Status.DISCONNECTED.
  6625. * Will either start a teardown process for converse.js or attempt
  6626. * to reconnect.
  6627. */
  6628. var reason = _converse.disconnection_reason;
  6629. if (_converse.disconnection_cause === Strophe.Status.AUTHFAIL) {
  6630. if (_converse.credentials_url && _converse.auto_reconnect) {
  6631. /* In this case, we reconnect, because we might be receiving
  6632. * expirable tokens from the credentials_url.
  6633. */
  6634. _converse.emit('will-reconnect');
  6635. return _converse.reconnect();
  6636. } else {
  6637. return _converse.disconnect();
  6638. }
  6639. } else if (_converse.disconnection_cause === _converse.LOGOUT || !_.isUndefined(reason) && reason === _.get(Strophe, 'ErrorCondition.NO_AUTH_MECH') || reason === "host-unknown" || reason === "remote-connection-failed" || !_converse.auto_reconnect) {
  6640. return _converse.disconnect();
  6641. }
  6642. _converse.emit('will-reconnect');
  6643. _converse.reconnect();
  6644. };
  6645. this.setDisconnectionCause = function (cause, reason, override) {
  6646. /* Used to keep track of why we got disconnected, so that we can
  6647. * decide on what the next appropriate action is (in onDisconnected)
  6648. */
  6649. if (_.isUndefined(cause)) {
  6650. delete _converse.disconnection_cause;
  6651. delete _converse.disconnection_reason;
  6652. } else if (_.isUndefined(_converse.disconnection_cause) || override) {
  6653. _converse.disconnection_cause = cause;
  6654. _converse.disconnection_reason = reason;
  6655. }
  6656. };
  6657. this.onConnectStatusChanged = function (status, message) {
  6658. /* Callback method called by Strophe as the Strophe.Connection goes
  6659. * through various states while establishing or tearing down a
  6660. * connection.
  6661. */
  6662. _converse.log("Status changed to: ".concat(_converse.CONNECTION_STATUS[status]));
  6663. if (status === Strophe.Status.CONNECTED || status === Strophe.Status.ATTACHED) {
  6664. _converse.setConnectionStatus(status); // By default we always want to send out an initial presence stanza.
  6665. _converse.send_initial_presence = true;
  6666. _converse.setDisconnectionCause();
  6667. if (_converse.connection.reconnecting) {
  6668. _converse.log(status === Strophe.Status.CONNECTED ? 'Reconnected' : 'Reattached');
  6669. _converse.onConnected(true);
  6670. } else {
  6671. _converse.log(status === Strophe.Status.CONNECTED ? 'Connected' : 'Attached');
  6672. if (_converse.connection.restored) {
  6673. // No need to send an initial presence stanza when
  6674. // we're restoring an existing session.
  6675. _converse.send_initial_presence = false;
  6676. }
  6677. _converse.onConnected();
  6678. }
  6679. } else if (status === Strophe.Status.DISCONNECTED) {
  6680. _converse.setDisconnectionCause(status, message);
  6681. _converse.onDisconnected();
  6682. } else if (status === Strophe.Status.ERROR) {
  6683. _converse.setConnectionStatus(status, __('An error occurred while connecting to the chat server.'));
  6684. } else if (status === Strophe.Status.CONNECTING) {
  6685. _converse.setConnectionStatus(status);
  6686. } else if (status === Strophe.Status.AUTHENTICATING) {
  6687. _converse.setConnectionStatus(status);
  6688. } else if (status === Strophe.Status.AUTHFAIL) {
  6689. if (!message) {
  6690. message = __('Your Jabber ID and/or password is incorrect. Please try again.');
  6691. }
  6692. _converse.setConnectionStatus(status, message);
  6693. _converse.setDisconnectionCause(status, message, true);
  6694. _converse.onDisconnected();
  6695. } else if (status === Strophe.Status.CONNFAIL) {
  6696. var feedback = message;
  6697. if (message === "host-unknown" || message == "remote-connection-failed") {
  6698. feedback = __("Sorry, we could not connect to the XMPP host with domain: %1$s", "\"".concat(Strophe.getDomainFromJid(_converse.connection.jid), "\""));
  6699. } else if (!_.isUndefined(message) && message === _.get(Strophe, 'ErrorCondition.NO_AUTH_MECH')) {
  6700. feedback = __("The XMPP server did not offer a supported authentication mechanism");
  6701. }
  6702. _converse.setConnectionStatus(status, feedback);
  6703. _converse.setDisconnectionCause(status, message);
  6704. } else if (status === Strophe.Status.DISCONNECTING) {
  6705. _converse.setDisconnectionCause(status, message);
  6706. }
  6707. };
  6708. this.incrementMsgCounter = function () {
  6709. this.msg_counter += 1;
  6710. var unreadMsgCount = this.msg_counter;
  6711. var title = document.title;
  6712. if (_.isNil(title)) {
  6713. return;
  6714. }
  6715. if (title.search(/^Messages \(\d+\) /) === -1) {
  6716. title = "Messages (".concat(unreadMsgCount, ") ").concat(title);
  6717. } else {
  6718. title = title.replace(/^Messages \(\d+\) /, "Messages (".concat(unreadMsgCount, ")"));
  6719. }
  6720. };
  6721. this.clearMsgCounter = function () {
  6722. this.msg_counter = 0;
  6723. var title = document.title;
  6724. if (_.isNil(title)) {
  6725. return;
  6726. }
  6727. if (title.search(/^Messages \(\d+\) /) !== -1) {
  6728. title = title.replace(/^Messages \(\d+\) /, "");
  6729. }
  6730. };
  6731. this.initStatus = function (reconnecting) {
  6732. // If there's no xmppstatus obj, then we were never connected to
  6733. // begin with, so we set reconnecting to false.
  6734. reconnecting = _.isUndefined(_converse.xmppstatus) ? false : reconnecting;
  6735. if (reconnecting) {
  6736. _converse.onStatusInitialized(reconnecting);
  6737. } else {
  6738. _this.xmppstatus = new _this.XMPPStatus();
  6739. var id = b64_sha1("converse.xmppstatus-".concat(_converse.bare_jid));
  6740. _this.xmppstatus.id = id; // Appears to be necessary for backbone.browserStorage
  6741. _this.xmppstatus.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  6742. _this.xmppstatus.fetch({
  6743. success: _.partial(_converse.onStatusInitialized, reconnecting),
  6744. error: _.partial(_converse.onStatusInitialized, reconnecting)
  6745. });
  6746. }
  6747. };
  6748. this.initSession = function () {
  6749. _converse.session = new Backbone.Model();
  6750. var id = b64_sha1('converse.bosh-session');
  6751. _converse.session.id = id; // Appears to be necessary for backbone.browserStorage
  6752. _converse.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  6753. _converse.session.fetch();
  6754. };
  6755. this.clearSession = function () {
  6756. if (!_.isUndefined(this.roster)) {
  6757. this.roster.browserStorage._clear();
  6758. }
  6759. if (!_.isUndefined(this.session) && this.session.browserStorage) {
  6760. this.session.browserStorage._clear();
  6761. }
  6762. };
  6763. this.logOut = function () {
  6764. _converse.clearSession();
  6765. _converse.setDisconnectionCause(_converse.LOGOUT, undefined, true);
  6766. if (!_.isUndefined(_converse.connection)) {
  6767. _converse.connection.disconnect();
  6768. } else {
  6769. _converse._tearDown();
  6770. } // Recreate all the promises
  6771. _.each(_.keys(_converse.promises), addPromise);
  6772. _converse.emit('logout');
  6773. };
  6774. this.saveWindowState = function (ev, hidden) {
  6775. // XXX: eventually we should be able to just use
  6776. // document.visibilityState (when we drop support for older
  6777. // browsers).
  6778. var state;
  6779. var event_map = {
  6780. 'focus': "visible",
  6781. 'focusin': "visible",
  6782. 'pageshow': "visible",
  6783. 'blur': "hidden",
  6784. 'focusout': "hidden",
  6785. 'pagehide': "hidden"
  6786. };
  6787. ev = ev || document.createEvent('Events');
  6788. if (ev.type in event_map) {
  6789. state = event_map[ev.type];
  6790. } else {
  6791. state = document[hidden] ? "hidden" : "visible";
  6792. }
  6793. if (state === 'visible') {
  6794. _converse.clearMsgCounter();
  6795. }
  6796. _converse.windowState = state;
  6797. _converse.emit('windowStateChanged', {
  6798. state: state
  6799. });
  6800. };
  6801. this.registerGlobalEventHandlers = function () {
  6802. // Taken from:
  6803. // http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active
  6804. var hidden = "hidden"; // Standards:
  6805. if (hidden in document) {
  6806. document.addEventListener("visibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6807. } else if ((hidden = "mozHidden") in document) {
  6808. document.addEventListener("mozvisibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6809. } else if ((hidden = "webkitHidden") in document) {
  6810. document.addEventListener("webkitvisibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6811. } else if ((hidden = "msHidden") in document) {
  6812. document.addEventListener("msvisibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6813. } else if ("onfocusin" in document) {
  6814. // IE 9 and lower:
  6815. document.onfocusin = document.onfocusout = _.partial(_converse.saveWindowState, _, hidden);
  6816. } else {
  6817. // All others:
  6818. window.onpageshow = window.onpagehide = window.onfocus = window.onblur = _.partial(_converse.saveWindowState, _, hidden);
  6819. } // set the initial state (but only if browser supports the Page Visibility API)
  6820. if (document[hidden] !== undefined) {
  6821. _.partial(_converse.saveWindowState, _, hidden)({
  6822. type: document[hidden] ? "blur" : "focus"
  6823. });
  6824. }
  6825. };
  6826. this.enableCarbons = function () {
  6827. var _this2 = this;
  6828. /* Ask the XMPP server to enable Message Carbons
  6829. * See XEP-0280 https://xmpp.org/extensions/xep-0280.html#enabling
  6830. */
  6831. if (!this.message_carbons || this.session.get('carbons_enabled')) {
  6832. return;
  6833. }
  6834. var carbons_iq = new Strophe.Builder('iq', {
  6835. from: this.connection.jid,
  6836. id: 'enablecarbons',
  6837. type: 'set'
  6838. }).c('enable', {
  6839. xmlns: Strophe.NS.CARBONS
  6840. });
  6841. this.connection.addHandler(function (iq) {
  6842. if (iq.querySelectorAll('error').length > 0) {
  6843. _converse.log('An error occured while trying to enable message carbons.', Strophe.LogLevel.ERROR);
  6844. } else {
  6845. _this2.session.save({
  6846. carbons_enabled: true
  6847. });
  6848. _converse.log('Message carbons have been enabled.');
  6849. }
  6850. }, null, "iq", null, "enablecarbons");
  6851. this.connection.send(carbons_iq);
  6852. };
  6853. this.initRoster = function () {
  6854. /* Initialize the Bakcbone collections that represent the contats
  6855. * roster and the roster groups.
  6856. */
  6857. _converse.roster = new _converse.RosterContacts();
  6858. _converse.roster.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.contacts-".concat(_converse.bare_jid)));
  6859. _converse.rostergroups = new _converse.RosterGroups();
  6860. _converse.rostergroups.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.roster.groups".concat(_converse.bare_jid)));
  6861. _converse.emit('rosterInitialized');
  6862. };
  6863. this.populateRoster = function () {
  6864. var ignore_cache = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  6865. /* Fetch all the roster groups, and then the roster contacts.
  6866. * Emit an event after fetching is done in each case.
  6867. *
  6868. * Parameters:
  6869. * (Bool) ignore_cache - If set to to true, the local cache
  6870. * will be ignored it's guaranteed that the XMPP server
  6871. * will be queried for the roster.
  6872. */
  6873. if (ignore_cache) {
  6874. _converse.send_initial_presence = true;
  6875. _converse.roster.fetchFromServer().then(function () {
  6876. _converse.emit('rosterContactsFetched');
  6877. _converse.sendInitialPresence();
  6878. }).catch(function (reason) {
  6879. _converse.log(reason, Strophe.LogLevel.ERROR);
  6880. _converse.sendInitialPresence();
  6881. });
  6882. } else {
  6883. _converse.rostergroups.fetchRosterGroups().then(function () {
  6884. _converse.emit('rosterGroupsFetched');
  6885. return _converse.roster.fetchRosterContacts();
  6886. }).then(function () {
  6887. _converse.emit('rosterContactsFetched');
  6888. _converse.sendInitialPresence();
  6889. }).catch(function (reason) {
  6890. _converse.log(reason, Strophe.LogLevel.ERROR);
  6891. _converse.sendInitialPresence();
  6892. });
  6893. }
  6894. };
  6895. this.unregisterPresenceHandler = function () {
  6896. if (!_.isUndefined(_converse.presence_ref)) {
  6897. _converse.connection.deleteHandler(_converse.presence_ref);
  6898. delete _converse.presence_ref;
  6899. }
  6900. };
  6901. this.registerPresenceHandler = function () {
  6902. _converse.unregisterPresenceHandler();
  6903. _converse.presence_ref = _converse.connection.addHandler(function (presence) {
  6904. _converse.roster.presenceHandler(presence);
  6905. return true;
  6906. }, null, 'presence', null);
  6907. };
  6908. this.sendInitialPresence = function () {
  6909. if (_converse.send_initial_presence) {
  6910. _converse.xmppstatus.sendPresence();
  6911. }
  6912. };
  6913. this.onStatusInitialized = function (reconnecting) {
  6914. /* Continue with session establishment (e.g. fetching chat boxes,
  6915. * populating the roster etc.) necessary once the connection has
  6916. * been established.
  6917. */
  6918. _converse.emit('statusInitialized');
  6919. if (reconnecting) {
  6920. // No need to recreate the roster, otherwise we lose our
  6921. // cached data. However we still emit an event, to give
  6922. // event handlers a chance to register views for the
  6923. // roster and its groups, before we start populating.
  6924. _converse.emit('rosterReadyAfterReconnection');
  6925. } else {
  6926. _converse.registerIntervalHandler();
  6927. _converse.initRoster();
  6928. }
  6929. _converse.roster.onConnected();
  6930. _converse.populateRoster(reconnecting);
  6931. _converse.registerPresenceHandler();
  6932. if (reconnecting) {
  6933. _converse.emit('reconnected');
  6934. } else {
  6935. init_promise.resolve();
  6936. _converse.emit('initialized');
  6937. _converse.emit('connected');
  6938. }
  6939. };
  6940. this.setUserJid = function () {
  6941. _converse.jid = _converse.connection.jid;
  6942. _converse.bare_jid = Strophe.getBareJidFromJid(_converse.connection.jid);
  6943. _converse.resource = Strophe.getResourceFromJid(_converse.connection.jid);
  6944. _converse.domain = Strophe.getDomainFromJid(_converse.connection.jid);
  6945. };
  6946. this.onConnected = function (reconnecting) {
  6947. /* Called as soon as a new connection has been established, either
  6948. * by logging in or by attaching to an existing BOSH session.
  6949. */
  6950. _converse.connection.flush(); // Solves problem of returned PubSub BOSH response not received by browser
  6951. _converse.setUserJid();
  6952. _converse.initSession();
  6953. _converse.enableCarbons();
  6954. _converse.initStatus(reconnecting);
  6955. };
  6956. this.RosterContact = Backbone.Model.extend({
  6957. defaults: {
  6958. 'chat_state': undefined,
  6959. 'chat_status': 'offline',
  6960. 'image': _converse.DEFAULT_IMAGE,
  6961. 'image_type': _converse.DEFAULT_IMAGE_TYPE,
  6962. 'num_unread': 0,
  6963. 'status': ''
  6964. },
  6965. initialize: function initialize(attributes) {
  6966. var _this3 = this;
  6967. var jid = attributes.jid,
  6968. bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase(),
  6969. resource = Strophe.getResourceFromJid(jid);
  6970. attributes.jid = bare_jid;
  6971. this.set(_.assignIn({
  6972. 'fullname': bare_jid,
  6973. 'groups': [],
  6974. 'id': bare_jid,
  6975. 'jid': bare_jid,
  6976. 'resources': {},
  6977. 'user_id': Strophe.getNodeFromJid(jid)
  6978. }, attributes));
  6979. this.on('destroy', function () {
  6980. _this3.removeFromRoster();
  6981. });
  6982. this.on('change:chat_status', function (item) {
  6983. _converse.emit('contactStatusChanged', item.attributes);
  6984. });
  6985. },
  6986. subscribe: function subscribe(message) {
  6987. /* Send a presence subscription request to this roster contact
  6988. *
  6989. * Parameters:
  6990. * (String) message - An optional message to explain the
  6991. * reason for the subscription request.
  6992. */
  6993. this.save('ask', "subscribe"); // ask === 'subscribe' Means we have ask to subscribe to them.
  6994. var pres = $pres({
  6995. to: this.get('jid'),
  6996. type: "subscribe"
  6997. });
  6998. if (message && message !== "") {
  6999. pres.c("status").t(message).up();
  7000. }
  7001. var nick = _converse.xmppstatus.get('fullname');
  7002. if (nick && nick !== "") {
  7003. pres.c('nick', {
  7004. 'xmlns': Strophe.NS.NICK
  7005. }).t(nick).up();
  7006. }
  7007. _converse.connection.send(pres);
  7008. return this;
  7009. },
  7010. ackSubscribe: function ackSubscribe() {
  7011. /* Upon receiving the presence stanza of type "subscribed",
  7012. * the user SHOULD acknowledge receipt of that subscription
  7013. * state notification by sending a presence stanza of type
  7014. * "subscribe" to the contact
  7015. */
  7016. _converse.connection.send($pres({
  7017. 'type': 'subscribe',
  7018. 'to': this.get('jid')
  7019. }));
  7020. },
  7021. ackUnsubscribe: function ackUnsubscribe() {
  7022. /* Upon receiving the presence stanza of type "unsubscribed",
  7023. * the user SHOULD acknowledge receipt of that subscription state
  7024. * notification by sending a presence stanza of type "unsubscribe"
  7025. * this step lets the user's server know that it MUST no longer
  7026. * send notification of the subscription state change to the user.
  7027. * Parameters:
  7028. * (String) jid - The Jabber ID of the user who is unsubscribing
  7029. */
  7030. _converse.connection.send($pres({
  7031. 'type': 'unsubscribe',
  7032. 'to': this.get('jid')
  7033. }));
  7034. this.destroy(); // Will cause removeFromRoster to be called.
  7035. },
  7036. unauthorize: function unauthorize(message) {
  7037. /* Unauthorize this contact's presence subscription
  7038. * Parameters:
  7039. * (String) message - Optional message to send to the person being unauthorized
  7040. */
  7041. _converse.rejectPresenceSubscription(this.get('jid'), message);
  7042. return this;
  7043. },
  7044. authorize: function authorize(message) {
  7045. /* Authorize presence subscription
  7046. * Parameters:
  7047. * (String) message - Optional message to send to the person being authorized
  7048. */
  7049. var pres = $pres({
  7050. to: this.get('jid'),
  7051. type: "subscribed"
  7052. });
  7053. if (message && message !== "") {
  7054. pres.c("status").t(message);
  7055. }
  7056. _converse.connection.send(pres);
  7057. return this;
  7058. },
  7059. addResource: function addResource(presence) {
  7060. /* Adds a new resource and it's associated attributes as taken
  7061. * from the passed in presence stanza.
  7062. *
  7063. * Also updates the contact's chat_status if the presence has
  7064. * higher priority (and is newer).
  7065. */
  7066. var jid = presence.getAttribute('from'),
  7067. chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
  7068. resource = Strophe.getResourceFromJid(jid),
  7069. delay = presence.querySelector("delay[xmlns=\"".concat(Strophe.NS.DELAY, "\"]")),
  7070. timestamp = _.isNull(delay) ? moment().format() : moment(delay.getAttribute('stamp')).format();
  7071. var priority = _.propertyOf(presence.querySelector('priority'))('textContent') || 0;
  7072. priority = _.isNaN(parseInt(priority, 10)) ? 0 : parseInt(priority, 10);
  7073. var resources = _.isObject(this.get('resources')) ? this.get('resources') : {};
  7074. resources[resource] = {
  7075. 'name': resource,
  7076. 'priority': priority,
  7077. 'status': chat_status,
  7078. 'timestamp': timestamp
  7079. };
  7080. var changed = {
  7081. 'resources': resources
  7082. };
  7083. var hpr = this.getHighestPriorityResource();
  7084. if (priority == hpr.priority && timestamp == hpr.timestamp) {
  7085. // Only set the chat status if this is the newest resource
  7086. // with the highest priority
  7087. changed.chat_status = chat_status;
  7088. }
  7089. this.save(changed);
  7090. return resources;
  7091. },
  7092. removeResource: function removeResource(resource) {
  7093. /* Remove the passed in resource from the contact's resources map.
  7094. *
  7095. * Also recomputes the chat_status given that there's one less
  7096. * resource.
  7097. */
  7098. var resources = this.get('resources');
  7099. if (!_.isObject(resources)) {
  7100. resources = {};
  7101. } else {
  7102. delete resources[resource];
  7103. }
  7104. this.save({
  7105. 'resources': resources,
  7106. 'chat_status': _.propertyOf(this.getHighestPriorityResource())('status') || 'offline'
  7107. });
  7108. },
  7109. getHighestPriorityResource: function getHighestPriorityResource() {
  7110. /* Return the resource with the highest priority.
  7111. *
  7112. * If multiple resources have the same priority, take the
  7113. * newest one.
  7114. */
  7115. var resources = this.get('resources');
  7116. if (_.isObject(resources) && _.size(resources)) {
  7117. var val = _.flow(_.values, _.partial(_.sortBy, _, ['priority', 'timestamp']), _.reverse)(resources)[0];
  7118. if (!_.isUndefined(val)) {
  7119. return val;
  7120. }
  7121. }
  7122. },
  7123. removeFromRoster: function removeFromRoster(callback) {
  7124. /* Instruct the XMPP server to remove this contact from our roster
  7125. * Parameters:
  7126. * (Function) callback
  7127. */
  7128. var iq = $iq({
  7129. type: 'set'
  7130. }).c('query', {
  7131. xmlns: Strophe.NS.ROSTER
  7132. }).c('item', {
  7133. jid: this.get('jid'),
  7134. subscription: "remove"
  7135. });
  7136. _converse.connection.sendIQ(iq, callback, callback);
  7137. return this;
  7138. }
  7139. });
  7140. this.RosterContacts = Backbone.Collection.extend({
  7141. model: _converse.RosterContact,
  7142. comparator: function comparator(contact1, contact2) {
  7143. var status1 = contact1.get('chat_status') || 'offline';
  7144. var status2 = contact2.get('chat_status') || 'offline';
  7145. if (_converse.STATUS_WEIGHTS[status1] === _converse.STATUS_WEIGHTS[status2]) {
  7146. var name1 = contact1.get('fullname').toLowerCase();
  7147. var name2 = contact2.get('fullname').toLowerCase();
  7148. return name1 < name2 ? -1 : name1 > name2 ? 1 : 0;
  7149. } else {
  7150. return _converse.STATUS_WEIGHTS[status1] < _converse.STATUS_WEIGHTS[status2] ? -1 : 1;
  7151. }
  7152. },
  7153. onConnected: function onConnected() {
  7154. /* Called as soon as the connection has been established
  7155. * (either after initial login, or after reconnection).
  7156. *
  7157. * Use the opportunity to register stanza handlers.
  7158. */
  7159. this.registerRosterHandler();
  7160. this.registerRosterXHandler();
  7161. },
  7162. registerRosterHandler: function registerRosterHandler() {
  7163. /* Register a handler for roster IQ "set" stanzas, which update
  7164. * roster contacts.
  7165. */
  7166. _converse.connection.addHandler(_converse.roster.onRosterPush.bind(_converse.roster), Strophe.NS.ROSTER, 'iq', "set");
  7167. },
  7168. registerRosterXHandler: function registerRosterXHandler() {
  7169. /* Register a handler for RosterX message stanzas, which are
  7170. * used to suggest roster contacts to a user.
  7171. */
  7172. var t = 0;
  7173. _converse.connection.addHandler(function (msg) {
  7174. window.setTimeout(function () {
  7175. _converse.connection.flush();
  7176. _converse.roster.subscribeToSuggestedItems.bind(_converse.roster)(msg);
  7177. }, t);
  7178. t += msg.querySelectorAll('item').length * 250;
  7179. return true;
  7180. }, Strophe.NS.ROSTERX, 'message', null);
  7181. },
  7182. fetchRosterContacts: function fetchRosterContacts() {
  7183. var _this4 = this;
  7184. /* Fetches the roster contacts, first by trying the
  7185. * sessionStorage cache, and if that's empty, then by querying
  7186. * the XMPP server.
  7187. *
  7188. * Returns a promise which resolves once the contacts have been
  7189. * fetched.
  7190. */
  7191. return new Promise(function (resolve, reject) {
  7192. _this4.fetch({
  7193. 'add': true,
  7194. 'silent': true,
  7195. success: function success(collection) {
  7196. if (collection.length === 0) {
  7197. _converse.send_initial_presence = true;
  7198. _converse.roster.fetchFromServer().then(resolve).catch(reject);
  7199. } else {
  7200. _converse.emit('cachedRoster', collection);
  7201. resolve();
  7202. }
  7203. }
  7204. });
  7205. });
  7206. },
  7207. subscribeToSuggestedItems: function subscribeToSuggestedItems(msg) {
  7208. _.each(msg.querySelectorAll('item'), function (item) {
  7209. if (item.getAttribute('action') === 'add') {
  7210. _converse.roster.addAndSubscribe(item.getAttribute('jid'), null, _converse.xmppstatus.get('fullname'));
  7211. }
  7212. });
  7213. return true;
  7214. },
  7215. isSelf: function isSelf(jid) {
  7216. return u.isSameBareJID(jid, _converse.connection.jid);
  7217. },
  7218. addAndSubscribe: function addAndSubscribe(jid, name, groups, message, attributes) {
  7219. /* Add a roster contact and then once we have confirmation from
  7220. * the XMPP server we subscribe to that contact's presence updates.
  7221. * Parameters:
  7222. * (String) jid - The Jabber ID of the user being added and subscribed to.
  7223. * (String) name - The name of that user
  7224. * (Array of Strings) groups - Any roster groups the user might belong to
  7225. * (String) message - An optional message to explain the
  7226. * reason for the subscription request.
  7227. * (Object) attributes - Any additional attributes to be stored on the user's model.
  7228. */
  7229. var handler = function handler(contact) {
  7230. if (contact instanceof _converse.RosterContact) {
  7231. contact.subscribe(message);
  7232. }
  7233. };
  7234. this.addContact(jid, name, groups, attributes).then(handler, handler);
  7235. },
  7236. sendContactAddIQ: function sendContactAddIQ(jid, name, groups, callback, errback) {
  7237. /* Send an IQ stanza to the XMPP server to add a new roster contact.
  7238. *
  7239. * Parameters:
  7240. * (String) jid - The Jabber ID of the user being added
  7241. * (String) name - The name of that user
  7242. * (Array of Strings) groups - Any roster groups the user might belong to
  7243. * (Function) callback - A function to call once the IQ is returned
  7244. * (Function) errback - A function to call if an error occured
  7245. */
  7246. name = _.isEmpty(name) ? jid : name;
  7247. var iq = $iq({
  7248. type: 'set'
  7249. }).c('query', {
  7250. xmlns: Strophe.NS.ROSTER
  7251. }).c('item', {
  7252. jid: jid,
  7253. name: name
  7254. });
  7255. _.each(groups, function (group) {
  7256. iq.c('group').t(group).up();
  7257. });
  7258. _converse.connection.sendIQ(iq, callback, errback);
  7259. },
  7260. addContact: function addContact(jid, name, groups, attributes) {
  7261. var _this5 = this;
  7262. /* Adds a RosterContact instance to _converse.roster and
  7263. * registers the contact on the XMPP server.
  7264. * Returns a promise which is resolved once the XMPP server has
  7265. * responded.
  7266. *
  7267. * Parameters:
  7268. * (String) jid - The Jabber ID of the user being added and subscribed to.
  7269. * (String) name - The name of that user
  7270. * (Array of Strings) groups - Any roster groups the user might belong to
  7271. * (Object) attributes - Any additional attributes to be stored on the user's model.
  7272. */
  7273. return new Promise(function (resolve, reject) {
  7274. groups = groups || [];
  7275. name = _.isEmpty(name) ? jid : name;
  7276. _this5.sendContactAddIQ(jid, name, groups, function () {
  7277. var contact = _this5.create(_.assignIn({
  7278. ask: undefined,
  7279. fullname: name,
  7280. groups: groups,
  7281. jid: jid,
  7282. requesting: false,
  7283. subscription: 'none'
  7284. }, attributes), {
  7285. sort: false
  7286. });
  7287. resolve(contact);
  7288. }, function (err) {
  7289. alert(__('Sorry, there was an error while trying to add %1$s as a contact.', name));
  7290. _converse.log(err, Strophe.LogLevel.ERROR);
  7291. resolve(err);
  7292. });
  7293. });
  7294. },
  7295. subscribeBack: function subscribeBack(bare_jid) {
  7296. var contact = this.get(bare_jid);
  7297. if (contact instanceof _converse.RosterContact) {
  7298. contact.authorize().subscribe();
  7299. } else {
  7300. // Can happen when a subscription is retried or roster was deleted
  7301. var handler = function handler(contact) {
  7302. if (contact instanceof _converse.RosterContact) {
  7303. contact.authorize().subscribe();
  7304. }
  7305. };
  7306. this.addContact(bare_jid, '', [], {
  7307. 'subscription': 'from'
  7308. }).then(handler, handler);
  7309. }
  7310. },
  7311. getNumOnlineContacts: function getNumOnlineContacts() {
  7312. var ignored = ['offline', 'unavailable'];
  7313. if (_converse.show_only_online_users) {
  7314. ignored = _.union(ignored, ['dnd', 'xa', 'away']);
  7315. }
  7316. return _.sum(this.models.filter(function (model) {
  7317. return !_.includes(ignored, model.get('chat_status'));
  7318. }));
  7319. },
  7320. onRosterPush: function onRosterPush(iq) {
  7321. /* Handle roster updates from the XMPP server.
  7322. * See: https://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push
  7323. *
  7324. * Parameters:
  7325. * (XMLElement) IQ - The IQ stanza received from the XMPP server.
  7326. */
  7327. var id = iq.getAttribute('id');
  7328. var from = iq.getAttribute('from');
  7329. if (from && from !== "" && Strophe.getBareJidFromJid(from) !== _converse.bare_jid) {
  7330. // Receiving client MUST ignore stanza unless it has no from or from = user's bare JID.
  7331. // XXX: Some naughty servers apparently send from a full
  7332. // JID so we need to explicitly compare bare jids here.
  7333. // https://github.com/jcbrand/converse.js/issues/493
  7334. _converse.connection.send($iq({
  7335. type: 'error',
  7336. id: id,
  7337. from: _converse.connection.jid
  7338. }).c('error', {
  7339. 'type': 'cancel'
  7340. }).c('service-unavailable', {
  7341. 'xmlns': Strophe.NS.ROSTER
  7342. }));
  7343. return true;
  7344. }
  7345. _converse.connection.send($iq({
  7346. type: 'result',
  7347. id: id,
  7348. from: _converse.connection.jid
  7349. }));
  7350. var items = sizzle("query[xmlns=\"".concat(Strophe.NS.ROSTER, "\"] item"), iq);
  7351. _.each(items, this.updateContact.bind(this));
  7352. _converse.emit('rosterPush', iq);
  7353. return true;
  7354. },
  7355. fetchFromServer: function fetchFromServer() {
  7356. var _this6 = this;
  7357. /* Fetch the roster from the XMPP server */
  7358. return new Promise(function (resolve, reject) {
  7359. var iq = $iq({
  7360. 'type': 'get',
  7361. 'id': _converse.connection.getUniqueId('roster')
  7362. }).c('query', {
  7363. xmlns: Strophe.NS.ROSTER
  7364. });
  7365. var callback = _.flow(_this6.onReceivedFromServer.bind(_this6), resolve);
  7366. var errback = function errback(iq) {
  7367. var errmsg = "Error while trying to fetch roster from the server";
  7368. _converse.log(errmsg, Strophe.LogLevel.ERROR);
  7369. reject(new Error(errmsg));
  7370. };
  7371. return _converse.connection.sendIQ(iq, callback, errback);
  7372. });
  7373. },
  7374. onReceivedFromServer: function onReceivedFromServer(iq) {
  7375. /* An IQ stanza containing the roster has been received from
  7376. * the XMPP server.
  7377. */
  7378. var items = sizzle("query[xmlns=\"".concat(Strophe.NS.ROSTER, "\"] item"), iq);
  7379. _.each(items, this.updateContact.bind(this));
  7380. _converse.emit('roster', iq);
  7381. },
  7382. updateContact: function updateContact(item) {
  7383. /* Update or create RosterContact models based on items
  7384. * received in the IQ from the server.
  7385. */
  7386. var jid = item.getAttribute('jid');
  7387. if (this.isSelf(jid)) {
  7388. return;
  7389. }
  7390. var contact = this.get(jid),
  7391. subscription = item.getAttribute("subscription"),
  7392. ask = item.getAttribute("ask"),
  7393. groups = _.map(item.getElementsByTagName('group'), Strophe.getText);
  7394. if (!contact) {
  7395. if (subscription === "none" && ask === null || subscription === "remove") {
  7396. return; // We're lazy when adding contacts.
  7397. }
  7398. this.create({
  7399. ask: ask,
  7400. fullname: item.getAttribute("name") || jid,
  7401. groups: groups,
  7402. jid: jid,
  7403. subscription: subscription
  7404. }, {
  7405. sort: false
  7406. });
  7407. } else {
  7408. if (subscription === "remove") {
  7409. return contact.destroy(); // will trigger removeFromRoster
  7410. } // We only find out about requesting contacts via the
  7411. // presence handler, so if we receive a contact
  7412. // here, we know they aren't requesting anymore.
  7413. // see docs/DEVELOPER.rst
  7414. contact.save({
  7415. subscription: subscription,
  7416. ask: ask,
  7417. requesting: null,
  7418. groups: groups
  7419. });
  7420. }
  7421. },
  7422. createRequestingContact: function createRequestingContact(presence) {
  7423. /* Creates a Requesting Contact.
  7424. *
  7425. * Note: this method gets completely overridden by converse-vcard.js
  7426. */
  7427. var bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from')),
  7428. nick_el = presence.querySelector("nick[xmlns=\"".concat(Strophe.NS.NICK, "\"]"));
  7429. var user_data = {
  7430. jid: bare_jid,
  7431. subscription: 'none',
  7432. ask: null,
  7433. requesting: true,
  7434. fullname: nick_el && nick_el.textContent || bare_jid
  7435. };
  7436. this.create(user_data);
  7437. _converse.emit('contactRequest', user_data);
  7438. },
  7439. handleIncomingSubscription: function handleIncomingSubscription(presence) {
  7440. var jid = presence.getAttribute('from'),
  7441. bare_jid = Strophe.getBareJidFromJid(jid),
  7442. contact = this.get(bare_jid);
  7443. if (!_converse.allow_contact_requests) {
  7444. _converse.rejectPresenceSubscription(jid, __("This client does not allow presence subscriptions"));
  7445. }
  7446. if (_converse.auto_subscribe) {
  7447. if (!contact || contact.get('subscription') !== 'to') {
  7448. this.subscribeBack(bare_jid);
  7449. } else {
  7450. contact.authorize();
  7451. }
  7452. } else {
  7453. if (contact) {
  7454. if (contact.get('subscription') !== 'none') {
  7455. contact.authorize();
  7456. } else if (contact.get('ask') === "subscribe") {
  7457. contact.authorize();
  7458. }
  7459. } else {
  7460. this.createRequestingContact(presence);
  7461. }
  7462. }
  7463. },
  7464. presenceHandler: function presenceHandler(presence) {
  7465. var presence_type = presence.getAttribute('type');
  7466. if (presence_type === 'error') {
  7467. return true;
  7468. }
  7469. var jid = presence.getAttribute('from'),
  7470. bare_jid = Strophe.getBareJidFromJid(jid),
  7471. resource = Strophe.getResourceFromJid(jid),
  7472. chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
  7473. status_message = _.propertyOf(presence.querySelector('status'))('textContent'),
  7474. contact = this.get(bare_jid);
  7475. if (this.isSelf(bare_jid)) {
  7476. if (_converse.connection.jid !== jid && presence_type !== 'unavailable' && (_converse.synchronize_availability === true || _converse.synchronize_availability === resource)) {
  7477. // Another resource has changed its status and
  7478. // synchronize_availability option set to update,
  7479. // we'll update ours as well.
  7480. _converse.xmppstatus.save({
  7481. 'status': chat_status
  7482. });
  7483. if (status_message) {
  7484. _converse.xmppstatus.save({
  7485. 'status_message': status_message
  7486. });
  7487. }
  7488. }
  7489. return;
  7490. } else if (sizzle("query[xmlns=\"".concat(Strophe.NS.MUC, "\"]"), presence).length) {
  7491. return; // Ignore MUC
  7492. }
  7493. if (contact && status_message !== contact.get('status')) {
  7494. contact.save({
  7495. 'status': status_message
  7496. });
  7497. }
  7498. if (presence_type === 'subscribed' && contact) {
  7499. contact.ackSubscribe();
  7500. } else if (presence_type === 'unsubscribed' && contact) {
  7501. contact.ackUnsubscribe();
  7502. } else if (presence_type === 'unsubscribe') {
  7503. return;
  7504. } else if (presence_type === 'subscribe') {
  7505. this.handleIncomingSubscription(presence);
  7506. } else if (presence_type === 'unavailable' && contact) {
  7507. contact.removeResource(resource);
  7508. } else if (contact) {
  7509. // presence_type is undefined
  7510. contact.addResource(presence);
  7511. }
  7512. }
  7513. });
  7514. this.RosterGroup = Backbone.Model.extend({
  7515. initialize: function initialize(attributes) {
  7516. this.set(_.assignIn({
  7517. description: __('Click to hide these contacts'),
  7518. state: _converse.OPENED
  7519. }, attributes)); // Collection of contacts belonging to this group.
  7520. this.contacts = new _converse.RosterContacts();
  7521. }
  7522. });
  7523. this.RosterGroups = Backbone.Collection.extend({
  7524. model: _converse.RosterGroup,
  7525. fetchRosterGroups: function fetchRosterGroups() {
  7526. var _this7 = this;
  7527. /* Fetches all the roster groups from sessionStorage.
  7528. *
  7529. * Returns a promise which resolves once the groups have been
  7530. * returned.
  7531. */
  7532. return new Promise(function (resolve, reject) {
  7533. _this7.fetch({
  7534. silent: true,
  7535. // We need to first have all groups before
  7536. // we can start positioning them, so we set
  7537. // 'silent' to true.
  7538. success: resolve
  7539. });
  7540. });
  7541. }
  7542. });
  7543. this.ConnectionFeedback = Backbone.Model.extend({
  7544. defaults: {
  7545. 'connection_status': Strophe.Status.DISCONNECTED,
  7546. 'message': ''
  7547. },
  7548. initialize: function initialize() {
  7549. this.on('change', function () {
  7550. _converse.emit('connfeedback', _converse.connfeedback);
  7551. });
  7552. }
  7553. });
  7554. this.connfeedback = new this.ConnectionFeedback();
  7555. this.XMPPStatus = Backbone.Model.extend({
  7556. defaults: function defaults() {
  7557. return {
  7558. "status": _converse.default_state,
  7559. "jid": _converse.bare_jid,
  7560. "vcard_updated": null
  7561. };
  7562. },
  7563. initialize: function initialize() {
  7564. var _this8 = this;
  7565. this.on('change:status', function (item) {
  7566. var status = _this8.get('status');
  7567. _this8.sendPresence(status);
  7568. _converse.emit('statusChanged', status);
  7569. });
  7570. this.on('change:status_message', function () {
  7571. var status_message = _this8.get('status_message');
  7572. _this8.sendPresence(_this8.get('status'), status_message);
  7573. _converse.emit('statusMessageChanged', status_message);
  7574. });
  7575. },
  7576. constructPresence: function constructPresence(type, status_message) {
  7577. var presence;
  7578. type = _.isString(type) ? type : this.get('status') || _converse.default_state;
  7579. status_message = _.isString(status_message) ? status_message : this.get('status_message'); // Most of these presence types are actually not explicitly sent,
  7580. // but I add all of them here for reference and future proofing.
  7581. if (type === 'unavailable' || type === 'probe' || type === 'error' || type === 'unsubscribe' || type === 'unsubscribed' || type === 'subscribe' || type === 'subscribed') {
  7582. presence = $pres({
  7583. 'type': type
  7584. });
  7585. } else if (type === 'offline') {
  7586. presence = $pres({
  7587. 'type': 'unavailable'
  7588. });
  7589. } else if (type === 'online') {
  7590. presence = $pres();
  7591. } else {
  7592. presence = $pres().c('show').t(type).up();
  7593. }
  7594. if (status_message) {
  7595. presence.c('status').t(status_message).up();
  7596. }
  7597. presence.c('priority').t(_.isNaN(Number(_converse.priority)) ? 0 : _converse.priority);
  7598. return presence;
  7599. },
  7600. sendPresence: function sendPresence(type, status_message) {
  7601. _converse.connection.send(this.constructPresence(type, status_message));
  7602. }
  7603. });
  7604. this.setUpXMLLogging = function () {
  7605. Strophe.log = function (level, msg) {
  7606. _converse.log(msg, level);
  7607. };
  7608. if (this.debug) {
  7609. this.connection.xmlInput = function (body) {
  7610. _converse.log(body.outerHTML, Strophe.LogLevel.DEBUG, 'color: darkgoldenrod');
  7611. };
  7612. this.connection.xmlOutput = function (body) {
  7613. _converse.log(body.outerHTML, Strophe.LogLevel.DEBUG, 'color: darkcyan');
  7614. };
  7615. }
  7616. };
  7617. this.fetchLoginCredentials = function () {
  7618. return new Promise(function (resolve, reject) {
  7619. var xhr = new XMLHttpRequest();
  7620. xhr.open('GET', _converse.credentials_url, true);
  7621. xhr.setRequestHeader('Accept', "application/json, text/javascript");
  7622. xhr.onload = function () {
  7623. if (xhr.status >= 200 && xhr.status < 400) {
  7624. var data = JSON.parse(xhr.responseText);
  7625. resolve({
  7626. 'jid': data.jid,
  7627. 'password': data.password
  7628. });
  7629. } else {
  7630. xhr.onerror();
  7631. }
  7632. };
  7633. xhr.onerror = function () {
  7634. delete _converse.connection;
  7635. _converse.emit('noResumeableSession', this);
  7636. reject(xhr.responseText);
  7637. };
  7638. xhr.send();
  7639. });
  7640. };
  7641. this.startNewBOSHSession = function () {
  7642. var xhr = new XMLHttpRequest();
  7643. xhr.open('GET', _converse.prebind_url, true);
  7644. xhr.setRequestHeader('Accept', "application/json, text/javascript");
  7645. xhr.onload = function () {
  7646. if (xhr.status >= 200 && xhr.status < 400) {
  7647. var data = JSON.parse(xhr.responseText);
  7648. _converse.connection.attach(data.jid, data.sid, data.rid, _converse.onConnectStatusChanged);
  7649. } else {
  7650. xhr.onerror();
  7651. }
  7652. };
  7653. xhr.onerror = function () {
  7654. delete _converse.connection;
  7655. _converse.emit('noResumeableSession', this);
  7656. };
  7657. xhr.send();
  7658. };
  7659. this.restoreBOSHSession = function (jid_is_required) {
  7660. /* Tries to restore a cached BOSH session. */
  7661. if (!this.jid) {
  7662. var msg = "restoreBOSHSession: tried to restore a \"keepalive\" session " + "but we don't have the JID for the user!";
  7663. if (jid_is_required) {
  7664. throw new Error(msg);
  7665. } else {
  7666. _converse.log(msg);
  7667. }
  7668. }
  7669. try {
  7670. this.connection.restore(this.jid, this.onConnectStatusChanged);
  7671. return true;
  7672. } catch (e) {
  7673. _converse.log("Could not restore session for jid: " + this.jid + " Error message: " + e.message, Strophe.LogLevel.WARN);
  7674. this.clearSession(); // If there's a roster, we want to clear it (see #555)
  7675. return false;
  7676. }
  7677. };
  7678. this.attemptPreboundSession = function (reconnecting) {
  7679. /* Handle session resumption or initialization when prebind is
  7680. * being used.
  7681. */
  7682. if (!reconnecting) {
  7683. if (this.keepalive && this.restoreBOSHSession(true)) {
  7684. return;
  7685. } // No keepalive, or session resumption has failed.
  7686. if (this.jid && this.sid && this.rid) {
  7687. return this.connection.attach(this.jid, this.sid, this.rid, this.onConnectStatusChanged);
  7688. }
  7689. }
  7690. if (this.prebind_url) {
  7691. return this.startNewBOSHSession();
  7692. } else {
  7693. throw new Error("attemptPreboundSession: If you use prebind and not keepalive, " + "then you MUST supply JID, RID and SID values or a prebind_url.");
  7694. }
  7695. };
  7696. this.attemptNonPreboundSession = function (credentials, reconnecting) {
  7697. /* Handle session resumption or initialization when prebind is not being used.
  7698. *
  7699. * Two potential options exist and are handled in this method:
  7700. * 1. keepalive
  7701. * 2. auto_login
  7702. */
  7703. if (!reconnecting && this.keepalive && this.restoreBOSHSession()) {
  7704. return;
  7705. }
  7706. if (credentials) {
  7707. // When credentials are passed in, they override prebinding
  7708. // or credentials fetching via HTTP
  7709. this.autoLogin(credentials);
  7710. } else if (this.auto_login) {
  7711. if (this.credentials_url) {
  7712. this.fetchLoginCredentials().then(this.autoLogin.bind(this), this.autoLogin.bind(this));
  7713. } else if (!this.jid) {
  7714. throw new Error("attemptNonPreboundSession: If you use auto_login, " + "you also need to give either a jid value (and if " + "applicable a password) or you need to pass in a URL " + "from where the username and password can be fetched " + "(via credentials_url).");
  7715. } else {
  7716. this.autoLogin(); // Probably ANONYMOUS login
  7717. }
  7718. } else if (reconnecting) {
  7719. this.autoLogin();
  7720. }
  7721. };
  7722. this.autoLogin = function (credentials) {
  7723. if (credentials) {
  7724. // If passed in, the credentials come from credentials_url,
  7725. // so we set them on the converse object.
  7726. this.jid = credentials.jid;
  7727. }
  7728. if (this.authentication === _converse.ANONYMOUS) {
  7729. if (!this.jid) {
  7730. throw new Error("Config Error: when using anonymous login " + "you need to provide the server's domain via the 'jid' option. " + "Either when calling converse.initialize, or when calling " + "_converse.api.user.login.");
  7731. }
  7732. if (!this.connection.reconnecting) {
  7733. this.connection.reset();
  7734. }
  7735. this.connection.connect(this.jid.toLowerCase(), null, this.onConnectStatusChanged);
  7736. } else if (this.authentication === _converse.LOGIN) {
  7737. var password = _.isNil(credentials) ? _converse.connection.pass || this.password : credentials.password;
  7738. if (!password) {
  7739. if (this.auto_login) {
  7740. throw new Error("initConnection: If you use auto_login and " + "authentication='login' then you also need to provide a password.");
  7741. }
  7742. _converse.setDisconnectionCause(Strophe.Status.AUTHFAIL, undefined, true);
  7743. _converse.disconnect();
  7744. return;
  7745. }
  7746. var resource = Strophe.getResourceFromJid(this.jid);
  7747. if (!resource) {
  7748. this.jid = this.jid.toLowerCase() + _converse.generateResource();
  7749. } else {
  7750. this.jid = Strophe.getBareJidFromJid(this.jid).toLowerCase() + '/' + resource;
  7751. }
  7752. if (!this.connection.reconnecting) {
  7753. this.connection.reset();
  7754. }
  7755. this.connection.connect(this.jid, password, this.onConnectStatusChanged);
  7756. }
  7757. };
  7758. this.logIn = function (credentials, reconnecting) {
  7759. // We now try to resume or automatically set up a new session.
  7760. // Otherwise the user will be shown a login form.
  7761. if (this.authentication === _converse.PREBIND) {
  7762. this.attemptPreboundSession(reconnecting);
  7763. } else {
  7764. this.attemptNonPreboundSession(credentials, reconnecting);
  7765. }
  7766. };
  7767. this.initConnection = function () {
  7768. if (!this.connection) {
  7769. if (!this.bosh_service_url && !this.websocket_url) {
  7770. throw new Error("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.");
  7771. }
  7772. if (('WebSocket' in window || 'MozWebSocket' in window) && this.websocket_url) {
  7773. this.connection = new Strophe.Connection(this.websocket_url, this.connection_options);
  7774. } else if (this.bosh_service_url) {
  7775. this.connection = new Strophe.Connection(this.bosh_service_url, _.assignIn(this.connection_options, {
  7776. 'keepalive': this.keepalive
  7777. }));
  7778. } else {
  7779. throw new Error("initConnection: this browser does not support websockets and bosh_service_url wasn't specified.");
  7780. }
  7781. }
  7782. _converse.emit('connectionInitialized');
  7783. };
  7784. this._tearDown = function () {
  7785. /* Remove those views which are only allowed with a valid
  7786. * connection.
  7787. */
  7788. _converse.emit('beforeTearDown');
  7789. _converse.unregisterPresenceHandler();
  7790. if (_converse.roster) {
  7791. _converse.roster.off().reset(); // Removes roster contacts
  7792. }
  7793. if (!_.isUndefined(_converse.session)) {
  7794. _converse.session.destroy();
  7795. }
  7796. window.removeEventListener('click', _converse.onUserActivity);
  7797. window.removeEventListener('focus', _converse.onUserActivity);
  7798. window.removeEventListener('keypress', _converse.onUserActivity);
  7799. window.removeEventListener('mousemove', _converse.onUserActivity);
  7800. window.removeEventListener(unloadevent, _converse.onUserActivity);
  7801. window.clearInterval(_converse.everySecondTrigger);
  7802. _converse.emit('afterTearDown');
  7803. return _converse;
  7804. };
  7805. this.initPlugins = function () {
  7806. // If initialize gets called a second time (e.g. during tests), then we
  7807. // need to re-apply all plugins (for a new converse instance), and we
  7808. // therefore need to clear this array that prevents plugins from being
  7809. // initialized twice.
  7810. // If initialize is called for the first time, then this array is empty
  7811. // in any case.
  7812. _converse.pluggable.initialized_plugins = [];
  7813. var whitelist = _converse.core_plugins.concat(_converse.whitelisted_plugins);
  7814. if (_converse.view_mode === 'embedded') {
  7815. _.forEach([// eslint-disable-line lodash/prefer-map
  7816. "converse-bookmarks", "converse-controlbox", "converse-dragresize", "converse-headline", "converse-minimize", "converse-otr", "converse-register", "converse-vcard"], function (name) {
  7817. _converse.blacklisted_plugins.push(name);
  7818. });
  7819. }
  7820. _converse.pluggable.initializePlugins({
  7821. 'updateSettings': function updateSettings() {
  7822. _converse.log("(DEPRECATION) " + "The `updateSettings` method has been deprecated. " + "Please use `_converse.api.settings.update` instead.", Strophe.LogLevel.WARN);
  7823. _converse.api.settings.update.apply(_converse, arguments);
  7824. },
  7825. '_converse': _converse
  7826. }, whitelist, _converse.blacklisted_plugins);
  7827. _converse.emit('pluginsInitialized');
  7828. }; // Initialization
  7829. // --------------
  7830. // This is the end of the initialize method.
  7831. if (settings.connection) {
  7832. this.connection = settings.connection;
  7833. }
  7834. function finishInitialization() {
  7835. _converse.initPlugins();
  7836. _converse.initConnection();
  7837. _converse.setUpXMLLogging();
  7838. _converse.logIn();
  7839. _converse.registerGlobalEventHandlers();
  7840. if (!Backbone.history.started) {
  7841. Backbone.history.start();
  7842. }
  7843. }
  7844. if (!_.isUndefined(_converse.connection) && _converse.connection.service === 'jasmine tests') {
  7845. finishInitialization();
  7846. return _converse;
  7847. } else if (_.isUndefined(i18n)) {
  7848. finishInitialization();
  7849. } else {
  7850. i18n.fetchTranslations(_converse.locale, _converse.locales, u.interpolate(_converse.locales_url, {
  7851. 'locale': _converse.locale
  7852. })).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(finishInitialization).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  7853. }
  7854. return init_promise;
  7855. }; // API methods only available to plugins
  7856. _converse.api = {
  7857. 'connection': {
  7858. 'connected': function connected() {
  7859. return _converse.connection && _converse.connection.connected || false;
  7860. },
  7861. 'disconnect': function disconnect() {
  7862. _converse.connection.disconnect();
  7863. }
  7864. },
  7865. 'emit': function emit() {
  7866. _converse.emit.apply(_converse, arguments);
  7867. },
  7868. 'user': {
  7869. 'jid': function jid() {
  7870. return _converse.connection.jid;
  7871. },
  7872. 'login': function login(credentials) {
  7873. _converse.initConnection();
  7874. _converse.logIn(credentials);
  7875. },
  7876. 'logout': function logout() {
  7877. _converse.logOut();
  7878. },
  7879. 'status': {
  7880. 'get': function get() {
  7881. return _converse.xmppstatus.get('status');
  7882. },
  7883. 'set': function set(value, message) {
  7884. var data = {
  7885. 'status': value
  7886. };
  7887. if (!_.includes(_.keys(_converse.STATUS_WEIGHTS), value)) {
  7888. throw new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1');
  7889. }
  7890. if (_.isString(message)) {
  7891. data.status_message = message;
  7892. }
  7893. _converse.xmppstatus.sendPresence(value);
  7894. _converse.xmppstatus.save(data);
  7895. },
  7896. 'message': {
  7897. 'get': function get() {
  7898. return _converse.xmppstatus.get('status_message');
  7899. },
  7900. 'set': function set(stat) {
  7901. _converse.xmppstatus.save({
  7902. 'status_message': stat
  7903. });
  7904. }
  7905. }
  7906. }
  7907. },
  7908. 'settings': {
  7909. 'update': function update(settings) {
  7910. u.merge(_converse.default_settings, settings);
  7911. u.merge(_converse, settings);
  7912. u.applyUserSettings(_converse, settings, _converse.user_settings);
  7913. },
  7914. 'get': function get(key) {
  7915. if (_.includes(_.keys(_converse.default_settings), key)) {
  7916. return _converse[key];
  7917. }
  7918. },
  7919. 'set': function set(key, val) {
  7920. var o = {};
  7921. if (_.isObject(key)) {
  7922. _.assignIn(_converse, _.pick(key, _.keys(_converse.default_settings)));
  7923. } else if (_.isString("string")) {
  7924. o[key] = val;
  7925. _.assignIn(_converse, _.pick(o, _.keys(_converse.default_settings)));
  7926. }
  7927. }
  7928. },
  7929. 'promises': {
  7930. 'add': function add(promises) {
  7931. promises = _.isArray(promises) ? promises : [promises];
  7932. _.each(promises, addPromise);
  7933. }
  7934. },
  7935. 'contacts': {
  7936. 'get': function get(jids) {
  7937. var _getter = function _getter(jid) {
  7938. return _converse.roster.get(Strophe.getBareJidFromJid(jid)) || null;
  7939. };
  7940. if (_.isUndefined(jids)) {
  7941. jids = _converse.roster.pluck('jid');
  7942. } else if (_.isString(jids)) {
  7943. return _getter(jids);
  7944. }
  7945. return _.map(jids, _getter);
  7946. },
  7947. 'add': function add(jid, name) {
  7948. if (!_.isString(jid) || !_.includes(jid, '@')) {
  7949. throw new TypeError('contacts.add: invalid jid');
  7950. }
  7951. _converse.roster.addAndSubscribe(jid, _.isEmpty(name) ? jid : name);
  7952. }
  7953. },
  7954. 'tokens': {
  7955. 'get': function get(id) {
  7956. if (!_converse.expose_rid_and_sid || _.isUndefined(_converse.connection)) {
  7957. return null;
  7958. }
  7959. if (id.toLowerCase() === 'rid') {
  7960. return _converse.connection.rid || _converse.connection._proto.rid;
  7961. } else if (id.toLowerCase() === 'sid') {
  7962. return _converse.connection.sid || _converse.connection._proto.sid;
  7963. }
  7964. }
  7965. },
  7966. 'listen': {
  7967. 'once': _converse.once.bind(_converse),
  7968. 'on': _converse.on.bind(_converse),
  7969. 'not': _converse.off.bind(_converse),
  7970. 'stanza': function stanza(name, options, handler) {
  7971. if (_.isFunction(options)) {
  7972. handler = options;
  7973. options = {};
  7974. } else {
  7975. options = options || {};
  7976. }
  7977. _converse.connection.addHandler(handler, options.ns, name, options.type, options.id, options.from, options);
  7978. }
  7979. },
  7980. 'waitUntil': function waitUntil(name) {
  7981. var promise = _converse.promises[name];
  7982. if (_.isUndefined(promise)) {
  7983. return null;
  7984. }
  7985. return promise;
  7986. },
  7987. 'send': function send(stanza) {
  7988. _converse.connection.send(stanza);
  7989. }
  7990. }; // The public API
  7991. window.converse = {
  7992. 'initialize': function initialize(settings, callback) {
  7993. return _converse.initialize(settings, callback);
  7994. },
  7995. 'plugins': {
  7996. 'add': function add(name, plugin) {
  7997. plugin.__name__ = name;
  7998. if (!_.isUndefined(_converse.pluggable.plugins[name])) {
  7999. throw new TypeError("Error: plugin with name \"".concat(name, "\" has already been ") + 'registered!');
  8000. } else {
  8001. _converse.pluggable.plugins[name] = plugin;
  8002. }
  8003. }
  8004. },
  8005. 'env': {
  8006. '$build': $build,
  8007. '$iq': $iq,
  8008. '$msg': $msg,
  8009. '$pres': $pres,
  8010. 'Backbone': Backbone,
  8011. 'Promise': Promise,
  8012. 'Strophe': Strophe,
  8013. '_': _,
  8014. 'f': f,
  8015. 'b64_sha1': b64_sha1,
  8016. 'moment': moment,
  8017. 'sizzle': sizzle,
  8018. 'utils': u
  8019. }
  8020. };
  8021. window.dispatchEvent(new CustomEvent('converse-loaded'));
  8022. return window.converse;
  8023. });
  8024. //# sourceMappingURL=converse-core.js.map;
  8025. // Native Javascript for Bootstrap 4 v2.0.21 | © dnp_theme | MIT-License
  8026. (function (root, factory) {
  8027. if (typeof define === 'function' && define.amd) {
  8028. // AMD support:
  8029. define('bootstrap',[], factory);
  8030. } else if (typeof module === 'object' && module.exports) {
  8031. // CommonJS-like:
  8032. module.exports = factory();
  8033. } else {
  8034. // Browser globals (root is window)
  8035. var bsn = factory();
  8036. root.Alert = bsn.Alert;
  8037. root.Button = bsn.Button;
  8038. root.Carousel = bsn.Carousel;
  8039. root.Collapse = bsn.Collapse;
  8040. root.Dropdown = bsn.Dropdown;
  8041. root.Modal = bsn.Modal;
  8042. root.Popover = bsn.Popover;
  8043. root.ScrollSpy = bsn.ScrollSpy;
  8044. root.Tab = bsn.Tab;
  8045. root.Tooltip = bsn.Tooltip;
  8046. }
  8047. }(this, function () {
  8048. /* Native Javascript for Bootstrap 4 | Internal Utility Functions
  8049. ----------------------------------------------------------------*/
  8050. "use strict";
  8051. // globals
  8052. var globalObject = typeof global !== 'undefined' ? global : this||window,
  8053. DOC = document, HTML = DOC.documentElement, body = 'body', // allow the library to be used in <head>
  8054. // Native Javascript for Bootstrap Global Object
  8055. BSN = globalObject.BSN = {},
  8056. supports = BSN.supports = [],
  8057. // function toggle attributes
  8058. dataToggle = 'data-toggle',
  8059. dataDismiss = 'data-dismiss',
  8060. dataSpy = 'data-spy',
  8061. dataRide = 'data-ride',
  8062. // components
  8063. stringAlert = 'Alert',
  8064. stringButton = 'Button',
  8065. stringCarousel = 'Carousel',
  8066. stringCollapse = 'Collapse',
  8067. stringDropdown = 'Dropdown',
  8068. stringModal = 'Modal',
  8069. stringPopover = 'Popover',
  8070. stringScrollSpy = 'ScrollSpy',
  8071. stringTab = 'Tab',
  8072. stringTooltip = 'Tooltip',
  8073. // options DATA API
  8074. databackdrop = 'data-backdrop',
  8075. dataKeyboard = 'data-keyboard',
  8076. dataTarget = 'data-target',
  8077. dataInterval = 'data-interval',
  8078. dataHeight = 'data-height',
  8079. dataPause = 'data-pause',
  8080. dataTitle = 'data-title',
  8081. dataOriginalTitle = 'data-original-title',
  8082. dataOriginalText = 'data-original-text',
  8083. dataDismissible = 'data-dismissible',
  8084. dataTrigger = 'data-trigger',
  8085. dataAnimation = 'data-animation',
  8086. dataContainer = 'data-container',
  8087. dataPlacement = 'data-placement',
  8088. dataDelay = 'data-delay',
  8089. dataOffsetTop = 'data-offset-top',
  8090. dataOffsetBottom = 'data-offset-bottom',
  8091. // option keys
  8092. backdrop = 'backdrop', keyboard = 'keyboard', delay = 'delay',
  8093. content = 'content', target = 'target',
  8094. interval = 'interval', pause = 'pause', animation = 'animation',
  8095. placement = 'placement', container = 'container',
  8096. // box model
  8097. offsetTop = 'offsetTop', offsetBottom = 'offsetBottom',
  8098. offsetLeft = 'offsetLeft',
  8099. scrollTop = 'scrollTop', scrollLeft = 'scrollLeft',
  8100. clientWidth = 'clientWidth', clientHeight = 'clientHeight',
  8101. offsetWidth = 'offsetWidth', offsetHeight = 'offsetHeight',
  8102. innerWidth = 'innerWidth', innerHeight = 'innerHeight',
  8103. scrollHeight = 'scrollHeight', height = 'height',
  8104. // aria
  8105. ariaExpanded = 'aria-expanded',
  8106. ariaHidden = 'aria-hidden',
  8107. // event names
  8108. clickEvent = 'click',
  8109. hoverEvent = 'hover',
  8110. keydownEvent = 'keydown',
  8111. keyupEvent = 'keyup',
  8112. resizeEvent = 'resize',
  8113. scrollEvent = 'scroll',
  8114. // originalEvents
  8115. showEvent = 'show',
  8116. shownEvent = 'shown',
  8117. hideEvent = 'hide',
  8118. hiddenEvent = 'hidden',
  8119. closeEvent = 'close',
  8120. closedEvent = 'closed',
  8121. slidEvent = 'slid',
  8122. slideEvent = 'slide',
  8123. changeEvent = 'change',
  8124. // other
  8125. getAttribute = 'getAttribute',
  8126. setAttribute = 'setAttribute',
  8127. hasAttribute = 'hasAttribute',
  8128. createElement = 'createElement',
  8129. appendChild = 'appendChild',
  8130. innerHTML = 'innerHTML',
  8131. getElementsByTagName = 'getElementsByTagName',
  8132. preventDefault = 'preventDefault',
  8133. getBoundingClientRect = 'getBoundingClientRect',
  8134. querySelectorAll = 'querySelectorAll',
  8135. getElementsByCLASSNAME = 'getElementsByClassName',
  8136. indexOf = 'indexOf',
  8137. parentNode = 'parentNode',
  8138. length = 'length',
  8139. toLowerCase = 'toLowerCase',
  8140. Transition = 'Transition',
  8141. Webkit = 'Webkit',
  8142. style = 'style',
  8143. push = 'push',
  8144. tabindex = 'tabindex',
  8145. contains = 'contains',
  8146. active = 'active',
  8147. showClass = 'show',
  8148. collapsing = 'collapsing',
  8149. disabled = 'disabled',
  8150. loading = 'loading',
  8151. left = 'left',
  8152. right = 'right',
  8153. top = 'top',
  8154. bottom = 'bottom',
  8155. // tooltip / popover
  8156. mouseHover = ('onmouseleave' in DOC) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ],
  8157. tipPositions = /\b(top|bottom|left|right)+/,
  8158. // modal
  8159. modalOverlay = 0,
  8160. fixedTop = 'fixed-top',
  8161. fixedBottom = 'fixed-bottom',
  8162. // transitionEnd since 2.0.4
  8163. supportTransitions = Webkit+Transition in HTML[style] || Transition[toLowerCase]() in HTML[style],
  8164. transitionEndEvent = Webkit+Transition in HTML[style] ? Webkit[toLowerCase]()+Transition+'End' : Transition[toLowerCase]()+'end',
  8165. // set new focus element since 2.0.3
  8166. setFocus = function(element){
  8167. element.focus ? element.focus() : element.setActive();
  8168. },
  8169. // class manipulation, since 2.0.0 requires polyfill.js
  8170. addClass = function(element,classNAME) {
  8171. element.classList.add(classNAME);
  8172. },
  8173. removeClass = function(element,classNAME) {
  8174. element.classList.remove(classNAME);
  8175. },
  8176. hasClass = function(element,classNAME){ // since 2.0.0
  8177. return element.classList[contains](classNAME);
  8178. },
  8179. // selection methods
  8180. getElementsByClassName = function(element,classNAME) { // returns Array
  8181. return [].slice.call(element[getElementsByCLASSNAME]( classNAME ));
  8182. },
  8183. queryElement = function (selector, parent) {
  8184. var lookUp = parent ? parent : DOC;
  8185. return typeof selector === 'object' ? selector : lookUp.querySelector(selector);
  8186. },
  8187. getClosest = function (element, selector) { //element is the element and selector is for the closest parent element to find
  8188. // source http://gomakethings.com/climbing-up-and-down-the-dom-tree-with-vanilla-javascript/
  8189. var firstChar = selector.charAt(0), selectorSubstring = selector.substr(1);
  8190. if ( firstChar === '.' ) {// If selector is a class
  8191. for ( ; element && element !== DOC; element = element[parentNode] ) { // Get closest match
  8192. if ( queryElement(selector,element[parentNode]) !== null && hasClass(element,selectorSubstring) ) { return element; }
  8193. }
  8194. } else if ( firstChar === '#' ) { // If selector is an ID
  8195. for ( ; element && element !== DOC; element = element[parentNode] ) { // Get closest match
  8196. if ( element.id === selectorSubstring ) { return element; }
  8197. }
  8198. }
  8199. return false;
  8200. },
  8201. // event attach jQuery style / trigger since 1.2.0
  8202. on = function (element, event, handler) {
  8203. element.addEventListener(event, handler, false);
  8204. },
  8205. off = function(element, event, handler) {
  8206. element.removeEventListener(event, handler, false);
  8207. },
  8208. one = function (element, event, handler) { // one since 2.0.4
  8209. on(element, event, function handlerWrapper(e){
  8210. handler(e);
  8211. off(element, event, handlerWrapper);
  8212. });
  8213. },
  8214. emulateTransitionEnd = function(element,handler){ // emulateTransitionEnd since 2.0.4
  8215. if (supportTransitions) { one(element, transitionEndEvent, function(e){ handler(e); }); }
  8216. else { handler(); }
  8217. },
  8218. bootstrapCustomEvent = function (eventName, componentName, related) {
  8219. var OriginalCustomEvent = new CustomEvent( eventName + '.bs.' + componentName);
  8220. OriginalCustomEvent.relatedTarget = related;
  8221. this.dispatchEvent(OriginalCustomEvent);
  8222. },
  8223. // tooltip / popover stuff
  8224. getScroll = function() { // also Affix and ScrollSpy uses it
  8225. return {
  8226. y : globalObject.pageYOffset || HTML[scrollTop],
  8227. x : globalObject.pageXOffset || HTML[scrollLeft]
  8228. }
  8229. },
  8230. styleTip = function(link,element,position,parent) { // both popovers and tooltips (target,tooltip,placement,elementToAppendTo)
  8231. var elementDimensions = { w : element[offsetWidth], h: element[offsetHeight] },
  8232. windowWidth = (HTML[clientWidth] || DOC[body][clientWidth]),
  8233. windowHeight = (HTML[clientHeight] || DOC[body][clientHeight]),
  8234. rect = link[getBoundingClientRect](),
  8235. scroll = parent === DOC[body] ? getScroll() : { x: parent[offsetLeft] + parent[scrollLeft], y: parent[offsetTop] + parent[scrollTop] },
  8236. linkDimensions = { w: rect[right] - rect[left], h: rect[bottom] - rect[top] },
  8237. arrow = queryElement('.arrow',element),
  8238. arrowWidth = arrow[offsetWidth], isPopover = hasClass(element,'popover'),
  8239. topPosition, leftPosition, arrowTop, arrowLeft,
  8240. halfTopExceed = rect[top] + linkDimensions.h/2 - elementDimensions.h/2 < 0,
  8241. halfLeftExceed = rect[left] + linkDimensions.w/2 - elementDimensions.w/2 < 0,
  8242. halfRightExceed = rect[left] + elementDimensions.w/2 + linkDimensions.w/2 >= windowWidth,
  8243. halfBottomExceed = rect[top] + elementDimensions.h/2 + linkDimensions.h/2 >= windowHeight,
  8244. topExceed = rect[top] - elementDimensions.h < 0,
  8245. leftExceed = rect[left] - elementDimensions.w < 0,
  8246. bottomExceed = rect[top] + elementDimensions.h + linkDimensions.h >= windowHeight,
  8247. rightExceed = rect[left] + elementDimensions.w + linkDimensions.w >= windowWidth;
  8248. // recompute position
  8249. position = (position === left || position === right) && leftExceed && rightExceed ? top : position; // first, when both left and right limits are exceeded, we fall back to top|bottom
  8250. position = position === top && topExceed ? bottom : position;
  8251. position = position === bottom && bottomExceed ? top : position;
  8252. position = position === left && leftExceed ? right : position;
  8253. position = position === right && rightExceed ? left : position;
  8254. // apply styling to tooltip or popover
  8255. if ( position === left || position === right ) { // secondary|side positions
  8256. if ( position === left ) { // LEFT
  8257. leftPosition = rect[left] + scroll.x - elementDimensions.w;
  8258. } else { // RIGHT
  8259. leftPosition = rect[left] + scroll.x + linkDimensions.w;
  8260. }
  8261. // adjust top and arrow
  8262. if (halfTopExceed) {
  8263. topPosition = rect[top] + scroll.y;
  8264. arrowTop = linkDimensions.h/2;
  8265. } else if (halfBottomExceed) {
  8266. topPosition = rect[top] + scroll.y - elementDimensions.h + linkDimensions.h;
  8267. arrowTop = elementDimensions.h - linkDimensions.h/2;
  8268. } else {
  8269. topPosition = rect[top] + scroll.y - elementDimensions.h/2 + linkDimensions.h/2;
  8270. arrowTop = elementDimensions.h/2;
  8271. }
  8272. } else if ( position === top || position === bottom ) { // primary|vertical positions
  8273. if ( position === top) { // TOP
  8274. topPosition = rect[top] + scroll.y - elementDimensions.h;
  8275. } else { // BOTTOM
  8276. topPosition = rect[top] + scroll.y + linkDimensions.h;
  8277. }
  8278. // adjust left | right and also the arrow
  8279. if (halfLeftExceed) {
  8280. leftPosition = 0;
  8281. arrowLeft = rect[left] + linkDimensions.w/2;
  8282. } else if (halfRightExceed) {
  8283. leftPosition = windowWidth - elementDimensions.w*1.01;
  8284. arrowLeft = elementDimensions.w - ( windowWidth - rect[left] ) + linkDimensions.w/2;
  8285. } else {
  8286. leftPosition = rect[left] + scroll.x - elementDimensions.w/2 + linkDimensions.w/2;
  8287. arrowLeft = elementDimensions.w/2;
  8288. }
  8289. }
  8290. // fixing some CSS bug with Bootstrap 4 alpha
  8291. topPosition = position === top && isPopover ? topPosition - arrowWidth : topPosition;
  8292. leftPosition = position === left && isPopover ? leftPosition - arrowWidth : leftPosition;
  8293. // apply style to tooltip/popover and it's arrow
  8294. element[style][top] = topPosition + 'px';
  8295. element[style][left] = leftPosition + 'px';
  8296. arrowTop && (arrow[style][top] = arrowTop + 'px');
  8297. arrowLeft && (arrow[style][left] = arrowLeft + 'px');
  8298. element.className[indexOf](position) === -1 && (element.className = element.className.replace(tipPositions,position));
  8299. };
  8300. BSN.version = '2.0.21';
  8301. /* Native Javascript for Bootstrap 4 | Alert
  8302. -------------------------------------------*/
  8303. // ALERT DEFINITION
  8304. // ================
  8305. var Alert = function( element ) {
  8306. // initialization element
  8307. element = queryElement(element);
  8308. // bind, target alert, duration and stuff
  8309. var self = this, component = 'alert',
  8310. alert = getClosest(element,'.'+component),
  8311. triggerHandler = function(){ hasClass(alert,'fade') ? emulateTransitionEnd(alert,transitionEndHandler) : transitionEndHandler(); },
  8312. // handlers
  8313. clickHandler = function(e){
  8314. alert = getClosest(e[target],'.'+component);
  8315. element = queryElement('['+dataDismiss+'="'+component+'"]',alert);
  8316. element && alert && (element === e[target] || element[contains](e[target])) && self.close();
  8317. },
  8318. transitionEndHandler = function(){
  8319. bootstrapCustomEvent.call(alert, closedEvent, component);
  8320. off(element, clickEvent, clickHandler); // detach it's listener
  8321. alert[parentNode].removeChild(alert);
  8322. };
  8323. // public method
  8324. this.close = function() {
  8325. if ( alert && element && hasClass(alert,showClass) ) {
  8326. bootstrapCustomEvent.call(alert, closeEvent, component);
  8327. removeClass(alert,showClass);
  8328. alert && triggerHandler();
  8329. }
  8330. };
  8331. // init
  8332. if ( !(stringAlert in element ) ) { // prevent adding event handlers twice
  8333. on(element, clickEvent, clickHandler);
  8334. }
  8335. element[stringAlert] = self;
  8336. };
  8337. // ALERT DATA API
  8338. // ==============
  8339. supports[push]([stringAlert, Alert, '['+dataDismiss+'="alert"]']);
  8340. /* Native Javascript for Bootstrap 4 | Button
  8341. ---------------------------------------------*/
  8342. // BUTTON DEFINITION
  8343. // ===================
  8344. var Button = function( element ) {
  8345. // initialization element
  8346. element = queryElement(element);
  8347. // constant
  8348. var toggled = false, // toggled makes sure to prevent triggering twice the change.bs.button events
  8349. // strings
  8350. component = 'button',
  8351. checked = 'checked',
  8352. reset = 'reset',
  8353. LABEL = 'LABEL',
  8354. INPUT = 'INPUT',
  8355. // private methods
  8356. keyHandler = function(e){
  8357. var key = e.which || e.keyCode;
  8358. key === 32 && e[target] === DOC.activeElement && toggle(e);
  8359. },
  8360. preventScroll = function(e){
  8361. var key = e.which || e.keyCode;
  8362. key === 32 && e[preventDefault]();
  8363. },
  8364. toggle = function(e) {
  8365. var label = e[target].tagName === LABEL ? e[target] : e[target][parentNode].tagName === LABEL ? e[target][parentNode] : null; // the .btn label
  8366. if ( !label ) return; //react if a label or its immediate child is clicked
  8367. var eventTarget = e[target], // the button itself, the target of the handler function
  8368. labels = getElementsByClassName(eventTarget[parentNode],'btn'), // all the button group buttons
  8369. input = label[getElementsByTagName](INPUT)[0];
  8370. if ( !input ) return; //return if no input found
  8371. // manage the dom manipulation
  8372. if ( input.type === 'checkbox' ) { //checkboxes
  8373. if ( !input[checked] ) {
  8374. addClass(label,active);
  8375. input[getAttribute](checked);
  8376. input[setAttribute](checked,checked);
  8377. input[checked] = true;
  8378. } else {
  8379. removeClass(label,active);
  8380. input[getAttribute](checked);
  8381. input.removeAttribute(checked);
  8382. input[checked] = false;
  8383. }
  8384. if (!toggled) { // prevent triggering the event twice
  8385. toggled = true;
  8386. bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
  8387. bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
  8388. }
  8389. }
  8390. if ( input.type === 'radio' && !toggled ) { // radio buttons
  8391. if ( !input[checked] ) { // don't trigger if already active
  8392. addClass(label,active);
  8393. input[setAttribute](checked,checked);
  8394. input[checked] = true;
  8395. bootstrapCustomEvent.call(input, changeEvent, component); //trigger the change for the input
  8396. bootstrapCustomEvent.call(element, changeEvent, component); //trigger the change for the btn-group
  8397. toggled = true;
  8398. for (var i = 0, ll = labels[length]; i<ll; i++) {
  8399. var otherLabel = labels[i], otherInput = otherLabel[getElementsByTagName](INPUT)[0];
  8400. if ( otherLabel !== label && hasClass(otherLabel,active) ) {
  8401. removeClass(otherLabel,active);
  8402. otherInput.removeAttribute(checked);
  8403. otherInput[checked] = false;
  8404. bootstrapCustomEvent.call(otherInput, changeEvent, component); // trigger the change
  8405. }
  8406. }
  8407. }
  8408. }
  8409. setTimeout( function() { toggled = false; }, 50 );
  8410. };
  8411. // init
  8412. if ( !( stringButton in element ) ) { // prevent adding event handlers twice
  8413. on( element, clickEvent, toggle );
  8414. queryElement('['+tabindex+']',element) && on( element, keyupEvent, keyHandler ),
  8415. on( element, keydownEvent, preventScroll );
  8416. }
  8417. // activate items on load
  8418. var labelsToACtivate = getElementsByClassName(element, 'btn'), lbll = labelsToACtivate[length];
  8419. for (var i=0; i<lbll; i++) {
  8420. !hasClass(labelsToACtivate[i],active) && queryElement('input:checked',labelsToACtivate[i])
  8421. && addClass(labelsToACtivate[i],active);
  8422. }
  8423. element[stringButton] = this;
  8424. };
  8425. // BUTTON DATA API
  8426. // =================
  8427. supports[push]( [ stringButton, Button, '['+dataToggle+'="buttons"]' ] );
  8428. /* Native Javascript for Bootstrap 4 | Carousel
  8429. ----------------------------------------------*/
  8430. // CAROUSEL DEFINITION
  8431. // ===================
  8432. var Carousel = function( element, options ) {
  8433. // initialization element
  8434. element = queryElement( element );
  8435. // set options
  8436. options = options || {};
  8437. // DATA API
  8438. var intervalAttribute = element[getAttribute](dataInterval),
  8439. intervalOption = options[interval],
  8440. intervalData = intervalAttribute === 'false' ? 0 : parseInt(intervalAttribute) || 5000, // bootstrap carousel default interval
  8441. pauseData = element[getAttribute](dataPause) === hoverEvent || false,
  8442. keyboardData = element[getAttribute](dataKeyboard) === 'true' || false,
  8443. // strings
  8444. component = 'carousel',
  8445. paused = 'paused',
  8446. direction = 'direction',
  8447. carouselItem = 'carousel-item',
  8448. dataSlideTo = 'data-slide-to';
  8449. this[keyboard] = options[keyboard] === true || keyboardData;
  8450. this[pause] = (options[pause] === hoverEvent || pauseData) ? hoverEvent : false; // false / hover
  8451. this[interval] = typeof intervalOption === 'number' ? intervalOption
  8452. : intervalData === 0 ? 0
  8453. : intervalData;
  8454. // bind, event targets
  8455. var self = this, index = element.index = 0, timer = element.timer = 0,
  8456. isSliding = false, // isSliding prevents click event handlers when animation is running
  8457. slides = getElementsByClassName(element,carouselItem), total = slides[length],
  8458. slideDirection = this[direction] = left,
  8459. leftArrow = getElementsByClassName(element,component+'-control-prev')[0],
  8460. rightArrow = getElementsByClassName(element,component+'-control-next')[0],
  8461. indicator = queryElement( '.'+component+'-indicators', element ),
  8462. indicators = indicator && indicator[getElementsByTagName]( "LI" ) || [];
  8463. // handlers
  8464. var pauseHandler = function () {
  8465. if ( self[interval] !==false && !hasClass(element,paused) ) {
  8466. addClass(element,paused);
  8467. !isSliding && clearInterval( timer );
  8468. }
  8469. },
  8470. resumeHandler = function() {
  8471. if ( self[interval] !== false && hasClass(element,paused) ) {
  8472. removeClass(element,paused);
  8473. !isSliding && clearInterval( timer );
  8474. !isSliding && self.cycle();
  8475. }
  8476. },
  8477. indicatorHandler = function(e) {
  8478. e[preventDefault]();
  8479. if (isSliding) return;
  8480. var eventTarget = e[target]; // event target | the current active item
  8481. if ( eventTarget && !hasClass(eventTarget,active) && eventTarget[getAttribute](dataSlideTo) ) {
  8482. index = parseInt( eventTarget[getAttribute](dataSlideTo), 10 );
  8483. } else { return false; }
  8484. self.slideTo( index ); //Do the slide
  8485. },
  8486. controlsHandler = function (e) {
  8487. e[preventDefault]();
  8488. if (isSliding) return;
  8489. var eventTarget = e.currentTarget || e.srcElement;
  8490. if ( eventTarget === rightArrow ) {
  8491. index++;
  8492. } else if ( eventTarget === leftArrow ) {
  8493. index--;
  8494. }
  8495. self.slideTo( index ); //Do the slide
  8496. },
  8497. keyHandler = function (e) {
  8498. if (isSliding) return;
  8499. switch (e.which) {
  8500. case 39:
  8501. index++;
  8502. break;
  8503. case 37:
  8504. index--;
  8505. break;
  8506. default: return;
  8507. }
  8508. self.slideTo( index ); //Do the slide
  8509. },
  8510. // private methods
  8511. isElementInScrollRange = function () {
  8512. var rect = element[getBoundingClientRect](),
  8513. viewportHeight = globalObject[innerHeight] || HTML[clientHeight]
  8514. return rect[top] <= viewportHeight && rect[bottom] >= 0; // bottom && top
  8515. },
  8516. setActivePage = function( pageIndex ) { //indicators
  8517. for ( var i = 0, icl = indicators[length]; i < icl; i++ ) {
  8518. removeClass(indicators[i],active);
  8519. }
  8520. if (indicators[pageIndex]) addClass(indicators[pageIndex], active);
  8521. };
  8522. // public methods
  8523. this.cycle = function() {
  8524. timer = setInterval(function() {
  8525. isElementInScrollRange() && (index++, self.slideTo( index ) );
  8526. }, this[interval]);
  8527. };
  8528. this.slideTo = function( next ) {
  8529. if (isSliding) return; // when controled via methods, make sure to check again
  8530. var activeItem = this.getActiveIndex(), // the current active
  8531. orientation;
  8532. // determine slideDirection first
  8533. if ( (activeItem < next ) || (activeItem === 0 && next === total -1 ) ) {
  8534. slideDirection = self[direction] = left; // next
  8535. } else if ( (activeItem > next) || (activeItem === total - 1 && next === 0 ) ) {
  8536. slideDirection = self[direction] = right; // prev
  8537. }
  8538. // find the right next index
  8539. if ( next < 0 ) { next = total - 1; }
  8540. else if ( next === total ){ next = 0; }
  8541. // update index
  8542. index = next;
  8543. orientation = slideDirection === left ? 'next' : 'prev'; //determine type
  8544. bootstrapCustomEvent.call(element, slideEvent, component, slides[next]); // here we go with the slide
  8545. isSliding = true;
  8546. clearInterval(timer);
  8547. setActivePage( next );
  8548. if ( supportTransitions && hasClass(element,'slide') ) {
  8549. addClass(slides[next],carouselItem +'-'+ orientation);
  8550. slides[next][offsetWidth];
  8551. addClass(slides[next],carouselItem +'-'+ slideDirection);
  8552. addClass(slides[activeItem],carouselItem +'-'+ slideDirection);
  8553. one(slides[activeItem], transitionEndEvent, function(e) {
  8554. var timeout = e[target] !== slides[activeItem] ? e.elapsedTime*1000 : 0;
  8555. setTimeout(function(){
  8556. isSliding = false;
  8557. addClass(slides[next],active);
  8558. removeClass(slides[activeItem],active);
  8559. removeClass(slides[next],carouselItem +'-'+ orientation);
  8560. removeClass(slides[next],carouselItem +'-'+ slideDirection);
  8561. removeClass(slides[activeItem],carouselItem +'-'+ slideDirection);
  8562. bootstrapCustomEvent.call(element, slidEvent, component, slides[next]);
  8563. if ( !DOC.hidden && self[interval] && !hasClass(element,paused) ) {
  8564. self.cycle();
  8565. }
  8566. },timeout+100);
  8567. });
  8568. } else {
  8569. addClass(slides[next],active);
  8570. slides[next][offsetWidth];
  8571. removeClass(slides[activeItem],active);
  8572. setTimeout(function() {
  8573. isSliding = false;
  8574. if ( self[interval] && !hasClass(element,paused) ) {
  8575. self.cycle();
  8576. }
  8577. bootstrapCustomEvent.call(element, slidEvent, component, slides[next]);
  8578. }, 100 );
  8579. }
  8580. };
  8581. this.getActiveIndex = function () {
  8582. return slides[indexOf](getElementsByClassName(element,carouselItem+' active')[0]) || 0;
  8583. };
  8584. // init
  8585. if ( !(stringCarousel in element ) ) { // prevent adding event handlers twice
  8586. if ( self[pause] && self[interval] ) {
  8587. on( element, mouseHover[0], pauseHandler );
  8588. on( element, mouseHover[1], resumeHandler );
  8589. on( element, 'touchstart', pauseHandler );
  8590. on( element, 'touchend', resumeHandler );
  8591. }
  8592. rightArrow && on( rightArrow, clickEvent, controlsHandler );
  8593. leftArrow && on( leftArrow, clickEvent, controlsHandler );
  8594. indicator && on( indicator, clickEvent, indicatorHandler );
  8595. self[keyboard] === true && on( globalObject, keydownEvent, keyHandler );
  8596. }
  8597. if (self.getActiveIndex()<0) {
  8598. slides[length] && addClass(slides[0],active);
  8599. indicators[length] && setActivePage(0);
  8600. }
  8601. if ( self[interval] ){ self.cycle(); }
  8602. element[stringCarousel] = self;
  8603. };
  8604. // CAROUSEL DATA API
  8605. // =================
  8606. supports[push]( [ stringCarousel, Carousel, '['+dataRide+'="carousel"]' ] );
  8607. /* Native Javascript for Bootstrap 4 | Collapse
  8608. -----------------------------------------------*/
  8609. // COLLAPSE DEFINITION
  8610. // ===================
  8611. var Collapse = function( element, options ) {
  8612. // initialization element
  8613. element = queryElement(element);
  8614. // set options
  8615. options = options || {};
  8616. // event targets and constants
  8617. var accordion = null, collapse = null, self = this,
  8618. isAnimating = false, // when true it will prevent click handlers
  8619. accordionData = element[getAttribute]('data-parent'),
  8620. // component strings
  8621. component = 'collapse',
  8622. collapsed = 'collapsed',
  8623. // private methods
  8624. openAction = function(collapseElement) {
  8625. bootstrapCustomEvent.call(collapseElement, showEvent, component);
  8626. isAnimating = true;
  8627. addClass(collapseElement,collapsing);
  8628. removeClass(collapseElement,component);
  8629. collapseElement[style][height] = collapseElement[scrollHeight] + 'px';
  8630. emulateTransitionEnd(collapseElement, function() {
  8631. isAnimating = false;
  8632. collapseElement[setAttribute](ariaExpanded,'true');
  8633. removeClass(collapseElement,collapsing);
  8634. addClass(collapseElement, component);
  8635. addClass(collapseElement,showClass);
  8636. collapseElement[style][height] = '';
  8637. bootstrapCustomEvent.call(collapseElement, shownEvent, component);
  8638. });
  8639. },
  8640. closeAction = function(collapseElement) {
  8641. bootstrapCustomEvent.call(collapseElement, hideEvent, component);
  8642. isAnimating = true;
  8643. collapseElement[style][height] = collapseElement[scrollHeight] + 'px'; // set height first
  8644. removeClass(collapseElement,component);
  8645. removeClass(collapseElement,showClass);
  8646. addClass(collapseElement,collapsing);
  8647. collapseElement[offsetWidth]; // force reflow to enable transition
  8648. collapseElement[style][height] = '0px';
  8649. emulateTransitionEnd(collapseElement, function() {
  8650. isAnimating = false;
  8651. collapseElement[setAttribute](ariaExpanded,'false');
  8652. removeClass(collapseElement,collapsing);
  8653. addClass(collapseElement,component);
  8654. collapseElement[style][height] = '';
  8655. bootstrapCustomEvent.call(collapseElement, hiddenEvent, component);
  8656. });
  8657. },
  8658. getTarget = function() {
  8659. var href = element.href && element[getAttribute]('href'),
  8660. parent = element[getAttribute](dataTarget),
  8661. id = href || ( parent && parent.charAt(0) === '#' ) && parent;
  8662. return id && queryElement(id);
  8663. };
  8664. // public methods
  8665. this.toggle = function(e) {
  8666. e[preventDefault]();
  8667. if (isAnimating) return;
  8668. if (!hasClass(collapse,showClass)) { self.show(); }
  8669. else { self.hide(); }
  8670. };
  8671. this.hide = function() {
  8672. closeAction(collapse);
  8673. addClass(element,collapsed);
  8674. };
  8675. this.show = function() {
  8676. if ( accordion ) {
  8677. var activeCollapse = queryElement('.'+component+'.'+showClass,accordion),
  8678. toggle = activeCollapse && (queryElement('['+dataToggle+'="'+component+'"]['+dataTarget+'="#'+activeCollapse.id+'"]',accordion)
  8679. || queryElement('['+dataToggle+'="'+component+'"][href="#'+activeCollapse.id+'"]',accordion) ),
  8680. correspondingCollapse = toggle && (toggle[getAttribute](dataTarget) || toggle.href);
  8681. if ( activeCollapse && toggle && activeCollapse !== collapse ) {
  8682. closeAction(activeCollapse);
  8683. if ( correspondingCollapse.split('#')[1] !== collapse.id ) { addClass(toggle,collapsed); }
  8684. else { removeClass(toggle,collapsed); }
  8685. }
  8686. }
  8687. openAction(collapse);
  8688. removeClass(element,collapsed);
  8689. };
  8690. // init
  8691. if ( !(stringCollapse in element ) ) { // prevent adding event handlers twice
  8692. on(element, clickEvent, self.toggle);
  8693. }
  8694. collapse = getTarget();
  8695. accordion = queryElement(options.parent) || accordionData && getClosest(element, accordionData);
  8696. element[stringCollapse] = self;
  8697. };
  8698. // COLLAPSE DATA API
  8699. // =================
  8700. supports[push]( [ stringCollapse, Collapse, '['+dataToggle+'="collapse"]' ] );
  8701. /* Native Javascript for Bootstrap 4 | Dropdown
  8702. ----------------------------------------------*/
  8703. // DROPDOWN DEFINITION
  8704. // ===================
  8705. var Dropdown = function( element, option ) {
  8706. // initialization element
  8707. element = queryElement(element);
  8708. // set option
  8709. this.persist = option === true || element[getAttribute]('data-persist') === 'true' || false;
  8710. // constants, event targets, strings
  8711. var self = this, children = 'children',
  8712. parent = element[parentNode],
  8713. component = 'dropdown', open = 'open',
  8714. relatedTarget = null,
  8715. menu = queryElement('.dropdown-menu', parent),
  8716. menuItems = (function(){
  8717. var set = menu[children], newSet = [];
  8718. for ( var i=0; i<set[length]; i++ ){
  8719. set[i][children][length] && (set[i][children][0].tagName === 'A' && newSet[push](set[i][children][0]));
  8720. set[i].tagName === 'A' && newSet[push](set[i]);
  8721. }
  8722. return newSet;
  8723. })(),
  8724. // preventDefault on empty anchor links
  8725. preventEmptyAnchor = function(anchor){
  8726. (anchor.href && anchor.href.slice(-1) === '#' || anchor[parentNode] && anchor[parentNode].href
  8727. && anchor[parentNode].href.slice(-1) === '#') && this[preventDefault]();
  8728. },
  8729. // toggle dismissible events
  8730. toggleDismiss = function(){
  8731. var type = element[open] ? on : off;
  8732. type(DOC, clickEvent, dismissHandler);
  8733. type(DOC, keydownEvent, preventScroll);
  8734. type(DOC, keyupEvent, keyHandler);
  8735. },
  8736. // handlers
  8737. dismissHandler = function(e) {
  8738. var eventTarget = e[target], hasData = eventTarget && (stringDropdown in eventTarget || stringDropdown in eventTarget[parentNode]);
  8739. if ( (eventTarget === menu || menu[contains](eventTarget)) && (self.persist || hasData) ) { return; }
  8740. else {
  8741. relatedTarget = eventTarget === element || element[contains](eventTarget) ? element : null;
  8742. hide();
  8743. }
  8744. preventEmptyAnchor.call(e,eventTarget);
  8745. },
  8746. clickHandler = function(e) {
  8747. relatedTarget = element;
  8748. show();
  8749. preventEmptyAnchor.call(e,e[target]);
  8750. },
  8751. preventScroll = function(e){
  8752. var key = e.which || e.keyCode;
  8753. if( key === 38 || key === 40 ) { e[preventDefault](); }
  8754. },
  8755. keyHandler = function(e){
  8756. var key = e.which || e.keyCode,
  8757. activeItem = DOC.activeElement,
  8758. idx = menuItems[indexOf](activeItem),
  8759. isSameElement = activeItem === element,
  8760. isInsideMenu = menu[contains](activeItem),
  8761. isMenuItem = activeItem[parentNode] === menu || activeItem[parentNode][parentNode] === menu;
  8762. if ( isMenuItem || isSameElement ) { // navigate up | down
  8763. idx = isSameElement ? 0
  8764. : key === 38 ? (idx>1?idx-1:0)
  8765. : key === 40 ? (idx<menuItems[length]-1?idx+1:idx) : idx;
  8766. menuItems[idx] && setFocus(menuItems[idx]);
  8767. }
  8768. if ( (menuItems[length] && isMenuItem // menu has items
  8769. || !menuItems[length] && (isInsideMenu || isSameElement) // menu might be a form
  8770. || !isInsideMenu ) // or the focused element is not in the menu at all
  8771. && element[open] && key === 27 // menu must be open
  8772. ) {
  8773. self.toggle();
  8774. relatedTarget = null;
  8775. }
  8776. },
  8777. // private methods
  8778. show = function() {
  8779. bootstrapCustomEvent.call(parent, showEvent, component, relatedTarget);
  8780. addClass(menu,showClass);
  8781. addClass(parent,showClass);
  8782. menu[setAttribute](ariaExpanded,true);
  8783. bootstrapCustomEvent.call(parent, shownEvent, component, relatedTarget);
  8784. element[open] = true;
  8785. off(element, clickEvent, clickHandler);
  8786. setTimeout(function(){
  8787. setFocus( menu[getElementsByTagName]('INPUT')[0] || element ); // focus the first input item | element
  8788. toggleDismiss();
  8789. },1);
  8790. },
  8791. hide = function() {
  8792. bootstrapCustomEvent.call(parent, hideEvent, component, relatedTarget);
  8793. removeClass(menu,showClass);
  8794. removeClass(parent,showClass);
  8795. menu[setAttribute](ariaExpanded,false);
  8796. bootstrapCustomEvent.call(parent, hiddenEvent, component, relatedTarget);
  8797. element[open] = false;
  8798. toggleDismiss();
  8799. setFocus(element);
  8800. setTimeout(function(){ on(element, clickEvent, clickHandler); },1);
  8801. };
  8802. // set initial state to closed
  8803. element[open] = false;
  8804. // public methods
  8805. this.toggle = function() {
  8806. if (hasClass(parent,showClass) && element[open]) { hide(); }
  8807. else { show(); }
  8808. };
  8809. // init
  8810. if ( !(stringDropdown in element) ) { // prevent adding event handlers twice
  8811. !tabindex in menu && menu[setAttribute](tabindex, '0'); // Fix onblur on Chrome | Safari
  8812. on(element, clickEvent, clickHandler);
  8813. }
  8814. element[stringDropdown] = self;
  8815. };
  8816. // DROPDOWN DATA API
  8817. // =================
  8818. supports[push]( [stringDropdown, Dropdown, '['+dataToggle+'="dropdown"]'] );
  8819. /* Native Javascript for Bootstrap 4 | Modal
  8820. -------------------------------------------*/
  8821. // MODAL DEFINITION
  8822. // ===============
  8823. var Modal = function(element, options) { // element can be the modal/triggering button
  8824. // the modal (both JavaScript / DATA API init) / triggering button element (DATA API)
  8825. element = queryElement(element);
  8826. // determine modal, triggering element
  8827. var btnCheck = element[getAttribute](dataTarget)||element[getAttribute]('href'),
  8828. checkModal = queryElement( btnCheck ),
  8829. modal = hasClass(element,'modal') ? element : checkModal,
  8830. // strings
  8831. component = 'modal',
  8832. staticString = 'static',
  8833. paddingLeft = 'paddingLeft',
  8834. paddingRight = 'paddingRight',
  8835. modalBackdropString = 'modal-backdrop';
  8836. if ( hasClass(element,'modal') ) { element = null; } // modal is now independent of it's triggering element
  8837. if ( !modal ) { return; } // invalidate
  8838. // set options
  8839. options = options || {};
  8840. this[keyboard] = options[keyboard] === false || modal[getAttribute](dataKeyboard) === 'false' ? false : true;
  8841. this[backdrop] = options[backdrop] === staticString || modal[getAttribute](databackdrop) === staticString ? staticString : true;
  8842. this[backdrop] = options[backdrop] === false || modal[getAttribute](databackdrop) === 'false' ? false : this[backdrop];
  8843. this[content] = options[content]; // JavaScript only
  8844. // bind, constants, event targets and other vars
  8845. var self = this, relatedTarget = null,
  8846. bodyIsOverflowing, modalIsOverflowing, scrollbarWidth, overlay,
  8847. // also find fixed-top / fixed-bottom items
  8848. fixedItems = getElementsByClassName(HTML,fixedTop).concat(getElementsByClassName(HTML,fixedBottom)),
  8849. // private methods
  8850. getWindowWidth = function() {
  8851. var htmlRect = HTML[getBoundingClientRect]();
  8852. return globalObject[innerWidth] || (htmlRect[right] - Math.abs(htmlRect[left]));
  8853. },
  8854. setScrollbar = function () {
  8855. var bodyStyle = globalObject.getComputedStyle(DOC[body]),
  8856. bodyPad = parseInt((bodyStyle[paddingRight]), 10), itemPad;
  8857. if (bodyIsOverflowing) {
  8858. DOC[body][style][paddingRight] = (bodyPad + scrollbarWidth) + 'px';
  8859. if (fixedItems[length]){
  8860. for (var i = 0; i < fixedItems[length]; i++) {
  8861. itemPad = globalObject.getComputedStyle(fixedItems[i])[paddingRight];
  8862. fixedItems[i][style][paddingRight] = ( parseInt(itemPad) + scrollbarWidth) + 'px';
  8863. }
  8864. }
  8865. }
  8866. },
  8867. resetScrollbar = function () {
  8868. DOC[body][style][paddingRight] = '';
  8869. if (fixedItems[length]){
  8870. for (var i = 0; i < fixedItems[length]; i++) {
  8871. fixedItems[i][style][paddingRight] = '';
  8872. }
  8873. }
  8874. },
  8875. measureScrollbar = function () { // thx walsh
  8876. var scrollDiv = DOC[createElement]('div'), scrollBarWidth;
  8877. scrollDiv.className = component+'-scrollbar-measure'; // this is here to stay
  8878. DOC[body][appendChild](scrollDiv);
  8879. scrollBarWidth = scrollDiv[offsetWidth] - scrollDiv[clientWidth];
  8880. DOC[body].removeChild(scrollDiv);
  8881. return scrollBarWidth;
  8882. },
  8883. checkScrollbar = function () {
  8884. bodyIsOverflowing = DOC[body][clientWidth] < getWindowWidth();
  8885. modalIsOverflowing = modal[scrollHeight] > HTML[clientHeight];
  8886. scrollbarWidth = measureScrollbar();
  8887. },
  8888. adjustDialog = function () {
  8889. modal[style][paddingLeft] = !bodyIsOverflowing && modalIsOverflowing ? scrollbarWidth + 'px' : '';
  8890. modal[style][paddingRight] = bodyIsOverflowing && !modalIsOverflowing ? scrollbarWidth + 'px' : '';
  8891. },
  8892. resetAdjustments = function () {
  8893. modal[style][paddingLeft] = '';
  8894. modal[style][paddingRight] = '';
  8895. },
  8896. createOverlay = function() {
  8897. modalOverlay = 1;
  8898. var newOverlay = DOC[createElement]('div');
  8899. overlay = queryElement('.'+modalBackdropString);
  8900. if ( overlay === null ) {
  8901. newOverlay[setAttribute]('class',modalBackdropString+' fade');
  8902. overlay = newOverlay;
  8903. DOC[body][appendChild](overlay);
  8904. }
  8905. },
  8906. removeOverlay = function() {
  8907. overlay = queryElement('.'+modalBackdropString);
  8908. if ( overlay && overlay !== null && typeof overlay === 'object' ) {
  8909. modalOverlay = 0;
  8910. DOC[body].removeChild(overlay); overlay = null;
  8911. }
  8912. bootstrapCustomEvent.call(modal, hiddenEvent, component);
  8913. },
  8914. keydownHandlerToggle = function() {
  8915. if (hasClass(modal,showClass)) {
  8916. on(DOC, keydownEvent, keyHandler);
  8917. } else {
  8918. off(DOC, keydownEvent, keyHandler);
  8919. }
  8920. },
  8921. resizeHandlerToggle = function() {
  8922. if (hasClass(modal,showClass)) {
  8923. on(globalObject, resizeEvent, self.update);
  8924. } else {
  8925. off(globalObject, resizeEvent, self.update);
  8926. }
  8927. },
  8928. dismissHandlerToggle = function() {
  8929. if (hasClass(modal,showClass)) {
  8930. on(modal, clickEvent, dismissHandler);
  8931. } else {
  8932. off(modal, clickEvent, dismissHandler);
  8933. }
  8934. },
  8935. // triggers
  8936. triggerShow = function() {
  8937. setFocus(modal);
  8938. bootstrapCustomEvent.call(modal, shownEvent, component, relatedTarget);
  8939. },
  8940. triggerHide = function() {
  8941. modal[style].display = '';
  8942. element && (setFocus(element));
  8943. setTimeout(function(){
  8944. if (!getElementsByClassName(DOC,component+' '+showClass)[0]) {
  8945. resetAdjustments();
  8946. resetScrollbar();
  8947. removeClass(DOC[body],component+'-open');
  8948. overlay && hasClass(overlay,'fade') ? (removeClass(overlay,showClass), emulateTransitionEnd(overlay,removeOverlay))
  8949. : removeOverlay();
  8950. resizeHandlerToggle();
  8951. dismissHandlerToggle();
  8952. keydownHandlerToggle();
  8953. }
  8954. }, 50);
  8955. },
  8956. // handlers
  8957. clickHandler = function(e) {
  8958. var clickTarget = e[target];
  8959. clickTarget = clickTarget[hasAttribute](dataTarget) || clickTarget[hasAttribute]('href') ? clickTarget : clickTarget[parentNode];
  8960. if ( clickTarget === element && !hasClass(modal,showClass) ) {
  8961. modal.modalTrigger = element;
  8962. relatedTarget = element;
  8963. self.show();
  8964. e[preventDefault]();
  8965. }
  8966. },
  8967. keyHandler = function(e) {
  8968. if (self[keyboard] && e.which == 27 && hasClass(modal,showClass)) {
  8969. self.hide();
  8970. }
  8971. },
  8972. dismissHandler = function(e) {
  8973. var clickTarget = e[target];
  8974. if ( hasClass(modal,showClass) && (clickTarget[parentNode][getAttribute](dataDismiss) === component
  8975. || clickTarget[getAttribute](dataDismiss) === component
  8976. || (clickTarget === modal && self[backdrop] !== staticString) ) ) {
  8977. self.hide(); relatedTarget = null;
  8978. e[preventDefault]();
  8979. }
  8980. };
  8981. // public methods
  8982. this.toggle = function() {
  8983. if ( hasClass(modal,showClass) ) {this.hide();} else {this.show();}
  8984. };
  8985. this.show = function() {
  8986. bootstrapCustomEvent.call(modal, showEvent, component, relatedTarget);
  8987. // we elegantly hide any opened modal
  8988. var currentOpen = getElementsByClassName(DOC,component+' '+showClass)[0];
  8989. currentOpen && currentOpen !== modal && currentOpen.modalTrigger[stringModal].hide();
  8990. if ( this[backdrop] ) {
  8991. !modalOverlay && createOverlay();
  8992. }
  8993. if ( overlay && modalOverlay && !hasClass(overlay,showClass)) {
  8994. overlay[offsetWidth]; // force reflow to enable trasition
  8995. addClass(overlay, showClass);
  8996. }
  8997. setTimeout( function() {
  8998. modal[style].display = 'block';
  8999. checkScrollbar();
  9000. setScrollbar();
  9001. adjustDialog();
  9002. addClass(DOC[body],component+'-open');
  9003. addClass(modal,showClass);
  9004. modal[setAttribute](ariaHidden, false);
  9005. resizeHandlerToggle();
  9006. dismissHandlerToggle();
  9007. keydownHandlerToggle();
  9008. hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerShow) : triggerShow();
  9009. }, supportTransitions ? 150 : 0);
  9010. };
  9011. this.hide = function() {
  9012. bootstrapCustomEvent.call(modal, hideEvent, component);
  9013. overlay = queryElement('.'+modalBackdropString);
  9014. removeClass(modal,showClass);
  9015. modal[setAttribute](ariaHidden, true);
  9016. setTimeout(function(){
  9017. hasClass(modal,'fade') ? emulateTransitionEnd(modal, triggerHide) : triggerHide();
  9018. }, supportTransitions ? 150 : 0);
  9019. };
  9020. this.setContent = function( content ) {
  9021. queryElement('.'+component+'-content',modal)[innerHTML] = content;
  9022. };
  9023. this.update = function() {
  9024. if (hasClass(modal,showClass)) {
  9025. checkScrollbar();
  9026. setScrollbar();
  9027. adjustDialog();
  9028. }
  9029. };
  9030. // init
  9031. // prevent adding event handlers over and over
  9032. // modal is independent of a triggering element
  9033. if ( !!element && !(stringModal in element) ) {
  9034. on(element, clickEvent, clickHandler);
  9035. }
  9036. if ( !!self[content] ) { self.setContent( self[content] ); }
  9037. !!element && (element[stringModal] = self);
  9038. };
  9039. // DATA API
  9040. supports[push]( [ stringModal, Modal, '['+dataToggle+'="modal"]' ] );
  9041. /* Native Javascript for Bootstrap 4 | Popover
  9042. ----------------------------------------------*/
  9043. // POPOVER DEFINITION
  9044. // ==================
  9045. var Popover = function( element, options ) {
  9046. // initialization element
  9047. element = queryElement(element);
  9048. // set options
  9049. options = options || {};
  9050. // DATA API
  9051. var triggerData = element[getAttribute](dataTrigger), // click / hover / focus
  9052. animationData = element[getAttribute](dataAnimation), // true / false
  9053. placementData = element[getAttribute](dataPlacement),
  9054. dismissibleData = element[getAttribute](dataDismissible),
  9055. delayData = element[getAttribute](dataDelay),
  9056. containerData = element[getAttribute](dataContainer),
  9057. // internal strings
  9058. component = 'popover',
  9059. template = 'template',
  9060. trigger = 'trigger',
  9061. classString = 'class',
  9062. div = 'div',
  9063. fade = 'fade',
  9064. content = 'content',
  9065. dataContent = 'data-content',
  9066. dismissible = 'dismissible',
  9067. closeBtn = '<button type="button" class="close">×</button>',
  9068. // check container
  9069. containerElement = queryElement(options[container]),
  9070. containerDataElement = queryElement(containerData),
  9071. // maybe the element is inside a modal
  9072. modal = getClosest(element,'.modal'),
  9073. // maybe the element is inside a fixed navbar
  9074. navbarFixedTop = getClosest(element,'.'+fixedTop),
  9075. navbarFixedBottom = getClosest(element,'.'+fixedBottom);
  9076. // set instance options
  9077. this[template] = options[template] ? options[template] : null; // JavaScript only
  9078. this[trigger] = options[trigger] ? options[trigger] : triggerData || hoverEvent;
  9079. this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
  9080. this[placement] = options[placement] ? options[placement] : placementData || top;
  9081. this[delay] = parseInt(options[delay] || delayData) || 200;
  9082. this[dismissible] = options[dismissible] || dismissibleData === 'true' ? true : false;
  9083. this[container] = containerElement ? containerElement
  9084. : containerDataElement ? containerDataElement
  9085. : navbarFixedTop ? navbarFixedTop
  9086. : navbarFixedBottom ? navbarFixedBottom
  9087. : modal ? modal : DOC[body];
  9088. // bind, content
  9089. var self = this,
  9090. titleString = element[getAttribute](dataTitle) || null,
  9091. contentString = element[getAttribute](dataContent) || null;
  9092. if ( !contentString && !this[template] ) return; // invalidate
  9093. // constants, vars
  9094. var popover = null, timer = 0, placementSetting = this[placement],
  9095. // handlers
  9096. dismissibleHandler = function(e) {
  9097. if (popover !== null && e[target] === queryElement('.close',popover)) {
  9098. self.hide();
  9099. }
  9100. },
  9101. // private methods
  9102. removePopover = function() {
  9103. self[container].removeChild(popover);
  9104. timer = null; popover = null;
  9105. },
  9106. createPopover = function() {
  9107. titleString = element[getAttribute](dataTitle); // check content again
  9108. contentString = element[getAttribute](dataContent);
  9109. popover = DOC[createElement](div);
  9110. // popover arrow
  9111. var popoverArrow = DOC[createElement](div);
  9112. popoverArrow[setAttribute](classString,'arrow');
  9113. popover[appendChild](popoverArrow);
  9114. if ( contentString !== null && self[template] === null ) { //create the popover from data attributes
  9115. popover[setAttribute]('role','tooltip');
  9116. if (titleString !== null) {
  9117. var popoverTitle = DOC[createElement]('h3');
  9118. popoverTitle[setAttribute](classString,component+'-header');
  9119. popoverTitle[innerHTML] = self[dismissible] ? titleString + closeBtn : titleString;
  9120. popover[appendChild](popoverTitle);
  9121. }
  9122. //set popover content
  9123. var popoverContent = DOC[createElement](div);
  9124. popoverContent[setAttribute](classString,component+'-body');
  9125. popoverContent[innerHTML] = self[dismissible] && titleString === null ? contentString + closeBtn : contentString;
  9126. popover[appendChild](popoverContent);
  9127. } else { // or create the popover from template
  9128. var popoverTemplate = DOC[createElement](div);
  9129. popoverTemplate[innerHTML] = self[template];
  9130. popover[innerHTML] = popoverTemplate.firstChild[innerHTML];
  9131. }
  9132. //append to the container
  9133. self[container][appendChild](popover);
  9134. popover[style].display = 'block';
  9135. popover[setAttribute](classString, component+ ' bs-' + component+'-'+placementSetting + ' ' + self[animation]);
  9136. },
  9137. showPopover = function () {
  9138. !hasClass(popover,showClass) && ( addClass(popover,showClass) );
  9139. },
  9140. updatePopover = function() {
  9141. styleTip(element,popover,placementSetting,self[container]);
  9142. },
  9143. // event toggle
  9144. dismissHandlerToggle = function(type){
  9145. if (clickEvent == self[trigger] || 'focus' == self[trigger]) {
  9146. !self[dismissible] && type( element, 'blur', self.hide );
  9147. }
  9148. self[dismissible] && type( DOC, clickEvent, dismissibleHandler );
  9149. type( globalObject, resizeEvent, self.hide );
  9150. },
  9151. // triggers
  9152. showTrigger = function() {
  9153. dismissHandlerToggle(on);
  9154. bootstrapCustomEvent.call(element, shownEvent, component);
  9155. },
  9156. hideTrigger = function() {
  9157. dismissHandlerToggle(off);
  9158. removePopover();
  9159. bootstrapCustomEvent.call(element, hiddenEvent, component);
  9160. };
  9161. // public methods / handlers
  9162. this.toggle = function() {
  9163. if (popover === null) { self.show(); }
  9164. else { self.hide(); }
  9165. };
  9166. this.show = function() {
  9167. clearTimeout(timer);
  9168. timer = setTimeout( function() {
  9169. if (popover === null) {
  9170. placementSetting = self[placement]; // we reset placement in all cases
  9171. createPopover();
  9172. updatePopover();
  9173. showPopover();
  9174. bootstrapCustomEvent.call(element, showEvent, component);
  9175. !!self[animation] ? emulateTransitionEnd(popover, showTrigger) : showTrigger();
  9176. }
  9177. }, 20 );
  9178. };
  9179. this.hide = function() {
  9180. clearTimeout(timer);
  9181. timer = setTimeout( function() {
  9182. if (popover && popover !== null && hasClass(popover,showClass)) {
  9183. bootstrapCustomEvent.call(element, hideEvent, component);
  9184. removeClass(popover,showClass);
  9185. !!self[animation] ? emulateTransitionEnd(popover, hideTrigger) : hideTrigger();
  9186. }
  9187. }, self[delay] );
  9188. };
  9189. // init
  9190. if ( !(stringPopover in element) ) { // prevent adding event handlers twice
  9191. if (self[trigger] === hoverEvent) {
  9192. on( element, mouseHover[0], self.show );
  9193. if (!self[dismissible]) { on( element, mouseHover[1], self.hide ); }
  9194. } else if (clickEvent == self[trigger] || 'focus' == self[trigger]) {
  9195. on( element, self[trigger], self.toggle );
  9196. }
  9197. }
  9198. element[stringPopover] = self;
  9199. };
  9200. // POPOVER DATA API
  9201. // ================
  9202. supports[push]( [ stringPopover, Popover, '['+dataToggle+'="popover"]' ] );
  9203. /* Native Javascript for Bootstrap 4 | ScrollSpy
  9204. -----------------------------------------------*/
  9205. // SCROLLSPY DEFINITION
  9206. // ====================
  9207. var ScrollSpy = function(element, options) {
  9208. // initialization element, the element we spy on
  9209. element = queryElement(element);
  9210. // DATA API
  9211. var targetData = queryElement(element[getAttribute](dataTarget)),
  9212. offsetData = element[getAttribute]('data-offset');
  9213. // set options
  9214. options = options || {};
  9215. if ( !options[target] && !targetData ) { return; } // invalidate
  9216. // event targets, constants
  9217. var self = this, spyTarget = options[target] && queryElement(options[target]) || targetData,
  9218. links = spyTarget && spyTarget[getElementsByTagName]('A'),
  9219. offset = parseInt(offsetData || options['offset']) || 10,
  9220. items = [], targetItems = [], scrollOffset,
  9221. scrollTarget = element[offsetHeight] < element[scrollHeight] ? element : globalObject, // determine which is the real scrollTarget
  9222. isWindow = scrollTarget === globalObject;
  9223. // populate items and targets
  9224. for (var i=0, il=links[length]; i<il; i++) {
  9225. var href = links[i][getAttribute]('href'),
  9226. targetItem = href && href.charAt(0) === '#' && href.slice(-1) !== '#' && queryElement(href);
  9227. if ( !!targetItem ) {
  9228. items[push](links[i]);
  9229. targetItems[push](targetItem);
  9230. }
  9231. }
  9232. // private methods
  9233. var updateItem = function(index) {
  9234. var item = items[index],
  9235. targetItem = targetItems[index], // the menu item targets this element
  9236. dropdown = item[parentNode][parentNode],
  9237. dropdownLink = hasClass(dropdown,'dropdown') && dropdown[getElementsByTagName]('A')[0],
  9238. targetRect = isWindow && targetItem[getBoundingClientRect](),
  9239. isActive = hasClass(item,active) || false,
  9240. topEdge = (isWindow ? targetRect[top] + scrollOffset : targetItem[offsetTop]) - offset,
  9241. bottomEdge = isWindow ? targetRect[bottom] + scrollOffset - offset : targetItems[index+1] ? targetItems[index+1][offsetTop] - offset : element[scrollHeight],
  9242. inside = scrollOffset >= topEdge && bottomEdge > scrollOffset;
  9243. if ( !isActive && inside ) {
  9244. if ( !hasClass(item,active) ) {
  9245. addClass(item,active);
  9246. if (dropdownLink && !hasClass(dropdownLink,active) ) {
  9247. addClass(dropdownLink,active);
  9248. }
  9249. bootstrapCustomEvent.call(element, 'activate', 'scrollspy', items[index]);
  9250. }
  9251. } else if ( !inside ) {
  9252. if ( hasClass(item,active) ) {
  9253. removeClass(item,active);
  9254. if (dropdownLink && hasClass(dropdownLink,active) && !getElementsByClassName(item[parentNode],active).length ) {
  9255. removeClass(dropdownLink,active);
  9256. }
  9257. }
  9258. } else if ( !inside && !isActive || isActive && inside ) {
  9259. return;
  9260. }
  9261. },
  9262. updateItems = function(){
  9263. scrollOffset = isWindow ? getScroll().y : element[scrollTop];
  9264. for (var index=0, itl=items[length]; index<itl; index++) {
  9265. updateItem(index)
  9266. }
  9267. };
  9268. // public method
  9269. this.refresh = function () {
  9270. updateItems();
  9271. }
  9272. // init
  9273. if ( !(stringScrollSpy in element) ) { // prevent adding event handlers twice
  9274. on( scrollTarget, scrollEvent, self.refresh );
  9275. on( globalObject, resizeEvent, self.refresh );
  9276. }
  9277. self.refresh();
  9278. element[stringScrollSpy] = self;
  9279. };
  9280. // SCROLLSPY DATA API
  9281. // ==================
  9282. supports[push]( [ stringScrollSpy, ScrollSpy, '['+dataSpy+'="scroll"]' ] );
  9283. /* Native Javascript for Bootstrap 4 | Tab
  9284. -----------------------------------------*/
  9285. // TAB DEFINITION
  9286. // ==============
  9287. var Tab = function( element, options ) {
  9288. // initialization element
  9289. element = queryElement(element);
  9290. // DATA API
  9291. var heightData = element[getAttribute](dataHeight),
  9292. // strings
  9293. component = 'tab', height = 'height', float = 'float', isAnimating = 'isAnimating';
  9294. // set options
  9295. options = options || {};
  9296. this[height] = supportTransitions ? (options[height] || heightData === 'true') : false;
  9297. // bind, event targets
  9298. var self = this, next,
  9299. tabs = getClosest(element,'.nav'),
  9300. tabsContentContainer = false,
  9301. dropdown = tabs && queryElement('.dropdown-toggle',tabs),
  9302. activeTab, activeContent, nextContent, containerHeight, equalContents, nextHeight,
  9303. // trigger
  9304. triggerEnd = function(){
  9305. tabsContentContainer[style][height] = '';
  9306. removeClass(tabsContentContainer,collapsing);
  9307. tabs[isAnimating] = false;
  9308. },
  9309. triggerShow = function() {
  9310. if (tabsContentContainer) { // height animation
  9311. if ( equalContents ) {
  9312. triggerEnd();
  9313. } else {
  9314. setTimeout(function(){ // enables height animation
  9315. tabsContentContainer[style][height] = nextHeight + 'px'; // height animation
  9316. tabsContentContainer[offsetWidth];
  9317. emulateTransitionEnd(tabsContentContainer, triggerEnd);
  9318. },1);
  9319. }
  9320. } else {
  9321. tabs[isAnimating] = false;
  9322. }
  9323. bootstrapCustomEvent.call(next, shownEvent, component, activeTab);
  9324. },
  9325. triggerHide = function() {
  9326. if (tabsContentContainer) {
  9327. activeContent[style][float] = left;
  9328. nextContent[style][float] = left;
  9329. containerHeight = activeContent[scrollHeight];
  9330. }
  9331. addClass(nextContent,active);
  9332. bootstrapCustomEvent.call(next, showEvent, component, activeTab);
  9333. removeClass(activeContent,active);
  9334. bootstrapCustomEvent.call(activeTab, hiddenEvent, component, next);
  9335. if (tabsContentContainer) {
  9336. nextHeight = nextContent[scrollHeight];
  9337. equalContents = nextHeight === containerHeight;
  9338. addClass(tabsContentContainer,collapsing);
  9339. tabsContentContainer[style][height] = containerHeight + 'px'; // height animation
  9340. tabsContentContainer[offsetHeight];
  9341. activeContent[style][float] = '';
  9342. nextContent[style][float] = '';
  9343. }
  9344. if ( hasClass(nextContent, 'fade') ) {
  9345. setTimeout(function(){
  9346. addClass(nextContent,showClass);
  9347. emulateTransitionEnd(nextContent,triggerShow);
  9348. },20);
  9349. } else { triggerShow(); }
  9350. };
  9351. if (!tabs) return; // invalidate
  9352. // set default animation state
  9353. tabs[isAnimating] = false;
  9354. // private methods
  9355. var getActiveTab = function() {
  9356. var activeTabs = getElementsByClassName(tabs,active), activeTab;
  9357. if ( activeTabs[length] === 1 && !hasClass(activeTabs[0][parentNode],'dropdown') ) {
  9358. activeTab = activeTabs[0];
  9359. } else if ( activeTabs[length] > 1 ) {
  9360. activeTab = activeTabs[activeTabs[length]-1];
  9361. }
  9362. return activeTab;
  9363. },
  9364. getActiveContent = function() {
  9365. return queryElement(getActiveTab()[getAttribute]('href'));
  9366. },
  9367. // handler
  9368. clickHandler = function(e) {
  9369. var href = e[target][getAttribute]('href');
  9370. e[preventDefault]();
  9371. next = e[target][getAttribute](dataToggle) === component || (href && href.charAt(0) === '#')
  9372. ? e[target] : e[target][parentNode]; // allow for child elements like icons to use the handler
  9373. !tabs[isAnimating] && !hasClass(next[parentNode],active) && self.show();
  9374. };
  9375. // public method
  9376. this.show = function() { // the tab we clicked is now the next tab
  9377. next = next || element;
  9378. nextContent = queryElement(next[getAttribute]('href')); //this is the actual object, the next tab content to activate
  9379. activeTab = getActiveTab();
  9380. activeContent = getActiveContent();
  9381. tabs[isAnimating] = true;
  9382. removeClass(activeTab,active);
  9383. addClass(next,active);
  9384. if ( dropdown ) {
  9385. if ( !hasClass(element[parentNode],'dropdown-menu') ) {
  9386. if (hasClass(dropdown,active)) removeClass(dropdown,active);
  9387. } else {
  9388. if (!hasClass(dropdown,active)) addClass(dropdown,active);
  9389. }
  9390. }
  9391. bootstrapCustomEvent.call(activeTab, hideEvent, component, next);
  9392. if (hasClass(activeContent, 'fade')) {
  9393. removeClass(activeContent,showClass);
  9394. emulateTransitionEnd(activeContent, triggerHide);
  9395. } else { triggerHide(); }
  9396. };
  9397. // init
  9398. if ( !(stringTab in element) ) { // prevent adding event handlers twice
  9399. on(element, clickEvent, clickHandler);
  9400. }
  9401. if (self[height]) { tabsContentContainer = getActiveContent()[parentNode]; }
  9402. element[stringTab] = self;
  9403. };
  9404. // TAB DATA API
  9405. // ============
  9406. supports[push]( [ stringTab, Tab, '['+dataToggle+'="tab"]' ] );
  9407. /* Native Javascript for Bootstrap 4 | Tooltip
  9408. ---------------------------------------------*/
  9409. // TOOLTIP DEFINITION
  9410. // ==================
  9411. var Tooltip = function( element,options ) {
  9412. // initialization element
  9413. element = queryElement(element);
  9414. // set options
  9415. options = options || {};
  9416. // DATA API
  9417. var animationData = element[getAttribute](dataAnimation),
  9418. placementData = element[getAttribute](dataPlacement),
  9419. delayData = element[getAttribute](dataDelay),
  9420. containerData = element[getAttribute](dataContainer),
  9421. // strings
  9422. component = 'tooltip',
  9423. classString = 'class',
  9424. title = 'title',
  9425. fade = 'fade',
  9426. div = 'div',
  9427. // check container
  9428. containerElement = queryElement(options[container]),
  9429. containerDataElement = queryElement(containerData),
  9430. // maybe the element is inside a modal
  9431. modal = getClosest(element,'.modal'),
  9432. // maybe the element is inside a fixed navbar
  9433. navbarFixedTop = getClosest(element,'.'+fixedTop),
  9434. navbarFixedBottom = getClosest(element,'.'+fixedBottom);
  9435. // set instance options
  9436. this[animation] = options[animation] && options[animation] !== fade ? options[animation] : animationData || fade;
  9437. this[placement] = options[placement] ? options[placement] : placementData || top;
  9438. this[delay] = parseInt(options[delay] || delayData) || 200;
  9439. this[container] = containerElement ? containerElement
  9440. : containerDataElement ? containerDataElement
  9441. : navbarFixedTop ? navbarFixedTop
  9442. : navbarFixedBottom ? navbarFixedBottom
  9443. : modal ? modal : DOC[body];
  9444. // bind, event targets, title and constants
  9445. var self = this, timer = 0, placementSetting = this[placement], tooltip = null,
  9446. titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle);
  9447. if ( !titleString || titleString == "" ) return; // invalidate
  9448. // private methods
  9449. var removeToolTip = function() {
  9450. self[container].removeChild(tooltip);
  9451. tooltip = null; timer = null;
  9452. },
  9453. createToolTip = function() {
  9454. titleString = element[getAttribute](title) || element[getAttribute](dataTitle) || element[getAttribute](dataOriginalTitle); // read the title again
  9455. if ( !titleString || titleString == "" ) return false; // invalidate
  9456. tooltip = DOC[createElement](div);
  9457. tooltip[setAttribute]('role',component);
  9458. // tooltip arrow
  9459. var tooltipArrow = DOC[createElement](div);
  9460. tooltipArrow[setAttribute](classString,'arrow');
  9461. tooltip[appendChild](tooltipArrow);
  9462. var tooltipInner = DOC[createElement](div);
  9463. tooltipInner[setAttribute](classString,component+'-inner');
  9464. tooltip[appendChild](tooltipInner);
  9465. tooltipInner[innerHTML] = titleString;
  9466. self[container][appendChild](tooltip);
  9467. tooltip[setAttribute](classString, component + ' bs-' + component+'-'+placementSetting + ' ' + self[animation]);
  9468. },
  9469. updateTooltip = function () {
  9470. styleTip(element,tooltip,placementSetting,self[container]);
  9471. },
  9472. showTooltip = function () {
  9473. !hasClass(tooltip,showClass) && ( addClass(tooltip,showClass) );
  9474. },
  9475. // triggers
  9476. showTrigger = function() {
  9477. on( globalObject, resizeEvent, self.hide );
  9478. bootstrapCustomEvent.call(element, shownEvent, component);
  9479. },
  9480. hideTrigger = function() {
  9481. off( globalObject, resizeEvent, self.hide );
  9482. removeToolTip();
  9483. bootstrapCustomEvent.call(element, hiddenEvent, component);
  9484. };
  9485. // public methods
  9486. this.show = function() {
  9487. clearTimeout(timer);
  9488. timer = setTimeout( function() {
  9489. if (tooltip === null) {
  9490. placementSetting = self[placement]; // we reset placement in all cases
  9491. if(createToolTip() == false) return;
  9492. updateTooltip();
  9493. showTooltip();
  9494. bootstrapCustomEvent.call(element, showEvent, component);
  9495. !!self[animation] ? emulateTransitionEnd(tooltip, showTrigger) : showTrigger();
  9496. }
  9497. }, 20 );
  9498. };
  9499. this.hide = function() {
  9500. clearTimeout(timer);
  9501. timer = setTimeout( function() {
  9502. if (tooltip && hasClass(tooltip,showClass)) {
  9503. bootstrapCustomEvent.call(element, hideEvent, component);
  9504. removeClass(tooltip,showClass);
  9505. !!self[animation] ? emulateTransitionEnd(tooltip, hideTrigger) : hideTrigger();
  9506. }
  9507. }, self[delay]);
  9508. };
  9509. this.toggle = function() {
  9510. if (!tooltip) { self.show(); }
  9511. else { self.hide(); }
  9512. };
  9513. // init
  9514. if ( !(stringTooltip in element) ) { // prevent adding event handlers twice
  9515. element[setAttribute](dataOriginalTitle,titleString);
  9516. element.removeAttribute(title);
  9517. on(element, mouseHover[0], self.show);
  9518. on(element, mouseHover[1], self.hide);
  9519. }
  9520. element[stringTooltip] = self;
  9521. };
  9522. // TOOLTIP DATA API
  9523. // =================
  9524. supports[push]( [ stringTooltip, Tooltip, '['+dataToggle+'="tooltip"]' ] );
  9525. /* Native Javascript for Bootstrap 4 | Initialize Data API
  9526. --------------------------------------------------------*/
  9527. var initializeDataAPI = function( constructor, collection ){
  9528. for (var i=0, l=collection[length]; i<l; i++) {
  9529. new constructor(collection[i]);
  9530. }
  9531. },
  9532. initCallback = BSN.initCallback = function(lookUp){
  9533. lookUp = lookUp || DOC;
  9534. for (var i=0, l=supports[length]; i<l; i++) {
  9535. initializeDataAPI( supports[i][1], lookUp[querySelectorAll] (supports[i][2]) );
  9536. }
  9537. };
  9538. // bulk initialize all components
  9539. DOC[body] ? initCallback() : on( DOC, 'DOMContentLoaded', function(){ initCallback(); } );
  9540. return {
  9541. Alert: Alert,
  9542. Button: Button,
  9543. Carousel: Carousel,
  9544. Collapse: Collapse,
  9545. Dropdown: Dropdown,
  9546. Modal: Modal,
  9547. Popover: Popover,
  9548. ScrollSpy: ScrollSpy,
  9549. Tab: Tab,
  9550. Tooltip: Tooltip
  9551. };
  9552. }));
  9553. /* jshint maxerr: 10000 */
  9554. /* jslint unused: true */
  9555. /* jshint shadow: true */
  9556. /* jshint -W075 */
  9557. (function(ns){
  9558. // this list must be ordered from largest length of the value array, index 0, to the shortest
  9559. ns.emojioneList = {":kiss_mm:":{"uc_base":"1f468-2764-1f48b-1f468","uc_output":"1f468-200d-2764-fe0f-200d-1f48b-200d-1f468","uc_match":"1f468-2764-fe0f-1f48b-1f468","uc_greedy":"1f468-2764-1f48b-1f468","shortnames":[":couplekiss_mm:"],"category":"people"},":kiss_woman_man:":{"uc_base":"1f469-2764-1f48b-1f468","uc_output":"1f469-200d-2764-fe0f-200d-1f48b-200d-1f468","uc_match":"1f469-2764-fe0f-1f48b-1f468","uc_greedy":"1f469-2764-1f48b-1f468","shortnames":[],"category":"people"},":kiss_ww:":{"uc_base":"1f469-2764-1f48b-1f469","uc_output":"1f469-200d-2764-fe0f-200d-1f48b-200d-1f469","uc_match":"1f469-2764-fe0f-1f48b-1f469","uc_greedy":"1f469-2764-1f48b-1f469","shortnames":[":couplekiss_ww:"],"category":"people"},":england:":{"uc_base":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","uc_output":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","uc_match":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","uc_greedy":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","shortnames":[],"category":"flags"},":scotland:":{"uc_base":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","uc_output":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","uc_match":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","uc_greedy":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","shortnames":[],"category":"flags"},":wales:":{"uc_base":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","uc_output":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","uc_match":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","uc_greedy":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","shortnames":[],"category":"flags"},":family_mmbb:":{"uc_base":"1f468-1f468-1f466-1f466","uc_output":"1f468-200d-1f468-200d-1f466-200d-1f466","uc_match":"1f468-1f468-1f466-1f466","uc_greedy":"1f468-1f468-1f466-1f466","shortnames":[],"category":"people"},":family_mmgb:":{"uc_base":"1f468-1f468-1f467-1f466","uc_output":"1f468-200d-1f468-200d-1f467-200d-1f466","uc_match":"1f468-1f468-1f467-1f466","uc_greedy":"1f468-1f468-1f467-1f466","shortnames":[],"category":"people"},":family_mmgg:":{"uc_base":"1f468-1f468-1f467-1f467","uc_output":"1f468-200d-1f468-200d-1f467-200d-1f467","uc_match":"1f468-1f468-1f467-1f467","uc_greedy":"1f468-1f468-1f467-1f467","shortnames":[],"category":"people"},":family_mwbb:":{"uc_base":"1f468-1f469-1f466-1f466","uc_output":"1f468-200d-1f469-200d-1f466-200d-1f466","uc_match":"1f468-1f469-1f466-1f466","uc_greedy":"1f468-1f469-1f466-1f466","shortnames":[],"category":"people"},":family_mwgb:":{"uc_base":"1f468-1f469-1f467-1f466","uc_output":"1f468-200d-1f469-200d-1f467-200d-1f466","uc_match":"1f468-1f469-1f467-1f466","uc_greedy":"1f468-1f469-1f467-1f466","shortnames":[],"category":"people"},":family_mwgg:":{"uc_base":"1f468-1f469-1f467-1f467","uc_output":"1f468-200d-1f469-200d-1f467-200d-1f467","uc_match":"1f468-1f469-1f467-1f467","uc_greedy":"1f468-1f469-1f467-1f467","shortnames":[],"category":"people"},":family_wwbb:":{"uc_base":"1f469-1f469-1f466-1f466","uc_output":"1f469-200d-1f469-200d-1f466-200d-1f466","uc_match":"1f469-1f469-1f466-1f466","uc_greedy":"1f469-1f469-1f466-1f466","shortnames":[],"category":"people"},":family_wwgb:":{"uc_base":"1f469-1f469-1f467-1f466","uc_output":"1f469-200d-1f469-200d-1f467-200d-1f466","uc_match":"1f469-1f469-1f467-1f466","uc_greedy":"1f469-1f469-1f467-1f466","shortnames":[],"category":"people"},":family_wwgg:":{"uc_base":"1f469-1f469-1f467-1f467","uc_output":"1f469-200d-1f469-200d-1f467-200d-1f467","uc_match":"1f469-1f469-1f467-1f467","uc_greedy":"1f469-1f469-1f467-1f467","shortnames":[],"category":"people"},":couple_mm:":{"uc_base":"1f468-2764-1f468","uc_output":"1f468-200d-2764-fe0f-200d-1f468","uc_match":"1f468-2764-fe0f-1f468","uc_greedy":"1f468-2764-1f468","shortnames":[":couple_with_heart_mm:"],"category":"people"},":couple_with_heart_woman_man:":{"uc_base":"1f469-2764-1f468","uc_output":"1f469-200d-2764-fe0f-200d-1f468","uc_match":"1f469-2764-fe0f-1f468","uc_greedy":"1f469-2764-1f468","shortnames":[],"category":"people"},":couple_ww:":{"uc_base":"1f469-2764-1f469","uc_output":"1f469-200d-2764-fe0f-200d-1f469","uc_match":"1f469-2764-fe0f-1f469","uc_greedy":"1f469-2764-1f469","shortnames":[":couple_with_heart_ww:"],"category":"people"},":family_man_boy_boy:":{"uc_base":"1f468-1f466-1f466","uc_output":"1f468-200d-1f466-200d-1f466","uc_match":"1f468-1f466-1f466","uc_greedy":"1f468-1f466-1f466","shortnames":[],"category":"people"},":family_man_girl_boy:":{"uc_base":"1f468-1f467-1f466","uc_output":"1f468-200d-1f467-200d-1f466","uc_match":"1f468-1f467-1f466","uc_greedy":"1f468-1f467-1f466","shortnames":[],"category":"people"},":family_man_girl_girl:":{"uc_base":"1f468-1f467-1f467","uc_output":"1f468-200d-1f467-200d-1f467","uc_match":"1f468-1f467-1f467","uc_greedy":"1f468-1f467-1f467","shortnames":[],"category":"people"},":family_man_woman_boy:":{"uc_base":"1f468-1f469-1f466","uc_output":"1f468-200d-1f469-200d-1f466","uc_match":"1f468-1f469-1f466","uc_greedy":"1f468-1f469-1f466","shortnames":[],"category":"people"},":family_mmb:":{"uc_base":"1f468-1f468-1f466","uc_output":"1f468-200d-1f468-200d-1f466","uc_match":"1f468-1f468-1f466","uc_greedy":"1f468-1f468-1f466","shortnames":[],"category":"people"},":family_mmg:":{"uc_base":"1f468-1f468-1f467","uc_output":"1f468-200d-1f468-200d-1f467","uc_match":"1f468-1f468-1f467","uc_greedy":"1f468-1f468-1f467","shortnames":[],"category":"people"},":family_mwg:":{"uc_base":"1f468-1f469-1f467","uc_output":"1f468-200d-1f469-200d-1f467","uc_match":"1f468-1f469-1f467","uc_greedy":"1f468-1f469-1f467","shortnames":[],"category":"people"},":family_woman_boy_boy:":{"uc_base":"1f469-1f466-1f466","uc_output":"1f469-200d-1f466-200d-1f466","uc_match":"1f469-1f466-1f466","uc_greedy":"1f469-1f466-1f466","shortnames":[],"category":"people"},":family_woman_girl_boy:":{"uc_base":"1f469-1f467-1f466","uc_output":"1f469-200d-1f467-200d-1f466","uc_match":"1f469-1f467-1f466","uc_greedy":"1f469-1f467-1f466","shortnames":[],"category":"people"},":family_woman_girl_girl:":{"uc_base":"1f469-1f467-1f467","uc_output":"1f469-200d-1f467-200d-1f467","uc_match":"1f469-1f467-1f467","uc_greedy":"1f469-1f467-1f467","shortnames":[],"category":"people"},":family_wwb:":{"uc_base":"1f469-1f469-1f466","uc_output":"1f469-200d-1f469-200d-1f466","uc_match":"1f469-1f469-1f466","uc_greedy":"1f469-1f469-1f466","shortnames":[],"category":"people"},":family_wwg:":{"uc_base":"1f469-1f469-1f467","uc_output":"1f469-200d-1f469-200d-1f467","uc_match":"1f469-1f469-1f467","uc_greedy":"1f469-1f469-1f467","shortnames":[],"category":"people"},":blond-haired_man_tone1:":{"uc_base":"1f471-1f3fb-2642","uc_output":"1f471-1f3fb-200d-2642-fe0f","uc_match":"1f471-1f3fb-2642-fe0f","uc_greedy":"1f471-1f3fb-2642","shortnames":[":blond-haired_man_light_skin_tone:"],"category":"people"},":blond-haired_man_tone2:":{"uc_base":"1f471-1f3fc-2642","uc_output":"1f471-1f3fc-200d-2642-fe0f","uc_match":"1f471-1f3fc-2642-fe0f","uc_greedy":"1f471-1f3fc-2642","shortnames":[":blond-haired_man_medium_light_skin_tone:"],"category":"people"},":blond-haired_man_tone3:":{"uc_base":"1f471-1f3fd-2642","uc_output":"1f471-1f3fd-200d-2642-fe0f","uc_match":"1f471-1f3fd-2642-fe0f","uc_greedy":"1f471-1f3fd-2642","shortnames":[":blond-haired_man_medium_skin_tone:"],"category":"people"},":blond-haired_man_tone4:":{"uc_base":"1f471-1f3fe-2642","uc_output":"1f471-1f3fe-200d-2642-fe0f","uc_match":"1f471-1f3fe-2642-fe0f","uc_greedy":"1f471-1f3fe-2642","shortnames":[":blond-haired_man_medium_dark_skin_tone:"],"category":"people"},":blond-haired_man_tone5:":{"uc_base":"1f471-1f3ff-2642","uc_output":"1f471-1f3ff-200d-2642-fe0f","uc_match":"1f471-1f3ff-2642-fe0f","uc_greedy":"1f471-1f3ff-2642","shortnames":[":blond-haired_man_dark_skin_tone:"],"category":"people"},":blond-haired_woman_tone1:":{"uc_base":"1f471-1f3fb-2640","uc_output":"1f471-1f3fb-200d-2640-fe0f","uc_match":"1f471-1f3fb-2640-fe0f","uc_greedy":"1f471-1f3fb-2640","shortnames":[":blond-haired_woman_light_skin_tone:"],"category":"people"},":blond-haired_woman_tone2:":{"uc_base":"1f471-1f3fc-2640","uc_output":"1f471-1f3fc-200d-2640-fe0f","uc_match":"1f471-1f3fc-2640-fe0f","uc_greedy":"1f471-1f3fc-2640","shortnames":[":blond-haired_woman_medium_light_skin_tone:"],"category":"people"},":blond-haired_woman_tone3:":{"uc_base":"1f471-1f3fd-2640","uc_output":"1f471-1f3fd-200d-2640-fe0f","uc_match":"1f471-1f3fd-2640-fe0f","uc_greedy":"1f471-1f3fd-2640","shortnames":[":blond-haired_woman_medium_skin_tone:"],"category":"people"},":blond-haired_woman_tone4:":{"uc_base":"1f471-1f3fe-2640","uc_output":"1f471-1f3fe-200d-2640-fe0f","uc_match":"1f471-1f3fe-2640-fe0f","uc_greedy":"1f471-1f3fe-2640","shortnames":[":blond-haired_woman_medium_dark_skin_tone:"],"category":"people"},":blond-haired_woman_tone5:":{"uc_base":"1f471-1f3ff-2640","uc_output":"1f471-1f3ff-200d-2640-fe0f","uc_match":"1f471-1f3ff-2640-fe0f","uc_greedy":"1f471-1f3ff-2640","shortnames":[":blond-haired_woman_dark_skin_tone:"],"category":"people"},":eye_in_speech_bubble:":{"uc_base":"1f441-1f5e8","uc_output":"1f441-fe0f-200d-1f5e8-fe0f","uc_match":"1f441-fe0f-1f5e8-fe0f","uc_greedy":"1f441-1f5e8","shortnames":[],"category":"symbols"},":man_biking_tone1:":{"uc_base":"1f6b4-1f3fb-2642","uc_output":"1f6b4-1f3fb-200d-2642-fe0f","uc_match":"1f6b4-1f3fb-2642-fe0f","uc_greedy":"1f6b4-1f3fb-2642","shortnames":[":man_biking_light_skin_tone:"],"category":"activity"},":man_biking_tone2:":{"uc_base":"1f6b4-1f3fc-2642","uc_output":"1f6b4-1f3fc-200d-2642-fe0f","uc_match":"1f6b4-1f3fc-2642-fe0f","uc_greedy":"1f6b4-1f3fc-2642","shortnames":[":man_biking_medium_light_skin_tone:"],"category":"activity"},":man_biking_tone3:":{"uc_base":"1f6b4-1f3fd-2642","uc_output":"1f6b4-1f3fd-200d-2642-fe0f","uc_match":"1f6b4-1f3fd-2642-fe0f","uc_greedy":"1f6b4-1f3fd-2642","shortnames":[":man_biking_medium_skin_tone:"],"category":"activity"},":man_biking_tone4:":{"uc_base":"1f6b4-1f3fe-2642","uc_output":"1f6b4-1f3fe-200d-2642-fe0f","uc_match":"1f6b4-1f3fe-2642-fe0f","uc_greedy":"1f6b4-1f3fe-2642","shortnames":[":man_biking_medium_dark_skin_tone:"],"category":"activity"},":man_biking_tone5:":{"uc_base":"1f6b4-1f3ff-2642","uc_output":"1f6b4-1f3ff-200d-2642-fe0f","uc_match":"1f6b4-1f3ff-2642-fe0f","uc_greedy":"1f6b4-1f3ff-2642","shortnames":[":man_biking_dark_skin_tone:"],"category":"activity"},":man_bowing_tone1:":{"uc_base":"1f647-1f3fb-2642","uc_output":"1f647-1f3fb-200d-2642-fe0f","uc_match":"1f647-1f3fb-2642-fe0f","uc_greedy":"1f647-1f3fb-2642","shortnames":[":man_bowing_light_skin_tone:"],"category":"people"},":man_bowing_tone2:":{"uc_base":"1f647-1f3fc-2642","uc_output":"1f647-1f3fc-200d-2642-fe0f","uc_match":"1f647-1f3fc-2642-fe0f","uc_greedy":"1f647-1f3fc-2642","shortnames":[":man_bowing_medium_light_skin_tone:"],"category":"people"},":man_bowing_tone3:":{"uc_base":"1f647-1f3fd-2642","uc_output":"1f647-1f3fd-200d-2642-fe0f","uc_match":"1f647-1f3fd-2642-fe0f","uc_greedy":"1f647-1f3fd-2642","shortnames":[":man_bowing_medium_skin_tone:"],"category":"people"},":man_bowing_tone4:":{"uc_base":"1f647-1f3fe-2642","uc_output":"1f647-1f3fe-200d-2642-fe0f","uc_match":"1f647-1f3fe-2642-fe0f","uc_greedy":"1f647-1f3fe-2642","shortnames":[":man_bowing_medium_dark_skin_tone:"],"category":"people"},":man_bowing_tone5:":{"uc_base":"1f647-1f3ff-2642","uc_output":"1f647-1f3ff-200d-2642-fe0f","uc_match":"1f647-1f3ff-2642-fe0f","uc_greedy":"1f647-1f3ff-2642","shortnames":[":man_bowing_dark_skin_tone:"],"category":"people"},":man_cartwheeling_tone1:":{"uc_base":"1f938-1f3fb-2642","uc_output":"1f938-1f3fb-200d-2642-fe0f","uc_match":"1f938-1f3fb-2642-fe0f","uc_greedy":"1f938-1f3fb-2642","shortnames":[":man_cartwheeling_light_skin_tone:"],"category":"activity"},":man_cartwheeling_tone2:":{"uc_base":"1f938-1f3fc-2642","uc_output":"1f938-1f3fc-200d-2642-fe0f","uc_match":"1f938-1f3fc-2642-fe0f","uc_greedy":"1f938-1f3fc-2642","shortnames":[":man_cartwheeling_medium_light_skin_tone:"],"category":"activity"},":man_cartwheeling_tone3:":{"uc_base":"1f938-1f3fd-2642","uc_output":"1f938-1f3fd-200d-2642-fe0f","uc_match":"1f938-1f3fd-2642-fe0f","uc_greedy":"1f938-1f3fd-2642","shortnames":[":man_cartwheeling_medium_skin_tone:"],"category":"activity"},":man_cartwheeling_tone4:":{"uc_base":"1f938-1f3fe-2642","uc_output":"1f938-1f3fe-200d-2642-fe0f","uc_match":"1f938-1f3fe-2642-fe0f","uc_greedy":"1f938-1f3fe-2642","shortnames":[":man_cartwheeling_medium_dark_skin_tone:"],"category":"activity"},":man_cartwheeling_tone5:":{"uc_base":"1f938-1f3ff-2642","uc_output":"1f938-1f3ff-200d-2642-fe0f","uc_match":"1f938-1f3ff-2642-fe0f","uc_greedy":"1f938-1f3ff-2642","shortnames":[":man_cartwheeling_dark_skin_tone:"],"category":"activity"},":man_climbing_tone1:":{"uc_base":"1f9d7-1f3fb-2642","uc_output":"1f9d7-1f3fb-200d-2642-fe0f","uc_match":"1f9d7-1f3fb-2642-fe0f","uc_greedy":"1f9d7-1f3fb-2642","shortnames":[":man_climbing_light_skin_tone:"],"category":"activity"},":man_climbing_tone2:":{"uc_base":"1f9d7-1f3fc-2642","uc_output":"1f9d7-1f3fc-200d-2642-fe0f","uc_match":"1f9d7-1f3fc-2642-fe0f","uc_greedy":"1f9d7-1f3fc-2642","shortnames":[":man_climbing_medium_light_skin_tone:"],"category":"activity"},":man_climbing_tone3:":{"uc_base":"1f9d7-1f3fd-2642","uc_output":"1f9d7-1f3fd-200d-2642-fe0f","uc_match":"1f9d7-1f3fd-2642-fe0f","uc_greedy":"1f9d7-1f3fd-2642","shortnames":[":man_climbing_medium_skin_tone:"],"category":"activity"},":man_climbing_tone4:":{"uc_base":"1f9d7-1f3fe-2642","uc_output":"1f9d7-1f3fe-200d-2642-fe0f","uc_match":"1f9d7-1f3fe-2642-fe0f","uc_greedy":"1f9d7-1f3fe-2642","shortnames":[":man_climbing_medium_dark_skin_tone:"],"category":"activity"},":man_climbing_tone5:":{"uc_base":"1f9d7-1f3ff-2642","uc_output":"1f9d7-1f3ff-200d-2642-fe0f","uc_match":"1f9d7-1f3ff-2642-fe0f","uc_greedy":"1f9d7-1f3ff-2642","shortnames":[":man_climbing_dark_skin_tone:"],"category":"activity"},":man_construction_worker_tone1:":{"uc_base":"1f477-1f3fb-2642","uc_output":"1f477-1f3fb-200d-2642-fe0f","uc_match":"1f477-1f3fb-2642-fe0f","uc_greedy":"1f477-1f3fb-2642","shortnames":[":man_construction_worker_light_skin_tone:"],"category":"people"},":man_construction_worker_tone2:":{"uc_base":"1f477-1f3fc-2642","uc_output":"1f477-1f3fc-200d-2642-fe0f","uc_match":"1f477-1f3fc-2642-fe0f","uc_greedy":"1f477-1f3fc-2642","shortnames":[":man_construction_worker_medium_light_skin_tone:"],"category":"people"},":man_construction_worker_tone3:":{"uc_base":"1f477-1f3fd-2642","uc_output":"1f477-1f3fd-200d-2642-fe0f","uc_match":"1f477-1f3fd-2642-fe0f","uc_greedy":"1f477-1f3fd-2642","shortnames":[":man_construction_worker_medium_skin_tone:"],"category":"people"},":man_construction_worker_tone4:":{"uc_base":"1f477-1f3fe-2642","uc_output":"1f477-1f3fe-200d-2642-fe0f","uc_match":"1f477-1f3fe-2642-fe0f","uc_greedy":"1f477-1f3fe-2642","shortnames":[":man_construction_worker_medium_dark_skin_tone:"],"category":"people"},":man_construction_worker_tone5:":{"uc_base":"1f477-1f3ff-2642","uc_output":"1f477-1f3ff-200d-2642-fe0f","uc_match":"1f477-1f3ff-2642-fe0f","uc_greedy":"1f477-1f3ff-2642","shortnames":[":man_construction_worker_dark_skin_tone:"],"category":"people"},":man_detective_tone1:":{"uc_base":"1f575-1f3fb-2642","uc_output":"1f575-1f3fb-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fb-2642-fe0f","uc_greedy":"1f575-1f3fb-2642","shortnames":[":man_detective_light_skin_tone:"],"category":"people"},":man_detective_tone2:":{"uc_base":"1f575-1f3fc-2642","uc_output":"1f575-1f3fc-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fc-2642-fe0f","uc_greedy":"1f575-1f3fc-2642","shortnames":[":man_detective_medium_light_skin_tone:"],"category":"people"},":man_detective_tone3:":{"uc_base":"1f575-1f3fd-2642","uc_output":"1f575-1f3fd-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fd-2642-fe0f","uc_greedy":"1f575-1f3fd-2642","shortnames":[":man_detective_medium_skin_tone:"],"category":"people"},":man_detective_tone4:":{"uc_base":"1f575-1f3fe-2642","uc_output":"1f575-1f3fe-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fe-2642-fe0f","uc_greedy":"1f575-1f3fe-2642","shortnames":[":man_detective_medium_dark_skin_tone:"],"category":"people"},":man_detective_tone5:":{"uc_base":"1f575-1f3ff-2642","uc_output":"1f575-1f3ff-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3ff-2642-fe0f","uc_greedy":"1f575-1f3ff-2642","shortnames":[":man_detective_dark_skin_tone:"],"category":"people"},":man_elf_tone1:":{"uc_base":"1f9dd-1f3fb-2642","uc_output":"1f9dd-1f3fb-200d-2642-fe0f","uc_match":"1f9dd-1f3fb-2642-fe0f","uc_greedy":"1f9dd-1f3fb-2642","shortnames":[":man_elf_light_skin_tone:"],"category":"people"},":man_elf_tone2:":{"uc_base":"1f9dd-1f3fc-2642","uc_output":"1f9dd-1f3fc-200d-2642-fe0f","uc_match":"1f9dd-1f3fc-2642-fe0f","uc_greedy":"1f9dd-1f3fc-2642","shortnames":[":man_elf_medium_light_skin_tone:"],"category":"people"},":man_elf_tone3:":{"uc_base":"1f9dd-1f3fd-2642","uc_output":"1f9dd-1f3fd-200d-2642-fe0f","uc_match":"1f9dd-1f3fd-2642-fe0f","uc_greedy":"1f9dd-1f3fd-2642","shortnames":[":man_elf_medium_skin_tone:"],"category":"people"},":man_elf_tone4:":{"uc_base":"1f9dd-1f3fe-2642","uc_output":"1f9dd-1f3fe-200d-2642-fe0f","uc_match":"1f9dd-1f3fe-2642-fe0f","uc_greedy":"1f9dd-1f3fe-2642","shortnames":[":man_elf_medium_dark_skin_tone:"],"category":"people"},":man_elf_tone5:":{"uc_base":"1f9dd-1f3ff-2642","uc_output":"1f9dd-1f3ff-200d-2642-fe0f","uc_match":"1f9dd-1f3ff-2642-fe0f","uc_greedy":"1f9dd-1f3ff-2642","shortnames":[":man_elf_dark_skin_tone:"],"category":"people"},":man_facepalming_tone1:":{"uc_base":"1f926-1f3fb-2642","uc_output":"1f926-1f3fb-200d-2642-fe0f","uc_match":"1f926-1f3fb-2642-fe0f","uc_greedy":"1f926-1f3fb-2642","shortnames":[":man_facepalming_light_skin_tone:"],"category":"people"},":man_facepalming_tone2:":{"uc_base":"1f926-1f3fc-2642","uc_output":"1f926-1f3fc-200d-2642-fe0f","uc_match":"1f926-1f3fc-2642-fe0f","uc_greedy":"1f926-1f3fc-2642","shortnames":[":man_facepalming_medium_light_skin_tone:"],"category":"people"},":man_facepalming_tone3:":{"uc_base":"1f926-1f3fd-2642","uc_output":"1f926-1f3fd-200d-2642-fe0f","uc_match":"1f926-1f3fd-2642-fe0f","uc_greedy":"1f926-1f3fd-2642","shortnames":[":man_facepalming_medium_skin_tone:"],"category":"people"},":man_facepalming_tone4:":{"uc_base":"1f926-1f3fe-2642","uc_output":"1f926-1f3fe-200d-2642-fe0f","uc_match":"1f926-1f3fe-2642-fe0f","uc_greedy":"1f926-1f3fe-2642","shortnames":[":man_facepalming_medium_dark_skin_tone:"],"category":"people"},":man_facepalming_tone5:":{"uc_base":"1f926-1f3ff-2642","uc_output":"1f926-1f3ff-200d-2642-fe0f","uc_match":"1f926-1f3ff-2642-fe0f","uc_greedy":"1f926-1f3ff-2642","shortnames":[":man_facepalming_dark_skin_tone:"],"category":"people"},":man_fairy_tone1:":{"uc_base":"1f9da-1f3fb-2642","uc_output":"1f9da-1f3fb-200d-2642-fe0f","uc_match":"1f9da-1f3fb-2642-fe0f","uc_greedy":"1f9da-1f3fb-2642","shortnames":[":man_fairy_light_skin_tone:"],"category":"people"},":man_fairy_tone2:":{"uc_base":"1f9da-1f3fc-2642","uc_output":"1f9da-1f3fc-200d-2642-fe0f","uc_match":"1f9da-1f3fc-2642-fe0f","uc_greedy":"1f9da-1f3fc-2642","shortnames":[":man_fairy_medium_light_skin_tone:"],"category":"people"},":man_fairy_tone3:":{"uc_base":"1f9da-1f3fd-2642","uc_output":"1f9da-1f3fd-200d-2642-fe0f","uc_match":"1f9da-1f3fd-2642-fe0f","uc_greedy":"1f9da-1f3fd-2642","shortnames":[":man_fairy_medium_skin_tone:"],"category":"people"},":man_fairy_tone4:":{"uc_base":"1f9da-1f3fe-2642","uc_output":"1f9da-1f3fe-200d-2642-fe0f","uc_match":"1f9da-1f3fe-2642-fe0f","uc_greedy":"1f9da-1f3fe-2642","shortnames":[":man_fairy_medium_dark_skin_tone:"],"category":"people"},":man_fairy_tone5:":{"uc_base":"1f9da-1f3ff-2642","uc_output":"1f9da-1f3ff-200d-2642-fe0f","uc_match":"1f9da-1f3ff-2642-fe0f","uc_greedy":"1f9da-1f3ff-2642","shortnames":[":man_fairy_dark_skin_tone:"],"category":"people"},":man_frowning_tone1:":{"uc_base":"1f64d-1f3fb-2642","uc_output":"1f64d-1f3fb-200d-2642-fe0f","uc_match":"1f64d-1f3fb-2642-fe0f","uc_greedy":"1f64d-1f3fb-2642","shortnames":[":man_frowning_light_skin_tone:"],"category":"people"},":man_frowning_tone2:":{"uc_base":"1f64d-1f3fc-2642","uc_output":"1f64d-1f3fc-200d-2642-fe0f","uc_match":"1f64d-1f3fc-2642-fe0f","uc_greedy":"1f64d-1f3fc-2642","shortnames":[":man_frowning_medium_light_skin_tone:"],"category":"people"},":man_frowning_tone3:":{"uc_base":"1f64d-1f3fd-2642","uc_output":"1f64d-1f3fd-200d-2642-fe0f","uc_match":"1f64d-1f3fd-2642-fe0f","uc_greedy":"1f64d-1f3fd-2642","shortnames":[":man_frowning_medium_skin_tone:"],"category":"people"},":man_frowning_tone4:":{"uc_base":"1f64d-1f3fe-2642","uc_output":"1f64d-1f3fe-200d-2642-fe0f","uc_match":"1f64d-1f3fe-2642-fe0f","uc_greedy":"1f64d-1f3fe-2642","shortnames":[":man_frowning_medium_dark_skin_tone:"],"category":"people"},":man_frowning_tone5:":{"uc_base":"1f64d-1f3ff-2642","uc_output":"1f64d-1f3ff-200d-2642-fe0f","uc_match":"1f64d-1f3ff-2642-fe0f","uc_greedy":"1f64d-1f3ff-2642","shortnames":[":man_frowning_dark_skin_tone:"],"category":"people"},":man_gesturing_no_tone1:":{"uc_base":"1f645-1f3fb-2642","uc_output":"1f645-1f3fb-200d-2642-fe0f","uc_match":"1f645-1f3fb-2642-fe0f","uc_greedy":"1f645-1f3fb-2642","shortnames":[":man_gesturing_no_light_skin_tone:"],"category":"people"},":man_gesturing_no_tone2:":{"uc_base":"1f645-1f3fc-2642","uc_output":"1f645-1f3fc-200d-2642-fe0f","uc_match":"1f645-1f3fc-2642-fe0f","uc_greedy":"1f645-1f3fc-2642","shortnames":[":man_gesturing_no_medium_light_skin_tone:"],"category":"people"},":man_gesturing_no_tone3:":{"uc_base":"1f645-1f3fd-2642","uc_output":"1f645-1f3fd-200d-2642-fe0f","uc_match":"1f645-1f3fd-2642-fe0f","uc_greedy":"1f645-1f3fd-2642","shortnames":[":man_gesturing_no_medium_skin_tone:"],"category":"people"},":man_gesturing_no_tone4:":{"uc_base":"1f645-1f3fe-2642","uc_output":"1f645-1f3fe-200d-2642-fe0f","uc_match":"1f645-1f3fe-2642-fe0f","uc_greedy":"1f645-1f3fe-2642","shortnames":[":man_gesturing_no_medium_dark_skin_tone:"],"category":"people"},":man_gesturing_no_tone5:":{"uc_base":"1f645-1f3ff-2642","uc_output":"1f645-1f3ff-200d-2642-fe0f","uc_match":"1f645-1f3ff-2642-fe0f","uc_greedy":"1f645-1f3ff-2642","shortnames":[":man_gesturing_no_dark_skin_tone:"],"category":"people"},":man_gesturing_ok_tone1:":{"uc_base":"1f646-1f3fb-2642","uc_output":"1f646-1f3fb-200d-2642-fe0f","uc_match":"1f646-1f3fb-2642-fe0f","uc_greedy":"1f646-1f3fb-2642","shortnames":[":man_gesturing_ok_light_skin_tone:"],"category":"people"},":man_gesturing_ok_tone2:":{"uc_base":"1f646-1f3fc-2642","uc_output":"1f646-1f3fc-200d-2642-fe0f","uc_match":"1f646-1f3fc-2642-fe0f","uc_greedy":"1f646-1f3fc-2642","shortnames":[":man_gesturing_ok_medium_light_skin_tone:"],"category":"people"},":man_gesturing_ok_tone3:":{"uc_base":"1f646-1f3fd-2642","uc_output":"1f646-1f3fd-200d-2642-fe0f","uc_match":"1f646-1f3fd-2642-fe0f","uc_greedy":"1f646-1f3fd-2642","shortnames":[":man_gesturing_ok_medium_skin_tone:"],"category":"people"},":man_gesturing_ok_tone4:":{"uc_base":"1f646-1f3fe-2642","uc_output":"1f646-1f3fe-200d-2642-fe0f","uc_match":"1f646-1f3fe-2642-fe0f","uc_greedy":"1f646-1f3fe-2642","shortnames":[":man_gesturing_ok_medium_dark_skin_tone:"],"category":"people"},":man_gesturing_ok_tone5:":{"uc_base":"1f646-1f3ff-2642","uc_output":"1f646-1f3ff-200d-2642-fe0f","uc_match":"1f646-1f3ff-2642-fe0f","uc_greedy":"1f646-1f3ff-2642","shortnames":[":man_gesturing_ok_dark_skin_tone:"],"category":"people"},":man_getting_face_massage_tone1:":{"uc_base":"1f486-1f3fb-2642","uc_output":"1f486-1f3fb-200d-2642-fe0f","uc_match":"1f486-1f3fb-2642-fe0f","uc_greedy":"1f486-1f3fb-2642","shortnames":[":man_getting_face_massage_light_skin_tone:"],"category":"people"},":man_getting_face_massage_tone2:":{"uc_base":"1f486-1f3fc-2642","uc_output":"1f486-1f3fc-200d-2642-fe0f","uc_match":"1f486-1f3fc-2642-fe0f","uc_greedy":"1f486-1f3fc-2642","shortnames":[":man_getting_face_massage_medium_light_skin_tone:"],"category":"people"},":man_getting_face_massage_tone3:":{"uc_base":"1f486-1f3fd-2642","uc_output":"1f486-1f3fd-200d-2642-fe0f","uc_match":"1f486-1f3fd-2642-fe0f","uc_greedy":"1f486-1f3fd-2642","shortnames":[":man_getting_face_massage_medium_skin_tone:"],"category":"people"},":man_getting_face_massage_tone4:":{"uc_base":"1f486-1f3fe-2642","uc_output":"1f486-1f3fe-200d-2642-fe0f","uc_match":"1f486-1f3fe-2642-fe0f","uc_greedy":"1f486-1f3fe-2642","shortnames":[":man_getting_face_massage_medium_dark_skin_tone:"],"category":"people"},":man_getting_face_massage_tone5:":{"uc_base":"1f486-1f3ff-2642","uc_output":"1f486-1f3ff-200d-2642-fe0f","uc_match":"1f486-1f3ff-2642-fe0f","uc_greedy":"1f486-1f3ff-2642","shortnames":[":man_getting_face_massage_dark_skin_tone:"],"category":"people"},":man_getting_haircut_tone1:":{"uc_base":"1f487-1f3fb-2642","uc_output":"1f487-1f3fb-200d-2642-fe0f","uc_match":"1f487-1f3fb-2642-fe0f","uc_greedy":"1f487-1f3fb-2642","shortnames":[":man_getting_haircut_light_skin_tone:"],"category":"people"},":man_getting_haircut_tone2:":{"uc_base":"1f487-1f3fc-2642","uc_output":"1f487-1f3fc-200d-2642-fe0f","uc_match":"1f487-1f3fc-2642-fe0f","uc_greedy":"1f487-1f3fc-2642","shortnames":[":man_getting_haircut_medium_light_skin_tone:"],"category":"people"},":man_getting_haircut_tone3:":{"uc_base":"1f487-1f3fd-2642","uc_output":"1f487-1f3fd-200d-2642-fe0f","uc_match":"1f487-1f3fd-2642-fe0f","uc_greedy":"1f487-1f3fd-2642","shortnames":[":man_getting_haircut_medium_skin_tone:"],"category":"people"},":man_getting_haircut_tone4:":{"uc_base":"1f487-1f3fe-2642","uc_output":"1f487-1f3fe-200d-2642-fe0f","uc_match":"1f487-1f3fe-2642-fe0f","uc_greedy":"1f487-1f3fe-2642","shortnames":[":man_getting_haircut_medium_dark_skin_tone:"],"category":"people"},":man_getting_haircut_tone5:":{"uc_base":"1f487-1f3ff-2642","uc_output":"1f487-1f3ff-200d-2642-fe0f","uc_match":"1f487-1f3ff-2642-fe0f","uc_greedy":"1f487-1f3ff-2642","shortnames":[":man_getting_haircut_dark_skin_tone:"],"category":"people"},":man_golfing_tone1:":{"uc_base":"1f3cc-1f3fb-2642","uc_output":"1f3cc-1f3fb-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fb-2642-fe0f","uc_greedy":"1f3cc-1f3fb-2642","shortnames":[":man_golfing_light_skin_tone:"],"category":"activity"},":man_golfing_tone2:":{"uc_base":"1f3cc-1f3fc-2642","uc_output":"1f3cc-1f3fc-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fc-2642-fe0f","uc_greedy":"1f3cc-1f3fc-2642","shortnames":[":man_golfing_medium_light_skin_tone:"],"category":"activity"},":man_golfing_tone3:":{"uc_base":"1f3cc-1f3fd-2642","uc_output":"1f3cc-1f3fd-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fd-2642-fe0f","uc_greedy":"1f3cc-1f3fd-2642","shortnames":[":man_golfing_medium_skin_tone:"],"category":"activity"},":man_golfing_tone4:":{"uc_base":"1f3cc-1f3fe-2642","uc_output":"1f3cc-1f3fe-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fe-2642-fe0f","uc_greedy":"1f3cc-1f3fe-2642","shortnames":[":man_golfing_medium_dark_skin_tone:"],"category":"activity"},":man_golfing_tone5:":{"uc_base":"1f3cc-1f3ff-2642","uc_output":"1f3cc-1f3ff-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3ff-2642-fe0f","uc_greedy":"1f3cc-1f3ff-2642","shortnames":[":man_golfing_dark_skin_tone:"],"category":"activity"},":man_guard_tone1:":{"uc_base":"1f482-1f3fb-2642","uc_output":"1f482-1f3fb-200d-2642-fe0f","uc_match":"1f482-1f3fb-2642-fe0f","uc_greedy":"1f482-1f3fb-2642","shortnames":[":man_guard_light_skin_tone:"],"category":"people"},":man_guard_tone2:":{"uc_base":"1f482-1f3fc-2642","uc_output":"1f482-1f3fc-200d-2642-fe0f","uc_match":"1f482-1f3fc-2642-fe0f","uc_greedy":"1f482-1f3fc-2642","shortnames":[":man_guard_medium_light_skin_tone:"],"category":"people"},":man_guard_tone3:":{"uc_base":"1f482-1f3fd-2642","uc_output":"1f482-1f3fd-200d-2642-fe0f","uc_match":"1f482-1f3fd-2642-fe0f","uc_greedy":"1f482-1f3fd-2642","shortnames":[":man_guard_medium_skin_tone:"],"category":"people"},":man_guard_tone4:":{"uc_base":"1f482-1f3fe-2642","uc_output":"1f482-1f3fe-200d-2642-fe0f","uc_match":"1f482-1f3fe-2642-fe0f","uc_greedy":"1f482-1f3fe-2642","shortnames":[":man_guard_medium_dark_skin_tone:"],"category":"people"},":man_guard_tone5:":{"uc_base":"1f482-1f3ff-2642","uc_output":"1f482-1f3ff-200d-2642-fe0f","uc_match":"1f482-1f3ff-2642-fe0f","uc_greedy":"1f482-1f3ff-2642","shortnames":[":man_guard_dark_skin_tone:"],"category":"people"},":man_health_worker_tone1:":{"uc_base":"1f468-1f3fb-2695","uc_output":"1f468-1f3fb-200d-2695-fe0f","uc_match":"1f468-1f3fb-2695-fe0f","uc_greedy":"1f468-1f3fb-2695","shortnames":[":man_health_worker_light_skin_tone:"],"category":"people"},":man_health_worker_tone2:":{"uc_base":"1f468-1f3fc-2695","uc_output":"1f468-1f3fc-200d-2695-fe0f","uc_match":"1f468-1f3fc-2695-fe0f","uc_greedy":"1f468-1f3fc-2695","shortnames":[":man_health_worker_medium_light_skin_tone:"],"category":"people"},":man_health_worker_tone3:":{"uc_base":"1f468-1f3fd-2695","uc_output":"1f468-1f3fd-200d-2695-fe0f","uc_match":"1f468-1f3fd-2695-fe0f","uc_greedy":"1f468-1f3fd-2695","shortnames":[":man_health_worker_medium_skin_tone:"],"category":"people"},":man_health_worker_tone4:":{"uc_base":"1f468-1f3fe-2695","uc_output":"1f468-1f3fe-200d-2695-fe0f","uc_match":"1f468-1f3fe-2695-fe0f","uc_greedy":"1f468-1f3fe-2695","shortnames":[":man_health_worker_medium_dark_skin_tone:"],"category":"people"},":man_health_worker_tone5:":{"uc_base":"1f468-1f3ff-2695","uc_output":"1f468-1f3ff-200d-2695-fe0f","uc_match":"1f468-1f3ff-2695-fe0f","uc_greedy":"1f468-1f3ff-2695","shortnames":[":man_health_worker_dark_skin_tone:"],"category":"people"},":man_in_lotus_position_tone1:":{"uc_base":"1f9d8-1f3fb-2642","uc_output":"1f9d8-1f3fb-200d-2642-fe0f","uc_match":"1f9d8-1f3fb-2642-fe0f","uc_greedy":"1f9d8-1f3fb-2642","shortnames":[":man_in_lotus_position_light_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone2:":{"uc_base":"1f9d8-1f3fc-2642","uc_output":"1f9d8-1f3fc-200d-2642-fe0f","uc_match":"1f9d8-1f3fc-2642-fe0f","uc_greedy":"1f9d8-1f3fc-2642","shortnames":[":man_in_lotus_position_medium_light_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone3:":{"uc_base":"1f9d8-1f3fd-2642","uc_output":"1f9d8-1f3fd-200d-2642-fe0f","uc_match":"1f9d8-1f3fd-2642-fe0f","uc_greedy":"1f9d8-1f3fd-2642","shortnames":[":man_in_lotus_position_medium_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone4:":{"uc_base":"1f9d8-1f3fe-2642","uc_output":"1f9d8-1f3fe-200d-2642-fe0f","uc_match":"1f9d8-1f3fe-2642-fe0f","uc_greedy":"1f9d8-1f3fe-2642","shortnames":[":man_in_lotus_position_medium_dark_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone5:":{"uc_base":"1f9d8-1f3ff-2642","uc_output":"1f9d8-1f3ff-200d-2642-fe0f","uc_match":"1f9d8-1f3ff-2642-fe0f","uc_greedy":"1f9d8-1f3ff-2642","shortnames":[":man_in_lotus_position_dark_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone1:":{"uc_base":"1f9d6-1f3fb-2642","uc_output":"1f9d6-1f3fb-200d-2642-fe0f","uc_match":"1f9d6-1f3fb-2642-fe0f","uc_greedy":"1f9d6-1f3fb-2642","shortnames":[":man_in_steamy_room_light_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone2:":{"uc_base":"1f9d6-1f3fc-2642","uc_output":"1f9d6-1f3fc-200d-2642-fe0f","uc_match":"1f9d6-1f3fc-2642-fe0f","uc_greedy":"1f9d6-1f3fc-2642","shortnames":[":man_in_steamy_room_medium_light_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone3:":{"uc_base":"1f9d6-1f3fd-2642","uc_output":"1f9d6-1f3fd-200d-2642-fe0f","uc_match":"1f9d6-1f3fd-2642-fe0f","uc_greedy":"1f9d6-1f3fd-2642","shortnames":[":man_in_steamy_room_medium_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone4:":{"uc_base":"1f9d6-1f3fe-2642","uc_output":"1f9d6-1f3fe-200d-2642-fe0f","uc_match":"1f9d6-1f3fe-2642-fe0f","uc_greedy":"1f9d6-1f3fe-2642","shortnames":[":man_in_steamy_room_medium_dark_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone5:":{"uc_base":"1f9d6-1f3ff-2642","uc_output":"1f9d6-1f3ff-200d-2642-fe0f","uc_match":"1f9d6-1f3ff-2642-fe0f","uc_greedy":"1f9d6-1f3ff-2642","shortnames":[":man_in_steamy_room_dark_skin_tone:"],"category":"activity"},":man_judge_tone1:":{"uc_base":"1f468-1f3fb-2696","uc_output":"1f468-1f3fb-200d-2696-fe0f","uc_match":"1f468-1f3fb-2696-fe0f","uc_greedy":"1f468-1f3fb-2696","shortnames":[":man_judge_light_skin_tone:"],"category":"people"},":man_judge_tone2:":{"uc_base":"1f468-1f3fc-2696","uc_output":"1f468-1f3fc-200d-2696-fe0f","uc_match":"1f468-1f3fc-2696-fe0f","uc_greedy":"1f468-1f3fc-2696","shortnames":[":man_judge_medium_light_skin_tone:"],"category":"people"},":man_judge_tone3:":{"uc_base":"1f468-1f3fd-2696","uc_output":"1f468-1f3fd-200d-2696-fe0f","uc_match":"1f468-1f3fd-2696-fe0f","uc_greedy":"1f468-1f3fd-2696","shortnames":[":man_judge_medium_skin_tone:"],"category":"people"},":man_judge_tone4:":{"uc_base":"1f468-1f3fe-2696","uc_output":"1f468-1f3fe-200d-2696-fe0f","uc_match":"1f468-1f3fe-2696-fe0f","uc_greedy":"1f468-1f3fe-2696","shortnames":[":man_judge_medium_dark_skin_tone:"],"category":"people"},":man_judge_tone5:":{"uc_base":"1f468-1f3ff-2696","uc_output":"1f468-1f3ff-200d-2696-fe0f","uc_match":"1f468-1f3ff-2696-fe0f","uc_greedy":"1f468-1f3ff-2696","shortnames":[":man_judge_dark_skin_tone:"],"category":"people"},":man_juggling_tone1:":{"uc_base":"1f939-1f3fb-2642","uc_output":"1f939-1f3fb-200d-2642-fe0f","uc_match":"1f939-1f3fb-2642-fe0f","uc_greedy":"1f939-1f3fb-2642","shortnames":[":man_juggling_light_skin_tone:"],"category":"activity"},":man_juggling_tone2:":{"uc_base":"1f939-1f3fc-2642","uc_output":"1f939-1f3fc-200d-2642-fe0f","uc_match":"1f939-1f3fc-2642-fe0f","uc_greedy":"1f939-1f3fc-2642","shortnames":[":man_juggling_medium_light_skin_tone:"],"category":"activity"},":man_juggling_tone3:":{"uc_base":"1f939-1f3fd-2642","uc_output":"1f939-1f3fd-200d-2642-fe0f","uc_match":"1f939-1f3fd-2642-fe0f","uc_greedy":"1f939-1f3fd-2642","shortnames":[":man_juggling_medium_skin_tone:"],"category":"activity"},":man_juggling_tone4:":{"uc_base":"1f939-1f3fe-2642","uc_output":"1f939-1f3fe-200d-2642-fe0f","uc_match":"1f939-1f3fe-2642-fe0f","uc_greedy":"1f939-1f3fe-2642","shortnames":[":man_juggling_medium_dark_skin_tone:"],"category":"activity"},":man_juggling_tone5:":{"uc_base":"1f939-1f3ff-2642","uc_output":"1f939-1f3ff-200d-2642-fe0f","uc_match":"1f939-1f3ff-2642-fe0f","uc_greedy":"1f939-1f3ff-2642","shortnames":[":man_juggling_dark_skin_tone:"],"category":"activity"},":man_lifting_weights_tone1:":{"uc_base":"1f3cb-1f3fb-2642","uc_output":"1f3cb-1f3fb-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fb-2642-fe0f","uc_greedy":"1f3cb-1f3fb-2642","shortnames":[":man_lifting_weights_light_skin_tone:"],"category":"activity"},":man_lifting_weights_tone2:":{"uc_base":"1f3cb-1f3fc-2642","uc_output":"1f3cb-1f3fc-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fc-2642-fe0f","uc_greedy":"1f3cb-1f3fc-2642","shortnames":[":man_lifting_weights_medium_light_skin_tone:"],"category":"activity"},":man_lifting_weights_tone3:":{"uc_base":"1f3cb-1f3fd-2642","uc_output":"1f3cb-1f3fd-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fd-2642-fe0f","uc_greedy":"1f3cb-1f3fd-2642","shortnames":[":man_lifting_weights_medium_skin_tone:"],"category":"activity"},":man_lifting_weights_tone4:":{"uc_base":"1f3cb-1f3fe-2642","uc_output":"1f3cb-1f3fe-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fe-2642-fe0f","uc_greedy":"1f3cb-1f3fe-2642","shortnames":[":man_lifting_weights_medium_dark_skin_tone:"],"category":"activity"},":man_lifting_weights_tone5:":{"uc_base":"1f3cb-1f3ff-2642","uc_output":"1f3cb-1f3ff-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3ff-2642-fe0f","uc_greedy":"1f3cb-1f3ff-2642","shortnames":[":man_lifting_weights_dark_skin_tone:"],"category":"activity"},":man_mage_tone1:":{"uc_base":"1f9d9-1f3fb-2642","uc_output":"1f9d9-1f3fb-200d-2642-fe0f","uc_match":"1f9d9-1f3fb-2642-fe0f","uc_greedy":"1f9d9-1f3fb-2642","shortnames":[":man_mage_light_skin_tone:"],"category":"people"},":man_mage_tone2:":{"uc_base":"1f9d9-1f3fc-2642","uc_output":"1f9d9-1f3fc-200d-2642-fe0f","uc_match":"1f9d9-1f3fc-2642-fe0f","uc_greedy":"1f9d9-1f3fc-2642","shortnames":[":man_mage_medium_light_skin_tone:"],"category":"people"},":man_mage_tone3:":{"uc_base":"1f9d9-1f3fd-2642","uc_output":"1f9d9-1f3fd-200d-2642-fe0f","uc_match":"1f9d9-1f3fd-2642-fe0f","uc_greedy":"1f9d9-1f3fd-2642","shortnames":[":man_mage_medium_skin_tone:"],"category":"people"},":man_mage_tone4:":{"uc_base":"1f9d9-1f3fe-2642","uc_output":"1f9d9-1f3fe-200d-2642-fe0f","uc_match":"1f9d9-1f3fe-2642-fe0f","uc_greedy":"1f9d9-1f3fe-2642","shortnames":[":man_mage_medium_dark_skin_tone:"],"category":"people"},":man_mage_tone5:":{"uc_base":"1f9d9-1f3ff-2642","uc_output":"1f9d9-1f3ff-200d-2642-fe0f","uc_match":"1f9d9-1f3ff-2642-fe0f","uc_greedy":"1f9d9-1f3ff-2642","shortnames":[":man_mage_dark_skin_tone:"],"category":"people"},":man_mountain_biking_tone1:":{"uc_base":"1f6b5-1f3fb-2642","uc_output":"1f6b5-1f3fb-200d-2642-fe0f","uc_match":"1f6b5-1f3fb-2642-fe0f","uc_greedy":"1f6b5-1f3fb-2642","shortnames":[":man_mountain_biking_light_skin_tone:"],"category":"activity"},":man_mountain_biking_tone2:":{"uc_base":"1f6b5-1f3fc-2642","uc_output":"1f6b5-1f3fc-200d-2642-fe0f","uc_match":"1f6b5-1f3fc-2642-fe0f","uc_greedy":"1f6b5-1f3fc-2642","shortnames":[":man_mountain_biking_medium_light_skin_tone:"],"category":"activity"},":man_mountain_biking_tone3:":{"uc_base":"1f6b5-1f3fd-2642","uc_output":"1f6b5-1f3fd-200d-2642-fe0f","uc_match":"1f6b5-1f3fd-2642-fe0f","uc_greedy":"1f6b5-1f3fd-2642","shortnames":[":man_mountain_biking_medium_skin_tone:"],"category":"activity"},":man_mountain_biking_tone4:":{"uc_base":"1f6b5-1f3fe-2642","uc_output":"1f6b5-1f3fe-200d-2642-fe0f","uc_match":"1f6b5-1f3fe-2642-fe0f","uc_greedy":"1f6b5-1f3fe-2642","shortnames":[":man_mountain_biking_medium_dark_skin_tone:"],"category":"activity"},":man_mountain_biking_tone5:":{"uc_base":"1f6b5-1f3ff-2642","uc_output":"1f6b5-1f3ff-200d-2642-fe0f","uc_match":"1f6b5-1f3ff-2642-fe0f","uc_greedy":"1f6b5-1f3ff-2642","shortnames":[":man_mountain_biking_dark_skin_tone:"],"category":"activity"},":man_pilot_tone1:":{"uc_base":"1f468-1f3fb-2708","uc_output":"1f468-1f3fb-200d-2708-fe0f","uc_match":"1f468-1f3fb-2708-fe0f","uc_greedy":"1f468-1f3fb-2708","shortnames":[":man_pilot_light_skin_tone:"],"category":"people"},":man_pilot_tone2:":{"uc_base":"1f468-1f3fc-2708","uc_output":"1f468-1f3fc-200d-2708-fe0f","uc_match":"1f468-1f3fc-2708-fe0f","uc_greedy":"1f468-1f3fc-2708","shortnames":[":man_pilot_medium_light_skin_tone:"],"category":"people"},":man_pilot_tone3:":{"uc_base":"1f468-1f3fd-2708","uc_output":"1f468-1f3fd-200d-2708-fe0f","uc_match":"1f468-1f3fd-2708-fe0f","uc_greedy":"1f468-1f3fd-2708","shortnames":[":man_pilot_medium_skin_tone:"],"category":"people"},":man_pilot_tone4:":{"uc_base":"1f468-1f3fe-2708","uc_output":"1f468-1f3fe-200d-2708-fe0f","uc_match":"1f468-1f3fe-2708-fe0f","uc_greedy":"1f468-1f3fe-2708","shortnames":[":man_pilot_medium_dark_skin_tone:"],"category":"people"},":man_pilot_tone5:":{"uc_base":"1f468-1f3ff-2708","uc_output":"1f468-1f3ff-200d-2708-fe0f","uc_match":"1f468-1f3ff-2708-fe0f","uc_greedy":"1f468-1f3ff-2708","shortnames":[":man_pilot_dark_skin_tone:"],"category":"people"},":man_playing_handball_tone1:":{"uc_base":"1f93e-1f3fb-2642","uc_output":"1f93e-1f3fb-200d-2642-fe0f","uc_match":"1f93e-1f3fb-2642-fe0f","uc_greedy":"1f93e-1f3fb-2642","shortnames":[":man_playing_handball_light_skin_tone:"],"category":"activity"},":man_playing_handball_tone2:":{"uc_base":"1f93e-1f3fc-2642","uc_output":"1f93e-1f3fc-200d-2642-fe0f","uc_match":"1f93e-1f3fc-2642-fe0f","uc_greedy":"1f93e-1f3fc-2642","shortnames":[":man_playing_handball_medium_light_skin_tone:"],"category":"activity"},":man_playing_handball_tone3:":{"uc_base":"1f93e-1f3fd-2642","uc_output":"1f93e-1f3fd-200d-2642-fe0f","uc_match":"1f93e-1f3fd-2642-fe0f","uc_greedy":"1f93e-1f3fd-2642","shortnames":[":man_playing_handball_medium_skin_tone:"],"category":"activity"},":man_playing_handball_tone4:":{"uc_base":"1f93e-1f3fe-2642","uc_output":"1f93e-1f3fe-200d-2642-fe0f","uc_match":"1f93e-1f3fe-2642-fe0f","uc_greedy":"1f93e-1f3fe-2642","shortnames":[":man_playing_handball_medium_dark_skin_tone:"],"category":"activity"},":man_playing_handball_tone5:":{"uc_base":"1f93e-1f3ff-2642","uc_output":"1f93e-1f3ff-200d-2642-fe0f","uc_match":"1f93e-1f3ff-2642-fe0f","uc_greedy":"1f93e-1f3ff-2642","shortnames":[":man_playing_handball_dark_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone1:":{"uc_base":"1f93d-1f3fb-2642","uc_output":"1f93d-1f3fb-200d-2642-fe0f","uc_match":"1f93d-1f3fb-2642-fe0f","uc_greedy":"1f93d-1f3fb-2642","shortnames":[":man_playing_water_polo_light_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone2:":{"uc_base":"1f93d-1f3fc-2642","uc_output":"1f93d-1f3fc-200d-2642-fe0f","uc_match":"1f93d-1f3fc-2642-fe0f","uc_greedy":"1f93d-1f3fc-2642","shortnames":[":man_playing_water_polo_medium_light_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone3:":{"uc_base":"1f93d-1f3fd-2642","uc_output":"1f93d-1f3fd-200d-2642-fe0f","uc_match":"1f93d-1f3fd-2642-fe0f","uc_greedy":"1f93d-1f3fd-2642","shortnames":[":man_playing_water_polo_medium_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone4:":{"uc_base":"1f93d-1f3fe-2642","uc_output":"1f93d-1f3fe-200d-2642-fe0f","uc_match":"1f93d-1f3fe-2642-fe0f","uc_greedy":"1f93d-1f3fe-2642","shortnames":[":man_playing_water_polo_medium_dark_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone5:":{"uc_base":"1f93d-1f3ff-2642","uc_output":"1f93d-1f3ff-200d-2642-fe0f","uc_match":"1f93d-1f3ff-2642-fe0f","uc_greedy":"1f93d-1f3ff-2642","shortnames":[":man_playing_water_polo_dark_skin_tone:"],"category":"activity"},":man_police_officer_tone1:":{"uc_base":"1f46e-1f3fb-2642","uc_output":"1f46e-1f3fb-200d-2642-fe0f","uc_match":"1f46e-1f3fb-2642-fe0f","uc_greedy":"1f46e-1f3fb-2642","shortnames":[":man_police_officer_light_skin_tone:"],"category":"people"},":man_police_officer_tone2:":{"uc_base":"1f46e-1f3fc-2642","uc_output":"1f46e-1f3fc-200d-2642-fe0f","uc_match":"1f46e-1f3fc-2642-fe0f","uc_greedy":"1f46e-1f3fc-2642","shortnames":[":man_police_officer_medium_light_skin_tone:"],"category":"people"},":man_police_officer_tone3:":{"uc_base":"1f46e-1f3fd-2642","uc_output":"1f46e-1f3fd-200d-2642-fe0f","uc_match":"1f46e-1f3fd-2642-fe0f","uc_greedy":"1f46e-1f3fd-2642","shortnames":[":man_police_officer_medium_skin_tone:"],"category":"people"},":man_police_officer_tone4:":{"uc_base":"1f46e-1f3fe-2642","uc_output":"1f46e-1f3fe-200d-2642-fe0f","uc_match":"1f46e-1f3fe-2642-fe0f","uc_greedy":"1f46e-1f3fe-2642","shortnames":[":man_police_officer_medium_dark_skin_tone:"],"category":"people"},":man_police_officer_tone5:":{"uc_base":"1f46e-1f3ff-2642","uc_output":"1f46e-1f3ff-200d-2642-fe0f","uc_match":"1f46e-1f3ff-2642-fe0f","uc_greedy":"1f46e-1f3ff-2642","shortnames":[":man_police_officer_dark_skin_tone:"],"category":"people"},":man_pouting_tone1:":{"uc_base":"1f64e-1f3fb-2642","uc_output":"1f64e-1f3fb-200d-2642-fe0f","uc_match":"1f64e-1f3fb-2642-fe0f","uc_greedy":"1f64e-1f3fb-2642","shortnames":[":man_pouting_light_skin_tone:"],"category":"people"},":man_pouting_tone2:":{"uc_base":"1f64e-1f3fc-2642","uc_output":"1f64e-1f3fc-200d-2642-fe0f","uc_match":"1f64e-1f3fc-2642-fe0f","uc_greedy":"1f64e-1f3fc-2642","shortnames":[":man_pouting_medium_light_skin_tone:"],"category":"people"},":man_pouting_tone3:":{"uc_base":"1f64e-1f3fd-2642","uc_output":"1f64e-1f3fd-200d-2642-fe0f","uc_match":"1f64e-1f3fd-2642-fe0f","uc_greedy":"1f64e-1f3fd-2642","shortnames":[":man_pouting_medium_skin_tone:"],"category":"people"},":man_pouting_tone4:":{"uc_base":"1f64e-1f3fe-2642","uc_output":"1f64e-1f3fe-200d-2642-fe0f","uc_match":"1f64e-1f3fe-2642-fe0f","uc_greedy":"1f64e-1f3fe-2642","shortnames":[":man_pouting_medium_dark_skin_tone:"],"category":"people"},":man_pouting_tone5:":{"uc_base":"1f64e-1f3ff-2642","uc_output":"1f64e-1f3ff-200d-2642-fe0f","uc_match":"1f64e-1f3ff-2642-fe0f","uc_greedy":"1f64e-1f3ff-2642","shortnames":[":man_pouting_dark_skin_tone:"],"category":"people"},":man_raising_hand_tone1:":{"uc_base":"1f64b-1f3fb-2642","uc_output":"1f64b-1f3fb-200d-2642-fe0f","uc_match":"1f64b-1f3fb-2642-fe0f","uc_greedy":"1f64b-1f3fb-2642","shortnames":[":man_raising_hand_light_skin_tone:"],"category":"people"},":man_raising_hand_tone2:":{"uc_base":"1f64b-1f3fc-2642","uc_output":"1f64b-1f3fc-200d-2642-fe0f","uc_match":"1f64b-1f3fc-2642-fe0f","uc_greedy":"1f64b-1f3fc-2642","shortnames":[":man_raising_hand_medium_light_skin_tone:"],"category":"people"},":man_raising_hand_tone3:":{"uc_base":"1f64b-1f3fd-2642","uc_output":"1f64b-1f3fd-200d-2642-fe0f","uc_match":"1f64b-1f3fd-2642-fe0f","uc_greedy":"1f64b-1f3fd-2642","shortnames":[":man_raising_hand_medium_skin_tone:"],"category":"people"},":man_raising_hand_tone4:":{"uc_base":"1f64b-1f3fe-2642","uc_output":"1f64b-1f3fe-200d-2642-fe0f","uc_match":"1f64b-1f3fe-2642-fe0f","uc_greedy":"1f64b-1f3fe-2642","shortnames":[":man_raising_hand_medium_dark_skin_tone:"],"category":"people"},":man_raising_hand_tone5:":{"uc_base":"1f64b-1f3ff-2642","uc_output":"1f64b-1f3ff-200d-2642-fe0f","uc_match":"1f64b-1f3ff-2642-fe0f","uc_greedy":"1f64b-1f3ff-2642","shortnames":[":man_raising_hand_dark_skin_tone:"],"category":"people"},":man_rowing_boat_tone1:":{"uc_base":"1f6a3-1f3fb-2642","uc_output":"1f6a3-1f3fb-200d-2642-fe0f","uc_match":"1f6a3-1f3fb-2642-fe0f","uc_greedy":"1f6a3-1f3fb-2642","shortnames":[":man_rowing_boat_light_skin_tone:"],"category":"activity"},":man_rowing_boat_tone2:":{"uc_base":"1f6a3-1f3fc-2642","uc_output":"1f6a3-1f3fc-200d-2642-fe0f","uc_match":"1f6a3-1f3fc-2642-fe0f","uc_greedy":"1f6a3-1f3fc-2642","shortnames":[":man_rowing_boat_medium_light_skin_tone:"],"category":"activity"},":man_rowing_boat_tone3:":{"uc_base":"1f6a3-1f3fd-2642","uc_output":"1f6a3-1f3fd-200d-2642-fe0f","uc_match":"1f6a3-1f3fd-2642-fe0f","uc_greedy":"1f6a3-1f3fd-2642","shortnames":[":man_rowing_boat_medium_skin_tone:"],"category":"activity"},":man_rowing_boat_tone4:":{"uc_base":"1f6a3-1f3fe-2642","uc_output":"1f6a3-1f3fe-200d-2642-fe0f","uc_match":"1f6a3-1f3fe-2642-fe0f","uc_greedy":"1f6a3-1f3fe-2642","shortnames":[":man_rowing_boat_medium_dark_skin_tone:"],"category":"activity"},":man_rowing_boat_tone5:":{"uc_base":"1f6a3-1f3ff-2642","uc_output":"1f6a3-1f3ff-200d-2642-fe0f","uc_match":"1f6a3-1f3ff-2642-fe0f","uc_greedy":"1f6a3-1f3ff-2642","shortnames":[":man_rowing_boat_dark_skin_tone:"],"category":"activity"},":man_running_tone1:":{"uc_base":"1f3c3-1f3fb-2642","uc_output":"1f3c3-1f3fb-200d-2642-fe0f","uc_match":"1f3c3-1f3fb-2642-fe0f","uc_greedy":"1f3c3-1f3fb-2642","shortnames":[":man_running_light_skin_tone:"],"category":"people"},":man_running_tone2:":{"uc_base":"1f3c3-1f3fc-2642","uc_output":"1f3c3-1f3fc-200d-2642-fe0f","uc_match":"1f3c3-1f3fc-2642-fe0f","uc_greedy":"1f3c3-1f3fc-2642","shortnames":[":man_running_medium_light_skin_tone:"],"category":"people"},":man_running_tone3:":{"uc_base":"1f3c3-1f3fd-2642","uc_output":"1f3c3-1f3fd-200d-2642-fe0f","uc_match":"1f3c3-1f3fd-2642-fe0f","uc_greedy":"1f3c3-1f3fd-2642","shortnames":[":man_running_medium_skin_tone:"],"category":"people"},":man_running_tone4:":{"uc_base":"1f3c3-1f3fe-2642","uc_output":"1f3c3-1f3fe-200d-2642-fe0f","uc_match":"1f3c3-1f3fe-2642-fe0f","uc_greedy":"1f3c3-1f3fe-2642","shortnames":[":man_running_medium_dark_skin_tone:"],"category":"people"},":man_running_tone5:":{"uc_base":"1f3c3-1f3ff-2642","uc_output":"1f3c3-1f3ff-200d-2642-fe0f","uc_match":"1f3c3-1f3ff-2642-fe0f","uc_greedy":"1f3c3-1f3ff-2642","shortnames":[":man_running_dark_skin_tone:"],"category":"people"},":man_shrugging_tone1:":{"uc_base":"1f937-1f3fb-2642","uc_output":"1f937-1f3fb-200d-2642-fe0f","uc_match":"1f937-1f3fb-2642-fe0f","uc_greedy":"1f937-1f3fb-2642","shortnames":[":man_shrugging_light_skin_tone:"],"category":"people"},":man_shrugging_tone2:":{"uc_base":"1f937-1f3fc-2642","uc_output":"1f937-1f3fc-200d-2642-fe0f","uc_match":"1f937-1f3fc-2642-fe0f","uc_greedy":"1f937-1f3fc-2642","shortnames":[":man_shrugging_medium_light_skin_tone:"],"category":"people"},":man_shrugging_tone3:":{"uc_base":"1f937-1f3fd-2642","uc_output":"1f937-1f3fd-200d-2642-fe0f","uc_match":"1f937-1f3fd-2642-fe0f","uc_greedy":"1f937-1f3fd-2642","shortnames":[":man_shrugging_medium_skin_tone:"],"category":"people"},":man_shrugging_tone4:":{"uc_base":"1f937-1f3fe-2642","uc_output":"1f937-1f3fe-200d-2642-fe0f","uc_match":"1f937-1f3fe-2642-fe0f","uc_greedy":"1f937-1f3fe-2642","shortnames":[":man_shrugging_medium_dark_skin_tone:"],"category":"people"},":man_shrugging_tone5:":{"uc_base":"1f937-1f3ff-2642","uc_output":"1f937-1f3ff-200d-2642-fe0f","uc_match":"1f937-1f3ff-2642-fe0f","uc_greedy":"1f937-1f3ff-2642","shortnames":[":man_shrugging_dark_skin_tone:"],"category":"people"},":man_surfing_tone1:":{"uc_base":"1f3c4-1f3fb-2642","uc_output":"1f3c4-1f3fb-200d-2642-fe0f","uc_match":"1f3c4-1f3fb-2642-fe0f","uc_greedy":"1f3c4-1f3fb-2642","shortnames":[":man_surfing_light_skin_tone:"],"category":"activity"},":man_surfing_tone2:":{"uc_base":"1f3c4-1f3fc-2642","uc_output":"1f3c4-1f3fc-200d-2642-fe0f","uc_match":"1f3c4-1f3fc-2642-fe0f","uc_greedy":"1f3c4-1f3fc-2642","shortnames":[":man_surfing_medium_light_skin_tone:"],"category":"activity"},":man_surfing_tone3:":{"uc_base":"1f3c4-1f3fd-2642","uc_output":"1f3c4-1f3fd-200d-2642-fe0f","uc_match":"1f3c4-1f3fd-2642-fe0f","uc_greedy":"1f3c4-1f3fd-2642","shortnames":[":man_surfing_medium_skin_tone:"],"category":"activity"},":man_surfing_tone4:":{"uc_base":"1f3c4-1f3fe-2642","uc_output":"1f3c4-1f3fe-200d-2642-fe0f","uc_match":"1f3c4-1f3fe-2642-fe0f","uc_greedy":"1f3c4-1f3fe-2642","shortnames":[":man_surfing_medium_dark_skin_tone:"],"category":"activity"},":man_surfing_tone5:":{"uc_base":"1f3c4-1f3ff-2642","uc_output":"1f3c4-1f3ff-200d-2642-fe0f","uc_match":"1f3c4-1f3ff-2642-fe0f","uc_greedy":"1f3c4-1f3ff-2642","shortnames":[":man_surfing_dark_skin_tone:"],"category":"activity"},":man_swimming_tone1:":{"uc_base":"1f3ca-1f3fb-2642","uc_output":"1f3ca-1f3fb-200d-2642-fe0f","uc_match":"1f3ca-1f3fb-2642-fe0f","uc_greedy":"1f3ca-1f3fb-2642","shortnames":[":man_swimming_light_skin_tone:"],"category":"activity"},":man_swimming_tone2:":{"uc_base":"1f3ca-1f3fc-2642","uc_output":"1f3ca-1f3fc-200d-2642-fe0f","uc_match":"1f3ca-1f3fc-2642-fe0f","uc_greedy":"1f3ca-1f3fc-2642","shortnames":[":man_swimming_medium_light_skin_tone:"],"category":"activity"},":man_swimming_tone3:":{"uc_base":"1f3ca-1f3fd-2642","uc_output":"1f3ca-1f3fd-200d-2642-fe0f","uc_match":"1f3ca-1f3fd-2642-fe0f","uc_greedy":"1f3ca-1f3fd-2642","shortnames":[":man_swimming_medium_skin_tone:"],"category":"activity"},":man_swimming_tone4:":{"uc_base":"1f3ca-1f3fe-2642","uc_output":"1f3ca-1f3fe-200d-2642-fe0f","uc_match":"1f3ca-1f3fe-2642-fe0f","uc_greedy":"1f3ca-1f3fe-2642","shortnames":[":man_swimming_medium_dark_skin_tone:"],"category":"activity"},":man_swimming_tone5:":{"uc_base":"1f3ca-1f3ff-2642","uc_output":"1f3ca-1f3ff-200d-2642-fe0f","uc_match":"1f3ca-1f3ff-2642-fe0f","uc_greedy":"1f3ca-1f3ff-2642","shortnames":[":man_swimming_dark_skin_tone:"],"category":"activity"},":man_tipping_hand_tone1:":{"uc_base":"1f481-1f3fb-2642","uc_output":"1f481-1f3fb-200d-2642-fe0f","uc_match":"1f481-1f3fb-2642-fe0f","uc_greedy":"1f481-1f3fb-2642","shortnames":[":man_tipping_hand_light_skin_tone:"],"category":"people"},":man_tipping_hand_tone2:":{"uc_base":"1f481-1f3fc-2642","uc_output":"1f481-1f3fc-200d-2642-fe0f","uc_match":"1f481-1f3fc-2642-fe0f","uc_greedy":"1f481-1f3fc-2642","shortnames":[":man_tipping_hand_medium_light_skin_tone:"],"category":"people"},":man_tipping_hand_tone3:":{"uc_base":"1f481-1f3fd-2642","uc_output":"1f481-1f3fd-200d-2642-fe0f","uc_match":"1f481-1f3fd-2642-fe0f","uc_greedy":"1f481-1f3fd-2642","shortnames":[":man_tipping_hand_medium_skin_tone:"],"category":"people"},":man_tipping_hand_tone4:":{"uc_base":"1f481-1f3fe-2642","uc_output":"1f481-1f3fe-200d-2642-fe0f","uc_match":"1f481-1f3fe-2642-fe0f","uc_greedy":"1f481-1f3fe-2642","shortnames":[":man_tipping_hand_medium_dark_skin_tone:"],"category":"people"},":man_tipping_hand_tone5:":{"uc_base":"1f481-1f3ff-2642","uc_output":"1f481-1f3ff-200d-2642-fe0f","uc_match":"1f481-1f3ff-2642-fe0f","uc_greedy":"1f481-1f3ff-2642","shortnames":[":man_tipping_hand_dark_skin_tone:"],"category":"people"},":man_vampire_tone1:":{"uc_base":"1f9db-1f3fb-2642","uc_output":"1f9db-1f3fb-200d-2642-fe0f","uc_match":"1f9db-1f3fb-2642-fe0f","uc_greedy":"1f9db-1f3fb-2642","shortnames":[":man_vampire_light_skin_tone:"],"category":"people"},":man_vampire_tone2:":{"uc_base":"1f9db-1f3fc-2642","uc_output":"1f9db-1f3fc-200d-2642-fe0f","uc_match":"1f9db-1f3fc-2642-fe0f","uc_greedy":"1f9db-1f3fc-2642","shortnames":[":man_vampire_medium_light_skin_tone:"],"category":"people"},":man_vampire_tone3:":{"uc_base":"1f9db-1f3fd-2642","uc_output":"1f9db-1f3fd-200d-2642-fe0f","uc_match":"1f9db-1f3fd-2642-fe0f","uc_greedy":"1f9db-1f3fd-2642","shortnames":[":man_vampire_medium_skin_tone:"],"category":"people"},":man_vampire_tone4:":{"uc_base":"1f9db-1f3fe-2642","uc_output":"1f9db-1f3fe-200d-2642-fe0f","uc_match":"1f9db-1f3fe-2642-fe0f","uc_greedy":"1f9db-1f3fe-2642","shortnames":[":man_vampire_medium_dark_skin_tone:"],"category":"people"},":man_vampire_tone5:":{"uc_base":"1f9db-1f3ff-2642","uc_output":"1f9db-1f3ff-200d-2642-fe0f","uc_match":"1f9db-1f3ff-2642-fe0f","uc_greedy":"1f9db-1f3ff-2642","shortnames":[":man_vampire_dark_skin_tone:"],"category":"people"},":man_walking_tone1:":{"uc_base":"1f6b6-1f3fb-2642","uc_output":"1f6b6-1f3fb-200d-2642-fe0f","uc_match":"1f6b6-1f3fb-2642-fe0f","uc_greedy":"1f6b6-1f3fb-2642","shortnames":[":man_walking_light_skin_tone:"],"category":"people"},":man_walking_tone2:":{"uc_base":"1f6b6-1f3fc-2642","uc_output":"1f6b6-1f3fc-200d-2642-fe0f","uc_match":"1f6b6-1f3fc-2642-fe0f","uc_greedy":"1f6b6-1f3fc-2642","shortnames":[":man_walking_medium_light_skin_tone:"],"category":"people"},":man_walking_tone3:":{"uc_base":"1f6b6-1f3fd-2642","uc_output":"1f6b6-1f3fd-200d-2642-fe0f","uc_match":"1f6b6-1f3fd-2642-fe0f","uc_greedy":"1f6b6-1f3fd-2642","shortnames":[":man_walking_medium_skin_tone:"],"category":"people"},":man_walking_tone4:":{"uc_base":"1f6b6-1f3fe-2642","uc_output":"1f6b6-1f3fe-200d-2642-fe0f","uc_match":"1f6b6-1f3fe-2642-fe0f","uc_greedy":"1f6b6-1f3fe-2642","shortnames":[":man_walking_medium_dark_skin_tone:"],"category":"people"},":man_walking_tone5:":{"uc_base":"1f6b6-1f3ff-2642","uc_output":"1f6b6-1f3ff-200d-2642-fe0f","uc_match":"1f6b6-1f3ff-2642-fe0f","uc_greedy":"1f6b6-1f3ff-2642","shortnames":[":man_walking_dark_skin_tone:"],"category":"people"},":man_wearing_turban_tone1:":{"uc_base":"1f473-1f3fb-2642","uc_output":"1f473-1f3fb-200d-2642-fe0f","uc_match":"1f473-1f3fb-2642-fe0f","uc_greedy":"1f473-1f3fb-2642","shortnames":[":man_wearing_turban_light_skin_tone:"],"category":"people"},":man_wearing_turban_tone2:":{"uc_base":"1f473-1f3fc-2642","uc_output":"1f473-1f3fc-200d-2642-fe0f","uc_match":"1f473-1f3fc-2642-fe0f","uc_greedy":"1f473-1f3fc-2642","shortnames":[":man_wearing_turban_medium_light_skin_tone:"],"category":"people"},":man_wearing_turban_tone3:":{"uc_base":"1f473-1f3fd-2642","uc_output":"1f473-1f3fd-200d-2642-fe0f","uc_match":"1f473-1f3fd-2642-fe0f","uc_greedy":"1f473-1f3fd-2642","shortnames":[":man_wearing_turban_medium_skin_tone:"],"category":"people"},":man_wearing_turban_tone4:":{"uc_base":"1f473-1f3fe-2642","uc_output":"1f473-1f3fe-200d-2642-fe0f","uc_match":"1f473-1f3fe-2642-fe0f","uc_greedy":"1f473-1f3fe-2642","shortnames":[":man_wearing_turban_medium_dark_skin_tone:"],"category":"people"},":man_wearing_turban_tone5:":{"uc_base":"1f473-1f3ff-2642","uc_output":"1f473-1f3ff-200d-2642-fe0f","uc_match":"1f473-1f3ff-2642-fe0f","uc_greedy":"1f473-1f3ff-2642","shortnames":[":man_wearing_turban_dark_skin_tone:"],"category":"people"},":mermaid_tone1:":{"uc_base":"1f9dc-1f3fb-2640","uc_output":"1f9dc-1f3fb-200d-2640-fe0f","uc_match":"1f9dc-1f3fb-2640-fe0f","uc_greedy":"1f9dc-1f3fb-2640","shortnames":[":mermaid_light_skin_tone:"],"category":"people"},":mermaid_tone2:":{"uc_base":"1f9dc-1f3fc-2640","uc_output":"1f9dc-1f3fc-200d-2640-fe0f","uc_match":"1f9dc-1f3fc-2640-fe0f","uc_greedy":"1f9dc-1f3fc-2640","shortnames":[":mermaid_medium_light_skin_tone:"],"category":"people"},":mermaid_tone3:":{"uc_base":"1f9dc-1f3fd-2640","uc_output":"1f9dc-1f3fd-200d-2640-fe0f","uc_match":"1f9dc-1f3fd-2640-fe0f","uc_greedy":"1f9dc-1f3fd-2640","shortnames":[":mermaid_medium_skin_tone:"],"category":"people"},":mermaid_tone4:":{"uc_base":"1f9dc-1f3fe-2640","uc_output":"1f9dc-1f3fe-200d-2640-fe0f","uc_match":"1f9dc-1f3fe-2640-fe0f","uc_greedy":"1f9dc-1f3fe-2640","shortnames":[":mermaid_medium_dark_skin_tone:"],"category":"people"},":mermaid_tone5:":{"uc_base":"1f9dc-1f3ff-2640","uc_output":"1f9dc-1f3ff-200d-2640-fe0f","uc_match":"1f9dc-1f3ff-2640-fe0f","uc_greedy":"1f9dc-1f3ff-2640","shortnames":[":mermaid_dark_skin_tone:"],"category":"people"},":merman_tone1:":{"uc_base":"1f9dc-1f3fb-2642","uc_output":"1f9dc-1f3fb-200d-2642-fe0f","uc_match":"1f9dc-1f3fb-2642-fe0f","uc_greedy":"1f9dc-1f3fb-2642","shortnames":[":merman_light_skin_tone:"],"category":"people"},":merman_tone2:":{"uc_base":"1f9dc-1f3fc-2642","uc_output":"1f9dc-1f3fc-200d-2642-fe0f","uc_match":"1f9dc-1f3fc-2642-fe0f","uc_greedy":"1f9dc-1f3fc-2642","shortnames":[":merman_medium_light_skin_tone:"],"category":"people"},":merman_tone3:":{"uc_base":"1f9dc-1f3fd-2642","uc_output":"1f9dc-1f3fd-200d-2642-fe0f","uc_match":"1f9dc-1f3fd-2642-fe0f","uc_greedy":"1f9dc-1f3fd-2642","shortnames":[":merman_medium_skin_tone:"],"category":"people"},":merman_tone4:":{"uc_base":"1f9dc-1f3fe-2642","uc_output":"1f9dc-1f3fe-200d-2642-fe0f","uc_match":"1f9dc-1f3fe-2642-fe0f","uc_greedy":"1f9dc-1f3fe-2642","shortnames":[":merman_medium_dark_skin_tone:"],"category":"people"},":merman_tone5:":{"uc_base":"1f9dc-1f3ff-2642","uc_output":"1f9dc-1f3ff-200d-2642-fe0f","uc_match":"1f9dc-1f3ff-2642-fe0f","uc_greedy":"1f9dc-1f3ff-2642","shortnames":[":merman_dark_skin_tone:"],"category":"people"},":woman_biking_tone1:":{"uc_base":"1f6b4-1f3fb-2640","uc_output":"1f6b4-1f3fb-200d-2640-fe0f","uc_match":"1f6b4-1f3fb-2640-fe0f","uc_greedy":"1f6b4-1f3fb-2640","shortnames":[":woman_biking_light_skin_tone:"],"category":"activity"},":woman_biking_tone2:":{"uc_base":"1f6b4-1f3fc-2640","uc_output":"1f6b4-1f3fc-200d-2640-fe0f","uc_match":"1f6b4-1f3fc-2640-fe0f","uc_greedy":"1f6b4-1f3fc-2640","shortnames":[":woman_biking_medium_light_skin_tone:"],"category":"activity"},":woman_biking_tone3:":{"uc_base":"1f6b4-1f3fd-2640","uc_output":"1f6b4-1f3fd-200d-2640-fe0f","uc_match":"1f6b4-1f3fd-2640-fe0f","uc_greedy":"1f6b4-1f3fd-2640","shortnames":[":woman_biking_medium_skin_tone:"],"category":"activity"},":woman_biking_tone4:":{"uc_base":"1f6b4-1f3fe-2640","uc_output":"1f6b4-1f3fe-200d-2640-fe0f","uc_match":"1f6b4-1f3fe-2640-fe0f","uc_greedy":"1f6b4-1f3fe-2640","shortnames":[":woman_biking_medium_dark_skin_tone:"],"category":"activity"},":woman_biking_tone5:":{"uc_base":"1f6b4-1f3ff-2640","uc_output":"1f6b4-1f3ff-200d-2640-fe0f","uc_match":"1f6b4-1f3ff-2640-fe0f","uc_greedy":"1f6b4-1f3ff-2640","shortnames":[":woman_biking_dark_skin_tone:"],"category":"activity"},":woman_bowing_tone1:":{"uc_base":"1f647-1f3fb-2640","uc_output":"1f647-1f3fb-200d-2640-fe0f","uc_match":"1f647-1f3fb-2640-fe0f","uc_greedy":"1f647-1f3fb-2640","shortnames":[":woman_bowing_light_skin_tone:"],"category":"people"},":woman_bowing_tone2:":{"uc_base":"1f647-1f3fc-2640","uc_output":"1f647-1f3fc-200d-2640-fe0f","uc_match":"1f647-1f3fc-2640-fe0f","uc_greedy":"1f647-1f3fc-2640","shortnames":[":woman_bowing_medium_light_skin_tone:"],"category":"people"},":woman_bowing_tone3:":{"uc_base":"1f647-1f3fd-2640","uc_output":"1f647-1f3fd-200d-2640-fe0f","uc_match":"1f647-1f3fd-2640-fe0f","uc_greedy":"1f647-1f3fd-2640","shortnames":[":woman_bowing_medium_skin_tone:"],"category":"people"},":woman_bowing_tone4:":{"uc_base":"1f647-1f3fe-2640","uc_output":"1f647-1f3fe-200d-2640-fe0f","uc_match":"1f647-1f3fe-2640-fe0f","uc_greedy":"1f647-1f3fe-2640","shortnames":[":woman_bowing_medium_dark_skin_tone:"],"category":"people"},":woman_bowing_tone5:":{"uc_base":"1f647-1f3ff-2640","uc_output":"1f647-1f3ff-200d-2640-fe0f","uc_match":"1f647-1f3ff-2640-fe0f","uc_greedy":"1f647-1f3ff-2640","shortnames":[":woman_bowing_dark_skin_tone:"],"category":"people"},":woman_cartwheeling_tone1:":{"uc_base":"1f938-1f3fb-2640","uc_output":"1f938-1f3fb-200d-2640-fe0f","uc_match":"1f938-1f3fb-2640-fe0f","uc_greedy":"1f938-1f3fb-2640","shortnames":[":woman_cartwheeling_light_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone2:":{"uc_base":"1f938-1f3fc-2640","uc_output":"1f938-1f3fc-200d-2640-fe0f","uc_match":"1f938-1f3fc-2640-fe0f","uc_greedy":"1f938-1f3fc-2640","shortnames":[":woman_cartwheeling_medium_light_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone3:":{"uc_base":"1f938-1f3fd-2640","uc_output":"1f938-1f3fd-200d-2640-fe0f","uc_match":"1f938-1f3fd-2640-fe0f","uc_greedy":"1f938-1f3fd-2640","shortnames":[":woman_cartwheeling_medium_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone4:":{"uc_base":"1f938-1f3fe-2640","uc_output":"1f938-1f3fe-200d-2640-fe0f","uc_match":"1f938-1f3fe-2640-fe0f","uc_greedy":"1f938-1f3fe-2640","shortnames":[":woman_cartwheeling_medium_dark_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone5:":{"uc_base":"1f938-1f3ff-2640","uc_output":"1f938-1f3ff-200d-2640-fe0f","uc_match":"1f938-1f3ff-2640-fe0f","uc_greedy":"1f938-1f3ff-2640","shortnames":[":woman_cartwheeling_dark_skin_tone:"],"category":"activity"},":woman_climbing_tone1:":{"uc_base":"1f9d7-1f3fb-2640","uc_output":"1f9d7-1f3fb-200d-2640-fe0f","uc_match":"1f9d7-1f3fb-2640-fe0f","uc_greedy":"1f9d7-1f3fb-2640","shortnames":[":woman_climbing_light_skin_tone:"],"category":"activity"},":woman_climbing_tone2:":{"uc_base":"1f9d7-1f3fc-2640","uc_output":"1f9d7-1f3fc-200d-2640-fe0f","uc_match":"1f9d7-1f3fc-2640-fe0f","uc_greedy":"1f9d7-1f3fc-2640","shortnames":[":woman_climbing_medium_light_skin_tone:"],"category":"activity"},":woman_climbing_tone3:":{"uc_base":"1f9d7-1f3fd-2640","uc_output":"1f9d7-1f3fd-200d-2640-fe0f","uc_match":"1f9d7-1f3fd-2640-fe0f","uc_greedy":"1f9d7-1f3fd-2640","shortnames":[":woman_climbing_medium_skin_tone:"],"category":"activity"},":woman_climbing_tone4:":{"uc_base":"1f9d7-1f3fe-2640","uc_output":"1f9d7-1f3fe-200d-2640-fe0f","uc_match":"1f9d7-1f3fe-2640-fe0f","uc_greedy":"1f9d7-1f3fe-2640","shortnames":[":woman_climbing_medium_dark_skin_tone:"],"category":"activity"},":woman_climbing_tone5:":{"uc_base":"1f9d7-1f3ff-2640","uc_output":"1f9d7-1f3ff-200d-2640-fe0f","uc_match":"1f9d7-1f3ff-2640-fe0f","uc_greedy":"1f9d7-1f3ff-2640","shortnames":[":woman_climbing_dark_skin_tone:"],"category":"activity"},":woman_construction_worker_tone1:":{"uc_base":"1f477-1f3fb-2640","uc_output":"1f477-1f3fb-200d-2640-fe0f","uc_match":"1f477-1f3fb-2640-fe0f","uc_greedy":"1f477-1f3fb-2640","shortnames":[":woman_construction_worker_light_skin_tone:"],"category":"people"},":woman_construction_worker_tone2:":{"uc_base":"1f477-1f3fc-2640","uc_output":"1f477-1f3fc-200d-2640-fe0f","uc_match":"1f477-1f3fc-2640-fe0f","uc_greedy":"1f477-1f3fc-2640","shortnames":[":woman_construction_worker_medium_light_skin_tone:"],"category":"people"},":woman_construction_worker_tone3:":{"uc_base":"1f477-1f3fd-2640","uc_output":"1f477-1f3fd-200d-2640-fe0f","uc_match":"1f477-1f3fd-2640-fe0f","uc_greedy":"1f477-1f3fd-2640","shortnames":[":woman_construction_worker_medium_skin_tone:"],"category":"people"},":woman_construction_worker_tone4:":{"uc_base":"1f477-1f3fe-2640","uc_output":"1f477-1f3fe-200d-2640-fe0f","uc_match":"1f477-1f3fe-2640-fe0f","uc_greedy":"1f477-1f3fe-2640","shortnames":[":woman_construction_worker_medium_dark_skin_tone:"],"category":"people"},":woman_construction_worker_tone5:":{"uc_base":"1f477-1f3ff-2640","uc_output":"1f477-1f3ff-200d-2640-fe0f","uc_match":"1f477-1f3ff-2640-fe0f","uc_greedy":"1f477-1f3ff-2640","shortnames":[":woman_construction_worker_dark_skin_tone:"],"category":"people"},":woman_detective_tone1:":{"uc_base":"1f575-1f3fb-2640","uc_output":"1f575-1f3fb-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fb-2640-fe0f","uc_greedy":"1f575-1f3fb-2640","shortnames":[":woman_detective_light_skin_tone:"],"category":"people"},":woman_detective_tone2:":{"uc_base":"1f575-1f3fc-2640","uc_output":"1f575-1f3fc-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fc-2640-fe0f","uc_greedy":"1f575-1f3fc-2640","shortnames":[":woman_detective_medium_light_skin_tone:"],"category":"people"},":woman_detective_tone3:":{"uc_base":"1f575-1f3fd-2640","uc_output":"1f575-1f3fd-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fd-2640-fe0f","uc_greedy":"1f575-1f3fd-2640","shortnames":[":woman_detective_medium_skin_tone:"],"category":"people"},":woman_detective_tone4:":{"uc_base":"1f575-1f3fe-2640","uc_output":"1f575-1f3fe-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fe-2640-fe0f","uc_greedy":"1f575-1f3fe-2640","shortnames":[":woman_detective_medium_dark_skin_tone:"],"category":"people"},":woman_detective_tone5:":{"uc_base":"1f575-1f3ff-2640","uc_output":"1f575-1f3ff-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3ff-2640-fe0f","uc_greedy":"1f575-1f3ff-2640","shortnames":[":woman_detective_dark_skin_tone:"],"category":"people"},":woman_elf_tone1:":{"uc_base":"1f9dd-1f3fb-2640","uc_output":"1f9dd-1f3fb-200d-2640-fe0f","uc_match":"1f9dd-1f3fb-2640-fe0f","uc_greedy":"1f9dd-1f3fb-2640","shortnames":[":woman_elf_light_skin_tone:"],"category":"people"},":woman_elf_tone2:":{"uc_base":"1f9dd-1f3fc-2640","uc_output":"1f9dd-1f3fc-200d-2640-fe0f","uc_match":"1f9dd-1f3fc-2640-fe0f","uc_greedy":"1f9dd-1f3fc-2640","shortnames":[":woman_elf_medium_light_skin_tone:"],"category":"people"},":woman_elf_tone3:":{"uc_base":"1f9dd-1f3fd-2640","uc_output":"1f9dd-1f3fd-200d-2640-fe0f","uc_match":"1f9dd-1f3fd-2640-fe0f","uc_greedy":"1f9dd-1f3fd-2640","shortnames":[":woman_elf_medium_skin_tone:"],"category":"people"},":woman_elf_tone4:":{"uc_base":"1f9dd-1f3fe-2640","uc_output":"1f9dd-1f3fe-200d-2640-fe0f","uc_match":"1f9dd-1f3fe-2640-fe0f","uc_greedy":"1f9dd-1f3fe-2640","shortnames":[":woman_elf_medium_dark_skin_tone:"],"category":"people"},":woman_elf_tone5:":{"uc_base":"1f9dd-1f3ff-2640","uc_output":"1f9dd-1f3ff-200d-2640-fe0f","uc_match":"1f9dd-1f3ff-2640-fe0f","uc_greedy":"1f9dd-1f3ff-2640","shortnames":[":woman_elf_dark_skin_tone:"],"category":"people"},":woman_facepalming_tone1:":{"uc_base":"1f926-1f3fb-2640","uc_output":"1f926-1f3fb-200d-2640-fe0f","uc_match":"1f926-1f3fb-2640-fe0f","uc_greedy":"1f926-1f3fb-2640","shortnames":[":woman_facepalming_light_skin_tone:"],"category":"people"},":woman_facepalming_tone2:":{"uc_base":"1f926-1f3fc-2640","uc_output":"1f926-1f3fc-200d-2640-fe0f","uc_match":"1f926-1f3fc-2640-fe0f","uc_greedy":"1f926-1f3fc-2640","shortnames":[":woman_facepalming_medium_light_skin_tone:"],"category":"people"},":woman_facepalming_tone3:":{"uc_base":"1f926-1f3fd-2640","uc_output":"1f926-1f3fd-200d-2640-fe0f","uc_match":"1f926-1f3fd-2640-fe0f","uc_greedy":"1f926-1f3fd-2640","shortnames":[":woman_facepalming_medium_skin_tone:"],"category":"people"},":woman_facepalming_tone4:":{"uc_base":"1f926-1f3fe-2640","uc_output":"1f926-1f3fe-200d-2640-fe0f","uc_match":"1f926-1f3fe-2640-fe0f","uc_greedy":"1f926-1f3fe-2640","shortnames":[":woman_facepalming_medium_dark_skin_tone:"],"category":"people"},":woman_facepalming_tone5:":{"uc_base":"1f926-1f3ff-2640","uc_output":"1f926-1f3ff-200d-2640-fe0f","uc_match":"1f926-1f3ff-2640-fe0f","uc_greedy":"1f926-1f3ff-2640","shortnames":[":woman_facepalming_dark_skin_tone:"],"category":"people"},":woman_fairy_tone1:":{"uc_base":"1f9da-1f3fb-2640","uc_output":"1f9da-1f3fb-200d-2640-fe0f","uc_match":"1f9da-1f3fb-2640-fe0f","uc_greedy":"1f9da-1f3fb-2640","shortnames":[":woman_fairy_light_skin_tone:"],"category":"people"},":woman_fairy_tone2:":{"uc_base":"1f9da-1f3fc-2640","uc_output":"1f9da-1f3fc-200d-2640-fe0f","uc_match":"1f9da-1f3fc-2640-fe0f","uc_greedy":"1f9da-1f3fc-2640","shortnames":[":woman_fairy_medium_light_skin_tone:"],"category":"people"},":woman_fairy_tone3:":{"uc_base":"1f9da-1f3fd-2640","uc_output":"1f9da-1f3fd-200d-2640-fe0f","uc_match":"1f9da-1f3fd-2640-fe0f","uc_greedy":"1f9da-1f3fd-2640","shortnames":[":woman_fairy_medium_skin_tone:"],"category":"people"},":woman_fairy_tone4:":{"uc_base":"1f9da-1f3fe-2640","uc_output":"1f9da-1f3fe-200d-2640-fe0f","uc_match":"1f9da-1f3fe-2640-fe0f","uc_greedy":"1f9da-1f3fe-2640","shortnames":[":woman_fairy_medium_dark_skin_tone:"],"category":"people"},":woman_fairy_tone5:":{"uc_base":"1f9da-1f3ff-2640","uc_output":"1f9da-1f3ff-200d-2640-fe0f","uc_match":"1f9da-1f3ff-2640-fe0f","uc_greedy":"1f9da-1f3ff-2640","shortnames":[":woman_fairy_dark_skin_tone:"],"category":"people"},":woman_frowning_tone1:":{"uc_base":"1f64d-1f3fb-2640","uc_output":"1f64d-1f3fb-200d-2640-fe0f","uc_match":"1f64d-1f3fb-2640-fe0f","uc_greedy":"1f64d-1f3fb-2640","shortnames":[":woman_frowning_light_skin_tone:"],"category":"people"},":woman_frowning_tone2:":{"uc_base":"1f64d-1f3fc-2640","uc_output":"1f64d-1f3fc-200d-2640-fe0f","uc_match":"1f64d-1f3fc-2640-fe0f","uc_greedy":"1f64d-1f3fc-2640","shortnames":[":woman_frowning_medium_light_skin_tone:"],"category":"people"},":woman_frowning_tone3:":{"uc_base":"1f64d-1f3fd-2640","uc_output":"1f64d-1f3fd-200d-2640-fe0f","uc_match":"1f64d-1f3fd-2640-fe0f","uc_greedy":"1f64d-1f3fd-2640","shortnames":[":woman_frowning_medium_skin_tone:"],"category":"people"},":woman_frowning_tone4:":{"uc_base":"1f64d-1f3fe-2640","uc_output":"1f64d-1f3fe-200d-2640-fe0f","uc_match":"1f64d-1f3fe-2640-fe0f","uc_greedy":"1f64d-1f3fe-2640","shortnames":[":woman_frowning_medium_dark_skin_tone:"],"category":"people"},":woman_frowning_tone5:":{"uc_base":"1f64d-1f3ff-2640","uc_output":"1f64d-1f3ff-200d-2640-fe0f","uc_match":"1f64d-1f3ff-2640-fe0f","uc_greedy":"1f64d-1f3ff-2640","shortnames":[":woman_frowning_dark_skin_tone:"],"category":"people"},":woman_gesturing_no_tone1:":{"uc_base":"1f645-1f3fb-2640","uc_output":"1f645-1f3fb-200d-2640-fe0f","uc_match":"1f645-1f3fb-2640-fe0f","uc_greedy":"1f645-1f3fb-2640","shortnames":[":woman_gesturing_no_light_skin_tone:"],"category":"people"},":woman_gesturing_no_tone2:":{"uc_base":"1f645-1f3fc-2640","uc_output":"1f645-1f3fc-200d-2640-fe0f","uc_match":"1f645-1f3fc-2640-fe0f","uc_greedy":"1f645-1f3fc-2640","shortnames":[":woman_gesturing_no_medium_light_skin_tone:"],"category":"people"},":woman_gesturing_no_tone3:":{"uc_base":"1f645-1f3fd-2640","uc_output":"1f645-1f3fd-200d-2640-fe0f","uc_match":"1f645-1f3fd-2640-fe0f","uc_greedy":"1f645-1f3fd-2640","shortnames":[":woman_gesturing_no_medium_skin_tone:"],"category":"people"},":woman_gesturing_no_tone4:":{"uc_base":"1f645-1f3fe-2640","uc_output":"1f645-1f3fe-200d-2640-fe0f","uc_match":"1f645-1f3fe-2640-fe0f","uc_greedy":"1f645-1f3fe-2640","shortnames":[":woman_gesturing_no_medium_dark_skin_tone:"],"category":"people"},":woman_gesturing_no_tone5:":{"uc_base":"1f645-1f3ff-2640","uc_output":"1f645-1f3ff-200d-2640-fe0f","uc_match":"1f645-1f3ff-2640-fe0f","uc_greedy":"1f645-1f3ff-2640","shortnames":[":woman_gesturing_no_dark_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone1:":{"uc_base":"1f646-1f3fb-2640","uc_output":"1f646-1f3fb-200d-2640-fe0f","uc_match":"1f646-1f3fb-2640-fe0f","uc_greedy":"1f646-1f3fb-2640","shortnames":[":woman_gesturing_ok_light_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone2:":{"uc_base":"1f646-1f3fc-2640","uc_output":"1f646-1f3fc-200d-2640-fe0f","uc_match":"1f646-1f3fc-2640-fe0f","uc_greedy":"1f646-1f3fc-2640","shortnames":[":woman_gesturing_ok_medium_light_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone3:":{"uc_base":"1f646-1f3fd-2640","uc_output":"1f646-1f3fd-200d-2640-fe0f","uc_match":"1f646-1f3fd-2640-fe0f","uc_greedy":"1f646-1f3fd-2640","shortnames":[":woman_gesturing_ok_medium_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone4:":{"uc_base":"1f646-1f3fe-2640","uc_output":"1f646-1f3fe-200d-2640-fe0f","uc_match":"1f646-1f3fe-2640-fe0f","uc_greedy":"1f646-1f3fe-2640","shortnames":[":woman_gesturing_ok_medium_dark_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone5:":{"uc_base":"1f646-1f3ff-2640","uc_output":"1f646-1f3ff-200d-2640-fe0f","uc_match":"1f646-1f3ff-2640-fe0f","uc_greedy":"1f646-1f3ff-2640","shortnames":[":woman_gesturing_ok_dark_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone1:":{"uc_base":"1f486-1f3fb-2640","uc_output":"1f486-1f3fb-200d-2640-fe0f","uc_match":"1f486-1f3fb-2640-fe0f","uc_greedy":"1f486-1f3fb-2640","shortnames":[":woman_getting_face_massage_light_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone2:":{"uc_base":"1f486-1f3fc-2640","uc_output":"1f486-1f3fc-200d-2640-fe0f","uc_match":"1f486-1f3fc-2640-fe0f","uc_greedy":"1f486-1f3fc-2640","shortnames":[":woman_getting_face_massage_medium_light_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone3:":{"uc_base":"1f486-1f3fd-2640","uc_output":"1f486-1f3fd-200d-2640-fe0f","uc_match":"1f486-1f3fd-2640-fe0f","uc_greedy":"1f486-1f3fd-2640","shortnames":[":woman_getting_face_massage_medium_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone4:":{"uc_base":"1f486-1f3fe-2640","uc_output":"1f486-1f3fe-200d-2640-fe0f","uc_match":"1f486-1f3fe-2640-fe0f","uc_greedy":"1f486-1f3fe-2640","shortnames":[":woman_getting_face_massage_medium_dark_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone5:":{"uc_base":"1f486-1f3ff-2640","uc_output":"1f486-1f3ff-200d-2640-fe0f","uc_match":"1f486-1f3ff-2640-fe0f","uc_greedy":"1f486-1f3ff-2640","shortnames":[":woman_getting_face_massage_dark_skin_tone:"],"category":"people"},":woman_getting_haircut_tone1:":{"uc_base":"1f487-1f3fb-2640","uc_output":"1f487-1f3fb-200d-2640-fe0f","uc_match":"1f487-1f3fb-2640-fe0f","uc_greedy":"1f487-1f3fb-2640","shortnames":[":woman_getting_haircut_light_skin_tone:"],"category":"people"},":woman_getting_haircut_tone2:":{"uc_base":"1f487-1f3fc-2640","uc_output":"1f487-1f3fc-200d-2640-fe0f","uc_match":"1f487-1f3fc-2640-fe0f","uc_greedy":"1f487-1f3fc-2640","shortnames":[":woman_getting_haircut_medium_light_skin_tone:"],"category":"people"},":woman_getting_haircut_tone3:":{"uc_base":"1f487-1f3fd-2640","uc_output":"1f487-1f3fd-200d-2640-fe0f","uc_match":"1f487-1f3fd-2640-fe0f","uc_greedy":"1f487-1f3fd-2640","shortnames":[":woman_getting_haircut_medium_skin_tone:"],"category":"people"},":woman_getting_haircut_tone4:":{"uc_base":"1f487-1f3fe-2640","uc_output":"1f487-1f3fe-200d-2640-fe0f","uc_match":"1f487-1f3fe-2640-fe0f","uc_greedy":"1f487-1f3fe-2640","shortnames":[":woman_getting_haircut_medium_dark_skin_tone:"],"category":"people"},":woman_getting_haircut_tone5:":{"uc_base":"1f487-1f3ff-2640","uc_output":"1f487-1f3ff-200d-2640-fe0f","uc_match":"1f487-1f3ff-2640-fe0f","uc_greedy":"1f487-1f3ff-2640","shortnames":[":woman_getting_haircut_dark_skin_tone:"],"category":"people"},":woman_golfing_tone1:":{"uc_base":"1f3cc-1f3fb-2640","uc_output":"1f3cc-1f3fb-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fb-2640-fe0f","uc_greedy":"1f3cc-1f3fb-2640","shortnames":[":woman_golfing_light_skin_tone:"],"category":"activity"},":woman_golfing_tone2:":{"uc_base":"1f3cc-1f3fc-2640","uc_output":"1f3cc-1f3fc-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fc-2640-fe0f","uc_greedy":"1f3cc-1f3fc-2640","shortnames":[":woman_golfing_medium_light_skin_tone:"],"category":"activity"},":woman_golfing_tone3:":{"uc_base":"1f3cc-1f3fd-2640","uc_output":"1f3cc-1f3fd-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fd-2640-fe0f","uc_greedy":"1f3cc-1f3fd-2640","shortnames":[":woman_golfing_medium_skin_tone:"],"category":"activity"},":woman_golfing_tone4:":{"uc_base":"1f3cc-1f3fe-2640","uc_output":"1f3cc-1f3fe-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fe-2640-fe0f","uc_greedy":"1f3cc-1f3fe-2640","shortnames":[":woman_golfing_medium_dark_skin_tone:"],"category":"activity"},":woman_golfing_tone5:":{"uc_base":"1f3cc-1f3ff-2640","uc_output":"1f3cc-1f3ff-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3ff-2640-fe0f","uc_greedy":"1f3cc-1f3ff-2640","shortnames":[":woman_golfing_dark_skin_tone:"],"category":"activity"},":woman_guard_tone1:":{"uc_base":"1f482-1f3fb-2640","uc_output":"1f482-1f3fb-200d-2640-fe0f","uc_match":"1f482-1f3fb-2640-fe0f","uc_greedy":"1f482-1f3fb-2640","shortnames":[":woman_guard_light_skin_tone:"],"category":"people"},":woman_guard_tone2:":{"uc_base":"1f482-1f3fc-2640","uc_output":"1f482-1f3fc-200d-2640-fe0f","uc_match":"1f482-1f3fc-2640-fe0f","uc_greedy":"1f482-1f3fc-2640","shortnames":[":woman_guard_medium_light_skin_tone:"],"category":"people"},":woman_guard_tone3:":{"uc_base":"1f482-1f3fd-2640","uc_output":"1f482-1f3fd-200d-2640-fe0f","uc_match":"1f482-1f3fd-2640-fe0f","uc_greedy":"1f482-1f3fd-2640","shortnames":[":woman_guard_medium_skin_tone:"],"category":"people"},":woman_guard_tone4:":{"uc_base":"1f482-1f3fe-2640","uc_output":"1f482-1f3fe-200d-2640-fe0f","uc_match":"1f482-1f3fe-2640-fe0f","uc_greedy":"1f482-1f3fe-2640","shortnames":[":woman_guard_medium_dark_skin_tone:"],"category":"people"},":woman_guard_tone5:":{"uc_base":"1f482-1f3ff-2640","uc_output":"1f482-1f3ff-200d-2640-fe0f","uc_match":"1f482-1f3ff-2640-fe0f","uc_greedy":"1f482-1f3ff-2640","shortnames":[":woman_guard_dark_skin_tone:"],"category":"people"},":woman_health_worker_tone1:":{"uc_base":"1f469-1f3fb-2695","uc_output":"1f469-1f3fb-200d-2695-fe0f","uc_match":"1f469-1f3fb-2695-fe0f","uc_greedy":"1f469-1f3fb-2695","shortnames":[":woman_health_worker_light_skin_tone:"],"category":"people"},":woman_health_worker_tone2:":{"uc_base":"1f469-1f3fc-2695","uc_output":"1f469-1f3fc-200d-2695-fe0f","uc_match":"1f469-1f3fc-2695-fe0f","uc_greedy":"1f469-1f3fc-2695","shortnames":[":woman_health_worker_medium_light_skin_tone:"],"category":"people"},":woman_health_worker_tone3:":{"uc_base":"1f469-1f3fd-2695","uc_output":"1f469-1f3fd-200d-2695-fe0f","uc_match":"1f469-1f3fd-2695-fe0f","uc_greedy":"1f469-1f3fd-2695","shortnames":[":woman_health_worker_medium_skin_tone:"],"category":"people"},":woman_health_worker_tone4:":{"uc_base":"1f469-1f3fe-2695","uc_output":"1f469-1f3fe-200d-2695-fe0f","uc_match":"1f469-1f3fe-2695-fe0f","uc_greedy":"1f469-1f3fe-2695","shortnames":[":woman_health_worker_medium_dark_skin_tone:"],"category":"people"},":woman_health_worker_tone5:":{"uc_base":"1f469-1f3ff-2695","uc_output":"1f469-1f3ff-200d-2695-fe0f","uc_match":"1f469-1f3ff-2695-fe0f","uc_greedy":"1f469-1f3ff-2695","shortnames":[":woman_health_worker_dark_skin_tone:"],"category":"people"},":woman_in_lotus_position_tone1:":{"uc_base":"1f9d8-1f3fb-2640","uc_output":"1f9d8-1f3fb-200d-2640-fe0f","uc_match":"1f9d8-1f3fb-2640-fe0f","uc_greedy":"1f9d8-1f3fb-2640","shortnames":[":woman_in_lotus_position_light_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone2:":{"uc_base":"1f9d8-1f3fc-2640","uc_output":"1f9d8-1f3fc-200d-2640-fe0f","uc_match":"1f9d8-1f3fc-2640-fe0f","uc_greedy":"1f9d8-1f3fc-2640","shortnames":[":woman_in_lotus_position_medium_light_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone3:":{"uc_base":"1f9d8-1f3fd-2640","uc_output":"1f9d8-1f3fd-200d-2640-fe0f","uc_match":"1f9d8-1f3fd-2640-fe0f","uc_greedy":"1f9d8-1f3fd-2640","shortnames":[":woman_in_lotus_position_medium_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone4:":{"uc_base":"1f9d8-1f3fe-2640","uc_output":"1f9d8-1f3fe-200d-2640-fe0f","uc_match":"1f9d8-1f3fe-2640-fe0f","uc_greedy":"1f9d8-1f3fe-2640","shortnames":[":woman_in_lotus_position_medium_dark_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone5:":{"uc_base":"1f9d8-1f3ff-2640","uc_output":"1f9d8-1f3ff-200d-2640-fe0f","uc_match":"1f9d8-1f3ff-2640-fe0f","uc_greedy":"1f9d8-1f3ff-2640","shortnames":[":woman_in_lotus_position_dark_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone1:":{"uc_base":"1f9d6-1f3fb-2640","uc_output":"1f9d6-1f3fb-200d-2640-fe0f","uc_match":"1f9d6-1f3fb-2640-fe0f","uc_greedy":"1f9d6-1f3fb-2640","shortnames":[":woman_in_steamy_room_light_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone2:":{"uc_base":"1f9d6-1f3fc-2640","uc_output":"1f9d6-1f3fc-200d-2640-fe0f","uc_match":"1f9d6-1f3fc-2640-fe0f","uc_greedy":"1f9d6-1f3fc-2640","shortnames":[":woman_in_steamy_room_medium_light_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone3:":{"uc_base":"1f9d6-1f3fd-2640","uc_output":"1f9d6-1f3fd-200d-2640-fe0f","uc_match":"1f9d6-1f3fd-2640-fe0f","uc_greedy":"1f9d6-1f3fd-2640","shortnames":[":woman_in_steamy_room_medium_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone4:":{"uc_base":"1f9d6-1f3fe-2640","uc_output":"1f9d6-1f3fe-200d-2640-fe0f","uc_match":"1f9d6-1f3fe-2640-fe0f","uc_greedy":"1f9d6-1f3fe-2640","shortnames":[":woman_in_steamy_room_medium_dark_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone5:":{"uc_base":"1f9d6-1f3ff-2640","uc_output":"1f9d6-1f3ff-200d-2640-fe0f","uc_match":"1f9d6-1f3ff-2640-fe0f","uc_greedy":"1f9d6-1f3ff-2640","shortnames":[":woman_in_steamy_room_dark_skin_tone:"],"category":"activity"},":woman_judge_tone1:":{"uc_base":"1f469-1f3fb-2696","uc_output":"1f469-1f3fb-200d-2696-fe0f","uc_match":"1f469-1f3fb-2696-fe0f","uc_greedy":"1f469-1f3fb-2696","shortnames":[":woman_judge_light_skin_tone:"],"category":"people"},":woman_judge_tone2:":{"uc_base":"1f469-1f3fc-2696","uc_output":"1f469-1f3fc-200d-2696-fe0f","uc_match":"1f469-1f3fc-2696-fe0f","uc_greedy":"1f469-1f3fc-2696","shortnames":[":woman_judge_medium_light_skin_tone:"],"category":"people"},":woman_judge_tone3:":{"uc_base":"1f469-1f3fd-2696","uc_output":"1f469-1f3fd-200d-2696-fe0f","uc_match":"1f469-1f3fd-2696-fe0f","uc_greedy":"1f469-1f3fd-2696","shortnames":[":woman_judge_medium_skin_tone:"],"category":"people"},":woman_judge_tone4:":{"uc_base":"1f469-1f3fe-2696","uc_output":"1f469-1f3fe-200d-2696-fe0f","uc_match":"1f469-1f3fe-2696-fe0f","uc_greedy":"1f469-1f3fe-2696","shortnames":[":woman_judge_medium_dark_skin_tone:"],"category":"people"},":woman_judge_tone5:":{"uc_base":"1f469-1f3ff-2696","uc_output":"1f469-1f3ff-200d-2696-fe0f","uc_match":"1f469-1f3ff-2696-fe0f","uc_greedy":"1f469-1f3ff-2696","shortnames":[":woman_judge_dark_skin_tone:"],"category":"people"},":woman_juggling_tone1:":{"uc_base":"1f939-1f3fb-2640","uc_output":"1f939-1f3fb-200d-2640-fe0f","uc_match":"1f939-1f3fb-2640-fe0f","uc_greedy":"1f939-1f3fb-2640","shortnames":[":woman_juggling_light_skin_tone:"],"category":"activity"},":woman_juggling_tone2:":{"uc_base":"1f939-1f3fc-2640","uc_output":"1f939-1f3fc-200d-2640-fe0f","uc_match":"1f939-1f3fc-2640-fe0f","uc_greedy":"1f939-1f3fc-2640","shortnames":[":woman_juggling_medium_light_skin_tone:"],"category":"activity"},":woman_juggling_tone3:":{"uc_base":"1f939-1f3fd-2640","uc_output":"1f939-1f3fd-200d-2640-fe0f","uc_match":"1f939-1f3fd-2640-fe0f","uc_greedy":"1f939-1f3fd-2640","shortnames":[":woman_juggling_medium_skin_tone:"],"category":"activity"},":woman_juggling_tone4:":{"uc_base":"1f939-1f3fe-2640","uc_output":"1f939-1f3fe-200d-2640-fe0f","uc_match":"1f939-1f3fe-2640-fe0f","uc_greedy":"1f939-1f3fe-2640","shortnames":[":woman_juggling_medium_dark_skin_tone:"],"category":"activity"},":woman_juggling_tone5:":{"uc_base":"1f939-1f3ff-2640","uc_output":"1f939-1f3ff-200d-2640-fe0f","uc_match":"1f939-1f3ff-2640-fe0f","uc_greedy":"1f939-1f3ff-2640","shortnames":[":woman_juggling_dark_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone1:":{"uc_base":"1f3cb-1f3fb-2640","uc_output":"1f3cb-1f3fb-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fb-2640-fe0f","uc_greedy":"1f3cb-1f3fb-2640","shortnames":[":woman_lifting_weights_light_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone2:":{"uc_base":"1f3cb-1f3fc-2640","uc_output":"1f3cb-1f3fc-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fc-2640-fe0f","uc_greedy":"1f3cb-1f3fc-2640","shortnames":[":woman_lifting_weights_medium_light_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone3:":{"uc_base":"1f3cb-1f3fd-2640","uc_output":"1f3cb-1f3fd-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fd-2640-fe0f","uc_greedy":"1f3cb-1f3fd-2640","shortnames":[":woman_lifting_weights_medium_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone4:":{"uc_base":"1f3cb-1f3fe-2640","uc_output":"1f3cb-1f3fe-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fe-2640-fe0f","uc_greedy":"1f3cb-1f3fe-2640","shortnames":[":woman_lifting_weights_medium_dark_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone5:":{"uc_base":"1f3cb-1f3ff-2640","uc_output":"1f3cb-1f3ff-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3ff-2640-fe0f","uc_greedy":"1f3cb-1f3ff-2640","shortnames":[":woman_lifting_weights_dark_skin_tone:"],"category":"activity"},":woman_mage_tone1:":{"uc_base":"1f9d9-1f3fb-2640","uc_output":"1f9d9-1f3fb-200d-2640-fe0f","uc_match":"1f9d9-1f3fb-2640-fe0f","uc_greedy":"1f9d9-1f3fb-2640","shortnames":[":woman_mage_light_skin_tone:"],"category":"people"},":woman_mage_tone2:":{"uc_base":"1f9d9-1f3fc-2640","uc_output":"1f9d9-1f3fc-200d-2640-fe0f","uc_match":"1f9d9-1f3fc-2640-fe0f","uc_greedy":"1f9d9-1f3fc-2640","shortnames":[":woman_mage_medium_light_skin_tone:"],"category":"people"},":woman_mage_tone3:":{"uc_base":"1f9d9-1f3fd-2640","uc_output":"1f9d9-1f3fd-200d-2640-fe0f","uc_match":"1f9d9-1f3fd-2640-fe0f","uc_greedy":"1f9d9-1f3fd-2640","shortnames":[":woman_mage_medium_skin_tone:"],"category":"people"},":woman_mage_tone4:":{"uc_base":"1f9d9-1f3fe-2640","uc_output":"1f9d9-1f3fe-200d-2640-fe0f","uc_match":"1f9d9-1f3fe-2640-fe0f","uc_greedy":"1f9d9-1f3fe-2640","shortnames":[":woman_mage_medium_dark_skin_tone:"],"category":"people"},":woman_mage_tone5:":{"uc_base":"1f9d9-1f3ff-2640","uc_output":"1f9d9-1f3ff-200d-2640-fe0f","uc_match":"1f9d9-1f3ff-2640-fe0f","uc_greedy":"1f9d9-1f3ff-2640","shortnames":[":woman_mage_dark_skin_tone:"],"category":"people"},":woman_mountain_biking_tone1:":{"uc_base":"1f6b5-1f3fb-2640","uc_output":"1f6b5-1f3fb-200d-2640-fe0f","uc_match":"1f6b5-1f3fb-2640-fe0f","uc_greedy":"1f6b5-1f3fb-2640","shortnames":[":woman_mountain_biking_light_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone2:":{"uc_base":"1f6b5-1f3fc-2640","uc_output":"1f6b5-1f3fc-200d-2640-fe0f","uc_match":"1f6b5-1f3fc-2640-fe0f","uc_greedy":"1f6b5-1f3fc-2640","shortnames":[":woman_mountain_biking_medium_light_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone3:":{"uc_base":"1f6b5-1f3fd-2640","uc_output":"1f6b5-1f3fd-200d-2640-fe0f","uc_match":"1f6b5-1f3fd-2640-fe0f","uc_greedy":"1f6b5-1f3fd-2640","shortnames":[":woman_mountain_biking_medium_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone4:":{"uc_base":"1f6b5-1f3fe-2640","uc_output":"1f6b5-1f3fe-200d-2640-fe0f","uc_match":"1f6b5-1f3fe-2640-fe0f","uc_greedy":"1f6b5-1f3fe-2640","shortnames":[":woman_mountain_biking_medium_dark_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone5:":{"uc_base":"1f6b5-1f3ff-2640","uc_output":"1f6b5-1f3ff-200d-2640-fe0f","uc_match":"1f6b5-1f3ff-2640-fe0f","uc_greedy":"1f6b5-1f3ff-2640","shortnames":[":woman_mountain_biking_dark_skin_tone:"],"category":"activity"},":woman_pilot_tone1:":{"uc_base":"1f469-1f3fb-2708","uc_output":"1f469-1f3fb-200d-2708-fe0f","uc_match":"1f469-1f3fb-2708-fe0f","uc_greedy":"1f469-1f3fb-2708","shortnames":[":woman_pilot_light_skin_tone:"],"category":"people"},":woman_pilot_tone2:":{"uc_base":"1f469-1f3fc-2708","uc_output":"1f469-1f3fc-200d-2708-fe0f","uc_match":"1f469-1f3fc-2708-fe0f","uc_greedy":"1f469-1f3fc-2708","shortnames":[":woman_pilot_medium_light_skin_tone:"],"category":"people"},":woman_pilot_tone3:":{"uc_base":"1f469-1f3fd-2708","uc_output":"1f469-1f3fd-200d-2708-fe0f","uc_match":"1f469-1f3fd-2708-fe0f","uc_greedy":"1f469-1f3fd-2708","shortnames":[":woman_pilot_medium_skin_tone:"],"category":"people"},":woman_pilot_tone4:":{"uc_base":"1f469-1f3fe-2708","uc_output":"1f469-1f3fe-200d-2708-fe0f","uc_match":"1f469-1f3fe-2708-fe0f","uc_greedy":"1f469-1f3fe-2708","shortnames":[":woman_pilot_medium_dark_skin_tone:"],"category":"people"},":woman_pilot_tone5:":{"uc_base":"1f469-1f3ff-2708","uc_output":"1f469-1f3ff-200d-2708-fe0f","uc_match":"1f469-1f3ff-2708-fe0f","uc_greedy":"1f469-1f3ff-2708","shortnames":[":woman_pilot_dark_skin_tone:"],"category":"people"},":woman_playing_handball_tone1:":{"uc_base":"1f93e-1f3fb-2640","uc_output":"1f93e-1f3fb-200d-2640-fe0f","uc_match":"1f93e-1f3fb-2640-fe0f","uc_greedy":"1f93e-1f3fb-2640","shortnames":[":woman_playing_handball_light_skin_tone:"],"category":"activity"},":woman_playing_handball_tone2:":{"uc_base":"1f93e-1f3fc-2640","uc_output":"1f93e-1f3fc-200d-2640-fe0f","uc_match":"1f93e-1f3fc-2640-fe0f","uc_greedy":"1f93e-1f3fc-2640","shortnames":[":woman_playing_handball_medium_light_skin_tone:"],"category":"activity"},":woman_playing_handball_tone3:":{"uc_base":"1f93e-1f3fd-2640","uc_output":"1f93e-1f3fd-200d-2640-fe0f","uc_match":"1f93e-1f3fd-2640-fe0f","uc_greedy":"1f93e-1f3fd-2640","shortnames":[":woman_playing_handball_medium_skin_tone:"],"category":"activity"},":woman_playing_handball_tone4:":{"uc_base":"1f93e-1f3fe-2640","uc_output":"1f93e-1f3fe-200d-2640-fe0f","uc_match":"1f93e-1f3fe-2640-fe0f","uc_greedy":"1f93e-1f3fe-2640","shortnames":[":woman_playing_handball_medium_dark_skin_tone:"],"category":"activity"},":woman_playing_handball_tone5:":{"uc_base":"1f93e-1f3ff-2640","uc_output":"1f93e-1f3ff-200d-2640-fe0f","uc_match":"1f93e-1f3ff-2640-fe0f","uc_greedy":"1f93e-1f3ff-2640","shortnames":[":woman_playing_handball_dark_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone1:":{"uc_base":"1f93d-1f3fb-2640","uc_output":"1f93d-1f3fb-200d-2640-fe0f","uc_match":"1f93d-1f3fb-2640-fe0f","uc_greedy":"1f93d-1f3fb-2640","shortnames":[":woman_playing_water_polo_light_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone2:":{"uc_base":"1f93d-1f3fc-2640","uc_output":"1f93d-1f3fc-200d-2640-fe0f","uc_match":"1f93d-1f3fc-2640-fe0f","uc_greedy":"1f93d-1f3fc-2640","shortnames":[":woman_playing_water_polo_medium_light_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone3:":{"uc_base":"1f93d-1f3fd-2640","uc_output":"1f93d-1f3fd-200d-2640-fe0f","uc_match":"1f93d-1f3fd-2640-fe0f","uc_greedy":"1f93d-1f3fd-2640","shortnames":[":woman_playing_water_polo_medium_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone4:":{"uc_base":"1f93d-1f3fe-2640","uc_output":"1f93d-1f3fe-200d-2640-fe0f","uc_match":"1f93d-1f3fe-2640-fe0f","uc_greedy":"1f93d-1f3fe-2640","shortnames":[":woman_playing_water_polo_medium_dark_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone5:":{"uc_base":"1f93d-1f3ff-2640","uc_output":"1f93d-1f3ff-200d-2640-fe0f","uc_match":"1f93d-1f3ff-2640-fe0f","uc_greedy":"1f93d-1f3ff-2640","shortnames":[":woman_playing_water_polo_dark_skin_tone:"],"category":"activity"},":woman_police_officer_tone1:":{"uc_base":"1f46e-1f3fb-2640","uc_output":"1f46e-1f3fb-200d-2640-fe0f","uc_match":"1f46e-1f3fb-2640-fe0f","uc_greedy":"1f46e-1f3fb-2640","shortnames":[":woman_police_officer_light_skin_tone:"],"category":"people"},":woman_police_officer_tone2:":{"uc_base":"1f46e-1f3fc-2640","uc_output":"1f46e-1f3fc-200d-2640-fe0f","uc_match":"1f46e-1f3fc-2640-fe0f","uc_greedy":"1f46e-1f3fc-2640","shortnames":[":woman_police_officer_medium_light_skin_tone:"],"category":"people"},":woman_police_officer_tone3:":{"uc_base":"1f46e-1f3fd-2640","uc_output":"1f46e-1f3fd-200d-2640-fe0f","uc_match":"1f46e-1f3fd-2640-fe0f","uc_greedy":"1f46e-1f3fd-2640","shortnames":[":woman_police_officer_medium_skin_tone:"],"category":"people"},":woman_police_officer_tone4:":{"uc_base":"1f46e-1f3fe-2640","uc_output":"1f46e-1f3fe-200d-2640-fe0f","uc_match":"1f46e-1f3fe-2640-fe0f","uc_greedy":"1f46e-1f3fe-2640","shortnames":[":woman_police_officer_medium_dark_skin_tone:"],"category":"people"},":woman_police_officer_tone5:":{"uc_base":"1f46e-1f3ff-2640","uc_output":"1f46e-1f3ff-200d-2640-fe0f","uc_match":"1f46e-1f3ff-2640-fe0f","uc_greedy":"1f46e-1f3ff-2640","shortnames":[":woman_police_officer_dark_skin_tone:"],"category":"people"},":woman_pouting_tone1:":{"uc_base":"1f64e-1f3fb-2640","uc_output":"1f64e-1f3fb-200d-2640-fe0f","uc_match":"1f64e-1f3fb-2640-fe0f","uc_greedy":"1f64e-1f3fb-2640","shortnames":[":woman_pouting_light_skin_tone:"],"category":"people"},":woman_pouting_tone2:":{"uc_base":"1f64e-1f3fc-2640","uc_output":"1f64e-1f3fc-200d-2640-fe0f","uc_match":"1f64e-1f3fc-2640-fe0f","uc_greedy":"1f64e-1f3fc-2640","shortnames":[":woman_pouting_medium_light_skin_tone:"],"category":"people"},":woman_pouting_tone3:":{"uc_base":"1f64e-1f3fd-2640","uc_output":"1f64e-1f3fd-200d-2640-fe0f","uc_match":"1f64e-1f3fd-2640-fe0f","uc_greedy":"1f64e-1f3fd-2640","shortnames":[":woman_pouting_medium_skin_tone:"],"category":"people"},":woman_pouting_tone4:":{"uc_base":"1f64e-1f3fe-2640","uc_output":"1f64e-1f3fe-200d-2640-fe0f","uc_match":"1f64e-1f3fe-2640-fe0f","uc_greedy":"1f64e-1f3fe-2640","shortnames":[":woman_pouting_medium_dark_skin_tone:"],"category":"people"},":woman_pouting_tone5:":{"uc_base":"1f64e-1f3ff-2640","uc_output":"1f64e-1f3ff-200d-2640-fe0f","uc_match":"1f64e-1f3ff-2640-fe0f","uc_greedy":"1f64e-1f3ff-2640","shortnames":[":woman_pouting_dark_skin_tone:"],"category":"people"},":woman_raising_hand_tone1:":{"uc_base":"1f64b-1f3fb-2640","uc_output":"1f64b-1f3fb-200d-2640-fe0f","uc_match":"1f64b-1f3fb-2640-fe0f","uc_greedy":"1f64b-1f3fb-2640","shortnames":[":woman_raising_hand_light_skin_tone:"],"category":"people"},":woman_raising_hand_tone2:":{"uc_base":"1f64b-1f3fc-2640","uc_output":"1f64b-1f3fc-200d-2640-fe0f","uc_match":"1f64b-1f3fc-2640-fe0f","uc_greedy":"1f64b-1f3fc-2640","shortnames":[":woman_raising_hand_medium_light_skin_tone:"],"category":"people"},":woman_raising_hand_tone3:":{"uc_base":"1f64b-1f3fd-2640","uc_output":"1f64b-1f3fd-200d-2640-fe0f","uc_match":"1f64b-1f3fd-2640-fe0f","uc_greedy":"1f64b-1f3fd-2640","shortnames":[":woman_raising_hand_medium_skin_tone:"],"category":"people"},":woman_raising_hand_tone4:":{"uc_base":"1f64b-1f3fe-2640","uc_output":"1f64b-1f3fe-200d-2640-fe0f","uc_match":"1f64b-1f3fe-2640-fe0f","uc_greedy":"1f64b-1f3fe-2640","shortnames":[":woman_raising_hand_medium_dark_skin_tone:"],"category":"people"},":woman_raising_hand_tone5:":{"uc_base":"1f64b-1f3ff-2640","uc_output":"1f64b-1f3ff-200d-2640-fe0f","uc_match":"1f64b-1f3ff-2640-fe0f","uc_greedy":"1f64b-1f3ff-2640","shortnames":[":woman_raising_hand_dark_skin_tone:"],"category":"people"},":woman_rowing_boat_tone1:":{"uc_base":"1f6a3-1f3fb-2640","uc_output":"1f6a3-1f3fb-200d-2640-fe0f","uc_match":"1f6a3-1f3fb-2640-fe0f","uc_greedy":"1f6a3-1f3fb-2640","shortnames":[":woman_rowing_boat_light_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone2:":{"uc_base":"1f6a3-1f3fc-2640","uc_output":"1f6a3-1f3fc-200d-2640-fe0f","uc_match":"1f6a3-1f3fc-2640-fe0f","uc_greedy":"1f6a3-1f3fc-2640","shortnames":[":woman_rowing_boat_medium_light_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone3:":{"uc_base":"1f6a3-1f3fd-2640","uc_output":"1f6a3-1f3fd-200d-2640-fe0f","uc_match":"1f6a3-1f3fd-2640-fe0f","uc_greedy":"1f6a3-1f3fd-2640","shortnames":[":woman_rowing_boat_medium_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone4:":{"uc_base":"1f6a3-1f3fe-2640","uc_output":"1f6a3-1f3fe-200d-2640-fe0f","uc_match":"1f6a3-1f3fe-2640-fe0f","uc_greedy":"1f6a3-1f3fe-2640","shortnames":[":woman_rowing_boat_medium_dark_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone5:":{"uc_base":"1f6a3-1f3ff-2640","uc_output":"1f6a3-1f3ff-200d-2640-fe0f","uc_match":"1f6a3-1f3ff-2640-fe0f","uc_greedy":"1f6a3-1f3ff-2640","shortnames":[":woman_rowing_boat_dark_skin_tone:"],"category":"activity"},":woman_running_tone1:":{"uc_base":"1f3c3-1f3fb-2640","uc_output":"1f3c3-1f3fb-200d-2640-fe0f","uc_match":"1f3c3-1f3fb-2640-fe0f","uc_greedy":"1f3c3-1f3fb-2640","shortnames":[":woman_running_light_skin_tone:"],"category":"people"},":woman_running_tone2:":{"uc_base":"1f3c3-1f3fc-2640","uc_output":"1f3c3-1f3fc-200d-2640-fe0f","uc_match":"1f3c3-1f3fc-2640-fe0f","uc_greedy":"1f3c3-1f3fc-2640","shortnames":[":woman_running_medium_light_skin_tone:"],"category":"people"},":woman_running_tone3:":{"uc_base":"1f3c3-1f3fd-2640","uc_output":"1f3c3-1f3fd-200d-2640-fe0f","uc_match":"1f3c3-1f3fd-2640-fe0f","uc_greedy":"1f3c3-1f3fd-2640","shortnames":[":woman_running_medium_skin_tone:"],"category":"people"},":woman_running_tone4:":{"uc_base":"1f3c3-1f3fe-2640","uc_output":"1f3c3-1f3fe-200d-2640-fe0f","uc_match":"1f3c3-1f3fe-2640-fe0f","uc_greedy":"1f3c3-1f3fe-2640","shortnames":[":woman_running_medium_dark_skin_tone:"],"category":"people"},":woman_running_tone5:":{"uc_base":"1f3c3-1f3ff-2640","uc_output":"1f3c3-1f3ff-200d-2640-fe0f","uc_match":"1f3c3-1f3ff-2640-fe0f","uc_greedy":"1f3c3-1f3ff-2640","shortnames":[":woman_running_dark_skin_tone:"],"category":"people"},":woman_shrugging_tone1:":{"uc_base":"1f937-1f3fb-2640","uc_output":"1f937-1f3fb-200d-2640-fe0f","uc_match":"1f937-1f3fb-2640-fe0f","uc_greedy":"1f937-1f3fb-2640","shortnames":[":woman_shrugging_light_skin_tone:"],"category":"people"},":woman_shrugging_tone2:":{"uc_base":"1f937-1f3fc-2640","uc_output":"1f937-1f3fc-200d-2640-fe0f","uc_match":"1f937-1f3fc-2640-fe0f","uc_greedy":"1f937-1f3fc-2640","shortnames":[":woman_shrugging_medium_light_skin_tone:"],"category":"people"},":woman_shrugging_tone3:":{"uc_base":"1f937-1f3fd-2640","uc_output":"1f937-1f3fd-200d-2640-fe0f","uc_match":"1f937-1f3fd-2640-fe0f","uc_greedy":"1f937-1f3fd-2640","shortnames":[":woman_shrugging_medium_skin_tone:"],"category":"people"},":woman_shrugging_tone4:":{"uc_base":"1f937-1f3fe-2640","uc_output":"1f937-1f3fe-200d-2640-fe0f","uc_match":"1f937-1f3fe-2640-fe0f","uc_greedy":"1f937-1f3fe-2640","shortnames":[":woman_shrugging_medium_dark_skin_tone:"],"category":"people"},":woman_shrugging_tone5:":{"uc_base":"1f937-1f3ff-2640","uc_output":"1f937-1f3ff-200d-2640-fe0f","uc_match":"1f937-1f3ff-2640-fe0f","uc_greedy":"1f937-1f3ff-2640","shortnames":[":woman_shrugging_dark_skin_tone:"],"category":"people"},":woman_surfing_tone1:":{"uc_base":"1f3c4-1f3fb-2640","uc_output":"1f3c4-1f3fb-200d-2640-fe0f","uc_match":"1f3c4-1f3fb-2640-fe0f","uc_greedy":"1f3c4-1f3fb-2640","shortnames":[":woman_surfing_light_skin_tone:"],"category":"activity"},":woman_surfing_tone2:":{"uc_base":"1f3c4-1f3fc-2640","uc_output":"1f3c4-1f3fc-200d-2640-fe0f","uc_match":"1f3c4-1f3fc-2640-fe0f","uc_greedy":"1f3c4-1f3fc-2640","shortnames":[":woman_surfing_medium_light_skin_tone:"],"category":"activity"},":woman_surfing_tone3:":{"uc_base":"1f3c4-1f3fd-2640","uc_output":"1f3c4-1f3fd-200d-2640-fe0f","uc_match":"1f3c4-1f3fd-2640-fe0f","uc_greedy":"1f3c4-1f3fd-2640","shortnames":[":woman_surfing_medium_skin_tone:"],"category":"activity"},":woman_surfing_tone4:":{"uc_base":"1f3c4-1f3fe-2640","uc_output":"1f3c4-1f3fe-200d-2640-fe0f","uc_match":"1f3c4-1f3fe-2640-fe0f","uc_greedy":"1f3c4-1f3fe-2640","shortnames":[":woman_surfing_medium_dark_skin_tone:"],"category":"activity"},":woman_surfing_tone5:":{"uc_base":"1f3c4-1f3ff-2640","uc_output":"1f3c4-1f3ff-200d-2640-fe0f","uc_match":"1f3c4-1f3ff-2640-fe0f","uc_greedy":"1f3c4-1f3ff-2640","shortnames":[":woman_surfing_dark_skin_tone:"],"category":"activity"},":woman_swimming_tone1:":{"uc_base":"1f3ca-1f3fb-2640","uc_output":"1f3ca-1f3fb-200d-2640-fe0f","uc_match":"1f3ca-1f3fb-2640-fe0f","uc_greedy":"1f3ca-1f3fb-2640","shortnames":[":woman_swimming_light_skin_tone:"],"category":"activity"},":woman_swimming_tone2:":{"uc_base":"1f3ca-1f3fc-2640","uc_output":"1f3ca-1f3fc-200d-2640-fe0f","uc_match":"1f3ca-1f3fc-2640-fe0f","uc_greedy":"1f3ca-1f3fc-2640","shortnames":[":woman_swimming_medium_light_skin_tone:"],"category":"activity"},":woman_swimming_tone3:":{"uc_base":"1f3ca-1f3fd-2640","uc_output":"1f3ca-1f3fd-200d-2640-fe0f","uc_match":"1f3ca-1f3fd-2640-fe0f","uc_greedy":"1f3ca-1f3fd-2640","shortnames":[":woman_swimming_medium_skin_tone:"],"category":"activity"},":woman_swimming_tone4:":{"uc_base":"1f3ca-1f3fe-2640","uc_output":"1f3ca-1f3fe-200d-2640-fe0f","uc_match":"1f3ca-1f3fe-2640-fe0f","uc_greedy":"1f3ca-1f3fe-2640","shortnames":[":woman_swimming_medium_dark_skin_tone:"],"category":"activity"},":woman_swimming_tone5:":{"uc_base":"1f3ca-1f3ff-2640","uc_output":"1f3ca-1f3ff-200d-2640-fe0f","uc_match":"1f3ca-1f3ff-2640-fe0f","uc_greedy":"1f3ca-1f3ff-2640","shortnames":[":woman_swimming_dark_skin_tone:"],"category":"activity"},":woman_tipping_hand_tone1:":{"uc_base":"1f481-1f3fb-2640","uc_output":"1f481-1f3fb-200d-2640-fe0f","uc_match":"1f481-1f3fb-2640-fe0f","uc_greedy":"1f481-1f3fb-2640","shortnames":[":woman_tipping_hand_light_skin_tone:"],"category":"people"},":woman_tipping_hand_tone2:":{"uc_base":"1f481-1f3fc-2640","uc_output":"1f481-1f3fc-200d-2640-fe0f","uc_match":"1f481-1f3fc-2640-fe0f","uc_greedy":"1f481-1f3fc-2640","shortnames":[":woman_tipping_hand_medium_light_skin_tone:"],"category":"people"},":woman_tipping_hand_tone3:":{"uc_base":"1f481-1f3fd-2640","uc_output":"1f481-1f3fd-200d-2640-fe0f","uc_match":"1f481-1f3fd-2640-fe0f","uc_greedy":"1f481-1f3fd-2640","shortnames":[":woman_tipping_hand_medium_skin_tone:"],"category":"people"},":woman_tipping_hand_tone4:":{"uc_base":"1f481-1f3fe-2640","uc_output":"1f481-1f3fe-200d-2640-fe0f","uc_match":"1f481-1f3fe-2640-fe0f","uc_greedy":"1f481-1f3fe-2640","shortnames":[":woman_tipping_hand_medium_dark_skin_tone:"],"category":"people"},":woman_tipping_hand_tone5:":{"uc_base":"1f481-1f3ff-2640","uc_output":"1f481-1f3ff-200d-2640-fe0f","uc_match":"1f481-1f3ff-2640-fe0f","uc_greedy":"1f481-1f3ff-2640","shortnames":[":woman_tipping_hand_dark_skin_tone:"],"category":"people"},":woman_vampire_tone1:":{"uc_base":"1f9db-1f3fb-2640","uc_output":"1f9db-1f3fb-200d-2640-fe0f","uc_match":"1f9db-1f3fb-2640-fe0f","uc_greedy":"1f9db-1f3fb-2640","shortnames":[":woman_vampire_light_skin_tone:"],"category":"people"},":woman_vampire_tone2:":{"uc_base":"1f9db-1f3fc-2640","uc_output":"1f9db-1f3fc-200d-2640-fe0f","uc_match":"1f9db-1f3fc-2640-fe0f","uc_greedy":"1f9db-1f3fc-2640","shortnames":[":woman_vampire_medium_light_skin_tone:"],"category":"people"},":woman_vampire_tone3:":{"uc_base":"1f9db-1f3fd-2640","uc_output":"1f9db-1f3fd-200d-2640-fe0f","uc_match":"1f9db-1f3fd-2640-fe0f","uc_greedy":"1f9db-1f3fd-2640","shortnames":[":woman_vampire_medium_skin_tone:"],"category":"people"},":woman_vampire_tone4:":{"uc_base":"1f9db-1f3fe-2640","uc_output":"1f9db-1f3fe-200d-2640-fe0f","uc_match":"1f9db-1f3fe-2640-fe0f","uc_greedy":"1f9db-1f3fe-2640","shortnames":[":woman_vampire_medium_dark_skin_tone:"],"category":"people"},":woman_vampire_tone5:":{"uc_base":"1f9db-1f3ff-2640","uc_output":"1f9db-1f3ff-200d-2640-fe0f","uc_match":"1f9db-1f3ff-2640-fe0f","uc_greedy":"1f9db-1f3ff-2640","shortnames":[":woman_vampire_dark_skin_tone:"],"category":"people"},":woman_walking_tone1:":{"uc_base":"1f6b6-1f3fb-2640","uc_output":"1f6b6-1f3fb-200d-2640-fe0f","uc_match":"1f6b6-1f3fb-2640-fe0f","uc_greedy":"1f6b6-1f3fb-2640","shortnames":[":woman_walking_light_skin_tone:"],"category":"people"},":woman_walking_tone2:":{"uc_base":"1f6b6-1f3fc-2640","uc_output":"1f6b6-1f3fc-200d-2640-fe0f","uc_match":"1f6b6-1f3fc-2640-fe0f","uc_greedy":"1f6b6-1f3fc-2640","shortnames":[":woman_walking_medium_light_skin_tone:"],"category":"people"},":woman_walking_tone3:":{"uc_base":"1f6b6-1f3fd-2640","uc_output":"1f6b6-1f3fd-200d-2640-fe0f","uc_match":"1f6b6-1f3fd-2640-fe0f","uc_greedy":"1f6b6-1f3fd-2640","shortnames":[":woman_walking_medium_skin_tone:"],"category":"people"},":woman_walking_tone4:":{"uc_base":"1f6b6-1f3fe-2640","uc_output":"1f6b6-1f3fe-200d-2640-fe0f","uc_match":"1f6b6-1f3fe-2640-fe0f","uc_greedy":"1f6b6-1f3fe-2640","shortnames":[":woman_walking_medium_dark_skin_tone:"],"category":"people"},":woman_walking_tone5:":{"uc_base":"1f6b6-1f3ff-2640","uc_output":"1f6b6-1f3ff-200d-2640-fe0f","uc_match":"1f6b6-1f3ff-2640-fe0f","uc_greedy":"1f6b6-1f3ff-2640","shortnames":[":woman_walking_dark_skin_tone:"],"category":"people"},":woman_wearing_turban_tone1:":{"uc_base":"1f473-1f3fb-2640","uc_output":"1f473-1f3fb-200d-2640-fe0f","uc_match":"1f473-1f3fb-2640-fe0f","uc_greedy":"1f473-1f3fb-2640","shortnames":[":woman_wearing_turban_light_skin_tone:"],"category":"people"},":woman_wearing_turban_tone2:":{"uc_base":"1f473-1f3fc-2640","uc_output":"1f473-1f3fc-200d-2640-fe0f","uc_match":"1f473-1f3fc-2640-fe0f","uc_greedy":"1f473-1f3fc-2640","shortnames":[":woman_wearing_turban_medium_light_skin_tone:"],"category":"people"},":woman_wearing_turban_tone3:":{"uc_base":"1f473-1f3fd-2640","uc_output":"1f473-1f3fd-200d-2640-fe0f","uc_match":"1f473-1f3fd-2640-fe0f","uc_greedy":"1f473-1f3fd-2640","shortnames":[":woman_wearing_turban_medium_skin_tone:"],"category":"people"},":woman_wearing_turban_tone4:":{"uc_base":"1f473-1f3fe-2640","uc_output":"1f473-1f3fe-200d-2640-fe0f","uc_match":"1f473-1f3fe-2640-fe0f","uc_greedy":"1f473-1f3fe-2640","shortnames":[":woman_wearing_turban_medium_dark_skin_tone:"],"category":"people"},":woman_wearing_turban_tone5:":{"uc_base":"1f473-1f3ff-2640","uc_output":"1f473-1f3ff-200d-2640-fe0f","uc_match":"1f473-1f3ff-2640-fe0f","uc_greedy":"1f473-1f3ff-2640","shortnames":[":woman_wearing_turban_dark_skin_tone:"],"category":"people"},":man_bouncing_ball_tone1:":{"uc_base":"26f9-1f3fb-2642","uc_output":"26f9-1f3fb-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fb-2642-fe0f","uc_greedy":"26f9-1f3fb-2642","shortnames":[":man_bouncing_ball_light_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone2:":{"uc_base":"26f9-1f3fc-2642","uc_output":"26f9-1f3fc-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fc-2642-fe0f","uc_greedy":"26f9-1f3fc-2642","shortnames":[":man_bouncing_ball_medium_light_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone3:":{"uc_base":"26f9-1f3fd-2642","uc_output":"26f9-1f3fd-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fd-2642-fe0f","uc_greedy":"26f9-1f3fd-2642","shortnames":[":man_bouncing_ball_medium_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone4:":{"uc_base":"26f9-1f3fe-2642","uc_output":"26f9-1f3fe-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fe-2642-fe0f","uc_greedy":"26f9-1f3fe-2642","shortnames":[":man_bouncing_ball_medium_dark_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone5:":{"uc_base":"26f9-1f3ff-2642","uc_output":"26f9-1f3ff-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3ff-2642-fe0f","uc_greedy":"26f9-1f3ff-2642","shortnames":[":man_bouncing_ball_dark_skin_tone:"],"category":"activity"},":man_detective:":{"uc_base":"1f575-2642","uc_output":"1f575-fe0f-200d-2642-fe0f","uc_match":"1f575-fe0f-2642-fe0f","uc_greedy":"1f575-2642","shortnames":[],"category":"people"},":man_golfing:":{"uc_base":"1f3cc-2642","uc_output":"1f3cc-fe0f-200d-2642-fe0f","uc_match":"1f3cc-fe0f-2642-fe0f","uc_greedy":"1f3cc-2642","shortnames":[],"category":"activity"},":man_lifting_weights:":{"uc_base":"1f3cb-2642","uc_output":"1f3cb-fe0f-200d-2642-fe0f","uc_match":"1f3cb-fe0f-2642-fe0f","uc_greedy":"1f3cb-2642","shortnames":[],"category":"activity"},":woman_bouncing_ball_tone1:":{"uc_base":"26f9-1f3fb-2640","uc_output":"26f9-1f3fb-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fb-2640-fe0f","uc_greedy":"26f9-1f3fb-2640","shortnames":[":woman_bouncing_ball_light_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone2:":{"uc_base":"26f9-1f3fc-2640","uc_output":"26f9-1f3fc-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fc-2640-fe0f","uc_greedy":"26f9-1f3fc-2640","shortnames":[":woman_bouncing_ball_medium_light_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone3:":{"uc_base":"26f9-1f3fd-2640","uc_output":"26f9-1f3fd-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fd-2640-fe0f","uc_greedy":"26f9-1f3fd-2640","shortnames":[":woman_bouncing_ball_medium_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone4:":{"uc_base":"26f9-1f3fe-2640","uc_output":"26f9-1f3fe-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fe-2640-fe0f","uc_greedy":"26f9-1f3fe-2640","shortnames":[":woman_bouncing_ball_medium_dark_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone5:":{"uc_base":"26f9-1f3ff-2640","uc_output":"26f9-1f3ff-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3ff-2640-fe0f","uc_greedy":"26f9-1f3ff-2640","shortnames":[":woman_bouncing_ball_dark_skin_tone:"],"category":"activity"},":woman_detective:":{"uc_base":"1f575-2640","uc_output":"1f575-fe0f-200d-2640-fe0f","uc_match":"1f575-fe0f-2640-fe0f","uc_greedy":"1f575-2640","shortnames":[],"category":"people"},":woman_golfing:":{"uc_base":"1f3cc-2640","uc_output":"1f3cc-fe0f-200d-2640-fe0f","uc_match":"1f3cc-fe0f-2640-fe0f","uc_greedy":"1f3cc-2640","shortnames":[],"category":"activity"},":woman_lifting_weights:":{"uc_base":"1f3cb-2640","uc_output":"1f3cb-fe0f-200d-2640-fe0f","uc_match":"1f3cb-fe0f-2640-fe0f","uc_greedy":"1f3cb-2640","shortnames":[],"category":"activity"},":man_bouncing_ball:":{"uc_base":"26f9-2642","uc_output":"26f9-fe0f-200d-2642-fe0f","uc_match":"26f9-fe0f-2642-fe0f","uc_greedy":"26f9-2642","shortnames":[],"category":"activity"},":woman_bouncing_ball:":{"uc_base":"26f9-2640","uc_output":"26f9-fe0f-200d-2640-fe0f","uc_match":"26f9-fe0f-2640-fe0f","uc_greedy":"26f9-2640","shortnames":[],"category":"activity"},":man_artist_tone1:":{"uc_base":"1f468-1f3fb-1f3a8","uc_output":"1f468-1f3fb-200d-1f3a8","uc_match":"1f468-1f3fb-1f3a8","uc_greedy":"1f468-1f3fb-1f3a8","shortnames":[":man_artist_light_skin_tone:"],"category":"people"},":man_artist_tone2:":{"uc_base":"1f468-1f3fc-1f3a8","uc_output":"1f468-1f3fc-200d-1f3a8","uc_match":"1f468-1f3fc-1f3a8","uc_greedy":"1f468-1f3fc-1f3a8","shortnames":[":man_artist_medium_light_skin_tone:"],"category":"people"},":man_artist_tone3:":{"uc_base":"1f468-1f3fd-1f3a8","uc_output":"1f468-1f3fd-200d-1f3a8","uc_match":"1f468-1f3fd-1f3a8","uc_greedy":"1f468-1f3fd-1f3a8","shortnames":[":man_artist_medium_skin_tone:"],"category":"people"},":man_artist_tone4:":{"uc_base":"1f468-1f3fe-1f3a8","uc_output":"1f468-1f3fe-200d-1f3a8","uc_match":"1f468-1f3fe-1f3a8","uc_greedy":"1f468-1f3fe-1f3a8","shortnames":[":man_artist_medium_dark_skin_tone:"],"category":"people"},":man_artist_tone5:":{"uc_base":"1f468-1f3ff-1f3a8","uc_output":"1f468-1f3ff-200d-1f3a8","uc_match":"1f468-1f3ff-1f3a8","uc_greedy":"1f468-1f3ff-1f3a8","shortnames":[":man_artist_dark_skin_tone:"],"category":"people"},":man_astronaut_tone1:":{"uc_base":"1f468-1f3fb-1f680","uc_output":"1f468-1f3fb-200d-1f680","uc_match":"1f468-1f3fb-1f680","uc_greedy":"1f468-1f3fb-1f680","shortnames":[":man_astronaut_light_skin_tone:"],"category":"people"},":man_astronaut_tone2:":{"uc_base":"1f468-1f3fc-1f680","uc_output":"1f468-1f3fc-200d-1f680","uc_match":"1f468-1f3fc-1f680","uc_greedy":"1f468-1f3fc-1f680","shortnames":[":man_astronaut_medium_light_skin_tone:"],"category":"people"},":man_astronaut_tone3:":{"uc_base":"1f468-1f3fd-1f680","uc_output":"1f468-1f3fd-200d-1f680","uc_match":"1f468-1f3fd-1f680","uc_greedy":"1f468-1f3fd-1f680","shortnames":[":man_astronaut_medium_skin_tone:"],"category":"people"},":man_astronaut_tone4:":{"uc_base":"1f468-1f3fe-1f680","uc_output":"1f468-1f3fe-200d-1f680","uc_match":"1f468-1f3fe-1f680","uc_greedy":"1f468-1f3fe-1f680","shortnames":[":man_astronaut_medium_dark_skin_tone:"],"category":"people"},":man_astronaut_tone5:":{"uc_base":"1f468-1f3ff-1f680","uc_output":"1f468-1f3ff-200d-1f680","uc_match":"1f468-1f3ff-1f680","uc_greedy":"1f468-1f3ff-1f680","shortnames":[":man_astronaut_dark_skin_tone:"],"category":"people"},":man_cook_tone1:":{"uc_base":"1f468-1f3fb-1f373","uc_output":"1f468-1f3fb-200d-1f373","uc_match":"1f468-1f3fb-1f373","uc_greedy":"1f468-1f3fb-1f373","shortnames":[":man_cook_light_skin_tone:"],"category":"people"},":man_cook_tone2:":{"uc_base":"1f468-1f3fc-1f373","uc_output":"1f468-1f3fc-200d-1f373","uc_match":"1f468-1f3fc-1f373","uc_greedy":"1f468-1f3fc-1f373","shortnames":[":man_cook_medium_light_skin_tone:"],"category":"people"},":man_cook_tone3:":{"uc_base":"1f468-1f3fd-1f373","uc_output":"1f468-1f3fd-200d-1f373","uc_match":"1f468-1f3fd-1f373","uc_greedy":"1f468-1f3fd-1f373","shortnames":[":man_cook_medium_skin_tone:"],"category":"people"},":man_cook_tone4:":{"uc_base":"1f468-1f3fe-1f373","uc_output":"1f468-1f3fe-200d-1f373","uc_match":"1f468-1f3fe-1f373","uc_greedy":"1f468-1f3fe-1f373","shortnames":[":man_cook_medium_dark_skin_tone:"],"category":"people"},":man_cook_tone5:":{"uc_base":"1f468-1f3ff-1f373","uc_output":"1f468-1f3ff-200d-1f373","uc_match":"1f468-1f3ff-1f373","uc_greedy":"1f468-1f3ff-1f373","shortnames":[":man_cook_dark_skin_tone:"],"category":"people"},":man_factory_worker_tone1:":{"uc_base":"1f468-1f3fb-1f3ed","uc_output":"1f468-1f3fb-200d-1f3ed","uc_match":"1f468-1f3fb-1f3ed","uc_greedy":"1f468-1f3fb-1f3ed","shortnames":[":man_factory_worker_light_skin_tone:"],"category":"people"},":man_factory_worker_tone2:":{"uc_base":"1f468-1f3fc-1f3ed","uc_output":"1f468-1f3fc-200d-1f3ed","uc_match":"1f468-1f3fc-1f3ed","uc_greedy":"1f468-1f3fc-1f3ed","shortnames":[":man_factory_worker_medium_light_skin_tone:"],"category":"people"},":man_factory_worker_tone3:":{"uc_base":"1f468-1f3fd-1f3ed","uc_output":"1f468-1f3fd-200d-1f3ed","uc_match":"1f468-1f3fd-1f3ed","uc_greedy":"1f468-1f3fd-1f3ed","shortnames":[":man_factory_worker_medium_skin_tone:"],"category":"people"},":man_factory_worker_tone4:":{"uc_base":"1f468-1f3fe-1f3ed","uc_output":"1f468-1f3fe-200d-1f3ed","uc_match":"1f468-1f3fe-1f3ed","uc_greedy":"1f468-1f3fe-1f3ed","shortnames":[":man_factory_worker_medium_dark_skin_tone:"],"category":"people"},":man_factory_worker_tone5:":{"uc_base":"1f468-1f3ff-1f3ed","uc_output":"1f468-1f3ff-200d-1f3ed","uc_match":"1f468-1f3ff-1f3ed","uc_greedy":"1f468-1f3ff-1f3ed","shortnames":[":man_factory_worker_dark_skin_tone:"],"category":"people"},":man_farmer_tone1:":{"uc_base":"1f468-1f3fb-1f33e","uc_output":"1f468-1f3fb-200d-1f33e","uc_match":"1f468-1f3fb-1f33e","uc_greedy":"1f468-1f3fb-1f33e","shortnames":[":man_farmer_light_skin_tone:"],"category":"people"},":man_farmer_tone2:":{"uc_base":"1f468-1f3fc-1f33e","uc_output":"1f468-1f3fc-200d-1f33e","uc_match":"1f468-1f3fc-1f33e","uc_greedy":"1f468-1f3fc-1f33e","shortnames":[":man_farmer_medium_light_skin_tone:"],"category":"people"},":man_farmer_tone3:":{"uc_base":"1f468-1f3fd-1f33e","uc_output":"1f468-1f3fd-200d-1f33e","uc_match":"1f468-1f3fd-1f33e","uc_greedy":"1f468-1f3fd-1f33e","shortnames":[":man_farmer_medium_skin_tone:"],"category":"people"},":man_farmer_tone4:":{"uc_base":"1f468-1f3fe-1f33e","uc_output":"1f468-1f3fe-200d-1f33e","uc_match":"1f468-1f3fe-1f33e","uc_greedy":"1f468-1f3fe-1f33e","shortnames":[":man_farmer_medium_dark_skin_tone:"],"category":"people"},":man_farmer_tone5:":{"uc_base":"1f468-1f3ff-1f33e","uc_output":"1f468-1f3ff-200d-1f33e","uc_match":"1f468-1f3ff-1f33e","uc_greedy":"1f468-1f3ff-1f33e","shortnames":[":man_farmer_dark_skin_tone:"],"category":"people"},":man_firefighter_tone1:":{"uc_base":"1f468-1f3fb-1f692","uc_output":"1f468-1f3fb-200d-1f692","uc_match":"1f468-1f3fb-1f692","uc_greedy":"1f468-1f3fb-1f692","shortnames":[":man_firefighter_light_skin_tone:"],"category":"people"},":man_firefighter_tone2:":{"uc_base":"1f468-1f3fc-1f692","uc_output":"1f468-1f3fc-200d-1f692","uc_match":"1f468-1f3fc-1f692","uc_greedy":"1f468-1f3fc-1f692","shortnames":[":man_firefighter_medium_light_skin_tone:"],"category":"people"},":man_firefighter_tone3:":{"uc_base":"1f468-1f3fd-1f692","uc_output":"1f468-1f3fd-200d-1f692","uc_match":"1f468-1f3fd-1f692","uc_greedy":"1f468-1f3fd-1f692","shortnames":[":man_firefighter_medium_skin_tone:"],"category":"people"},":man_firefighter_tone4:":{"uc_base":"1f468-1f3fe-1f692","uc_output":"1f468-1f3fe-200d-1f692","uc_match":"1f468-1f3fe-1f692","uc_greedy":"1f468-1f3fe-1f692","shortnames":[":man_firefighter_medium_dark_skin_tone:"],"category":"people"},":man_firefighter_tone5:":{"uc_base":"1f468-1f3ff-1f692","uc_output":"1f468-1f3ff-200d-1f692","uc_match":"1f468-1f3ff-1f692","uc_greedy":"1f468-1f3ff-1f692","shortnames":[":man_firefighter_dark_skin_tone:"],"category":"people"},":man_mechanic_tone1:":{"uc_base":"1f468-1f3fb-1f527","uc_output":"1f468-1f3fb-200d-1f527","uc_match":"1f468-1f3fb-1f527","uc_greedy":"1f468-1f3fb-1f527","shortnames":[":man_mechanic_light_skin_tone:"],"category":"people"},":man_mechanic_tone2:":{"uc_base":"1f468-1f3fc-1f527","uc_output":"1f468-1f3fc-200d-1f527","uc_match":"1f468-1f3fc-1f527","uc_greedy":"1f468-1f3fc-1f527","shortnames":[":man_mechanic_medium_light_skin_tone:"],"category":"people"},":man_mechanic_tone3:":{"uc_base":"1f468-1f3fd-1f527","uc_output":"1f468-1f3fd-200d-1f527","uc_match":"1f468-1f3fd-1f527","uc_greedy":"1f468-1f3fd-1f527","shortnames":[":man_mechanic_medium_skin_tone:"],"category":"people"},":man_mechanic_tone4:":{"uc_base":"1f468-1f3fe-1f527","uc_output":"1f468-1f3fe-200d-1f527","uc_match":"1f468-1f3fe-1f527","uc_greedy":"1f468-1f3fe-1f527","shortnames":[":man_mechanic_medium_dark_skin_tone:"],"category":"people"},":man_mechanic_tone5:":{"uc_base":"1f468-1f3ff-1f527","uc_output":"1f468-1f3ff-200d-1f527","uc_match":"1f468-1f3ff-1f527","uc_greedy":"1f468-1f3ff-1f527","shortnames":[":man_mechanic_dark_skin_tone:"],"category":"people"},":man_office_worker_tone1:":{"uc_base":"1f468-1f3fb-1f4bc","uc_output":"1f468-1f3fb-200d-1f4bc","uc_match":"1f468-1f3fb-1f4bc","uc_greedy":"1f468-1f3fb-1f4bc","shortnames":[":man_office_worker_light_skin_tone:"],"category":"people"},":man_office_worker_tone2:":{"uc_base":"1f468-1f3fc-1f4bc","uc_output":"1f468-1f3fc-200d-1f4bc","uc_match":"1f468-1f3fc-1f4bc","uc_greedy":"1f468-1f3fc-1f4bc","shortnames":[":man_office_worker_medium_light_skin_tone:"],"category":"people"},":man_office_worker_tone3:":{"uc_base":"1f468-1f3fd-1f4bc","uc_output":"1f468-1f3fd-200d-1f4bc","uc_match":"1f468-1f3fd-1f4bc","uc_greedy":"1f468-1f3fd-1f4bc","shortnames":[":man_office_worker_medium_skin_tone:"],"category":"people"},":man_office_worker_tone4:":{"uc_base":"1f468-1f3fe-1f4bc","uc_output":"1f468-1f3fe-200d-1f4bc","uc_match":"1f468-1f3fe-1f4bc","uc_greedy":"1f468-1f3fe-1f4bc","shortnames":[":man_office_worker_medium_dark_skin_tone:"],"category":"people"},":man_office_worker_tone5:":{"uc_base":"1f468-1f3ff-1f4bc","uc_output":"1f468-1f3ff-200d-1f4bc","uc_match":"1f468-1f3ff-1f4bc","uc_greedy":"1f468-1f3ff-1f4bc","shortnames":[":man_office_worker_dark_skin_tone:"],"category":"people"},":man_scientist_tone1:":{"uc_base":"1f468-1f3fb-1f52c","uc_output":"1f468-1f3fb-200d-1f52c","uc_match":"1f468-1f3fb-1f52c","uc_greedy":"1f468-1f3fb-1f52c","shortnames":[":man_scientist_light_skin_tone:"],"category":"people"},":man_scientist_tone2:":{"uc_base":"1f468-1f3fc-1f52c","uc_output":"1f468-1f3fc-200d-1f52c","uc_match":"1f468-1f3fc-1f52c","uc_greedy":"1f468-1f3fc-1f52c","shortnames":[":man_scientist_medium_light_skin_tone:"],"category":"people"},":man_scientist_tone3:":{"uc_base":"1f468-1f3fd-1f52c","uc_output":"1f468-1f3fd-200d-1f52c","uc_match":"1f468-1f3fd-1f52c","uc_greedy":"1f468-1f3fd-1f52c","shortnames":[":man_scientist_medium_skin_tone:"],"category":"people"},":man_scientist_tone4:":{"uc_base":"1f468-1f3fe-1f52c","uc_output":"1f468-1f3fe-200d-1f52c","uc_match":"1f468-1f3fe-1f52c","uc_greedy":"1f468-1f3fe-1f52c","shortnames":[":man_scientist_medium_dark_skin_tone:"],"category":"people"},":man_scientist_tone5:":{"uc_base":"1f468-1f3ff-1f52c","uc_output":"1f468-1f3ff-200d-1f52c","uc_match":"1f468-1f3ff-1f52c","uc_greedy":"1f468-1f3ff-1f52c","shortnames":[":man_scientist_dark_skin_tone:"],"category":"people"},":man_singer_tone1:":{"uc_base":"1f468-1f3fb-1f3a4","uc_output":"1f468-1f3fb-200d-1f3a4","uc_match":"1f468-1f3fb-1f3a4","uc_greedy":"1f468-1f3fb-1f3a4","shortnames":[":man_singer_light_skin_tone:"],"category":"people"},":man_singer_tone2:":{"uc_base":"1f468-1f3fc-1f3a4","uc_output":"1f468-1f3fc-200d-1f3a4","uc_match":"1f468-1f3fc-1f3a4","uc_greedy":"1f468-1f3fc-1f3a4","shortnames":[":man_singer_medium_light_skin_tone:"],"category":"people"},":man_singer_tone3:":{"uc_base":"1f468-1f3fd-1f3a4","uc_output":"1f468-1f3fd-200d-1f3a4","uc_match":"1f468-1f3fd-1f3a4","uc_greedy":"1f468-1f3fd-1f3a4","shortnames":[":man_singer_medium_skin_tone:"],"category":"people"},":man_singer_tone4:":{"uc_base":"1f468-1f3fe-1f3a4","uc_output":"1f468-1f3fe-200d-1f3a4","uc_match":"1f468-1f3fe-1f3a4","uc_greedy":"1f468-1f3fe-1f3a4","shortnames":[":man_singer_medium_dark_skin_tone:"],"category":"people"},":man_singer_tone5:":{"uc_base":"1f468-1f3ff-1f3a4","uc_output":"1f468-1f3ff-200d-1f3a4","uc_match":"1f468-1f3ff-1f3a4","uc_greedy":"1f468-1f3ff-1f3a4","shortnames":[":man_singer_dark_skin_tone:"],"category":"people"},":man_student_tone1:":{"uc_base":"1f468-1f3fb-1f393","uc_output":"1f468-1f3fb-200d-1f393","uc_match":"1f468-1f3fb-1f393","uc_greedy":"1f468-1f3fb-1f393","shortnames":[":man_student_light_skin_tone:"],"category":"people"},":man_student_tone2:":{"uc_base":"1f468-1f3fc-1f393","uc_output":"1f468-1f3fc-200d-1f393","uc_match":"1f468-1f3fc-1f393","uc_greedy":"1f468-1f3fc-1f393","shortnames":[":man_student_medium_light_skin_tone:"],"category":"people"},":man_student_tone3:":{"uc_base":"1f468-1f3fd-1f393","uc_output":"1f468-1f3fd-200d-1f393","uc_match":"1f468-1f3fd-1f393","uc_greedy":"1f468-1f3fd-1f393","shortnames":[":man_student_medium_skin_tone:"],"category":"people"},":man_student_tone4:":{"uc_base":"1f468-1f3fe-1f393","uc_output":"1f468-1f3fe-200d-1f393","uc_match":"1f468-1f3fe-1f393","uc_greedy":"1f468-1f3fe-1f393","shortnames":[":man_student_medium_dark_skin_tone:"],"category":"people"},":man_student_tone5:":{"uc_base":"1f468-1f3ff-1f393","uc_output":"1f468-1f3ff-200d-1f393","uc_match":"1f468-1f3ff-1f393","uc_greedy":"1f468-1f3ff-1f393","shortnames":[":man_student_dark_skin_tone:"],"category":"people"},":man_teacher_tone1:":{"uc_base":"1f468-1f3fb-1f3eb","uc_output":"1f468-1f3fb-200d-1f3eb","uc_match":"1f468-1f3fb-1f3eb","uc_greedy":"1f468-1f3fb-1f3eb","shortnames":[":man_teacher_light_skin_tone:"],"category":"people"},":man_teacher_tone2:":{"uc_base":"1f468-1f3fc-1f3eb","uc_output":"1f468-1f3fc-200d-1f3eb","uc_match":"1f468-1f3fc-1f3eb","uc_greedy":"1f468-1f3fc-1f3eb","shortnames":[":man_teacher_medium_light_skin_tone:"],"category":"people"},":man_teacher_tone3:":{"uc_base":"1f468-1f3fd-1f3eb","uc_output":"1f468-1f3fd-200d-1f3eb","uc_match":"1f468-1f3fd-1f3eb","uc_greedy":"1f468-1f3fd-1f3eb","shortnames":[":man_teacher_medium_skin_tone:"],"category":"people"},":man_teacher_tone4:":{"uc_base":"1f468-1f3fe-1f3eb","uc_output":"1f468-1f3fe-200d-1f3eb","uc_match":"1f468-1f3fe-1f3eb","uc_greedy":"1f468-1f3fe-1f3eb","shortnames":[":man_teacher_medium_dark_skin_tone:"],"category":"people"},":man_teacher_tone5:":{"uc_base":"1f468-1f3ff-1f3eb","uc_output":"1f468-1f3ff-200d-1f3eb","uc_match":"1f468-1f3ff-1f3eb","uc_greedy":"1f468-1f3ff-1f3eb","shortnames":[":man_teacher_dark_skin_tone:"],"category":"people"},":man_technologist_tone1:":{"uc_base":"1f468-1f3fb-1f4bb","uc_output":"1f468-1f3fb-200d-1f4bb","uc_match":"1f468-1f3fb-1f4bb","uc_greedy":"1f468-1f3fb-1f4bb","shortnames":[":man_technologist_light_skin_tone:"],"category":"people"},":man_technologist_tone2:":{"uc_base":"1f468-1f3fc-1f4bb","uc_output":"1f468-1f3fc-200d-1f4bb","uc_match":"1f468-1f3fc-1f4bb","uc_greedy":"1f468-1f3fc-1f4bb","shortnames":[":man_technologist_medium_light_skin_tone:"],"category":"people"},":man_technologist_tone3:":{"uc_base":"1f468-1f3fd-1f4bb","uc_output":"1f468-1f3fd-200d-1f4bb","uc_match":"1f468-1f3fd-1f4bb","uc_greedy":"1f468-1f3fd-1f4bb","shortnames":[":man_technologist_medium_skin_tone:"],"category":"people"},":man_technologist_tone4:":{"uc_base":"1f468-1f3fe-1f4bb","uc_output":"1f468-1f3fe-200d-1f4bb","uc_match":"1f468-1f3fe-1f4bb","uc_greedy":"1f468-1f3fe-1f4bb","shortnames":[":man_technologist_medium_dark_skin_tone:"],"category":"people"},":man_technologist_tone5:":{"uc_base":"1f468-1f3ff-1f4bb","uc_output":"1f468-1f3ff-200d-1f4bb","uc_match":"1f468-1f3ff-1f4bb","uc_greedy":"1f468-1f3ff-1f4bb","shortnames":[":man_technologist_dark_skin_tone:"],"category":"people"},":woman_artist_tone1:":{"uc_base":"1f469-1f3fb-1f3a8","uc_output":"1f469-1f3fb-200d-1f3a8","uc_match":"1f469-1f3fb-1f3a8","uc_greedy":"1f469-1f3fb-1f3a8","shortnames":[":woman_artist_light_skin_tone:"],"category":"people"},":woman_artist_tone2:":{"uc_base":"1f469-1f3fc-1f3a8","uc_output":"1f469-1f3fc-200d-1f3a8","uc_match":"1f469-1f3fc-1f3a8","uc_greedy":"1f469-1f3fc-1f3a8","shortnames":[":woman_artist_medium_light_skin_tone:"],"category":"people"},":woman_artist_tone3:":{"uc_base":"1f469-1f3fd-1f3a8","uc_output":"1f469-1f3fd-200d-1f3a8","uc_match":"1f469-1f3fd-1f3a8","uc_greedy":"1f469-1f3fd-1f3a8","shortnames":[":woman_artist_medium_skin_tone:"],"category":"people"},":woman_artist_tone4:":{"uc_base":"1f469-1f3fe-1f3a8","uc_output":"1f469-1f3fe-200d-1f3a8","uc_match":"1f469-1f3fe-1f3a8","uc_greedy":"1f469-1f3fe-1f3a8","shortnames":[":woman_artist_medium_dark_skin_tone:"],"category":"people"},":woman_artist_tone5:":{"uc_base":"1f469-1f3ff-1f3a8","uc_output":"1f469-1f3ff-200d-1f3a8","uc_match":"1f469-1f3ff-1f3a8","uc_greedy":"1f469-1f3ff-1f3a8","shortnames":[":woman_artist_dark_skin_tone:"],"category":"people"},":woman_astronaut_tone1:":{"uc_base":"1f469-1f3fb-1f680","uc_output":"1f469-1f3fb-200d-1f680","uc_match":"1f469-1f3fb-1f680","uc_greedy":"1f469-1f3fb-1f680","shortnames":[":woman_astronaut_light_skin_tone:"],"category":"people"},":woman_astronaut_tone2:":{"uc_base":"1f469-1f3fc-1f680","uc_output":"1f469-1f3fc-200d-1f680","uc_match":"1f469-1f3fc-1f680","uc_greedy":"1f469-1f3fc-1f680","shortnames":[":woman_astronaut_medium_light_skin_tone:"],"category":"people"},":woman_astronaut_tone3:":{"uc_base":"1f469-1f3fd-1f680","uc_output":"1f469-1f3fd-200d-1f680","uc_match":"1f469-1f3fd-1f680","uc_greedy":"1f469-1f3fd-1f680","shortnames":[":woman_astronaut_medium_skin_tone:"],"category":"people"},":woman_astronaut_tone4:":{"uc_base":"1f469-1f3fe-1f680","uc_output":"1f469-1f3fe-200d-1f680","uc_match":"1f469-1f3fe-1f680","uc_greedy":"1f469-1f3fe-1f680","shortnames":[":woman_astronaut_medium_dark_skin_tone:"],"category":"people"},":woman_astronaut_tone5:":{"uc_base":"1f469-1f3ff-1f680","uc_output":"1f469-1f3ff-200d-1f680","uc_match":"1f469-1f3ff-1f680","uc_greedy":"1f469-1f3ff-1f680","shortnames":[":woman_astronaut_dark_skin_tone:"],"category":"people"},":woman_cook_tone1:":{"uc_base":"1f469-1f3fb-1f373","uc_output":"1f469-1f3fb-200d-1f373","uc_match":"1f469-1f3fb-1f373","uc_greedy":"1f469-1f3fb-1f373","shortnames":[":woman_cook_light_skin_tone:"],"category":"people"},":woman_cook_tone2:":{"uc_base":"1f469-1f3fc-1f373","uc_output":"1f469-1f3fc-200d-1f373","uc_match":"1f469-1f3fc-1f373","uc_greedy":"1f469-1f3fc-1f373","shortnames":[":woman_cook_medium_light_skin_tone:"],"category":"people"},":woman_cook_tone3:":{"uc_base":"1f469-1f3fd-1f373","uc_output":"1f469-1f3fd-200d-1f373","uc_match":"1f469-1f3fd-1f373","uc_greedy":"1f469-1f3fd-1f373","shortnames":[":woman_cook_medium_skin_tone:"],"category":"people"},":woman_cook_tone4:":{"uc_base":"1f469-1f3fe-1f373","uc_output":"1f469-1f3fe-200d-1f373","uc_match":"1f469-1f3fe-1f373","uc_greedy":"1f469-1f3fe-1f373","shortnames":[":woman_cook_medium_dark_skin_tone:"],"category":"people"},":woman_cook_tone5:":{"uc_base":"1f469-1f3ff-1f373","uc_output":"1f469-1f3ff-200d-1f373","uc_match":"1f469-1f3ff-1f373","uc_greedy":"1f469-1f3ff-1f373","shortnames":[":woman_cook_dark_skin_tone:"],"category":"people"},":woman_factory_worker_tone1:":{"uc_base":"1f469-1f3fb-1f3ed","uc_output":"1f469-1f3fb-200d-1f3ed","uc_match":"1f469-1f3fb-1f3ed","uc_greedy":"1f469-1f3fb-1f3ed","shortnames":[":woman_factory_worker_light_skin_tone:"],"category":"people"},":woman_factory_worker_tone2:":{"uc_base":"1f469-1f3fc-1f3ed","uc_output":"1f469-1f3fc-200d-1f3ed","uc_match":"1f469-1f3fc-1f3ed","uc_greedy":"1f469-1f3fc-1f3ed","shortnames":[":woman_factory_worker_medium_light_skin_tone:"],"category":"people"},":woman_factory_worker_tone3:":{"uc_base":"1f469-1f3fd-1f3ed","uc_output":"1f469-1f3fd-200d-1f3ed","uc_match":"1f469-1f3fd-1f3ed","uc_greedy":"1f469-1f3fd-1f3ed","shortnames":[":woman_factory_worker_medium_skin_tone:"],"category":"people"},":woman_factory_worker_tone4:":{"uc_base":"1f469-1f3fe-1f3ed","uc_output":"1f469-1f3fe-200d-1f3ed","uc_match":"1f469-1f3fe-1f3ed","uc_greedy":"1f469-1f3fe-1f3ed","shortnames":[":woman_factory_worker_medium_dark_skin_tone:"],"category":"people"},":woman_factory_worker_tone5:":{"uc_base":"1f469-1f3ff-1f3ed","uc_output":"1f469-1f3ff-200d-1f3ed","uc_match":"1f469-1f3ff-1f3ed","uc_greedy":"1f469-1f3ff-1f3ed","shortnames":[":woman_factory_worker_dark_skin_tone:"],"category":"people"},":woman_farmer_tone1:":{"uc_base":"1f469-1f3fb-1f33e","uc_output":"1f469-1f3fb-200d-1f33e","uc_match":"1f469-1f3fb-1f33e","uc_greedy":"1f469-1f3fb-1f33e","shortnames":[":woman_farmer_light_skin_tone:"],"category":"people"},":woman_farmer_tone2:":{"uc_base":"1f469-1f3fc-1f33e","uc_output":"1f469-1f3fc-200d-1f33e","uc_match":"1f469-1f3fc-1f33e","uc_greedy":"1f469-1f3fc-1f33e","shortnames":[":woman_farmer_medium_light_skin_tone:"],"category":"people"},":woman_farmer_tone3:":{"uc_base":"1f469-1f3fd-1f33e","uc_output":"1f469-1f3fd-200d-1f33e","uc_match":"1f469-1f3fd-1f33e","uc_greedy":"1f469-1f3fd-1f33e","shortnames":[":woman_farmer_medium_skin_tone:"],"category":"people"},":woman_farmer_tone4:":{"uc_base":"1f469-1f3fe-1f33e","uc_output":"1f469-1f3fe-200d-1f33e","uc_match":"1f469-1f3fe-1f33e","uc_greedy":"1f469-1f3fe-1f33e","shortnames":[":woman_farmer_medium_dark_skin_tone:"],"category":"people"},":woman_farmer_tone5:":{"uc_base":"1f469-1f3ff-1f33e","uc_output":"1f469-1f3ff-200d-1f33e","uc_match":"1f469-1f3ff-1f33e","uc_greedy":"1f469-1f3ff-1f33e","shortnames":[":woman_farmer_dark_skin_tone:"],"category":"people"},":woman_firefighter_tone1:":{"uc_base":"1f469-1f3fb-1f692","uc_output":"1f469-1f3fb-200d-1f692","uc_match":"1f469-1f3fb-1f692","uc_greedy":"1f469-1f3fb-1f692","shortnames":[":woman_firefighter_light_skin_tone:"],"category":"people"},":woman_firefighter_tone2:":{"uc_base":"1f469-1f3fc-1f692","uc_output":"1f469-1f3fc-200d-1f692","uc_match":"1f469-1f3fc-1f692","uc_greedy":"1f469-1f3fc-1f692","shortnames":[":woman_firefighter_medium_light_skin_tone:"],"category":"people"},":woman_firefighter_tone3:":{"uc_base":"1f469-1f3fd-1f692","uc_output":"1f469-1f3fd-200d-1f692","uc_match":"1f469-1f3fd-1f692","uc_greedy":"1f469-1f3fd-1f692","shortnames":[":woman_firefighter_medium_skin_tone:"],"category":"people"},":woman_firefighter_tone4:":{"uc_base":"1f469-1f3fe-1f692","uc_output":"1f469-1f3fe-200d-1f692","uc_match":"1f469-1f3fe-1f692","uc_greedy":"1f469-1f3fe-1f692","shortnames":[":woman_firefighter_medium_dark_skin_tone:"],"category":"people"},":woman_firefighter_tone5:":{"uc_base":"1f469-1f3ff-1f692","uc_output":"1f469-1f3ff-200d-1f692","uc_match":"1f469-1f3ff-1f692","uc_greedy":"1f469-1f3ff-1f692","shortnames":[":woman_firefighter_dark_skin_tone:"],"category":"people"},":woman_mechanic_tone1:":{"uc_base":"1f469-1f3fb-1f527","uc_output":"1f469-1f3fb-200d-1f527","uc_match":"1f469-1f3fb-1f527","uc_greedy":"1f469-1f3fb-1f527","shortnames":[":woman_mechanic_light_skin_tone:"],"category":"people"},":woman_mechanic_tone2:":{"uc_base":"1f469-1f3fc-1f527","uc_output":"1f469-1f3fc-200d-1f527","uc_match":"1f469-1f3fc-1f527","uc_greedy":"1f469-1f3fc-1f527","shortnames":[":woman_mechanic_medium_light_skin_tone:"],"category":"people"},":woman_mechanic_tone3:":{"uc_base":"1f469-1f3fd-1f527","uc_output":"1f469-1f3fd-200d-1f527","uc_match":"1f469-1f3fd-1f527","uc_greedy":"1f469-1f3fd-1f527","shortnames":[":woman_mechanic_medium_skin_tone:"],"category":"people"},":woman_mechanic_tone4:":{"uc_base":"1f469-1f3fe-1f527","uc_output":"1f469-1f3fe-200d-1f527","uc_match":"1f469-1f3fe-1f527","uc_greedy":"1f469-1f3fe-1f527","shortnames":[":woman_mechanic_medium_dark_skin_tone:"],"category":"people"},":woman_mechanic_tone5:":{"uc_base":"1f469-1f3ff-1f527","uc_output":"1f469-1f3ff-200d-1f527","uc_match":"1f469-1f3ff-1f527","uc_greedy":"1f469-1f3ff-1f527","shortnames":[":woman_mechanic_dark_skin_tone:"],"category":"people"},":woman_office_worker_tone1:":{"uc_base":"1f469-1f3fb-1f4bc","uc_output":"1f469-1f3fb-200d-1f4bc","uc_match":"1f469-1f3fb-1f4bc","uc_greedy":"1f469-1f3fb-1f4bc","shortnames":[":woman_office_worker_light_skin_tone:"],"category":"people"},":woman_office_worker_tone2:":{"uc_base":"1f469-1f3fc-1f4bc","uc_output":"1f469-1f3fc-200d-1f4bc","uc_match":"1f469-1f3fc-1f4bc","uc_greedy":"1f469-1f3fc-1f4bc","shortnames":[":woman_office_worker_medium_light_skin_tone:"],"category":"people"},":woman_office_worker_tone3:":{"uc_base":"1f469-1f3fd-1f4bc","uc_output":"1f469-1f3fd-200d-1f4bc","uc_match":"1f469-1f3fd-1f4bc","uc_greedy":"1f469-1f3fd-1f4bc","shortnames":[":woman_office_worker_medium_skin_tone:"],"category":"people"},":woman_office_worker_tone4:":{"uc_base":"1f469-1f3fe-1f4bc","uc_output":"1f469-1f3fe-200d-1f4bc","uc_match":"1f469-1f3fe-1f4bc","uc_greedy":"1f469-1f3fe-1f4bc","shortnames":[":woman_office_worker_medium_dark_skin_tone:"],"category":"people"},":woman_office_worker_tone5:":{"uc_base":"1f469-1f3ff-1f4bc","uc_output":"1f469-1f3ff-200d-1f4bc","uc_match":"1f469-1f3ff-1f4bc","uc_greedy":"1f469-1f3ff-1f4bc","shortnames":[":woman_office_worker_dark_skin_tone:"],"category":"people"},":woman_scientist_tone1:":{"uc_base":"1f469-1f3fb-1f52c","uc_output":"1f469-1f3fb-200d-1f52c","uc_match":"1f469-1f3fb-1f52c","uc_greedy":"1f469-1f3fb-1f52c","shortnames":[":woman_scientist_light_skin_tone:"],"category":"people"},":woman_scientist_tone2:":{"uc_base":"1f469-1f3fc-1f52c","uc_output":"1f469-1f3fc-200d-1f52c","uc_match":"1f469-1f3fc-1f52c","uc_greedy":"1f469-1f3fc-1f52c","shortnames":[":woman_scientist_medium_light_skin_tone:"],"category":"people"},":woman_scientist_tone3:":{"uc_base":"1f469-1f3fd-1f52c","uc_output":"1f469-1f3fd-200d-1f52c","uc_match":"1f469-1f3fd-1f52c","uc_greedy":"1f469-1f3fd-1f52c","shortnames":[":woman_scientist_medium_skin_tone:"],"category":"people"},":woman_scientist_tone4:":{"uc_base":"1f469-1f3fe-1f52c","uc_output":"1f469-1f3fe-200d-1f52c","uc_match":"1f469-1f3fe-1f52c","uc_greedy":"1f469-1f3fe-1f52c","shortnames":[":woman_scientist_medium_dark_skin_tone:"],"category":"people"},":woman_scientist_tone5:":{"uc_base":"1f469-1f3ff-1f52c","uc_output":"1f469-1f3ff-200d-1f52c","uc_match":"1f469-1f3ff-1f52c","uc_greedy":"1f469-1f3ff-1f52c","shortnames":[":woman_scientist_dark_skin_tone:"],"category":"people"},":woman_singer_tone1:":{"uc_base":"1f469-1f3fb-1f3a4","uc_output":"1f469-1f3fb-200d-1f3a4","uc_match":"1f469-1f3fb-1f3a4","uc_greedy":"1f469-1f3fb-1f3a4","shortnames":[":woman_singer_light_skin_tone:"],"category":"people"},":woman_singer_tone2:":{"uc_base":"1f469-1f3fc-1f3a4","uc_output":"1f469-1f3fc-200d-1f3a4","uc_match":"1f469-1f3fc-1f3a4","uc_greedy":"1f469-1f3fc-1f3a4","shortnames":[":woman_singer_medium_light_skin_tone:"],"category":"people"},":woman_singer_tone3:":{"uc_base":"1f469-1f3fd-1f3a4","uc_output":"1f469-1f3fd-200d-1f3a4","uc_match":"1f469-1f3fd-1f3a4","uc_greedy":"1f469-1f3fd-1f3a4","shortnames":[":woman_singer_medium_skin_tone:"],"category":"people"},":woman_singer_tone4:":{"uc_base":"1f469-1f3fe-1f3a4","uc_output":"1f469-1f3fe-200d-1f3a4","uc_match":"1f469-1f3fe-1f3a4","uc_greedy":"1f469-1f3fe-1f3a4","shortnames":[":woman_singer_medium_dark_skin_tone:"],"category":"people"},":woman_singer_tone5:":{"uc_base":"1f469-1f3ff-1f3a4","uc_output":"1f469-1f3ff-200d-1f3a4","uc_match":"1f469-1f3ff-1f3a4","uc_greedy":"1f469-1f3ff-1f3a4","shortnames":[":woman_singer_dark_skin_tone:"],"category":"people"},":woman_student_tone1:":{"uc_base":"1f469-1f3fb-1f393","uc_output":"1f469-1f3fb-200d-1f393","uc_match":"1f469-1f3fb-1f393","uc_greedy":"1f469-1f3fb-1f393","shortnames":[":woman_student_light_skin_tone:"],"category":"people"},":woman_student_tone2:":{"uc_base":"1f469-1f3fc-1f393","uc_output":"1f469-1f3fc-200d-1f393","uc_match":"1f469-1f3fc-1f393","uc_greedy":"1f469-1f3fc-1f393","shortnames":[":woman_student_medium_light_skin_tone:"],"category":"people"},":woman_student_tone3:":{"uc_base":"1f469-1f3fd-1f393","uc_output":"1f469-1f3fd-200d-1f393","uc_match":"1f469-1f3fd-1f393","uc_greedy":"1f469-1f3fd-1f393","shortnames":[":woman_student_medium_skin_tone:"],"category":"people"},":woman_student_tone4:":{"uc_base":"1f469-1f3fe-1f393","uc_output":"1f469-1f3fe-200d-1f393","uc_match":"1f469-1f3fe-1f393","uc_greedy":"1f469-1f3fe-1f393","shortnames":[":woman_student_medium_dark_skin_tone:"],"category":"people"},":woman_student_tone5:":{"uc_base":"1f469-1f3ff-1f393","uc_output":"1f469-1f3ff-200d-1f393","uc_match":"1f469-1f3ff-1f393","uc_greedy":"1f469-1f3ff-1f393","shortnames":[":woman_student_dark_skin_tone:"],"category":"people"},":woman_teacher_tone1:":{"uc_base":"1f469-1f3fb-1f3eb","uc_output":"1f469-1f3fb-200d-1f3eb","uc_match":"1f469-1f3fb-1f3eb","uc_greedy":"1f469-1f3fb-1f3eb","shortnames":[":woman_teacher_light_skin_tone:"],"category":"people"},":woman_teacher_tone2:":{"uc_base":"1f469-1f3fc-1f3eb","uc_output":"1f469-1f3fc-200d-1f3eb","uc_match":"1f469-1f3fc-1f3eb","uc_greedy":"1f469-1f3fc-1f3eb","shortnames":[":woman_teacher_medium_light_skin_tone:"],"category":"people"},":woman_teacher_tone3:":{"uc_base":"1f469-1f3fd-1f3eb","uc_output":"1f469-1f3fd-200d-1f3eb","uc_match":"1f469-1f3fd-1f3eb","uc_greedy":"1f469-1f3fd-1f3eb","shortnames":[":woman_teacher_medium_skin_tone:"],"category":"people"},":woman_teacher_tone4:":{"uc_base":"1f469-1f3fe-1f3eb","uc_output":"1f469-1f3fe-200d-1f3eb","uc_match":"1f469-1f3fe-1f3eb","uc_greedy":"1f469-1f3fe-1f3eb","shortnames":[":woman_teacher_medium_dark_skin_tone:"],"category":"people"},":woman_teacher_tone5:":{"uc_base":"1f469-1f3ff-1f3eb","uc_output":"1f469-1f3ff-200d-1f3eb","uc_match":"1f469-1f3ff-1f3eb","uc_greedy":"1f469-1f3ff-1f3eb","shortnames":[":woman_teacher_dark_skin_tone:"],"category":"people"},":woman_technologist_tone1:":{"uc_base":"1f469-1f3fb-1f4bb","uc_output":"1f469-1f3fb-200d-1f4bb","uc_match":"1f469-1f3fb-1f4bb","uc_greedy":"1f469-1f3fb-1f4bb","shortnames":[":woman_technologist_light_skin_tone:"],"category":"people"},":woman_technologist_tone2:":{"uc_base":"1f469-1f3fc-1f4bb","uc_output":"1f469-1f3fc-200d-1f4bb","uc_match":"1f469-1f3fc-1f4bb","uc_greedy":"1f469-1f3fc-1f4bb","shortnames":[":woman_technologist_medium_light_skin_tone:"],"category":"people"},":woman_technologist_tone3:":{"uc_base":"1f469-1f3fd-1f4bb","uc_output":"1f469-1f3fd-200d-1f4bb","uc_match":"1f469-1f3fd-1f4bb","uc_greedy":"1f469-1f3fd-1f4bb","shortnames":[":woman_technologist_medium_skin_tone:"],"category":"people"},":woman_technologist_tone4:":{"uc_base":"1f469-1f3fe-1f4bb","uc_output":"1f469-1f3fe-200d-1f4bb","uc_match":"1f469-1f3fe-1f4bb","uc_greedy":"1f469-1f3fe-1f4bb","shortnames":[":woman_technologist_medium_dark_skin_tone:"],"category":"people"},":woman_technologist_tone5:":{"uc_base":"1f469-1f3ff-1f4bb","uc_output":"1f469-1f3ff-200d-1f4bb","uc_match":"1f469-1f3ff-1f4bb","uc_greedy":"1f469-1f3ff-1f4bb","shortnames":[":woman_technologist_dark_skin_tone:"],"category":"people"},":rainbow_flag:":{"uc_base":"1f3f3-1f308","uc_output":"1f3f3-fe0f-200d-1f308","uc_match":"1f3f3-fe0f-1f308","uc_greedy":"1f3f3-1f308","shortnames":[":gay_pride_flag:"],"category":"flags"},":blond-haired_man:":{"uc_base":"1f471-2642","uc_output":"1f471-200d-2642-fe0f","uc_match":"1f471-2642-fe0f","uc_greedy":"1f471-2642","shortnames":[],"category":"people"},":blond-haired_woman:":{"uc_base":"1f471-2640","uc_output":"1f471-200d-2640-fe0f","uc_match":"1f471-2640-fe0f","uc_greedy":"1f471-2640","shortnames":[],"category":"people"},":man_biking:":{"uc_base":"1f6b4-2642","uc_output":"1f6b4-200d-2642-fe0f","uc_match":"1f6b4-2642-fe0f","uc_greedy":"1f6b4-2642","shortnames":[],"category":"activity"},":man_bowing:":{"uc_base":"1f647-2642","uc_output":"1f647-200d-2642-fe0f","uc_match":"1f647-2642-fe0f","uc_greedy":"1f647-2642","shortnames":[],"category":"people"},":man_cartwheeling:":{"uc_base":"1f938-2642","uc_output":"1f938-200d-2642-fe0f","uc_match":"1f938-2642-fe0f","uc_greedy":"1f938-2642","shortnames":[],"category":"activity"},":man_climbing:":{"uc_base":"1f9d7-2642","uc_output":"1f9d7-200d-2642-fe0f","uc_match":"1f9d7-2642-fe0f","uc_greedy":"1f9d7-2642","shortnames":[],"category":"activity"},":man_construction_worker:":{"uc_base":"1f477-2642","uc_output":"1f477-200d-2642-fe0f","uc_match":"1f477-2642-fe0f","uc_greedy":"1f477-2642","shortnames":[],"category":"people"},":man_elf:":{"uc_base":"1f9dd-2642","uc_output":"1f9dd-200d-2642-fe0f","uc_match":"1f9dd-2642-fe0f","uc_greedy":"1f9dd-2642","shortnames":[],"category":"people"},":man_facepalming:":{"uc_base":"1f926-2642","uc_output":"1f926-200d-2642-fe0f","uc_match":"1f926-2642-fe0f","uc_greedy":"1f926-2642","shortnames":[],"category":"people"},":man_fairy:":{"uc_base":"1f9da-2642","uc_output":"1f9da-200d-2642-fe0f","uc_match":"1f9da-2642-fe0f","uc_greedy":"1f9da-2642","shortnames":[],"category":"people"},":man_frowning:":{"uc_base":"1f64d-2642","uc_output":"1f64d-200d-2642-fe0f","uc_match":"1f64d-2642-fe0f","uc_greedy":"1f64d-2642","shortnames":[],"category":"people"},":man_genie:":{"uc_base":"1f9de-2642","uc_output":"1f9de-200d-2642-fe0f","uc_match":"1f9de-2642-fe0f","uc_greedy":"1f9de-2642","shortnames":[],"category":"people"},":man_gesturing_no:":{"uc_base":"1f645-2642","uc_output":"1f645-200d-2642-fe0f","uc_match":"1f645-2642-fe0f","uc_greedy":"1f645-2642","shortnames":[],"category":"people"},":man_gesturing_ok:":{"uc_base":"1f646-2642","uc_output":"1f646-200d-2642-fe0f","uc_match":"1f646-2642-fe0f","uc_greedy":"1f646-2642","shortnames":[],"category":"people"},":man_getting_face_massage:":{"uc_base":"1f486-2642","uc_output":"1f486-200d-2642-fe0f","uc_match":"1f486-2642-fe0f","uc_greedy":"1f486-2642","shortnames":[],"category":"people"},":man_getting_haircut:":{"uc_base":"1f487-2642","uc_output":"1f487-200d-2642-fe0f","uc_match":"1f487-2642-fe0f","uc_greedy":"1f487-2642","shortnames":[],"category":"people"},":man_guard:":{"uc_base":"1f482-2642","uc_output":"1f482-200d-2642-fe0f","uc_match":"1f482-2642-fe0f","uc_greedy":"1f482-2642","shortnames":[],"category":"people"},":man_health_worker:":{"uc_base":"1f468-2695","uc_output":"1f468-200d-2695-fe0f","uc_match":"1f468-2695-fe0f","uc_greedy":"1f468-2695","shortnames":[],"category":"people"},":man_in_lotus_position:":{"uc_base":"1f9d8-2642","uc_output":"1f9d8-200d-2642-fe0f","uc_match":"1f9d8-2642-fe0f","uc_greedy":"1f9d8-2642","shortnames":[],"category":"activity"},":man_in_steamy_room:":{"uc_base":"1f9d6-2642","uc_output":"1f9d6-200d-2642-fe0f","uc_match":"1f9d6-2642-fe0f","uc_greedy":"1f9d6-2642","shortnames":[],"category":"activity"},":man_judge:":{"uc_base":"1f468-2696","uc_output":"1f468-200d-2696-fe0f","uc_match":"1f468-2696-fe0f","uc_greedy":"1f468-2696","shortnames":[],"category":"people"},":man_juggling:":{"uc_base":"1f939-2642","uc_output":"1f939-200d-2642-fe0f","uc_match":"1f939-2642-fe0f","uc_greedy":"1f939-2642","shortnames":[],"category":"activity"},":man_mage:":{"uc_base":"1f9d9-2642","uc_output":"1f9d9-200d-2642-fe0f","uc_match":"1f9d9-2642-fe0f","uc_greedy":"1f9d9-2642","shortnames":[],"category":"people"},":man_mountain_biking:":{"uc_base":"1f6b5-2642","uc_output":"1f6b5-200d-2642-fe0f","uc_match":"1f6b5-2642-fe0f","uc_greedy":"1f6b5-2642","shortnames":[],"category":"activity"},":man_pilot:":{"uc_base":"1f468-2708","uc_output":"1f468-200d-2708-fe0f","uc_match":"1f468-2708-fe0f","uc_greedy":"1f468-2708","shortnames":[],"category":"people"},":man_playing_handball:":{"uc_base":"1f93e-2642","uc_output":"1f93e-200d-2642-fe0f","uc_match":"1f93e-2642-fe0f","uc_greedy":"1f93e-2642","shortnames":[],"category":"activity"},":man_playing_water_polo:":{"uc_base":"1f93d-2642","uc_output":"1f93d-200d-2642-fe0f","uc_match":"1f93d-2642-fe0f","uc_greedy":"1f93d-2642","shortnames":[],"category":"activity"},":man_police_officer:":{"uc_base":"1f46e-2642","uc_output":"1f46e-200d-2642-fe0f","uc_match":"1f46e-2642-fe0f","uc_greedy":"1f46e-2642","shortnames":[],"category":"people"},":man_pouting:":{"uc_base":"1f64e-2642","uc_output":"1f64e-200d-2642-fe0f","uc_match":"1f64e-2642-fe0f","uc_greedy":"1f64e-2642","shortnames":[],"category":"people"},":man_raising_hand:":{"uc_base":"1f64b-2642","uc_output":"1f64b-200d-2642-fe0f","uc_match":"1f64b-2642-fe0f","uc_greedy":"1f64b-2642","shortnames":[],"category":"people"},":man_rowing_boat:":{"uc_base":"1f6a3-2642","uc_output":"1f6a3-200d-2642-fe0f","uc_match":"1f6a3-2642-fe0f","uc_greedy":"1f6a3-2642","shortnames":[],"category":"activity"},":man_running:":{"uc_base":"1f3c3-2642","uc_output":"1f3c3-200d-2642-fe0f","uc_match":"1f3c3-2642-fe0f","uc_greedy":"1f3c3-2642","shortnames":[],"category":"people"},":man_shrugging:":{"uc_base":"1f937-2642","uc_output":"1f937-200d-2642-fe0f","uc_match":"1f937-2642-fe0f","uc_greedy":"1f937-2642","shortnames":[],"category":"people"},":man_surfing:":{"uc_base":"1f3c4-2642","uc_output":"1f3c4-200d-2642-fe0f","uc_match":"1f3c4-2642-fe0f","uc_greedy":"1f3c4-2642","shortnames":[],"category":"activity"},":man_swimming:":{"uc_base":"1f3ca-2642","uc_output":"1f3ca-200d-2642-fe0f","uc_match":"1f3ca-2642-fe0f","uc_greedy":"1f3ca-2642","shortnames":[],"category":"activity"},":man_tipping_hand:":{"uc_base":"1f481-2642","uc_output":"1f481-200d-2642-fe0f","uc_match":"1f481-2642-fe0f","uc_greedy":"1f481-2642","shortnames":[],"category":"people"},":man_vampire:":{"uc_base":"1f9db-2642","uc_output":"1f9db-200d-2642-fe0f","uc_match":"1f9db-2642-fe0f","uc_greedy":"1f9db-2642","shortnames":[],"category":"people"},":man_walking:":{"uc_base":"1f6b6-2642","uc_output":"1f6b6-200d-2642-fe0f","uc_match":"1f6b6-2642-fe0f","uc_greedy":"1f6b6-2642","shortnames":[],"category":"people"},":man_wearing_turban:":{"uc_base":"1f473-2642","uc_output":"1f473-200d-2642-fe0f","uc_match":"1f473-2642-fe0f","uc_greedy":"1f473-2642","shortnames":[],"category":"people"},":man_zombie:":{"uc_base":"1f9df-2642","uc_output":"1f9df-200d-2642-fe0f","uc_match":"1f9df-2642-fe0f","uc_greedy":"1f9df-2642","shortnames":[],"category":"people"},":men_with_bunny_ears_partying:":{"uc_base":"1f46f-2642","uc_output":"1f46f-200d-2642-fe0f","uc_match":"1f46f-2642-fe0f","uc_greedy":"1f46f-2642","shortnames":[],"category":"people"},":men_wrestling:":{"uc_base":"1f93c-2642","uc_output":"1f93c-200d-2642-fe0f","uc_match":"1f93c-2642-fe0f","uc_greedy":"1f93c-2642","shortnames":[],"category":"activity"},":mermaid:":{"uc_base":"1f9dc-2640","uc_output":"1f9dc-200d-2640-fe0f","uc_match":"1f9dc-2640-fe0f","uc_greedy":"1f9dc-2640","shortnames":[],"category":"people"},":merman:":{"uc_base":"1f9dc-2642","uc_output":"1f9dc-200d-2642-fe0f","uc_match":"1f9dc-2642-fe0f","uc_greedy":"1f9dc-2642","shortnames":[],"category":"people"},":woman_biking:":{"uc_base":"1f6b4-2640","uc_output":"1f6b4-200d-2640-fe0f","uc_match":"1f6b4-2640-fe0f","uc_greedy":"1f6b4-2640","shortnames":[],"category":"activity"},":woman_bowing:":{"uc_base":"1f647-2640","uc_output":"1f647-200d-2640-fe0f","uc_match":"1f647-2640-fe0f","uc_greedy":"1f647-2640","shortnames":[],"category":"people"},":woman_cartwheeling:":{"uc_base":"1f938-2640","uc_output":"1f938-200d-2640-fe0f","uc_match":"1f938-2640-fe0f","uc_greedy":"1f938-2640","shortnames":[],"category":"activity"},":woman_climbing:":{"uc_base":"1f9d7-2640","uc_output":"1f9d7-200d-2640-fe0f","uc_match":"1f9d7-2640-fe0f","uc_greedy":"1f9d7-2640","shortnames":[],"category":"activity"},":woman_construction_worker:":{"uc_base":"1f477-2640","uc_output":"1f477-200d-2640-fe0f","uc_match":"1f477-2640-fe0f","uc_greedy":"1f477-2640","shortnames":[],"category":"people"},":woman_elf:":{"uc_base":"1f9dd-2640","uc_output":"1f9dd-200d-2640-fe0f","uc_match":"1f9dd-2640-fe0f","uc_greedy":"1f9dd-2640","shortnames":[],"category":"people"},":woman_facepalming:":{"uc_base":"1f926-2640","uc_output":"1f926-200d-2640-fe0f","uc_match":"1f926-2640-fe0f","uc_greedy":"1f926-2640","shortnames":[],"category":"people"},":woman_fairy:":{"uc_base":"1f9da-2640","uc_output":"1f9da-200d-2640-fe0f","uc_match":"1f9da-2640-fe0f","uc_greedy":"1f9da-2640","shortnames":[],"category":"people"},":woman_frowning:":{"uc_base":"1f64d-2640","uc_output":"1f64d-200d-2640-fe0f","uc_match":"1f64d-2640-fe0f","uc_greedy":"1f64d-2640","shortnames":[],"category":"people"},":woman_genie:":{"uc_base":"1f9de-2640","uc_output":"1f9de-200d-2640-fe0f","uc_match":"1f9de-2640-fe0f","uc_greedy":"1f9de-2640","shortnames":[],"category":"people"},":woman_gesturing_no:":{"uc_base":"1f645-2640","uc_output":"1f645-200d-2640-fe0f","uc_match":"1f645-2640-fe0f","uc_greedy":"1f645-2640","shortnames":[],"category":"people"},":woman_gesturing_ok:":{"uc_base":"1f646-2640","uc_output":"1f646-200d-2640-fe0f","uc_match":"1f646-2640-fe0f","uc_greedy":"1f646-2640","shortnames":[],"category":"people"},":woman_getting_face_massage:":{"uc_base":"1f486-2640","uc_output":"1f486-200d-2640-fe0f","uc_match":"1f486-2640-fe0f","uc_greedy":"1f486-2640","shortnames":[],"category":"people"},":woman_getting_haircut:":{"uc_base":"1f487-2640","uc_output":"1f487-200d-2640-fe0f","uc_match":"1f487-2640-fe0f","uc_greedy":"1f487-2640","shortnames":[],"category":"people"},":woman_guard:":{"uc_base":"1f482-2640","uc_output":"1f482-200d-2640-fe0f","uc_match":"1f482-2640-fe0f","uc_greedy":"1f482-2640","shortnames":[],"category":"people"},":woman_health_worker:":{"uc_base":"1f469-2695","uc_output":"1f469-200d-2695-fe0f","uc_match":"1f469-2695-fe0f","uc_greedy":"1f469-2695","shortnames":[],"category":"people"},":woman_in_lotus_position:":{"uc_base":"1f9d8-2640","uc_output":"1f9d8-200d-2640-fe0f","uc_match":"1f9d8-2640-fe0f","uc_greedy":"1f9d8-2640","shortnames":[],"category":"activity"},":woman_in_steamy_room:":{"uc_base":"1f9d6-2640","uc_output":"1f9d6-200d-2640-fe0f","uc_match":"1f9d6-2640-fe0f","uc_greedy":"1f9d6-2640","shortnames":[],"category":"activity"},":woman_judge:":{"uc_base":"1f469-2696","uc_output":"1f469-200d-2696-fe0f","uc_match":"1f469-2696-fe0f","uc_greedy":"1f469-2696","shortnames":[],"category":"people"},":woman_juggling:":{"uc_base":"1f939-2640","uc_output":"1f939-200d-2640-fe0f","uc_match":"1f939-2640-fe0f","uc_greedy":"1f939-2640","shortnames":[],"category":"activity"},":woman_mage:":{"uc_base":"1f9d9-2640","uc_output":"1f9d9-200d-2640-fe0f","uc_match":"1f9d9-2640-fe0f","uc_greedy":"1f9d9-2640","shortnames":[],"category":"people"},":woman_mountain_biking:":{"uc_base":"1f6b5-2640","uc_output":"1f6b5-200d-2640-fe0f","uc_match":"1f6b5-2640-fe0f","uc_greedy":"1f6b5-2640","shortnames":[],"category":"activity"},":woman_pilot:":{"uc_base":"1f469-2708","uc_output":"1f469-200d-2708-fe0f","uc_match":"1f469-2708-fe0f","uc_greedy":"1f469-2708","shortnames":[],"category":"people"},":woman_playing_handball:":{"uc_base":"1f93e-2640","uc_output":"1f93e-200d-2640-fe0f","uc_match":"1f93e-2640-fe0f","uc_greedy":"1f93e-2640","shortnames":[],"category":"activity"},":woman_playing_water_polo:":{"uc_base":"1f93d-2640","uc_output":"1f93d-200d-2640-fe0f","uc_match":"1f93d-2640-fe0f","uc_greedy":"1f93d-2640","shortnames":[],"category":"activity"},":woman_police_officer:":{"uc_base":"1f46e-2640","uc_output":"1f46e-200d-2640-fe0f","uc_match":"1f46e-2640-fe0f","uc_greedy":"1f46e-2640","shortnames":[],"category":"people"},":woman_pouting:":{"uc_base":"1f64e-2640","uc_output":"1f64e-200d-2640-fe0f","uc_match":"1f64e-2640-fe0f","uc_greedy":"1f64e-2640","shortnames":[],"category":"people"},":woman_raising_hand:":{"uc_base":"1f64b-2640","uc_output":"1f64b-200d-2640-fe0f","uc_match":"1f64b-2640-fe0f","uc_greedy":"1f64b-2640","shortnames":[],"category":"people"},":woman_rowing_boat:":{"uc_base":"1f6a3-2640","uc_output":"1f6a3-200d-2640-fe0f","uc_match":"1f6a3-2640-fe0f","uc_greedy":"1f6a3-2640","shortnames":[],"category":"activity"},":woman_running:":{"uc_base":"1f3c3-2640","uc_output":"1f3c3-200d-2640-fe0f","uc_match":"1f3c3-2640-fe0f","uc_greedy":"1f3c3-2640","shortnames":[],"category":"people"},":woman_shrugging:":{"uc_base":"1f937-2640","uc_output":"1f937-200d-2640-fe0f","uc_match":"1f937-2640-fe0f","uc_greedy":"1f937-2640","shortnames":[],"category":"people"},":woman_surfing:":{"uc_base":"1f3c4-2640","uc_output":"1f3c4-200d-2640-fe0f","uc_match":"1f3c4-2640-fe0f","uc_greedy":"1f3c4-2640","shortnames":[],"category":"activity"},":woman_swimming:":{"uc_base":"1f3ca-2640","uc_output":"1f3ca-200d-2640-fe0f","uc_match":"1f3ca-2640-fe0f","uc_greedy":"1f3ca-2640","shortnames":[],"category":"activity"},":woman_tipping_hand:":{"uc_base":"1f481-2640","uc_output":"1f481-200d-2640-fe0f","uc_match":"1f481-2640-fe0f","uc_greedy":"1f481-2640","shortnames":[],"category":"people"},":woman_vampire:":{"uc_base":"1f9db-2640","uc_output":"1f9db-200d-2640-fe0f","uc_match":"1f9db-2640-fe0f","uc_greedy":"1f9db-2640","shortnames":[],"category":"people"},":woman_walking:":{"uc_base":"1f6b6-2640","uc_output":"1f6b6-200d-2640-fe0f","uc_match":"1f6b6-2640-fe0f","uc_greedy":"1f6b6-2640","shortnames":[],"category":"people"},":woman_wearing_turban:":{"uc_base":"1f473-2640","uc_output":"1f473-200d-2640-fe0f","uc_match":"1f473-2640-fe0f","uc_greedy":"1f473-2640","shortnames":[],"category":"people"},":woman_zombie:":{"uc_base":"1f9df-2640","uc_output":"1f9df-200d-2640-fe0f","uc_match":"1f9df-2640-fe0f","uc_greedy":"1f9df-2640","shortnames":[],"category":"people"},":women_with_bunny_ears_partying:":{"uc_base":"1f46f-2640","uc_output":"1f46f-200d-2640-fe0f","uc_match":"1f46f-2640-fe0f","uc_greedy":"1f46f-2640","shortnames":[],"category":"people"},":women_wrestling:":{"uc_base":"1f93c-2640","uc_output":"1f93c-200d-2640-fe0f","uc_match":"1f93c-2640-fe0f","uc_greedy":"1f93c-2640","shortnames":[],"category":"activity"},":family_man_boy:":{"uc_base":"1f468-1f466","uc_output":"1f468-200d-1f466","uc_match":"1f468-1f466","uc_greedy":"1f468-1f466","shortnames":[],"category":"people"},":family_man_girl:":{"uc_base":"1f468-1f467","uc_output":"1f468-200d-1f467","uc_match":"1f468-1f467","uc_greedy":"1f468-1f467","shortnames":[],"category":"people"},":family_woman_boy:":{"uc_base":"1f469-1f466","uc_output":"1f469-200d-1f466","uc_match":"1f469-1f466","uc_greedy":"1f469-1f466","shortnames":[],"category":"people"},":family_woman_girl:":{"uc_base":"1f469-1f467","uc_output":"1f469-200d-1f467","uc_match":"1f469-1f467","uc_greedy":"1f469-1f467","shortnames":[],"category":"people"},":man_artist:":{"uc_base":"1f468-1f3a8","uc_output":"1f468-200d-1f3a8","uc_match":"1f468-1f3a8","uc_greedy":"1f468-1f3a8","shortnames":[],"category":"people"},":man_astronaut:":{"uc_base":"1f468-1f680","uc_output":"1f468-200d-1f680","uc_match":"1f468-1f680","uc_greedy":"1f468-1f680","shortnames":[],"category":"people"},":man_cook:":{"uc_base":"1f468-1f373","uc_output":"1f468-200d-1f373","uc_match":"1f468-1f373","uc_greedy":"1f468-1f373","shortnames":[],"category":"people"},":man_factory_worker:":{"uc_base":"1f468-1f3ed","uc_output":"1f468-200d-1f3ed","uc_match":"1f468-1f3ed","uc_greedy":"1f468-1f3ed","shortnames":[],"category":"people"},":man_farmer:":{"uc_base":"1f468-1f33e","uc_output":"1f468-200d-1f33e","uc_match":"1f468-1f33e","uc_greedy":"1f468-1f33e","shortnames":[],"category":"people"},":man_firefighter:":{"uc_base":"1f468-1f692","uc_output":"1f468-200d-1f692","uc_match":"1f468-1f692","uc_greedy":"1f468-1f692","shortnames":[],"category":"people"},":man_mechanic:":{"uc_base":"1f468-1f527","uc_output":"1f468-200d-1f527","uc_match":"1f468-1f527","uc_greedy":"1f468-1f527","shortnames":[],"category":"people"},":man_office_worker:":{"uc_base":"1f468-1f4bc","uc_output":"1f468-200d-1f4bc","uc_match":"1f468-1f4bc","uc_greedy":"1f468-1f4bc","shortnames":[],"category":"people"},":man_scientist:":{"uc_base":"1f468-1f52c","uc_output":"1f468-200d-1f52c","uc_match":"1f468-1f52c","uc_greedy":"1f468-1f52c","shortnames":[],"category":"people"},":man_singer:":{"uc_base":"1f468-1f3a4","uc_output":"1f468-200d-1f3a4","uc_match":"1f468-1f3a4","uc_greedy":"1f468-1f3a4","shortnames":[],"category":"people"},":man_student:":{"uc_base":"1f468-1f393","uc_output":"1f468-200d-1f393","uc_match":"1f468-1f393","uc_greedy":"1f468-1f393","shortnames":[],"category":"people"},":man_teacher:":{"uc_base":"1f468-1f3eb","uc_output":"1f468-200d-1f3eb","uc_match":"1f468-1f3eb","uc_greedy":"1f468-1f3eb","shortnames":[],"category":"people"},":man_technologist:":{"uc_base":"1f468-1f4bb","uc_output":"1f468-200d-1f4bb","uc_match":"1f468-1f4bb","uc_greedy":"1f468-1f4bb","shortnames":[],"category":"people"},":woman_artist:":{"uc_base":"1f469-1f3a8","uc_output":"1f469-200d-1f3a8","uc_match":"1f469-1f3a8","uc_greedy":"1f469-1f3a8","shortnames":[],"category":"people"},":woman_astronaut:":{"uc_base":"1f469-1f680","uc_output":"1f469-200d-1f680","uc_match":"1f469-1f680","uc_greedy":"1f469-1f680","shortnames":[],"category":"people"},":woman_cook:":{"uc_base":"1f469-1f373","uc_output":"1f469-200d-1f373","uc_match":"1f469-1f373","uc_greedy":"1f469-1f373","shortnames":[],"category":"people"},":woman_factory_worker:":{"uc_base":"1f469-1f3ed","uc_output":"1f469-200d-1f3ed","uc_match":"1f469-1f3ed","uc_greedy":"1f469-1f3ed","shortnames":[],"category":"people"},":woman_farmer:":{"uc_base":"1f469-1f33e","uc_output":"1f469-200d-1f33e","uc_match":"1f469-1f33e","uc_greedy":"1f469-1f33e","shortnames":[],"category":"people"},":woman_firefighter:":{"uc_base":"1f469-1f692","uc_output":"1f469-200d-1f692","uc_match":"1f469-1f692","uc_greedy":"1f469-1f692","shortnames":[],"category":"people"},":woman_mechanic:":{"uc_base":"1f469-1f527","uc_output":"1f469-200d-1f527","uc_match":"1f469-1f527","uc_greedy":"1f469-1f527","shortnames":[],"category":"people"},":woman_office_worker:":{"uc_base":"1f469-1f4bc","uc_output":"1f469-200d-1f4bc","uc_match":"1f469-1f4bc","uc_greedy":"1f469-1f4bc","shortnames":[],"category":"people"},":woman_scientist:":{"uc_base":"1f469-1f52c","uc_output":"1f469-200d-1f52c","uc_match":"1f469-1f52c","uc_greedy":"1f469-1f52c","shortnames":[],"category":"people"},":woman_singer:":{"uc_base":"1f469-1f3a4","uc_output":"1f469-200d-1f3a4","uc_match":"1f469-1f3a4","uc_greedy":"1f469-1f3a4","shortnames":[],"category":"people"},":woman_student:":{"uc_base":"1f469-1f393","uc_output":"1f469-200d-1f393","uc_match":"1f469-1f393","uc_greedy":"1f469-1f393","shortnames":[],"category":"people"},":woman_teacher:":{"uc_base":"1f469-1f3eb","uc_output":"1f469-200d-1f3eb","uc_match":"1f469-1f3eb","uc_greedy":"1f469-1f3eb","shortnames":[],"category":"people"},":woman_technologist:":{"uc_base":"1f469-1f4bb","uc_output":"1f469-200d-1f4bb","uc_match":"1f469-1f4bb","uc_greedy":"1f469-1f4bb","shortnames":[],"category":"people"},":asterisk:":{"uc_base":"002a-20e3","uc_output":"002a-fe0f-20e3","uc_match":"002a-20e3","uc_greedy":"002a-20e3","shortnames":[":keycap_asterisk:"],"category":"symbols"},":eight:":{"uc_base":"0038-20e3","uc_output":"0038-fe0f-20e3","uc_match":"0038-20e3","uc_greedy":"0038-20e3","shortnames":[],"category":"symbols"},":five:":{"uc_base":"0035-20e3","uc_output":"0035-fe0f-20e3","uc_match":"0035-20e3","uc_greedy":"0035-20e3","shortnames":[],"category":"symbols"},":four:":{"uc_base":"0034-20e3","uc_output":"0034-fe0f-20e3","uc_match":"0034-20e3","uc_greedy":"0034-20e3","shortnames":[],"category":"symbols"},":hash:":{"uc_base":"0023-20e3","uc_output":"0023-fe0f-20e3","uc_match":"0023-20e3","uc_greedy":"0023-20e3","shortnames":[],"category":"symbols"},":nine:":{"uc_base":"0039-20e3","uc_output":"0039-fe0f-20e3","uc_match":"0039-20e3","uc_greedy":"0039-20e3","shortnames":[],"category":"symbols"},":one:":{"uc_base":"0031-20e3","uc_output":"0031-fe0f-20e3","uc_match":"0031-20e3","uc_greedy":"0031-20e3","shortnames":[],"category":"symbols"},":seven:":{"uc_base":"0037-20e3","uc_output":"0037-fe0f-20e3","uc_match":"0037-20e3","uc_greedy":"0037-20e3","shortnames":[],"category":"symbols"},":six:":{"uc_base":"0036-20e3","uc_output":"0036-fe0f-20e3","uc_match":"0036-20e3","uc_greedy":"0036-20e3","shortnames":[],"category":"symbols"},":three:":{"uc_base":"0033-20e3","uc_output":"0033-fe0f-20e3","uc_match":"0033-20e3","uc_greedy":"0033-20e3","shortnames":[],"category":"symbols"},":two:":{"uc_base":"0032-20e3","uc_output":"0032-fe0f-20e3","uc_match":"0032-20e3","uc_greedy":"0032-20e3","shortnames":[],"category":"symbols"},":zero:":{"uc_base":"0030-20e3","uc_output":"0030-fe0f-20e3","uc_match":"0030-20e3","uc_greedy":"0030-20e3","shortnames":[],"category":"symbols"},":adult_tone1:":{"uc_base":"1f9d1-1f3fb","uc_output":"1f9d1-1f3fb","uc_match":"1f9d1-1f3fb","uc_greedy":"1f9d1-1f3fb","shortnames":[":adult_light_skin_tone:"],"category":"people"},":adult_tone2:":{"uc_base":"1f9d1-1f3fc","uc_output":"1f9d1-1f3fc","uc_match":"1f9d1-1f3fc","uc_greedy":"1f9d1-1f3fc","shortnames":[":adult_medium_light_skin_tone:"],"category":"people"},":adult_tone3:":{"uc_base":"1f9d1-1f3fd","uc_output":"1f9d1-1f3fd","uc_match":"1f9d1-1f3fd","uc_greedy":"1f9d1-1f3fd","shortnames":[":adult_medium_skin_tone:"],"category":"people"},":adult_tone4:":{"uc_base":"1f9d1-1f3fe","uc_output":"1f9d1-1f3fe","uc_match":"1f9d1-1f3fe","uc_greedy":"1f9d1-1f3fe","shortnames":[":adult_medium_dark_skin_tone:"],"category":"people"},":adult_tone5:":{"uc_base":"1f9d1-1f3ff","uc_output":"1f9d1-1f3ff","uc_match":"1f9d1-1f3ff","uc_greedy":"1f9d1-1f3ff","shortnames":[":adult_dark_skin_tone:"],"category":"people"},":angel_tone1:":{"uc_base":"1f47c-1f3fb","uc_output":"1f47c-1f3fb","uc_match":"1f47c-1f3fb","uc_greedy":"1f47c-1f3fb","shortnames":[],"category":"people"},":angel_tone2:":{"uc_base":"1f47c-1f3fc","uc_output":"1f47c-1f3fc","uc_match":"1f47c-1f3fc","uc_greedy":"1f47c-1f3fc","shortnames":[],"category":"people"},":angel_tone3:":{"uc_base":"1f47c-1f3fd","uc_output":"1f47c-1f3fd","uc_match":"1f47c-1f3fd","uc_greedy":"1f47c-1f3fd","shortnames":[],"category":"people"},":angel_tone4:":{"uc_base":"1f47c-1f3fe","uc_output":"1f47c-1f3fe","uc_match":"1f47c-1f3fe","uc_greedy":"1f47c-1f3fe","shortnames":[],"category":"people"},":angel_tone5:":{"uc_base":"1f47c-1f3ff","uc_output":"1f47c-1f3ff","uc_match":"1f47c-1f3ff","uc_greedy":"1f47c-1f3ff","shortnames":[],"category":"people"},":baby_tone1:":{"uc_base":"1f476-1f3fb","uc_output":"1f476-1f3fb","uc_match":"1f476-1f3fb","uc_greedy":"1f476-1f3fb","shortnames":[],"category":"people"},":baby_tone2:":{"uc_base":"1f476-1f3fc","uc_output":"1f476-1f3fc","uc_match":"1f476-1f3fc","uc_greedy":"1f476-1f3fc","shortnames":[],"category":"people"},":baby_tone3:":{"uc_base":"1f476-1f3fd","uc_output":"1f476-1f3fd","uc_match":"1f476-1f3fd","uc_greedy":"1f476-1f3fd","shortnames":[],"category":"people"},":baby_tone4:":{"uc_base":"1f476-1f3fe","uc_output":"1f476-1f3fe","uc_match":"1f476-1f3fe","uc_greedy":"1f476-1f3fe","shortnames":[],"category":"people"},":baby_tone5:":{"uc_base":"1f476-1f3ff","uc_output":"1f476-1f3ff","uc_match":"1f476-1f3ff","uc_greedy":"1f476-1f3ff","shortnames":[],"category":"people"},":bath_tone1:":{"uc_base":"1f6c0-1f3fb","uc_output":"1f6c0-1f3fb","uc_match":"1f6c0-1f3fb","uc_greedy":"1f6c0-1f3fb","shortnames":[],"category":"objects"},":bath_tone2:":{"uc_base":"1f6c0-1f3fc","uc_output":"1f6c0-1f3fc","uc_match":"1f6c0-1f3fc","uc_greedy":"1f6c0-1f3fc","shortnames":[],"category":"objects"},":bath_tone3:":{"uc_base":"1f6c0-1f3fd","uc_output":"1f6c0-1f3fd","uc_match":"1f6c0-1f3fd","uc_greedy":"1f6c0-1f3fd","shortnames":[],"category":"objects"},":bath_tone4:":{"uc_base":"1f6c0-1f3fe","uc_output":"1f6c0-1f3fe","uc_match":"1f6c0-1f3fe","uc_greedy":"1f6c0-1f3fe","shortnames":[],"category":"objects"},":bath_tone5:":{"uc_base":"1f6c0-1f3ff","uc_output":"1f6c0-1f3ff","uc_match":"1f6c0-1f3ff","uc_greedy":"1f6c0-1f3ff","shortnames":[],"category":"objects"},":bearded_person_tone1:":{"uc_base":"1f9d4-1f3fb","uc_output":"1f9d4-1f3fb","uc_match":"1f9d4-1f3fb","uc_greedy":"1f9d4-1f3fb","shortnames":[":bearded_person_light_skin_tone:"],"category":"people"},":bearded_person_tone2:":{"uc_base":"1f9d4-1f3fc","uc_output":"1f9d4-1f3fc","uc_match":"1f9d4-1f3fc","uc_greedy":"1f9d4-1f3fc","shortnames":[":bearded_person_medium_light_skin_tone:"],"category":"people"},":bearded_person_tone3:":{"uc_base":"1f9d4-1f3fd","uc_output":"1f9d4-1f3fd","uc_match":"1f9d4-1f3fd","uc_greedy":"1f9d4-1f3fd","shortnames":[":bearded_person_medium_skin_tone:"],"category":"people"},":bearded_person_tone4:":{"uc_base":"1f9d4-1f3fe","uc_output":"1f9d4-1f3fe","uc_match":"1f9d4-1f3fe","uc_greedy":"1f9d4-1f3fe","shortnames":[":bearded_person_medium_dark_skin_tone:"],"category":"people"},":bearded_person_tone5:":{"uc_base":"1f9d4-1f3ff","uc_output":"1f9d4-1f3ff","uc_match":"1f9d4-1f3ff","uc_greedy":"1f9d4-1f3ff","shortnames":[":bearded_person_dark_skin_tone:"],"category":"people"},":blond_haired_person_tone1:":{"uc_base":"1f471-1f3fb","uc_output":"1f471-1f3fb","uc_match":"1f471-1f3fb","uc_greedy":"1f471-1f3fb","shortnames":[":person_with_blond_hair_tone1:"],"category":"people"},":blond_haired_person_tone2:":{"uc_base":"1f471-1f3fc","uc_output":"1f471-1f3fc","uc_match":"1f471-1f3fc","uc_greedy":"1f471-1f3fc","shortnames":[":person_with_blond_hair_tone2:"],"category":"people"},":blond_haired_person_tone3:":{"uc_base":"1f471-1f3fd","uc_output":"1f471-1f3fd","uc_match":"1f471-1f3fd","uc_greedy":"1f471-1f3fd","shortnames":[":person_with_blond_hair_tone3:"],"category":"people"},":blond_haired_person_tone4:":{"uc_base":"1f471-1f3fe","uc_output":"1f471-1f3fe","uc_match":"1f471-1f3fe","uc_greedy":"1f471-1f3fe","shortnames":[":person_with_blond_hair_tone4:"],"category":"people"},":blond_haired_person_tone5:":{"uc_base":"1f471-1f3ff","uc_output":"1f471-1f3ff","uc_match":"1f471-1f3ff","uc_greedy":"1f471-1f3ff","shortnames":[":person_with_blond_hair_tone5:"],"category":"people"},":boy_tone1:":{"uc_base":"1f466-1f3fb","uc_output":"1f466-1f3fb","uc_match":"1f466-1f3fb","uc_greedy":"1f466-1f3fb","shortnames":[],"category":"people"},":boy_tone2:":{"uc_base":"1f466-1f3fc","uc_output":"1f466-1f3fc","uc_match":"1f466-1f3fc","uc_greedy":"1f466-1f3fc","shortnames":[],"category":"people"},":boy_tone3:":{"uc_base":"1f466-1f3fd","uc_output":"1f466-1f3fd","uc_match":"1f466-1f3fd","uc_greedy":"1f466-1f3fd","shortnames":[],"category":"people"},":boy_tone4:":{"uc_base":"1f466-1f3fe","uc_output":"1f466-1f3fe","uc_match":"1f466-1f3fe","uc_greedy":"1f466-1f3fe","shortnames":[],"category":"people"},":boy_tone5:":{"uc_base":"1f466-1f3ff","uc_output":"1f466-1f3ff","uc_match":"1f466-1f3ff","uc_greedy":"1f466-1f3ff","shortnames":[],"category":"people"},":breast_feeding_tone1:":{"uc_base":"1f931-1f3fb","uc_output":"1f931-1f3fb","uc_match":"1f931-1f3fb","uc_greedy":"1f931-1f3fb","shortnames":[":breast_feeding_light_skin_tone:"],"category":"activity"},":breast_feeding_tone2:":{"uc_base":"1f931-1f3fc","uc_output":"1f931-1f3fc","uc_match":"1f931-1f3fc","uc_greedy":"1f931-1f3fc","shortnames":[":breast_feeding_medium_light_skin_tone:"],"category":"activity"},":breast_feeding_tone3:":{"uc_base":"1f931-1f3fd","uc_output":"1f931-1f3fd","uc_match":"1f931-1f3fd","uc_greedy":"1f931-1f3fd","shortnames":[":breast_feeding_medium_skin_tone:"],"category":"activity"},":breast_feeding_tone4:":{"uc_base":"1f931-1f3fe","uc_output":"1f931-1f3fe","uc_match":"1f931-1f3fe","uc_greedy":"1f931-1f3fe","shortnames":[":breast_feeding_medium_dark_skin_tone:"],"category":"activity"},":breast_feeding_tone5:":{"uc_base":"1f931-1f3ff","uc_output":"1f931-1f3ff","uc_match":"1f931-1f3ff","uc_greedy":"1f931-1f3ff","shortnames":[":breast_feeding_dark_skin_tone:"],"category":"activity"},":bride_with_veil_tone1:":{"uc_base":"1f470-1f3fb","uc_output":"1f470-1f3fb","uc_match":"1f470-1f3fb","uc_greedy":"1f470-1f3fb","shortnames":[],"category":"people"},":bride_with_veil_tone2:":{"uc_base":"1f470-1f3fc","uc_output":"1f470-1f3fc","uc_match":"1f470-1f3fc","uc_greedy":"1f470-1f3fc","shortnames":[],"category":"people"},":bride_with_veil_tone3:":{"uc_base":"1f470-1f3fd","uc_output":"1f470-1f3fd","uc_match":"1f470-1f3fd","uc_greedy":"1f470-1f3fd","shortnames":[],"category":"people"},":bride_with_veil_tone4:":{"uc_base":"1f470-1f3fe","uc_output":"1f470-1f3fe","uc_match":"1f470-1f3fe","uc_greedy":"1f470-1f3fe","shortnames":[],"category":"people"},":bride_with_veil_tone5:":{"uc_base":"1f470-1f3ff","uc_output":"1f470-1f3ff","uc_match":"1f470-1f3ff","uc_greedy":"1f470-1f3ff","shortnames":[],"category":"people"},":call_me_tone1:":{"uc_base":"1f919-1f3fb","uc_output":"1f919-1f3fb","uc_match":"1f919-1f3fb","uc_greedy":"1f919-1f3fb","shortnames":[":call_me_hand_tone1:"],"category":"people"},":call_me_tone2:":{"uc_base":"1f919-1f3fc","uc_output":"1f919-1f3fc","uc_match":"1f919-1f3fc","uc_greedy":"1f919-1f3fc","shortnames":[":call_me_hand_tone2:"],"category":"people"},":call_me_tone3:":{"uc_base":"1f919-1f3fd","uc_output":"1f919-1f3fd","uc_match":"1f919-1f3fd","uc_greedy":"1f919-1f3fd","shortnames":[":call_me_hand_tone3:"],"category":"people"},":call_me_tone4:":{"uc_base":"1f919-1f3fe","uc_output":"1f919-1f3fe","uc_match":"1f919-1f3fe","uc_greedy":"1f919-1f3fe","shortnames":[":call_me_hand_tone4:"],"category":"people"},":call_me_tone5:":{"uc_base":"1f919-1f3ff","uc_output":"1f919-1f3ff","uc_match":"1f919-1f3ff","uc_greedy":"1f919-1f3ff","shortnames":[":call_me_hand_tone5:"],"category":"people"},":child_tone1:":{"uc_base":"1f9d2-1f3fb","uc_output":"1f9d2-1f3fb","uc_match":"1f9d2-1f3fb","uc_greedy":"1f9d2-1f3fb","shortnames":[":child_light_skin_tone:"],"category":"people"},":child_tone2:":{"uc_base":"1f9d2-1f3fc","uc_output":"1f9d2-1f3fc","uc_match":"1f9d2-1f3fc","uc_greedy":"1f9d2-1f3fc","shortnames":[":child_medium_light_skin_tone:"],"category":"people"},":child_tone3:":{"uc_base":"1f9d2-1f3fd","uc_output":"1f9d2-1f3fd","uc_match":"1f9d2-1f3fd","uc_greedy":"1f9d2-1f3fd","shortnames":[":child_medium_skin_tone:"],"category":"people"},":child_tone4:":{"uc_base":"1f9d2-1f3fe","uc_output":"1f9d2-1f3fe","uc_match":"1f9d2-1f3fe","uc_greedy":"1f9d2-1f3fe","shortnames":[":child_medium_dark_skin_tone:"],"category":"people"},":child_tone5:":{"uc_base":"1f9d2-1f3ff","uc_output":"1f9d2-1f3ff","uc_match":"1f9d2-1f3ff","uc_greedy":"1f9d2-1f3ff","shortnames":[":child_dark_skin_tone:"],"category":"people"},":clap_tone1:":{"uc_base":"1f44f-1f3fb","uc_output":"1f44f-1f3fb","uc_match":"1f44f-1f3fb","uc_greedy":"1f44f-1f3fb","shortnames":[],"category":"people"},":clap_tone2:":{"uc_base":"1f44f-1f3fc","uc_output":"1f44f-1f3fc","uc_match":"1f44f-1f3fc","uc_greedy":"1f44f-1f3fc","shortnames":[],"category":"people"},":clap_tone3:":{"uc_base":"1f44f-1f3fd","uc_output":"1f44f-1f3fd","uc_match":"1f44f-1f3fd","uc_greedy":"1f44f-1f3fd","shortnames":[],"category":"people"},":clap_tone4:":{"uc_base":"1f44f-1f3fe","uc_output":"1f44f-1f3fe","uc_match":"1f44f-1f3fe","uc_greedy":"1f44f-1f3fe","shortnames":[],"category":"people"},":clap_tone5:":{"uc_base":"1f44f-1f3ff","uc_output":"1f44f-1f3ff","uc_match":"1f44f-1f3ff","uc_greedy":"1f44f-1f3ff","shortnames":[],"category":"people"},":construction_worker_tone1:":{"uc_base":"1f477-1f3fb","uc_output":"1f477-1f3fb","uc_match":"1f477-1f3fb","uc_greedy":"1f477-1f3fb","shortnames":[],"category":"people"},":construction_worker_tone2:":{"uc_base":"1f477-1f3fc","uc_output":"1f477-1f3fc","uc_match":"1f477-1f3fc","uc_greedy":"1f477-1f3fc","shortnames":[],"category":"people"},":construction_worker_tone3:":{"uc_base":"1f477-1f3fd","uc_output":"1f477-1f3fd","uc_match":"1f477-1f3fd","uc_greedy":"1f477-1f3fd","shortnames":[],"category":"people"},":construction_worker_tone4:":{"uc_base":"1f477-1f3fe","uc_output":"1f477-1f3fe","uc_match":"1f477-1f3fe","uc_greedy":"1f477-1f3fe","shortnames":[],"category":"people"},":construction_worker_tone5:":{"uc_base":"1f477-1f3ff","uc_output":"1f477-1f3ff","uc_match":"1f477-1f3ff","uc_greedy":"1f477-1f3ff","shortnames":[],"category":"people"},":dancer_tone1:":{"uc_base":"1f483-1f3fb","uc_output":"1f483-1f3fb","uc_match":"1f483-1f3fb","uc_greedy":"1f483-1f3fb","shortnames":[],"category":"people"},":dancer_tone2:":{"uc_base":"1f483-1f3fc","uc_output":"1f483-1f3fc","uc_match":"1f483-1f3fc","uc_greedy":"1f483-1f3fc","shortnames":[],"category":"people"},":dancer_tone3:":{"uc_base":"1f483-1f3fd","uc_output":"1f483-1f3fd","uc_match":"1f483-1f3fd","uc_greedy":"1f483-1f3fd","shortnames":[],"category":"people"},":dancer_tone4:":{"uc_base":"1f483-1f3fe","uc_output":"1f483-1f3fe","uc_match":"1f483-1f3fe","uc_greedy":"1f483-1f3fe","shortnames":[],"category":"people"},":dancer_tone5:":{"uc_base":"1f483-1f3ff","uc_output":"1f483-1f3ff","uc_match":"1f483-1f3ff","uc_greedy":"1f483-1f3ff","shortnames":[],"category":"people"},":detective_tone1:":{"uc_base":"1f575-1f3fb","uc_output":"1f575-1f3fb","uc_match":"1f575-fe0f-1f3fb","uc_greedy":"1f575-fe0f-1f3fb","shortnames":[":spy_tone1:",":sleuth_or_spy_tone1:"],"category":"people"},":detective_tone2:":{"uc_base":"1f575-1f3fc","uc_output":"1f575-1f3fc","uc_match":"1f575-fe0f-1f3fc","uc_greedy":"1f575-fe0f-1f3fc","shortnames":[":spy_tone2:",":sleuth_or_spy_tone2:"],"category":"people"},":detective_tone3:":{"uc_base":"1f575-1f3fd","uc_output":"1f575-1f3fd","uc_match":"1f575-fe0f-1f3fd","uc_greedy":"1f575-fe0f-1f3fd","shortnames":[":spy_tone3:",":sleuth_or_spy_tone3:"],"category":"people"},":detective_tone4:":{"uc_base":"1f575-1f3fe","uc_output":"1f575-1f3fe","uc_match":"1f575-fe0f-1f3fe","uc_greedy":"1f575-fe0f-1f3fe","shortnames":[":spy_tone4:",":sleuth_or_spy_tone4:"],"category":"people"},":detective_tone5:":{"uc_base":"1f575-1f3ff","uc_output":"1f575-1f3ff","uc_match":"1f575-fe0f-1f3ff","uc_greedy":"1f575-fe0f-1f3ff","shortnames":[":spy_tone5:",":sleuth_or_spy_tone5:"],"category":"people"},":ear_tone1:":{"uc_base":"1f442-1f3fb","uc_output":"1f442-1f3fb","uc_match":"1f442-1f3fb","uc_greedy":"1f442-1f3fb","shortnames":[],"category":"people"},":ear_tone2:":{"uc_base":"1f442-1f3fc","uc_output":"1f442-1f3fc","uc_match":"1f442-1f3fc","uc_greedy":"1f442-1f3fc","shortnames":[],"category":"people"},":ear_tone3:":{"uc_base":"1f442-1f3fd","uc_output":"1f442-1f3fd","uc_match":"1f442-1f3fd","uc_greedy":"1f442-1f3fd","shortnames":[],"category":"people"},":ear_tone4:":{"uc_base":"1f442-1f3fe","uc_output":"1f442-1f3fe","uc_match":"1f442-1f3fe","uc_greedy":"1f442-1f3fe","shortnames":[],"category":"people"},":ear_tone5:":{"uc_base":"1f442-1f3ff","uc_output":"1f442-1f3ff","uc_match":"1f442-1f3ff","uc_greedy":"1f442-1f3ff","shortnames":[],"category":"people"},":elf_tone1:":{"uc_base":"1f9dd-1f3fb","uc_output":"1f9dd-1f3fb","uc_match":"1f9dd-1f3fb","uc_greedy":"1f9dd-1f3fb","shortnames":[":elf_light_skin_tone:"],"category":"people"},":elf_tone2:":{"uc_base":"1f9dd-1f3fc","uc_output":"1f9dd-1f3fc","uc_match":"1f9dd-1f3fc","uc_greedy":"1f9dd-1f3fc","shortnames":[":elf_medium_light_skin_tone:"],"category":"people"},":elf_tone3:":{"uc_base":"1f9dd-1f3fd","uc_output":"1f9dd-1f3fd","uc_match":"1f9dd-1f3fd","uc_greedy":"1f9dd-1f3fd","shortnames":[":elf_medium_skin_tone:"],"category":"people"},":elf_tone4:":{"uc_base":"1f9dd-1f3fe","uc_output":"1f9dd-1f3fe","uc_match":"1f9dd-1f3fe","uc_greedy":"1f9dd-1f3fe","shortnames":[":elf_medium_dark_skin_tone:"],"category":"people"},":elf_tone5:":{"uc_base":"1f9dd-1f3ff","uc_output":"1f9dd-1f3ff","uc_match":"1f9dd-1f3ff","uc_greedy":"1f9dd-1f3ff","shortnames":[":elf_dark_skin_tone:"],"category":"people"},":fairy_tone1:":{"uc_base":"1f9da-1f3fb","uc_output":"1f9da-1f3fb","uc_match":"1f9da-1f3fb","uc_greedy":"1f9da-1f3fb","shortnames":[":fairy_light_skin_tone:"],"category":"people"},":fairy_tone2:":{"uc_base":"1f9da-1f3fc","uc_output":"1f9da-1f3fc","uc_match":"1f9da-1f3fc","uc_greedy":"1f9da-1f3fc","shortnames":[":fairy_medium_light_skin_tone:"],"category":"people"},":fairy_tone3:":{"uc_base":"1f9da-1f3fd","uc_output":"1f9da-1f3fd","uc_match":"1f9da-1f3fd","uc_greedy":"1f9da-1f3fd","shortnames":[":fairy_medium_skin_tone:"],"category":"people"},":fairy_tone4:":{"uc_base":"1f9da-1f3fe","uc_output":"1f9da-1f3fe","uc_match":"1f9da-1f3fe","uc_greedy":"1f9da-1f3fe","shortnames":[":fairy_medium_dark_skin_tone:"],"category":"people"},":fairy_tone5:":{"uc_base":"1f9da-1f3ff","uc_output":"1f9da-1f3ff","uc_match":"1f9da-1f3ff","uc_greedy":"1f9da-1f3ff","shortnames":[":fairy_dark_skin_tone:"],"category":"people"},":fingers_crossed_tone1:":{"uc_base":"1f91e-1f3fb","uc_output":"1f91e-1f3fb","uc_match":"1f91e-1f3fb","uc_greedy":"1f91e-1f3fb","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone1:"],"category":"people"},":fingers_crossed_tone2:":{"uc_base":"1f91e-1f3fc","uc_output":"1f91e-1f3fc","uc_match":"1f91e-1f3fc","uc_greedy":"1f91e-1f3fc","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone2:"],"category":"people"},":fingers_crossed_tone3:":{"uc_base":"1f91e-1f3fd","uc_output":"1f91e-1f3fd","uc_match":"1f91e-1f3fd","uc_greedy":"1f91e-1f3fd","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone3:"],"category":"people"},":fingers_crossed_tone4:":{"uc_base":"1f91e-1f3fe","uc_output":"1f91e-1f3fe","uc_match":"1f91e-1f3fe","uc_greedy":"1f91e-1f3fe","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone4:"],"category":"people"},":fingers_crossed_tone5:":{"uc_base":"1f91e-1f3ff","uc_output":"1f91e-1f3ff","uc_match":"1f91e-1f3ff","uc_greedy":"1f91e-1f3ff","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone5:"],"category":"people"},":flag_ac:":{"uc_base":"1f1e6-1f1e8","uc_output":"1f1e6-1f1e8","uc_match":"1f1e6-1f1e8","uc_greedy":"1f1e6-1f1e8","shortnames":[":ac:"],"category":"flags"},":flag_ad:":{"uc_base":"1f1e6-1f1e9","uc_output":"1f1e6-1f1e9","uc_match":"1f1e6-1f1e9","uc_greedy":"1f1e6-1f1e9","shortnames":[":ad:"],"category":"flags"},":flag_ae:":{"uc_base":"1f1e6-1f1ea","uc_output":"1f1e6-1f1ea","uc_match":"1f1e6-1f1ea","uc_greedy":"1f1e6-1f1ea","shortnames":[":ae:"],"category":"flags"},":flag_af:":{"uc_base":"1f1e6-1f1eb","uc_output":"1f1e6-1f1eb","uc_match":"1f1e6-1f1eb","uc_greedy":"1f1e6-1f1eb","shortnames":[":af:"],"category":"flags"},":flag_ag:":{"uc_base":"1f1e6-1f1ec","uc_output":"1f1e6-1f1ec","uc_match":"1f1e6-1f1ec","uc_greedy":"1f1e6-1f1ec","shortnames":[":ag:"],"category":"flags"},":flag_ai:":{"uc_base":"1f1e6-1f1ee","uc_output":"1f1e6-1f1ee","uc_match":"1f1e6-1f1ee","uc_greedy":"1f1e6-1f1ee","shortnames":[":ai:"],"category":"flags"},":flag_al:":{"uc_base":"1f1e6-1f1f1","uc_output":"1f1e6-1f1f1","uc_match":"1f1e6-1f1f1","uc_greedy":"1f1e6-1f1f1","shortnames":[":al:"],"category":"flags"},":flag_am:":{"uc_base":"1f1e6-1f1f2","uc_output":"1f1e6-1f1f2","uc_match":"1f1e6-1f1f2","uc_greedy":"1f1e6-1f1f2","shortnames":[":am:"],"category":"flags"},":flag_ao:":{"uc_base":"1f1e6-1f1f4","uc_output":"1f1e6-1f1f4","uc_match":"1f1e6-1f1f4","uc_greedy":"1f1e6-1f1f4","shortnames":[":ao:"],"category":"flags"},":flag_aq:":{"uc_base":"1f1e6-1f1f6","uc_output":"1f1e6-1f1f6","uc_match":"1f1e6-1f1f6","uc_greedy":"1f1e6-1f1f6","shortnames":[":aq:"],"category":"flags"},":flag_ar:":{"uc_base":"1f1e6-1f1f7","uc_output":"1f1e6-1f1f7","uc_match":"1f1e6-1f1f7","uc_greedy":"1f1e6-1f1f7","shortnames":[":ar:"],"category":"flags"},":flag_as:":{"uc_base":"1f1e6-1f1f8","uc_output":"1f1e6-1f1f8","uc_match":"1f1e6-1f1f8","uc_greedy":"1f1e6-1f1f8","shortnames":[":as:"],"category":"flags"},":flag_at:":{"uc_base":"1f1e6-1f1f9","uc_output":"1f1e6-1f1f9","uc_match":"1f1e6-1f1f9","uc_greedy":"1f1e6-1f1f9","shortnames":[":at:"],"category":"flags"},":flag_au:":{"uc_base":"1f1e6-1f1fa","uc_output":"1f1e6-1f1fa","uc_match":"1f1e6-1f1fa","uc_greedy":"1f1e6-1f1fa","shortnames":[":au:"],"category":"flags"},":flag_aw:":{"uc_base":"1f1e6-1f1fc","uc_output":"1f1e6-1f1fc","uc_match":"1f1e6-1f1fc","uc_greedy":"1f1e6-1f1fc","shortnames":[":aw:"],"category":"flags"},":flag_ax:":{"uc_base":"1f1e6-1f1fd","uc_output":"1f1e6-1f1fd","uc_match":"1f1e6-1f1fd","uc_greedy":"1f1e6-1f1fd","shortnames":[":ax:"],"category":"flags"},":flag_az:":{"uc_base":"1f1e6-1f1ff","uc_output":"1f1e6-1f1ff","uc_match":"1f1e6-1f1ff","uc_greedy":"1f1e6-1f1ff","shortnames":[":az:"],"category":"flags"},":flag_ba:":{"uc_base":"1f1e7-1f1e6","uc_output":"1f1e7-1f1e6","uc_match":"1f1e7-1f1e6","uc_greedy":"1f1e7-1f1e6","shortnames":[":ba:"],"category":"flags"},":flag_bb:":{"uc_base":"1f1e7-1f1e7","uc_output":"1f1e7-1f1e7","uc_match":"1f1e7-1f1e7","uc_greedy":"1f1e7-1f1e7","shortnames":[":bb:"],"category":"flags"},":flag_bd:":{"uc_base":"1f1e7-1f1e9","uc_output":"1f1e7-1f1e9","uc_match":"1f1e7-1f1e9","uc_greedy":"1f1e7-1f1e9","shortnames":[":bd:"],"category":"flags"},":flag_be:":{"uc_base":"1f1e7-1f1ea","uc_output":"1f1e7-1f1ea","uc_match":"1f1e7-1f1ea","uc_greedy":"1f1e7-1f1ea","shortnames":[":be:"],"category":"flags"},":flag_bf:":{"uc_base":"1f1e7-1f1eb","uc_output":"1f1e7-1f1eb","uc_match":"1f1e7-1f1eb","uc_greedy":"1f1e7-1f1eb","shortnames":[":bf:"],"category":"flags"},":flag_bg:":{"uc_base":"1f1e7-1f1ec","uc_output":"1f1e7-1f1ec","uc_match":"1f1e7-1f1ec","uc_greedy":"1f1e7-1f1ec","shortnames":[":bg:"],"category":"flags"},":flag_bh:":{"uc_base":"1f1e7-1f1ed","uc_output":"1f1e7-1f1ed","uc_match":"1f1e7-1f1ed","uc_greedy":"1f1e7-1f1ed","shortnames":[":bh:"],"category":"flags"},":flag_bi:":{"uc_base":"1f1e7-1f1ee","uc_output":"1f1e7-1f1ee","uc_match":"1f1e7-1f1ee","uc_greedy":"1f1e7-1f1ee","shortnames":[":bi:"],"category":"flags"},":flag_bj:":{"uc_base":"1f1e7-1f1ef","uc_output":"1f1e7-1f1ef","uc_match":"1f1e7-1f1ef","uc_greedy":"1f1e7-1f1ef","shortnames":[":bj:"],"category":"flags"},":flag_bl:":{"uc_base":"1f1e7-1f1f1","uc_output":"1f1e7-1f1f1","uc_match":"1f1e7-1f1f1","uc_greedy":"1f1e7-1f1f1","shortnames":[":bl:"],"category":"flags"},":flag_bm:":{"uc_base":"1f1e7-1f1f2","uc_output":"1f1e7-1f1f2","uc_match":"1f1e7-1f1f2","uc_greedy":"1f1e7-1f1f2","shortnames":[":bm:"],"category":"flags"},":flag_bn:":{"uc_base":"1f1e7-1f1f3","uc_output":"1f1e7-1f1f3","uc_match":"1f1e7-1f1f3","uc_greedy":"1f1e7-1f1f3","shortnames":[":bn:"],"category":"flags"},":flag_bo:":{"uc_base":"1f1e7-1f1f4","uc_output":"1f1e7-1f1f4","uc_match":"1f1e7-1f1f4","uc_greedy":"1f1e7-1f1f4","shortnames":[":bo:"],"category":"flags"},":flag_bq:":{"uc_base":"1f1e7-1f1f6","uc_output":"1f1e7-1f1f6","uc_match":"1f1e7-1f1f6","uc_greedy":"1f1e7-1f1f6","shortnames":[":bq:"],"category":"flags"},":flag_br:":{"uc_base":"1f1e7-1f1f7","uc_output":"1f1e7-1f1f7","uc_match":"1f1e7-1f1f7","uc_greedy":"1f1e7-1f1f7","shortnames":[":br:"],"category":"flags"},":flag_bs:":{"uc_base":"1f1e7-1f1f8","uc_output":"1f1e7-1f1f8","uc_match":"1f1e7-1f1f8","uc_greedy":"1f1e7-1f1f8","shortnames":[":bs:"],"category":"flags"},":flag_bt:":{"uc_base":"1f1e7-1f1f9","uc_output":"1f1e7-1f1f9","uc_match":"1f1e7-1f1f9","uc_greedy":"1f1e7-1f1f9","shortnames":[":bt:"],"category":"flags"},":flag_bv:":{"uc_base":"1f1e7-1f1fb","uc_output":"1f1e7-1f1fb","uc_match":"1f1e7-1f1fb","uc_greedy":"1f1e7-1f1fb","shortnames":[":bv:"],"category":"flags"},":flag_bw:":{"uc_base":"1f1e7-1f1fc","uc_output":"1f1e7-1f1fc","uc_match":"1f1e7-1f1fc","uc_greedy":"1f1e7-1f1fc","shortnames":[":bw:"],"category":"flags"},":flag_by:":{"uc_base":"1f1e7-1f1fe","uc_output":"1f1e7-1f1fe","uc_match":"1f1e7-1f1fe","uc_greedy":"1f1e7-1f1fe","shortnames":[":by:"],"category":"flags"},":flag_bz:":{"uc_base":"1f1e7-1f1ff","uc_output":"1f1e7-1f1ff","uc_match":"1f1e7-1f1ff","uc_greedy":"1f1e7-1f1ff","shortnames":[":bz:"],"category":"flags"},":flag_ca:":{"uc_base":"1f1e8-1f1e6","uc_output":"1f1e8-1f1e6","uc_match":"1f1e8-1f1e6","uc_greedy":"1f1e8-1f1e6","shortnames":[":ca:"],"category":"flags"},":flag_cc:":{"uc_base":"1f1e8-1f1e8","uc_output":"1f1e8-1f1e8","uc_match":"1f1e8-1f1e8","uc_greedy":"1f1e8-1f1e8","shortnames":[":cc:"],"category":"flags"},":flag_cd:":{"uc_base":"1f1e8-1f1e9","uc_output":"1f1e8-1f1e9","uc_match":"1f1e8-1f1e9","uc_greedy":"1f1e8-1f1e9","shortnames":[":congo:"],"category":"flags"},":flag_cf:":{"uc_base":"1f1e8-1f1eb","uc_output":"1f1e8-1f1eb","uc_match":"1f1e8-1f1eb","uc_greedy":"1f1e8-1f1eb","shortnames":[":cf:"],"category":"flags"},":flag_cg:":{"uc_base":"1f1e8-1f1ec","uc_output":"1f1e8-1f1ec","uc_match":"1f1e8-1f1ec","uc_greedy":"1f1e8-1f1ec","shortnames":[":cg:"],"category":"flags"},":flag_ch:":{"uc_base":"1f1e8-1f1ed","uc_output":"1f1e8-1f1ed","uc_match":"1f1e8-1f1ed","uc_greedy":"1f1e8-1f1ed","shortnames":[":ch:"],"category":"flags"},":flag_ci:":{"uc_base":"1f1e8-1f1ee","uc_output":"1f1e8-1f1ee","uc_match":"1f1e8-1f1ee","uc_greedy":"1f1e8-1f1ee","shortnames":[":ci:"],"category":"flags"},":flag_ck:":{"uc_base":"1f1e8-1f1f0","uc_output":"1f1e8-1f1f0","uc_match":"1f1e8-1f1f0","uc_greedy":"1f1e8-1f1f0","shortnames":[":ck:"],"category":"flags"},":flag_cl:":{"uc_base":"1f1e8-1f1f1","uc_output":"1f1e8-1f1f1","uc_match":"1f1e8-1f1f1","uc_greedy":"1f1e8-1f1f1","shortnames":[":chile:"],"category":"flags"},":flag_cm:":{"uc_base":"1f1e8-1f1f2","uc_output":"1f1e8-1f1f2","uc_match":"1f1e8-1f1f2","uc_greedy":"1f1e8-1f1f2","shortnames":[":cm:"],"category":"flags"},":flag_cn:":{"uc_base":"1f1e8-1f1f3","uc_output":"1f1e8-1f1f3","uc_match":"1f1e8-1f1f3","uc_greedy":"1f1e8-1f1f3","shortnames":[":cn:"],"category":"flags"},":flag_co:":{"uc_base":"1f1e8-1f1f4","uc_output":"1f1e8-1f1f4","uc_match":"1f1e8-1f1f4","uc_greedy":"1f1e8-1f1f4","shortnames":[":co:"],"category":"flags"},":flag_cp:":{"uc_base":"1f1e8-1f1f5","uc_output":"1f1e8-1f1f5","uc_match":"1f1e8-1f1f5","uc_greedy":"1f1e8-1f1f5","shortnames":[":cp:"],"category":"flags"},":flag_cr:":{"uc_base":"1f1e8-1f1f7","uc_output":"1f1e8-1f1f7","uc_match":"1f1e8-1f1f7","uc_greedy":"1f1e8-1f1f7","shortnames":[":cr:"],"category":"flags"},":flag_cu:":{"uc_base":"1f1e8-1f1fa","uc_output":"1f1e8-1f1fa","uc_match":"1f1e8-1f1fa","uc_greedy":"1f1e8-1f1fa","shortnames":[":cu:"],"category":"flags"},":flag_cv:":{"uc_base":"1f1e8-1f1fb","uc_output":"1f1e8-1f1fb","uc_match":"1f1e8-1f1fb","uc_greedy":"1f1e8-1f1fb","shortnames":[":cv:"],"category":"flags"},":flag_cw:":{"uc_base":"1f1e8-1f1fc","uc_output":"1f1e8-1f1fc","uc_match":"1f1e8-1f1fc","uc_greedy":"1f1e8-1f1fc","shortnames":[":cw:"],"category":"flags"},":flag_cx:":{"uc_base":"1f1e8-1f1fd","uc_output":"1f1e8-1f1fd","uc_match":"1f1e8-1f1fd","uc_greedy":"1f1e8-1f1fd","shortnames":[":cx:"],"category":"flags"},":flag_cy:":{"uc_base":"1f1e8-1f1fe","uc_output":"1f1e8-1f1fe","uc_match":"1f1e8-1f1fe","uc_greedy":"1f1e8-1f1fe","shortnames":[":cy:"],"category":"flags"},":flag_cz:":{"uc_base":"1f1e8-1f1ff","uc_output":"1f1e8-1f1ff","uc_match":"1f1e8-1f1ff","uc_greedy":"1f1e8-1f1ff","shortnames":[":cz:"],"category":"flags"},":flag_de:":{"uc_base":"1f1e9-1f1ea","uc_output":"1f1e9-1f1ea","uc_match":"1f1e9-1f1ea","uc_greedy":"1f1e9-1f1ea","shortnames":[":de:"],"category":"flags"},":flag_dg:":{"uc_base":"1f1e9-1f1ec","uc_output":"1f1e9-1f1ec","uc_match":"1f1e9-1f1ec","uc_greedy":"1f1e9-1f1ec","shortnames":[":dg:"],"category":"flags"},":flag_dj:":{"uc_base":"1f1e9-1f1ef","uc_output":"1f1e9-1f1ef","uc_match":"1f1e9-1f1ef","uc_greedy":"1f1e9-1f1ef","shortnames":[":dj:"],"category":"flags"},":flag_dk:":{"uc_base":"1f1e9-1f1f0","uc_output":"1f1e9-1f1f0","uc_match":"1f1e9-1f1f0","uc_greedy":"1f1e9-1f1f0","shortnames":[":dk:"],"category":"flags"},":flag_dm:":{"uc_base":"1f1e9-1f1f2","uc_output":"1f1e9-1f1f2","uc_match":"1f1e9-1f1f2","uc_greedy":"1f1e9-1f1f2","shortnames":[":dm:"],"category":"flags"},":flag_do:":{"uc_base":"1f1e9-1f1f4","uc_output":"1f1e9-1f1f4","uc_match":"1f1e9-1f1f4","uc_greedy":"1f1e9-1f1f4","shortnames":[":do:"],"category":"flags"},":flag_dz:":{"uc_base":"1f1e9-1f1ff","uc_output":"1f1e9-1f1ff","uc_match":"1f1e9-1f1ff","uc_greedy":"1f1e9-1f1ff","shortnames":[":dz:"],"category":"flags"},":flag_ea:":{"uc_base":"1f1ea-1f1e6","uc_output":"1f1ea-1f1e6","uc_match":"1f1ea-1f1e6","uc_greedy":"1f1ea-1f1e6","shortnames":[":ea:"],"category":"flags"},":flag_ec:":{"uc_base":"1f1ea-1f1e8","uc_output":"1f1ea-1f1e8","uc_match":"1f1ea-1f1e8","uc_greedy":"1f1ea-1f1e8","shortnames":[":ec:"],"category":"flags"},":flag_ee:":{"uc_base":"1f1ea-1f1ea","uc_output":"1f1ea-1f1ea","uc_match":"1f1ea-1f1ea","uc_greedy":"1f1ea-1f1ea","shortnames":[":ee:"],"category":"flags"},":flag_eg:":{"uc_base":"1f1ea-1f1ec","uc_output":"1f1ea-1f1ec","uc_match":"1f1ea-1f1ec","uc_greedy":"1f1ea-1f1ec","shortnames":[":eg:"],"category":"flags"},":flag_eh:":{"uc_base":"1f1ea-1f1ed","uc_output":"1f1ea-1f1ed","uc_match":"1f1ea-1f1ed","uc_greedy":"1f1ea-1f1ed","shortnames":[":eh:"],"category":"flags"},":flag_er:":{"uc_base":"1f1ea-1f1f7","uc_output":"1f1ea-1f1f7","uc_match":"1f1ea-1f1f7","uc_greedy":"1f1ea-1f1f7","shortnames":[":er:"],"category":"flags"},":flag_es:":{"uc_base":"1f1ea-1f1f8","uc_output":"1f1ea-1f1f8","uc_match":"1f1ea-1f1f8","uc_greedy":"1f1ea-1f1f8","shortnames":[":es:"],"category":"flags"},":flag_et:":{"uc_base":"1f1ea-1f1f9","uc_output":"1f1ea-1f1f9","uc_match":"1f1ea-1f1f9","uc_greedy":"1f1ea-1f1f9","shortnames":[":et:"],"category":"flags"},":flag_eu:":{"uc_base":"1f1ea-1f1fa","uc_output":"1f1ea-1f1fa","uc_match":"1f1ea-1f1fa","uc_greedy":"1f1ea-1f1fa","shortnames":[":eu:"],"category":"flags"},":flag_fi:":{"uc_base":"1f1eb-1f1ee","uc_output":"1f1eb-1f1ee","uc_match":"1f1eb-1f1ee","uc_greedy":"1f1eb-1f1ee","shortnames":[":fi:"],"category":"flags"},":flag_fj:":{"uc_base":"1f1eb-1f1ef","uc_output":"1f1eb-1f1ef","uc_match":"1f1eb-1f1ef","uc_greedy":"1f1eb-1f1ef","shortnames":[":fj:"],"category":"flags"},":flag_fk:":{"uc_base":"1f1eb-1f1f0","uc_output":"1f1eb-1f1f0","uc_match":"1f1eb-1f1f0","uc_greedy":"1f1eb-1f1f0","shortnames":[":fk:"],"category":"flags"},":flag_fm:":{"uc_base":"1f1eb-1f1f2","uc_output":"1f1eb-1f1f2","uc_match":"1f1eb-1f1f2","uc_greedy":"1f1eb-1f1f2","shortnames":[":fm:"],"category":"flags"},":flag_fo:":{"uc_base":"1f1eb-1f1f4","uc_output":"1f1eb-1f1f4","uc_match":"1f1eb-1f1f4","uc_greedy":"1f1eb-1f1f4","shortnames":[":fo:"],"category":"flags"},":flag_fr:":{"uc_base":"1f1eb-1f1f7","uc_output":"1f1eb-1f1f7","uc_match":"1f1eb-1f1f7","uc_greedy":"1f1eb-1f1f7","shortnames":[":fr:"],"category":"flags"},":flag_ga:":{"uc_base":"1f1ec-1f1e6","uc_output":"1f1ec-1f1e6","uc_match":"1f1ec-1f1e6","uc_greedy":"1f1ec-1f1e6","shortnames":[":ga:"],"category":"flags"},":flag_gb:":{"uc_base":"1f1ec-1f1e7","uc_output":"1f1ec-1f1e7","uc_match":"1f1ec-1f1e7","uc_greedy":"1f1ec-1f1e7","shortnames":[":gb:"],"category":"flags"},":flag_gd:":{"uc_base":"1f1ec-1f1e9","uc_output":"1f1ec-1f1e9","uc_match":"1f1ec-1f1e9","uc_greedy":"1f1ec-1f1e9","shortnames":[":gd:"],"category":"flags"},":flag_ge:":{"uc_base":"1f1ec-1f1ea","uc_output":"1f1ec-1f1ea","uc_match":"1f1ec-1f1ea","uc_greedy":"1f1ec-1f1ea","shortnames":[":ge:"],"category":"flags"},":flag_gf:":{"uc_base":"1f1ec-1f1eb","uc_output":"1f1ec-1f1eb","uc_match":"1f1ec-1f1eb","uc_greedy":"1f1ec-1f1eb","shortnames":[":gf:"],"category":"flags"},":flag_gg:":{"uc_base":"1f1ec-1f1ec","uc_output":"1f1ec-1f1ec","uc_match":"1f1ec-1f1ec","uc_greedy":"1f1ec-1f1ec","shortnames":[":gg:"],"category":"flags"},":flag_gh:":{"uc_base":"1f1ec-1f1ed","uc_output":"1f1ec-1f1ed","uc_match":"1f1ec-1f1ed","uc_greedy":"1f1ec-1f1ed","shortnames":[":gh:"],"category":"flags"},":flag_gi:":{"uc_base":"1f1ec-1f1ee","uc_output":"1f1ec-1f1ee","uc_match":"1f1ec-1f1ee","uc_greedy":"1f1ec-1f1ee","shortnames":[":gi:"],"category":"flags"},":flag_gl:":{"uc_base":"1f1ec-1f1f1","uc_output":"1f1ec-1f1f1","uc_match":"1f1ec-1f1f1","uc_greedy":"1f1ec-1f1f1","shortnames":[":gl:"],"category":"flags"},":flag_gm:":{"uc_base":"1f1ec-1f1f2","uc_output":"1f1ec-1f1f2","uc_match":"1f1ec-1f1f2","uc_greedy":"1f1ec-1f1f2","shortnames":[":gm:"],"category":"flags"},":flag_gn:":{"uc_base":"1f1ec-1f1f3","uc_output":"1f1ec-1f1f3","uc_match":"1f1ec-1f1f3","uc_greedy":"1f1ec-1f1f3","shortnames":[":gn:"],"category":"flags"},":flag_gp:":{"uc_base":"1f1ec-1f1f5","uc_output":"1f1ec-1f1f5","uc_match":"1f1ec-1f1f5","uc_greedy":"1f1ec-1f1f5","shortnames":[":gp:"],"category":"flags"},":flag_gq:":{"uc_base":"1f1ec-1f1f6","uc_output":"1f1ec-1f1f6","uc_match":"1f1ec-1f1f6","uc_greedy":"1f1ec-1f1f6","shortnames":[":gq:"],"category":"flags"},":flag_gr:":{"uc_base":"1f1ec-1f1f7","uc_output":"1f1ec-1f1f7","uc_match":"1f1ec-1f1f7","uc_greedy":"1f1ec-1f1f7","shortnames":[":gr:"],"category":"flags"},":flag_gs:":{"uc_base":"1f1ec-1f1f8","uc_output":"1f1ec-1f1f8","uc_match":"1f1ec-1f1f8","uc_greedy":"1f1ec-1f1f8","shortnames":[":gs:"],"category":"flags"},":flag_gt:":{"uc_base":"1f1ec-1f1f9","uc_output":"1f1ec-1f1f9","uc_match":"1f1ec-1f1f9","uc_greedy":"1f1ec-1f1f9","shortnames":[":gt:"],"category":"flags"},":flag_gu:":{"uc_base":"1f1ec-1f1fa","uc_output":"1f1ec-1f1fa","uc_match":"1f1ec-1f1fa","uc_greedy":"1f1ec-1f1fa","shortnames":[":gu:"],"category":"flags"},":flag_gw:":{"uc_base":"1f1ec-1f1fc","uc_output":"1f1ec-1f1fc","uc_match":"1f1ec-1f1fc","uc_greedy":"1f1ec-1f1fc","shortnames":[":gw:"],"category":"flags"},":flag_gy:":{"uc_base":"1f1ec-1f1fe","uc_output":"1f1ec-1f1fe","uc_match":"1f1ec-1f1fe","uc_greedy":"1f1ec-1f1fe","shortnames":[":gy:"],"category":"flags"},":flag_hk:":{"uc_base":"1f1ed-1f1f0","uc_output":"1f1ed-1f1f0","uc_match":"1f1ed-1f1f0","uc_greedy":"1f1ed-1f1f0","shortnames":[":hk:"],"category":"flags"},":flag_hm:":{"uc_base":"1f1ed-1f1f2","uc_output":"1f1ed-1f1f2","uc_match":"1f1ed-1f1f2","uc_greedy":"1f1ed-1f1f2","shortnames":[":hm:"],"category":"flags"},":flag_hn:":{"uc_base":"1f1ed-1f1f3","uc_output":"1f1ed-1f1f3","uc_match":"1f1ed-1f1f3","uc_greedy":"1f1ed-1f1f3","shortnames":[":hn:"],"category":"flags"},":flag_hr:":{"uc_base":"1f1ed-1f1f7","uc_output":"1f1ed-1f1f7","uc_match":"1f1ed-1f1f7","uc_greedy":"1f1ed-1f1f7","shortnames":[":hr:"],"category":"flags"},":flag_ht:":{"uc_base":"1f1ed-1f1f9","uc_output":"1f1ed-1f1f9","uc_match":"1f1ed-1f1f9","uc_greedy":"1f1ed-1f1f9","shortnames":[":ht:"],"category":"flags"},":flag_hu:":{"uc_base":"1f1ed-1f1fa","uc_output":"1f1ed-1f1fa","uc_match":"1f1ed-1f1fa","uc_greedy":"1f1ed-1f1fa","shortnames":[":hu:"],"category":"flags"},":flag_ic:":{"uc_base":"1f1ee-1f1e8","uc_output":"1f1ee-1f1e8","uc_match":"1f1ee-1f1e8","uc_greedy":"1f1ee-1f1e8","shortnames":[":ic:"],"category":"flags"},":flag_id:":{"uc_base":"1f1ee-1f1e9","uc_output":"1f1ee-1f1e9","uc_match":"1f1ee-1f1e9","uc_greedy":"1f1ee-1f1e9","shortnames":[":indonesia:"],"category":"flags"},":flag_ie:":{"uc_base":"1f1ee-1f1ea","uc_output":"1f1ee-1f1ea","uc_match":"1f1ee-1f1ea","uc_greedy":"1f1ee-1f1ea","shortnames":[":ie:"],"category":"flags"},":flag_il:":{"uc_base":"1f1ee-1f1f1","uc_output":"1f1ee-1f1f1","uc_match":"1f1ee-1f1f1","uc_greedy":"1f1ee-1f1f1","shortnames":[":il:"],"category":"flags"},":flag_im:":{"uc_base":"1f1ee-1f1f2","uc_output":"1f1ee-1f1f2","uc_match":"1f1ee-1f1f2","uc_greedy":"1f1ee-1f1f2","shortnames":[":im:"],"category":"flags"},":flag_in:":{"uc_base":"1f1ee-1f1f3","uc_output":"1f1ee-1f1f3","uc_match":"1f1ee-1f1f3","uc_greedy":"1f1ee-1f1f3","shortnames":[":in:"],"category":"flags"},":flag_io:":{"uc_base":"1f1ee-1f1f4","uc_output":"1f1ee-1f1f4","uc_match":"1f1ee-1f1f4","uc_greedy":"1f1ee-1f1f4","shortnames":[":io:"],"category":"flags"},":flag_iq:":{"uc_base":"1f1ee-1f1f6","uc_output":"1f1ee-1f1f6","uc_match":"1f1ee-1f1f6","uc_greedy":"1f1ee-1f1f6","shortnames":[":iq:"],"category":"flags"},":flag_ir:":{"uc_base":"1f1ee-1f1f7","uc_output":"1f1ee-1f1f7","uc_match":"1f1ee-1f1f7","uc_greedy":"1f1ee-1f1f7","shortnames":[":ir:"],"category":"flags"},":flag_is:":{"uc_base":"1f1ee-1f1f8","uc_output":"1f1ee-1f1f8","uc_match":"1f1ee-1f1f8","uc_greedy":"1f1ee-1f1f8","shortnames":[":is:"],"category":"flags"},":flag_it:":{"uc_base":"1f1ee-1f1f9","uc_output":"1f1ee-1f1f9","uc_match":"1f1ee-1f1f9","uc_greedy":"1f1ee-1f1f9","shortnames":[":it:"],"category":"flags"},":flag_je:":{"uc_base":"1f1ef-1f1ea","uc_output":"1f1ef-1f1ea","uc_match":"1f1ef-1f1ea","uc_greedy":"1f1ef-1f1ea","shortnames":[":je:"],"category":"flags"},":flag_jm:":{"uc_base":"1f1ef-1f1f2","uc_output":"1f1ef-1f1f2","uc_match":"1f1ef-1f1f2","uc_greedy":"1f1ef-1f1f2","shortnames":[":jm:"],"category":"flags"},":flag_jo:":{"uc_base":"1f1ef-1f1f4","uc_output":"1f1ef-1f1f4","uc_match":"1f1ef-1f1f4","uc_greedy":"1f1ef-1f1f4","shortnames":[":jo:"],"category":"flags"},":flag_jp:":{"uc_base":"1f1ef-1f1f5","uc_output":"1f1ef-1f1f5","uc_match":"1f1ef-1f1f5","uc_greedy":"1f1ef-1f1f5","shortnames":[":jp:"],"category":"flags"},":flag_ke:":{"uc_base":"1f1f0-1f1ea","uc_output":"1f1f0-1f1ea","uc_match":"1f1f0-1f1ea","uc_greedy":"1f1f0-1f1ea","shortnames":[":ke:"],"category":"flags"},":flag_kg:":{"uc_base":"1f1f0-1f1ec","uc_output":"1f1f0-1f1ec","uc_match":"1f1f0-1f1ec","uc_greedy":"1f1f0-1f1ec","shortnames":[":kg:"],"category":"flags"},":flag_kh:":{"uc_base":"1f1f0-1f1ed","uc_output":"1f1f0-1f1ed","uc_match":"1f1f0-1f1ed","uc_greedy":"1f1f0-1f1ed","shortnames":[":kh:"],"category":"flags"},":flag_ki:":{"uc_base":"1f1f0-1f1ee","uc_output":"1f1f0-1f1ee","uc_match":"1f1f0-1f1ee","uc_greedy":"1f1f0-1f1ee","shortnames":[":ki:"],"category":"flags"},":flag_km:":{"uc_base":"1f1f0-1f1f2","uc_output":"1f1f0-1f1f2","uc_match":"1f1f0-1f1f2","uc_greedy":"1f1f0-1f1f2","shortnames":[":km:"],"category":"flags"},":flag_kn:":{"uc_base":"1f1f0-1f1f3","uc_output":"1f1f0-1f1f3","uc_match":"1f1f0-1f1f3","uc_greedy":"1f1f0-1f1f3","shortnames":[":kn:"],"category":"flags"},":flag_kp:":{"uc_base":"1f1f0-1f1f5","uc_output":"1f1f0-1f1f5","uc_match":"1f1f0-1f1f5","uc_greedy":"1f1f0-1f1f5","shortnames":[":kp:"],"category":"flags"},":flag_kr:":{"uc_base":"1f1f0-1f1f7","uc_output":"1f1f0-1f1f7","uc_match":"1f1f0-1f1f7","uc_greedy":"1f1f0-1f1f7","shortnames":[":kr:"],"category":"flags"},":flag_kw:":{"uc_base":"1f1f0-1f1fc","uc_output":"1f1f0-1f1fc","uc_match":"1f1f0-1f1fc","uc_greedy":"1f1f0-1f1fc","shortnames":[":kw:"],"category":"flags"},":flag_ky:":{"uc_base":"1f1f0-1f1fe","uc_output":"1f1f0-1f1fe","uc_match":"1f1f0-1f1fe","uc_greedy":"1f1f0-1f1fe","shortnames":[":ky:"],"category":"flags"},":flag_kz:":{"uc_base":"1f1f0-1f1ff","uc_output":"1f1f0-1f1ff","uc_match":"1f1f0-1f1ff","uc_greedy":"1f1f0-1f1ff","shortnames":[":kz:"],"category":"flags"},":flag_la:":{"uc_base":"1f1f1-1f1e6","uc_output":"1f1f1-1f1e6","uc_match":"1f1f1-1f1e6","uc_greedy":"1f1f1-1f1e6","shortnames":[":la:"],"category":"flags"},":flag_lb:":{"uc_base":"1f1f1-1f1e7","uc_output":"1f1f1-1f1e7","uc_match":"1f1f1-1f1e7","uc_greedy":"1f1f1-1f1e7","shortnames":[":lb:"],"category":"flags"},":flag_lc:":{"uc_base":"1f1f1-1f1e8","uc_output":"1f1f1-1f1e8","uc_match":"1f1f1-1f1e8","uc_greedy":"1f1f1-1f1e8","shortnames":[":lc:"],"category":"flags"},":flag_li:":{"uc_base":"1f1f1-1f1ee","uc_output":"1f1f1-1f1ee","uc_match":"1f1f1-1f1ee","uc_greedy":"1f1f1-1f1ee","shortnames":[":li:"],"category":"flags"},":flag_lk:":{"uc_base":"1f1f1-1f1f0","uc_output":"1f1f1-1f1f0","uc_match":"1f1f1-1f1f0","uc_greedy":"1f1f1-1f1f0","shortnames":[":lk:"],"category":"flags"},":flag_lr:":{"uc_base":"1f1f1-1f1f7","uc_output":"1f1f1-1f1f7","uc_match":"1f1f1-1f1f7","uc_greedy":"1f1f1-1f1f7","shortnames":[":lr:"],"category":"flags"},":flag_ls:":{"uc_base":"1f1f1-1f1f8","uc_output":"1f1f1-1f1f8","uc_match":"1f1f1-1f1f8","uc_greedy":"1f1f1-1f1f8","shortnames":[":ls:"],"category":"flags"},":flag_lt:":{"uc_base":"1f1f1-1f1f9","uc_output":"1f1f1-1f1f9","uc_match":"1f1f1-1f1f9","uc_greedy":"1f1f1-1f1f9","shortnames":[":lt:"],"category":"flags"},":flag_lu:":{"uc_base":"1f1f1-1f1fa","uc_output":"1f1f1-1f1fa","uc_match":"1f1f1-1f1fa","uc_greedy":"1f1f1-1f1fa","shortnames":[":lu:"],"category":"flags"},":flag_lv:":{"uc_base":"1f1f1-1f1fb","uc_output":"1f1f1-1f1fb","uc_match":"1f1f1-1f1fb","uc_greedy":"1f1f1-1f1fb","shortnames":[":lv:"],"category":"flags"},":flag_ly:":{"uc_base":"1f1f1-1f1fe","uc_output":"1f1f1-1f1fe","uc_match":"1f1f1-1f1fe","uc_greedy":"1f1f1-1f1fe","shortnames":[":ly:"],"category":"flags"},":flag_ma:":{"uc_base":"1f1f2-1f1e6","uc_output":"1f1f2-1f1e6","uc_match":"1f1f2-1f1e6","uc_greedy":"1f1f2-1f1e6","shortnames":[":ma:"],"category":"flags"},":flag_mc:":{"uc_base":"1f1f2-1f1e8","uc_output":"1f1f2-1f1e8","uc_match":"1f1f2-1f1e8","uc_greedy":"1f1f2-1f1e8","shortnames":[":mc:"],"category":"flags"},":flag_md:":{"uc_base":"1f1f2-1f1e9","uc_output":"1f1f2-1f1e9","uc_match":"1f1f2-1f1e9","uc_greedy":"1f1f2-1f1e9","shortnames":[":md:"],"category":"flags"},":flag_me:":{"uc_base":"1f1f2-1f1ea","uc_output":"1f1f2-1f1ea","uc_match":"1f1f2-1f1ea","uc_greedy":"1f1f2-1f1ea","shortnames":[":me:"],"category":"flags"},":flag_mf:":{"uc_base":"1f1f2-1f1eb","uc_output":"1f1f2-1f1eb","uc_match":"1f1f2-1f1eb","uc_greedy":"1f1f2-1f1eb","shortnames":[":mf:"],"category":"flags"},":flag_mg:":{"uc_base":"1f1f2-1f1ec","uc_output":"1f1f2-1f1ec","uc_match":"1f1f2-1f1ec","uc_greedy":"1f1f2-1f1ec","shortnames":[":mg:"],"category":"flags"},":flag_mh:":{"uc_base":"1f1f2-1f1ed","uc_output":"1f1f2-1f1ed","uc_match":"1f1f2-1f1ed","uc_greedy":"1f1f2-1f1ed","shortnames":[":mh:"],"category":"flags"},":flag_mk:":{"uc_base":"1f1f2-1f1f0","uc_output":"1f1f2-1f1f0","uc_match":"1f1f2-1f1f0","uc_greedy":"1f1f2-1f1f0","shortnames":[":mk:"],"category":"flags"},":flag_ml:":{"uc_base":"1f1f2-1f1f1","uc_output":"1f1f2-1f1f1","uc_match":"1f1f2-1f1f1","uc_greedy":"1f1f2-1f1f1","shortnames":[":ml:"],"category":"flags"},":flag_mm:":{"uc_base":"1f1f2-1f1f2","uc_output":"1f1f2-1f1f2","uc_match":"1f1f2-1f1f2","uc_greedy":"1f1f2-1f1f2","shortnames":[":mm:"],"category":"flags"},":flag_mn:":{"uc_base":"1f1f2-1f1f3","uc_output":"1f1f2-1f1f3","uc_match":"1f1f2-1f1f3","uc_greedy":"1f1f2-1f1f3","shortnames":[":mn:"],"category":"flags"},":flag_mo:":{"uc_base":"1f1f2-1f1f4","uc_output":"1f1f2-1f1f4","uc_match":"1f1f2-1f1f4","uc_greedy":"1f1f2-1f1f4","shortnames":[":mo:"],"category":"flags"},":flag_mp:":{"uc_base":"1f1f2-1f1f5","uc_output":"1f1f2-1f1f5","uc_match":"1f1f2-1f1f5","uc_greedy":"1f1f2-1f1f5","shortnames":[":mp:"],"category":"flags"},":flag_mq:":{"uc_base":"1f1f2-1f1f6","uc_output":"1f1f2-1f1f6","uc_match":"1f1f2-1f1f6","uc_greedy":"1f1f2-1f1f6","shortnames":[":mq:"],"category":"flags"},":flag_mr:":{"uc_base":"1f1f2-1f1f7","uc_output":"1f1f2-1f1f7","uc_match":"1f1f2-1f1f7","uc_greedy":"1f1f2-1f1f7","shortnames":[":mr:"],"category":"flags"},":flag_ms:":{"uc_base":"1f1f2-1f1f8","uc_output":"1f1f2-1f1f8","uc_match":"1f1f2-1f1f8","uc_greedy":"1f1f2-1f1f8","shortnames":[":ms:"],"category":"flags"},":flag_mt:":{"uc_base":"1f1f2-1f1f9","uc_output":"1f1f2-1f1f9","uc_match":"1f1f2-1f1f9","uc_greedy":"1f1f2-1f1f9","shortnames":[":mt:"],"category":"flags"},":flag_mu:":{"uc_base":"1f1f2-1f1fa","uc_output":"1f1f2-1f1fa","uc_match":"1f1f2-1f1fa","uc_greedy":"1f1f2-1f1fa","shortnames":[":mu:"],"category":"flags"},":flag_mv:":{"uc_base":"1f1f2-1f1fb","uc_output":"1f1f2-1f1fb","uc_match":"1f1f2-1f1fb","uc_greedy":"1f1f2-1f1fb","shortnames":[":mv:"],"category":"flags"},":flag_mw:":{"uc_base":"1f1f2-1f1fc","uc_output":"1f1f2-1f1fc","uc_match":"1f1f2-1f1fc","uc_greedy":"1f1f2-1f1fc","shortnames":[":mw:"],"category":"flags"},":flag_mx:":{"uc_base":"1f1f2-1f1fd","uc_output":"1f1f2-1f1fd","uc_match":"1f1f2-1f1fd","uc_greedy":"1f1f2-1f1fd","shortnames":[":mx:"],"category":"flags"},":flag_my:":{"uc_base":"1f1f2-1f1fe","uc_output":"1f1f2-1f1fe","uc_match":"1f1f2-1f1fe","uc_greedy":"1f1f2-1f1fe","shortnames":[":my:"],"category":"flags"},":flag_mz:":{"uc_base":"1f1f2-1f1ff","uc_output":"1f1f2-1f1ff","uc_match":"1f1f2-1f1ff","uc_greedy":"1f1f2-1f1ff","shortnames":[":mz:"],"category":"flags"},":flag_na:":{"uc_base":"1f1f3-1f1e6","uc_output":"1f1f3-1f1e6","uc_match":"1f1f3-1f1e6","uc_greedy":"1f1f3-1f1e6","shortnames":[":na:"],"category":"flags"},":flag_nc:":{"uc_base":"1f1f3-1f1e8","uc_output":"1f1f3-1f1e8","uc_match":"1f1f3-1f1e8","uc_greedy":"1f1f3-1f1e8","shortnames":[":nc:"],"category":"flags"},":flag_ne:":{"uc_base":"1f1f3-1f1ea","uc_output":"1f1f3-1f1ea","uc_match":"1f1f3-1f1ea","uc_greedy":"1f1f3-1f1ea","shortnames":[":ne:"],"category":"flags"},":flag_nf:":{"uc_base":"1f1f3-1f1eb","uc_output":"1f1f3-1f1eb","uc_match":"1f1f3-1f1eb","uc_greedy":"1f1f3-1f1eb","shortnames":[":nf:"],"category":"flags"},":flag_ng:":{"uc_base":"1f1f3-1f1ec","uc_output":"1f1f3-1f1ec","uc_match":"1f1f3-1f1ec","uc_greedy":"1f1f3-1f1ec","shortnames":[":nigeria:"],"category":"flags"},":flag_ni:":{"uc_base":"1f1f3-1f1ee","uc_output":"1f1f3-1f1ee","uc_match":"1f1f3-1f1ee","uc_greedy":"1f1f3-1f1ee","shortnames":[":ni:"],"category":"flags"},":flag_nl:":{"uc_base":"1f1f3-1f1f1","uc_output":"1f1f3-1f1f1","uc_match":"1f1f3-1f1f1","uc_greedy":"1f1f3-1f1f1","shortnames":[":nl:"],"category":"flags"},":flag_no:":{"uc_base":"1f1f3-1f1f4","uc_output":"1f1f3-1f1f4","uc_match":"1f1f3-1f1f4","uc_greedy":"1f1f3-1f1f4","shortnames":[":no:"],"category":"flags"},":flag_np:":{"uc_base":"1f1f3-1f1f5","uc_output":"1f1f3-1f1f5","uc_match":"1f1f3-1f1f5","uc_greedy":"1f1f3-1f1f5","shortnames":[":np:"],"category":"flags"},":flag_nr:":{"uc_base":"1f1f3-1f1f7","uc_output":"1f1f3-1f1f7","uc_match":"1f1f3-1f1f7","uc_greedy":"1f1f3-1f1f7","shortnames":[":nr:"],"category":"flags"},":flag_nu:":{"uc_base":"1f1f3-1f1fa","uc_output":"1f1f3-1f1fa","uc_match":"1f1f3-1f1fa","uc_greedy":"1f1f3-1f1fa","shortnames":[":nu:"],"category":"flags"},":flag_nz:":{"uc_base":"1f1f3-1f1ff","uc_output":"1f1f3-1f1ff","uc_match":"1f1f3-1f1ff","uc_greedy":"1f1f3-1f1ff","shortnames":[":nz:"],"category":"flags"},":flag_om:":{"uc_base":"1f1f4-1f1f2","uc_output":"1f1f4-1f1f2","uc_match":"1f1f4-1f1f2","uc_greedy":"1f1f4-1f1f2","shortnames":[":om:"],"category":"flags"},":flag_pa:":{"uc_base":"1f1f5-1f1e6","uc_output":"1f1f5-1f1e6","uc_match":"1f1f5-1f1e6","uc_greedy":"1f1f5-1f1e6","shortnames":[":pa:"],"category":"flags"},":flag_pe:":{"uc_base":"1f1f5-1f1ea","uc_output":"1f1f5-1f1ea","uc_match":"1f1f5-1f1ea","uc_greedy":"1f1f5-1f1ea","shortnames":[":pe:"],"category":"flags"},":flag_pf:":{"uc_base":"1f1f5-1f1eb","uc_output":"1f1f5-1f1eb","uc_match":"1f1f5-1f1eb","uc_greedy":"1f1f5-1f1eb","shortnames":[":pf:"],"category":"flags"},":flag_pg:":{"uc_base":"1f1f5-1f1ec","uc_output":"1f1f5-1f1ec","uc_match":"1f1f5-1f1ec","uc_greedy":"1f1f5-1f1ec","shortnames":[":pg:"],"category":"flags"},":flag_ph:":{"uc_base":"1f1f5-1f1ed","uc_output":"1f1f5-1f1ed","uc_match":"1f1f5-1f1ed","uc_greedy":"1f1f5-1f1ed","shortnames":[":ph:"],"category":"flags"},":flag_pk:":{"uc_base":"1f1f5-1f1f0","uc_output":"1f1f5-1f1f0","uc_match":"1f1f5-1f1f0","uc_greedy":"1f1f5-1f1f0","shortnames":[":pk:"],"category":"flags"},":flag_pl:":{"uc_base":"1f1f5-1f1f1","uc_output":"1f1f5-1f1f1","uc_match":"1f1f5-1f1f1","uc_greedy":"1f1f5-1f1f1","shortnames":[":pl:"],"category":"flags"},":flag_pm:":{"uc_base":"1f1f5-1f1f2","uc_output":"1f1f5-1f1f2","uc_match":"1f1f5-1f1f2","uc_greedy":"1f1f5-1f1f2","shortnames":[":pm:"],"category":"flags"},":flag_pn:":{"uc_base":"1f1f5-1f1f3","uc_output":"1f1f5-1f1f3","uc_match":"1f1f5-1f1f3","uc_greedy":"1f1f5-1f1f3","shortnames":[":pn:"],"category":"flags"},":flag_pr:":{"uc_base":"1f1f5-1f1f7","uc_output":"1f1f5-1f1f7","uc_match":"1f1f5-1f1f7","uc_greedy":"1f1f5-1f1f7","shortnames":[":pr:"],"category":"flags"},":flag_ps:":{"uc_base":"1f1f5-1f1f8","uc_output":"1f1f5-1f1f8","uc_match":"1f1f5-1f1f8","uc_greedy":"1f1f5-1f1f8","shortnames":[":ps:"],"category":"flags"},":flag_pt:":{"uc_base":"1f1f5-1f1f9","uc_output":"1f1f5-1f1f9","uc_match":"1f1f5-1f1f9","uc_greedy":"1f1f5-1f1f9","shortnames":[":pt:"],"category":"flags"},":flag_pw:":{"uc_base":"1f1f5-1f1fc","uc_output":"1f1f5-1f1fc","uc_match":"1f1f5-1f1fc","uc_greedy":"1f1f5-1f1fc","shortnames":[":pw:"],"category":"flags"},":flag_py:":{"uc_base":"1f1f5-1f1fe","uc_output":"1f1f5-1f1fe","uc_match":"1f1f5-1f1fe","uc_greedy":"1f1f5-1f1fe","shortnames":[":py:"],"category":"flags"},":flag_qa:":{"uc_base":"1f1f6-1f1e6","uc_output":"1f1f6-1f1e6","uc_match":"1f1f6-1f1e6","uc_greedy":"1f1f6-1f1e6","shortnames":[":qa:"],"category":"flags"},":flag_re:":{"uc_base":"1f1f7-1f1ea","uc_output":"1f1f7-1f1ea","uc_match":"1f1f7-1f1ea","uc_greedy":"1f1f7-1f1ea","shortnames":[":re:"],"category":"flags"},":flag_ro:":{"uc_base":"1f1f7-1f1f4","uc_output":"1f1f7-1f1f4","uc_match":"1f1f7-1f1f4","uc_greedy":"1f1f7-1f1f4","shortnames":[":ro:"],"category":"flags"},":flag_rs:":{"uc_base":"1f1f7-1f1f8","uc_output":"1f1f7-1f1f8","uc_match":"1f1f7-1f1f8","uc_greedy":"1f1f7-1f1f8","shortnames":[":rs:"],"category":"flags"},":flag_ru:":{"uc_base":"1f1f7-1f1fa","uc_output":"1f1f7-1f1fa","uc_match":"1f1f7-1f1fa","uc_greedy":"1f1f7-1f1fa","shortnames":[":ru:"],"category":"flags"},":flag_rw:":{"uc_base":"1f1f7-1f1fc","uc_output":"1f1f7-1f1fc","uc_match":"1f1f7-1f1fc","uc_greedy":"1f1f7-1f1fc","shortnames":[":rw:"],"category":"flags"},":flag_sa:":{"uc_base":"1f1f8-1f1e6","uc_output":"1f1f8-1f1e6","uc_match":"1f1f8-1f1e6","uc_greedy":"1f1f8-1f1e6","shortnames":[":saudiarabia:",":saudi:"],"category":"flags"},":flag_sb:":{"uc_base":"1f1f8-1f1e7","uc_output":"1f1f8-1f1e7","uc_match":"1f1f8-1f1e7","uc_greedy":"1f1f8-1f1e7","shortnames":[":sb:"],"category":"flags"},":flag_sc:":{"uc_base":"1f1f8-1f1e8","uc_output":"1f1f8-1f1e8","uc_match":"1f1f8-1f1e8","uc_greedy":"1f1f8-1f1e8","shortnames":[":sc:"],"category":"flags"},":flag_sd:":{"uc_base":"1f1f8-1f1e9","uc_output":"1f1f8-1f1e9","uc_match":"1f1f8-1f1e9","uc_greedy":"1f1f8-1f1e9","shortnames":[":sd:"],"category":"flags"},":flag_se:":{"uc_base":"1f1f8-1f1ea","uc_output":"1f1f8-1f1ea","uc_match":"1f1f8-1f1ea","uc_greedy":"1f1f8-1f1ea","shortnames":[":se:"],"category":"flags"},":flag_sg:":{"uc_base":"1f1f8-1f1ec","uc_output":"1f1f8-1f1ec","uc_match":"1f1f8-1f1ec","uc_greedy":"1f1f8-1f1ec","shortnames":[":sg:"],"category":"flags"},":flag_sh:":{"uc_base":"1f1f8-1f1ed","uc_output":"1f1f8-1f1ed","uc_match":"1f1f8-1f1ed","uc_greedy":"1f1f8-1f1ed","shortnames":[":sh:"],"category":"flags"},":flag_si:":{"uc_base":"1f1f8-1f1ee","uc_output":"1f1f8-1f1ee","uc_match":"1f1f8-1f1ee","uc_greedy":"1f1f8-1f1ee","shortnames":[":si:"],"category":"flags"},":flag_sj:":{"uc_base":"1f1f8-1f1ef","uc_output":"1f1f8-1f1ef","uc_match":"1f1f8-1f1ef","uc_greedy":"1f1f8-1f1ef","shortnames":[":sj:"],"category":"flags"},":flag_sk:":{"uc_base":"1f1f8-1f1f0","uc_output":"1f1f8-1f1f0","uc_match":"1f1f8-1f1f0","uc_greedy":"1f1f8-1f1f0","shortnames":[":sk:"],"category":"flags"},":flag_sl:":{"uc_base":"1f1f8-1f1f1","uc_output":"1f1f8-1f1f1","uc_match":"1f1f8-1f1f1","uc_greedy":"1f1f8-1f1f1","shortnames":[":sl:"],"category":"flags"},":flag_sm:":{"uc_base":"1f1f8-1f1f2","uc_output":"1f1f8-1f1f2","uc_match":"1f1f8-1f1f2","uc_greedy":"1f1f8-1f1f2","shortnames":[":sm:"],"category":"flags"},":flag_sn:":{"uc_base":"1f1f8-1f1f3","uc_output":"1f1f8-1f1f3","uc_match":"1f1f8-1f1f3","uc_greedy":"1f1f8-1f1f3","shortnames":[":sn:"],"category":"flags"},":flag_so:":{"uc_base":"1f1f8-1f1f4","uc_output":"1f1f8-1f1f4","uc_match":"1f1f8-1f1f4","uc_greedy":"1f1f8-1f1f4","shortnames":[":so:"],"category":"flags"},":flag_sr:":{"uc_base":"1f1f8-1f1f7","uc_output":"1f1f8-1f1f7","uc_match":"1f1f8-1f1f7","uc_greedy":"1f1f8-1f1f7","shortnames":[":sr:"],"category":"flags"},":flag_ss:":{"uc_base":"1f1f8-1f1f8","uc_output":"1f1f8-1f1f8","uc_match":"1f1f8-1f1f8","uc_greedy":"1f1f8-1f1f8","shortnames":[":ss:"],"category":"flags"},":flag_st:":{"uc_base":"1f1f8-1f1f9","uc_output":"1f1f8-1f1f9","uc_match":"1f1f8-1f1f9","uc_greedy":"1f1f8-1f1f9","shortnames":[":st:"],"category":"flags"},":flag_sv:":{"uc_base":"1f1f8-1f1fb","uc_output":"1f1f8-1f1fb","uc_match":"1f1f8-1f1fb","uc_greedy":"1f1f8-1f1fb","shortnames":[":sv:"],"category":"flags"},":flag_sx:":{"uc_base":"1f1f8-1f1fd","uc_output":"1f1f8-1f1fd","uc_match":"1f1f8-1f1fd","uc_greedy":"1f1f8-1f1fd","shortnames":[":sx:"],"category":"flags"},":flag_sy:":{"uc_base":"1f1f8-1f1fe","uc_output":"1f1f8-1f1fe","uc_match":"1f1f8-1f1fe","uc_greedy":"1f1f8-1f1fe","shortnames":[":sy:"],"category":"flags"},":flag_sz:":{"uc_base":"1f1f8-1f1ff","uc_output":"1f1f8-1f1ff","uc_match":"1f1f8-1f1ff","uc_greedy":"1f1f8-1f1ff","shortnames":[":sz:"],"category":"flags"},":flag_ta:":{"uc_base":"1f1f9-1f1e6","uc_output":"1f1f9-1f1e6","uc_match":"1f1f9-1f1e6","uc_greedy":"1f1f9-1f1e6","shortnames":[":ta:"],"category":"flags"},":flag_tc:":{"uc_base":"1f1f9-1f1e8","uc_output":"1f1f9-1f1e8","uc_match":"1f1f9-1f1e8","uc_greedy":"1f1f9-1f1e8","shortnames":[":tc:"],"category":"flags"},":flag_td:":{"uc_base":"1f1f9-1f1e9","uc_output":"1f1f9-1f1e9","uc_match":"1f1f9-1f1e9","uc_greedy":"1f1f9-1f1e9","shortnames":[":td:"],"category":"flags"},":flag_tf:":{"uc_base":"1f1f9-1f1eb","uc_output":"1f1f9-1f1eb","uc_match":"1f1f9-1f1eb","uc_greedy":"1f1f9-1f1eb","shortnames":[":tf:"],"category":"flags"},":flag_tg:":{"uc_base":"1f1f9-1f1ec","uc_output":"1f1f9-1f1ec","uc_match":"1f1f9-1f1ec","uc_greedy":"1f1f9-1f1ec","shortnames":[":tg:"],"category":"flags"},":flag_th:":{"uc_base":"1f1f9-1f1ed","uc_output":"1f1f9-1f1ed","uc_match":"1f1f9-1f1ed","uc_greedy":"1f1f9-1f1ed","shortnames":[":th:"],"category":"flags"},":flag_tj:":{"uc_base":"1f1f9-1f1ef","uc_output":"1f1f9-1f1ef","uc_match":"1f1f9-1f1ef","uc_greedy":"1f1f9-1f1ef","shortnames":[":tj:"],"category":"flags"},":flag_tk:":{"uc_base":"1f1f9-1f1f0","uc_output":"1f1f9-1f1f0","uc_match":"1f1f9-1f1f0","uc_greedy":"1f1f9-1f1f0","shortnames":[":tk:"],"category":"flags"},":flag_tl:":{"uc_base":"1f1f9-1f1f1","uc_output":"1f1f9-1f1f1","uc_match":"1f1f9-1f1f1","uc_greedy":"1f1f9-1f1f1","shortnames":[":tl:"],"category":"flags"},":flag_tm:":{"uc_base":"1f1f9-1f1f2","uc_output":"1f1f9-1f1f2","uc_match":"1f1f9-1f1f2","uc_greedy":"1f1f9-1f1f2","shortnames":[":turkmenistan:"],"category":"flags"},":flag_tn:":{"uc_base":"1f1f9-1f1f3","uc_output":"1f1f9-1f1f3","uc_match":"1f1f9-1f1f3","uc_greedy":"1f1f9-1f1f3","shortnames":[":tn:"],"category":"flags"},":flag_to:":{"uc_base":"1f1f9-1f1f4","uc_output":"1f1f9-1f1f4","uc_match":"1f1f9-1f1f4","uc_greedy":"1f1f9-1f1f4","shortnames":[":to:"],"category":"flags"},":flag_tr:":{"uc_base":"1f1f9-1f1f7","uc_output":"1f1f9-1f1f7","uc_match":"1f1f9-1f1f7","uc_greedy":"1f1f9-1f1f7","shortnames":[":tr:"],"category":"flags"},":flag_tt:":{"uc_base":"1f1f9-1f1f9","uc_output":"1f1f9-1f1f9","uc_match":"1f1f9-1f1f9","uc_greedy":"1f1f9-1f1f9","shortnames":[":tt:"],"category":"flags"},":flag_tv:":{"uc_base":"1f1f9-1f1fb","uc_output":"1f1f9-1f1fb","uc_match":"1f1f9-1f1fb","uc_greedy":"1f1f9-1f1fb","shortnames":[":tuvalu:"],"category":"flags"},":flag_tw:":{"uc_base":"1f1f9-1f1fc","uc_output":"1f1f9-1f1fc","uc_match":"1f1f9-1f1fc","uc_greedy":"1f1f9-1f1fc","shortnames":[":tw:"],"category":"flags"},":flag_tz:":{"uc_base":"1f1f9-1f1ff","uc_output":"1f1f9-1f1ff","uc_match":"1f1f9-1f1ff","uc_greedy":"1f1f9-1f1ff","shortnames":[":tz:"],"category":"flags"},":flag_ua:":{"uc_base":"1f1fa-1f1e6","uc_output":"1f1fa-1f1e6","uc_match":"1f1fa-1f1e6","uc_greedy":"1f1fa-1f1e6","shortnames":[":ua:"],"category":"flags"},":flag_ug:":{"uc_base":"1f1fa-1f1ec","uc_output":"1f1fa-1f1ec","uc_match":"1f1fa-1f1ec","uc_greedy":"1f1fa-1f1ec","shortnames":[":ug:"],"category":"flags"},":flag_um:":{"uc_base":"1f1fa-1f1f2","uc_output":"1f1fa-1f1f2","uc_match":"1f1fa-1f1f2","uc_greedy":"1f1fa-1f1f2","shortnames":[":um:"],"category":"flags"},":flag_us:":{"uc_base":"1f1fa-1f1f8","uc_output":"1f1fa-1f1f8","uc_match":"1f1fa-1f1f8","uc_greedy":"1f1fa-1f1f8","shortnames":[":us:"],"category":"flags"},":flag_uy:":{"uc_base":"1f1fa-1f1fe","uc_output":"1f1fa-1f1fe","uc_match":"1f1fa-1f1fe","uc_greedy":"1f1fa-1f1fe","shortnames":[":uy:"],"category":"flags"},":flag_uz:":{"uc_base":"1f1fa-1f1ff","uc_output":"1f1fa-1f1ff","uc_match":"1f1fa-1f1ff","uc_greedy":"1f1fa-1f1ff","shortnames":[":uz:"],"category":"flags"},":flag_va:":{"uc_base":"1f1fb-1f1e6","uc_output":"1f1fb-1f1e6","uc_match":"1f1fb-1f1e6","uc_greedy":"1f1fb-1f1e6","shortnames":[":va:"],"category":"flags"},":flag_vc:":{"uc_base":"1f1fb-1f1e8","uc_output":"1f1fb-1f1e8","uc_match":"1f1fb-1f1e8","uc_greedy":"1f1fb-1f1e8","shortnames":[":vc:"],"category":"flags"},":flag_ve:":{"uc_base":"1f1fb-1f1ea","uc_output":"1f1fb-1f1ea","uc_match":"1f1fb-1f1ea","uc_greedy":"1f1fb-1f1ea","shortnames":[":ve:"],"category":"flags"},":flag_vg:":{"uc_base":"1f1fb-1f1ec","uc_output":"1f1fb-1f1ec","uc_match":"1f1fb-1f1ec","uc_greedy":"1f1fb-1f1ec","shortnames":[":vg:"],"category":"flags"},":flag_vi:":{"uc_base":"1f1fb-1f1ee","uc_output":"1f1fb-1f1ee","uc_match":"1f1fb-1f1ee","uc_greedy":"1f1fb-1f1ee","shortnames":[":vi:"],"category":"flags"},":flag_vn:":{"uc_base":"1f1fb-1f1f3","uc_output":"1f1fb-1f1f3","uc_match":"1f1fb-1f1f3","uc_greedy":"1f1fb-1f1f3","shortnames":[":vn:"],"category":"flags"},":flag_vu:":{"uc_base":"1f1fb-1f1fa","uc_output":"1f1fb-1f1fa","uc_match":"1f1fb-1f1fa","uc_greedy":"1f1fb-1f1fa","shortnames":[":vu:"],"category":"flags"},":flag_wf:":{"uc_base":"1f1fc-1f1eb","uc_output":"1f1fc-1f1eb","uc_match":"1f1fc-1f1eb","uc_greedy":"1f1fc-1f1eb","shortnames":[":wf:"],"category":"flags"},":flag_ws:":{"uc_base":"1f1fc-1f1f8","uc_output":"1f1fc-1f1f8","uc_match":"1f1fc-1f1f8","uc_greedy":"1f1fc-1f1f8","shortnames":[":ws:"],"category":"flags"},":flag_xk:":{"uc_base":"1f1fd-1f1f0","uc_output":"1f1fd-1f1f0","uc_match":"1f1fd-1f1f0","uc_greedy":"1f1fd-1f1f0","shortnames":[":xk:"],"category":"flags"},":flag_ye:":{"uc_base":"1f1fe-1f1ea","uc_output":"1f1fe-1f1ea","uc_match":"1f1fe-1f1ea","uc_greedy":"1f1fe-1f1ea","shortnames":[":ye:"],"category":"flags"},":flag_yt:":{"uc_base":"1f1fe-1f1f9","uc_output":"1f1fe-1f1f9","uc_match":"1f1fe-1f1f9","uc_greedy":"1f1fe-1f1f9","shortnames":[":yt:"],"category":"flags"},":flag_za:":{"uc_base":"1f1ff-1f1e6","uc_output":"1f1ff-1f1e6","uc_match":"1f1ff-1f1e6","uc_greedy":"1f1ff-1f1e6","shortnames":[":za:"],"category":"flags"},":flag_zm:":{"uc_base":"1f1ff-1f1f2","uc_output":"1f1ff-1f1f2","uc_match":"1f1ff-1f1f2","uc_greedy":"1f1ff-1f1f2","shortnames":[":zm:"],"category":"flags"},":flag_zw:":{"uc_base":"1f1ff-1f1fc","uc_output":"1f1ff-1f1fc","uc_match":"1f1ff-1f1fc","uc_greedy":"1f1ff-1f1fc","shortnames":[":zw:"],"category":"flags"},":girl_tone1:":{"uc_base":"1f467-1f3fb","uc_output":"1f467-1f3fb","uc_match":"1f467-1f3fb","uc_greedy":"1f467-1f3fb","shortnames":[],"category":"people"},":girl_tone2:":{"uc_base":"1f467-1f3fc","uc_output":"1f467-1f3fc","uc_match":"1f467-1f3fc","uc_greedy":"1f467-1f3fc","shortnames":[],"category":"people"},":girl_tone3:":{"uc_base":"1f467-1f3fd","uc_output":"1f467-1f3fd","uc_match":"1f467-1f3fd","uc_greedy":"1f467-1f3fd","shortnames":[],"category":"people"},":girl_tone4:":{"uc_base":"1f467-1f3fe","uc_output":"1f467-1f3fe","uc_match":"1f467-1f3fe","uc_greedy":"1f467-1f3fe","shortnames":[],"category":"people"},":girl_tone5:":{"uc_base":"1f467-1f3ff","uc_output":"1f467-1f3ff","uc_match":"1f467-1f3ff","uc_greedy":"1f467-1f3ff","shortnames":[],"category":"people"},":guard_tone1:":{"uc_base":"1f482-1f3fb","uc_output":"1f482-1f3fb","uc_match":"1f482-1f3fb","uc_greedy":"1f482-1f3fb","shortnames":[":guardsman_tone1:"],"category":"people"},":guard_tone2:":{"uc_base":"1f482-1f3fc","uc_output":"1f482-1f3fc","uc_match":"1f482-1f3fc","uc_greedy":"1f482-1f3fc","shortnames":[":guardsman_tone2:"],"category":"people"},":guard_tone3:":{"uc_base":"1f482-1f3fd","uc_output":"1f482-1f3fd","uc_match":"1f482-1f3fd","uc_greedy":"1f482-1f3fd","shortnames":[":guardsman_tone3:"],"category":"people"},":guard_tone4:":{"uc_base":"1f482-1f3fe","uc_output":"1f482-1f3fe","uc_match":"1f482-1f3fe","uc_greedy":"1f482-1f3fe","shortnames":[":guardsman_tone4:"],"category":"people"},":guard_tone5:":{"uc_base":"1f482-1f3ff","uc_output":"1f482-1f3ff","uc_match":"1f482-1f3ff","uc_greedy":"1f482-1f3ff","shortnames":[":guardsman_tone5:"],"category":"people"},":hand_splayed_tone1:":{"uc_base":"1f590-1f3fb","uc_output":"1f590-1f3fb","uc_match":"1f590-fe0f-1f3fb","uc_greedy":"1f590-fe0f-1f3fb","shortnames":[":raised_hand_with_fingers_splayed_tone1:"],"category":"people"},":hand_splayed_tone2:":{"uc_base":"1f590-1f3fc","uc_output":"1f590-1f3fc","uc_match":"1f590-fe0f-1f3fc","uc_greedy":"1f590-fe0f-1f3fc","shortnames":[":raised_hand_with_fingers_splayed_tone2:"],"category":"people"},":hand_splayed_tone3:":{"uc_base":"1f590-1f3fd","uc_output":"1f590-1f3fd","uc_match":"1f590-fe0f-1f3fd","uc_greedy":"1f590-fe0f-1f3fd","shortnames":[":raised_hand_with_fingers_splayed_tone3:"],"category":"people"},":hand_splayed_tone4:":{"uc_base":"1f590-1f3fe","uc_output":"1f590-1f3fe","uc_match":"1f590-fe0f-1f3fe","uc_greedy":"1f590-fe0f-1f3fe","shortnames":[":raised_hand_with_fingers_splayed_tone4:"],"category":"people"},":hand_splayed_tone5:":{"uc_base":"1f590-1f3ff","uc_output":"1f590-1f3ff","uc_match":"1f590-fe0f-1f3ff","uc_greedy":"1f590-fe0f-1f3ff","shortnames":[":raised_hand_with_fingers_splayed_tone5:"],"category":"people"},":horse_racing_tone1:":{"uc_base":"1f3c7-1f3fb","uc_output":"1f3c7-1f3fb","uc_match":"1f3c7-1f3fb","uc_greedy":"1f3c7-1f3fb","shortnames":[],"category":"activity"},":horse_racing_tone2:":{"uc_base":"1f3c7-1f3fc","uc_output":"1f3c7-1f3fc","uc_match":"1f3c7-1f3fc","uc_greedy":"1f3c7-1f3fc","shortnames":[],"category":"activity"},":horse_racing_tone3:":{"uc_base":"1f3c7-1f3fd","uc_output":"1f3c7-1f3fd","uc_match":"1f3c7-1f3fd","uc_greedy":"1f3c7-1f3fd","shortnames":[],"category":"activity"},":horse_racing_tone4:":{"uc_base":"1f3c7-1f3fe","uc_output":"1f3c7-1f3fe","uc_match":"1f3c7-1f3fe","uc_greedy":"1f3c7-1f3fe","shortnames":[],"category":"activity"},":horse_racing_tone5:":{"uc_base":"1f3c7-1f3ff","uc_output":"1f3c7-1f3ff","uc_match":"1f3c7-1f3ff","uc_greedy":"1f3c7-1f3ff","shortnames":[],"category":"activity"},":left_facing_fist_tone1:":{"uc_base":"1f91b-1f3fb","uc_output":"1f91b-1f3fb","uc_match":"1f91b-1f3fb","uc_greedy":"1f91b-1f3fb","shortnames":[":left_fist_tone1:"],"category":"people"},":left_facing_fist_tone2:":{"uc_base":"1f91b-1f3fc","uc_output":"1f91b-1f3fc","uc_match":"1f91b-1f3fc","uc_greedy":"1f91b-1f3fc","shortnames":[":left_fist_tone2:"],"category":"people"},":left_facing_fist_tone3:":{"uc_base":"1f91b-1f3fd","uc_output":"1f91b-1f3fd","uc_match":"1f91b-1f3fd","uc_greedy":"1f91b-1f3fd","shortnames":[":left_fist_tone3:"],"category":"people"},":left_facing_fist_tone4:":{"uc_base":"1f91b-1f3fe","uc_output":"1f91b-1f3fe","uc_match":"1f91b-1f3fe","uc_greedy":"1f91b-1f3fe","shortnames":[":left_fist_tone4:"],"category":"people"},":left_facing_fist_tone5:":{"uc_base":"1f91b-1f3ff","uc_output":"1f91b-1f3ff","uc_match":"1f91b-1f3ff","uc_greedy":"1f91b-1f3ff","shortnames":[":left_fist_tone5:"],"category":"people"},":love_you_gesture_tone1:":{"uc_base":"1f91f-1f3fb","uc_output":"1f91f-1f3fb","uc_match":"1f91f-1f3fb","uc_greedy":"1f91f-1f3fb","shortnames":[":love_you_gesture_light_skin_tone:"],"category":"people"},":love_you_gesture_tone2:":{"uc_base":"1f91f-1f3fc","uc_output":"1f91f-1f3fc","uc_match":"1f91f-1f3fc","uc_greedy":"1f91f-1f3fc","shortnames":[":love_you_gesture_medium_light_skin_tone:"],"category":"people"},":love_you_gesture_tone3:":{"uc_base":"1f91f-1f3fd","uc_output":"1f91f-1f3fd","uc_match":"1f91f-1f3fd","uc_greedy":"1f91f-1f3fd","shortnames":[":love_you_gesture_medium_skin_tone:"],"category":"people"},":love_you_gesture_tone4:":{"uc_base":"1f91f-1f3fe","uc_output":"1f91f-1f3fe","uc_match":"1f91f-1f3fe","uc_greedy":"1f91f-1f3fe","shortnames":[":love_you_gesture_medium_dark_skin_tone:"],"category":"people"},":love_you_gesture_tone5:":{"uc_base":"1f91f-1f3ff","uc_output":"1f91f-1f3ff","uc_match":"1f91f-1f3ff","uc_greedy":"1f91f-1f3ff","shortnames":[":love_you_gesture_dark_skin_tone:"],"category":"people"},":mage_tone1:":{"uc_base":"1f9d9-1f3fb","uc_output":"1f9d9-1f3fb","uc_match":"1f9d9-1f3fb","uc_greedy":"1f9d9-1f3fb","shortnames":[":mage_light_skin_tone:"],"category":"people"},":mage_tone2:":{"uc_base":"1f9d9-1f3fc","uc_output":"1f9d9-1f3fc","uc_match":"1f9d9-1f3fc","uc_greedy":"1f9d9-1f3fc","shortnames":[":mage_medium_light_skin_tone:"],"category":"people"},":mage_tone3:":{"uc_base":"1f9d9-1f3fd","uc_output":"1f9d9-1f3fd","uc_match":"1f9d9-1f3fd","uc_greedy":"1f9d9-1f3fd","shortnames":[":mage_medium_skin_tone:"],"category":"people"},":mage_tone4:":{"uc_base":"1f9d9-1f3fe","uc_output":"1f9d9-1f3fe","uc_match":"1f9d9-1f3fe","uc_greedy":"1f9d9-1f3fe","shortnames":[":mage_medium_dark_skin_tone:"],"category":"people"},":mage_tone5:":{"uc_base":"1f9d9-1f3ff","uc_output":"1f9d9-1f3ff","uc_match":"1f9d9-1f3ff","uc_greedy":"1f9d9-1f3ff","shortnames":[":mage_dark_skin_tone:"],"category":"people"},":man_dancing_tone1:":{"uc_base":"1f57a-1f3fb","uc_output":"1f57a-1f3fb","uc_match":"1f57a-1f3fb","uc_greedy":"1f57a-1f3fb","shortnames":[":male_dancer_tone1:"],"category":"people"},":man_dancing_tone2:":{"uc_base":"1f57a-1f3fc","uc_output":"1f57a-1f3fc","uc_match":"1f57a-1f3fc","uc_greedy":"1f57a-1f3fc","shortnames":[":male_dancer_tone2:"],"category":"people"},":man_dancing_tone3:":{"uc_base":"1f57a-1f3fd","uc_output":"1f57a-1f3fd","uc_match":"1f57a-1f3fd","uc_greedy":"1f57a-1f3fd","shortnames":[":male_dancer_tone3:"],"category":"people"},":man_dancing_tone4:":{"uc_base":"1f57a-1f3fe","uc_output":"1f57a-1f3fe","uc_match":"1f57a-1f3fe","uc_greedy":"1f57a-1f3fe","shortnames":[":male_dancer_tone4:"],"category":"people"},":man_dancing_tone5:":{"uc_base":"1f57a-1f3ff","uc_output":"1f57a-1f3ff","uc_match":"1f57a-1f3ff","uc_greedy":"1f57a-1f3ff","shortnames":[":male_dancer_tone5:"],"category":"people"},":man_in_business_suit_levitating_tone1:":{"uc_base":"1f574-1f3fb","uc_output":"1f574-1f3fb","uc_match":"1f574-fe0f-1f3fb","uc_greedy":"1f574-fe0f-1f3fb","shortnames":[":man_in_business_suit_levitating_light_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone2:":{"uc_base":"1f574-1f3fc","uc_output":"1f574-1f3fc","uc_match":"1f574-fe0f-1f3fc","uc_greedy":"1f574-fe0f-1f3fc","shortnames":[":man_in_business_suit_levitating_medium_light_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone3:":{"uc_base":"1f574-1f3fd","uc_output":"1f574-1f3fd","uc_match":"1f574-fe0f-1f3fd","uc_greedy":"1f574-fe0f-1f3fd","shortnames":[":man_in_business_suit_levitating_medium_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone4:":{"uc_base":"1f574-1f3fe","uc_output":"1f574-1f3fe","uc_match":"1f574-fe0f-1f3fe","uc_greedy":"1f574-fe0f-1f3fe","shortnames":[":man_in_business_suit_levitating_medium_dark_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone5:":{"uc_base":"1f574-1f3ff","uc_output":"1f574-1f3ff","uc_match":"1f574-fe0f-1f3ff","uc_greedy":"1f574-fe0f-1f3ff","shortnames":[":man_in_business_suit_levitating_dark_skin_tone:"],"category":"people"},":man_in_tuxedo_tone1:":{"uc_base":"1f935-1f3fb","uc_output":"1f935-1f3fb","uc_match":"1f935-1f3fb","uc_greedy":"1f935-1f3fb","shortnames":[":tuxedo_tone1:"],"category":"people"},":man_in_tuxedo_tone2:":{"uc_base":"1f935-1f3fc","uc_output":"1f935-1f3fc","uc_match":"1f935-1f3fc","uc_greedy":"1f935-1f3fc","shortnames":[":tuxedo_tone2:"],"category":"people"},":man_in_tuxedo_tone3:":{"uc_base":"1f935-1f3fd","uc_output":"1f935-1f3fd","uc_match":"1f935-1f3fd","uc_greedy":"1f935-1f3fd","shortnames":[":tuxedo_tone3:"],"category":"people"},":man_in_tuxedo_tone4:":{"uc_base":"1f935-1f3fe","uc_output":"1f935-1f3fe","uc_match":"1f935-1f3fe","uc_greedy":"1f935-1f3fe","shortnames":[":tuxedo_tone4:"],"category":"people"},":man_in_tuxedo_tone5:":{"uc_base":"1f935-1f3ff","uc_output":"1f935-1f3ff","uc_match":"1f935-1f3ff","uc_greedy":"1f935-1f3ff","shortnames":[":tuxedo_tone5:"],"category":"people"},":man_tone1:":{"uc_base":"1f468-1f3fb","uc_output":"1f468-1f3fb","uc_match":"1f468-1f3fb","uc_greedy":"1f468-1f3fb","shortnames":[],"category":"people"},":man_tone2:":{"uc_base":"1f468-1f3fc","uc_output":"1f468-1f3fc","uc_match":"1f468-1f3fc","uc_greedy":"1f468-1f3fc","shortnames":[],"category":"people"},":man_tone3:":{"uc_base":"1f468-1f3fd","uc_output":"1f468-1f3fd","uc_match":"1f468-1f3fd","uc_greedy":"1f468-1f3fd","shortnames":[],"category":"people"},":man_tone4:":{"uc_base":"1f468-1f3fe","uc_output":"1f468-1f3fe","uc_match":"1f468-1f3fe","uc_greedy":"1f468-1f3fe","shortnames":[],"category":"people"},":man_tone5:":{"uc_base":"1f468-1f3ff","uc_output":"1f468-1f3ff","uc_match":"1f468-1f3ff","uc_greedy":"1f468-1f3ff","shortnames":[],"category":"people"},":man_with_chinese_cap_tone1:":{"uc_base":"1f472-1f3fb","uc_output":"1f472-1f3fb","uc_match":"1f472-1f3fb","uc_greedy":"1f472-1f3fb","shortnames":[":man_with_gua_pi_mao_tone1:"],"category":"people"},":man_with_chinese_cap_tone2:":{"uc_base":"1f472-1f3fc","uc_output":"1f472-1f3fc","uc_match":"1f472-1f3fc","uc_greedy":"1f472-1f3fc","shortnames":[":man_with_gua_pi_mao_tone2:"],"category":"people"},":man_with_chinese_cap_tone3:":{"uc_base":"1f472-1f3fd","uc_output":"1f472-1f3fd","uc_match":"1f472-1f3fd","uc_greedy":"1f472-1f3fd","shortnames":[":man_with_gua_pi_mao_tone3:"],"category":"people"},":man_with_chinese_cap_tone4:":{"uc_base":"1f472-1f3fe","uc_output":"1f472-1f3fe","uc_match":"1f472-1f3fe","uc_greedy":"1f472-1f3fe","shortnames":[":man_with_gua_pi_mao_tone4:"],"category":"people"},":man_with_chinese_cap_tone5:":{"uc_base":"1f472-1f3ff","uc_output":"1f472-1f3ff","uc_match":"1f472-1f3ff","uc_greedy":"1f472-1f3ff","shortnames":[":man_with_gua_pi_mao_tone5:"],"category":"people"},":merperson_tone1:":{"uc_base":"1f9dc-1f3fb","uc_output":"1f9dc-1f3fb","uc_match":"1f9dc-1f3fb","uc_greedy":"1f9dc-1f3fb","shortnames":[":merperson_light_skin_tone:"],"category":"people"},":merperson_tone2:":{"uc_base":"1f9dc-1f3fc","uc_output":"1f9dc-1f3fc","uc_match":"1f9dc-1f3fc","uc_greedy":"1f9dc-1f3fc","shortnames":[":merperson_medium_light_skin_tone:"],"category":"people"},":merperson_tone3:":{"uc_base":"1f9dc-1f3fd","uc_output":"1f9dc-1f3fd","uc_match":"1f9dc-1f3fd","uc_greedy":"1f9dc-1f3fd","shortnames":[":merperson_medium_skin_tone:"],"category":"people"},":merperson_tone4:":{"uc_base":"1f9dc-1f3fe","uc_output":"1f9dc-1f3fe","uc_match":"1f9dc-1f3fe","uc_greedy":"1f9dc-1f3fe","shortnames":[":merperson_medium_dark_skin_tone:"],"category":"people"},":merperson_tone5:":{"uc_base":"1f9dc-1f3ff","uc_output":"1f9dc-1f3ff","uc_match":"1f9dc-1f3ff","uc_greedy":"1f9dc-1f3ff","shortnames":[":merperson_dark_skin_tone:"],"category":"people"},":metal_tone1:":{"uc_base":"1f918-1f3fb","uc_output":"1f918-1f3fb","uc_match":"1f918-1f3fb","uc_greedy":"1f918-1f3fb","shortnames":[":sign_of_the_horns_tone1:"],"category":"people"},":metal_tone2:":{"uc_base":"1f918-1f3fc","uc_output":"1f918-1f3fc","uc_match":"1f918-1f3fc","uc_greedy":"1f918-1f3fc","shortnames":[":sign_of_the_horns_tone2:"],"category":"people"},":metal_tone3:":{"uc_base":"1f918-1f3fd","uc_output":"1f918-1f3fd","uc_match":"1f918-1f3fd","uc_greedy":"1f918-1f3fd","shortnames":[":sign_of_the_horns_tone3:"],"category":"people"},":metal_tone4:":{"uc_base":"1f918-1f3fe","uc_output":"1f918-1f3fe","uc_match":"1f918-1f3fe","uc_greedy":"1f918-1f3fe","shortnames":[":sign_of_the_horns_tone4:"],"category":"people"},":metal_tone5:":{"uc_base":"1f918-1f3ff","uc_output":"1f918-1f3ff","uc_match":"1f918-1f3ff","uc_greedy":"1f918-1f3ff","shortnames":[":sign_of_the_horns_tone5:"],"category":"people"},":middle_finger_tone1:":{"uc_base":"1f595-1f3fb","uc_output":"1f595-1f3fb","uc_match":"1f595-1f3fb","uc_greedy":"1f595-1f3fb","shortnames":[":reversed_hand_with_middle_finger_extended_tone1:"],"category":"people"},":middle_finger_tone2:":{"uc_base":"1f595-1f3fc","uc_output":"1f595-1f3fc","uc_match":"1f595-1f3fc","uc_greedy":"1f595-1f3fc","shortnames":[":reversed_hand_with_middle_finger_extended_tone2:"],"category":"people"},":middle_finger_tone3:":{"uc_base":"1f595-1f3fd","uc_output":"1f595-1f3fd","uc_match":"1f595-1f3fd","uc_greedy":"1f595-1f3fd","shortnames":[":reversed_hand_with_middle_finger_extended_tone3:"],"category":"people"},":middle_finger_tone4:":{"uc_base":"1f595-1f3fe","uc_output":"1f595-1f3fe","uc_match":"1f595-1f3fe","uc_greedy":"1f595-1f3fe","shortnames":[":reversed_hand_with_middle_finger_extended_tone4:"],"category":"people"},":middle_finger_tone5:":{"uc_base":"1f595-1f3ff","uc_output":"1f595-1f3ff","uc_match":"1f595-1f3ff","uc_greedy":"1f595-1f3ff","shortnames":[":reversed_hand_with_middle_finger_extended_tone5:"],"category":"people"},":mrs_claus_tone1:":{"uc_base":"1f936-1f3fb","uc_output":"1f936-1f3fb","uc_match":"1f936-1f3fb","uc_greedy":"1f936-1f3fb","shortnames":[":mother_christmas_tone1:"],"category":"people"},":mrs_claus_tone2:":{"uc_base":"1f936-1f3fc","uc_output":"1f936-1f3fc","uc_match":"1f936-1f3fc","uc_greedy":"1f936-1f3fc","shortnames":[":mother_christmas_tone2:"],"category":"people"},":mrs_claus_tone3:":{"uc_base":"1f936-1f3fd","uc_output":"1f936-1f3fd","uc_match":"1f936-1f3fd","uc_greedy":"1f936-1f3fd","shortnames":[":mother_christmas_tone3:"],"category":"people"},":mrs_claus_tone4:":{"uc_base":"1f936-1f3fe","uc_output":"1f936-1f3fe","uc_match":"1f936-1f3fe","uc_greedy":"1f936-1f3fe","shortnames":[":mother_christmas_tone4:"],"category":"people"},":mrs_claus_tone5:":{"uc_base":"1f936-1f3ff","uc_output":"1f936-1f3ff","uc_match":"1f936-1f3ff","uc_greedy":"1f936-1f3ff","shortnames":[":mother_christmas_tone5:"],"category":"people"},":muscle_tone1:":{"uc_base":"1f4aa-1f3fb","uc_output":"1f4aa-1f3fb","uc_match":"1f4aa-1f3fb","uc_greedy":"1f4aa-1f3fb","shortnames":[],"category":"people"},":muscle_tone2:":{"uc_base":"1f4aa-1f3fc","uc_output":"1f4aa-1f3fc","uc_match":"1f4aa-1f3fc","uc_greedy":"1f4aa-1f3fc","shortnames":[],"category":"people"},":muscle_tone3:":{"uc_base":"1f4aa-1f3fd","uc_output":"1f4aa-1f3fd","uc_match":"1f4aa-1f3fd","uc_greedy":"1f4aa-1f3fd","shortnames":[],"category":"people"},":muscle_tone4:":{"uc_base":"1f4aa-1f3fe","uc_output":"1f4aa-1f3fe","uc_match":"1f4aa-1f3fe","uc_greedy":"1f4aa-1f3fe","shortnames":[],"category":"people"},":muscle_tone5:":{"uc_base":"1f4aa-1f3ff","uc_output":"1f4aa-1f3ff","uc_match":"1f4aa-1f3ff","uc_greedy":"1f4aa-1f3ff","shortnames":[],"category":"people"},":nail_care_tone1:":{"uc_base":"1f485-1f3fb","uc_output":"1f485-1f3fb","uc_match":"1f485-1f3fb","uc_greedy":"1f485-1f3fb","shortnames":[],"category":"people"},":nail_care_tone2:":{"uc_base":"1f485-1f3fc","uc_output":"1f485-1f3fc","uc_match":"1f485-1f3fc","uc_greedy":"1f485-1f3fc","shortnames":[],"category":"people"},":nail_care_tone3:":{"uc_base":"1f485-1f3fd","uc_output":"1f485-1f3fd","uc_match":"1f485-1f3fd","uc_greedy":"1f485-1f3fd","shortnames":[],"category":"people"},":nail_care_tone4:":{"uc_base":"1f485-1f3fe","uc_output":"1f485-1f3fe","uc_match":"1f485-1f3fe","uc_greedy":"1f485-1f3fe","shortnames":[],"category":"people"},":nail_care_tone5:":{"uc_base":"1f485-1f3ff","uc_output":"1f485-1f3ff","uc_match":"1f485-1f3ff","uc_greedy":"1f485-1f3ff","shortnames":[],"category":"people"},":nose_tone1:":{"uc_base":"1f443-1f3fb","uc_output":"1f443-1f3fb","uc_match":"1f443-1f3fb","uc_greedy":"1f443-1f3fb","shortnames":[],"category":"people"},":nose_tone2:":{"uc_base":"1f443-1f3fc","uc_output":"1f443-1f3fc","uc_match":"1f443-1f3fc","uc_greedy":"1f443-1f3fc","shortnames":[],"category":"people"},":nose_tone3:":{"uc_base":"1f443-1f3fd","uc_output":"1f443-1f3fd","uc_match":"1f443-1f3fd","uc_greedy":"1f443-1f3fd","shortnames":[],"category":"people"},":nose_tone4:":{"uc_base":"1f443-1f3fe","uc_output":"1f443-1f3fe","uc_match":"1f443-1f3fe","uc_greedy":"1f443-1f3fe","shortnames":[],"category":"people"},":nose_tone5:":{"uc_base":"1f443-1f3ff","uc_output":"1f443-1f3ff","uc_match":"1f443-1f3ff","uc_greedy":"1f443-1f3ff","shortnames":[],"category":"people"},":ok_hand_tone1:":{"uc_base":"1f44c-1f3fb","uc_output":"1f44c-1f3fb","uc_match":"1f44c-1f3fb","uc_greedy":"1f44c-1f3fb","shortnames":[],"category":"people"},":ok_hand_tone2:":{"uc_base":"1f44c-1f3fc","uc_output":"1f44c-1f3fc","uc_match":"1f44c-1f3fc","uc_greedy":"1f44c-1f3fc","shortnames":[],"category":"people"},":ok_hand_tone3:":{"uc_base":"1f44c-1f3fd","uc_output":"1f44c-1f3fd","uc_match":"1f44c-1f3fd","uc_greedy":"1f44c-1f3fd","shortnames":[],"category":"people"},":ok_hand_tone4:":{"uc_base":"1f44c-1f3fe","uc_output":"1f44c-1f3fe","uc_match":"1f44c-1f3fe","uc_greedy":"1f44c-1f3fe","shortnames":[],"category":"people"},":ok_hand_tone5:":{"uc_base":"1f44c-1f3ff","uc_output":"1f44c-1f3ff","uc_match":"1f44c-1f3ff","uc_greedy":"1f44c-1f3ff","shortnames":[],"category":"people"},":older_adult_tone1:":{"uc_base":"1f9d3-1f3fb","uc_output":"1f9d3-1f3fb","uc_match":"1f9d3-1f3fb","uc_greedy":"1f9d3-1f3fb","shortnames":[":older_adult_light_skin_tone:"],"category":"people"},":older_adult_tone2:":{"uc_base":"1f9d3-1f3fc","uc_output":"1f9d3-1f3fc","uc_match":"1f9d3-1f3fc","uc_greedy":"1f9d3-1f3fc","shortnames":[":older_adult_medium_light_skin_tone:"],"category":"people"},":older_adult_tone3:":{"uc_base":"1f9d3-1f3fd","uc_output":"1f9d3-1f3fd","uc_match":"1f9d3-1f3fd","uc_greedy":"1f9d3-1f3fd","shortnames":[":older_adult_medium_skin_tone:"],"category":"people"},":older_adult_tone4:":{"uc_base":"1f9d3-1f3fe","uc_output":"1f9d3-1f3fe","uc_match":"1f9d3-1f3fe","uc_greedy":"1f9d3-1f3fe","shortnames":[":older_adult_medium_dark_skin_tone:"],"category":"people"},":older_adult_tone5:":{"uc_base":"1f9d3-1f3ff","uc_output":"1f9d3-1f3ff","uc_match":"1f9d3-1f3ff","uc_greedy":"1f9d3-1f3ff","shortnames":[":older_adult_dark_skin_tone:"],"category":"people"},":older_man_tone1:":{"uc_base":"1f474-1f3fb","uc_output":"1f474-1f3fb","uc_match":"1f474-1f3fb","uc_greedy":"1f474-1f3fb","shortnames":[],"category":"people"},":older_man_tone2:":{"uc_base":"1f474-1f3fc","uc_output":"1f474-1f3fc","uc_match":"1f474-1f3fc","uc_greedy":"1f474-1f3fc","shortnames":[],"category":"people"},":older_man_tone3:":{"uc_base":"1f474-1f3fd","uc_output":"1f474-1f3fd","uc_match":"1f474-1f3fd","uc_greedy":"1f474-1f3fd","shortnames":[],"category":"people"},":older_man_tone4:":{"uc_base":"1f474-1f3fe","uc_output":"1f474-1f3fe","uc_match":"1f474-1f3fe","uc_greedy":"1f474-1f3fe","shortnames":[],"category":"people"},":older_man_tone5:":{"uc_base":"1f474-1f3ff","uc_output":"1f474-1f3ff","uc_match":"1f474-1f3ff","uc_greedy":"1f474-1f3ff","shortnames":[],"category":"people"},":older_woman_tone1:":{"uc_base":"1f475-1f3fb","uc_output":"1f475-1f3fb","uc_match":"1f475-1f3fb","uc_greedy":"1f475-1f3fb","shortnames":[":grandma_tone1:"],"category":"people"},":older_woman_tone2:":{"uc_base":"1f475-1f3fc","uc_output":"1f475-1f3fc","uc_match":"1f475-1f3fc","uc_greedy":"1f475-1f3fc","shortnames":[":grandma_tone2:"],"category":"people"},":older_woman_tone3:":{"uc_base":"1f475-1f3fd","uc_output":"1f475-1f3fd","uc_match":"1f475-1f3fd","uc_greedy":"1f475-1f3fd","shortnames":[":grandma_tone3:"],"category":"people"},":older_woman_tone4:":{"uc_base":"1f475-1f3fe","uc_output":"1f475-1f3fe","uc_match":"1f475-1f3fe","uc_greedy":"1f475-1f3fe","shortnames":[":grandma_tone4:"],"category":"people"},":older_woman_tone5:":{"uc_base":"1f475-1f3ff","uc_output":"1f475-1f3ff","uc_match":"1f475-1f3ff","uc_greedy":"1f475-1f3ff","shortnames":[":grandma_tone5:"],"category":"people"},":open_hands_tone1:":{"uc_base":"1f450-1f3fb","uc_output":"1f450-1f3fb","uc_match":"1f450-1f3fb","uc_greedy":"1f450-1f3fb","shortnames":[],"category":"people"},":open_hands_tone2:":{"uc_base":"1f450-1f3fc","uc_output":"1f450-1f3fc","uc_match":"1f450-1f3fc","uc_greedy":"1f450-1f3fc","shortnames":[],"category":"people"},":open_hands_tone3:":{"uc_base":"1f450-1f3fd","uc_output":"1f450-1f3fd","uc_match":"1f450-1f3fd","uc_greedy":"1f450-1f3fd","shortnames":[],"category":"people"},":open_hands_tone4:":{"uc_base":"1f450-1f3fe","uc_output":"1f450-1f3fe","uc_match":"1f450-1f3fe","uc_greedy":"1f450-1f3fe","shortnames":[],"category":"people"},":open_hands_tone5:":{"uc_base":"1f450-1f3ff","uc_output":"1f450-1f3ff","uc_match":"1f450-1f3ff","uc_greedy":"1f450-1f3ff","shortnames":[],"category":"people"},":palms_up_together_tone1:":{"uc_base":"1f932-1f3fb","uc_output":"1f932-1f3fb","uc_match":"1f932-1f3fb","uc_greedy":"1f932-1f3fb","shortnames":[":palms_up_together_light_skin_tone:"],"category":"people"},":palms_up_together_tone2:":{"uc_base":"1f932-1f3fc","uc_output":"1f932-1f3fc","uc_match":"1f932-1f3fc","uc_greedy":"1f932-1f3fc","shortnames":[":palms_up_together_medium_light_skin_tone:"],"category":"people"},":palms_up_together_tone3:":{"uc_base":"1f932-1f3fd","uc_output":"1f932-1f3fd","uc_match":"1f932-1f3fd","uc_greedy":"1f932-1f3fd","shortnames":[":palms_up_together_medium_skin_tone:"],"category":"people"},":palms_up_together_tone4:":{"uc_base":"1f932-1f3fe","uc_output":"1f932-1f3fe","uc_match":"1f932-1f3fe","uc_greedy":"1f932-1f3fe","shortnames":[":palms_up_together_medium_dark_skin_tone:"],"category":"people"},":palms_up_together_tone5:":{"uc_base":"1f932-1f3ff","uc_output":"1f932-1f3ff","uc_match":"1f932-1f3ff","uc_greedy":"1f932-1f3ff","shortnames":[":palms_up_together_dark_skin_tone:"],"category":"people"},":person_biking_tone1:":{"uc_base":"1f6b4-1f3fb","uc_output":"1f6b4-1f3fb","uc_match":"1f6b4-1f3fb","uc_greedy":"1f6b4-1f3fb","shortnames":[":bicyclist_tone1:"],"category":"activity"},":person_biking_tone2:":{"uc_base":"1f6b4-1f3fc","uc_output":"1f6b4-1f3fc","uc_match":"1f6b4-1f3fc","uc_greedy":"1f6b4-1f3fc","shortnames":[":bicyclist_tone2:"],"category":"activity"},":person_biking_tone3:":{"uc_base":"1f6b4-1f3fd","uc_output":"1f6b4-1f3fd","uc_match":"1f6b4-1f3fd","uc_greedy":"1f6b4-1f3fd","shortnames":[":bicyclist_tone3:"],"category":"activity"},":person_biking_tone4:":{"uc_base":"1f6b4-1f3fe","uc_output":"1f6b4-1f3fe","uc_match":"1f6b4-1f3fe","uc_greedy":"1f6b4-1f3fe","shortnames":[":bicyclist_tone4:"],"category":"activity"},":person_biking_tone5:":{"uc_base":"1f6b4-1f3ff","uc_output":"1f6b4-1f3ff","uc_match":"1f6b4-1f3ff","uc_greedy":"1f6b4-1f3ff","shortnames":[":bicyclist_tone5:"],"category":"activity"},":person_bowing_tone1:":{"uc_base":"1f647-1f3fb","uc_output":"1f647-1f3fb","uc_match":"1f647-1f3fb","uc_greedy":"1f647-1f3fb","shortnames":[":bow_tone1:"],"category":"people"},":person_bowing_tone2:":{"uc_base":"1f647-1f3fc","uc_output":"1f647-1f3fc","uc_match":"1f647-1f3fc","uc_greedy":"1f647-1f3fc","shortnames":[":bow_tone2:"],"category":"people"},":person_bowing_tone3:":{"uc_base":"1f647-1f3fd","uc_output":"1f647-1f3fd","uc_match":"1f647-1f3fd","uc_greedy":"1f647-1f3fd","shortnames":[":bow_tone3:"],"category":"people"},":person_bowing_tone4:":{"uc_base":"1f647-1f3fe","uc_output":"1f647-1f3fe","uc_match":"1f647-1f3fe","uc_greedy":"1f647-1f3fe","shortnames":[":bow_tone4:"],"category":"people"},":person_bowing_tone5:":{"uc_base":"1f647-1f3ff","uc_output":"1f647-1f3ff","uc_match":"1f647-1f3ff","uc_greedy":"1f647-1f3ff","shortnames":[":bow_tone5:"],"category":"people"},":person_climbing_tone1:":{"uc_base":"1f9d7-1f3fb","uc_output":"1f9d7-1f3fb","uc_match":"1f9d7-1f3fb","uc_greedy":"1f9d7-1f3fb","shortnames":[":person_climbing_light_skin_tone:"],"category":"activity"},":person_climbing_tone2:":{"uc_base":"1f9d7-1f3fc","uc_output":"1f9d7-1f3fc","uc_match":"1f9d7-1f3fc","uc_greedy":"1f9d7-1f3fc","shortnames":[":person_climbing_medium_light_skin_tone:"],"category":"activity"},":person_climbing_tone3:":{"uc_base":"1f9d7-1f3fd","uc_output":"1f9d7-1f3fd","uc_match":"1f9d7-1f3fd","uc_greedy":"1f9d7-1f3fd","shortnames":[":person_climbing_medium_skin_tone:"],"category":"activity"},":person_climbing_tone4:":{"uc_base":"1f9d7-1f3fe","uc_output":"1f9d7-1f3fe","uc_match":"1f9d7-1f3fe","uc_greedy":"1f9d7-1f3fe","shortnames":[":person_climbing_medium_dark_skin_tone:"],"category":"activity"},":person_climbing_tone5:":{"uc_base":"1f9d7-1f3ff","uc_output":"1f9d7-1f3ff","uc_match":"1f9d7-1f3ff","uc_greedy":"1f9d7-1f3ff","shortnames":[":person_climbing_dark_skin_tone:"],"category":"activity"},":person_doing_cartwheel_tone1:":{"uc_base":"1f938-1f3fb","uc_output":"1f938-1f3fb","uc_match":"1f938-1f3fb","uc_greedy":"1f938-1f3fb","shortnames":[":cartwheel_tone1:"],"category":"activity"},":person_doing_cartwheel_tone2:":{"uc_base":"1f938-1f3fc","uc_output":"1f938-1f3fc","uc_match":"1f938-1f3fc","uc_greedy":"1f938-1f3fc","shortnames":[":cartwheel_tone2:"],"category":"activity"},":person_doing_cartwheel_tone3:":{"uc_base":"1f938-1f3fd","uc_output":"1f938-1f3fd","uc_match":"1f938-1f3fd","uc_greedy":"1f938-1f3fd","shortnames":[":cartwheel_tone3:"],"category":"activity"},":person_doing_cartwheel_tone4:":{"uc_base":"1f938-1f3fe","uc_output":"1f938-1f3fe","uc_match":"1f938-1f3fe","uc_greedy":"1f938-1f3fe","shortnames":[":cartwheel_tone4:"],"category":"activity"},":person_doing_cartwheel_tone5:":{"uc_base":"1f938-1f3ff","uc_output":"1f938-1f3ff","uc_match":"1f938-1f3ff","uc_greedy":"1f938-1f3ff","shortnames":[":cartwheel_tone5:"],"category":"activity"},":person_facepalming_tone1:":{"uc_base":"1f926-1f3fb","uc_output":"1f926-1f3fb","uc_match":"1f926-1f3fb","uc_greedy":"1f926-1f3fb","shortnames":[":face_palm_tone1:",":facepalm_tone1:"],"category":"people"},":person_facepalming_tone2:":{"uc_base":"1f926-1f3fc","uc_output":"1f926-1f3fc","uc_match":"1f926-1f3fc","uc_greedy":"1f926-1f3fc","shortnames":[":face_palm_tone2:",":facepalm_tone2:"],"category":"people"},":person_facepalming_tone3:":{"uc_base":"1f926-1f3fd","uc_output":"1f926-1f3fd","uc_match":"1f926-1f3fd","uc_greedy":"1f926-1f3fd","shortnames":[":face_palm_tone3:",":facepalm_tone3:"],"category":"people"},":person_facepalming_tone4:":{"uc_base":"1f926-1f3fe","uc_output":"1f926-1f3fe","uc_match":"1f926-1f3fe","uc_greedy":"1f926-1f3fe","shortnames":[":face_palm_tone4:",":facepalm_tone4:"],"category":"people"},":person_facepalming_tone5:":{"uc_base":"1f926-1f3ff","uc_output":"1f926-1f3ff","uc_match":"1f926-1f3ff","uc_greedy":"1f926-1f3ff","shortnames":[":face_palm_tone5:",":facepalm_tone5:"],"category":"people"},":person_frowning_tone1:":{"uc_base":"1f64d-1f3fb","uc_output":"1f64d-1f3fb","uc_match":"1f64d-1f3fb","uc_greedy":"1f64d-1f3fb","shortnames":[],"category":"people"},":person_frowning_tone2:":{"uc_base":"1f64d-1f3fc","uc_output":"1f64d-1f3fc","uc_match":"1f64d-1f3fc","uc_greedy":"1f64d-1f3fc","shortnames":[],"category":"people"},":person_frowning_tone3:":{"uc_base":"1f64d-1f3fd","uc_output":"1f64d-1f3fd","uc_match":"1f64d-1f3fd","uc_greedy":"1f64d-1f3fd","shortnames":[],"category":"people"},":person_frowning_tone4:":{"uc_base":"1f64d-1f3fe","uc_output":"1f64d-1f3fe","uc_match":"1f64d-1f3fe","uc_greedy":"1f64d-1f3fe","shortnames":[],"category":"people"},":person_frowning_tone5:":{"uc_base":"1f64d-1f3ff","uc_output":"1f64d-1f3ff","uc_match":"1f64d-1f3ff","uc_greedy":"1f64d-1f3ff","shortnames":[],"category":"people"},":person_gesturing_no_tone1:":{"uc_base":"1f645-1f3fb","uc_output":"1f645-1f3fb","uc_match":"1f645-1f3fb","uc_greedy":"1f645-1f3fb","shortnames":[":no_good_tone1:"],"category":"people"},":person_gesturing_no_tone2:":{"uc_base":"1f645-1f3fc","uc_output":"1f645-1f3fc","uc_match":"1f645-1f3fc","uc_greedy":"1f645-1f3fc","shortnames":[":no_good_tone2:"],"category":"people"},":person_gesturing_no_tone3:":{"uc_base":"1f645-1f3fd","uc_output":"1f645-1f3fd","uc_match":"1f645-1f3fd","uc_greedy":"1f645-1f3fd","shortnames":[":no_good_tone3:"],"category":"people"},":person_gesturing_no_tone4:":{"uc_base":"1f645-1f3fe","uc_output":"1f645-1f3fe","uc_match":"1f645-1f3fe","uc_greedy":"1f645-1f3fe","shortnames":[":no_good_tone4:"],"category":"people"},":person_gesturing_no_tone5:":{"uc_base":"1f645-1f3ff","uc_output":"1f645-1f3ff","uc_match":"1f645-1f3ff","uc_greedy":"1f645-1f3ff","shortnames":[":no_good_tone5:"],"category":"people"},":person_gesturing_ok_tone1:":{"uc_base":"1f646-1f3fb","uc_output":"1f646-1f3fb","uc_match":"1f646-1f3fb","uc_greedy":"1f646-1f3fb","shortnames":[":ok_woman_tone1:"],"category":"people"},":person_gesturing_ok_tone2:":{"uc_base":"1f646-1f3fc","uc_output":"1f646-1f3fc","uc_match":"1f646-1f3fc","uc_greedy":"1f646-1f3fc","shortnames":[":ok_woman_tone2:"],"category":"people"},":person_gesturing_ok_tone3:":{"uc_base":"1f646-1f3fd","uc_output":"1f646-1f3fd","uc_match":"1f646-1f3fd","uc_greedy":"1f646-1f3fd","shortnames":[":ok_woman_tone3:"],"category":"people"},":person_gesturing_ok_tone4:":{"uc_base":"1f646-1f3fe","uc_output":"1f646-1f3fe","uc_match":"1f646-1f3fe","uc_greedy":"1f646-1f3fe","shortnames":[":ok_woman_tone4:"],"category":"people"},":person_gesturing_ok_tone5:":{"uc_base":"1f646-1f3ff","uc_output":"1f646-1f3ff","uc_match":"1f646-1f3ff","uc_greedy":"1f646-1f3ff","shortnames":[":ok_woman_tone5:"],"category":"people"},":person_getting_haircut_tone1:":{"uc_base":"1f487-1f3fb","uc_output":"1f487-1f3fb","uc_match":"1f487-1f3fb","uc_greedy":"1f487-1f3fb","shortnames":[":haircut_tone1:"],"category":"people"},":person_getting_haircut_tone2:":{"uc_base":"1f487-1f3fc","uc_output":"1f487-1f3fc","uc_match":"1f487-1f3fc","uc_greedy":"1f487-1f3fc","shortnames":[":haircut_tone2:"],"category":"people"},":person_getting_haircut_tone3:":{"uc_base":"1f487-1f3fd","uc_output":"1f487-1f3fd","uc_match":"1f487-1f3fd","uc_greedy":"1f487-1f3fd","shortnames":[":haircut_tone3:"],"category":"people"},":person_getting_haircut_tone4:":{"uc_base":"1f487-1f3fe","uc_output":"1f487-1f3fe","uc_match":"1f487-1f3fe","uc_greedy":"1f487-1f3fe","shortnames":[":haircut_tone4:"],"category":"people"},":person_getting_haircut_tone5:":{"uc_base":"1f487-1f3ff","uc_output":"1f487-1f3ff","uc_match":"1f487-1f3ff","uc_greedy":"1f487-1f3ff","shortnames":[":haircut_tone5:"],"category":"people"},":person_getting_massage_tone1:":{"uc_base":"1f486-1f3fb","uc_output":"1f486-1f3fb","uc_match":"1f486-1f3fb","uc_greedy":"1f486-1f3fb","shortnames":[":massage_tone1:"],"category":"people"},":person_getting_massage_tone2:":{"uc_base":"1f486-1f3fc","uc_output":"1f486-1f3fc","uc_match":"1f486-1f3fc","uc_greedy":"1f486-1f3fc","shortnames":[":massage_tone2:"],"category":"people"},":person_getting_massage_tone3:":{"uc_base":"1f486-1f3fd","uc_output":"1f486-1f3fd","uc_match":"1f486-1f3fd","uc_greedy":"1f486-1f3fd","shortnames":[":massage_tone3:"],"category":"people"},":person_getting_massage_tone4:":{"uc_base":"1f486-1f3fe","uc_output":"1f486-1f3fe","uc_match":"1f486-1f3fe","uc_greedy":"1f486-1f3fe","shortnames":[":massage_tone4:"],"category":"people"},":person_getting_massage_tone5:":{"uc_base":"1f486-1f3ff","uc_output":"1f486-1f3ff","uc_match":"1f486-1f3ff","uc_greedy":"1f486-1f3ff","shortnames":[":massage_tone5:"],"category":"people"},":person_golfing_tone1:":{"uc_base":"1f3cc-1f3fb","uc_output":"1f3cc-1f3fb","uc_match":"1f3cc-fe0f-1f3fb","uc_greedy":"1f3cc-fe0f-1f3fb","shortnames":[":person_golfing_light_skin_tone:"],"category":"activity"},":person_golfing_tone2:":{"uc_base":"1f3cc-1f3fc","uc_output":"1f3cc-1f3fc","uc_match":"1f3cc-fe0f-1f3fc","uc_greedy":"1f3cc-fe0f-1f3fc","shortnames":[":person_golfing_medium_light_skin_tone:"],"category":"activity"},":person_golfing_tone3:":{"uc_base":"1f3cc-1f3fd","uc_output":"1f3cc-1f3fd","uc_match":"1f3cc-fe0f-1f3fd","uc_greedy":"1f3cc-fe0f-1f3fd","shortnames":[":person_golfing_medium_skin_tone:"],"category":"activity"},":person_golfing_tone4:":{"uc_base":"1f3cc-1f3fe","uc_output":"1f3cc-1f3fe","uc_match":"1f3cc-fe0f-1f3fe","uc_greedy":"1f3cc-fe0f-1f3fe","shortnames":[":person_golfing_medium_dark_skin_tone:"],"category":"activity"},":person_golfing_tone5:":{"uc_base":"1f3cc-1f3ff","uc_output":"1f3cc-1f3ff","uc_match":"1f3cc-fe0f-1f3ff","uc_greedy":"1f3cc-fe0f-1f3ff","shortnames":[":person_golfing_dark_skin_tone:"],"category":"activity"},":person_in_bed_tone1:":{"uc_base":"1f6cc-1f3fb","uc_output":"1f6cc-1f3fb","uc_match":"1f6cc-1f3fb","uc_greedy":"1f6cc-1f3fb","shortnames":[":person_in_bed_light_skin_tone:"],"category":"objects"},":person_in_bed_tone2:":{"uc_base":"1f6cc-1f3fc","uc_output":"1f6cc-1f3fc","uc_match":"1f6cc-1f3fc","uc_greedy":"1f6cc-1f3fc","shortnames":[":person_in_bed_medium_light_skin_tone:"],"category":"objects"},":person_in_bed_tone3:":{"uc_base":"1f6cc-1f3fd","uc_output":"1f6cc-1f3fd","uc_match":"1f6cc-1f3fd","uc_greedy":"1f6cc-1f3fd","shortnames":[":person_in_bed_medium_skin_tone:"],"category":"objects"},":person_in_bed_tone4:":{"uc_base":"1f6cc-1f3fe","uc_output":"1f6cc-1f3fe","uc_match":"1f6cc-1f3fe","uc_greedy":"1f6cc-1f3fe","shortnames":[":person_in_bed_medium_dark_skin_tone:"],"category":"objects"},":person_in_bed_tone5:":{"uc_base":"1f6cc-1f3ff","uc_output":"1f6cc-1f3ff","uc_match":"1f6cc-1f3ff","uc_greedy":"1f6cc-1f3ff","shortnames":[":person_in_bed_dark_skin_tone:"],"category":"objects"},":person_in_lotus_position_tone1:":{"uc_base":"1f9d8-1f3fb","uc_output":"1f9d8-1f3fb","uc_match":"1f9d8-1f3fb","uc_greedy":"1f9d8-1f3fb","shortnames":[":person_in_lotus_position_light_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone2:":{"uc_base":"1f9d8-1f3fc","uc_output":"1f9d8-1f3fc","uc_match":"1f9d8-1f3fc","uc_greedy":"1f9d8-1f3fc","shortnames":[":person_in_lotus_position_medium_light_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone3:":{"uc_base":"1f9d8-1f3fd","uc_output":"1f9d8-1f3fd","uc_match":"1f9d8-1f3fd","uc_greedy":"1f9d8-1f3fd","shortnames":[":person_in_lotus_position_medium_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone4:":{"uc_base":"1f9d8-1f3fe","uc_output":"1f9d8-1f3fe","uc_match":"1f9d8-1f3fe","uc_greedy":"1f9d8-1f3fe","shortnames":[":person_in_lotus_position_medium_dark_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone5:":{"uc_base":"1f9d8-1f3ff","uc_output":"1f9d8-1f3ff","uc_match":"1f9d8-1f3ff","uc_greedy":"1f9d8-1f3ff","shortnames":[":person_in_lotus_position_dark_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone1:":{"uc_base":"1f9d6-1f3fb","uc_output":"1f9d6-1f3fb","uc_match":"1f9d6-1f3fb","uc_greedy":"1f9d6-1f3fb","shortnames":[":person_in_steamy_room_light_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone2:":{"uc_base":"1f9d6-1f3fc","uc_output":"1f9d6-1f3fc","uc_match":"1f9d6-1f3fc","uc_greedy":"1f9d6-1f3fc","shortnames":[":person_in_steamy_room_medium_light_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone3:":{"uc_base":"1f9d6-1f3fd","uc_output":"1f9d6-1f3fd","uc_match":"1f9d6-1f3fd","uc_greedy":"1f9d6-1f3fd","shortnames":[":person_in_steamy_room_medium_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone4:":{"uc_base":"1f9d6-1f3fe","uc_output":"1f9d6-1f3fe","uc_match":"1f9d6-1f3fe","uc_greedy":"1f9d6-1f3fe","shortnames":[":person_in_steamy_room_medium_dark_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone5:":{"uc_base":"1f9d6-1f3ff","uc_output":"1f9d6-1f3ff","uc_match":"1f9d6-1f3ff","uc_greedy":"1f9d6-1f3ff","shortnames":[":person_in_steamy_room_dark_skin_tone:"],"category":"activity"},":person_juggling_tone1:":{"uc_base":"1f939-1f3fb","uc_output":"1f939-1f3fb","uc_match":"1f939-1f3fb","uc_greedy":"1f939-1f3fb","shortnames":[":juggling_tone1:",":juggler_tone1:"],"category":"activity"},":person_juggling_tone2:":{"uc_base":"1f939-1f3fc","uc_output":"1f939-1f3fc","uc_match":"1f939-1f3fc","uc_greedy":"1f939-1f3fc","shortnames":[":juggling_tone2:",":juggler_tone2:"],"category":"activity"},":person_juggling_tone3:":{"uc_base":"1f939-1f3fd","uc_output":"1f939-1f3fd","uc_match":"1f939-1f3fd","uc_greedy":"1f939-1f3fd","shortnames":[":juggling_tone3:",":juggler_tone3:"],"category":"activity"},":person_juggling_tone4:":{"uc_base":"1f939-1f3fe","uc_output":"1f939-1f3fe","uc_match":"1f939-1f3fe","uc_greedy":"1f939-1f3fe","shortnames":[":juggling_tone4:",":juggler_tone4:"],"category":"activity"},":person_juggling_tone5:":{"uc_base":"1f939-1f3ff","uc_output":"1f939-1f3ff","uc_match":"1f939-1f3ff","uc_greedy":"1f939-1f3ff","shortnames":[":juggling_tone5:",":juggler_tone5:"],"category":"activity"},":person_lifting_weights_tone1:":{"uc_base":"1f3cb-1f3fb","uc_output":"1f3cb-1f3fb","uc_match":"1f3cb-fe0f-1f3fb","uc_greedy":"1f3cb-fe0f-1f3fb","shortnames":[":lifter_tone1:",":weight_lifter_tone1:"],"category":"activity"},":person_lifting_weights_tone2:":{"uc_base":"1f3cb-1f3fc","uc_output":"1f3cb-1f3fc","uc_match":"1f3cb-fe0f-1f3fc","uc_greedy":"1f3cb-fe0f-1f3fc","shortnames":[":lifter_tone2:",":weight_lifter_tone2:"],"category":"activity"},":person_lifting_weights_tone3:":{"uc_base":"1f3cb-1f3fd","uc_output":"1f3cb-1f3fd","uc_match":"1f3cb-fe0f-1f3fd","uc_greedy":"1f3cb-fe0f-1f3fd","shortnames":[":lifter_tone3:",":weight_lifter_tone3:"],"category":"activity"},":person_lifting_weights_tone4:":{"uc_base":"1f3cb-1f3fe","uc_output":"1f3cb-1f3fe","uc_match":"1f3cb-fe0f-1f3fe","uc_greedy":"1f3cb-fe0f-1f3fe","shortnames":[":lifter_tone4:",":weight_lifter_tone4:"],"category":"activity"},":person_lifting_weights_tone5:":{"uc_base":"1f3cb-1f3ff","uc_output":"1f3cb-1f3ff","uc_match":"1f3cb-fe0f-1f3ff","uc_greedy":"1f3cb-fe0f-1f3ff","shortnames":[":lifter_tone5:",":weight_lifter_tone5:"],"category":"activity"},":person_mountain_biking_tone1:":{"uc_base":"1f6b5-1f3fb","uc_output":"1f6b5-1f3fb","uc_match":"1f6b5-1f3fb","uc_greedy":"1f6b5-1f3fb","shortnames":[":mountain_bicyclist_tone1:"],"category":"activity"},":person_mountain_biking_tone2:":{"uc_base":"1f6b5-1f3fc","uc_output":"1f6b5-1f3fc","uc_match":"1f6b5-1f3fc","uc_greedy":"1f6b5-1f3fc","shortnames":[":mountain_bicyclist_tone2:"],"category":"activity"},":person_mountain_biking_tone3:":{"uc_base":"1f6b5-1f3fd","uc_output":"1f6b5-1f3fd","uc_match":"1f6b5-1f3fd","uc_greedy":"1f6b5-1f3fd","shortnames":[":mountain_bicyclist_tone3:"],"category":"activity"},":person_mountain_biking_tone4:":{"uc_base":"1f6b5-1f3fe","uc_output":"1f6b5-1f3fe","uc_match":"1f6b5-1f3fe","uc_greedy":"1f6b5-1f3fe","shortnames":[":mountain_bicyclist_tone4:"],"category":"activity"},":person_mountain_biking_tone5:":{"uc_base":"1f6b5-1f3ff","uc_output":"1f6b5-1f3ff","uc_match":"1f6b5-1f3ff","uc_greedy":"1f6b5-1f3ff","shortnames":[":mountain_bicyclist_tone5:"],"category":"activity"},":person_playing_handball_tone1:":{"uc_base":"1f93e-1f3fb","uc_output":"1f93e-1f3fb","uc_match":"1f93e-1f3fb","uc_greedy":"1f93e-1f3fb","shortnames":[":handball_tone1:"],"category":"activity"},":person_playing_handball_tone2:":{"uc_base":"1f93e-1f3fc","uc_output":"1f93e-1f3fc","uc_match":"1f93e-1f3fc","uc_greedy":"1f93e-1f3fc","shortnames":[":handball_tone2:"],"category":"activity"},":person_playing_handball_tone3:":{"uc_base":"1f93e-1f3fd","uc_output":"1f93e-1f3fd","uc_match":"1f93e-1f3fd","uc_greedy":"1f93e-1f3fd","shortnames":[":handball_tone3:"],"category":"activity"},":person_playing_handball_tone4:":{"uc_base":"1f93e-1f3fe","uc_output":"1f93e-1f3fe","uc_match":"1f93e-1f3fe","uc_greedy":"1f93e-1f3fe","shortnames":[":handball_tone4:"],"category":"activity"},":person_playing_handball_tone5:":{"uc_base":"1f93e-1f3ff","uc_output":"1f93e-1f3ff","uc_match":"1f93e-1f3ff","uc_greedy":"1f93e-1f3ff","shortnames":[":handball_tone5:"],"category":"activity"},":person_playing_water_polo_tone1:":{"uc_base":"1f93d-1f3fb","uc_output":"1f93d-1f3fb","uc_match":"1f93d-1f3fb","uc_greedy":"1f93d-1f3fb","shortnames":[":water_polo_tone1:"],"category":"activity"},":person_playing_water_polo_tone2:":{"uc_base":"1f93d-1f3fc","uc_output":"1f93d-1f3fc","uc_match":"1f93d-1f3fc","uc_greedy":"1f93d-1f3fc","shortnames":[":water_polo_tone2:"],"category":"activity"},":person_playing_water_polo_tone3:":{"uc_base":"1f93d-1f3fd","uc_output":"1f93d-1f3fd","uc_match":"1f93d-1f3fd","uc_greedy":"1f93d-1f3fd","shortnames":[":water_polo_tone3:"],"category":"activity"},":person_playing_water_polo_tone4:":{"uc_base":"1f93d-1f3fe","uc_output":"1f93d-1f3fe","uc_match":"1f93d-1f3fe","uc_greedy":"1f93d-1f3fe","shortnames":[":water_polo_tone4:"],"category":"activity"},":person_playing_water_polo_tone5:":{"uc_base":"1f93d-1f3ff","uc_output":"1f93d-1f3ff","uc_match":"1f93d-1f3ff","uc_greedy":"1f93d-1f3ff","shortnames":[":water_polo_tone5:"],"category":"activity"},":person_pouting_tone1:":{"uc_base":"1f64e-1f3fb","uc_output":"1f64e-1f3fb","uc_match":"1f64e-1f3fb","uc_greedy":"1f64e-1f3fb","shortnames":[":person_with_pouting_face_tone1:"],"category":"people"},":person_pouting_tone2:":{"uc_base":"1f64e-1f3fc","uc_output":"1f64e-1f3fc","uc_match":"1f64e-1f3fc","uc_greedy":"1f64e-1f3fc","shortnames":[":person_with_pouting_face_tone2:"],"category":"people"},":person_pouting_tone3:":{"uc_base":"1f64e-1f3fd","uc_output":"1f64e-1f3fd","uc_match":"1f64e-1f3fd","uc_greedy":"1f64e-1f3fd","shortnames":[":person_with_pouting_face_tone3:"],"category":"people"},":person_pouting_tone4:":{"uc_base":"1f64e-1f3fe","uc_output":"1f64e-1f3fe","uc_match":"1f64e-1f3fe","uc_greedy":"1f64e-1f3fe","shortnames":[":person_with_pouting_face_tone4:"],"category":"people"},":person_pouting_tone5:":{"uc_base":"1f64e-1f3ff","uc_output":"1f64e-1f3ff","uc_match":"1f64e-1f3ff","uc_greedy":"1f64e-1f3ff","shortnames":[":person_with_pouting_face_tone5:"],"category":"people"},":person_raising_hand_tone1:":{"uc_base":"1f64b-1f3fb","uc_output":"1f64b-1f3fb","uc_match":"1f64b-1f3fb","uc_greedy":"1f64b-1f3fb","shortnames":[":raising_hand_tone1:"],"category":"people"},":person_raising_hand_tone2:":{"uc_base":"1f64b-1f3fc","uc_output":"1f64b-1f3fc","uc_match":"1f64b-1f3fc","uc_greedy":"1f64b-1f3fc","shortnames":[":raising_hand_tone2:"],"category":"people"},":person_raising_hand_tone3:":{"uc_base":"1f64b-1f3fd","uc_output":"1f64b-1f3fd","uc_match":"1f64b-1f3fd","uc_greedy":"1f64b-1f3fd","shortnames":[":raising_hand_tone3:"],"category":"people"},":person_raising_hand_tone4:":{"uc_base":"1f64b-1f3fe","uc_output":"1f64b-1f3fe","uc_match":"1f64b-1f3fe","uc_greedy":"1f64b-1f3fe","shortnames":[":raising_hand_tone4:"],"category":"people"},":person_raising_hand_tone5:":{"uc_base":"1f64b-1f3ff","uc_output":"1f64b-1f3ff","uc_match":"1f64b-1f3ff","uc_greedy":"1f64b-1f3ff","shortnames":[":raising_hand_tone5:"],"category":"people"},":person_rowing_boat_tone1:":{"uc_base":"1f6a3-1f3fb","uc_output":"1f6a3-1f3fb","uc_match":"1f6a3-1f3fb","uc_greedy":"1f6a3-1f3fb","shortnames":[":rowboat_tone1:"],"category":"activity"},":person_rowing_boat_tone2:":{"uc_base":"1f6a3-1f3fc","uc_output":"1f6a3-1f3fc","uc_match":"1f6a3-1f3fc","uc_greedy":"1f6a3-1f3fc","shortnames":[":rowboat_tone2:"],"category":"activity"},":person_rowing_boat_tone3:":{"uc_base":"1f6a3-1f3fd","uc_output":"1f6a3-1f3fd","uc_match":"1f6a3-1f3fd","uc_greedy":"1f6a3-1f3fd","shortnames":[":rowboat_tone3:"],"category":"activity"},":person_rowing_boat_tone4:":{"uc_base":"1f6a3-1f3fe","uc_output":"1f6a3-1f3fe","uc_match":"1f6a3-1f3fe","uc_greedy":"1f6a3-1f3fe","shortnames":[":rowboat_tone4:"],"category":"activity"},":person_rowing_boat_tone5:":{"uc_base":"1f6a3-1f3ff","uc_output":"1f6a3-1f3ff","uc_match":"1f6a3-1f3ff","uc_greedy":"1f6a3-1f3ff","shortnames":[":rowboat_tone5:"],"category":"activity"},":person_running_tone1:":{"uc_base":"1f3c3-1f3fb","uc_output":"1f3c3-1f3fb","uc_match":"1f3c3-1f3fb","uc_greedy":"1f3c3-1f3fb","shortnames":[":runner_tone1:"],"category":"people"},":person_running_tone2:":{"uc_base":"1f3c3-1f3fc","uc_output":"1f3c3-1f3fc","uc_match":"1f3c3-1f3fc","uc_greedy":"1f3c3-1f3fc","shortnames":[":runner_tone2:"],"category":"people"},":person_running_tone3:":{"uc_base":"1f3c3-1f3fd","uc_output":"1f3c3-1f3fd","uc_match":"1f3c3-1f3fd","uc_greedy":"1f3c3-1f3fd","shortnames":[":runner_tone3:"],"category":"people"},":person_running_tone4:":{"uc_base":"1f3c3-1f3fe","uc_output":"1f3c3-1f3fe","uc_match":"1f3c3-1f3fe","uc_greedy":"1f3c3-1f3fe","shortnames":[":runner_tone4:"],"category":"people"},":person_running_tone5:":{"uc_base":"1f3c3-1f3ff","uc_output":"1f3c3-1f3ff","uc_match":"1f3c3-1f3ff","uc_greedy":"1f3c3-1f3ff","shortnames":[":runner_tone5:"],"category":"people"},":person_shrugging_tone1:":{"uc_base":"1f937-1f3fb","uc_output":"1f937-1f3fb","uc_match":"1f937-1f3fb","uc_greedy":"1f937-1f3fb","shortnames":[":shrug_tone1:"],"category":"people"},":person_shrugging_tone2:":{"uc_base":"1f937-1f3fc","uc_output":"1f937-1f3fc","uc_match":"1f937-1f3fc","uc_greedy":"1f937-1f3fc","shortnames":[":shrug_tone2:"],"category":"people"},":person_shrugging_tone3:":{"uc_base":"1f937-1f3fd","uc_output":"1f937-1f3fd","uc_match":"1f937-1f3fd","uc_greedy":"1f937-1f3fd","shortnames":[":shrug_tone3:"],"category":"people"},":person_shrugging_tone4:":{"uc_base":"1f937-1f3fe","uc_output":"1f937-1f3fe","uc_match":"1f937-1f3fe","uc_greedy":"1f937-1f3fe","shortnames":[":shrug_tone4:"],"category":"people"},":person_shrugging_tone5:":{"uc_base":"1f937-1f3ff","uc_output":"1f937-1f3ff","uc_match":"1f937-1f3ff","uc_greedy":"1f937-1f3ff","shortnames":[":shrug_tone5:"],"category":"people"},":person_surfing_tone1:":{"uc_base":"1f3c4-1f3fb","uc_output":"1f3c4-1f3fb","uc_match":"1f3c4-1f3fb","uc_greedy":"1f3c4-1f3fb","shortnames":[":surfer_tone1:"],"category":"activity"},":person_surfing_tone2:":{"uc_base":"1f3c4-1f3fc","uc_output":"1f3c4-1f3fc","uc_match":"1f3c4-1f3fc","uc_greedy":"1f3c4-1f3fc","shortnames":[":surfer_tone2:"],"category":"activity"},":person_surfing_tone3:":{"uc_base":"1f3c4-1f3fd","uc_output":"1f3c4-1f3fd","uc_match":"1f3c4-1f3fd","uc_greedy":"1f3c4-1f3fd","shortnames":[":surfer_tone3:"],"category":"activity"},":person_surfing_tone4:":{"uc_base":"1f3c4-1f3fe","uc_output":"1f3c4-1f3fe","uc_match":"1f3c4-1f3fe","uc_greedy":"1f3c4-1f3fe","shortnames":[":surfer_tone4:"],"category":"activity"},":person_surfing_tone5:":{"uc_base":"1f3c4-1f3ff","uc_output":"1f3c4-1f3ff","uc_match":"1f3c4-1f3ff","uc_greedy":"1f3c4-1f3ff","shortnames":[":surfer_tone5:"],"category":"activity"},":person_swimming_tone1:":{"uc_base":"1f3ca-1f3fb","uc_output":"1f3ca-1f3fb","uc_match":"1f3ca-1f3fb","uc_greedy":"1f3ca-1f3fb","shortnames":[":swimmer_tone1:"],"category":"activity"},":person_swimming_tone2:":{"uc_base":"1f3ca-1f3fc","uc_output":"1f3ca-1f3fc","uc_match":"1f3ca-1f3fc","uc_greedy":"1f3ca-1f3fc","shortnames":[":swimmer_tone2:"],"category":"activity"},":person_swimming_tone3:":{"uc_base":"1f3ca-1f3fd","uc_output":"1f3ca-1f3fd","uc_match":"1f3ca-1f3fd","uc_greedy":"1f3ca-1f3fd","shortnames":[":swimmer_tone3:"],"category":"activity"},":person_swimming_tone4:":{"uc_base":"1f3ca-1f3fe","uc_output":"1f3ca-1f3fe","uc_match":"1f3ca-1f3fe","uc_greedy":"1f3ca-1f3fe","shortnames":[":swimmer_tone4:"],"category":"activity"},":person_swimming_tone5:":{"uc_base":"1f3ca-1f3ff","uc_output":"1f3ca-1f3ff","uc_match":"1f3ca-1f3ff","uc_greedy":"1f3ca-1f3ff","shortnames":[":swimmer_tone5:"],"category":"activity"},":person_tipping_hand_tone1:":{"uc_base":"1f481-1f3fb","uc_output":"1f481-1f3fb","uc_match":"1f481-1f3fb","uc_greedy":"1f481-1f3fb","shortnames":[":information_desk_person_tone1:"],"category":"people"},":person_tipping_hand_tone2:":{"uc_base":"1f481-1f3fc","uc_output":"1f481-1f3fc","uc_match":"1f481-1f3fc","uc_greedy":"1f481-1f3fc","shortnames":[":information_desk_person_tone2:"],"category":"people"},":person_tipping_hand_tone3:":{"uc_base":"1f481-1f3fd","uc_output":"1f481-1f3fd","uc_match":"1f481-1f3fd","uc_greedy":"1f481-1f3fd","shortnames":[":information_desk_person_tone3:"],"category":"people"},":person_tipping_hand_tone4:":{"uc_base":"1f481-1f3fe","uc_output":"1f481-1f3fe","uc_match":"1f481-1f3fe","uc_greedy":"1f481-1f3fe","shortnames":[":information_desk_person_tone4:"],"category":"people"},":person_tipping_hand_tone5:":{"uc_base":"1f481-1f3ff","uc_output":"1f481-1f3ff","uc_match":"1f481-1f3ff","uc_greedy":"1f481-1f3ff","shortnames":[":information_desk_person_tone5:"],"category":"people"},":person_walking_tone1:":{"uc_base":"1f6b6-1f3fb","uc_output":"1f6b6-1f3fb","uc_match":"1f6b6-1f3fb","uc_greedy":"1f6b6-1f3fb","shortnames":[":walking_tone1:"],"category":"people"},":person_walking_tone2:":{"uc_base":"1f6b6-1f3fc","uc_output":"1f6b6-1f3fc","uc_match":"1f6b6-1f3fc","uc_greedy":"1f6b6-1f3fc","shortnames":[":walking_tone2:"],"category":"people"},":person_walking_tone3:":{"uc_base":"1f6b6-1f3fd","uc_output":"1f6b6-1f3fd","uc_match":"1f6b6-1f3fd","uc_greedy":"1f6b6-1f3fd","shortnames":[":walking_tone3:"],"category":"people"},":person_walking_tone4:":{"uc_base":"1f6b6-1f3fe","uc_output":"1f6b6-1f3fe","uc_match":"1f6b6-1f3fe","uc_greedy":"1f6b6-1f3fe","shortnames":[":walking_tone4:"],"category":"people"},":person_walking_tone5:":{"uc_base":"1f6b6-1f3ff","uc_output":"1f6b6-1f3ff","uc_match":"1f6b6-1f3ff","uc_greedy":"1f6b6-1f3ff","shortnames":[":walking_tone5:"],"category":"people"},":person_wearing_turban_tone1:":{"uc_base":"1f473-1f3fb","uc_output":"1f473-1f3fb","uc_match":"1f473-1f3fb","uc_greedy":"1f473-1f3fb","shortnames":[":man_with_turban_tone1:"],"category":"people"},":person_wearing_turban_tone2:":{"uc_base":"1f473-1f3fc","uc_output":"1f473-1f3fc","uc_match":"1f473-1f3fc","uc_greedy":"1f473-1f3fc","shortnames":[":man_with_turban_tone2:"],"category":"people"},":person_wearing_turban_tone3:":{"uc_base":"1f473-1f3fd","uc_output":"1f473-1f3fd","uc_match":"1f473-1f3fd","uc_greedy":"1f473-1f3fd","shortnames":[":man_with_turban_tone3:"],"category":"people"},":person_wearing_turban_tone4:":{"uc_base":"1f473-1f3fe","uc_output":"1f473-1f3fe","uc_match":"1f473-1f3fe","uc_greedy":"1f473-1f3fe","shortnames":[":man_with_turban_tone4:"],"category":"people"},":person_wearing_turban_tone5:":{"uc_base":"1f473-1f3ff","uc_output":"1f473-1f3ff","uc_match":"1f473-1f3ff","uc_greedy":"1f473-1f3ff","shortnames":[":man_with_turban_tone5:"],"category":"people"},":point_down_tone1:":{"uc_base":"1f447-1f3fb","uc_output":"1f447-1f3fb","uc_match":"1f447-1f3fb","uc_greedy":"1f447-1f3fb","shortnames":[],"category":"people"},":point_down_tone2:":{"uc_base":"1f447-1f3fc","uc_output":"1f447-1f3fc","uc_match":"1f447-1f3fc","uc_greedy":"1f447-1f3fc","shortnames":[],"category":"people"},":point_down_tone3:":{"uc_base":"1f447-1f3fd","uc_output":"1f447-1f3fd","uc_match":"1f447-1f3fd","uc_greedy":"1f447-1f3fd","shortnames":[],"category":"people"},":point_down_tone4:":{"uc_base":"1f447-1f3fe","uc_output":"1f447-1f3fe","uc_match":"1f447-1f3fe","uc_greedy":"1f447-1f3fe","shortnames":[],"category":"people"},":point_down_tone5:":{"uc_base":"1f447-1f3ff","uc_output":"1f447-1f3ff","uc_match":"1f447-1f3ff","uc_greedy":"1f447-1f3ff","shortnames":[],"category":"people"},":point_left_tone1:":{"uc_base":"1f448-1f3fb","uc_output":"1f448-1f3fb","uc_match":"1f448-1f3fb","uc_greedy":"1f448-1f3fb","shortnames":[],"category":"people"},":point_left_tone2:":{"uc_base":"1f448-1f3fc","uc_output":"1f448-1f3fc","uc_match":"1f448-1f3fc","uc_greedy":"1f448-1f3fc","shortnames":[],"category":"people"},":point_left_tone3:":{"uc_base":"1f448-1f3fd","uc_output":"1f448-1f3fd","uc_match":"1f448-1f3fd","uc_greedy":"1f448-1f3fd","shortnames":[],"category":"people"},":point_left_tone4:":{"uc_base":"1f448-1f3fe","uc_output":"1f448-1f3fe","uc_match":"1f448-1f3fe","uc_greedy":"1f448-1f3fe","shortnames":[],"category":"people"},":point_left_tone5:":{"uc_base":"1f448-1f3ff","uc_output":"1f448-1f3ff","uc_match":"1f448-1f3ff","uc_greedy":"1f448-1f3ff","shortnames":[],"category":"people"},":point_right_tone1:":{"uc_base":"1f449-1f3fb","uc_output":"1f449-1f3fb","uc_match":"1f449-1f3fb","uc_greedy":"1f449-1f3fb","shortnames":[],"category":"people"},":point_right_tone2:":{"uc_base":"1f449-1f3fc","uc_output":"1f449-1f3fc","uc_match":"1f449-1f3fc","uc_greedy":"1f449-1f3fc","shortnames":[],"category":"people"},":point_right_tone3:":{"uc_base":"1f449-1f3fd","uc_output":"1f449-1f3fd","uc_match":"1f449-1f3fd","uc_greedy":"1f449-1f3fd","shortnames":[],"category":"people"},":point_right_tone4:":{"uc_base":"1f449-1f3fe","uc_output":"1f449-1f3fe","uc_match":"1f449-1f3fe","uc_greedy":"1f449-1f3fe","shortnames":[],"category":"people"},":point_right_tone5:":{"uc_base":"1f449-1f3ff","uc_output":"1f449-1f3ff","uc_match":"1f449-1f3ff","uc_greedy":"1f449-1f3ff","shortnames":[],"category":"people"},":point_up_2_tone1:":{"uc_base":"1f446-1f3fb","uc_output":"1f446-1f3fb","uc_match":"1f446-1f3fb","uc_greedy":"1f446-1f3fb","shortnames":[],"category":"people"},":point_up_2_tone2:":{"uc_base":"1f446-1f3fc","uc_output":"1f446-1f3fc","uc_match":"1f446-1f3fc","uc_greedy":"1f446-1f3fc","shortnames":[],"category":"people"},":point_up_2_tone3:":{"uc_base":"1f446-1f3fd","uc_output":"1f446-1f3fd","uc_match":"1f446-1f3fd","uc_greedy":"1f446-1f3fd","shortnames":[],"category":"people"},":point_up_2_tone4:":{"uc_base":"1f446-1f3fe","uc_output":"1f446-1f3fe","uc_match":"1f446-1f3fe","uc_greedy":"1f446-1f3fe","shortnames":[],"category":"people"},":point_up_2_tone5:":{"uc_base":"1f446-1f3ff","uc_output":"1f446-1f3ff","uc_match":"1f446-1f3ff","uc_greedy":"1f446-1f3ff","shortnames":[],"category":"people"},":police_officer_tone1:":{"uc_base":"1f46e-1f3fb","uc_output":"1f46e-1f3fb","uc_match":"1f46e-1f3fb","uc_greedy":"1f46e-1f3fb","shortnames":[":cop_tone1:"],"category":"people"},":police_officer_tone2:":{"uc_base":"1f46e-1f3fc","uc_output":"1f46e-1f3fc","uc_match":"1f46e-1f3fc","uc_greedy":"1f46e-1f3fc","shortnames":[":cop_tone2:"],"category":"people"},":police_officer_tone3:":{"uc_base":"1f46e-1f3fd","uc_output":"1f46e-1f3fd","uc_match":"1f46e-1f3fd","uc_greedy":"1f46e-1f3fd","shortnames":[":cop_tone3:"],"category":"people"},":police_officer_tone4:":{"uc_base":"1f46e-1f3fe","uc_output":"1f46e-1f3fe","uc_match":"1f46e-1f3fe","uc_greedy":"1f46e-1f3fe","shortnames":[":cop_tone4:"],"category":"people"},":police_officer_tone5:":{"uc_base":"1f46e-1f3ff","uc_output":"1f46e-1f3ff","uc_match":"1f46e-1f3ff","uc_greedy":"1f46e-1f3ff","shortnames":[":cop_tone5:"],"category":"people"},":pray_tone1:":{"uc_base":"1f64f-1f3fb","uc_output":"1f64f-1f3fb","uc_match":"1f64f-1f3fb","uc_greedy":"1f64f-1f3fb","shortnames":[],"category":"people"},":pray_tone2:":{"uc_base":"1f64f-1f3fc","uc_output":"1f64f-1f3fc","uc_match":"1f64f-1f3fc","uc_greedy":"1f64f-1f3fc","shortnames":[],"category":"people"},":pray_tone3:":{"uc_base":"1f64f-1f3fd","uc_output":"1f64f-1f3fd","uc_match":"1f64f-1f3fd","uc_greedy":"1f64f-1f3fd","shortnames":[],"category":"people"},":pray_tone4:":{"uc_base":"1f64f-1f3fe","uc_output":"1f64f-1f3fe","uc_match":"1f64f-1f3fe","uc_greedy":"1f64f-1f3fe","shortnames":[],"category":"people"},":pray_tone5:":{"uc_base":"1f64f-1f3ff","uc_output":"1f64f-1f3ff","uc_match":"1f64f-1f3ff","uc_greedy":"1f64f-1f3ff","shortnames":[],"category":"people"},":pregnant_woman_tone1:":{"uc_base":"1f930-1f3fb","uc_output":"1f930-1f3fb","uc_match":"1f930-1f3fb","uc_greedy":"1f930-1f3fb","shortnames":[":expecting_woman_tone1:"],"category":"people"},":pregnant_woman_tone2:":{"uc_base":"1f930-1f3fc","uc_output":"1f930-1f3fc","uc_match":"1f930-1f3fc","uc_greedy":"1f930-1f3fc","shortnames":[":expecting_woman_tone2:"],"category":"people"},":pregnant_woman_tone3:":{"uc_base":"1f930-1f3fd","uc_output":"1f930-1f3fd","uc_match":"1f930-1f3fd","uc_greedy":"1f930-1f3fd","shortnames":[":expecting_woman_tone3:"],"category":"people"},":pregnant_woman_tone4:":{"uc_base":"1f930-1f3fe","uc_output":"1f930-1f3fe","uc_match":"1f930-1f3fe","uc_greedy":"1f930-1f3fe","shortnames":[":expecting_woman_tone4:"],"category":"people"},":pregnant_woman_tone5:":{"uc_base":"1f930-1f3ff","uc_output":"1f930-1f3ff","uc_match":"1f930-1f3ff","uc_greedy":"1f930-1f3ff","shortnames":[":expecting_woman_tone5:"],"category":"people"},":prince_tone1:":{"uc_base":"1f934-1f3fb","uc_output":"1f934-1f3fb","uc_match":"1f934-1f3fb","uc_greedy":"1f934-1f3fb","shortnames":[],"category":"people"},":prince_tone2:":{"uc_base":"1f934-1f3fc","uc_output":"1f934-1f3fc","uc_match":"1f934-1f3fc","uc_greedy":"1f934-1f3fc","shortnames":[],"category":"people"},":prince_tone3:":{"uc_base":"1f934-1f3fd","uc_output":"1f934-1f3fd","uc_match":"1f934-1f3fd","uc_greedy":"1f934-1f3fd","shortnames":[],"category":"people"},":prince_tone4:":{"uc_base":"1f934-1f3fe","uc_output":"1f934-1f3fe","uc_match":"1f934-1f3fe","uc_greedy":"1f934-1f3fe","shortnames":[],"category":"people"},":prince_tone5:":{"uc_base":"1f934-1f3ff","uc_output":"1f934-1f3ff","uc_match":"1f934-1f3ff","uc_greedy":"1f934-1f3ff","shortnames":[],"category":"people"},":princess_tone1:":{"uc_base":"1f478-1f3fb","uc_output":"1f478-1f3fb","uc_match":"1f478-1f3fb","uc_greedy":"1f478-1f3fb","shortnames":[],"category":"people"},":princess_tone2:":{"uc_base":"1f478-1f3fc","uc_output":"1f478-1f3fc","uc_match":"1f478-1f3fc","uc_greedy":"1f478-1f3fc","shortnames":[],"category":"people"},":princess_tone3:":{"uc_base":"1f478-1f3fd","uc_output":"1f478-1f3fd","uc_match":"1f478-1f3fd","uc_greedy":"1f478-1f3fd","shortnames":[],"category":"people"},":princess_tone4:":{"uc_base":"1f478-1f3fe","uc_output":"1f478-1f3fe","uc_match":"1f478-1f3fe","uc_greedy":"1f478-1f3fe","shortnames":[],"category":"people"},":princess_tone5:":{"uc_base":"1f478-1f3ff","uc_output":"1f478-1f3ff","uc_match":"1f478-1f3ff","uc_greedy":"1f478-1f3ff","shortnames":[],"category":"people"},":punch_tone1:":{"uc_base":"1f44a-1f3fb","uc_output":"1f44a-1f3fb","uc_match":"1f44a-1f3fb","uc_greedy":"1f44a-1f3fb","shortnames":[],"category":"people"},":punch_tone2:":{"uc_base":"1f44a-1f3fc","uc_output":"1f44a-1f3fc","uc_match":"1f44a-1f3fc","uc_greedy":"1f44a-1f3fc","shortnames":[],"category":"people"},":punch_tone3:":{"uc_base":"1f44a-1f3fd","uc_output":"1f44a-1f3fd","uc_match":"1f44a-1f3fd","uc_greedy":"1f44a-1f3fd","shortnames":[],"category":"people"},":punch_tone4:":{"uc_base":"1f44a-1f3fe","uc_output":"1f44a-1f3fe","uc_match":"1f44a-1f3fe","uc_greedy":"1f44a-1f3fe","shortnames":[],"category":"people"},":punch_tone5:":{"uc_base":"1f44a-1f3ff","uc_output":"1f44a-1f3ff","uc_match":"1f44a-1f3ff","uc_greedy":"1f44a-1f3ff","shortnames":[],"category":"people"},":raised_back_of_hand_tone1:":{"uc_base":"1f91a-1f3fb","uc_output":"1f91a-1f3fb","uc_match":"1f91a-1f3fb","uc_greedy":"1f91a-1f3fb","shortnames":[":back_of_hand_tone1:"],"category":"people"},":raised_back_of_hand_tone2:":{"uc_base":"1f91a-1f3fc","uc_output":"1f91a-1f3fc","uc_match":"1f91a-1f3fc","uc_greedy":"1f91a-1f3fc","shortnames":[":back_of_hand_tone2:"],"category":"people"},":raised_back_of_hand_tone3:":{"uc_base":"1f91a-1f3fd","uc_output":"1f91a-1f3fd","uc_match":"1f91a-1f3fd","uc_greedy":"1f91a-1f3fd","shortnames":[":back_of_hand_tone3:"],"category":"people"},":raised_back_of_hand_tone4:":{"uc_base":"1f91a-1f3fe","uc_output":"1f91a-1f3fe","uc_match":"1f91a-1f3fe","uc_greedy":"1f91a-1f3fe","shortnames":[":back_of_hand_tone4:"],"category":"people"},":raised_back_of_hand_tone5:":{"uc_base":"1f91a-1f3ff","uc_output":"1f91a-1f3ff","uc_match":"1f91a-1f3ff","uc_greedy":"1f91a-1f3ff","shortnames":[":back_of_hand_tone5:"],"category":"people"},":raised_hands_tone1:":{"uc_base":"1f64c-1f3fb","uc_output":"1f64c-1f3fb","uc_match":"1f64c-1f3fb","uc_greedy":"1f64c-1f3fb","shortnames":[],"category":"people"},":raised_hands_tone2:":{"uc_base":"1f64c-1f3fc","uc_output":"1f64c-1f3fc","uc_match":"1f64c-1f3fc","uc_greedy":"1f64c-1f3fc","shortnames":[],"category":"people"},":raised_hands_tone3:":{"uc_base":"1f64c-1f3fd","uc_output":"1f64c-1f3fd","uc_match":"1f64c-1f3fd","uc_greedy":"1f64c-1f3fd","shortnames":[],"category":"people"},":raised_hands_tone4:":{"uc_base":"1f64c-1f3fe","uc_output":"1f64c-1f3fe","uc_match":"1f64c-1f3fe","uc_greedy":"1f64c-1f3fe","shortnames":[],"category":"people"},":raised_hands_tone5:":{"uc_base":"1f64c-1f3ff","uc_output":"1f64c-1f3ff","uc_match":"1f64c-1f3ff","uc_greedy":"1f64c-1f3ff","shortnames":[],"category":"people"},":right_facing_fist_tone1:":{"uc_base":"1f91c-1f3fb","uc_output":"1f91c-1f3fb","uc_match":"1f91c-1f3fb","uc_greedy":"1f91c-1f3fb","shortnames":[":right_fist_tone1:"],"category":"people"},":right_facing_fist_tone2:":{"uc_base":"1f91c-1f3fc","uc_output":"1f91c-1f3fc","uc_match":"1f91c-1f3fc","uc_greedy":"1f91c-1f3fc","shortnames":[":right_fist_tone2:"],"category":"people"},":right_facing_fist_tone3:":{"uc_base":"1f91c-1f3fd","uc_output":"1f91c-1f3fd","uc_match":"1f91c-1f3fd","uc_greedy":"1f91c-1f3fd","shortnames":[":right_fist_tone3:"],"category":"people"},":right_facing_fist_tone4:":{"uc_base":"1f91c-1f3fe","uc_output":"1f91c-1f3fe","uc_match":"1f91c-1f3fe","uc_greedy":"1f91c-1f3fe","shortnames":[":right_fist_tone4:"],"category":"people"},":right_facing_fist_tone5:":{"uc_base":"1f91c-1f3ff","uc_output":"1f91c-1f3ff","uc_match":"1f91c-1f3ff","uc_greedy":"1f91c-1f3ff","shortnames":[":right_fist_tone5:"],"category":"people"},":santa_tone1:":{"uc_base":"1f385-1f3fb","uc_output":"1f385-1f3fb","uc_match":"1f385-1f3fb","uc_greedy":"1f385-1f3fb","shortnames":[],"category":"people"},":santa_tone2:":{"uc_base":"1f385-1f3fc","uc_output":"1f385-1f3fc","uc_match":"1f385-1f3fc","uc_greedy":"1f385-1f3fc","shortnames":[],"category":"people"},":santa_tone3:":{"uc_base":"1f385-1f3fd","uc_output":"1f385-1f3fd","uc_match":"1f385-1f3fd","uc_greedy":"1f385-1f3fd","shortnames":[],"category":"people"},":santa_tone4:":{"uc_base":"1f385-1f3fe","uc_output":"1f385-1f3fe","uc_match":"1f385-1f3fe","uc_greedy":"1f385-1f3fe","shortnames":[],"category":"people"},":santa_tone5:":{"uc_base":"1f385-1f3ff","uc_output":"1f385-1f3ff","uc_match":"1f385-1f3ff","uc_greedy":"1f385-1f3ff","shortnames":[],"category":"people"},":selfie_tone1:":{"uc_base":"1f933-1f3fb","uc_output":"1f933-1f3fb","uc_match":"1f933-1f3fb","uc_greedy":"1f933-1f3fb","shortnames":[],"category":"people"},":selfie_tone2:":{"uc_base":"1f933-1f3fc","uc_output":"1f933-1f3fc","uc_match":"1f933-1f3fc","uc_greedy":"1f933-1f3fc","shortnames":[],"category":"people"},":selfie_tone3:":{"uc_base":"1f933-1f3fd","uc_output":"1f933-1f3fd","uc_match":"1f933-1f3fd","uc_greedy":"1f933-1f3fd","shortnames":[],"category":"people"},":selfie_tone4:":{"uc_base":"1f933-1f3fe","uc_output":"1f933-1f3fe","uc_match":"1f933-1f3fe","uc_greedy":"1f933-1f3fe","shortnames":[],"category":"people"},":selfie_tone5:":{"uc_base":"1f933-1f3ff","uc_output":"1f933-1f3ff","uc_match":"1f933-1f3ff","uc_greedy":"1f933-1f3ff","shortnames":[],"category":"people"},":snowboarder_tone1:":{"uc_base":"1f3c2-1f3fb","uc_output":"1f3c2-1f3fb","uc_match":"1f3c2-1f3fb","uc_greedy":"1f3c2-1f3fb","shortnames":[":snowboarder_light_skin_tone:"],"category":"activity"},":snowboarder_tone2:":{"uc_base":"1f3c2-1f3fc","uc_output":"1f3c2-1f3fc","uc_match":"1f3c2-1f3fc","uc_greedy":"1f3c2-1f3fc","shortnames":[":snowboarder_medium_light_skin_tone:"],"category":"activity"},":snowboarder_tone3:":{"uc_base":"1f3c2-1f3fd","uc_output":"1f3c2-1f3fd","uc_match":"1f3c2-1f3fd","uc_greedy":"1f3c2-1f3fd","shortnames":[":snowboarder_medium_skin_tone:"],"category":"activity"},":snowboarder_tone4:":{"uc_base":"1f3c2-1f3fe","uc_output":"1f3c2-1f3fe","uc_match":"1f3c2-1f3fe","uc_greedy":"1f3c2-1f3fe","shortnames":[":snowboarder_medium_dark_skin_tone:"],"category":"activity"},":snowboarder_tone5:":{"uc_base":"1f3c2-1f3ff","uc_output":"1f3c2-1f3ff","uc_match":"1f3c2-1f3ff","uc_greedy":"1f3c2-1f3ff","shortnames":[":snowboarder_dark_skin_tone:"],"category":"activity"},":thumbsdown_tone1:":{"uc_base":"1f44e-1f3fb","uc_output":"1f44e-1f3fb","uc_match":"1f44e-1f3fb","uc_greedy":"1f44e-1f3fb","shortnames":[":-1_tone1:",":thumbdown_tone1:"],"category":"people"},":thumbsdown_tone2:":{"uc_base":"1f44e-1f3fc","uc_output":"1f44e-1f3fc","uc_match":"1f44e-1f3fc","uc_greedy":"1f44e-1f3fc","shortnames":[":-1_tone2:",":thumbdown_tone2:"],"category":"people"},":thumbsdown_tone3:":{"uc_base":"1f44e-1f3fd","uc_output":"1f44e-1f3fd","uc_match":"1f44e-1f3fd","uc_greedy":"1f44e-1f3fd","shortnames":[":-1_tone3:",":thumbdown_tone3:"],"category":"people"},":thumbsdown_tone4:":{"uc_base":"1f44e-1f3fe","uc_output":"1f44e-1f3fe","uc_match":"1f44e-1f3fe","uc_greedy":"1f44e-1f3fe","shortnames":[":-1_tone4:",":thumbdown_tone4:"],"category":"people"},":thumbsdown_tone5:":{"uc_base":"1f44e-1f3ff","uc_output":"1f44e-1f3ff","uc_match":"1f44e-1f3ff","uc_greedy":"1f44e-1f3ff","shortnames":[":-1_tone5:",":thumbdown_tone5:"],"category":"people"},":thumbsup_tone1:":{"uc_base":"1f44d-1f3fb","uc_output":"1f44d-1f3fb","uc_match":"1f44d-1f3fb","uc_greedy":"1f44d-1f3fb","shortnames":[":+1_tone1:",":thumbup_tone1:"],"category":"people"},":thumbsup_tone2:":{"uc_base":"1f44d-1f3fc","uc_output":"1f44d-1f3fc","uc_match":"1f44d-1f3fc","uc_greedy":"1f44d-1f3fc","shortnames":[":+1_tone2:",":thumbup_tone2:"],"category":"people"},":thumbsup_tone3:":{"uc_base":"1f44d-1f3fd","uc_output":"1f44d-1f3fd","uc_match":"1f44d-1f3fd","uc_greedy":"1f44d-1f3fd","shortnames":[":+1_tone3:",":thumbup_tone3:"],"category":"people"},":thumbsup_tone4:":{"uc_base":"1f44d-1f3fe","uc_output":"1f44d-1f3fe","uc_match":"1f44d-1f3fe","uc_greedy":"1f44d-1f3fe","shortnames":[":+1_tone4:",":thumbup_tone4:"],"category":"people"},":thumbsup_tone5:":{"uc_base":"1f44d-1f3ff","uc_output":"1f44d-1f3ff","uc_match":"1f44d-1f3ff","uc_greedy":"1f44d-1f3ff","shortnames":[":+1_tone5:",":thumbup_tone5:"],"category":"people"},":united_nations:":{"uc_base":"1f1fa-1f1f3","uc_output":"1f1fa-1f1f3","uc_match":"1f1fa-1f1f3","uc_greedy":"1f1fa-1f1f3","shortnames":[],"category":"flags"},":vampire_tone1:":{"uc_base":"1f9db-1f3fb","uc_output":"1f9db-1f3fb","uc_match":"1f9db-1f3fb","uc_greedy":"1f9db-1f3fb","shortnames":[":vampire_light_skin_tone:"],"category":"people"},":vampire_tone2:":{"uc_base":"1f9db-1f3fc","uc_output":"1f9db-1f3fc","uc_match":"1f9db-1f3fc","uc_greedy":"1f9db-1f3fc","shortnames":[":vampire_medium_light_skin_tone:"],"category":"people"},":vampire_tone3:":{"uc_base":"1f9db-1f3fd","uc_output":"1f9db-1f3fd","uc_match":"1f9db-1f3fd","uc_greedy":"1f9db-1f3fd","shortnames":[":vampire_medium_skin_tone:"],"category":"people"},":vampire_tone4:":{"uc_base":"1f9db-1f3fe","uc_output":"1f9db-1f3fe","uc_match":"1f9db-1f3fe","uc_greedy":"1f9db-1f3fe","shortnames":[":vampire_medium_dark_skin_tone:"],"category":"people"},":vampire_tone5:":{"uc_base":"1f9db-1f3ff","uc_output":"1f9db-1f3ff","uc_match":"1f9db-1f3ff","uc_greedy":"1f9db-1f3ff","shortnames":[":vampire_dark_skin_tone:"],"category":"people"},":vulcan_tone1:":{"uc_base":"1f596-1f3fb","uc_output":"1f596-1f3fb","uc_match":"1f596-1f3fb","uc_greedy":"1f596-1f3fb","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone1:"],"category":"people"},":vulcan_tone2:":{"uc_base":"1f596-1f3fc","uc_output":"1f596-1f3fc","uc_match":"1f596-1f3fc","uc_greedy":"1f596-1f3fc","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone2:"],"category":"people"},":vulcan_tone3:":{"uc_base":"1f596-1f3fd","uc_output":"1f596-1f3fd","uc_match":"1f596-1f3fd","uc_greedy":"1f596-1f3fd","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone3:"],"category":"people"},":vulcan_tone4:":{"uc_base":"1f596-1f3fe","uc_output":"1f596-1f3fe","uc_match":"1f596-1f3fe","uc_greedy":"1f596-1f3fe","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone4:"],"category":"people"},":vulcan_tone5:":{"uc_base":"1f596-1f3ff","uc_output":"1f596-1f3ff","uc_match":"1f596-1f3ff","uc_greedy":"1f596-1f3ff","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone5:"],"category":"people"},":wave_tone1:":{"uc_base":"1f44b-1f3fb","uc_output":"1f44b-1f3fb","uc_match":"1f44b-1f3fb","uc_greedy":"1f44b-1f3fb","shortnames":[],"category":"people"},":wave_tone2:":{"uc_base":"1f44b-1f3fc","uc_output":"1f44b-1f3fc","uc_match":"1f44b-1f3fc","uc_greedy":"1f44b-1f3fc","shortnames":[],"category":"people"},":wave_tone3:":{"uc_base":"1f44b-1f3fd","uc_output":"1f44b-1f3fd","uc_match":"1f44b-1f3fd","uc_greedy":"1f44b-1f3fd","shortnames":[],"category":"people"},":wave_tone4:":{"uc_base":"1f44b-1f3fe","uc_output":"1f44b-1f3fe","uc_match":"1f44b-1f3fe","uc_greedy":"1f44b-1f3fe","shortnames":[],"category":"people"},":wave_tone5:":{"uc_base":"1f44b-1f3ff","uc_output":"1f44b-1f3ff","uc_match":"1f44b-1f3ff","uc_greedy":"1f44b-1f3ff","shortnames":[],"category":"people"},":woman_tone1:":{"uc_base":"1f469-1f3fb","uc_output":"1f469-1f3fb","uc_match":"1f469-1f3fb","uc_greedy":"1f469-1f3fb","shortnames":[],"category":"people"},":woman_tone2:":{"uc_base":"1f469-1f3fc","uc_output":"1f469-1f3fc","uc_match":"1f469-1f3fc","uc_greedy":"1f469-1f3fc","shortnames":[],"category":"people"},":woman_tone3:":{"uc_base":"1f469-1f3fd","uc_output":"1f469-1f3fd","uc_match":"1f469-1f3fd","uc_greedy":"1f469-1f3fd","shortnames":[],"category":"people"},":woman_tone4:":{"uc_base":"1f469-1f3fe","uc_output":"1f469-1f3fe","uc_match":"1f469-1f3fe","uc_greedy":"1f469-1f3fe","shortnames":[],"category":"people"},":woman_tone5:":{"uc_base":"1f469-1f3ff","uc_output":"1f469-1f3ff","uc_match":"1f469-1f3ff","uc_greedy":"1f469-1f3ff","shortnames":[],"category":"people"},":woman_with_headscarf_tone1:":{"uc_base":"1f9d5-1f3fb","uc_output":"1f9d5-1f3fb","uc_match":"1f9d5-1f3fb","uc_greedy":"1f9d5-1f3fb","shortnames":[":woman_with_headscarf_light_skin_tone:"],"category":"people"},":woman_with_headscarf_tone2:":{"uc_base":"1f9d5-1f3fc","uc_output":"1f9d5-1f3fc","uc_match":"1f9d5-1f3fc","uc_greedy":"1f9d5-1f3fc","shortnames":[":woman_with_headscarf_medium_light_skin_tone:"],"category":"people"},":woman_with_headscarf_tone3:":{"uc_base":"1f9d5-1f3fd","uc_output":"1f9d5-1f3fd","uc_match":"1f9d5-1f3fd","uc_greedy":"1f9d5-1f3fd","shortnames":[":woman_with_headscarf_medium_skin_tone:"],"category":"people"},":woman_with_headscarf_tone4:":{"uc_base":"1f9d5-1f3fe","uc_output":"1f9d5-1f3fe","uc_match":"1f9d5-1f3fe","uc_greedy":"1f9d5-1f3fe","shortnames":[":woman_with_headscarf_medium_dark_skin_tone:"],"category":"people"},":woman_with_headscarf_tone5:":{"uc_base":"1f9d5-1f3ff","uc_output":"1f9d5-1f3ff","uc_match":"1f9d5-1f3ff","uc_greedy":"1f9d5-1f3ff","shortnames":[":woman_with_headscarf_dark_skin_tone:"],"category":"people"},":a:":{"uc_base":"1f170","uc_output":"1f170-fe0f","uc_match":"1f170-fe0f","uc_greedy":"1f170","shortnames":[],"category":"symbols"},":airplane_small:":{"uc_base":"1f6e9","uc_output":"1f6e9-fe0f","uc_match":"1f6e9-fe0f","uc_greedy":"1f6e9","shortnames":[":small_airplane:"],"category":"travel"},":anger_right:":{"uc_base":"1f5ef","uc_output":"1f5ef-fe0f","uc_match":"1f5ef-fe0f","uc_greedy":"1f5ef","shortnames":[":right_anger_bubble:"],"category":"symbols"},":b:":{"uc_base":"1f171","uc_output":"1f171-fe0f","uc_match":"1f171-fe0f","uc_greedy":"1f171","shortnames":[],"category":"symbols"},":ballot_box:":{"uc_base":"1f5f3","uc_output":"1f5f3-fe0f","uc_match":"1f5f3-fe0f","uc_greedy":"1f5f3","shortnames":[":ballot_box_with_ballot:"],"category":"objects"},":beach:":{"uc_base":"1f3d6","uc_output":"1f3d6-fe0f","uc_match":"1f3d6-fe0f","uc_greedy":"1f3d6","shortnames":[":beach_with_umbrella:"],"category":"travel"},":bed:":{"uc_base":"1f6cf","uc_output":"1f6cf-fe0f","uc_match":"1f6cf-fe0f","uc_greedy":"1f6cf","shortnames":[],"category":"objects"},":bellhop:":{"uc_base":"1f6ce","uc_output":"1f6ce-fe0f","uc_match":"1f6ce-fe0f","uc_greedy":"1f6ce","shortnames":[":bellhop_bell:"],"category":"objects"},":calendar_spiral:":{"uc_base":"1f5d3","uc_output":"1f5d3-fe0f","uc_match":"1f5d3-fe0f","uc_greedy":"1f5d3","shortnames":[":spiral_calendar_pad:"],"category":"objects"},":camping:":{"uc_base":"1f3d5","uc_output":"1f3d5-fe0f","uc_match":"1f3d5-fe0f","uc_greedy":"1f3d5","shortnames":[],"category":"travel"},":candle:":{"uc_base":"1f56f","uc_output":"1f56f-fe0f","uc_match":"1f56f-fe0f","uc_greedy":"1f56f","shortnames":[],"category":"objects"},":card_box:":{"uc_base":"1f5c3","uc_output":"1f5c3-fe0f","uc_match":"1f5c3-fe0f","uc_greedy":"1f5c3","shortnames":[":card_file_box:"],"category":"objects"},":chipmunk:":{"uc_base":"1f43f","uc_output":"1f43f-fe0f","uc_match":"1f43f-fe0f","uc_greedy":"1f43f","shortnames":[],"category":"nature"},":cityscape:":{"uc_base":"1f3d9","uc_output":"1f3d9-fe0f","uc_match":"1f3d9-fe0f","uc_greedy":"1f3d9","shortnames":[],"category":"travel"},":classical_building:":{"uc_base":"1f3db","uc_output":"1f3db-fe0f","uc_match":"1f3db-fe0f","uc_greedy":"1f3db","shortnames":[],"category":"travel"},":clock:":{"uc_base":"1f570","uc_output":"1f570-fe0f","uc_match":"1f570-fe0f","uc_greedy":"1f570","shortnames":[":mantlepiece_clock:"],"category":"objects"},":cloud_lightning:":{"uc_base":"1f329","uc_output":"1f329-fe0f","uc_match":"1f329-fe0f","uc_greedy":"1f329","shortnames":[":cloud_with_lightning:"],"category":"nature"},":cloud_rain:":{"uc_base":"1f327","uc_output":"1f327-fe0f","uc_match":"1f327-fe0f","uc_greedy":"1f327","shortnames":[":cloud_with_rain:"],"category":"nature"},":cloud_snow:":{"uc_base":"1f328","uc_output":"1f328-fe0f","uc_match":"1f328-fe0f","uc_greedy":"1f328","shortnames":[":cloud_with_snow:"],"category":"nature"},":cloud_tornado:":{"uc_base":"1f32a","uc_output":"1f32a-fe0f","uc_match":"1f32a-fe0f","uc_greedy":"1f32a","shortnames":[":cloud_with_tornado:"],"category":"nature"},":compression:":{"uc_base":"1f5dc","uc_output":"1f5dc-fe0f","uc_match":"1f5dc-fe0f","uc_greedy":"1f5dc","shortnames":[],"category":"objects"},":construction_site:":{"uc_base":"1f3d7","uc_output":"1f3d7-fe0f","uc_match":"1f3d7-fe0f","uc_greedy":"1f3d7","shortnames":[":building_construction:"],"category":"travel"},":control_knobs:":{"uc_base":"1f39b","uc_output":"1f39b-fe0f","uc_match":"1f39b-fe0f","uc_greedy":"1f39b","shortnames":[],"category":"objects"},":couch:":{"uc_base":"1f6cb","uc_output":"1f6cb-fe0f","uc_match":"1f6cb-fe0f","uc_greedy":"1f6cb","shortnames":[":couch_and_lamp:"],"category":"objects"},":crayon:":{"uc_base":"1f58d","uc_output":"1f58d-fe0f","uc_match":"1f58d-fe0f","uc_greedy":"1f58d","shortnames":[":lower_left_crayon:"],"category":"objects"},":cruise_ship:":{"uc_base":"1f6f3","uc_output":"1f6f3-fe0f","uc_match":"1f6f3-fe0f","uc_greedy":"1f6f3","shortnames":[":passenger_ship:"],"category":"travel"},":dagger:":{"uc_base":"1f5e1","uc_output":"1f5e1-fe0f","uc_match":"1f5e1-fe0f","uc_greedy":"1f5e1","shortnames":[":dagger_knife:"],"category":"objects"},":dark_sunglasses:":{"uc_base":"1f576","uc_output":"1f576-fe0f","uc_match":"1f576-fe0f","uc_greedy":"1f576","shortnames":[],"category":"people"},":desert:":{"uc_base":"1f3dc","uc_output":"1f3dc-fe0f","uc_match":"1f3dc-fe0f","uc_greedy":"1f3dc","shortnames":[],"category":"travel"},":desktop:":{"uc_base":"1f5a5","uc_output":"1f5a5-fe0f","uc_match":"1f5a5-fe0f","uc_greedy":"1f5a5","shortnames":[":desktop_computer:"],"category":"objects"},":detective:":{"uc_base":"1f575","uc_output":"1f575-fe0f","uc_match":"1f575-fe0f","uc_greedy":"1f575","shortnames":[":spy:",":sleuth_or_spy:"],"category":"people"},":dividers:":{"uc_base":"1f5c2","uc_output":"1f5c2-fe0f","uc_match":"1f5c2-fe0f","uc_greedy":"1f5c2","shortnames":[":card_index_dividers:"],"category":"objects"},":dove:":{"uc_base":"1f54a","uc_output":"1f54a-fe0f","uc_match":"1f54a-fe0f","uc_greedy":"1f54a","shortnames":[":dove_of_peace:"],"category":"nature"},":eye:":{"uc_base":"1f441","uc_output":"1f441-fe0f","uc_match":"1f441-fe0f","uc_greedy":"1f441","shortnames":[],"category":"people"},":file_cabinet:":{"uc_base":"1f5c4","uc_output":"1f5c4-fe0f","uc_match":"1f5c4-fe0f","uc_greedy":"1f5c4","shortnames":[],"category":"objects"},":film_frames:":{"uc_base":"1f39e","uc_output":"1f39e-fe0f","uc_match":"1f39e-fe0f","uc_greedy":"1f39e","shortnames":[],"category":"objects"},":fist_tone1:":{"uc_base":"270a-1f3fb","uc_output":"270a-1f3fb","uc_match":"270a-1f3fb","uc_greedy":"270a-1f3fb","shortnames":[],"category":"people"},":fist_tone2:":{"uc_base":"270a-1f3fc","uc_output":"270a-1f3fc","uc_match":"270a-1f3fc","uc_greedy":"270a-1f3fc","shortnames":[],"category":"people"},":fist_tone3:":{"uc_base":"270a-1f3fd","uc_output":"270a-1f3fd","uc_match":"270a-1f3fd","uc_greedy":"270a-1f3fd","shortnames":[],"category":"people"},":fist_tone4:":{"uc_base":"270a-1f3fe","uc_output":"270a-1f3fe","uc_match":"270a-1f3fe","uc_greedy":"270a-1f3fe","shortnames":[],"category":"people"},":fist_tone5:":{"uc_base":"270a-1f3ff","uc_output":"270a-1f3ff","uc_match":"270a-1f3ff","uc_greedy":"270a-1f3ff","shortnames":[],"category":"people"},":flag_white:":{"uc_base":"1f3f3","uc_output":"1f3f3-fe0f","uc_match":"1f3f3-fe0f","uc_greedy":"1f3f3","shortnames":[":waving_white_flag:"],"category":"flags"},":fog:":{"uc_base":"1f32b","uc_output":"1f32b-fe0f","uc_match":"1f32b-fe0f","uc_greedy":"1f32b","shortnames":[],"category":"nature"},":fork_knife_plate:":{"uc_base":"1f37d","uc_output":"1f37d-fe0f","uc_match":"1f37d-fe0f","uc_greedy":"1f37d","shortnames":[":fork_and_knife_with_plate:"],"category":"food"},":frame_photo:":{"uc_base":"1f5bc","uc_output":"1f5bc-fe0f","uc_match":"1f5bc-fe0f","uc_greedy":"1f5bc","shortnames":[":frame_with_picture:"],"category":"objects"},":hand_splayed:":{"uc_base":"1f590","uc_output":"1f590-fe0f","uc_match":"1f590-fe0f","uc_greedy":"1f590","shortnames":[":raised_hand_with_fingers_splayed:"],"category":"people"},":hole:":{"uc_base":"1f573","uc_output":"1f573-fe0f","uc_match":"1f573-fe0f","uc_greedy":"1f573","shortnames":[],"category":"objects"},":homes:":{"uc_base":"1f3d8","uc_output":"1f3d8-fe0f","uc_match":"1f3d8-fe0f","uc_greedy":"1f3d8","shortnames":[":house_buildings:"],"category":"travel"},":hot_pepper:":{"uc_base":"1f336","uc_output":"1f336-fe0f","uc_match":"1f336-fe0f","uc_greedy":"1f336","shortnames":[],"category":"food"},":house_abandoned:":{"uc_base":"1f3da","uc_output":"1f3da-fe0f","uc_match":"1f3da-fe0f","uc_greedy":"1f3da","shortnames":[":derelict_house_building:"],"category":"travel"},":island:":{"uc_base":"1f3dd","uc_output":"1f3dd-fe0f","uc_match":"1f3dd-fe0f","uc_greedy":"1f3dd","shortnames":[":desert_island:"],"category":"travel"},":joystick:":{"uc_base":"1f579","uc_output":"1f579-fe0f","uc_match":"1f579-fe0f","uc_greedy":"1f579","shortnames":[],"category":"objects"},":key2:":{"uc_base":"1f5dd","uc_output":"1f5dd-fe0f","uc_match":"1f5dd-fe0f","uc_greedy":"1f5dd","shortnames":[":old_key:"],"category":"objects"},":label:":{"uc_base":"1f3f7","uc_output":"1f3f7-fe0f","uc_match":"1f3f7-fe0f","uc_greedy":"1f3f7","shortnames":[],"category":"objects"},":level_slider:":{"uc_base":"1f39a","uc_output":"1f39a-fe0f","uc_match":"1f39a-fe0f","uc_greedy":"1f39a","shortnames":[],"category":"objects"},":man_in_business_suit_levitating:":{"uc_base":"1f574","uc_output":"1f574-fe0f","uc_match":"1f574-fe0f","uc_greedy":"1f574","shortnames":[],"category":"people"},":map:":{"uc_base":"1f5fa","uc_output":"1f5fa-fe0f","uc_match":"1f5fa-fe0f","uc_greedy":"1f5fa","shortnames":[":world_map:"],"category":"travel"},":microphone2:":{"uc_base":"1f399","uc_output":"1f399-fe0f","uc_match":"1f399-fe0f","uc_greedy":"1f399","shortnames":[":studio_microphone:"],"category":"objects"},":military_medal:":{"uc_base":"1f396","uc_output":"1f396-fe0f","uc_match":"1f396-fe0f","uc_greedy":"1f396","shortnames":[],"category":"activity"},":motorboat:":{"uc_base":"1f6e5","uc_output":"1f6e5-fe0f","uc_match":"1f6e5-fe0f","uc_greedy":"1f6e5","shortnames":[],"category":"travel"},":motorcycle:":{"uc_base":"1f3cd","uc_output":"1f3cd-fe0f","uc_match":"1f3cd-fe0f","uc_greedy":"1f3cd","shortnames":[":racing_motorcycle:"],"category":"travel"},":motorway:":{"uc_base":"1f6e3","uc_output":"1f6e3-fe0f","uc_match":"1f6e3-fe0f","uc_greedy":"1f6e3","shortnames":[],"category":"travel"},":mountain_snow:":{"uc_base":"1f3d4","uc_output":"1f3d4-fe0f","uc_match":"1f3d4-fe0f","uc_greedy":"1f3d4","shortnames":[":snow_capped_mountain:"],"category":"travel"},":mouse_three_button:":{"uc_base":"1f5b1","uc_output":"1f5b1-fe0f","uc_match":"1f5b1-fe0f","uc_greedy":"1f5b1","shortnames":[":three_button_mouse:"],"category":"objects"},":newspaper2:":{"uc_base":"1f5de","uc_output":"1f5de-fe0f","uc_match":"1f5de-fe0f","uc_greedy":"1f5de","shortnames":[":rolled_up_newspaper:"],"category":"objects"},":notepad_spiral:":{"uc_base":"1f5d2","uc_output":"1f5d2-fe0f","uc_match":"1f5d2-fe0f","uc_greedy":"1f5d2","shortnames":[":spiral_note_pad:"],"category":"objects"},":o2:":{"uc_base":"1f17e","uc_output":"1f17e-fe0f","uc_match":"1f17e-fe0f","uc_greedy":"1f17e","shortnames":[],"category":"symbols"},":oil:":{"uc_base":"1f6e2","uc_output":"1f6e2-fe0f","uc_match":"1f6e2-fe0f","uc_greedy":"1f6e2","shortnames":[":oil_drum:"],"category":"objects"},":om_symbol:":{"uc_base":"1f549","uc_output":"1f549-fe0f","uc_match":"1f549-fe0f","uc_greedy":"1f549","shortnames":[],"category":"symbols"},":paintbrush:":{"uc_base":"1f58c","uc_output":"1f58c-fe0f","uc_match":"1f58c-fe0f","uc_greedy":"1f58c","shortnames":[":lower_left_paintbrush:"],"category":"objects"},":paperclips:":{"uc_base":"1f587","uc_output":"1f587-fe0f","uc_match":"1f587-fe0f","uc_greedy":"1f587","shortnames":[":linked_paperclips:"],"category":"objects"},":park:":{"uc_base":"1f3de","uc_output":"1f3de-fe0f","uc_match":"1f3de-fe0f","uc_greedy":"1f3de","shortnames":[":national_park:"],"category":"travel"},":parking:":{"uc_base":"1f17f","uc_output":"1f17f-fe0f","uc_match":"1f17f-fe0f","uc_greedy":"1f17f","shortnames":[],"category":"symbols"},":pen_ballpoint:":{"uc_base":"1f58a","uc_output":"1f58a-fe0f","uc_match":"1f58a-fe0f","uc_greedy":"1f58a","shortnames":[":lower_left_ballpoint_pen:"],"category":"objects"},":pen_fountain:":{"uc_base":"1f58b","uc_output":"1f58b-fe0f","uc_match":"1f58b-fe0f","uc_greedy":"1f58b","shortnames":[":lower_left_fountain_pen:"],"category":"objects"},":person_bouncing_ball_tone1:":{"uc_base":"26f9-1f3fb","uc_output":"26f9-1f3fb","uc_match":"26f9-fe0f-1f3fb","uc_greedy":"26f9-fe0f-1f3fb","shortnames":[":basketball_player_tone1:",":person_with_ball_tone1:"],"category":"activity"},":person_bouncing_ball_tone2:":{"uc_base":"26f9-1f3fc","uc_output":"26f9-1f3fc","uc_match":"26f9-fe0f-1f3fc","uc_greedy":"26f9-fe0f-1f3fc","shortnames":[":basketball_player_tone2:",":person_with_ball_tone2:"],"category":"activity"},":person_bouncing_ball_tone3:":{"uc_base":"26f9-1f3fd","uc_output":"26f9-1f3fd","uc_match":"26f9-fe0f-1f3fd","uc_greedy":"26f9-fe0f-1f3fd","shortnames":[":basketball_player_tone3:",":person_with_ball_tone3:"],"category":"activity"},":person_bouncing_ball_tone4:":{"uc_base":"26f9-1f3fe","uc_output":"26f9-1f3fe","uc_match":"26f9-fe0f-1f3fe","uc_greedy":"26f9-fe0f-1f3fe","shortnames":[":basketball_player_tone4:",":person_with_ball_tone4:"],"category":"activity"},":person_bouncing_ball_tone5:":{"uc_base":"26f9-1f3ff","uc_output":"26f9-1f3ff","uc_match":"26f9-fe0f-1f3ff","uc_greedy":"26f9-fe0f-1f3ff","shortnames":[":basketball_player_tone5:",":person_with_ball_tone5:"],"category":"activity"},":person_golfing:":{"uc_base":"1f3cc","uc_output":"1f3cc-fe0f","uc_match":"1f3cc-fe0f","uc_greedy":"1f3cc","shortnames":[":golfer:"],"category":"activity"},":person_lifting_weights:":{"uc_base":"1f3cb","uc_output":"1f3cb-fe0f","uc_match":"1f3cb-fe0f","uc_greedy":"1f3cb","shortnames":[":lifter:",":weight_lifter:"],"category":"activity"},":point_up_tone1:":{"uc_base":"261d-1f3fb","uc_output":"261d-1f3fb","uc_match":"261d-fe0f-1f3fb","uc_greedy":"261d-fe0f-1f3fb","shortnames":[],"category":"people"},":point_up_tone2:":{"uc_base":"261d-1f3fc","uc_output":"261d-1f3fc","uc_match":"261d-fe0f-1f3fc","uc_greedy":"261d-fe0f-1f3fc","shortnames":[],"category":"people"},":point_up_tone3:":{"uc_base":"261d-1f3fd","uc_output":"261d-1f3fd","uc_match":"261d-fe0f-1f3fd","uc_greedy":"261d-fe0f-1f3fd","shortnames":[],"category":"people"},":point_up_tone4:":{"uc_base":"261d-1f3fe","uc_output":"261d-1f3fe","uc_match":"261d-fe0f-1f3fe","uc_greedy":"261d-fe0f-1f3fe","shortnames":[],"category":"people"},":point_up_tone5:":{"uc_base":"261d-1f3ff","uc_output":"261d-1f3ff","uc_match":"261d-fe0f-1f3ff","uc_greedy":"261d-fe0f-1f3ff","shortnames":[],"category":"people"},":printer:":{"uc_base":"1f5a8","uc_output":"1f5a8-fe0f","uc_match":"1f5a8-fe0f","uc_greedy":"1f5a8","shortnames":[],"category":"objects"},":projector:":{"uc_base":"1f4fd","uc_output":"1f4fd-fe0f","uc_match":"1f4fd-fe0f","uc_greedy":"1f4fd","shortnames":[":film_projector:"],"category":"objects"},":race_car:":{"uc_base":"1f3ce","uc_output":"1f3ce-fe0f","uc_match":"1f3ce-fe0f","uc_greedy":"1f3ce","shortnames":[":racing_car:"],"category":"travel"},":railway_track:":{"uc_base":"1f6e4","uc_output":"1f6e4-fe0f","uc_match":"1f6e4-fe0f","uc_greedy":"1f6e4","shortnames":[":railroad_track:"],"category":"travel"},":raised_hand_tone1:":{"uc_base":"270b-1f3fb","uc_output":"270b-1f3fb","uc_match":"270b-1f3fb","uc_greedy":"270b-1f3fb","shortnames":[],"category":"people"},":raised_hand_tone2:":{"uc_base":"270b-1f3fc","uc_output":"270b-1f3fc","uc_match":"270b-1f3fc","uc_greedy":"270b-1f3fc","shortnames":[],"category":"people"},":raised_hand_tone3:":{"uc_base":"270b-1f3fd","uc_output":"270b-1f3fd","uc_match":"270b-1f3fd","uc_greedy":"270b-1f3fd","shortnames":[],"category":"people"},":raised_hand_tone4:":{"uc_base":"270b-1f3fe","uc_output":"270b-1f3fe","uc_match":"270b-1f3fe","uc_greedy":"270b-1f3fe","shortnames":[],"category":"people"},":raised_hand_tone5:":{"uc_base":"270b-1f3ff","uc_output":"270b-1f3ff","uc_match":"270b-1f3ff","uc_greedy":"270b-1f3ff","shortnames":[],"category":"people"},":reminder_ribbon:":{"uc_base":"1f397","uc_output":"1f397-fe0f","uc_match":"1f397-fe0f","uc_greedy":"1f397","shortnames":[],"category":"activity"},":rosette:":{"uc_base":"1f3f5","uc_output":"1f3f5-fe0f","uc_match":"1f3f5-fe0f","uc_greedy":"1f3f5","shortnames":[],"category":"activity"},":sa:":{"uc_base":"1f202","uc_output":"1f202-fe0f","uc_match":"1f202-fe0f","uc_greedy":"1f202","shortnames":[],"category":"symbols"},":satellite_orbital:":{"uc_base":"1f6f0","uc_output":"1f6f0-fe0f","uc_match":"1f6f0-fe0f","uc_greedy":"1f6f0","shortnames":[],"category":"travel"},":shield:":{"uc_base":"1f6e1","uc_output":"1f6e1-fe0f","uc_match":"1f6e1-fe0f","uc_greedy":"1f6e1","shortnames":[],"category":"objects"},":shopping_bags:":{"uc_base":"1f6cd","uc_output":"1f6cd-fe0f","uc_match":"1f6cd-fe0f","uc_greedy":"1f6cd","shortnames":[],"category":"objects"},":speaking_head:":{"uc_base":"1f5e3","uc_output":"1f5e3-fe0f","uc_match":"1f5e3-fe0f","uc_greedy":"1f5e3","shortnames":[":speaking_head_in_silhouette:"],"category":"people"},":speech_left:":{"uc_base":"1f5e8","uc_output":"1f5e8-fe0f","uc_match":"1f5e8-fe0f","uc_greedy":"1f5e8","shortnames":[":left_speech_bubble:"],"category":"symbols"},":spider:":{"uc_base":"1f577","uc_output":"1f577-fe0f","uc_match":"1f577-fe0f","uc_greedy":"1f577","shortnames":[],"category":"nature"},":spider_web:":{"uc_base":"1f578","uc_output":"1f578-fe0f","uc_match":"1f578-fe0f","uc_greedy":"1f578","shortnames":[],"category":"nature"},":stadium:":{"uc_base":"1f3df","uc_output":"1f3df-fe0f","uc_match":"1f3df-fe0f","uc_greedy":"1f3df","shortnames":[],"category":"travel"},":thermometer:":{"uc_base":"1f321","uc_output":"1f321-fe0f","uc_match":"1f321-fe0f","uc_greedy":"1f321","shortnames":[],"category":"objects"},":tickets:":{"uc_base":"1f39f","uc_output":"1f39f-fe0f","uc_match":"1f39f-fe0f","uc_greedy":"1f39f","shortnames":[":admission_tickets:"],"category":"activity"},":tools:":{"uc_base":"1f6e0","uc_output":"1f6e0-fe0f","uc_match":"1f6e0-fe0f","uc_greedy":"1f6e0","shortnames":[":hammer_and_wrench:"],"category":"objects"},":trackball:":{"uc_base":"1f5b2","uc_output":"1f5b2-fe0f","uc_match":"1f5b2-fe0f","uc_greedy":"1f5b2","shortnames":[],"category":"objects"},":u6708:":{"uc_base":"1f237","uc_output":"1f237-fe0f","uc_match":"1f237-fe0f","uc_greedy":"1f237","shortnames":[],"category":"symbols"},":v_tone1:":{"uc_base":"270c-1f3fb","uc_output":"270c-1f3fb","uc_match":"270c-fe0f-1f3fb","uc_greedy":"270c-fe0f-1f3fb","shortnames":[],"category":"people"},":v_tone2:":{"uc_base":"270c-1f3fc","uc_output":"270c-1f3fc","uc_match":"270c-fe0f-1f3fc","uc_greedy":"270c-fe0f-1f3fc","shortnames":[],"category":"people"},":v_tone3:":{"uc_base":"270c-1f3fd","uc_output":"270c-1f3fd","uc_match":"270c-fe0f-1f3fd","uc_greedy":"270c-fe0f-1f3fd","shortnames":[],"category":"people"},":v_tone4:":{"uc_base":"270c-1f3fe","uc_output":"270c-1f3fe","uc_match":"270c-fe0f-1f3fe","uc_greedy":"270c-fe0f-1f3fe","shortnames":[],"category":"people"},":v_tone5:":{"uc_base":"270c-1f3ff","uc_output":"270c-1f3ff","uc_match":"270c-fe0f-1f3ff","uc_greedy":"270c-fe0f-1f3ff","shortnames":[],"category":"people"},":wastebasket:":{"uc_base":"1f5d1","uc_output":"1f5d1-fe0f","uc_match":"1f5d1-fe0f","uc_greedy":"1f5d1","shortnames":[],"category":"objects"},":white_sun_cloud:":{"uc_base":"1f325","uc_output":"1f325-fe0f","uc_match":"1f325-fe0f","uc_greedy":"1f325","shortnames":[":white_sun_behind_cloud:"],"category":"nature"},":white_sun_rain_cloud:":{"uc_base":"1f326","uc_output":"1f326-fe0f","uc_match":"1f326-fe0f","uc_greedy":"1f326","shortnames":[":white_sun_behind_cloud_with_rain:"],"category":"nature"},":white_sun_small_cloud:":{"uc_base":"1f324","uc_output":"1f324-fe0f","uc_match":"1f324-fe0f","uc_greedy":"1f324","shortnames":[":white_sun_with_small_cloud:"],"category":"nature"},":wind_blowing_face:":{"uc_base":"1f32c","uc_output":"1f32c-fe0f","uc_match":"1f32c-fe0f","uc_greedy":"1f32c","shortnames":[],"category":"nature"},":writing_hand_tone1:":{"uc_base":"270d-1f3fb","uc_output":"270d-1f3fb","uc_match":"270d-fe0f-1f3fb","uc_greedy":"270d-fe0f-1f3fb","shortnames":[],"category":"people"},":writing_hand_tone2:":{"uc_base":"270d-1f3fc","uc_output":"270d-1f3fc","uc_match":"270d-fe0f-1f3fc","uc_greedy":"270d-fe0f-1f3fc","shortnames":[],"category":"people"},":writing_hand_tone3:":{"uc_base":"270d-1f3fd","uc_output":"270d-1f3fd","uc_match":"270d-fe0f-1f3fd","uc_greedy":"270d-fe0f-1f3fd","shortnames":[],"category":"people"},":writing_hand_tone4:":{"uc_base":"270d-1f3fe","uc_output":"270d-1f3fe","uc_match":"270d-fe0f-1f3fe","uc_greedy":"270d-fe0f-1f3fe","shortnames":[],"category":"people"},":writing_hand_tone5:":{"uc_base":"270d-1f3ff","uc_output":"270d-1f3ff","uc_match":"270d-fe0f-1f3ff","uc_greedy":"270d-fe0f-1f3ff","shortnames":[],"category":"people"},":airplane:":{"uc_base":"2708","uc_output":"2708-fe0f","uc_match":"2708-fe0f","uc_greedy":"2708","shortnames":[],"category":"travel"},":alembic:":{"uc_base":"2697","uc_output":"2697-fe0f","uc_match":"2697-fe0f","uc_greedy":"2697","shortnames":[],"category":"objects"},":arrow_backward:":{"uc_base":"25c0","uc_output":"25c0-fe0f","uc_match":"25c0-fe0f","uc_greedy":"25c0","shortnames":[],"category":"symbols"},":arrow_down:":{"uc_base":"2b07","uc_output":"2b07-fe0f","uc_match":"2b07-fe0f","uc_greedy":"2b07","shortnames":[],"category":"symbols"},":arrow_forward:":{"uc_base":"25b6","uc_output":"25b6-fe0f","uc_match":"25b6-fe0f","uc_greedy":"25b6","shortnames":[],"category":"symbols"},":arrow_heading_down:":{"uc_base":"2935","uc_output":"2935-fe0f","uc_match":"2935-fe0f","uc_greedy":"2935","shortnames":[],"category":"symbols"},":arrow_heading_up:":{"uc_base":"2934","uc_output":"2934-fe0f","uc_match":"2934-fe0f","uc_greedy":"2934","shortnames":[],"category":"symbols"},":arrow_left:":{"uc_base":"2b05","uc_output":"2b05-fe0f","uc_match":"2b05-fe0f","uc_greedy":"2b05","shortnames":[],"category":"symbols"},":arrow_lower_left:":{"uc_base":"2199","uc_output":"2199-fe0f","uc_match":"2199-fe0f","uc_greedy":"2199","shortnames":[],"category":"symbols"},":arrow_lower_right:":{"uc_base":"2198","uc_output":"2198-fe0f","uc_match":"2198-fe0f","uc_greedy":"2198","shortnames":[],"category":"symbols"},":arrow_right:":{"uc_base":"27a1","uc_output":"27a1-fe0f","uc_match":"27a1-fe0f","uc_greedy":"27a1","shortnames":[],"category":"symbols"},":arrow_right_hook:":{"uc_base":"21aa","uc_output":"21aa-fe0f","uc_match":"21aa-fe0f","uc_greedy":"21aa","shortnames":[],"category":"symbols"},":arrow_up:":{"uc_base":"2b06","uc_output":"2b06-fe0f","uc_match":"2b06-fe0f","uc_greedy":"2b06","shortnames":[],"category":"symbols"},":arrow_up_down:":{"uc_base":"2195","uc_output":"2195-fe0f","uc_match":"2195-fe0f","uc_greedy":"2195","shortnames":[],"category":"symbols"},":arrow_upper_left:":{"uc_base":"2196","uc_output":"2196-fe0f","uc_match":"2196-fe0f","uc_greedy":"2196","shortnames":[],"category":"symbols"},":arrow_upper_right:":{"uc_base":"2197","uc_output":"2197-fe0f","uc_match":"2197-fe0f","uc_greedy":"2197","shortnames":[],"category":"symbols"},":asterisk_symbol:":{"uc_base":"002a","uc_output":"002a-fe0f","uc_match":"002a-fe0f","uc_greedy":"002a","shortnames":[],"category":"symbols"},":atom:":{"uc_base":"269b","uc_output":"269b-fe0f","uc_match":"269b-fe0f","uc_greedy":"269b","shortnames":[":atom_symbol:"],"category":"symbols"},":ballot_box_with_check:":{"uc_base":"2611","uc_output":"2611-fe0f","uc_match":"2611-fe0f","uc_greedy":"2611","shortnames":[],"category":"symbols"},":bangbang:":{"uc_base":"203c","uc_output":"203c-fe0f","uc_match":"203c-fe0f","uc_greedy":"203c","shortnames":[],"category":"symbols"},":beach_umbrella:":{"uc_base":"26f1","uc_output":"26f1-fe0f","uc_match":"26f1-fe0f","uc_greedy":"26f1","shortnames":[":umbrella_on_ground:"],"category":"travel"},":biohazard:":{"uc_base":"2623","uc_output":"2623-fe0f","uc_match":"2623-fe0f","uc_greedy":"2623","shortnames":[":biohazard_sign:"],"category":"symbols"},":black_medium_square:":{"uc_base":"25fc","uc_output":"25fc-fe0f","uc_match":"25fc-fe0f","uc_greedy":"25fc","shortnames":[],"category":"symbols"},":black_nib:":{"uc_base":"2712","uc_output":"2712-fe0f","uc_match":"2712-fe0f","uc_greedy":"2712","shortnames":[],"category":"objects"},":black_small_square:":{"uc_base":"25aa","uc_output":"25aa-fe0f","uc_match":"25aa-fe0f","uc_greedy":"25aa","shortnames":[],"category":"symbols"},":chains:":{"uc_base":"26d3","uc_output":"26d3-fe0f","uc_match":"26d3-fe0f","uc_greedy":"26d3","shortnames":[],"category":"objects"},":cloud:":{"uc_base":"2601","uc_output":"2601-fe0f","uc_match":"2601-fe0f","uc_greedy":"2601","shortnames":[],"category":"nature"},":clubs:":{"uc_base":"2663","uc_output":"2663-fe0f","uc_match":"2663-fe0f","uc_greedy":"2663","shortnames":[],"category":"symbols"},":coffin:":{"uc_base":"26b0","uc_output":"26b0-fe0f","uc_match":"26b0-fe0f","uc_greedy":"26b0","shortnames":[],"category":"objects"},":comet:":{"uc_base":"2604","uc_output":"2604-fe0f","uc_match":"2604-fe0f","uc_greedy":"2604","shortnames":[],"category":"nature"},":congratulations:":{"uc_base":"3297","uc_output":"3297-fe0f","uc_match":"3297-fe0f","uc_greedy":"3297","shortnames":[],"category":"symbols"},":copyright:":{"uc_base":"00a9","uc_output":"00a9-fe0f","uc_match":"00a9-fe0f","uc_greedy":"00a9","shortnames":[],"category":"symbols"},":cross:":{"uc_base":"271d","uc_output":"271d-fe0f","uc_match":"271d-fe0f","uc_greedy":"271d","shortnames":[":latin_cross:"],"category":"symbols"},":crossed_swords:":{"uc_base":"2694","uc_output":"2694-fe0f","uc_match":"2694-fe0f","uc_greedy":"2694","shortnames":[],"category":"objects"},":diamonds:":{"uc_base":"2666","uc_output":"2666-fe0f","uc_match":"2666-fe0f","uc_greedy":"2666","shortnames":[],"category":"symbols"},":digit_eight:":{"uc_base":"0038","uc_output":"0038-fe0f","uc_match":"0038-fe0f","uc_greedy":"0038","shortnames":[],"category":"symbols"},":digit_five:":{"uc_base":"0035","uc_output":"0035-fe0f","uc_match":"0035-fe0f","uc_greedy":"0035","shortnames":[],"category":"symbols"},":digit_four:":{"uc_base":"0034","uc_output":"0034-fe0f","uc_match":"0034-fe0f","uc_greedy":"0034","shortnames":[],"category":"symbols"},":digit_nine:":{"uc_base":"0039","uc_output":"0039-fe0f","uc_match":"0039-fe0f","uc_greedy":"0039","shortnames":[],"category":"symbols"},":digit_one:":{"uc_base":"0031","uc_output":"0031-fe0f","uc_match":"0031-fe0f","uc_greedy":"0031","shortnames":[],"category":"symbols"},":digit_seven:":{"uc_base":"0037","uc_output":"0037-fe0f","uc_match":"0037-fe0f","uc_greedy":"0037","shortnames":[],"category":"symbols"},":digit_six:":{"uc_base":"0036","uc_output":"0036-fe0f","uc_match":"0036-fe0f","uc_greedy":"0036","shortnames":[],"category":"symbols"},":digit_three:":{"uc_base":"0033","uc_output":"0033-fe0f","uc_match":"0033-fe0f","uc_greedy":"0033","shortnames":[],"category":"symbols"},":digit_two:":{"uc_base":"0032","uc_output":"0032-fe0f","uc_match":"0032-fe0f","uc_greedy":"0032","shortnames":[],"category":"symbols"},":digit_zero:":{"uc_base":"0030","uc_output":"0030-fe0f","uc_match":"0030-fe0f","uc_greedy":"0030","shortnames":[],"category":"symbols"},":eight_pointed_black_star:":{"uc_base":"2734","uc_output":"2734-fe0f","uc_match":"2734-fe0f","uc_greedy":"2734","shortnames":[],"category":"symbols"},":eight_spoked_asterisk:":{"uc_base":"2733","uc_output":"2733-fe0f","uc_match":"2733-fe0f","uc_greedy":"2733","shortnames":[],"category":"symbols"},":eject:":{"uc_base":"23cf","uc_output":"23cf-fe0f","uc_match":"23cf-fe0f","uc_greedy":"23cf","shortnames":[":eject_symbol:"],"category":"symbols"},":envelope:":{"uc_base":"2709","uc_output":"2709-fe0f","uc_match":"2709-fe0f","uc_greedy":"2709","shortnames":[],"category":"objects"},":female_sign:":{"uc_base":"2640","uc_output":"2640-fe0f","uc_match":"2640-fe0f","uc_greedy":"2640","shortnames":[],"category":"people"},":ferry:":{"uc_base":"26f4","uc_output":"26f4-fe0f","uc_match":"26f4-fe0f","uc_greedy":"26f4","shortnames":[],"category":"travel"},":fleur-de-lis:":{"uc_base":"269c","uc_output":"269c-fe0f","uc_match":"269c-fe0f","uc_greedy":"269c","shortnames":[],"category":"symbols"},":frowning2:":{"uc_base":"2639","uc_output":"2639-fe0f","uc_match":"2639-fe0f","uc_greedy":"2639","shortnames":[":white_frowning_face:"],"category":"people"},":gear:":{"uc_base":"2699","uc_output":"2699-fe0f","uc_match":"2699-fe0f","uc_greedy":"2699","shortnames":[],"category":"objects"},":hammer_pick:":{"uc_base":"2692","uc_output":"2692-fe0f","uc_match":"2692-fe0f","uc_greedy":"2692","shortnames":[":hammer_and_pick:"],"category":"objects"},":heart:":{"uc_base":"2764","uc_output":"2764-fe0f","uc_match":"2764-fe0f","uc_greedy":"2764","shortnames":[],"category":"symbols"},":heart_exclamation:":{"uc_base":"2763","uc_output":"2763-fe0f","uc_match":"2763-fe0f","uc_greedy":"2763","shortnames":[":heavy_heart_exclamation_mark_ornament:"],"category":"symbols"},":hearts:":{"uc_base":"2665","uc_output":"2665-fe0f","uc_match":"2665-fe0f","uc_greedy":"2665","shortnames":[],"category":"symbols"},":heavy_check_mark:":{"uc_base":"2714","uc_output":"2714-fe0f","uc_match":"2714-fe0f","uc_greedy":"2714","shortnames":[],"category":"symbols"},":heavy_multiplication_x:":{"uc_base":"2716","uc_output":"2716-fe0f","uc_match":"2716-fe0f","uc_greedy":"2716","shortnames":[],"category":"symbols"},":helmet_with_cross:":{"uc_base":"26d1","uc_output":"26d1-fe0f","uc_match":"26d1-fe0f","uc_greedy":"26d1","shortnames":[":helmet_with_white_cross:"],"category":"people"},":hotsprings:":{"uc_base":"2668","uc_output":"2668-fe0f","uc_match":"2668-fe0f","uc_greedy":"2668","shortnames":[],"category":"symbols"},":ice_skate:":{"uc_base":"26f8","uc_output":"26f8-fe0f","uc_match":"26f8-fe0f","uc_greedy":"26f8","shortnames":[],"category":"activity"},":information_source:":{"uc_base":"2139","uc_output":"2139-fe0f","uc_match":"2139-fe0f","uc_greedy":"2139","shortnames":[],"category":"symbols"},":interrobang:":{"uc_base":"2049","uc_output":"2049-fe0f","uc_match":"2049-fe0f","uc_greedy":"2049","shortnames":[],"category":"symbols"},":keyboard:":{"uc_base":"2328","uc_output":"2328-fe0f","uc_match":"2328-fe0f","uc_greedy":"2328","shortnames":[],"category":"objects"},":left_right_arrow:":{"uc_base":"2194","uc_output":"2194-fe0f","uc_match":"2194-fe0f","uc_greedy":"2194","shortnames":[],"category":"symbols"},":leftwards_arrow_with_hook:":{"uc_base":"21a9","uc_output":"21a9-fe0f","uc_match":"21a9-fe0f","uc_greedy":"21a9","shortnames":[],"category":"symbols"},":m:":{"uc_base":"24c2","uc_output":"24c2-fe0f","uc_match":"24c2-fe0f","uc_greedy":"24c2","shortnames":[],"category":"symbols"},":male_sign:":{"uc_base":"2642","uc_output":"2642-fe0f","uc_match":"2642-fe0f","uc_greedy":"2642","shortnames":[],"category":"people"},":medical_symbol:":{"uc_base":"2695","uc_output":"2695-fe0f","uc_match":"2695-fe0f","uc_greedy":"2695","shortnames":[],"category":"people"},":mountain:":{"uc_base":"26f0","uc_output":"26f0-fe0f","uc_match":"26f0-fe0f","uc_greedy":"26f0","shortnames":[],"category":"travel"},":orthodox_cross:":{"uc_base":"2626","uc_output":"2626-fe0f","uc_match":"2626-fe0f","uc_greedy":"2626","shortnames":[],"category":"symbols"},":part_alternation_mark:":{"uc_base":"303d","uc_output":"303d-fe0f","uc_match":"303d-fe0f","uc_greedy":"303d","shortnames":[],"category":"symbols"},":pause_button:":{"uc_base":"23f8","uc_output":"23f8-fe0f","uc_match":"23f8-fe0f","uc_greedy":"23f8","shortnames":[":double_vertical_bar:"],"category":"symbols"},":peace:":{"uc_base":"262e","uc_output":"262e-fe0f","uc_match":"262e-fe0f","uc_greedy":"262e","shortnames":[":peace_symbol:"],"category":"symbols"},":pencil2:":{"uc_base":"270f","uc_output":"270f-fe0f","uc_match":"270f-fe0f","uc_greedy":"270f","shortnames":[],"category":"objects"},":person_bouncing_ball:":{"uc_base":"26f9","uc_output":"26f9-fe0f","uc_match":"26f9-fe0f","uc_greedy":"26f9","shortnames":[":basketball_player:",":person_with_ball:"],"category":"activity"},":pick:":{"uc_base":"26cf","uc_output":"26cf-fe0f","uc_match":"26cf-fe0f","uc_greedy":"26cf","shortnames":[],"category":"objects"},":play_pause:":{"uc_base":"23ef","uc_output":"23ef-fe0f","uc_match":"23ef-fe0f","uc_greedy":"23ef","shortnames":[],"category":"symbols"},":point_up:":{"uc_base":"261d","uc_output":"261d-fe0f","uc_match":"261d-fe0f","uc_greedy":"261d","shortnames":[],"category":"people"},":pound_symbol:":{"uc_base":"0023","uc_output":"0023-fe0f","uc_match":"0023-fe0f","uc_greedy":"0023","shortnames":[],"category":"symbols"},":radioactive:":{"uc_base":"2622","uc_output":"2622-fe0f","uc_match":"2622-fe0f","uc_greedy":"2622","shortnames":[":radioactive_sign:"],"category":"symbols"},":record_button:":{"uc_base":"23fa","uc_output":"23fa-fe0f","uc_match":"23fa-fe0f","uc_greedy":"23fa","shortnames":[],"category":"symbols"},":recycle:":{"uc_base":"267b","uc_output":"267b-fe0f","uc_match":"267b-fe0f","uc_greedy":"267b","shortnames":[],"category":"symbols"},":registered:":{"uc_base":"00ae","uc_output":"00ae-fe0f","uc_match":"00ae-fe0f","uc_greedy":"00ae","shortnames":[],"category":"symbols"},":relaxed:":{"uc_base":"263a","uc_output":"263a-fe0f","uc_match":"263a-fe0f","uc_greedy":"263a","shortnames":[],"category":"people"},":scales:":{"uc_base":"2696","uc_output":"2696-fe0f","uc_match":"2696-fe0f","uc_greedy":"2696","shortnames":[],"category":"objects"},":scissors:":{"uc_base":"2702","uc_output":"2702-fe0f","uc_match":"2702-fe0f","uc_greedy":"2702","shortnames":[],"category":"objects"},":secret:":{"uc_base":"3299","uc_output":"3299-fe0f","uc_match":"3299-fe0f","uc_greedy":"3299","shortnames":[],"category":"symbols"},":shamrock:":{"uc_base":"2618","uc_output":"2618-fe0f","uc_match":"2618-fe0f","uc_greedy":"2618","shortnames":[],"category":"nature"},":shinto_shrine:":{"uc_base":"26e9","uc_output":"26e9-fe0f","uc_match":"26e9-fe0f","uc_greedy":"26e9","shortnames":[],"category":"travel"},":skier:":{"uc_base":"26f7","uc_output":"26f7-fe0f","uc_match":"26f7-fe0f","uc_greedy":"26f7","shortnames":[],"category":"activity"},":skull_crossbones:":{"uc_base":"2620","uc_output":"2620-fe0f","uc_match":"2620-fe0f","uc_greedy":"2620","shortnames":[":skull_and_crossbones:"],"category":"people"},":snowflake:":{"uc_base":"2744","uc_output":"2744-fe0f","uc_match":"2744-fe0f","uc_greedy":"2744","shortnames":[],"category":"nature"},":snowman2:":{"uc_base":"2603","uc_output":"2603-fe0f","uc_match":"2603-fe0f","uc_greedy":"2603","shortnames":[],"category":"nature"},":spades:":{"uc_base":"2660","uc_output":"2660-fe0f","uc_match":"2660-fe0f","uc_greedy":"2660","shortnames":[],"category":"symbols"},":sparkle:":{"uc_base":"2747","uc_output":"2747-fe0f","uc_match":"2747-fe0f","uc_greedy":"2747","shortnames":[],"category":"symbols"},":star_and_crescent:":{"uc_base":"262a","uc_output":"262a-fe0f","uc_match":"262a-fe0f","uc_greedy":"262a","shortnames":[],"category":"symbols"},":star_of_david:":{"uc_base":"2721","uc_output":"2721-fe0f","uc_match":"2721-fe0f","uc_greedy":"2721","shortnames":[],"category":"symbols"},":stop_button:":{"uc_base":"23f9","uc_output":"23f9-fe0f","uc_match":"23f9-fe0f","uc_greedy":"23f9","shortnames":[],"category":"symbols"},":stopwatch:":{"uc_base":"23f1","uc_output":"23f1-fe0f","uc_match":"23f1-fe0f","uc_greedy":"23f1","shortnames":[],"category":"objects"},":sunny:":{"uc_base":"2600","uc_output":"2600-fe0f","uc_match":"2600-fe0f","uc_greedy":"2600","shortnames":[],"category":"nature"},":telephone:":{"uc_base":"260e","uc_output":"260e-fe0f","uc_match":"260e-fe0f","uc_greedy":"260e","shortnames":[],"category":"objects"},":thunder_cloud_rain:":{"uc_base":"26c8","uc_output":"26c8-fe0f","uc_match":"26c8-fe0f","uc_greedy":"26c8","shortnames":[":thunder_cloud_and_rain:"],"category":"nature"},":timer:":{"uc_base":"23f2","uc_output":"23f2-fe0f","uc_match":"23f2-fe0f","uc_greedy":"23f2","shortnames":[":timer_clock:"],"category":"objects"},":tm:":{"uc_base":"2122","uc_output":"2122-fe0f","uc_match":"2122-fe0f","uc_greedy":"2122","shortnames":[],"category":"symbols"},":track_next:":{"uc_base":"23ed","uc_output":"23ed-fe0f","uc_match":"23ed-fe0f","uc_greedy":"23ed","shortnames":[":next_track:"],"category":"symbols"},":track_previous:":{"uc_base":"23ee","uc_output":"23ee-fe0f","uc_match":"23ee-fe0f","uc_greedy":"23ee","shortnames":[":previous_track:"],"category":"symbols"},":umbrella2:":{"uc_base":"2602","uc_output":"2602-fe0f","uc_match":"2602-fe0f","uc_greedy":"2602","shortnames":[],"category":"people"},":urn:":{"uc_base":"26b1","uc_output":"26b1-fe0f","uc_match":"26b1-fe0f","uc_greedy":"26b1","shortnames":[":funeral_urn:"],"category":"objects"},":v:":{"uc_base":"270c","uc_output":"270c-fe0f","uc_match":"270c-fe0f","uc_greedy":"270c","shortnames":[],"category":"people"},":warning:":{"uc_base":"26a0","uc_output":"26a0-fe0f","uc_match":"26a0-fe0f","uc_greedy":"26a0","shortnames":[],"category":"symbols"},":wavy_dash:":{"uc_base":"3030","uc_output":"3030-fe0f","uc_match":"3030-fe0f","uc_greedy":"3030","shortnames":[],"category":"symbols"},":wheel_of_dharma:":{"uc_base":"2638","uc_output":"2638-fe0f","uc_match":"2638-fe0f","uc_greedy":"2638","shortnames":[],"category":"symbols"},":white_medium_square:":{"uc_base":"25fb","uc_output":"25fb-fe0f","uc_match":"25fb-fe0f","uc_greedy":"25fb","shortnames":[],"category":"symbols"},":white_small_square:":{"uc_base":"25ab","uc_output":"25ab-fe0f","uc_match":"25ab-fe0f","uc_greedy":"25ab","shortnames":[],"category":"symbols"},":writing_hand:":{"uc_base":"270d","uc_output":"270d-fe0f","uc_match":"270d-fe0f","uc_greedy":"270d","shortnames":[],"category":"people"},":yin_yang:":{"uc_base":"262f","uc_output":"262f-fe0f","uc_match":"262f-fe0f","uc_greedy":"262f","shortnames":[],"category":"symbols"},":100:":{"uc_base":"1f4af","uc_output":"1f4af","uc_match":"1f4af","uc_greedy":"1f4af","shortnames":[],"category":"symbols"},":1234:":{"uc_base":"1f522","uc_output":"1f522","uc_match":"1f522","uc_greedy":"1f522","shortnames":[],"category":"symbols"},":8ball:":{"uc_base":"1f3b1","uc_output":"1f3b1","uc_match":"1f3b1","uc_greedy":"1f3b1","shortnames":[],"category":"activity"},":ab:":{"uc_base":"1f18e","uc_output":"1f18e","uc_match":"1f18e","uc_greedy":"1f18e","shortnames":[],"category":"symbols"},":abc:":{"uc_base":"1f524","uc_output":"1f524","uc_match":"1f524","uc_greedy":"1f524","shortnames":[],"category":"symbols"},":abcd:":{"uc_base":"1f521","uc_output":"1f521","uc_match":"1f521","uc_greedy":"1f521","shortnames":[],"category":"symbols"},":accept:":{"uc_base":"1f251","uc_output":"1f251","uc_match":"1f251","uc_greedy":"1f251","shortnames":[],"category":"symbols"},":adult:":{"uc_base":"1f9d1","uc_output":"1f9d1","uc_match":"1f9d1","uc_greedy":"1f9d1","shortnames":[],"category":"people"},":aerial_tramway:":{"uc_base":"1f6a1","uc_output":"1f6a1","uc_match":"1f6a1","uc_greedy":"1f6a1","shortnames":[],"category":"travel"},":airplane_arriving:":{"uc_base":"1f6ec","uc_output":"1f6ec","uc_match":"1f6ec","uc_greedy":"1f6ec","shortnames":[],"category":"travel"},":airplane_departure:":{"uc_base":"1f6eb","uc_output":"1f6eb","uc_match":"1f6eb","uc_greedy":"1f6eb","shortnames":[],"category":"travel"},":alien:":{"uc_base":"1f47d","uc_output":"1f47d","uc_match":"1f47d","uc_greedy":"1f47d","shortnames":[],"category":"people"},":ambulance:":{"uc_base":"1f691","uc_output":"1f691","uc_match":"1f691","uc_greedy":"1f691","shortnames":[],"category":"travel"},":amphora:":{"uc_base":"1f3fa","uc_output":"1f3fa","uc_match":"1f3fa","uc_greedy":"1f3fa","shortnames":[],"category":"objects"},":angel:":{"uc_base":"1f47c","uc_output":"1f47c","uc_match":"1f47c","uc_greedy":"1f47c","shortnames":[],"category":"people"},":anger:":{"uc_base":"1f4a2","uc_output":"1f4a2","uc_match":"1f4a2","uc_greedy":"1f4a2","shortnames":[],"category":"symbols"},":angry:":{"uc_base":"1f620","uc_output":"1f620","uc_match":"1f620","uc_greedy":"1f620","shortnames":[],"category":"people"},":anguished:":{"uc_base":"1f627","uc_output":"1f627","uc_match":"1f627","uc_greedy":"1f627","shortnames":[],"category":"people"},":ant:":{"uc_base":"1f41c","uc_output":"1f41c","uc_match":"1f41c","uc_greedy":"1f41c","shortnames":[],"category":"nature"},":apple:":{"uc_base":"1f34e","uc_output":"1f34e","uc_match":"1f34e","uc_greedy":"1f34e","shortnames":[],"category":"food"},":arrow_down_small:":{"uc_base":"1f53d","uc_output":"1f53d","uc_match":"1f53d","uc_greedy":"1f53d","shortnames":[],"category":"symbols"},":arrow_up_small:":{"uc_base":"1f53c","uc_output":"1f53c","uc_match":"1f53c","uc_greedy":"1f53c","shortnames":[],"category":"symbols"},":arrows_clockwise:":{"uc_base":"1f503","uc_output":"1f503","uc_match":"1f503","uc_greedy":"1f503","shortnames":[],"category":"symbols"},":arrows_counterclockwise:":{"uc_base":"1f504","uc_output":"1f504","uc_match":"1f504","uc_greedy":"1f504","shortnames":[],"category":"symbols"},":art:":{"uc_base":"1f3a8","uc_output":"1f3a8","uc_match":"1f3a8","uc_greedy":"1f3a8","shortnames":[],"category":"activity"},":articulated_lorry:":{"uc_base":"1f69b","uc_output":"1f69b","uc_match":"1f69b","uc_greedy":"1f69b","shortnames":[],"category":"travel"},":astonished:":{"uc_base":"1f632","uc_output":"1f632","uc_match":"1f632","uc_greedy":"1f632","shortnames":[],"category":"people"},":athletic_shoe:":{"uc_base":"1f45f","uc_output":"1f45f","uc_match":"1f45f","uc_greedy":"1f45f","shortnames":[],"category":"people"},":atm:":{"uc_base":"1f3e7","uc_output":"1f3e7","uc_match":"1f3e7","uc_greedy":"1f3e7","shortnames":[],"category":"symbols"},":avocado:":{"uc_base":"1f951","uc_output":"1f951","uc_match":"1f951","uc_greedy":"1f951","shortnames":[],"category":"food"},":baby:":{"uc_base":"1f476","uc_output":"1f476","uc_match":"1f476","uc_greedy":"1f476","shortnames":[],"category":"people"},":baby_bottle:":{"uc_base":"1f37c","uc_output":"1f37c","uc_match":"1f37c","uc_greedy":"1f37c","shortnames":[],"category":"food"},":baby_chick:":{"uc_base":"1f424","uc_output":"1f424","uc_match":"1f424","uc_greedy":"1f424","shortnames":[],"category":"nature"},":baby_symbol:":{"uc_base":"1f6bc","uc_output":"1f6bc","uc_match":"1f6bc","uc_greedy":"1f6bc","shortnames":[],"category":"symbols"},":back:":{"uc_base":"1f519","uc_output":"1f519","uc_match":"1f519","uc_greedy":"1f519","shortnames":[],"category":"symbols"},":bacon:":{"uc_base":"1f953","uc_output":"1f953","uc_match":"1f953","uc_greedy":"1f953","shortnames":[],"category":"food"},":badminton:":{"uc_base":"1f3f8","uc_output":"1f3f8","uc_match":"1f3f8","uc_greedy":"1f3f8","shortnames":[],"category":"activity"},":baggage_claim:":{"uc_base":"1f6c4","uc_output":"1f6c4","uc_match":"1f6c4","uc_greedy":"1f6c4","shortnames":[],"category":"symbols"},":balloon:":{"uc_base":"1f388","uc_output":"1f388","uc_match":"1f388","uc_greedy":"1f388","shortnames":[],"category":"objects"},":bamboo:":{"uc_base":"1f38d","uc_output":"1f38d","uc_match":"1f38d","uc_greedy":"1f38d","shortnames":[],"category":"nature"},":banana:":{"uc_base":"1f34c","uc_output":"1f34c","uc_match":"1f34c","uc_greedy":"1f34c","shortnames":[],"category":"food"},":bank:":{"uc_base":"1f3e6","uc_output":"1f3e6","uc_match":"1f3e6","uc_greedy":"1f3e6","shortnames":[],"category":"travel"},":bar_chart:":{"uc_base":"1f4ca","uc_output":"1f4ca","uc_match":"1f4ca","uc_greedy":"1f4ca","shortnames":[],"category":"objects"},":barber:":{"uc_base":"1f488","uc_output":"1f488","uc_match":"1f488","uc_greedy":"1f488","shortnames":[],"category":"objects"},":basketball:":{"uc_base":"1f3c0","uc_output":"1f3c0","uc_match":"1f3c0","uc_greedy":"1f3c0","shortnames":[],"category":"activity"},":bat:":{"uc_base":"1f987","uc_output":"1f987","uc_match":"1f987","uc_greedy":"1f987","shortnames":[],"category":"nature"},":bath:":{"uc_base":"1f6c0","uc_output":"1f6c0","uc_match":"1f6c0","uc_greedy":"1f6c0","shortnames":[],"category":"objects"},":bathtub:":{"uc_base":"1f6c1","uc_output":"1f6c1","uc_match":"1f6c1","uc_greedy":"1f6c1","shortnames":[],"category":"objects"},":battery:":{"uc_base":"1f50b","uc_output":"1f50b","uc_match":"1f50b","uc_greedy":"1f50b","shortnames":[],"category":"objects"},":bear:":{"uc_base":"1f43b","uc_output":"1f43b","uc_match":"1f43b","uc_greedy":"1f43b","shortnames":[],"category":"nature"},":bearded_person:":{"uc_base":"1f9d4","uc_output":"1f9d4","uc_match":"1f9d4","uc_greedy":"1f9d4","shortnames":[],"category":"people"},":bee:":{"uc_base":"1f41d","uc_output":"1f41d","uc_match":"1f41d","uc_greedy":"1f41d","shortnames":[],"category":"nature"},":beer:":{"uc_base":"1f37a","uc_output":"1f37a","uc_match":"1f37a","uc_greedy":"1f37a","shortnames":[],"category":"food"},":beers:":{"uc_base":"1f37b","uc_output":"1f37b","uc_match":"1f37b","uc_greedy":"1f37b","shortnames":[],"category":"food"},":beetle:":{"uc_base":"1f41e","uc_output":"1f41e","uc_match":"1f41e","uc_greedy":"1f41e","shortnames":[],"category":"nature"},":beginner:":{"uc_base":"1f530","uc_output":"1f530","uc_match":"1f530","uc_greedy":"1f530","shortnames":[],"category":"symbols"},":bell:":{"uc_base":"1f514","uc_output":"1f514","uc_match":"1f514","uc_greedy":"1f514","shortnames":[],"category":"symbols"},":bento:":{"uc_base":"1f371","uc_output":"1f371","uc_match":"1f371","uc_greedy":"1f371","shortnames":[],"category":"food"},":bike:":{"uc_base":"1f6b2","uc_output":"1f6b2","uc_match":"1f6b2","uc_greedy":"1f6b2","shortnames":[],"category":"travel"},":bikini:":{"uc_base":"1f459","uc_output":"1f459","uc_match":"1f459","uc_greedy":"1f459","shortnames":[],"category":"people"},":billed_cap:":{"uc_base":"1f9e2","uc_output":"1f9e2","uc_match":"1f9e2","uc_greedy":"1f9e2","shortnames":[],"category":"people"},":bird:":{"uc_base":"1f426","uc_output":"1f426","uc_match":"1f426","uc_greedy":"1f426","shortnames":[],"category":"nature"},":birthday:":{"uc_base":"1f382","uc_output":"1f382","uc_match":"1f382","uc_greedy":"1f382","shortnames":[],"category":"food"},":black_heart:":{"uc_base":"1f5a4","uc_output":"1f5a4","uc_match":"1f5a4","uc_greedy":"1f5a4","shortnames":[],"category":"symbols"},":black_joker:":{"uc_base":"1f0cf","uc_output":"1f0cf","uc_match":"1f0cf","uc_greedy":"1f0cf","shortnames":[],"category":"symbols"},":black_square_button:":{"uc_base":"1f532","uc_output":"1f532","uc_match":"1f532","uc_greedy":"1f532","shortnames":[],"category":"symbols"},":blond_haired_person:":{"uc_base":"1f471","uc_output":"1f471","uc_match":"1f471","uc_greedy":"1f471","shortnames":[":person_with_blond_hair:"],"category":"people"},":blossom:":{"uc_base":"1f33c","uc_output":"1f33c","uc_match":"1f33c","uc_greedy":"1f33c","shortnames":[],"category":"nature"},":blowfish:":{"uc_base":"1f421","uc_output":"1f421","uc_match":"1f421","uc_greedy":"1f421","shortnames":[],"category":"nature"},":blue_book:":{"uc_base":"1f4d8","uc_output":"1f4d8","uc_match":"1f4d8","uc_greedy":"1f4d8","shortnames":[],"category":"objects"},":blue_car:":{"uc_base":"1f699","uc_output":"1f699","uc_match":"1f699","uc_greedy":"1f699","shortnames":[],"category":"travel"},":blue_circle:":{"uc_base":"1f535","uc_output":"1f535","uc_match":"1f535","uc_greedy":"1f535","shortnames":[],"category":"symbols"},":blue_heart:":{"uc_base":"1f499","uc_output":"1f499","uc_match":"1f499","uc_greedy":"1f499","shortnames":[],"category":"symbols"},":blush:":{"uc_base":"1f60a","uc_output":"1f60a","uc_match":"1f60a","uc_greedy":"1f60a","shortnames":[],"category":"people"},":boar:":{"uc_base":"1f417","uc_output":"1f417","uc_match":"1f417","uc_greedy":"1f417","shortnames":[],"category":"nature"},":bomb:":{"uc_base":"1f4a3","uc_output":"1f4a3","uc_match":"1f4a3","uc_greedy":"1f4a3","shortnames":[],"category":"objects"},":book:":{"uc_base":"1f4d6","uc_output":"1f4d6","uc_match":"1f4d6","uc_greedy":"1f4d6","shortnames":[],"category":"objects"},":bookmark:":{"uc_base":"1f516","uc_output":"1f516","uc_match":"1f516","uc_greedy":"1f516","shortnames":[],"category":"objects"},":bookmark_tabs:":{"uc_base":"1f4d1","uc_output":"1f4d1","uc_match":"1f4d1","uc_greedy":"1f4d1","shortnames":[],"category":"objects"},":books:":{"uc_base":"1f4da","uc_output":"1f4da","uc_match":"1f4da","uc_greedy":"1f4da","shortnames":[],"category":"objects"},":boom:":{"uc_base":"1f4a5","uc_output":"1f4a5","uc_match":"1f4a5","uc_greedy":"1f4a5","shortnames":[],"category":"nature"},":boot:":{"uc_base":"1f462","uc_output":"1f462","uc_match":"1f462","uc_greedy":"1f462","shortnames":[],"category":"people"},":bouquet:":{"uc_base":"1f490","uc_output":"1f490","uc_match":"1f490","uc_greedy":"1f490","shortnames":[],"category":"nature"},":bow_and_arrow:":{"uc_base":"1f3f9","uc_output":"1f3f9","uc_match":"1f3f9","uc_greedy":"1f3f9","shortnames":[":archery:"],"category":"activity"},":bowl_with_spoon:":{"uc_base":"1f963","uc_output":"1f963","uc_match":"1f963","uc_greedy":"1f963","shortnames":[],"category":"food"},":bowling:":{"uc_base":"1f3b3","uc_output":"1f3b3","uc_match":"1f3b3","uc_greedy":"1f3b3","shortnames":[],"category":"activity"},":boxing_glove:":{"uc_base":"1f94a","uc_output":"1f94a","uc_match":"1f94a","uc_greedy":"1f94a","shortnames":[":boxing_gloves:"],"category":"activity"},":boy:":{"uc_base":"1f466","uc_output":"1f466","uc_match":"1f466","uc_greedy":"1f466","shortnames":[],"category":"people"},":brain:":{"uc_base":"1f9e0","uc_output":"1f9e0","uc_match":"1f9e0","uc_greedy":"1f9e0","shortnames":[],"category":"people"},":bread:":{"uc_base":"1f35e","uc_output":"1f35e","uc_match":"1f35e","uc_greedy":"1f35e","shortnames":[],"category":"food"},":breast_feeding:":{"uc_base":"1f931","uc_output":"1f931","uc_match":"1f931","uc_greedy":"1f931","shortnames":[],"category":"activity"},":bride_with_veil:":{"uc_base":"1f470","uc_output":"1f470","uc_match":"1f470","uc_greedy":"1f470","shortnames":[],"category":"people"},":bridge_at_night:":{"uc_base":"1f309","uc_output":"1f309","uc_match":"1f309","uc_greedy":"1f309","shortnames":[],"category":"travel"},":briefcase:":{"uc_base":"1f4bc","uc_output":"1f4bc","uc_match":"1f4bc","uc_greedy":"1f4bc","shortnames":[],"category":"people"},":broccoli:":{"uc_base":"1f966","uc_output":"1f966","uc_match":"1f966","uc_greedy":"1f966","shortnames":[],"category":"food"},":broken_heart:":{"uc_base":"1f494","uc_output":"1f494","uc_match":"1f494","uc_greedy":"1f494","shortnames":[],"category":"symbols"},":bug:":{"uc_base":"1f41b","uc_output":"1f41b","uc_match":"1f41b","uc_greedy":"1f41b","shortnames":[],"category":"nature"},":bulb:":{"uc_base":"1f4a1","uc_output":"1f4a1","uc_match":"1f4a1","uc_greedy":"1f4a1","shortnames":[],"category":"objects"},":bullettrain_front:":{"uc_base":"1f685","uc_output":"1f685","uc_match":"1f685","uc_greedy":"1f685","shortnames":[],"category":"travel"},":bullettrain_side:":{"uc_base":"1f684","uc_output":"1f684","uc_match":"1f684","uc_greedy":"1f684","shortnames":[],"category":"travel"},":burrito:":{"uc_base":"1f32f","uc_output":"1f32f","uc_match":"1f32f","uc_greedy":"1f32f","shortnames":[],"category":"food"},":bus:":{"uc_base":"1f68c","uc_output":"1f68c","uc_match":"1f68c","uc_greedy":"1f68c","shortnames":[],"category":"travel"},":busstop:":{"uc_base":"1f68f","uc_output":"1f68f","uc_match":"1f68f","uc_greedy":"1f68f","shortnames":[],"category":"travel"},":bust_in_silhouette:":{"uc_base":"1f464","uc_output":"1f464","uc_match":"1f464","uc_greedy":"1f464","shortnames":[],"category":"people"},":busts_in_silhouette:":{"uc_base":"1f465","uc_output":"1f465","uc_match":"1f465","uc_greedy":"1f465","shortnames":[],"category":"people"},":butterfly:":{"uc_base":"1f98b","uc_output":"1f98b","uc_match":"1f98b","uc_greedy":"1f98b","shortnames":[],"category":"nature"},":cactus:":{"uc_base":"1f335","uc_output":"1f335","uc_match":"1f335","uc_greedy":"1f335","shortnames":[],"category":"nature"},":cake:":{"uc_base":"1f370","uc_output":"1f370","uc_match":"1f370","uc_greedy":"1f370","shortnames":[],"category":"food"},":calendar:":{"uc_base":"1f4c6","uc_output":"1f4c6","uc_match":"1f4c6","uc_greedy":"1f4c6","shortnames":[],"category":"objects"},":call_me:":{"uc_base":"1f919","uc_output":"1f919","uc_match":"1f919","uc_greedy":"1f919","shortnames":[":call_me_hand:"],"category":"people"},":calling:":{"uc_base":"1f4f2","uc_output":"1f4f2","uc_match":"1f4f2","uc_greedy":"1f4f2","shortnames":[],"category":"objects"},":camel:":{"uc_base":"1f42b","uc_output":"1f42b","uc_match":"1f42b","uc_greedy":"1f42b","shortnames":[],"category":"nature"},":camera:":{"uc_base":"1f4f7","uc_output":"1f4f7","uc_match":"1f4f7","uc_greedy":"1f4f7","shortnames":[],"category":"objects"},":camera_with_flash:":{"uc_base":"1f4f8","uc_output":"1f4f8","uc_match":"1f4f8","uc_greedy":"1f4f8","shortnames":[],"category":"objects"},":candy:":{"uc_base":"1f36c","uc_output":"1f36c","uc_match":"1f36c","uc_greedy":"1f36c","shortnames":[],"category":"food"},":canned_food:":{"uc_base":"1f96b","uc_output":"1f96b","uc_match":"1f96b","uc_greedy":"1f96b","shortnames":[],"category":"food"},":canoe:":{"uc_base":"1f6f6","uc_output":"1f6f6","uc_match":"1f6f6","uc_greedy":"1f6f6","shortnames":[":kayak:"],"category":"travel"},":capital_abcd:":{"uc_base":"1f520","uc_output":"1f520","uc_match":"1f520","uc_greedy":"1f520","shortnames":[],"category":"symbols"},":card_index:":{"uc_base":"1f4c7","uc_output":"1f4c7","uc_match":"1f4c7","uc_greedy":"1f4c7","shortnames":[],"category":"objects"},":carousel_horse:":{"uc_base":"1f3a0","uc_output":"1f3a0","uc_match":"1f3a0","uc_greedy":"1f3a0","shortnames":[],"category":"travel"},":carrot:":{"uc_base":"1f955","uc_output":"1f955","uc_match":"1f955","uc_greedy":"1f955","shortnames":[],"category":"food"},":cat2:":{"uc_base":"1f408","uc_output":"1f408","uc_match":"1f408","uc_greedy":"1f408","shortnames":[],"category":"nature"},":cat:":{"uc_base":"1f431","uc_output":"1f431","uc_match":"1f431","uc_greedy":"1f431","shortnames":[],"category":"nature"},":cd:":{"uc_base":"1f4bf","uc_output":"1f4bf","uc_match":"1f4bf","uc_greedy":"1f4bf","shortnames":[],"category":"objects"},":champagne:":{"uc_base":"1f37e","uc_output":"1f37e","uc_match":"1f37e","uc_greedy":"1f37e","shortnames":[":bottle_with_popping_cork:"],"category":"food"},":champagne_glass:":{"uc_base":"1f942","uc_output":"1f942","uc_match":"1f942","uc_greedy":"1f942","shortnames":[":clinking_glass:"],"category":"food"},":chart:":{"uc_base":"1f4b9","uc_output":"1f4b9","uc_match":"1f4b9","uc_greedy":"1f4b9","shortnames":[],"category":"symbols"},":chart_with_downwards_trend:":{"uc_base":"1f4c9","uc_output":"1f4c9","uc_match":"1f4c9","uc_greedy":"1f4c9","shortnames":[],"category":"objects"},":chart_with_upwards_trend:":{"uc_base":"1f4c8","uc_output":"1f4c8","uc_match":"1f4c8","uc_greedy":"1f4c8","shortnames":[],"category":"objects"},":checkered_flag:":{"uc_base":"1f3c1","uc_output":"1f3c1","uc_match":"1f3c1","uc_greedy":"1f3c1","shortnames":[],"category":"flags"},":cheese:":{"uc_base":"1f9c0","uc_output":"1f9c0","uc_match":"1f9c0","uc_greedy":"1f9c0","shortnames":[":cheese_wedge:"],"category":"food"},":cherries:":{"uc_base":"1f352","uc_output":"1f352","uc_match":"1f352","uc_greedy":"1f352","shortnames":[],"category":"food"},":cherry_blossom:":{"uc_base":"1f338","uc_output":"1f338","uc_match":"1f338","uc_greedy":"1f338","shortnames":[],"category":"nature"},":chestnut:":{"uc_base":"1f330","uc_output":"1f330","uc_match":"1f330","uc_greedy":"1f330","shortnames":[],"category":"food"},":chicken:":{"uc_base":"1f414","uc_output":"1f414","uc_match":"1f414","uc_greedy":"1f414","shortnames":[],"category":"nature"},":child:":{"uc_base":"1f9d2","uc_output":"1f9d2","uc_match":"1f9d2","uc_greedy":"1f9d2","shortnames":[],"category":"people"},":children_crossing:":{"uc_base":"1f6b8","uc_output":"1f6b8","uc_match":"1f6b8","uc_greedy":"1f6b8","shortnames":[],"category":"symbols"},":chocolate_bar:":{"uc_base":"1f36b","uc_output":"1f36b","uc_match":"1f36b","uc_greedy":"1f36b","shortnames":[],"category":"food"},":chopsticks:":{"uc_base":"1f962","uc_output":"1f962","uc_match":"1f962","uc_greedy":"1f962","shortnames":[],"category":"food"},":christmas_tree:":{"uc_base":"1f384","uc_output":"1f384","uc_match":"1f384","uc_greedy":"1f384","shortnames":[],"category":"nature"},":cinema:":{"uc_base":"1f3a6","uc_output":"1f3a6","uc_match":"1f3a6","uc_greedy":"1f3a6","shortnames":[],"category":"symbols"},":circus_tent:":{"uc_base":"1f3aa","uc_output":"1f3aa","uc_match":"1f3aa","uc_greedy":"1f3aa","shortnames":[],"category":"activity"},":city_dusk:":{"uc_base":"1f306","uc_output":"1f306","uc_match":"1f306","uc_greedy":"1f306","shortnames":[],"category":"travel"},":city_sunset:":{"uc_base":"1f307","uc_output":"1f307","uc_match":"1f307","uc_greedy":"1f307","shortnames":[":city_sunrise:"],"category":"travel"},":cl:":{"uc_base":"1f191","uc_output":"1f191","uc_match":"1f191","uc_greedy":"1f191","shortnames":[],"category":"symbols"},":clap:":{"uc_base":"1f44f","uc_output":"1f44f","uc_match":"1f44f","uc_greedy":"1f44f","shortnames":[],"category":"people"},":clapper:":{"uc_base":"1f3ac","uc_output":"1f3ac","uc_match":"1f3ac","uc_greedy":"1f3ac","shortnames":[],"category":"activity"},":clipboard:":{"uc_base":"1f4cb","uc_output":"1f4cb","uc_match":"1f4cb","uc_greedy":"1f4cb","shortnames":[],"category":"objects"},":clock1030:":{"uc_base":"1f565","uc_output":"1f565","uc_match":"1f565","uc_greedy":"1f565","shortnames":[],"category":"symbols"},":clock10:":{"uc_base":"1f559","uc_output":"1f559","uc_match":"1f559","uc_greedy":"1f559","shortnames":[],"category":"symbols"},":clock1130:":{"uc_base":"1f566","uc_output":"1f566","uc_match":"1f566","uc_greedy":"1f566","shortnames":[],"category":"symbols"},":clock11:":{"uc_base":"1f55a","uc_output":"1f55a","uc_match":"1f55a","uc_greedy":"1f55a","shortnames":[],"category":"symbols"},":clock1230:":{"uc_base":"1f567","uc_output":"1f567","uc_match":"1f567","uc_greedy":"1f567","shortnames":[],"category":"symbols"},":clock12:":{"uc_base":"1f55b","uc_output":"1f55b","uc_match":"1f55b","uc_greedy":"1f55b","shortnames":[],"category":"symbols"},":clock130:":{"uc_base":"1f55c","uc_output":"1f55c","uc_match":"1f55c","uc_greedy":"1f55c","shortnames":[],"category":"symbols"},":clock1:":{"uc_base":"1f550","uc_output":"1f550","uc_match":"1f550","uc_greedy":"1f550","shortnames":[],"category":"symbols"},":clock230:":{"uc_base":"1f55d","uc_output":"1f55d","uc_match":"1f55d","uc_greedy":"1f55d","shortnames":[],"category":"symbols"},":clock2:":{"uc_base":"1f551","uc_output":"1f551","uc_match":"1f551","uc_greedy":"1f551","shortnames":[],"category":"symbols"},":clock330:":{"uc_base":"1f55e","uc_output":"1f55e","uc_match":"1f55e","uc_greedy":"1f55e","shortnames":[],"category":"symbols"},":clock3:":{"uc_base":"1f552","uc_output":"1f552","uc_match":"1f552","uc_greedy":"1f552","shortnames":[],"category":"symbols"},":clock430:":{"uc_base":"1f55f","uc_output":"1f55f","uc_match":"1f55f","uc_greedy":"1f55f","shortnames":[],"category":"symbols"},":clock4:":{"uc_base":"1f553","uc_output":"1f553","uc_match":"1f553","uc_greedy":"1f553","shortnames":[],"category":"symbols"},":clock530:":{"uc_base":"1f560","uc_output":"1f560","uc_match":"1f560","uc_greedy":"1f560","shortnames":[],"category":"symbols"},":clock5:":{"uc_base":"1f554","uc_output":"1f554","uc_match":"1f554","uc_greedy":"1f554","shortnames":[],"category":"symbols"},":clock630:":{"uc_base":"1f561","uc_output":"1f561","uc_match":"1f561","uc_greedy":"1f561","shortnames":[],"category":"symbols"},":clock6:":{"uc_base":"1f555","uc_output":"1f555","uc_match":"1f555","uc_greedy":"1f555","shortnames":[],"category":"symbols"},":clock730:":{"uc_base":"1f562","uc_output":"1f562","uc_match":"1f562","uc_greedy":"1f562","shortnames":[],"category":"symbols"},":clock7:":{"uc_base":"1f556","uc_output":"1f556","uc_match":"1f556","uc_greedy":"1f556","shortnames":[],"category":"symbols"},":clock830:":{"uc_base":"1f563","uc_output":"1f563","uc_match":"1f563","uc_greedy":"1f563","shortnames":[],"category":"symbols"},":clock8:":{"uc_base":"1f557","uc_output":"1f557","uc_match":"1f557","uc_greedy":"1f557","shortnames":[],"category":"symbols"},":clock930:":{"uc_base":"1f564","uc_output":"1f564","uc_match":"1f564","uc_greedy":"1f564","shortnames":[],"category":"symbols"},":clock9:":{"uc_base":"1f558","uc_output":"1f558","uc_match":"1f558","uc_greedy":"1f558","shortnames":[],"category":"symbols"},":closed_book:":{"uc_base":"1f4d5","uc_output":"1f4d5","uc_match":"1f4d5","uc_greedy":"1f4d5","shortnames":[],"category":"objects"},":closed_lock_with_key:":{"uc_base":"1f510","uc_output":"1f510","uc_match":"1f510","uc_greedy":"1f510","shortnames":[],"category":"objects"},":closed_umbrella:":{"uc_base":"1f302","uc_output":"1f302","uc_match":"1f302","uc_greedy":"1f302","shortnames":[],"category":"people"},":clown:":{"uc_base":"1f921","uc_output":"1f921","uc_match":"1f921","uc_greedy":"1f921","shortnames":[":clown_face:"],"category":"people"},":coat:":{"uc_base":"1f9e5","uc_output":"1f9e5","uc_match":"1f9e5","uc_greedy":"1f9e5","shortnames":[],"category":"people"},":cocktail:":{"uc_base":"1f378","uc_output":"1f378","uc_match":"1f378","uc_greedy":"1f378","shortnames":[],"category":"food"},":coconut:":{"uc_base":"1f965","uc_output":"1f965","uc_match":"1f965","uc_greedy":"1f965","shortnames":[],"category":"food"},":cold_sweat:":{"uc_base":"1f630","uc_output":"1f630","uc_match":"1f630","uc_greedy":"1f630","shortnames":[],"category":"people"},":computer:":{"uc_base":"1f4bb","uc_output":"1f4bb","uc_match":"1f4bb","uc_greedy":"1f4bb","shortnames":[],"category":"objects"},":confetti_ball:":{"uc_base":"1f38a","uc_output":"1f38a","uc_match":"1f38a","uc_greedy":"1f38a","shortnames":[],"category":"objects"},":confounded:":{"uc_base":"1f616","uc_output":"1f616","uc_match":"1f616","uc_greedy":"1f616","shortnames":[],"category":"people"},":confused:":{"uc_base":"1f615","uc_output":"1f615","uc_match":"1f615","uc_greedy":"1f615","shortnames":[],"category":"people"},":construction:":{"uc_base":"1f6a7","uc_output":"1f6a7","uc_match":"1f6a7","uc_greedy":"1f6a7","shortnames":[],"category":"travel"},":construction_worker:":{"uc_base":"1f477","uc_output":"1f477","uc_match":"1f477","uc_greedy":"1f477","shortnames":[],"category":"people"},":convenience_store:":{"uc_base":"1f3ea","uc_output":"1f3ea","uc_match":"1f3ea","uc_greedy":"1f3ea","shortnames":[],"category":"travel"},":cookie:":{"uc_base":"1f36a","uc_output":"1f36a","uc_match":"1f36a","uc_greedy":"1f36a","shortnames":[],"category":"food"},":cooking:":{"uc_base":"1f373","uc_output":"1f373","uc_match":"1f373","uc_greedy":"1f373","shortnames":[],"category":"food"},":cool:":{"uc_base":"1f192","uc_output":"1f192","uc_match":"1f192","uc_greedy":"1f192","shortnames":[],"category":"symbols"},":corn:":{"uc_base":"1f33d","uc_output":"1f33d","uc_match":"1f33d","uc_greedy":"1f33d","shortnames":[],"category":"food"},":couple:":{"uc_base":"1f46b","uc_output":"1f46b","uc_match":"1f46b","uc_greedy":"1f46b","shortnames":[],"category":"people"},":couple_with_heart:":{"uc_base":"1f491","uc_output":"1f491","uc_match":"1f491","uc_greedy":"1f491","shortnames":[],"category":"people"},":couplekiss:":{"uc_base":"1f48f","uc_output":"1f48f","uc_match":"1f48f","uc_greedy":"1f48f","shortnames":[],"category":"people"},":cow2:":{"uc_base":"1f404","uc_output":"1f404","uc_match":"1f404","uc_greedy":"1f404","shortnames":[],"category":"nature"},":cow:":{"uc_base":"1f42e","uc_output":"1f42e","uc_match":"1f42e","uc_greedy":"1f42e","shortnames":[],"category":"nature"},":cowboy:":{"uc_base":"1f920","uc_output":"1f920","uc_match":"1f920","uc_greedy":"1f920","shortnames":[":face_with_cowboy_hat:"],"category":"people"},":crab:":{"uc_base":"1f980","uc_output":"1f980","uc_match":"1f980","uc_greedy":"1f980","shortnames":[],"category":"nature"},":crazy_face:":{"uc_base":"1f92a","uc_output":"1f92a","uc_match":"1f92a","uc_greedy":"1f92a","shortnames":[],"category":"people"},":credit_card:":{"uc_base":"1f4b3","uc_output":"1f4b3","uc_match":"1f4b3","uc_greedy":"1f4b3","shortnames":[],"category":"objects"},":crescent_moon:":{"uc_base":"1f319","uc_output":"1f319","uc_match":"1f319","uc_greedy":"1f319","shortnames":[],"category":"nature"},":cricket:":{"uc_base":"1f997","uc_output":"1f997","uc_match":"1f997","uc_greedy":"1f997","shortnames":[],"category":"nature"},":cricket_game:":{"uc_base":"1f3cf","uc_output":"1f3cf","uc_match":"1f3cf","uc_greedy":"1f3cf","shortnames":[":cricket_bat_ball:"],"category":"activity"},":crocodile:":{"uc_base":"1f40a","uc_output":"1f40a","uc_match":"1f40a","uc_greedy":"1f40a","shortnames":[],"category":"nature"},":croissant:":{"uc_base":"1f950","uc_output":"1f950","uc_match":"1f950","uc_greedy":"1f950","shortnames":[],"category":"food"},":crossed_flags:":{"uc_base":"1f38c","uc_output":"1f38c","uc_match":"1f38c","uc_greedy":"1f38c","shortnames":[],"category":"flags"},":crown:":{"uc_base":"1f451","uc_output":"1f451","uc_match":"1f451","uc_greedy":"1f451","shortnames":[],"category":"people"},":cry:":{"uc_base":"1f622","uc_output":"1f622","uc_match":"1f622","uc_greedy":"1f622","shortnames":[],"category":"people"},":crying_cat_face:":{"uc_base":"1f63f","uc_output":"1f63f","uc_match":"1f63f","uc_greedy":"1f63f","shortnames":[],"category":"people"},":crystal_ball:":{"uc_base":"1f52e","uc_output":"1f52e","uc_match":"1f52e","uc_greedy":"1f52e","shortnames":[],"category":"objects"},":cucumber:":{"uc_base":"1f952","uc_output":"1f952","uc_match":"1f952","uc_greedy":"1f952","shortnames":[],"category":"food"},":cup_with_straw:":{"uc_base":"1f964","uc_output":"1f964","uc_match":"1f964","uc_greedy":"1f964","shortnames":[],"category":"food"},":cupid:":{"uc_base":"1f498","uc_output":"1f498","uc_match":"1f498","uc_greedy":"1f498","shortnames":[],"category":"symbols"},":curling_stone:":{"uc_base":"1f94c","uc_output":"1f94c","uc_match":"1f94c","uc_greedy":"1f94c","shortnames":[],"category":"activity"},":currency_exchange:":{"uc_base":"1f4b1","uc_output":"1f4b1","uc_match":"1f4b1","uc_greedy":"1f4b1","shortnames":[],"category":"symbols"},":curry:":{"uc_base":"1f35b","uc_output":"1f35b","uc_match":"1f35b","uc_greedy":"1f35b","shortnames":[],"category":"food"},":custard:":{"uc_base":"1f36e","uc_output":"1f36e","uc_match":"1f36e","uc_greedy":"1f36e","shortnames":[":pudding:",":flan:"],"category":"food"},":customs:":{"uc_base":"1f6c3","uc_output":"1f6c3","uc_match":"1f6c3","uc_greedy":"1f6c3","shortnames":[],"category":"symbols"},":cut_of_meat:":{"uc_base":"1f969","uc_output":"1f969","uc_match":"1f969","uc_greedy":"1f969","shortnames":[],"category":"food"},":cyclone:":{"uc_base":"1f300","uc_output":"1f300","uc_match":"1f300","uc_greedy":"1f300","shortnames":[],"category":"symbols"},":dancer:":{"uc_base":"1f483","uc_output":"1f483","uc_match":"1f483","uc_greedy":"1f483","shortnames":[],"category":"people"},":dango:":{"uc_base":"1f361","uc_output":"1f361","uc_match":"1f361","uc_greedy":"1f361","shortnames":[],"category":"food"},":dart:":{"uc_base":"1f3af","uc_output":"1f3af","uc_match":"1f3af","uc_greedy":"1f3af","shortnames":[],"category":"activity"},":dash:":{"uc_base":"1f4a8","uc_output":"1f4a8","uc_match":"1f4a8","uc_greedy":"1f4a8","shortnames":[],"category":"nature"},":date:":{"uc_base":"1f4c5","uc_output":"1f4c5","uc_match":"1f4c5","uc_greedy":"1f4c5","shortnames":[],"category":"objects"},":deciduous_tree:":{"uc_base":"1f333","uc_output":"1f333","uc_match":"1f333","uc_greedy":"1f333","shortnames":[],"category":"nature"},":deer:":{"uc_base":"1f98c","uc_output":"1f98c","uc_match":"1f98c","uc_greedy":"1f98c","shortnames":[],"category":"nature"},":department_store:":{"uc_base":"1f3ec","uc_output":"1f3ec","uc_match":"1f3ec","uc_greedy":"1f3ec","shortnames":[],"category":"travel"},":diamond_shape_with_a_dot_inside:":{"uc_base":"1f4a0","uc_output":"1f4a0","uc_match":"1f4a0","uc_greedy":"1f4a0","shortnames":[],"category":"symbols"},":disappointed:":{"uc_base":"1f61e","uc_output":"1f61e","uc_match":"1f61e","uc_greedy":"1f61e","shortnames":[],"category":"people"},":disappointed_relieved:":{"uc_base":"1f625","uc_output":"1f625","uc_match":"1f625","uc_greedy":"1f625","shortnames":[],"category":"people"},":dizzy:":{"uc_base":"1f4ab","uc_output":"1f4ab","uc_match":"1f4ab","uc_greedy":"1f4ab","shortnames":[],"category":"nature"},":dizzy_face:":{"uc_base":"1f635","uc_output":"1f635","uc_match":"1f635","uc_greedy":"1f635","shortnames":[],"category":"people"},":do_not_litter:":{"uc_base":"1f6af","uc_output":"1f6af","uc_match":"1f6af","uc_greedy":"1f6af","shortnames":[],"category":"symbols"},":dog2:":{"uc_base":"1f415","uc_output":"1f415","uc_match":"1f415","uc_greedy":"1f415","shortnames":[],"category":"nature"},":dog:":{"uc_base":"1f436","uc_output":"1f436","uc_match":"1f436","uc_greedy":"1f436","shortnames":[],"category":"nature"},":dollar:":{"uc_base":"1f4b5","uc_output":"1f4b5","uc_match":"1f4b5","uc_greedy":"1f4b5","shortnames":[],"category":"objects"},":dolls:":{"uc_base":"1f38e","uc_output":"1f38e","uc_match":"1f38e","uc_greedy":"1f38e","shortnames":[],"category":"objects"},":dolphin:":{"uc_base":"1f42c","uc_output":"1f42c","uc_match":"1f42c","uc_greedy":"1f42c","shortnames":[],"category":"nature"},":door:":{"uc_base":"1f6aa","uc_output":"1f6aa","uc_match":"1f6aa","uc_greedy":"1f6aa","shortnames":[],"category":"objects"},":doughnut:":{"uc_base":"1f369","uc_output":"1f369","uc_match":"1f369","uc_greedy":"1f369","shortnames":[],"category":"food"},":dragon:":{"uc_base":"1f409","uc_output":"1f409","uc_match":"1f409","uc_greedy":"1f409","shortnames":[],"category":"nature"},":dragon_face:":{"uc_base":"1f432","uc_output":"1f432","uc_match":"1f432","uc_greedy":"1f432","shortnames":[],"category":"nature"},":dress:":{"uc_base":"1f457","uc_output":"1f457","uc_match":"1f457","uc_greedy":"1f457","shortnames":[],"category":"people"},":dromedary_camel:":{"uc_base":"1f42a","uc_output":"1f42a","uc_match":"1f42a","uc_greedy":"1f42a","shortnames":[],"category":"nature"},":drooling_face:":{"uc_base":"1f924","uc_output":"1f924","uc_match":"1f924","uc_greedy":"1f924","shortnames":[":drool:"],"category":"people"},":droplet:":{"uc_base":"1f4a7","uc_output":"1f4a7","uc_match":"1f4a7","uc_greedy":"1f4a7","shortnames":[],"category":"nature"},":drum:":{"uc_base":"1f941","uc_output":"1f941","uc_match":"1f941","uc_greedy":"1f941","shortnames":[":drum_with_drumsticks:"],"category":"activity"},":duck:":{"uc_base":"1f986","uc_output":"1f986","uc_match":"1f986","uc_greedy":"1f986","shortnames":[],"category":"nature"},":dumpling:":{"uc_base":"1f95f","uc_output":"1f95f","uc_match":"1f95f","uc_greedy":"1f95f","shortnames":[],"category":"food"},":dvd:":{"uc_base":"1f4c0","uc_output":"1f4c0","uc_match":"1f4c0","uc_greedy":"1f4c0","shortnames":[],"category":"objects"},":e-mail:":{"uc_base":"1f4e7","uc_output":"1f4e7","uc_match":"1f4e7","uc_greedy":"1f4e7","shortnames":[":email:"],"category":"objects"},":eagle:":{"uc_base":"1f985","uc_output":"1f985","uc_match":"1f985","uc_greedy":"1f985","shortnames":[],"category":"nature"},":ear:":{"uc_base":"1f442","uc_output":"1f442","uc_match":"1f442","uc_greedy":"1f442","shortnames":[],"category":"people"},":ear_of_rice:":{"uc_base":"1f33e","uc_output":"1f33e","uc_match":"1f33e","uc_greedy":"1f33e","shortnames":[],"category":"nature"},":earth_africa:":{"uc_base":"1f30d","uc_output":"1f30d","uc_match":"1f30d","uc_greedy":"1f30d","shortnames":[],"category":"nature"},":earth_americas:":{"uc_base":"1f30e","uc_output":"1f30e","uc_match":"1f30e","uc_greedy":"1f30e","shortnames":[],"category":"nature"},":earth_asia:":{"uc_base":"1f30f","uc_output":"1f30f","uc_match":"1f30f","uc_greedy":"1f30f","shortnames":[],"category":"nature"},":egg:":{"uc_base":"1f95a","uc_output":"1f95a","uc_match":"1f95a","uc_greedy":"1f95a","shortnames":[],"category":"food"},":eggplant:":{"uc_base":"1f346","uc_output":"1f346","uc_match":"1f346","uc_greedy":"1f346","shortnames":[],"category":"food"},":electric_plug:":{"uc_base":"1f50c","uc_output":"1f50c","uc_match":"1f50c","uc_greedy":"1f50c","shortnames":[],"category":"objects"},":elephant:":{"uc_base":"1f418","uc_output":"1f418","uc_match":"1f418","uc_greedy":"1f418","shortnames":[],"category":"nature"},":elf:":{"uc_base":"1f9dd","uc_output":"1f9dd","uc_match":"1f9dd","uc_greedy":"1f9dd","shortnames":[],"category":"people"},":end:":{"uc_base":"1f51a","uc_output":"1f51a","uc_match":"1f51a","uc_greedy":"1f51a","shortnames":[],"category":"symbols"},":envelope_with_arrow:":{"uc_base":"1f4e9","uc_output":"1f4e9","uc_match":"1f4e9","uc_greedy":"1f4e9","shortnames":[],"category":"objects"},":euro:":{"uc_base":"1f4b6","uc_output":"1f4b6","uc_match":"1f4b6","uc_greedy":"1f4b6","shortnames":[],"category":"objects"},":european_castle:":{"uc_base":"1f3f0","uc_output":"1f3f0","uc_match":"1f3f0","uc_greedy":"1f3f0","shortnames":[],"category":"travel"},":european_post_office:":{"uc_base":"1f3e4","uc_output":"1f3e4","uc_match":"1f3e4","uc_greedy":"1f3e4","shortnames":[],"category":"travel"},":evergreen_tree:":{"uc_base":"1f332","uc_output":"1f332","uc_match":"1f332","uc_greedy":"1f332","shortnames":[],"category":"nature"},":exploding_head:":{"uc_base":"1f92f","uc_output":"1f92f","uc_match":"1f92f","uc_greedy":"1f92f","shortnames":[],"category":"people"},":expressionless:":{"uc_base":"1f611","uc_output":"1f611","uc_match":"1f611","uc_greedy":"1f611","shortnames":[],"category":"people"},":eyeglasses:":{"uc_base":"1f453","uc_output":"1f453","uc_match":"1f453","uc_greedy":"1f453","shortnames":[],"category":"people"},":eyes:":{"uc_base":"1f440","uc_output":"1f440","uc_match":"1f440","uc_greedy":"1f440","shortnames":[],"category":"people"},":face_vomiting:":{"uc_base":"1f92e","uc_output":"1f92e","uc_match":"1f92e","uc_greedy":"1f92e","shortnames":[],"category":"people"},":face_with_hand_over_mouth:":{"uc_base":"1f92d","uc_output":"1f92d","uc_match":"1f92d","uc_greedy":"1f92d","shortnames":[],"category":"people"},":face_with_monocle:":{"uc_base":"1f9d0","uc_output":"1f9d0","uc_match":"1f9d0","uc_greedy":"1f9d0","shortnames":[],"category":"people"},":face_with_raised_eyebrow:":{"uc_base":"1f928","uc_output":"1f928","uc_match":"1f928","uc_greedy":"1f928","shortnames":[],"category":"people"},":face_with_symbols_over_mouth:":{"uc_base":"1f92c","uc_output":"1f92c","uc_match":"1f92c","uc_greedy":"1f92c","shortnames":[],"category":"people"},":factory:":{"uc_base":"1f3ed","uc_output":"1f3ed","uc_match":"1f3ed","uc_greedy":"1f3ed","shortnames":[],"category":"travel"},":fairy:":{"uc_base":"1f9da","uc_output":"1f9da","uc_match":"1f9da","uc_greedy":"1f9da","shortnames":[],"category":"people"},":fallen_leaf:":{"uc_base":"1f342","uc_output":"1f342","uc_match":"1f342","uc_greedy":"1f342","shortnames":[],"category":"nature"},":family:":{"uc_base":"1f46a","uc_output":"1f46a","uc_match":"1f46a","uc_greedy":"1f46a","shortnames":[],"category":"people"},":fax:":{"uc_base":"1f4e0","uc_output":"1f4e0","uc_match":"1f4e0","uc_greedy":"1f4e0","shortnames":[],"category":"objects"},":fearful:":{"uc_base":"1f628","uc_output":"1f628","uc_match":"1f628","uc_greedy":"1f628","shortnames":[],"category":"people"},":feet:":{"uc_base":"1f43e","uc_output":"1f43e","uc_match":"1f43e","uc_greedy":"1f43e","shortnames":[":paw_prints:"],"category":"nature"},":ferris_wheel:":{"uc_base":"1f3a1","uc_output":"1f3a1","uc_match":"1f3a1","uc_greedy":"1f3a1","shortnames":[],"category":"travel"},":field_hockey:":{"uc_base":"1f3d1","uc_output":"1f3d1","uc_match":"1f3d1","uc_greedy":"1f3d1","shortnames":[],"category":"activity"},":file_folder:":{"uc_base":"1f4c1","uc_output":"1f4c1","uc_match":"1f4c1","uc_greedy":"1f4c1","shortnames":[],"category":"objects"},":fingers_crossed:":{"uc_base":"1f91e","uc_output":"1f91e","uc_match":"1f91e","uc_greedy":"1f91e","shortnames":[":hand_with_index_and_middle_finger_crossed:"],"category":"people"},":fire:":{"uc_base":"1f525","uc_output":"1f525","uc_match":"1f525","uc_greedy":"1f525","shortnames":[":flame:"],"category":"nature"},":fire_engine:":{"uc_base":"1f692","uc_output":"1f692","uc_match":"1f692","uc_greedy":"1f692","shortnames":[],"category":"travel"},":fireworks:":{"uc_base":"1f386","uc_output":"1f386","uc_match":"1f386","uc_greedy":"1f386","shortnames":[],"category":"travel"},":first_place:":{"uc_base":"1f947","uc_output":"1f947","uc_match":"1f947","uc_greedy":"1f947","shortnames":[":first_place_medal:"],"category":"activity"},":first_quarter_moon:":{"uc_base":"1f313","uc_output":"1f313","uc_match":"1f313","uc_greedy":"1f313","shortnames":[],"category":"nature"},":first_quarter_moon_with_face:":{"uc_base":"1f31b","uc_output":"1f31b","uc_match":"1f31b","uc_greedy":"1f31b","shortnames":[],"category":"nature"},":fish:":{"uc_base":"1f41f","uc_output":"1f41f","uc_match":"1f41f","uc_greedy":"1f41f","shortnames":[],"category":"nature"},":fish_cake:":{"uc_base":"1f365","uc_output":"1f365","uc_match":"1f365","uc_greedy":"1f365","shortnames":[],"category":"food"},":fishing_pole_and_fish:":{"uc_base":"1f3a3","uc_output":"1f3a3","uc_match":"1f3a3","uc_greedy":"1f3a3","shortnames":[],"category":"activity"},":flag_black:":{"uc_base":"1f3f4","uc_output":"1f3f4","uc_match":"1f3f4","uc_greedy":"1f3f4","shortnames":[":waving_black_flag:"],"category":"flags"},":flags:":{"uc_base":"1f38f","uc_output":"1f38f","uc_match":"1f38f","uc_greedy":"1f38f","shortnames":[],"category":"objects"},":flashlight:":{"uc_base":"1f526","uc_output":"1f526","uc_match":"1f526","uc_greedy":"1f526","shortnames":[],"category":"objects"},":floppy_disk:":{"uc_base":"1f4be","uc_output":"1f4be","uc_match":"1f4be","uc_greedy":"1f4be","shortnames":[],"category":"objects"},":flower_playing_cards:":{"uc_base":"1f3b4","uc_output":"1f3b4","uc_match":"1f3b4","uc_greedy":"1f3b4","shortnames":[],"category":"symbols"},":flushed:":{"uc_base":"1f633","uc_output":"1f633","uc_match":"1f633","uc_greedy":"1f633","shortnames":[],"category":"people"},":flying_saucer:":{"uc_base":"1f6f8","uc_output":"1f6f8","uc_match":"1f6f8","uc_greedy":"1f6f8","shortnames":[],"category":"travel"},":foggy:":{"uc_base":"1f301","uc_output":"1f301","uc_match":"1f301","uc_greedy":"1f301","shortnames":[],"category":"travel"},":football:":{"uc_base":"1f3c8","uc_output":"1f3c8","uc_match":"1f3c8","uc_greedy":"1f3c8","shortnames":[],"category":"activity"},":footprints:":{"uc_base":"1f463","uc_output":"1f463","uc_match":"1f463","uc_greedy":"1f463","shortnames":[],"category":"people"},":fork_and_knife:":{"uc_base":"1f374","uc_output":"1f374","uc_match":"1f374","uc_greedy":"1f374","shortnames":[],"category":"food"},":fortune_cookie:":{"uc_base":"1f960","uc_output":"1f960","uc_match":"1f960","uc_greedy":"1f960","shortnames":[],"category":"food"},":four_leaf_clover:":{"uc_base":"1f340","uc_output":"1f340","uc_match":"1f340","uc_greedy":"1f340","shortnames":[],"category":"nature"},":fox:":{"uc_base":"1f98a","uc_output":"1f98a","uc_match":"1f98a","uc_greedy":"1f98a","shortnames":[":fox_face:"],"category":"nature"},":free:":{"uc_base":"1f193","uc_output":"1f193","uc_match":"1f193","uc_greedy":"1f193","shortnames":[],"category":"symbols"},":french_bread:":{"uc_base":"1f956","uc_output":"1f956","uc_match":"1f956","uc_greedy":"1f956","shortnames":[":baguette_bread:"],"category":"food"},":fried_shrimp:":{"uc_base":"1f364","uc_output":"1f364","uc_match":"1f364","uc_greedy":"1f364","shortnames":[],"category":"food"},":fries:":{"uc_base":"1f35f","uc_output":"1f35f","uc_match":"1f35f","uc_greedy":"1f35f","shortnames":[],"category":"food"},":frog:":{"uc_base":"1f438","uc_output":"1f438","uc_match":"1f438","uc_greedy":"1f438","shortnames":[],"category":"nature"},":frowning:":{"uc_base":"1f626","uc_output":"1f626","uc_match":"1f626","uc_greedy":"1f626","shortnames":[],"category":"people"},":full_moon:":{"uc_base":"1f315","uc_output":"1f315","uc_match":"1f315","uc_greedy":"1f315","shortnames":[],"category":"nature"},":full_moon_with_face:":{"uc_base":"1f31d","uc_output":"1f31d","uc_match":"1f31d","uc_greedy":"1f31d","shortnames":[],"category":"nature"},":game_die:":{"uc_base":"1f3b2","uc_output":"1f3b2","uc_match":"1f3b2","uc_greedy":"1f3b2","shortnames":[],"category":"activity"},":gem:":{"uc_base":"1f48e","uc_output":"1f48e","uc_match":"1f48e","uc_greedy":"1f48e","shortnames":[],"category":"objects"},":genie:":{"uc_base":"1f9de","uc_output":"1f9de","uc_match":"1f9de","uc_greedy":"1f9de","shortnames":[],"category":"people"},":ghost:":{"uc_base":"1f47b","uc_output":"1f47b","uc_match":"1f47b","uc_greedy":"1f47b","shortnames":[],"category":"people"},":gift:":{"uc_base":"1f381","uc_output":"1f381","uc_match":"1f381","uc_greedy":"1f381","shortnames":[],"category":"objects"},":gift_heart:":{"uc_base":"1f49d","uc_output":"1f49d","uc_match":"1f49d","uc_greedy":"1f49d","shortnames":[],"category":"symbols"},":giraffe:":{"uc_base":"1f992","uc_output":"1f992","uc_match":"1f992","uc_greedy":"1f992","shortnames":[],"category":"nature"},":girl:":{"uc_base":"1f467","uc_output":"1f467","uc_match":"1f467","uc_greedy":"1f467","shortnames":[],"category":"people"},":globe_with_meridians:":{"uc_base":"1f310","uc_output":"1f310","uc_match":"1f310","uc_greedy":"1f310","shortnames":[],"category":"symbols"},":gloves:":{"uc_base":"1f9e4","uc_output":"1f9e4","uc_match":"1f9e4","uc_greedy":"1f9e4","shortnames":[],"category":"people"},":goal:":{"uc_base":"1f945","uc_output":"1f945","uc_match":"1f945","uc_greedy":"1f945","shortnames":[":goal_net:"],"category":"activity"},":goat:":{"uc_base":"1f410","uc_output":"1f410","uc_match":"1f410","uc_greedy":"1f410","shortnames":[],"category":"nature"},":gorilla:":{"uc_base":"1f98d","uc_output":"1f98d","uc_match":"1f98d","uc_greedy":"1f98d","shortnames":[],"category":"nature"},":grapes:":{"uc_base":"1f347","uc_output":"1f347","uc_match":"1f347","uc_greedy":"1f347","shortnames":[],"category":"food"},":green_apple:":{"uc_base":"1f34f","uc_output":"1f34f","uc_match":"1f34f","uc_greedy":"1f34f","shortnames":[],"category":"food"},":green_book:":{"uc_base":"1f4d7","uc_output":"1f4d7","uc_match":"1f4d7","uc_greedy":"1f4d7","shortnames":[],"category":"objects"},":green_heart:":{"uc_base":"1f49a","uc_output":"1f49a","uc_match":"1f49a","uc_greedy":"1f49a","shortnames":[],"category":"symbols"},":grimacing:":{"uc_base":"1f62c","uc_output":"1f62c","uc_match":"1f62c","uc_greedy":"1f62c","shortnames":[],"category":"people"},":grin:":{"uc_base":"1f601","uc_output":"1f601","uc_match":"1f601","uc_greedy":"1f601","shortnames":[],"category":"people"},":grinning:":{"uc_base":"1f600","uc_output":"1f600","uc_match":"1f600","uc_greedy":"1f600","shortnames":[],"category":"people"},":guard:":{"uc_base":"1f482","uc_output":"1f482","uc_match":"1f482","uc_greedy":"1f482","shortnames":[":guardsman:"],"category":"people"},":guitar:":{"uc_base":"1f3b8","uc_output":"1f3b8","uc_match":"1f3b8","uc_greedy":"1f3b8","shortnames":[],"category":"activity"},":gun:":{"uc_base":"1f52b","uc_output":"1f52b","uc_match":"1f52b","uc_greedy":"1f52b","shortnames":[],"category":"objects"},":hamburger:":{"uc_base":"1f354","uc_output":"1f354","uc_match":"1f354","uc_greedy":"1f354","shortnames":[],"category":"food"},":hammer:":{"uc_base":"1f528","uc_output":"1f528","uc_match":"1f528","uc_greedy":"1f528","shortnames":[],"category":"objects"},":hamster:":{"uc_base":"1f439","uc_output":"1f439","uc_match":"1f439","uc_greedy":"1f439","shortnames":[],"category":"nature"},":handbag:":{"uc_base":"1f45c","uc_output":"1f45c","uc_match":"1f45c","uc_greedy":"1f45c","shortnames":[],"category":"people"},":handshake:":{"uc_base":"1f91d","uc_output":"1f91d","uc_match":"1f91d","uc_greedy":"1f91d","shortnames":[":shaking_hands:"],"category":"people"},":hatched_chick:":{"uc_base":"1f425","uc_output":"1f425","uc_match":"1f425","uc_greedy":"1f425","shortnames":[],"category":"nature"},":hatching_chick:":{"uc_base":"1f423","uc_output":"1f423","uc_match":"1f423","uc_greedy":"1f423","shortnames":[],"category":"nature"},":head_bandage:":{"uc_base":"1f915","uc_output":"1f915","uc_match":"1f915","uc_greedy":"1f915","shortnames":[":face_with_head_bandage:"],"category":"people"},":headphones:":{"uc_base":"1f3a7","uc_output":"1f3a7","uc_match":"1f3a7","uc_greedy":"1f3a7","shortnames":[],"category":"activity"},":hear_no_evil:":{"uc_base":"1f649","uc_output":"1f649","uc_match":"1f649","uc_greedy":"1f649","shortnames":[],"category":"nature"},":heart_decoration:":{"uc_base":"1f49f","uc_output":"1f49f","uc_match":"1f49f","uc_greedy":"1f49f","shortnames":[],"category":"symbols"},":heart_eyes:":{"uc_base":"1f60d","uc_output":"1f60d","uc_match":"1f60d","uc_greedy":"1f60d","shortnames":[],"category":"people"},":heart_eyes_cat:":{"uc_base":"1f63b","uc_output":"1f63b","uc_match":"1f63b","uc_greedy":"1f63b","shortnames":[],"category":"people"},":heartbeat:":{"uc_base":"1f493","uc_output":"1f493","uc_match":"1f493","uc_greedy":"1f493","shortnames":[],"category":"symbols"},":heartpulse:":{"uc_base":"1f497","uc_output":"1f497","uc_match":"1f497","uc_greedy":"1f497","shortnames":[],"category":"symbols"},":heavy_dollar_sign:":{"uc_base":"1f4b2","uc_output":"1f4b2","uc_match":"1f4b2","uc_greedy":"1f4b2","shortnames":[],"category":"symbols"},":hedgehog:":{"uc_base":"1f994","uc_output":"1f994","uc_match":"1f994","uc_greedy":"1f994","shortnames":[],"category":"nature"},":helicopter:":{"uc_base":"1f681","uc_output":"1f681","uc_match":"1f681","uc_greedy":"1f681","shortnames":[],"category":"travel"},":herb:":{"uc_base":"1f33f","uc_output":"1f33f","uc_match":"1f33f","uc_greedy":"1f33f","shortnames":[],"category":"nature"},":hibiscus:":{"uc_base":"1f33a","uc_output":"1f33a","uc_match":"1f33a","uc_greedy":"1f33a","shortnames":[],"category":"nature"},":high_brightness:":{"uc_base":"1f506","uc_output":"1f506","uc_match":"1f506","uc_greedy":"1f506","shortnames":[],"category":"symbols"},":high_heel:":{"uc_base":"1f460","uc_output":"1f460","uc_match":"1f460","uc_greedy":"1f460","shortnames":[],"category":"people"},":hockey:":{"uc_base":"1f3d2","uc_output":"1f3d2","uc_match":"1f3d2","uc_greedy":"1f3d2","shortnames":[],"category":"activity"},":honey_pot:":{"uc_base":"1f36f","uc_output":"1f36f","uc_match":"1f36f","uc_greedy":"1f36f","shortnames":[],"category":"food"},":horse:":{"uc_base":"1f434","uc_output":"1f434","uc_match":"1f434","uc_greedy":"1f434","shortnames":[],"category":"nature"},":horse_racing:":{"uc_base":"1f3c7","uc_output":"1f3c7","uc_match":"1f3c7","uc_greedy":"1f3c7","shortnames":[],"category":"activity"},":hospital:":{"uc_base":"1f3e5","uc_output":"1f3e5","uc_match":"1f3e5","uc_greedy":"1f3e5","shortnames":[],"category":"travel"},":hotdog:":{"uc_base":"1f32d","uc_output":"1f32d","uc_match":"1f32d","uc_greedy":"1f32d","shortnames":[":hot_dog:"],"category":"food"},":hotel:":{"uc_base":"1f3e8","uc_output":"1f3e8","uc_match":"1f3e8","uc_greedy":"1f3e8","shortnames":[],"category":"travel"},":house:":{"uc_base":"1f3e0","uc_output":"1f3e0","uc_match":"1f3e0","uc_greedy":"1f3e0","shortnames":[],"category":"travel"},":house_with_garden:":{"uc_base":"1f3e1","uc_output":"1f3e1","uc_match":"1f3e1","uc_greedy":"1f3e1","shortnames":[],"category":"travel"},":hugging:":{"uc_base":"1f917","uc_output":"1f917","uc_match":"1f917","uc_greedy":"1f917","shortnames":[":hugging_face:"],"category":"people"},":hushed:":{"uc_base":"1f62f","uc_output":"1f62f","uc_match":"1f62f","uc_greedy":"1f62f","shortnames":[],"category":"people"},":ice_cream:":{"uc_base":"1f368","uc_output":"1f368","uc_match":"1f368","uc_greedy":"1f368","shortnames":[],"category":"food"},":icecream:":{"uc_base":"1f366","uc_output":"1f366","uc_match":"1f366","uc_greedy":"1f366","shortnames":[],"category":"food"},":id:":{"uc_base":"1f194","uc_output":"1f194","uc_match":"1f194","uc_greedy":"1f194","shortnames":[],"category":"symbols"},":ideograph_advantage:":{"uc_base":"1f250","uc_output":"1f250","uc_match":"1f250","uc_greedy":"1f250","shortnames":[],"category":"symbols"},":imp:":{"uc_base":"1f47f","uc_output":"1f47f","uc_match":"1f47f","uc_greedy":"1f47f","shortnames":[],"category":"people"},":inbox_tray:":{"uc_base":"1f4e5","uc_output":"1f4e5","uc_match":"1f4e5","uc_greedy":"1f4e5","shortnames":[],"category":"objects"},":incoming_envelope:":{"uc_base":"1f4e8","uc_output":"1f4e8","uc_match":"1f4e8","uc_greedy":"1f4e8","shortnames":[],"category":"objects"},":innocent:":{"uc_base":"1f607","uc_output":"1f607","uc_match":"1f607","uc_greedy":"1f607","shortnames":[],"category":"people"},":iphone:":{"uc_base":"1f4f1","uc_output":"1f4f1","uc_match":"1f4f1","uc_greedy":"1f4f1","shortnames":[],"category":"objects"},":izakaya_lantern:":{"uc_base":"1f3ee","uc_output":"1f3ee","uc_match":"1f3ee","uc_greedy":"1f3ee","shortnames":[],"category":"objects"},":jack_o_lantern:":{"uc_base":"1f383","uc_output":"1f383","uc_match":"1f383","uc_greedy":"1f383","shortnames":[],"category":"people"},":japan:":{"uc_base":"1f5fe","uc_output":"1f5fe","uc_match":"1f5fe","uc_greedy":"1f5fe","shortnames":[],"category":"travel"},":japanese_castle:":{"uc_base":"1f3ef","uc_output":"1f3ef","uc_match":"1f3ef","uc_greedy":"1f3ef","shortnames":[],"category":"travel"},":japanese_goblin:":{"uc_base":"1f47a","uc_output":"1f47a","uc_match":"1f47a","uc_greedy":"1f47a","shortnames":[],"category":"people"},":japanese_ogre:":{"uc_base":"1f479","uc_output":"1f479","uc_match":"1f479","uc_greedy":"1f479","shortnames":[],"category":"people"},":jeans:":{"uc_base":"1f456","uc_output":"1f456","uc_match":"1f456","uc_greedy":"1f456","shortnames":[],"category":"people"},":joy:":{"uc_base":"1f602","uc_output":"1f602","uc_match":"1f602","uc_greedy":"1f602","shortnames":[],"category":"people"},":joy_cat:":{"uc_base":"1f639","uc_output":"1f639","uc_match":"1f639","uc_greedy":"1f639","shortnames":[],"category":"people"},":kaaba:":{"uc_base":"1f54b","uc_output":"1f54b","uc_match":"1f54b","uc_greedy":"1f54b","shortnames":[],"category":"travel"},":key:":{"uc_base":"1f511","uc_output":"1f511","uc_match":"1f511","uc_greedy":"1f511","shortnames":[],"category":"objects"},":keycap_ten:":{"uc_base":"1f51f","uc_output":"1f51f","uc_match":"1f51f","uc_greedy":"1f51f","shortnames":[],"category":"symbols"},":kimono:":{"uc_base":"1f458","uc_output":"1f458","uc_match":"1f458","uc_greedy":"1f458","shortnames":[],"category":"people"},":kiss:":{"uc_base":"1f48b","uc_output":"1f48b","uc_match":"1f48b","uc_greedy":"1f48b","shortnames":[],"category":"people"},":kissing:":{"uc_base":"1f617","uc_output":"1f617","uc_match":"1f617","uc_greedy":"1f617","shortnames":[],"category":"people"},":kissing_cat:":{"uc_base":"1f63d","uc_output":"1f63d","uc_match":"1f63d","uc_greedy":"1f63d","shortnames":[],"category":"people"},":kissing_closed_eyes:":{"uc_base":"1f61a","uc_output":"1f61a","uc_match":"1f61a","uc_greedy":"1f61a","shortnames":[],"category":"people"},":kissing_heart:":{"uc_base":"1f618","uc_output":"1f618","uc_match":"1f618","uc_greedy":"1f618","shortnames":[],"category":"people"},":kissing_smiling_eyes:":{"uc_base":"1f619","uc_output":"1f619","uc_match":"1f619","uc_greedy":"1f619","shortnames":[],"category":"people"},":kiwi:":{"uc_base":"1f95d","uc_output":"1f95d","uc_match":"1f95d","uc_greedy":"1f95d","shortnames":[":kiwifruit:"],"category":"food"},":knife:":{"uc_base":"1f52a","uc_output":"1f52a","uc_match":"1f52a","uc_greedy":"1f52a","shortnames":[],"category":"objects"},":koala:":{"uc_base":"1f428","uc_output":"1f428","uc_match":"1f428","uc_greedy":"1f428","shortnames":[],"category":"nature"},":koko:":{"uc_base":"1f201","uc_output":"1f201","uc_match":"1f201","uc_greedy":"1f201","shortnames":[],"category":"symbols"},":large_blue_diamond:":{"uc_base":"1f537","uc_output":"1f537","uc_match":"1f537","uc_greedy":"1f537","shortnames":[],"category":"symbols"},":large_orange_diamond:":{"uc_base":"1f536","uc_output":"1f536","uc_match":"1f536","uc_greedy":"1f536","shortnames":[],"category":"symbols"},":last_quarter_moon:":{"uc_base":"1f317","uc_output":"1f317","uc_match":"1f317","uc_greedy":"1f317","shortnames":[],"category":"nature"},":last_quarter_moon_with_face:":{"uc_base":"1f31c","uc_output":"1f31c","uc_match":"1f31c","uc_greedy":"1f31c","shortnames":[],"category":"nature"},":laughing:":{"uc_base":"1f606","uc_output":"1f606","uc_match":"1f606","uc_greedy":"1f606","shortnames":[":satisfied:"],"category":"people"},":leaves:":{"uc_base":"1f343","uc_output":"1f343","uc_match":"1f343","uc_greedy":"1f343","shortnames":[],"category":"nature"},":ledger:":{"uc_base":"1f4d2","uc_output":"1f4d2","uc_match":"1f4d2","uc_greedy":"1f4d2","shortnames":[],"category":"objects"},":left_facing_fist:":{"uc_base":"1f91b","uc_output":"1f91b","uc_match":"1f91b","uc_greedy":"1f91b","shortnames":[":left_fist:"],"category":"people"},":left_luggage:":{"uc_base":"1f6c5","uc_output":"1f6c5","uc_match":"1f6c5","uc_greedy":"1f6c5","shortnames":[],"category":"symbols"},":lemon:":{"uc_base":"1f34b","uc_output":"1f34b","uc_match":"1f34b","uc_greedy":"1f34b","shortnames":[],"category":"food"},":leopard:":{"uc_base":"1f406","uc_output":"1f406","uc_match":"1f406","uc_greedy":"1f406","shortnames":[],"category":"nature"},":light_rail:":{"uc_base":"1f688","uc_output":"1f688","uc_match":"1f688","uc_greedy":"1f688","shortnames":[],"category":"travel"},":link:":{"uc_base":"1f517","uc_output":"1f517","uc_match":"1f517","uc_greedy":"1f517","shortnames":[],"category":"objects"},":lion_face:":{"uc_base":"1f981","uc_output":"1f981","uc_match":"1f981","uc_greedy":"1f981","shortnames":[":lion:"],"category":"nature"},":lips:":{"uc_base":"1f444","uc_output":"1f444","uc_match":"1f444","uc_greedy":"1f444","shortnames":[],"category":"people"},":lipstick:":{"uc_base":"1f484","uc_output":"1f484","uc_match":"1f484","uc_greedy":"1f484","shortnames":[],"category":"people"},":lizard:":{"uc_base":"1f98e","uc_output":"1f98e","uc_match":"1f98e","uc_greedy":"1f98e","shortnames":[],"category":"nature"},":lock:":{"uc_base":"1f512","uc_output":"1f512","uc_match":"1f512","uc_greedy":"1f512","shortnames":[],"category":"objects"},":lock_with_ink_pen:":{"uc_base":"1f50f","uc_output":"1f50f","uc_match":"1f50f","uc_greedy":"1f50f","shortnames":[],"category":"objects"},":lollipop:":{"uc_base":"1f36d","uc_output":"1f36d","uc_match":"1f36d","uc_greedy":"1f36d","shortnames":[],"category":"food"},":loud_sound:":{"uc_base":"1f50a","uc_output":"1f50a","uc_match":"1f50a","uc_greedy":"1f50a","shortnames":[],"category":"symbols"},":loudspeaker:":{"uc_base":"1f4e2","uc_output":"1f4e2","uc_match":"1f4e2","uc_greedy":"1f4e2","shortnames":[],"category":"symbols"},":love_hotel:":{"uc_base":"1f3e9","uc_output":"1f3e9","uc_match":"1f3e9","uc_greedy":"1f3e9","shortnames":[],"category":"travel"},":love_letter:":{"uc_base":"1f48c","uc_output":"1f48c","uc_match":"1f48c","uc_greedy":"1f48c","shortnames":[],"category":"objects"},":love_you_gesture:":{"uc_base":"1f91f","uc_output":"1f91f","uc_match":"1f91f","uc_greedy":"1f91f","shortnames":[],"category":"people"},":low_brightness:":{"uc_base":"1f505","uc_output":"1f505","uc_match":"1f505","uc_greedy":"1f505","shortnames":[],"category":"symbols"},":lying_face:":{"uc_base":"1f925","uc_output":"1f925","uc_match":"1f925","uc_greedy":"1f925","shortnames":[":liar:"],"category":"people"},":mag:":{"uc_base":"1f50d","uc_output":"1f50d","uc_match":"1f50d","uc_greedy":"1f50d","shortnames":[],"category":"objects"},":mag_right:":{"uc_base":"1f50e","uc_output":"1f50e","uc_match":"1f50e","uc_greedy":"1f50e","shortnames":[],"category":"objects"},":mage:":{"uc_base":"1f9d9","uc_output":"1f9d9","uc_match":"1f9d9","uc_greedy":"1f9d9","shortnames":[],"category":"people"},":mahjong:":{"uc_base":"1f004","uc_output":"1f004","uc_match":"1f004","uc_greedy":"1f004","shortnames":[],"category":"symbols"},":mailbox:":{"uc_base":"1f4eb","uc_output":"1f4eb","uc_match":"1f4eb","uc_greedy":"1f4eb","shortnames":[],"category":"objects"},":mailbox_closed:":{"uc_base":"1f4ea","uc_output":"1f4ea","uc_match":"1f4ea","uc_greedy":"1f4ea","shortnames":[],"category":"objects"},":mailbox_with_mail:":{"uc_base":"1f4ec","uc_output":"1f4ec","uc_match":"1f4ec","uc_greedy":"1f4ec","shortnames":[],"category":"objects"},":mailbox_with_no_mail:":{"uc_base":"1f4ed","uc_output":"1f4ed","uc_match":"1f4ed","uc_greedy":"1f4ed","shortnames":[],"category":"objects"},":man:":{"uc_base":"1f468","uc_output":"1f468","uc_match":"1f468","uc_greedy":"1f468","shortnames":[],"category":"people"},":man_dancing:":{"uc_base":"1f57a","uc_output":"1f57a","uc_match":"1f57a","uc_greedy":"1f57a","shortnames":[":male_dancer:"],"category":"people"},":man_in_tuxedo:":{"uc_base":"1f935","uc_output":"1f935","uc_match":"1f935","uc_greedy":"1f935","shortnames":[],"category":"people"},":man_with_chinese_cap:":{"uc_base":"1f472","uc_output":"1f472","uc_match":"1f472","uc_greedy":"1f472","shortnames":[":man_with_gua_pi_mao:"],"category":"people"},":mans_shoe:":{"uc_base":"1f45e","uc_output":"1f45e","uc_match":"1f45e","uc_greedy":"1f45e","shortnames":[],"category":"people"},":maple_leaf:":{"uc_base":"1f341","uc_output":"1f341","uc_match":"1f341","uc_greedy":"1f341","shortnames":[],"category":"nature"},":martial_arts_uniform:":{"uc_base":"1f94b","uc_output":"1f94b","uc_match":"1f94b","uc_greedy":"1f94b","shortnames":[":karate_uniform:"],"category":"activity"},":mask:":{"uc_base":"1f637","uc_output":"1f637","uc_match":"1f637","uc_greedy":"1f637","shortnames":[],"category":"people"},":meat_on_bone:":{"uc_base":"1f356","uc_output":"1f356","uc_match":"1f356","uc_greedy":"1f356","shortnames":[],"category":"food"},":medal:":{"uc_base":"1f3c5","uc_output":"1f3c5","uc_match":"1f3c5","uc_greedy":"1f3c5","shortnames":[":sports_medal:"],"category":"activity"},":mega:":{"uc_base":"1f4e3","uc_output":"1f4e3","uc_match":"1f4e3","uc_greedy":"1f4e3","shortnames":[],"category":"symbols"},":melon:":{"uc_base":"1f348","uc_output":"1f348","uc_match":"1f348","uc_greedy":"1f348","shortnames":[],"category":"food"},":menorah:":{"uc_base":"1f54e","uc_output":"1f54e","uc_match":"1f54e","uc_greedy":"1f54e","shortnames":[],"category":"symbols"},":mens:":{"uc_base":"1f6b9","uc_output":"1f6b9","uc_match":"1f6b9","uc_greedy":"1f6b9","shortnames":[],"category":"symbols"},":merperson:":{"uc_base":"1f9dc","uc_output":"1f9dc","uc_match":"1f9dc","uc_greedy":"1f9dc","shortnames":[],"category":"people"},":metal:":{"uc_base":"1f918","uc_output":"1f918","uc_match":"1f918","uc_greedy":"1f918","shortnames":[":sign_of_the_horns:"],"category":"people"},":metro:":{"uc_base":"1f687","uc_output":"1f687","uc_match":"1f687","uc_greedy":"1f687","shortnames":[],"category":"travel"},":microphone:":{"uc_base":"1f3a4","uc_output":"1f3a4","uc_match":"1f3a4","uc_greedy":"1f3a4","shortnames":[],"category":"activity"},":microscope:":{"uc_base":"1f52c","uc_output":"1f52c","uc_match":"1f52c","uc_greedy":"1f52c","shortnames":[],"category":"objects"},":middle_finger:":{"uc_base":"1f595","uc_output":"1f595","uc_match":"1f595","uc_greedy":"1f595","shortnames":[":reversed_hand_with_middle_finger_extended:"],"category":"people"},":milk:":{"uc_base":"1f95b","uc_output":"1f95b","uc_match":"1f95b","uc_greedy":"1f95b","shortnames":[":glass_of_milk:"],"category":"food"},":milky_way:":{"uc_base":"1f30c","uc_output":"1f30c","uc_match":"1f30c","uc_greedy":"1f30c","shortnames":[],"category":"travel"},":minibus:":{"uc_base":"1f690","uc_output":"1f690","uc_match":"1f690","uc_greedy":"1f690","shortnames":[],"category":"travel"},":minidisc:":{"uc_base":"1f4bd","uc_output":"1f4bd","uc_match":"1f4bd","uc_greedy":"1f4bd","shortnames":[],"category":"objects"},":mobile_phone_off:":{"uc_base":"1f4f4","uc_output":"1f4f4","uc_match":"1f4f4","uc_greedy":"1f4f4","shortnames":[],"category":"symbols"},":money_mouth:":{"uc_base":"1f911","uc_output":"1f911","uc_match":"1f911","uc_greedy":"1f911","shortnames":[":money_mouth_face:"],"category":"people"},":money_with_wings:":{"uc_base":"1f4b8","uc_output":"1f4b8","uc_match":"1f4b8","uc_greedy":"1f4b8","shortnames":[],"category":"objects"},":moneybag:":{"uc_base":"1f4b0","uc_output":"1f4b0","uc_match":"1f4b0","uc_greedy":"1f4b0","shortnames":[],"category":"objects"},":monkey:":{"uc_base":"1f412","uc_output":"1f412","uc_match":"1f412","uc_greedy":"1f412","shortnames":[],"category":"nature"},":monkey_face:":{"uc_base":"1f435","uc_output":"1f435","uc_match":"1f435","uc_greedy":"1f435","shortnames":[],"category":"nature"},":monorail:":{"uc_base":"1f69d","uc_output":"1f69d","uc_match":"1f69d","uc_greedy":"1f69d","shortnames":[],"category":"travel"},":mortar_board:":{"uc_base":"1f393","uc_output":"1f393","uc_match":"1f393","uc_greedy":"1f393","shortnames":[],"category":"people"},":mosque:":{"uc_base":"1f54c","uc_output":"1f54c","uc_match":"1f54c","uc_greedy":"1f54c","shortnames":[],"category":"travel"},":motor_scooter:":{"uc_base":"1f6f5","uc_output":"1f6f5","uc_match":"1f6f5","uc_greedy":"1f6f5","shortnames":[":motorbike:"],"category":"travel"},":mount_fuji:":{"uc_base":"1f5fb","uc_output":"1f5fb","uc_match":"1f5fb","uc_greedy":"1f5fb","shortnames":[],"category":"travel"},":mountain_cableway:":{"uc_base":"1f6a0","uc_output":"1f6a0","uc_match":"1f6a0","uc_greedy":"1f6a0","shortnames":[],"category":"travel"},":mountain_railway:":{"uc_base":"1f69e","uc_output":"1f69e","uc_match":"1f69e","uc_greedy":"1f69e","shortnames":[],"category":"travel"},":mouse2:":{"uc_base":"1f401","uc_output":"1f401","uc_match":"1f401","uc_greedy":"1f401","shortnames":[],"category":"nature"},":mouse:":{"uc_base":"1f42d","uc_output":"1f42d","uc_match":"1f42d","uc_greedy":"1f42d","shortnames":[],"category":"nature"},":movie_camera:":{"uc_base":"1f3a5","uc_output":"1f3a5","uc_match":"1f3a5","uc_greedy":"1f3a5","shortnames":[],"category":"objects"},":moyai:":{"uc_base":"1f5ff","uc_output":"1f5ff","uc_match":"1f5ff","uc_greedy":"1f5ff","shortnames":[],"category":"travel"},":mrs_claus:":{"uc_base":"1f936","uc_output":"1f936","uc_match":"1f936","uc_greedy":"1f936","shortnames":[":mother_christmas:"],"category":"people"},":muscle:":{"uc_base":"1f4aa","uc_output":"1f4aa","uc_match":"1f4aa","uc_greedy":"1f4aa","shortnames":[],"category":"people"},":mushroom:":{"uc_base":"1f344","uc_output":"1f344","uc_match":"1f344","uc_greedy":"1f344","shortnames":[],"category":"nature"},":musical_keyboard:":{"uc_base":"1f3b9","uc_output":"1f3b9","uc_match":"1f3b9","uc_greedy":"1f3b9","shortnames":[],"category":"activity"},":musical_note:":{"uc_base":"1f3b5","uc_output":"1f3b5","uc_match":"1f3b5","uc_greedy":"1f3b5","shortnames":[],"category":"symbols"},":musical_score:":{"uc_base":"1f3bc","uc_output":"1f3bc","uc_match":"1f3bc","uc_greedy":"1f3bc","shortnames":[],"category":"activity"},":mute:":{"uc_base":"1f507","uc_output":"1f507","uc_match":"1f507","uc_greedy":"1f507","shortnames":[],"category":"symbols"},":nail_care:":{"uc_base":"1f485","uc_output":"1f485","uc_match":"1f485","uc_greedy":"1f485","shortnames":[],"category":"people"},":name_badge:":{"uc_base":"1f4db","uc_output":"1f4db","uc_match":"1f4db","uc_greedy":"1f4db","shortnames":[],"category":"symbols"},":nauseated_face:":{"uc_base":"1f922","uc_output":"1f922","uc_match":"1f922","uc_greedy":"1f922","shortnames":[":sick:"],"category":"people"},":necktie:":{"uc_base":"1f454","uc_output":"1f454","uc_match":"1f454","uc_greedy":"1f454","shortnames":[],"category":"people"},":nerd:":{"uc_base":"1f913","uc_output":"1f913","uc_match":"1f913","uc_greedy":"1f913","shortnames":[":nerd_face:"],"category":"people"},":neutral_face:":{"uc_base":"1f610","uc_output":"1f610","uc_match":"1f610","uc_greedy":"1f610","shortnames":[],"category":"people"},":new:":{"uc_base":"1f195","uc_output":"1f195","uc_match":"1f195","uc_greedy":"1f195","shortnames":[],"category":"symbols"},":new_moon:":{"uc_base":"1f311","uc_output":"1f311","uc_match":"1f311","uc_greedy":"1f311","shortnames":[],"category":"nature"},":new_moon_with_face:":{"uc_base":"1f31a","uc_output":"1f31a","uc_match":"1f31a","uc_greedy":"1f31a","shortnames":[],"category":"nature"},":newspaper:":{"uc_base":"1f4f0","uc_output":"1f4f0","uc_match":"1f4f0","uc_greedy":"1f4f0","shortnames":[],"category":"objects"},":ng:":{"uc_base":"1f196","uc_output":"1f196","uc_match":"1f196","uc_greedy":"1f196","shortnames":[],"category":"symbols"},":night_with_stars:":{"uc_base":"1f303","uc_output":"1f303","uc_match":"1f303","uc_greedy":"1f303","shortnames":[],"category":"travel"},":no_bell:":{"uc_base":"1f515","uc_output":"1f515","uc_match":"1f515","uc_greedy":"1f515","shortnames":[],"category":"symbols"},":no_bicycles:":{"uc_base":"1f6b3","uc_output":"1f6b3","uc_match":"1f6b3","uc_greedy":"1f6b3","shortnames":[],"category":"symbols"},":no_entry_sign:":{"uc_base":"1f6ab","uc_output":"1f6ab","uc_match":"1f6ab","uc_greedy":"1f6ab","shortnames":[],"category":"symbols"},":no_mobile_phones:":{"uc_base":"1f4f5","uc_output":"1f4f5","uc_match":"1f4f5","uc_greedy":"1f4f5","shortnames":[],"category":"symbols"},":no_mouth:":{"uc_base":"1f636","uc_output":"1f636","uc_match":"1f636","uc_greedy":"1f636","shortnames":[],"category":"people"},":no_pedestrians:":{"uc_base":"1f6b7","uc_output":"1f6b7","uc_match":"1f6b7","uc_greedy":"1f6b7","shortnames":[],"category":"symbols"},":no_smoking:":{"uc_base":"1f6ad","uc_output":"1f6ad","uc_match":"1f6ad","uc_greedy":"1f6ad","shortnames":[],"category":"symbols"},":non-potable_water:":{"uc_base":"1f6b1","uc_output":"1f6b1","uc_match":"1f6b1","uc_greedy":"1f6b1","shortnames":[],"category":"symbols"},":nose:":{"uc_base":"1f443","uc_output":"1f443","uc_match":"1f443","uc_greedy":"1f443","shortnames":[],"category":"people"},":notebook:":{"uc_base":"1f4d3","uc_output":"1f4d3","uc_match":"1f4d3","uc_greedy":"1f4d3","shortnames":[],"category":"objects"},":notebook_with_decorative_cover:":{"uc_base":"1f4d4","uc_output":"1f4d4","uc_match":"1f4d4","uc_greedy":"1f4d4","shortnames":[],"category":"objects"},":notes:":{"uc_base":"1f3b6","uc_output":"1f3b6","uc_match":"1f3b6","uc_greedy":"1f3b6","shortnames":[],"category":"symbols"},":nut_and_bolt:":{"uc_base":"1f529","uc_output":"1f529","uc_match":"1f529","uc_greedy":"1f529","shortnames":[],"category":"objects"},":ocean:":{"uc_base":"1f30a","uc_output":"1f30a","uc_match":"1f30a","uc_greedy":"1f30a","shortnames":[],"category":"nature"},":octagonal_sign:":{"uc_base":"1f6d1","uc_output":"1f6d1","uc_match":"1f6d1","uc_greedy":"1f6d1","shortnames":[":stop_sign:"],"category":"symbols"},":octopus:":{"uc_base":"1f419","uc_output":"1f419","uc_match":"1f419","uc_greedy":"1f419","shortnames":[],"category":"nature"},":oden:":{"uc_base":"1f362","uc_output":"1f362","uc_match":"1f362","uc_greedy":"1f362","shortnames":[],"category":"food"},":office:":{"uc_base":"1f3e2","uc_output":"1f3e2","uc_match":"1f3e2","uc_greedy":"1f3e2","shortnames":[],"category":"travel"},":ok:":{"uc_base":"1f197","uc_output":"1f197","uc_match":"1f197","uc_greedy":"1f197","shortnames":[],"category":"symbols"},":ok_hand:":{"uc_base":"1f44c","uc_output":"1f44c","uc_match":"1f44c","uc_greedy":"1f44c","shortnames":[],"category":"people"},":older_adult:":{"uc_base":"1f9d3","uc_output":"1f9d3","uc_match":"1f9d3","uc_greedy":"1f9d3","shortnames":[],"category":"people"},":older_man:":{"uc_base":"1f474","uc_output":"1f474","uc_match":"1f474","uc_greedy":"1f474","shortnames":[],"category":"people"},":older_woman:":{"uc_base":"1f475","uc_output":"1f475","uc_match":"1f475","uc_greedy":"1f475","shortnames":[":grandma:"],"category":"people"},":on:":{"uc_base":"1f51b","uc_output":"1f51b","uc_match":"1f51b","uc_greedy":"1f51b","shortnames":[],"category":"symbols"},":oncoming_automobile:":{"uc_base":"1f698","uc_output":"1f698","uc_match":"1f698","uc_greedy":"1f698","shortnames":[],"category":"travel"},":oncoming_bus:":{"uc_base":"1f68d","uc_output":"1f68d","uc_match":"1f68d","uc_greedy":"1f68d","shortnames":[],"category":"travel"},":oncoming_police_car:":{"uc_base":"1f694","uc_output":"1f694","uc_match":"1f694","uc_greedy":"1f694","shortnames":[],"category":"travel"},":oncoming_taxi:":{"uc_base":"1f696","uc_output":"1f696","uc_match":"1f696","uc_greedy":"1f696","shortnames":[],"category":"travel"},":open_file_folder:":{"uc_base":"1f4c2","uc_output":"1f4c2","uc_match":"1f4c2","uc_greedy":"1f4c2","shortnames":[],"category":"objects"},":open_hands:":{"uc_base":"1f450","uc_output":"1f450","uc_match":"1f450","uc_greedy":"1f450","shortnames":[],"category":"people"},":open_mouth:":{"uc_base":"1f62e","uc_output":"1f62e","uc_match":"1f62e","uc_greedy":"1f62e","shortnames":[],"category":"people"},":orange_book:":{"uc_base":"1f4d9","uc_output":"1f4d9","uc_match":"1f4d9","uc_greedy":"1f4d9","shortnames":[],"category":"objects"},":orange_heart:":{"uc_base":"1f9e1","uc_output":"1f9e1","uc_match":"1f9e1","uc_greedy":"1f9e1","shortnames":[],"category":"objects"},":outbox_tray:":{"uc_base":"1f4e4","uc_output":"1f4e4","uc_match":"1f4e4","uc_greedy":"1f4e4","shortnames":[],"category":"objects"},":owl:":{"uc_base":"1f989","uc_output":"1f989","uc_match":"1f989","uc_greedy":"1f989","shortnames":[],"category":"nature"},":ox:":{"uc_base":"1f402","uc_output":"1f402","uc_match":"1f402","uc_greedy":"1f402","shortnames":[],"category":"nature"},":package:":{"uc_base":"1f4e6","uc_output":"1f4e6","uc_match":"1f4e6","uc_greedy":"1f4e6","shortnames":[],"category":"objects"},":page_facing_up:":{"uc_base":"1f4c4","uc_output":"1f4c4","uc_match":"1f4c4","uc_greedy":"1f4c4","shortnames":[],"category":"objects"},":page_with_curl:":{"uc_base":"1f4c3","uc_output":"1f4c3","uc_match":"1f4c3","uc_greedy":"1f4c3","shortnames":[],"category":"objects"},":pager:":{"uc_base":"1f4df","uc_output":"1f4df","uc_match":"1f4df","uc_greedy":"1f4df","shortnames":[],"category":"objects"},":palm_tree:":{"uc_base":"1f334","uc_output":"1f334","uc_match":"1f334","uc_greedy":"1f334","shortnames":[],"category":"nature"},":palms_up_together:":{"uc_base":"1f932","uc_output":"1f932","uc_match":"1f932","uc_greedy":"1f932","shortnames":[],"category":"people"},":pancakes:":{"uc_base":"1f95e","uc_output":"1f95e","uc_match":"1f95e","uc_greedy":"1f95e","shortnames":[],"category":"food"},":panda_face:":{"uc_base":"1f43c","uc_output":"1f43c","uc_match":"1f43c","uc_greedy":"1f43c","shortnames":[],"category":"nature"},":paperclip:":{"uc_base":"1f4ce","uc_output":"1f4ce","uc_match":"1f4ce","uc_greedy":"1f4ce","shortnames":[],"category":"objects"},":passport_control:":{"uc_base":"1f6c2","uc_output":"1f6c2","uc_match":"1f6c2","uc_greedy":"1f6c2","shortnames":[],"category":"symbols"},":peach:":{"uc_base":"1f351","uc_output":"1f351","uc_match":"1f351","uc_greedy":"1f351","shortnames":[],"category":"food"},":peanuts:":{"uc_base":"1f95c","uc_output":"1f95c","uc_match":"1f95c","uc_greedy":"1f95c","shortnames":[":shelled_peanut:"],"category":"food"},":pear:":{"uc_base":"1f350","uc_output":"1f350","uc_match":"1f350","uc_greedy":"1f350","shortnames":[],"category":"food"},":pencil:":{"uc_base":"1f4dd","uc_output":"1f4dd","uc_match":"1f4dd","uc_greedy":"1f4dd","shortnames":[":memo:"],"category":"objects"},":penguin:":{"uc_base":"1f427","uc_output":"1f427","uc_match":"1f427","uc_greedy":"1f427","shortnames":[],"category":"nature"},":pensive:":{"uc_base":"1f614","uc_output":"1f614","uc_match":"1f614","uc_greedy":"1f614","shortnames":[],"category":"people"},":people_with_bunny_ears_partying:":{"uc_base":"1f46f","uc_output":"1f46f","uc_match":"1f46f","uc_greedy":"1f46f","shortnames":[":dancers:"],"category":"people"},":people_wrestling:":{"uc_base":"1f93c","uc_output":"1f93c","uc_match":"1f93c","uc_greedy":"1f93c","shortnames":[":wrestlers:",":wrestling:"],"category":"activity"},":performing_arts:":{"uc_base":"1f3ad","uc_output":"1f3ad","uc_match":"1f3ad","uc_greedy":"1f3ad","shortnames":[],"category":"activity"},":persevere:":{"uc_base":"1f623","uc_output":"1f623","uc_match":"1f623","uc_greedy":"1f623","shortnames":[],"category":"people"},":person_biking:":{"uc_base":"1f6b4","uc_output":"1f6b4","uc_match":"1f6b4","uc_greedy":"1f6b4","shortnames":[":bicyclist:"],"category":"activity"},":person_bowing:":{"uc_base":"1f647","uc_output":"1f647","uc_match":"1f647","uc_greedy":"1f647","shortnames":[":bow:"],"category":"people"},":person_climbing:":{"uc_base":"1f9d7","uc_output":"1f9d7","uc_match":"1f9d7","uc_greedy":"1f9d7","shortnames":[],"category":"activity"},":person_doing_cartwheel:":{"uc_base":"1f938","uc_output":"1f938","uc_match":"1f938","uc_greedy":"1f938","shortnames":[":cartwheel:"],"category":"activity"},":person_facepalming:":{"uc_base":"1f926","uc_output":"1f926","uc_match":"1f926","uc_greedy":"1f926","shortnames":[":face_palm:",":facepalm:"],"category":"people"},":person_fencing:":{"uc_base":"1f93a","uc_output":"1f93a","uc_match":"1f93a","uc_greedy":"1f93a","shortnames":[":fencer:",":fencing:"],"category":"activity"},":person_frowning:":{"uc_base":"1f64d","uc_output":"1f64d","uc_match":"1f64d","uc_greedy":"1f64d","shortnames":[],"category":"people"},":person_gesturing_no:":{"uc_base":"1f645","uc_output":"1f645","uc_match":"1f645","uc_greedy":"1f645","shortnames":[":no_good:"],"category":"people"},":person_gesturing_ok:":{"uc_base":"1f646","uc_output":"1f646","uc_match":"1f646","uc_greedy":"1f646","shortnames":[":ok_woman:"],"category":"people"},":person_getting_haircut:":{"uc_base":"1f487","uc_output":"1f487","uc_match":"1f487","uc_greedy":"1f487","shortnames":[":haircut:"],"category":"people"},":person_getting_massage:":{"uc_base":"1f486","uc_output":"1f486","uc_match":"1f486","uc_greedy":"1f486","shortnames":[":massage:"],"category":"people"},":person_in_lotus_position:":{"uc_base":"1f9d8","uc_output":"1f9d8","uc_match":"1f9d8","uc_greedy":"1f9d8","shortnames":[],"category":"activity"},":person_in_steamy_room:":{"uc_base":"1f9d6","uc_output":"1f9d6","uc_match":"1f9d6","uc_greedy":"1f9d6","shortnames":[],"category":"activity"},":person_juggling:":{"uc_base":"1f939","uc_output":"1f939","uc_match":"1f939","uc_greedy":"1f939","shortnames":[":juggling:",":juggler:"],"category":"activity"},":person_mountain_biking:":{"uc_base":"1f6b5","uc_output":"1f6b5","uc_match":"1f6b5","uc_greedy":"1f6b5","shortnames":[":mountain_bicyclist:"],"category":"activity"},":person_playing_handball:":{"uc_base":"1f93e","uc_output":"1f93e","uc_match":"1f93e","uc_greedy":"1f93e","shortnames":[":handball:"],"category":"activity"},":person_playing_water_polo:":{"uc_base":"1f93d","uc_output":"1f93d","uc_match":"1f93d","uc_greedy":"1f93d","shortnames":[":water_polo:"],"category":"activity"},":person_pouting:":{"uc_base":"1f64e","uc_output":"1f64e","uc_match":"1f64e","uc_greedy":"1f64e","shortnames":[":person_with_pouting_face:"],"category":"people"},":person_raising_hand:":{"uc_base":"1f64b","uc_output":"1f64b","uc_match":"1f64b","uc_greedy":"1f64b","shortnames":[":raising_hand:"],"category":"people"},":person_rowing_boat:":{"uc_base":"1f6a3","uc_output":"1f6a3","uc_match":"1f6a3","uc_greedy":"1f6a3","shortnames":[":rowboat:"],"category":"activity"},":person_running:":{"uc_base":"1f3c3","uc_output":"1f3c3","uc_match":"1f3c3","uc_greedy":"1f3c3","shortnames":[":runner:"],"category":"people"},":person_shrugging:":{"uc_base":"1f937","uc_output":"1f937","uc_match":"1f937","uc_greedy":"1f937","shortnames":[":shrug:"],"category":"people"},":person_surfing:":{"uc_base":"1f3c4","uc_output":"1f3c4","uc_match":"1f3c4","uc_greedy":"1f3c4","shortnames":[":surfer:"],"category":"activity"},":person_swimming:":{"uc_base":"1f3ca","uc_output":"1f3ca","uc_match":"1f3ca","uc_greedy":"1f3ca","shortnames":[":swimmer:"],"category":"activity"},":person_tipping_hand:":{"uc_base":"1f481","uc_output":"1f481","uc_match":"1f481","uc_greedy":"1f481","shortnames":[":information_desk_person:"],"category":"people"},":person_walking:":{"uc_base":"1f6b6","uc_output":"1f6b6","uc_match":"1f6b6","uc_greedy":"1f6b6","shortnames":[":walking:"],"category":"people"},":person_wearing_turban:":{"uc_base":"1f473","uc_output":"1f473","uc_match":"1f473","uc_greedy":"1f473","shortnames":[":man_with_turban:"],"category":"people"},":pie:":{"uc_base":"1f967","uc_output":"1f967","uc_match":"1f967","uc_greedy":"1f967","shortnames":[],"category":"food"},":pig2:":{"uc_base":"1f416","uc_output":"1f416","uc_match":"1f416","uc_greedy":"1f416","shortnames":[],"category":"nature"},":pig:":{"uc_base":"1f437","uc_output":"1f437","uc_match":"1f437","uc_greedy":"1f437","shortnames":[],"category":"nature"},":pig_nose:":{"uc_base":"1f43d","uc_output":"1f43d","uc_match":"1f43d","uc_greedy":"1f43d","shortnames":[],"category":"nature"},":pill:":{"uc_base":"1f48a","uc_output":"1f48a","uc_match":"1f48a","uc_greedy":"1f48a","shortnames":[],"category":"objects"},":pineapple:":{"uc_base":"1f34d","uc_output":"1f34d","uc_match":"1f34d","uc_greedy":"1f34d","shortnames":[],"category":"food"},":ping_pong:":{"uc_base":"1f3d3","uc_output":"1f3d3","uc_match":"1f3d3","uc_greedy":"1f3d3","shortnames":[":table_tennis:"],"category":"activity"},":pizza:":{"uc_base":"1f355","uc_output":"1f355","uc_match":"1f355","uc_greedy":"1f355","shortnames":[],"category":"food"},":place_of_worship:":{"uc_base":"1f6d0","uc_output":"1f6d0","uc_match":"1f6d0","uc_greedy":"1f6d0","shortnames":[":worship_symbol:"],"category":"symbols"},":point_down:":{"uc_base":"1f447","uc_output":"1f447","uc_match":"1f447","uc_greedy":"1f447","shortnames":[],"category":"people"},":point_left:":{"uc_base":"1f448","uc_output":"1f448","uc_match":"1f448","uc_greedy":"1f448","shortnames":[],"category":"people"},":point_right:":{"uc_base":"1f449","uc_output":"1f449","uc_match":"1f449","uc_greedy":"1f449","shortnames":[],"category":"people"},":point_up_2:":{"uc_base":"1f446","uc_output":"1f446","uc_match":"1f446","uc_greedy":"1f446","shortnames":[],"category":"people"},":police_car:":{"uc_base":"1f693","uc_output":"1f693","uc_match":"1f693","uc_greedy":"1f693","shortnames":[],"category":"travel"},":police_officer:":{"uc_base":"1f46e","uc_output":"1f46e","uc_match":"1f46e","uc_greedy":"1f46e","shortnames":[":cop:"],"category":"people"},":poodle:":{"uc_base":"1f429","uc_output":"1f429","uc_match":"1f429","uc_greedy":"1f429","shortnames":[],"category":"nature"},":poop:":{"uc_base":"1f4a9","uc_output":"1f4a9","uc_match":"1f4a9","uc_greedy":"1f4a9","shortnames":[":shit:",":hankey:",":poo:"],"category":"people"},":popcorn:":{"uc_base":"1f37f","uc_output":"1f37f","uc_match":"1f37f","uc_greedy":"1f37f","shortnames":[],"category":"food"},":post_office:":{"uc_base":"1f3e3","uc_output":"1f3e3","uc_match":"1f3e3","uc_greedy":"1f3e3","shortnames":[],"category":"travel"},":postal_horn:":{"uc_base":"1f4ef","uc_output":"1f4ef","uc_match":"1f4ef","uc_greedy":"1f4ef","shortnames":[],"category":"objects"},":postbox:":{"uc_base":"1f4ee","uc_output":"1f4ee","uc_match":"1f4ee","uc_greedy":"1f4ee","shortnames":[],"category":"objects"},":potable_water:":{"uc_base":"1f6b0","uc_output":"1f6b0","uc_match":"1f6b0","uc_greedy":"1f6b0","shortnames":[],"category":"objects"},":potato:":{"uc_base":"1f954","uc_output":"1f954","uc_match":"1f954","uc_greedy":"1f954","shortnames":[],"category":"food"},":pouch:":{"uc_base":"1f45d","uc_output":"1f45d","uc_match":"1f45d","uc_greedy":"1f45d","shortnames":[],"category":"people"},":poultry_leg:":{"uc_base":"1f357","uc_output":"1f357","uc_match":"1f357","uc_greedy":"1f357","shortnames":[],"category":"food"},":pound:":{"uc_base":"1f4b7","uc_output":"1f4b7","uc_match":"1f4b7","uc_greedy":"1f4b7","shortnames":[],"category":"objects"},":pouting_cat:":{"uc_base":"1f63e","uc_output":"1f63e","uc_match":"1f63e","uc_greedy":"1f63e","shortnames":[],"category":"people"},":pray:":{"uc_base":"1f64f","uc_output":"1f64f","uc_match":"1f64f","uc_greedy":"1f64f","shortnames":[],"category":"people"},":prayer_beads:":{"uc_base":"1f4ff","uc_output":"1f4ff","uc_match":"1f4ff","uc_greedy":"1f4ff","shortnames":[],"category":"objects"},":pregnant_woman:":{"uc_base":"1f930","uc_output":"1f930","uc_match":"1f930","uc_greedy":"1f930","shortnames":[":expecting_woman:"],"category":"people"},":pretzel:":{"uc_base":"1f968","uc_output":"1f968","uc_match":"1f968","uc_greedy":"1f968","shortnames":[],"category":"food"},":prince:":{"uc_base":"1f934","uc_output":"1f934","uc_match":"1f934","uc_greedy":"1f934","shortnames":[],"category":"people"},":princess:":{"uc_base":"1f478","uc_output":"1f478","uc_match":"1f478","uc_greedy":"1f478","shortnames":[],"category":"people"},":punch:":{"uc_base":"1f44a","uc_output":"1f44a","uc_match":"1f44a","uc_greedy":"1f44a","shortnames":[],"category":"people"},":purple_heart:":{"uc_base":"1f49c","uc_output":"1f49c","uc_match":"1f49c","uc_greedy":"1f49c","shortnames":[],"category":"symbols"},":purse:":{"uc_base":"1f45b","uc_output":"1f45b","uc_match":"1f45b","uc_greedy":"1f45b","shortnames":[],"category":"people"},":pushpin:":{"uc_base":"1f4cc","uc_output":"1f4cc","uc_match":"1f4cc","uc_greedy":"1f4cc","shortnames":[],"category":"objects"},":put_litter_in_its_place:":{"uc_base":"1f6ae","uc_output":"1f6ae","uc_match":"1f6ae","uc_greedy":"1f6ae","shortnames":[],"category":"symbols"},":rabbit2:":{"uc_base":"1f407","uc_output":"1f407","uc_match":"1f407","uc_greedy":"1f407","shortnames":[],"category":"nature"},":rabbit:":{"uc_base":"1f430","uc_output":"1f430","uc_match":"1f430","uc_greedy":"1f430","shortnames":[],"category":"nature"},":racehorse:":{"uc_base":"1f40e","uc_output":"1f40e","uc_match":"1f40e","uc_greedy":"1f40e","shortnames":[],"category":"nature"},":radio:":{"uc_base":"1f4fb","uc_output":"1f4fb","uc_match":"1f4fb","uc_greedy":"1f4fb","shortnames":[],"category":"objects"},":radio_button:":{"uc_base":"1f518","uc_output":"1f518","uc_match":"1f518","uc_greedy":"1f518","shortnames":[],"category":"symbols"},":rage:":{"uc_base":"1f621","uc_output":"1f621","uc_match":"1f621","uc_greedy":"1f621","shortnames":[],"category":"people"},":railway_car:":{"uc_base":"1f683","uc_output":"1f683","uc_match":"1f683","uc_greedy":"1f683","shortnames":[],"category":"travel"},":rainbow:":{"uc_base":"1f308","uc_output":"1f308","uc_match":"1f308","uc_greedy":"1f308","shortnames":[],"category":"nature"},":raised_back_of_hand:":{"uc_base":"1f91a","uc_output":"1f91a","uc_match":"1f91a","uc_greedy":"1f91a","shortnames":[":back_of_hand:"],"category":"people"},":raised_hands:":{"uc_base":"1f64c","uc_output":"1f64c","uc_match":"1f64c","uc_greedy":"1f64c","shortnames":[],"category":"people"},":ram:":{"uc_base":"1f40f","uc_output":"1f40f","uc_match":"1f40f","uc_greedy":"1f40f","shortnames":[],"category":"nature"},":ramen:":{"uc_base":"1f35c","uc_output":"1f35c","uc_match":"1f35c","uc_greedy":"1f35c","shortnames":[],"category":"food"},":rat:":{"uc_base":"1f400","uc_output":"1f400","uc_match":"1f400","uc_greedy":"1f400","shortnames":[],"category":"nature"},":red_car:":{"uc_base":"1f697","uc_output":"1f697","uc_match":"1f697","uc_greedy":"1f697","shortnames":[],"category":"travel"},":red_circle:":{"uc_base":"1f534","uc_output":"1f534","uc_match":"1f534","uc_greedy":"1f534","shortnames":[],"category":"symbols"},":regional_indicator_a:":{"uc_base":"1f1e6","uc_output":"1f1e6","uc_match":"1f1e6","uc_greedy":"1f1e6","shortnames":[],"category":"regional"},":regional_indicator_b:":{"uc_base":"1f1e7","uc_output":"1f1e7","uc_match":"1f1e7","uc_greedy":"1f1e7","shortnames":[],"category":"regional"},":regional_indicator_c:":{"uc_base":"1f1e8","uc_output":"1f1e8","uc_match":"1f1e8","uc_greedy":"1f1e8","shortnames":[],"category":"regional"},":regional_indicator_d:":{"uc_base":"1f1e9","uc_output":"1f1e9","uc_match":"1f1e9","uc_greedy":"1f1e9","shortnames":[],"category":"regional"},":regional_indicator_e:":{"uc_base":"1f1ea","uc_output":"1f1ea","uc_match":"1f1ea","uc_greedy":"1f1ea","shortnames":[],"category":"regional"},":regional_indicator_f:":{"uc_base":"1f1eb","uc_output":"1f1eb","uc_match":"1f1eb","uc_greedy":"1f1eb","shortnames":[],"category":"regional"},":regional_indicator_g:":{"uc_base":"1f1ec","uc_output":"1f1ec","uc_match":"1f1ec","uc_greedy":"1f1ec","shortnames":[],"category":"regional"},":regional_indicator_h:":{"uc_base":"1f1ed","uc_output":"1f1ed","uc_match":"1f1ed","uc_greedy":"1f1ed","shortnames":[],"category":"regional"},":regional_indicator_i:":{"uc_base":"1f1ee","uc_output":"1f1ee","uc_match":"1f1ee","uc_greedy":"1f1ee","shortnames":[],"category":"regional"},":regional_indicator_j:":{"uc_base":"1f1ef","uc_output":"1f1ef","uc_match":"1f1ef","uc_greedy":"1f1ef","shortnames":[],"category":"regional"},":regional_indicator_k:":{"uc_base":"1f1f0","uc_output":"1f1f0","uc_match":"1f1f0","uc_greedy":"1f1f0","shortnames":[],"category":"regional"},":regional_indicator_l:":{"uc_base":"1f1f1","uc_output":"1f1f1","uc_match":"1f1f1","uc_greedy":"1f1f1","shortnames":[],"category":"regional"},":regional_indicator_m:":{"uc_base":"1f1f2","uc_output":"1f1f2","uc_match":"1f1f2","uc_greedy":"1f1f2","shortnames":[],"category":"regional"},":regional_indicator_n:":{"uc_base":"1f1f3","uc_output":"1f1f3","uc_match":"1f1f3","uc_greedy":"1f1f3","shortnames":[],"category":"regional"},":regional_indicator_o:":{"uc_base":"1f1f4","uc_output":"1f1f4","uc_match":"1f1f4","uc_greedy":"1f1f4","shortnames":[],"category":"regional"},":regional_indicator_p:":{"uc_base":"1f1f5","uc_output":"1f1f5","uc_match":"1f1f5","uc_greedy":"1f1f5","shortnames":[],"category":"regional"},":regional_indicator_q:":{"uc_base":"1f1f6","uc_output":"1f1f6","uc_match":"1f1f6","uc_greedy":"1f1f6","shortnames":[],"category":"regional"},":regional_indicator_r:":{"uc_base":"1f1f7","uc_output":"1f1f7","uc_match":"1f1f7","uc_greedy":"1f1f7","shortnames":[],"category":"regional"},":regional_indicator_s:":{"uc_base":"1f1f8","uc_output":"1f1f8","uc_match":"1f1f8","uc_greedy":"1f1f8","shortnames":[],"category":"regional"},":regional_indicator_t:":{"uc_base":"1f1f9","uc_output":"1f1f9","uc_match":"1f1f9","uc_greedy":"1f1f9","shortnames":[],"category":"regional"},":regional_indicator_u:":{"uc_base":"1f1fa","uc_output":"1f1fa","uc_match":"1f1fa","uc_greedy":"1f1fa","shortnames":[],"category":"regional"},":regional_indicator_v:":{"uc_base":"1f1fb","uc_output":"1f1fb","uc_match":"1f1fb","uc_greedy":"1f1fb","shortnames":[],"category":"regional"},":regional_indicator_w:":{"uc_base":"1f1fc","uc_output":"1f1fc","uc_match":"1f1fc","uc_greedy":"1f1fc","shortnames":[],"category":"regional"},":regional_indicator_x:":{"uc_base":"1f1fd","uc_output":"1f1fd","uc_match":"1f1fd","uc_greedy":"1f1fd","shortnames":[],"category":"regional"},":regional_indicator_y:":{"uc_base":"1f1fe","uc_output":"1f1fe","uc_match":"1f1fe","uc_greedy":"1f1fe","shortnames":[],"category":"regional"},":regional_indicator_z:":{"uc_base":"1f1ff","uc_output":"1f1ff","uc_match":"1f1ff","uc_greedy":"1f1ff","shortnames":[],"category":"regional"},":relieved:":{"uc_base":"1f60c","uc_output":"1f60c","uc_match":"1f60c","uc_greedy":"1f60c","shortnames":[],"category":"people"},":repeat:":{"uc_base":"1f501","uc_output":"1f501","uc_match":"1f501","uc_greedy":"1f501","shortnames":[],"category":"symbols"},":repeat_one:":{"uc_base":"1f502","uc_output":"1f502","uc_match":"1f502","uc_greedy":"1f502","shortnames":[],"category":"symbols"},":restroom:":{"uc_base":"1f6bb","uc_output":"1f6bb","uc_match":"1f6bb","uc_greedy":"1f6bb","shortnames":[],"category":"symbols"},":revolving_hearts:":{"uc_base":"1f49e","uc_output":"1f49e","uc_match":"1f49e","uc_greedy":"1f49e","shortnames":[],"category":"symbols"},":rhino:":{"uc_base":"1f98f","uc_output":"1f98f","uc_match":"1f98f","uc_greedy":"1f98f","shortnames":[":rhinoceros:"],"category":"nature"},":ribbon:":{"uc_base":"1f380","uc_output":"1f380","uc_match":"1f380","uc_greedy":"1f380","shortnames":[],"category":"objects"},":rice:":{"uc_base":"1f35a","uc_output":"1f35a","uc_match":"1f35a","uc_greedy":"1f35a","shortnames":[],"category":"food"},":rice_ball:":{"uc_base":"1f359","uc_output":"1f359","uc_match":"1f359","uc_greedy":"1f359","shortnames":[],"category":"food"},":rice_cracker:":{"uc_base":"1f358","uc_output":"1f358","uc_match":"1f358","uc_greedy":"1f358","shortnames":[],"category":"food"},":rice_scene:":{"uc_base":"1f391","uc_output":"1f391","uc_match":"1f391","uc_greedy":"1f391","shortnames":[],"category":"travel"},":right_facing_fist:":{"uc_base":"1f91c","uc_output":"1f91c","uc_match":"1f91c","uc_greedy":"1f91c","shortnames":[":right_fist:"],"category":"people"},":ring:":{"uc_base":"1f48d","uc_output":"1f48d","uc_match":"1f48d","uc_greedy":"1f48d","shortnames":[],"category":"people"},":robot:":{"uc_base":"1f916","uc_output":"1f916","uc_match":"1f916","uc_greedy":"1f916","shortnames":[":robot_face:"],"category":"people"},":rocket:":{"uc_base":"1f680","uc_output":"1f680","uc_match":"1f680","uc_greedy":"1f680","shortnames":[],"category":"travel"},":rofl:":{"uc_base":"1f923","uc_output":"1f923","uc_match":"1f923","uc_greedy":"1f923","shortnames":[":rolling_on_the_floor_laughing:"],"category":"people"},":roller_coaster:":{"uc_base":"1f3a2","uc_output":"1f3a2","uc_match":"1f3a2","uc_greedy":"1f3a2","shortnames":[],"category":"travel"},":rolling_eyes:":{"uc_base":"1f644","uc_output":"1f644","uc_match":"1f644","uc_greedy":"1f644","shortnames":[":face_with_rolling_eyes:"],"category":"people"},":rooster:":{"uc_base":"1f413","uc_output":"1f413","uc_match":"1f413","uc_greedy":"1f413","shortnames":[],"category":"nature"},":rose:":{"uc_base":"1f339","uc_output":"1f339","uc_match":"1f339","uc_greedy":"1f339","shortnames":[],"category":"nature"},":rotating_light:":{"uc_base":"1f6a8","uc_output":"1f6a8","uc_match":"1f6a8","uc_greedy":"1f6a8","shortnames":[],"category":"travel"},":round_pushpin:":{"uc_base":"1f4cd","uc_output":"1f4cd","uc_match":"1f4cd","uc_greedy":"1f4cd","shortnames":[],"category":"objects"},":rugby_football:":{"uc_base":"1f3c9","uc_output":"1f3c9","uc_match":"1f3c9","uc_greedy":"1f3c9","shortnames":[],"category":"activity"},":running_shirt_with_sash:":{"uc_base":"1f3bd","uc_output":"1f3bd","uc_match":"1f3bd","uc_greedy":"1f3bd","shortnames":[],"category":"activity"},":sake:":{"uc_base":"1f376","uc_output":"1f376","uc_match":"1f376","uc_greedy":"1f376","shortnames":[],"category":"food"},":salad:":{"uc_base":"1f957","uc_output":"1f957","uc_match":"1f957","uc_greedy":"1f957","shortnames":[":green_salad:"],"category":"food"},":sandal:":{"uc_base":"1f461","uc_output":"1f461","uc_match":"1f461","uc_greedy":"1f461","shortnames":[],"category":"people"},":sandwich:":{"uc_base":"1f96a","uc_output":"1f96a","uc_match":"1f96a","uc_greedy":"1f96a","shortnames":[],"category":"food"},":santa:":{"uc_base":"1f385","uc_output":"1f385","uc_match":"1f385","uc_greedy":"1f385","shortnames":[],"category":"people"},":satellite:":{"uc_base":"1f4e1","uc_output":"1f4e1","uc_match":"1f4e1","uc_greedy":"1f4e1","shortnames":[],"category":"objects"},":sauropod:":{"uc_base":"1f995","uc_output":"1f995","uc_match":"1f995","uc_greedy":"1f995","shortnames":[],"category":"nature"},":saxophone:":{"uc_base":"1f3b7","uc_output":"1f3b7","uc_match":"1f3b7","uc_greedy":"1f3b7","shortnames":[],"category":"activity"},":scarf:":{"uc_base":"1f9e3","uc_output":"1f9e3","uc_match":"1f9e3","uc_greedy":"1f9e3","shortnames":[],"category":"people"},":school:":{"uc_base":"1f3eb","uc_output":"1f3eb","uc_match":"1f3eb","uc_greedy":"1f3eb","shortnames":[],"category":"travel"},":school_satchel:":{"uc_base":"1f392","uc_output":"1f392","uc_match":"1f392","uc_greedy":"1f392","shortnames":[],"category":"people"},":scooter:":{"uc_base":"1f6f4","uc_output":"1f6f4","uc_match":"1f6f4","uc_greedy":"1f6f4","shortnames":[],"category":"travel"},":scorpion:":{"uc_base":"1f982","uc_output":"1f982","uc_match":"1f982","uc_greedy":"1f982","shortnames":[],"category":"nature"},":scream:":{"uc_base":"1f631","uc_output":"1f631","uc_match":"1f631","uc_greedy":"1f631","shortnames":[],"category":"people"},":scream_cat:":{"uc_base":"1f640","uc_output":"1f640","uc_match":"1f640","uc_greedy":"1f640","shortnames":[],"category":"people"},":scroll:":{"uc_base":"1f4dc","uc_output":"1f4dc","uc_match":"1f4dc","uc_greedy":"1f4dc","shortnames":[],"category":"objects"},":seat:":{"uc_base":"1f4ba","uc_output":"1f4ba","uc_match":"1f4ba","uc_greedy":"1f4ba","shortnames":[],"category":"travel"},":second_place:":{"uc_base":"1f948","uc_output":"1f948","uc_match":"1f948","uc_greedy":"1f948","shortnames":[":second_place_medal:"],"category":"activity"},":see_no_evil:":{"uc_base":"1f648","uc_output":"1f648","uc_match":"1f648","uc_greedy":"1f648","shortnames":[],"category":"nature"},":seedling:":{"uc_base":"1f331","uc_output":"1f331","uc_match":"1f331","uc_greedy":"1f331","shortnames":[],"category":"nature"},":selfie:":{"uc_base":"1f933","uc_output":"1f933","uc_match":"1f933","uc_greedy":"1f933","shortnames":[],"category":"people"},":shallow_pan_of_food:":{"uc_base":"1f958","uc_output":"1f958","uc_match":"1f958","uc_greedy":"1f958","shortnames":[":paella:"],"category":"food"},":shark:":{"uc_base":"1f988","uc_output":"1f988","uc_match":"1f988","uc_greedy":"1f988","shortnames":[],"category":"nature"},":shaved_ice:":{"uc_base":"1f367","uc_output":"1f367","uc_match":"1f367","uc_greedy":"1f367","shortnames":[],"category":"food"},":sheep:":{"uc_base":"1f411","uc_output":"1f411","uc_match":"1f411","uc_greedy":"1f411","shortnames":[],"category":"nature"},":shell:":{"uc_base":"1f41a","uc_output":"1f41a","uc_match":"1f41a","uc_greedy":"1f41a","shortnames":[],"category":"nature"},":ship:":{"uc_base":"1f6a2","uc_output":"1f6a2","uc_match":"1f6a2","uc_greedy":"1f6a2","shortnames":[],"category":"travel"},":shirt:":{"uc_base":"1f455","uc_output":"1f455","uc_match":"1f455","uc_greedy":"1f455","shortnames":[],"category":"people"},":shopping_cart:":{"uc_base":"1f6d2","uc_output":"1f6d2","uc_match":"1f6d2","uc_greedy":"1f6d2","shortnames":[":shopping_trolley:"],"category":"objects"},":shower:":{"uc_base":"1f6bf","uc_output":"1f6bf","uc_match":"1f6bf","uc_greedy":"1f6bf","shortnames":[],"category":"objects"},":shrimp:":{"uc_base":"1f990","uc_output":"1f990","uc_match":"1f990","uc_greedy":"1f990","shortnames":[],"category":"nature"},":shushing_face:":{"uc_base":"1f92b","uc_output":"1f92b","uc_match":"1f92b","uc_greedy":"1f92b","shortnames":[],"category":"people"},":signal_strength:":{"uc_base":"1f4f6","uc_output":"1f4f6","uc_match":"1f4f6","uc_greedy":"1f4f6","shortnames":[],"category":"symbols"},":six_pointed_star:":{"uc_base":"1f52f","uc_output":"1f52f","uc_match":"1f52f","uc_greedy":"1f52f","shortnames":[],"category":"symbols"},":ski:":{"uc_base":"1f3bf","uc_output":"1f3bf","uc_match":"1f3bf","uc_greedy":"1f3bf","shortnames":[],"category":"activity"},":skull:":{"uc_base":"1f480","uc_output":"1f480","uc_match":"1f480","uc_greedy":"1f480","shortnames":[":skeleton:"],"category":"people"},":sled:":{"uc_base":"1f6f7","uc_output":"1f6f7","uc_match":"1f6f7","uc_greedy":"1f6f7","shortnames":[],"category":"activity"},":sleeping:":{"uc_base":"1f634","uc_output":"1f634","uc_match":"1f634","uc_greedy":"1f634","shortnames":[],"category":"people"},":sleeping_accommodation:":{"uc_base":"1f6cc","uc_output":"1f6cc","uc_match":"1f6cc","uc_greedy":"1f6cc","shortnames":[],"category":"objects"},":sleepy:":{"uc_base":"1f62a","uc_output":"1f62a","uc_match":"1f62a","uc_greedy":"1f62a","shortnames":[],"category":"people"},":slight_frown:":{"uc_base":"1f641","uc_output":"1f641","uc_match":"1f641","uc_greedy":"1f641","shortnames":[":slightly_frowning_face:"],"category":"people"},":slight_smile:":{"uc_base":"1f642","uc_output":"1f642","uc_match":"1f642","uc_greedy":"1f642","shortnames":[":slightly_smiling_face:"],"category":"people"},":slot_machine:":{"uc_base":"1f3b0","uc_output":"1f3b0","uc_match":"1f3b0","uc_greedy":"1f3b0","shortnames":[],"category":"activity"},":small_blue_diamond:":{"uc_base":"1f539","uc_output":"1f539","uc_match":"1f539","uc_greedy":"1f539","shortnames":[],"category":"symbols"},":small_orange_diamond:":{"uc_base":"1f538","uc_output":"1f538","uc_match":"1f538","uc_greedy":"1f538","shortnames":[],"category":"symbols"},":small_red_triangle:":{"uc_base":"1f53a","uc_output":"1f53a","uc_match":"1f53a","uc_greedy":"1f53a","shortnames":[],"category":"symbols"},":small_red_triangle_down:":{"uc_base":"1f53b","uc_output":"1f53b","uc_match":"1f53b","uc_greedy":"1f53b","shortnames":[],"category":"symbols"},":smile:":{"uc_base":"1f604","uc_output":"1f604","uc_match":"1f604","uc_greedy":"1f604","shortnames":[],"category":"people"},":smile_cat:":{"uc_base":"1f638","uc_output":"1f638","uc_match":"1f638","uc_greedy":"1f638","shortnames":[],"category":"people"},":smiley:":{"uc_base":"1f603","uc_output":"1f603","uc_match":"1f603","uc_greedy":"1f603","shortnames":[],"category":"people"},":smiley_cat:":{"uc_base":"1f63a","uc_output":"1f63a","uc_match":"1f63a","uc_greedy":"1f63a","shortnames":[],"category":"people"},":smiling_imp:":{"uc_base":"1f608","uc_output":"1f608","uc_match":"1f608","uc_greedy":"1f608","shortnames":[],"category":"people"},":smirk:":{"uc_base":"1f60f","uc_output":"1f60f","uc_match":"1f60f","uc_greedy":"1f60f","shortnames":[],"category":"people"},":smirk_cat:":{"uc_base":"1f63c","uc_output":"1f63c","uc_match":"1f63c","uc_greedy":"1f63c","shortnames":[],"category":"people"},":smoking:":{"uc_base":"1f6ac","uc_output":"1f6ac","uc_match":"1f6ac","uc_greedy":"1f6ac","shortnames":[],"category":"objects"},":snail:":{"uc_base":"1f40c","uc_output":"1f40c","uc_match":"1f40c","uc_greedy":"1f40c","shortnames":[],"category":"nature"},":snake:":{"uc_base":"1f40d","uc_output":"1f40d","uc_match":"1f40d","uc_greedy":"1f40d","shortnames":[],"category":"nature"},":sneezing_face:":{"uc_base":"1f927","uc_output":"1f927","uc_match":"1f927","uc_greedy":"1f927","shortnames":[":sneeze:"],"category":"people"},":snowboarder:":{"uc_base":"1f3c2","uc_output":"1f3c2","uc_match":"1f3c2","uc_greedy":"1f3c2","shortnames":[],"category":"activity"},":sob:":{"uc_base":"1f62d","uc_output":"1f62d","uc_match":"1f62d","uc_greedy":"1f62d","shortnames":[],"category":"people"},":socks:":{"uc_base":"1f9e6","uc_output":"1f9e6","uc_match":"1f9e6","uc_greedy":"1f9e6","shortnames":[],"category":"people"},":soon:":{"uc_base":"1f51c","uc_output":"1f51c","uc_match":"1f51c","uc_greedy":"1f51c","shortnames":[],"category":"symbols"},":sos:":{"uc_base":"1f198","uc_output":"1f198","uc_match":"1f198","uc_greedy":"1f198","shortnames":[],"category":"symbols"},":sound:":{"uc_base":"1f509","uc_output":"1f509","uc_match":"1f509","uc_greedy":"1f509","shortnames":[],"category":"symbols"},":space_invader:":{"uc_base":"1f47e","uc_output":"1f47e","uc_match":"1f47e","uc_greedy":"1f47e","shortnames":[],"category":"people"},":spaghetti:":{"uc_base":"1f35d","uc_output":"1f35d","uc_match":"1f35d","uc_greedy":"1f35d","shortnames":[],"category":"food"},":sparkler:":{"uc_base":"1f387","uc_output":"1f387","uc_match":"1f387","uc_greedy":"1f387","shortnames":[],"category":"travel"},":sparkling_heart:":{"uc_base":"1f496","uc_output":"1f496","uc_match":"1f496","uc_greedy":"1f496","shortnames":[],"category":"symbols"},":speak_no_evil:":{"uc_base":"1f64a","uc_output":"1f64a","uc_match":"1f64a","uc_greedy":"1f64a","shortnames":[],"category":"nature"},":speaker:":{"uc_base":"1f508","uc_output":"1f508","uc_match":"1f508","uc_greedy":"1f508","shortnames":[],"category":"symbols"},":speech_balloon:":{"uc_base":"1f4ac","uc_output":"1f4ac","uc_match":"1f4ac","uc_greedy":"1f4ac","shortnames":[],"category":"symbols"},":speedboat:":{"uc_base":"1f6a4","uc_output":"1f6a4","uc_match":"1f6a4","uc_greedy":"1f6a4","shortnames":[],"category":"travel"},":spoon:":{"uc_base":"1f944","uc_output":"1f944","uc_match":"1f944","uc_greedy":"1f944","shortnames":[],"category":"food"},":squid:":{"uc_base":"1f991","uc_output":"1f991","uc_match":"1f991","uc_greedy":"1f991","shortnames":[],"category":"nature"},":star2:":{"uc_base":"1f31f","uc_output":"1f31f","uc_match":"1f31f","uc_greedy":"1f31f","shortnames":[],"category":"nature"},":star_struck:":{"uc_base":"1f929","uc_output":"1f929","uc_match":"1f929","uc_greedy":"1f929","shortnames":[],"category":"people"},":stars:":{"uc_base":"1f320","uc_output":"1f320","uc_match":"1f320","uc_greedy":"1f320","shortnames":[],"category":"travel"},":station:":{"uc_base":"1f689","uc_output":"1f689","uc_match":"1f689","uc_greedy":"1f689","shortnames":[],"category":"travel"},":statue_of_liberty:":{"uc_base":"1f5fd","uc_output":"1f5fd","uc_match":"1f5fd","uc_greedy":"1f5fd","shortnames":[],"category":"travel"},":steam_locomotive:":{"uc_base":"1f682","uc_output":"1f682","uc_match":"1f682","uc_greedy":"1f682","shortnames":[],"category":"travel"},":stew:":{"uc_base":"1f372","uc_output":"1f372","uc_match":"1f372","uc_greedy":"1f372","shortnames":[],"category":"food"},":straight_ruler:":{"uc_base":"1f4cf","uc_output":"1f4cf","uc_match":"1f4cf","uc_greedy":"1f4cf","shortnames":[],"category":"objects"},":strawberry:":{"uc_base":"1f353","uc_output":"1f353","uc_match":"1f353","uc_greedy":"1f353","shortnames":[],"category":"food"},":stuck_out_tongue:":{"uc_base":"1f61b","uc_output":"1f61b","uc_match":"1f61b","uc_greedy":"1f61b","shortnames":[],"category":"people"},":stuck_out_tongue_closed_eyes:":{"uc_base":"1f61d","uc_output":"1f61d","uc_match":"1f61d","uc_greedy":"1f61d","shortnames":[],"category":"people"},":stuck_out_tongue_winking_eye:":{"uc_base":"1f61c","uc_output":"1f61c","uc_match":"1f61c","uc_greedy":"1f61c","shortnames":[],"category":"people"},":stuffed_flatbread:":{"uc_base":"1f959","uc_output":"1f959","uc_match":"1f959","uc_greedy":"1f959","shortnames":[":stuffed_pita:"],"category":"food"},":sun_with_face:":{"uc_base":"1f31e","uc_output":"1f31e","uc_match":"1f31e","uc_greedy":"1f31e","shortnames":[],"category":"nature"},":sunflower:":{"uc_base":"1f33b","uc_output":"1f33b","uc_match":"1f33b","uc_greedy":"1f33b","shortnames":[],"category":"nature"},":sunglasses:":{"uc_base":"1f60e","uc_output":"1f60e","uc_match":"1f60e","uc_greedy":"1f60e","shortnames":[],"category":"people"},":sunrise:":{"uc_base":"1f305","uc_output":"1f305","uc_match":"1f305","uc_greedy":"1f305","shortnames":[],"category":"travel"},":sunrise_over_mountains:":{"uc_base":"1f304","uc_output":"1f304","uc_match":"1f304","uc_greedy":"1f304","shortnames":[],"category":"travel"},":sushi:":{"uc_base":"1f363","uc_output":"1f363","uc_match":"1f363","uc_greedy":"1f363","shortnames":[],"category":"food"},":suspension_railway:":{"uc_base":"1f69f","uc_output":"1f69f","uc_match":"1f69f","uc_greedy":"1f69f","shortnames":[],"category":"travel"},":sweat:":{"uc_base":"1f613","uc_output":"1f613","uc_match":"1f613","uc_greedy":"1f613","shortnames":[],"category":"people"},":sweat_drops:":{"uc_base":"1f4a6","uc_output":"1f4a6","uc_match":"1f4a6","uc_greedy":"1f4a6","shortnames":[],"category":"nature"},":sweat_smile:":{"uc_base":"1f605","uc_output":"1f605","uc_match":"1f605","uc_greedy":"1f605","shortnames":[],"category":"people"},":sweet_potato:":{"uc_base":"1f360","uc_output":"1f360","uc_match":"1f360","uc_greedy":"1f360","shortnames":[],"category":"food"},":symbols:":{"uc_base":"1f523","uc_output":"1f523","uc_match":"1f523","uc_greedy":"1f523","shortnames":[],"category":"symbols"},":synagogue:":{"uc_base":"1f54d","uc_output":"1f54d","uc_match":"1f54d","uc_greedy":"1f54d","shortnames":[],"category":"travel"},":syringe:":{"uc_base":"1f489","uc_output":"1f489","uc_match":"1f489","uc_greedy":"1f489","shortnames":[],"category":"objects"},":t_rex:":{"uc_base":"1f996","uc_output":"1f996","uc_match":"1f996","uc_greedy":"1f996","shortnames":[],"category":"nature"},":taco:":{"uc_base":"1f32e","uc_output":"1f32e","uc_match":"1f32e","uc_greedy":"1f32e","shortnames":[],"category":"food"},":tada:":{"uc_base":"1f389","uc_output":"1f389","uc_match":"1f389","uc_greedy":"1f389","shortnames":[],"category":"objects"},":takeout_box:":{"uc_base":"1f961","uc_output":"1f961","uc_match":"1f961","uc_greedy":"1f961","shortnames":[],"category":"food"},":tanabata_tree:":{"uc_base":"1f38b","uc_output":"1f38b","uc_match":"1f38b","uc_greedy":"1f38b","shortnames":[],"category":"nature"},":tangerine:":{"uc_base":"1f34a","uc_output":"1f34a","uc_match":"1f34a","uc_greedy":"1f34a","shortnames":[],"category":"food"},":taxi:":{"uc_base":"1f695","uc_output":"1f695","uc_match":"1f695","uc_greedy":"1f695","shortnames":[],"category":"travel"},":tea:":{"uc_base":"1f375","uc_output":"1f375","uc_match":"1f375","uc_greedy":"1f375","shortnames":[],"category":"food"},":telephone_receiver:":{"uc_base":"1f4de","uc_output":"1f4de","uc_match":"1f4de","uc_greedy":"1f4de","shortnames":[],"category":"objects"},":telescope:":{"uc_base":"1f52d","uc_output":"1f52d","uc_match":"1f52d","uc_greedy":"1f52d","shortnames":[],"category":"objects"},":tennis:":{"uc_base":"1f3be","uc_output":"1f3be","uc_match":"1f3be","uc_greedy":"1f3be","shortnames":[],"category":"activity"},":thermometer_face:":{"uc_base":"1f912","uc_output":"1f912","uc_match":"1f912","uc_greedy":"1f912","shortnames":[":face_with_thermometer:"],"category":"people"},":thinking:":{"uc_base":"1f914","uc_output":"1f914","uc_match":"1f914","uc_greedy":"1f914","shortnames":[":thinking_face:"],"category":"people"},":third_place:":{"uc_base":"1f949","uc_output":"1f949","uc_match":"1f949","uc_greedy":"1f949","shortnames":[":third_place_medal:"],"category":"activity"},":thought_balloon:":{"uc_base":"1f4ad","uc_output":"1f4ad","uc_match":"1f4ad","uc_greedy":"1f4ad","shortnames":[],"category":"symbols"},":thumbsdown:":{"uc_base":"1f44e","uc_output":"1f44e","uc_match":"1f44e","uc_greedy":"1f44e","shortnames":[":-1:",":thumbdown:"],"category":"people"},":thumbsup:":{"uc_base":"1f44d","uc_output":"1f44d","uc_match":"1f44d","uc_greedy":"1f44d","shortnames":[":+1:",":thumbup:"],"category":"people"},":ticket:":{"uc_base":"1f3ab","uc_output":"1f3ab","uc_match":"1f3ab","uc_greedy":"1f3ab","shortnames":[],"category":"activity"},":tiger2:":{"uc_base":"1f405","uc_output":"1f405","uc_match":"1f405","uc_greedy":"1f405","shortnames":[],"category":"nature"},":tiger:":{"uc_base":"1f42f","uc_output":"1f42f","uc_match":"1f42f","uc_greedy":"1f42f","shortnames":[],"category":"nature"},":tired_face:":{"uc_base":"1f62b","uc_output":"1f62b","uc_match":"1f62b","uc_greedy":"1f62b","shortnames":[],"category":"people"},":toilet:":{"uc_base":"1f6bd","uc_output":"1f6bd","uc_match":"1f6bd","uc_greedy":"1f6bd","shortnames":[],"category":"objects"},":tokyo_tower:":{"uc_base":"1f5fc","uc_output":"1f5fc","uc_match":"1f5fc","uc_greedy":"1f5fc","shortnames":[],"category":"travel"},":tomato:":{"uc_base":"1f345","uc_output":"1f345","uc_match":"1f345","uc_greedy":"1f345","shortnames":[],"category":"food"},":tone1:":{"uc_base":"1f3fb","uc_output":"1f3fb","uc_match":"1f3fb","uc_greedy":"1f3fb","shortnames":[],"category":"modifier"},":tone2:":{"uc_base":"1f3fc","uc_output":"1f3fc","uc_match":"1f3fc","uc_greedy":"1f3fc","shortnames":[],"category":"modifier"},":tone3:":{"uc_base":"1f3fd","uc_output":"1f3fd","uc_match":"1f3fd","uc_greedy":"1f3fd","shortnames":[],"category":"modifier"},":tone4:":{"uc_base":"1f3fe","uc_output":"1f3fe","uc_match":"1f3fe","uc_greedy":"1f3fe","shortnames":[],"category":"modifier"},":tone5:":{"uc_base":"1f3ff","uc_output":"1f3ff","uc_match":"1f3ff","uc_greedy":"1f3ff","shortnames":[],"category":"modifier"},":tongue:":{"uc_base":"1f445","uc_output":"1f445","uc_match":"1f445","uc_greedy":"1f445","shortnames":[],"category":"people"},":top:":{"uc_base":"1f51d","uc_output":"1f51d","uc_match":"1f51d","uc_greedy":"1f51d","shortnames":[],"category":"symbols"},":tophat:":{"uc_base":"1f3a9","uc_output":"1f3a9","uc_match":"1f3a9","uc_greedy":"1f3a9","shortnames":[],"category":"people"},":tractor:":{"uc_base":"1f69c","uc_output":"1f69c","uc_match":"1f69c","uc_greedy":"1f69c","shortnames":[],"category":"travel"},":traffic_light:":{"uc_base":"1f6a5","uc_output":"1f6a5","uc_match":"1f6a5","uc_greedy":"1f6a5","shortnames":[],"category":"travel"},":train2:":{"uc_base":"1f686","uc_output":"1f686","uc_match":"1f686","uc_greedy":"1f686","shortnames":[],"category":"travel"},":train:":{"uc_base":"1f68b","uc_output":"1f68b","uc_match":"1f68b","uc_greedy":"1f68b","shortnames":[],"category":"travel"},":tram:":{"uc_base":"1f68a","uc_output":"1f68a","uc_match":"1f68a","uc_greedy":"1f68a","shortnames":[],"category":"travel"},":triangular_flag_on_post:":{"uc_base":"1f6a9","uc_output":"1f6a9","uc_match":"1f6a9","uc_greedy":"1f6a9","shortnames":[],"category":"flags"},":triangular_ruler:":{"uc_base":"1f4d0","uc_output":"1f4d0","uc_match":"1f4d0","uc_greedy":"1f4d0","shortnames":[],"category":"objects"},":trident:":{"uc_base":"1f531","uc_output":"1f531","uc_match":"1f531","uc_greedy":"1f531","shortnames":[],"category":"symbols"},":triumph:":{"uc_base":"1f624","uc_output":"1f624","uc_match":"1f624","uc_greedy":"1f624","shortnames":[],"category":"people"},":trolleybus:":{"uc_base":"1f68e","uc_output":"1f68e","uc_match":"1f68e","uc_greedy":"1f68e","shortnames":[],"category":"travel"},":trophy:":{"uc_base":"1f3c6","uc_output":"1f3c6","uc_match":"1f3c6","uc_greedy":"1f3c6","shortnames":[],"category":"activity"},":tropical_drink:":{"uc_base":"1f379","uc_output":"1f379","uc_match":"1f379","uc_greedy":"1f379","shortnames":[],"category":"food"},":tropical_fish:":{"uc_base":"1f420","uc_output":"1f420","uc_match":"1f420","uc_greedy":"1f420","shortnames":[],"category":"nature"},":truck:":{"uc_base":"1f69a","uc_output":"1f69a","uc_match":"1f69a","uc_greedy":"1f69a","shortnames":[],"category":"travel"},":trumpet:":{"uc_base":"1f3ba","uc_output":"1f3ba","uc_match":"1f3ba","uc_greedy":"1f3ba","shortnames":[],"category":"activity"},":tulip:":{"uc_base":"1f337","uc_output":"1f337","uc_match":"1f337","uc_greedy":"1f337","shortnames":[],"category":"nature"},":tumbler_glass:":{"uc_base":"1f943","uc_output":"1f943","uc_match":"1f943","uc_greedy":"1f943","shortnames":[":whisky:"],"category":"food"},":turkey:":{"uc_base":"1f983","uc_output":"1f983","uc_match":"1f983","uc_greedy":"1f983","shortnames":[],"category":"nature"},":turtle:":{"uc_base":"1f422","uc_output":"1f422","uc_match":"1f422","uc_greedy":"1f422","shortnames":[],"category":"nature"},":tv:":{"uc_base":"1f4fa","uc_output":"1f4fa","uc_match":"1f4fa","uc_greedy":"1f4fa","shortnames":[],"category":"objects"},":twisted_rightwards_arrows:":{"uc_base":"1f500","uc_output":"1f500","uc_match":"1f500","uc_greedy":"1f500","shortnames":[],"category":"symbols"},":two_hearts:":{"uc_base":"1f495","uc_output":"1f495","uc_match":"1f495","uc_greedy":"1f495","shortnames":[],"category":"symbols"},":two_men_holding_hands:":{"uc_base":"1f46c","uc_output":"1f46c","uc_match":"1f46c","uc_greedy":"1f46c","shortnames":[],"category":"people"},":two_women_holding_hands:":{"uc_base":"1f46d","uc_output":"1f46d","uc_match":"1f46d","uc_greedy":"1f46d","shortnames":[],"category":"people"},":u5272:":{"uc_base":"1f239","uc_output":"1f239","uc_match":"1f239","uc_greedy":"1f239","shortnames":[],"category":"symbols"},":u5408:":{"uc_base":"1f234","uc_output":"1f234","uc_match":"1f234","uc_greedy":"1f234","shortnames":[],"category":"symbols"},":u55b6:":{"uc_base":"1f23a","uc_output":"1f23a","uc_match":"1f23a","uc_greedy":"1f23a","shortnames":[],"category":"symbols"},":u6307:":{"uc_base":"1f22f","uc_output":"1f22f","uc_match":"1f22f","uc_greedy":"1f22f","shortnames":[],"category":"symbols"},":u6709:":{"uc_base":"1f236","uc_output":"1f236","uc_match":"1f236","uc_greedy":"1f236","shortnames":[],"category":"symbols"},":u6e80:":{"uc_base":"1f235","uc_output":"1f235","uc_match":"1f235","uc_greedy":"1f235","shortnames":[],"category":"symbols"},":u7121:":{"uc_base":"1f21a","uc_output":"1f21a","uc_match":"1f21a","uc_greedy":"1f21a","shortnames":[],"category":"symbols"},":u7533:":{"uc_base":"1f238","uc_output":"1f238","uc_match":"1f238","uc_greedy":"1f238","shortnames":[],"category":"symbols"},":u7981:":{"uc_base":"1f232","uc_output":"1f232","uc_match":"1f232","uc_greedy":"1f232","shortnames":[],"category":"symbols"},":u7a7a:":{"uc_base":"1f233","uc_output":"1f233","uc_match":"1f233","uc_greedy":"1f233","shortnames":[],"category":"symbols"},":unamused:":{"uc_base":"1f612","uc_output":"1f612","uc_match":"1f612","uc_greedy":"1f612","shortnames":[],"category":"people"},":underage:":{"uc_base":"1f51e","uc_output":"1f51e","uc_match":"1f51e","uc_greedy":"1f51e","shortnames":[],"category":"symbols"},":unicorn:":{"uc_base":"1f984","uc_output":"1f984","uc_match":"1f984","uc_greedy":"1f984","shortnames":[":unicorn_face:"],"category":"nature"},":unlock:":{"uc_base":"1f513","uc_output":"1f513","uc_match":"1f513","uc_greedy":"1f513","shortnames":[],"category":"objects"},":up:":{"uc_base":"1f199","uc_output":"1f199","uc_match":"1f199","uc_greedy":"1f199","shortnames":[],"category":"symbols"},":upside_down:":{"uc_base":"1f643","uc_output":"1f643","uc_match":"1f643","uc_greedy":"1f643","shortnames":[":upside_down_face:"],"category":"people"},":vampire:":{"uc_base":"1f9db","uc_output":"1f9db","uc_match":"1f9db","uc_greedy":"1f9db","shortnames":[],"category":"people"},":vertical_traffic_light:":{"uc_base":"1f6a6","uc_output":"1f6a6","uc_match":"1f6a6","uc_greedy":"1f6a6","shortnames":[],"category":"travel"},":vhs:":{"uc_base":"1f4fc","uc_output":"1f4fc","uc_match":"1f4fc","uc_greedy":"1f4fc","shortnames":[],"category":"objects"},":vibration_mode:":{"uc_base":"1f4f3","uc_output":"1f4f3","uc_match":"1f4f3","uc_greedy":"1f4f3","shortnames":[],"category":"symbols"},":video_camera:":{"uc_base":"1f4f9","uc_output":"1f4f9","uc_match":"1f4f9","uc_greedy":"1f4f9","shortnames":[],"category":"objects"},":video_game:":{"uc_base":"1f3ae","uc_output":"1f3ae","uc_match":"1f3ae","uc_greedy":"1f3ae","shortnames":[],"category":"activity"},":violin:":{"uc_base":"1f3bb","uc_output":"1f3bb","uc_match":"1f3bb","uc_greedy":"1f3bb","shortnames":[],"category":"activity"},":volcano:":{"uc_base":"1f30b","uc_output":"1f30b","uc_match":"1f30b","uc_greedy":"1f30b","shortnames":[],"category":"travel"},":volleyball:":{"uc_base":"1f3d0","uc_output":"1f3d0","uc_match":"1f3d0","uc_greedy":"1f3d0","shortnames":[],"category":"activity"},":vs:":{"uc_base":"1f19a","uc_output":"1f19a","uc_match":"1f19a","uc_greedy":"1f19a","shortnames":[],"category":"symbols"},":vulcan:":{"uc_base":"1f596","uc_output":"1f596","uc_match":"1f596","uc_greedy":"1f596","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers:"],"category":"people"},":waning_crescent_moon:":{"uc_base":"1f318","uc_output":"1f318","uc_match":"1f318","uc_greedy":"1f318","shortnames":[],"category":"nature"},":waning_gibbous_moon:":{"uc_base":"1f316","uc_output":"1f316","uc_match":"1f316","uc_greedy":"1f316","shortnames":[],"category":"nature"},":water_buffalo:":{"uc_base":"1f403","uc_output":"1f403","uc_match":"1f403","uc_greedy":"1f403","shortnames":[],"category":"nature"},":watermelon:":{"uc_base":"1f349","uc_output":"1f349","uc_match":"1f349","uc_greedy":"1f349","shortnames":[],"category":"food"},":wave:":{"uc_base":"1f44b","uc_output":"1f44b","uc_match":"1f44b","uc_greedy":"1f44b","shortnames":[],"category":"people"},":waxing_crescent_moon:":{"uc_base":"1f312","uc_output":"1f312","uc_match":"1f312","uc_greedy":"1f312","shortnames":[],"category":"nature"},":waxing_gibbous_moon:":{"uc_base":"1f314","uc_output":"1f314","uc_match":"1f314","uc_greedy":"1f314","shortnames":[],"category":"nature"},":wc:":{"uc_base":"1f6be","uc_output":"1f6be","uc_match":"1f6be","uc_greedy":"1f6be","shortnames":[],"category":"symbols"},":weary:":{"uc_base":"1f629","uc_output":"1f629","uc_match":"1f629","uc_greedy":"1f629","shortnames":[],"category":"people"},":wedding:":{"uc_base":"1f492","uc_output":"1f492","uc_match":"1f492","uc_greedy":"1f492","shortnames":[],"category":"travel"},":whale2:":{"uc_base":"1f40b","uc_output":"1f40b","uc_match":"1f40b","uc_greedy":"1f40b","shortnames":[],"category":"nature"},":whale:":{"uc_base":"1f433","uc_output":"1f433","uc_match":"1f433","uc_greedy":"1f433","shortnames":[],"category":"nature"},":white_flower:":{"uc_base":"1f4ae","uc_output":"1f4ae","uc_match":"1f4ae","uc_greedy":"1f4ae","shortnames":[],"category":"symbols"},":white_square_button:":{"uc_base":"1f533","uc_output":"1f533","uc_match":"1f533","uc_greedy":"1f533","shortnames":[],"category":"symbols"},":wilted_rose:":{"uc_base":"1f940","uc_output":"1f940","uc_match":"1f940","uc_greedy":"1f940","shortnames":[":wilted_flower:"],"category":"nature"},":wind_chime:":{"uc_base":"1f390","uc_output":"1f390","uc_match":"1f390","uc_greedy":"1f390","shortnames":[],"category":"objects"},":wine_glass:":{"uc_base":"1f377","uc_output":"1f377","uc_match":"1f377","uc_greedy":"1f377","shortnames":[],"category":"food"},":wink:":{"uc_base":"1f609","uc_output":"1f609","uc_match":"1f609","uc_greedy":"1f609","shortnames":[],"category":"people"},":wolf:":{"uc_base":"1f43a","uc_output":"1f43a","uc_match":"1f43a","uc_greedy":"1f43a","shortnames":[],"category":"nature"},":woman:":{"uc_base":"1f469","uc_output":"1f469","uc_match":"1f469","uc_greedy":"1f469","shortnames":[],"category":"people"},":woman_with_headscarf:":{"uc_base":"1f9d5","uc_output":"1f9d5","uc_match":"1f9d5","uc_greedy":"1f9d5","shortnames":[],"category":"people"},":womans_clothes:":{"uc_base":"1f45a","uc_output":"1f45a","uc_match":"1f45a","uc_greedy":"1f45a","shortnames":[],"category":"people"},":womans_hat:":{"uc_base":"1f452","uc_output":"1f452","uc_match":"1f452","uc_greedy":"1f452","shortnames":[],"category":"people"},":womens:":{"uc_base":"1f6ba","uc_output":"1f6ba","uc_match":"1f6ba","uc_greedy":"1f6ba","shortnames":[],"category":"symbols"},":worried:":{"uc_base":"1f61f","uc_output":"1f61f","uc_match":"1f61f","uc_greedy":"1f61f","shortnames":[],"category":"people"},":wrench:":{"uc_base":"1f527","uc_output":"1f527","uc_match":"1f527","uc_greedy":"1f527","shortnames":[],"category":"objects"},":yellow_heart:":{"uc_base":"1f49b","uc_output":"1f49b","uc_match":"1f49b","uc_greedy":"1f49b","shortnames":[],"category":"symbols"},":yen:":{"uc_base":"1f4b4","uc_output":"1f4b4","uc_match":"1f4b4","uc_greedy":"1f4b4","shortnames":[],"category":"objects"},":yum:":{"uc_base":"1f60b","uc_output":"1f60b","uc_match":"1f60b","uc_greedy":"1f60b","shortnames":[],"category":"people"},":zebra:":{"uc_base":"1f993","uc_output":"1f993","uc_match":"1f993","uc_greedy":"1f993","shortnames":[],"category":"nature"},":zipper_mouth:":{"uc_base":"1f910","uc_output":"1f910","uc_match":"1f910","uc_greedy":"1f910","shortnames":[":zipper_mouth_face:"],"category":"people"},":zombie:":{"uc_base":"1f9df","uc_output":"1f9df","uc_match":"1f9df","uc_greedy":"1f9df","shortnames":[],"category":"people"},":zzz:":{"uc_base":"1f4a4","uc_output":"1f4a4","uc_match":"1f4a4","uc_greedy":"1f4a4","shortnames":[],"category":"symbols"},":alarm_clock:":{"uc_base":"23f0","uc_output":"23f0","uc_match":"23f0","uc_greedy":"23f0","shortnames":[],"category":"objects"},":anchor:":{"uc_base":"2693","uc_output":"2693","uc_match":"2693","uc_greedy":"2693","shortnames":[],"category":"travel"},":aquarius:":{"uc_base":"2652","uc_output":"2652","uc_match":"2652","uc_greedy":"2652","shortnames":[],"category":"symbols"},":aries:":{"uc_base":"2648","uc_output":"2648","uc_match":"2648","uc_greedy":"2648","shortnames":[],"category":"symbols"},":arrow_double_down:":{"uc_base":"23ec","uc_output":"23ec","uc_match":"23ec","uc_greedy":"23ec","shortnames":[],"category":"symbols"},":arrow_double_up:":{"uc_base":"23eb","uc_output":"23eb","uc_match":"23eb","uc_greedy":"23eb","shortnames":[],"category":"symbols"},":baseball:":{"uc_base":"26be","uc_output":"26be","uc_match":"26be","uc_greedy":"26be","shortnames":[],"category":"activity"},":black_circle:":{"uc_base":"26ab","uc_output":"26ab","uc_match":"26ab","uc_greedy":"26ab","shortnames":[],"category":"symbols"},":black_large_square:":{"uc_base":"2b1b","uc_output":"2b1b","uc_match":"2b1b","uc_greedy":"2b1b","shortnames":[],"category":"symbols"},":black_medium_small_square:":{"uc_base":"25fe","uc_output":"25fe","uc_match":"25fe","uc_greedy":"25fe","shortnames":[],"category":"symbols"},":cancer:":{"uc_base":"264b","uc_output":"264b","uc_match":"264b","uc_greedy":"264b","shortnames":[],"category":"symbols"},":capricorn:":{"uc_base":"2651","uc_output":"2651","uc_match":"2651","uc_greedy":"2651","shortnames":[],"category":"symbols"},":church:":{"uc_base":"26ea","uc_output":"26ea","uc_match":"26ea","uc_greedy":"26ea","shortnames":[],"category":"travel"},":coffee:":{"uc_base":"2615","uc_output":"2615","uc_match":"2615","uc_greedy":"2615","shortnames":[],"category":"food"},":curly_loop:":{"uc_base":"27b0","uc_output":"27b0","uc_match":"27b0","uc_greedy":"27b0","shortnames":[],"category":"symbols"},":exclamation:":{"uc_base":"2757","uc_output":"2757","uc_match":"2757","uc_greedy":"2757","shortnames":[],"category":"symbols"},":fast_forward:":{"uc_base":"23e9","uc_output":"23e9","uc_match":"23e9","uc_greedy":"23e9","shortnames":[],"category":"symbols"},":fist:":{"uc_base":"270a","uc_output":"270a","uc_match":"270a","uc_greedy":"270a","shortnames":[],"category":"people"},":fountain:":{"uc_base":"26f2","uc_output":"26f2","uc_match":"26f2","uc_greedy":"26f2","shortnames":[],"category":"travel"},":fuelpump:":{"uc_base":"26fd","uc_output":"26fd","uc_match":"26fd","uc_greedy":"26fd","shortnames":[],"category":"travel"},":gemini:":{"uc_base":"264a","uc_output":"264a","uc_match":"264a","uc_greedy":"264a","shortnames":[],"category":"symbols"},":golf:":{"uc_base":"26f3","uc_output":"26f3","uc_match":"26f3","uc_greedy":"26f3","shortnames":[],"category":"activity"},":grey_exclamation:":{"uc_base":"2755","uc_output":"2755","uc_match":"2755","uc_greedy":"2755","shortnames":[],"category":"symbols"},":grey_question:":{"uc_base":"2754","uc_output":"2754","uc_match":"2754","uc_greedy":"2754","shortnames":[],"category":"symbols"},":heavy_division_sign:":{"uc_base":"2797","uc_output":"2797","uc_match":"2797","uc_greedy":"2797","shortnames":[],"category":"symbols"},":heavy_minus_sign:":{"uc_base":"2796","uc_output":"2796","uc_match":"2796","uc_greedy":"2796","shortnames":[],"category":"symbols"},":heavy_plus_sign:":{"uc_base":"2795","uc_output":"2795","uc_match":"2795","uc_greedy":"2795","shortnames":[],"category":"symbols"},":hourglass:":{"uc_base":"231b","uc_output":"231b","uc_match":"231b","uc_greedy":"231b","shortnames":[],"category":"objects"},":hourglass_flowing_sand:":{"uc_base":"23f3","uc_output":"23f3","uc_match":"23f3","uc_greedy":"23f3","shortnames":[],"category":"objects"},":leo:":{"uc_base":"264c","uc_output":"264c","uc_match":"264c","uc_greedy":"264c","shortnames":[],"category":"symbols"},":libra:":{"uc_base":"264e","uc_output":"264e","uc_match":"264e","uc_greedy":"264e","shortnames":[],"category":"symbols"},":loop:":{"uc_base":"27bf","uc_output":"27bf","uc_match":"27bf","uc_greedy":"27bf","shortnames":[],"category":"symbols"},":negative_squared_cross_mark:":{"uc_base":"274e","uc_output":"274e","uc_match":"274e","uc_greedy":"274e","shortnames":[],"category":"symbols"},":no_entry:":{"uc_base":"26d4","uc_output":"26d4","uc_match":"26d4","uc_greedy":"26d4","shortnames":[],"category":"symbols"},":o:":{"uc_base":"2b55","uc_output":"2b55","uc_match":"2b55","uc_greedy":"2b55","shortnames":[],"category":"symbols"},":ophiuchus:":{"uc_base":"26ce","uc_output":"26ce","uc_match":"26ce","uc_greedy":"26ce","shortnames":[],"category":"symbols"},":partly_sunny:":{"uc_base":"26c5","uc_output":"26c5","uc_match":"26c5","uc_greedy":"26c5","shortnames":[],"category":"nature"},":pisces:":{"uc_base":"2653","uc_output":"2653","uc_match":"2653","uc_greedy":"2653","shortnames":[],"category":"symbols"},":question:":{"uc_base":"2753","uc_output":"2753","uc_match":"2753","uc_greedy":"2753","shortnames":[],"category":"symbols"},":raised_hand:":{"uc_base":"270b","uc_output":"270b","uc_match":"270b","uc_greedy":"270b","shortnames":[],"category":"people"},":rewind:":{"uc_base":"23ea","uc_output":"23ea","uc_match":"23ea","uc_greedy":"23ea","shortnames":[],"category":"symbols"},":sagittarius:":{"uc_base":"2650","uc_output":"2650","uc_match":"2650","uc_greedy":"2650","shortnames":[],"category":"symbols"},":sailboat:":{"uc_base":"26f5","uc_output":"26f5","uc_match":"26f5","uc_greedy":"26f5","shortnames":[],"category":"travel"},":scorpius:":{"uc_base":"264f","uc_output":"264f","uc_match":"264f","uc_greedy":"264f","shortnames":[],"category":"symbols"},":snowman:":{"uc_base":"26c4","uc_output":"26c4","uc_match":"26c4","uc_greedy":"26c4","shortnames":[],"category":"nature"},":soccer:":{"uc_base":"26bd","uc_output":"26bd","uc_match":"26bd","uc_greedy":"26bd","shortnames":[],"category":"activity"},":sparkles:":{"uc_base":"2728","uc_output":"2728","uc_match":"2728","uc_greedy":"2728","shortnames":[],"category":"nature"},":star:":{"uc_base":"2b50","uc_output":"2b50","uc_match":"2b50","uc_greedy":"2b50","shortnames":[],"category":"nature"},":taurus:":{"uc_base":"2649","uc_output":"2649","uc_match":"2649","uc_greedy":"2649","shortnames":[],"category":"symbols"},":tent:":{"uc_base":"26fa","uc_output":"26fa","uc_match":"26fa","uc_greedy":"26fa","shortnames":[],"category":"travel"},":umbrella:":{"uc_base":"2614","uc_output":"2614","uc_match":"2614","uc_greedy":"2614","shortnames":[],"category":"nature"},":virgo:":{"uc_base":"264d","uc_output":"264d","uc_match":"264d","uc_greedy":"264d","shortnames":[],"category":"symbols"},":watch:":{"uc_base":"231a","uc_output":"231a","uc_match":"231a","uc_greedy":"231a","shortnames":[],"category":"objects"},":wheelchair:":{"uc_base":"267f","uc_output":"267f","uc_match":"267f","uc_greedy":"267f","shortnames":[],"category":"symbols"},":white_check_mark:":{"uc_base":"2705","uc_output":"2705","uc_match":"2705","uc_greedy":"2705","shortnames":[],"category":"symbols"},":white_circle:":{"uc_base":"26aa","uc_output":"26aa","uc_match":"26aa","uc_greedy":"26aa","shortnames":[],"category":"symbols"},":white_large_square:":{"uc_base":"2b1c","uc_output":"2b1c","uc_match":"2b1c","uc_greedy":"2b1c","shortnames":[],"category":"symbols"},":white_medium_small_square:":{"uc_base":"25fd","uc_output":"25fd","uc_match":"25fd","uc_greedy":"25fd","shortnames":[],"category":"symbols"},":x:":{"uc_base":"274c","uc_output":"274c","uc_match":"274c","uc_greedy":"274c","shortnames":[],"category":"symbols"},":zap:":{"uc_base":"26a1","uc_output":"26a1","uc_match":"26a1","uc_greedy":"26a1","shortnames":[],"category":"nature"}};
  9560. var tmpShortNames = [], emoji;
  9561. for (emoji in ns.emojioneList) {
  9562. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  9563. tmpShortNames.push(emoji.replace(/[+]/g, "\\$&"));
  9564. for (var i = 0; i < ns.emojioneList[emoji].shortnames.length; i++) {
  9565. tmpShortNames.push(ns.emojioneList[emoji].shortnames[i].replace(/[+]/g, "\\$&"));
  9566. }
  9567. }
  9568. ns.shortnames = tmpShortNames.join('|');
  9569. // javascript escapes here must be ordered from largest length to shortest
  9570. ns.jsEscapeMap = {"\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74\uDB40\uDC7F":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f468-1f468-1f466-1f466","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f468-1f468-1f467-1f466","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f468-1f468-1f467-1f467","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f468-1f469-1f466-1f466","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f468-1f469-1f467-1f466","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f468-1f469-1f467-1f467","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f469-1f469-1f466-1f466","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f469-1f469-1f467-1f466","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f469-1f469-1f467-1f467","\uD83D\uDC68\u200D\u2764\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC8B\u200D\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\u200D\u2764\uFE0F\u200D\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"1f575-1f3fb-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"1f575-1f3fb-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"1f575-1f3fc-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"1f575-1f3fc-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"1f575-1f3fd-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"1f575-1f3fd-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"1f575-1f3fe-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"1f575-1f3fe-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"1f575-1f3ff-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"1f575-1f3ff-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cb-1f3ff-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cc-1f3ff-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cc-1f3ff-2642","\u26F9\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"26f9-1f3fb-2640","\u26F9\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"26f9-1f3fb-2642","\u26F9\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"26f9-1f3fc-2640","\u26F9\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"26f9-1f3fc-2642","\u26F9\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"26f9-1f3fd-2640","\u26F9\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"26f9-1f3fd-2642","\u26F9\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"26f9-1f3fe-2640","\u26F9\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"26f9-1f3fe-2642","\u26F9\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"26f9-1f3ff-2640","\u26F9\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"26f9-1f3ff-2642","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC66":"1f468-1f468-1f466","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC67":"1f468-1f468-1f467","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67":"1f468-1f469-1f467","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66":"1f469-1f469-1f466","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67":"1f469-1f469-1f467","\uD83D\uDC68\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f468-1f466-1f466","\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f468-1f467-1f466","\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f469-1f466-1f466","\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f469-1f467-1f466","\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f469-1f467-1f467","\uD83D\uDC68\u2764\uFE0F\uD83D\uDC8B\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f468-1f467-1f467","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66":"1f468-1f469-1f466","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC8B\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC8B\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u200D\u2764\u200D\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\uD83C\uDFFB\u200D\u2695\uFE0F":"1f468-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFB\u200D\u2696\uFE0F":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFB\u200D\u2708\uFE0F":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u200D\u2695\uFE0F":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFC\u200D\u2696\uFE0F":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFC\u200D\u2708\uFE0F":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u200D\u2695\uFE0F":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFD\u200D\u2696\uFE0F":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFD\u200D\u2708\uFE0F":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u200D\u2695\uFE0F":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFE\u200D\u2696\uFE0F":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFE\u200D\u2708\uFE0F":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u200D\u2695\uFE0F":"1f468-1f3ff-2695","\uD83D\uDC68\uD83C\uDFFF\u200D\u2696\uFE0F":"1f468-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFF\u200D\u2708\uFE0F":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u200D\u2695\uFE0F":"1f469-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFB\u200D\u2696\uFE0F":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFB\u200D\u2708\uFE0F":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u200D\u2695\uFE0F":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFC\u200D\u2696\uFE0F":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFC\u200D\u2708\uFE0F":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u200D\u2695\uFE0F":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFD\u200D\u2696\uFE0F":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFD\u200D\u2708\uFE0F":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u200D\u2695\uFE0F":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFE\u200D\u2696\uFE0F":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFE\u200D\u2708\uFE0F":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u200D\u2695\uFE0F":"1f469-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFF\u200D\u2696\uFE0F":"1f469-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFF\u200D\u2708\uFE0F":"1f469-1f3ff-2708","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2640\uFE0F":"1f46e-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2642\uFE0F":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2640\uFE0F":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2642\uFE0F":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2640\uFE0F":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2642\uFE0F":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2640\uFE0F":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2642\uFE0F":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2640\uFE0F":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2642\uFE0F":"1f46e-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFB\u200D\u2640\uFE0F":"1f471-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFB\u200D\u2642\uFE0F":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFC\u200D\u2640\uFE0F":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFC\u200D\u2642\uFE0F":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFD\u200D\u2640\uFE0F":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFD\u200D\u2642\uFE0F":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFE\u200D\u2640\uFE0F":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFE\u200D\u2642\uFE0F":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFF\u200D\u2640\uFE0F":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFF\u200D\u2642\uFE0F":"1f471-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFB\u200D\u2640\uFE0F":"1f473-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFB\u200D\u2642\uFE0F":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFC\u200D\u2640\uFE0F":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFC\u200D\u2642\uFE0F":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFD\u200D\u2640\uFE0F":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFD\u200D\u2642\uFE0F":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFE\u200D\u2640\uFE0F":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFE\u200D\u2642\uFE0F":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFF\u200D\u2640\uFE0F":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFF\u200D\u2642\uFE0F":"1f473-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFB\u200D\u2640\uFE0F":"1f477-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFB\u200D\u2642\uFE0F":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFC\u200D\u2640\uFE0F":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFC\u200D\u2642\uFE0F":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFD\u200D\u2640\uFE0F":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFD\u200D\u2642\uFE0F":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFE\u200D\u2640\uFE0F":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFE\u200D\u2642\uFE0F":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFF\u200D\u2640\uFE0F":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFF\u200D\u2642\uFE0F":"1f477-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFB\u200D\u2640\uFE0F":"1f482-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFB\u200D\u2642\uFE0F":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFC\u200D\u2640\uFE0F":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFC\u200D\u2642\uFE0F":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFD\u200D\u2640\uFE0F":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFD\u200D\u2642\uFE0F":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFE\u200D\u2640\uFE0F":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFE\u200D\u2642\uFE0F":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFF\u200D\u2640\uFE0F":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFF\u200D\u2642\uFE0F":"1f482-1f3ff-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u2640\uFE0F":"1f575-1f3fb-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u2642\uFE0F":"1f575-1f3fb-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u2640\uFE0F":"1f575-1f3fc-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u2642\uFE0F":"1f575-1f3fc-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u2640\uFE0F":"1f575-1f3fd-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u2642\uFE0F":"1f575-1f3fd-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u2640\uFE0F":"1f575-1f3fe-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u2642\uFE0F":"1f575-1f3fe-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u2640\uFE0F":"1f575-1f3ff-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u2642\uFE0F":"1f575-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3c3-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3c3-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3c4-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3c4-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3ca-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3ca-1f3ff-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u2640\uFE0F":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u2642\uFE0F":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u2640\uFE0F":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u2642\uFE0F":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u2640\uFE0F":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u2642\uFE0F":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u2640\uFE0F":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u2642\uFE0F":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u2640\uFE0F":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u2642\uFE0F":"1f3cb-1f3ff-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u2640\uFE0F":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u2642\uFE0F":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u2640\uFE0F":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u2642\uFE0F":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u2640\uFE0F":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u2642\uFE0F":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u2640\uFE0F":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u2642\uFE0F":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u2640\uFE0F":"1f3cc-1f3ff-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u2642\uFE0F":"1f3cc-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFB\u200D\u2640\uFE0F":"1f486-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFB\u200D\u2642\uFE0F":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFC\u200D\u2640\uFE0F":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFC\u200D\u2642\uFE0F":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFD\u200D\u2640\uFE0F":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFD\u200D\u2642\uFE0F":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFE\u200D\u2640\uFE0F":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFE\u200D\u2642\uFE0F":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFF\u200D\u2640\uFE0F":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFF\u200D\u2642\uFE0F":"1f486-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFB\u200D\u2640\uFE0F":"1f487-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFB\u200D\u2642\uFE0F":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFC\u200D\u2640\uFE0F":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFC\u200D\u2642\uFE0F":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFD\u200D\u2640\uFE0F":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFD\u200D\u2642\uFE0F":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFE\u200D\u2640\uFE0F":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFE\u200D\u2642\uFE0F":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFF\u200D\u2640\uFE0F":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFF\u200D\u2642\uFE0F":"1f487-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6a3-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6a3-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6b4-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6b4-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6b5-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6b5-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6b6-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6b6-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFB\u200D\u2640\uFE0F":"1f938-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFB\u200D\u2642\uFE0F":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFC\u200D\u2640\uFE0F":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFC\u200D\u2642\uFE0F":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFD\u200D\u2640\uFE0F":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFD\u200D\u2642\uFE0F":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFE\u200D\u2640\uFE0F":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFE\u200D\u2642\uFE0F":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFF\u200D\u2640\uFE0F":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFF\u200D\u2642\uFE0F":"1f938-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFB\u200D\u2640\uFE0F":"1f939-1f3fb-2640","\uD83E\uDD39\uD83C\uDFFB\u200D\u2642\uFE0F":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFC\u200D\u2640\uFE0F":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFC\u200D\u2642\uFE0F":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFD\u200D\u2640\uFE0F":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFD\u200D\u2642\uFE0F":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFE\u200D\u2640\uFE0F":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFE\u200D\u2642\uFE0F":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFF\u200D\u2640\uFE0F":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u200D\u2642\uFE0F":"1f939-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2640\uFE0F":"1f93d-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2642\uFE0F":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2640\uFE0F":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2642\uFE0F":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2640\uFE0F":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2642\uFE0F":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2640\uFE0F":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2642\uFE0F":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2640\uFE0F":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2642\uFE0F":"1f93d-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2640\uFE0F":"1f93e-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2642\uFE0F":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2640\uFE0F":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2642\uFE0F":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2640\uFE0F":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2642\uFE0F":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2640\uFE0F":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2642\uFE0F":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2640\uFE0F":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2642\uFE0F":"1f93e-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFB\u200D\u2640\uFE0F":"1f481-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFB\u200D\u2642\uFE0F":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFC\u200D\u2640\uFE0F":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFC\u200D\u2642\uFE0F":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFD\u200D\u2640\uFE0F":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFD\u200D\u2642\uFE0F":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFE\u200D\u2640\uFE0F":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFE\u200D\u2642\uFE0F":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFF\u200D\u2640\uFE0F":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFF\u200D\u2642\uFE0F":"1f481-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFB\u200D\u2640\uFE0F":"1f645-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFB\u200D\u2642\uFE0F":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFC\u200D\u2640\uFE0F":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFC\u200D\u2642\uFE0F":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFD\u200D\u2640\uFE0F":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFD\u200D\u2642\uFE0F":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFE\u200D\u2640\uFE0F":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFE\u200D\u2642\uFE0F":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFF\u200D\u2640\uFE0F":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFF\u200D\u2642\uFE0F":"1f645-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFB\u200D\u2640\uFE0F":"1f646-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFB\u200D\u2642\uFE0F":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFC\u200D\u2640\uFE0F":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFC\u200D\u2642\uFE0F":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFD\u200D\u2640\uFE0F":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFD\u200D\u2642\uFE0F":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFE\u200D\u2640\uFE0F":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFE\u200D\u2642\uFE0F":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFF\u200D\u2640\uFE0F":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFF\u200D\u2642\uFE0F":"1f646-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFB\u200D\u2640\uFE0F":"1f647-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFB\u200D\u2642\uFE0F":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFC\u200D\u2640\uFE0F":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFC\u200D\u2642\uFE0F":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFD\u200D\u2640\uFE0F":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFD\u200D\u2642\uFE0F":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFE\u200D\u2640\uFE0F":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFE\u200D\u2642\uFE0F":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFF\u200D\u2640\uFE0F":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFF\u200D\u2642\uFE0F":"1f647-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2640\uFE0F":"1f64b-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2642\uFE0F":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2640\uFE0F":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2642\uFE0F":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2640\uFE0F":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2642\uFE0F":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2640\uFE0F":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2642\uFE0F":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2640\uFE0F":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2642\uFE0F":"1f64b-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2640\uFE0F":"1f64d-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2642\uFE0F":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2640\uFE0F":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2642\uFE0F":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2640\uFE0F":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2642\uFE0F":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2640\uFE0F":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2642\uFE0F":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2640\uFE0F":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2642\uFE0F":"1f64d-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2640\uFE0F":"1f64e-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2642\uFE0F":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2640\uFE0F":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2642\uFE0F":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2640\uFE0F":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2642\uFE0F":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2640\uFE0F":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2642\uFE0F":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2640\uFE0F":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2642\uFE0F":"1f64e-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFB\u200D\u2640\uFE0F":"1f926-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFB\u200D\u2642\uFE0F":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFC\u200D\u2640\uFE0F":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFC\u200D\u2642\uFE0F":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFD\u200D\u2640\uFE0F":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFD\u200D\u2642\uFE0F":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFE\u200D\u2640\uFE0F":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFE\u200D\u2642\uFE0F":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFF\u200D\u2640\uFE0F":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFF\u200D\u2642\uFE0F":"1f926-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFB\u200D\u2640\uFE0F":"1f937-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFB\u200D\u2642\uFE0F":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFC\u200D\u2640\uFE0F":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFC\u200D\u2642\uFE0F":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFD\u200D\u2640\uFE0F":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFD\u200D\u2642\uFE0F":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFE\u200D\u2640\uFE0F":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFE\u200D\u2642\uFE0F":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFF\u200D\u2640\uFE0F":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFF\u200D\u2642\uFE0F":"1f937-1f3ff-2642","\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8\uFE0F":"1f441-1f5e8","\uD83D\uDD75\uD83C\uDFFB\u200D\u2640\uFE0F":"1f575-1f3fb-2640","\uD83D\uDD75\uD83C\uDFFB\u200D\u2642\uFE0F":"1f575-1f3fb-2642","\uD83D\uDD75\uD83C\uDFFC\u200D\u2640\uFE0F":"1f575-1f3fc-2640","\uD83D\uDD75\uD83C\uDFFC\u200D\u2642\uFE0F":"1f575-1f3fc-2642","\uD83D\uDD75\uD83C\uDFFD\u200D\u2640\uFE0F":"1f575-1f3fd-2640","\uD83D\uDD75\uD83C\uDFFD\u200D\u2642\uFE0F":"1f575-1f3fd-2642","\uD83D\uDD75\uD83C\uDFFE\u200D\u2640\uFE0F":"1f575-1f3fe-2640","\uD83D\uDD75\uD83C\uDFFE\u200D\u2642\uFE0F":"1f575-1f3fe-2642","\uD83D\uDD75\uD83C\uDFFF\u200D\u2640\uFE0F":"1f575-1f3ff-2640","\uD83D\uDD75\uD83C\uDFFF\u200D\u2642\uFE0F":"1f575-1f3ff-2642","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cb-1f3ff-2642","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cc-1f3ff-2640","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cc-1f3ff-2642","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d9-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9da-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9db-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9dc-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9dd-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d6-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d7-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d8-1f3ff-2642","\uD83D\uDD75\uFE0F\u200D\u2640\uFE0F":"1f575-2640","\uD83D\uDD75\uFE0F\u200D\u2642\uFE0F":"1f575-2642","\u26F9\uFE0F\uD83C\uDFFB\u2640\uFE0F":"26f9-1f3fb-2640","\u26F9\uFE0F\uD83C\uDFFB\u2642\uFE0F":"26f9-1f3fb-2642","\u26F9\uFE0F\uD83C\uDFFC\u2640\uFE0F":"26f9-1f3fc-2640","\u26F9\uFE0F\uD83C\uDFFC\u2642\uFE0F":"26f9-1f3fc-2642","\u26F9\uFE0F\uD83C\uDFFD\u2640\uFE0F":"26f9-1f3fd-2640","\u26F9\uFE0F\uD83C\uDFFD\u2642\uFE0F":"26f9-1f3fd-2642","\u26F9\uFE0F\uD83C\uDFFE\u2640\uFE0F":"26f9-1f3fe-2640","\u26F9\uFE0F\uD83C\uDFFE\u2642\uFE0F":"26f9-1f3fe-2642","\u26F9\uFE0F\uD83C\uDFFF\u2640\uFE0F":"26f9-1f3ff-2640","\u26F9\uFE0F\uD83C\uDFFF\u2642\uFE0F":"26f9-1f3ff-2642","\uD83C\uDFCB\uFE0F\u200D\u2640\uFE0F":"1f3cb-2640","\uD83C\uDFCB\uFE0F\u200D\u2642\uFE0F":"1f3cb-2642","\uD83C\uDFCC\uFE0F\u200D\u2640\uFE0F":"1f3cc-2640","\uD83C\uDFCC\uFE0F\u200D\u2642\uFE0F":"1f3cc-2642","\u26F9\uD83C\uDFFB\u200D\u2640\uFE0F":"26f9-1f3fb-2640","\u26F9\uD83C\uDFFB\u200D\u2642\uFE0F":"26f9-1f3fb-2642","\u26F9\uD83C\uDFFC\u200D\u2640\uFE0F":"26f9-1f3fc-2640","\u26F9\uD83C\uDFFC\u200D\u2642\uFE0F":"26f9-1f3fc-2642","\u26F9\uD83C\uDFFD\u200D\u2640\uFE0F":"26f9-1f3fd-2640","\u26F9\uD83C\uDFFD\u200D\u2642\uFE0F":"26f9-1f3fd-2642","\u26F9\uD83C\uDFFE\u200D\u2640\uFE0F":"26f9-1f3fe-2640","\u26F9\uD83C\uDFFE\u200D\u2642\uFE0F":"26f9-1f3fe-2642","\u26F9\uD83C\uDFFF\u200D\u2640\uFE0F":"26f9-1f3ff-2640","\u26F9\uD83C\uDFFF\u200D\u2642\uFE0F":"26f9-1f3ff-2642","\u26F9\uFE0F\u200D\u2640\uFE0F":"26f9-2640","\u26F9\uFE0F\u200D\u2642\uFE0F":"26f9-2642","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC66\uD83D\uDC66":"1f468-1f468-1f466-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67\uD83D\uDC66":"1f468-1f468-1f467-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67\uD83D\uDC67":"1f468-1f468-1f467-1f467","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f468-1f469-1f466-1f466","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f468-1f469-1f467-1f466","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f468-1f469-1f467-1f467","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f469-1f469-1f466-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f469-1f469-1f467-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f469-1f469-1f467-1f467","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDCBB":"1f468-1f3ff-1f4bb","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDCBB":"1f468-1f3fe-1f4bb","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDCBB":"1f468-1f3fd-1f4bb","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDCBB":"1f468-1f3fc-1f4bb","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDCBB":"1f468-1f3fb-1f4bb","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDCBB":"1f469-1f3ff-1f4bb","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDCBB":"1f469-1f3fe-1f4bb","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDCBB":"1f469-1f3fd-1f4bb","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDCBB":"1f469-1f3fc-1f4bb","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDCBB":"1f469-1f3fb-1f4bb","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFEB":"1f468-1f3ff-1f3eb","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFEB":"1f468-1f3fe-1f3eb","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFEB":"1f468-1f3fd-1f3eb","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFEB":"1f468-1f3fc-1f3eb","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFEB":"1f468-1f3fb-1f3eb","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFEB":"1f469-1f3ff-1f3eb","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFEB":"1f469-1f3fe-1f3eb","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFEB":"1f469-1f3fd-1f3eb","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFEB":"1f469-1f3fc-1f3eb","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFEB":"1f469-1f3fb-1f3eb","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDF93":"1f468-1f3ff-1f393","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDF93":"1f468-1f3fe-1f393","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDF93":"1f468-1f3fd-1f393","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDF93":"1f468-1f3fc-1f393","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDF93":"1f468-1f3fb-1f393","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDF93":"1f469-1f3ff-1f393","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDF93":"1f469-1f3fe-1f393","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDF93":"1f469-1f3fd-1f393","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDF93":"1f469-1f3fc-1f393","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDF93":"1f469-1f3fb-1f393","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFA4":"1f468-1f3ff-1f3a4","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFA4":"1f468-1f3fe-1f3a4","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFA4":"1f468-1f3fd-1f3a4","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFA4":"1f468-1f3fc-1f3a4","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFA4":"1f468-1f3fb-1f3a4","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFA4":"1f469-1f3ff-1f3a4","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFA4":"1f469-1f3fe-1f3a4","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFA4":"1f469-1f3fd-1f3a4","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFA4":"1f469-1f3fc-1f3a4","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFA4":"1f469-1f3fb-1f3a4","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDD2C":"1f468-1f3ff-1f52c","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDD2C":"1f468-1f3fe-1f52c","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDD2C":"1f468-1f3fd-1f52c","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDD2C":"1f468-1f3fc-1f52c","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDD2C":"1f468-1f3fb-1f52c","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDD2C":"1f469-1f3ff-1f52c","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDD2C":"1f469-1f3fe-1f52c","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDD2C":"1f469-1f3fd-1f52c","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDD2C":"1f469-1f3fc-1f52c","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDD2C":"1f469-1f3fb-1f52c","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDCBC":"1f468-1f3ff-1f4bc","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDCBC":"1f468-1f3fe-1f4bc","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDCBC":"1f468-1f3fd-1f4bc","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDCBC":"1f468-1f3fc-1f4bc","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDCBC":"1f468-1f3fb-1f4bc","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDCBC":"1f469-1f3ff-1f4bc","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDCBC":"1f469-1f3fe-1f4bc","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDCBC":"1f469-1f3fd-1f4bc","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDCBC":"1f469-1f3fc-1f4bc","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDCBC":"1f469-1f3fb-1f4bc","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDD27":"1f468-1f3ff-1f527","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDD27":"1f468-1f3fe-1f527","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDD27":"1f468-1f3fd-1f527","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDD27":"1f468-1f3fc-1f527","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDD27":"1f468-1f3fb-1f527","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDD27":"1f469-1f3ff-1f527","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDD27":"1f469-1f3fe-1f527","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDD27":"1f469-1f3fd-1f527","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDD27":"1f469-1f3fc-1f527","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDD27":"1f469-1f3fb-1f527","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFED":"1f468-1f3ff-1f3ed","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFED":"1f468-1f3fe-1f3ed","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFED":"1f468-1f3fd-1f3ed","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFED":"1f468-1f3fc-1f3ed","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFED":"1f468-1f3fb-1f3ed","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFED":"1f469-1f3ff-1f3ed","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFED":"1f469-1f3fe-1f3ed","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFED":"1f469-1f3fd-1f3ed","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFED":"1f469-1f3fc-1f3ed","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFED":"1f469-1f3fb-1f3ed","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDF73":"1f468-1f3ff-1f373","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDF73":"1f468-1f3fe-1f373","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDF73":"1f468-1f3fd-1f373","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDF73":"1f468-1f3fc-1f373","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDF73":"1f468-1f3fb-1f373","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDF73":"1f469-1f3ff-1f373","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDF73":"1f469-1f3fe-1f373","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDF73":"1f469-1f3fd-1f373","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDF73":"1f469-1f3fc-1f373","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDF73":"1f469-1f3fb-1f373","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDF3E":"1f468-1f3ff-1f33e","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDF3E":"1f468-1f3fe-1f33e","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDF3E":"1f468-1f3fd-1f33e","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDF3E":"1f468-1f3fc-1f33e","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDF3E":"1f468-1f3fb-1f33e","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDF3E":"1f469-1f3ff-1f33e","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDF3E":"1f469-1f3fe-1f33e","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDF3E":"1f469-1f3fd-1f33e","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDF3E":"1f469-1f3fc-1f33e","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDF3E":"1f469-1f3fb-1f33e","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFA8":"1f468-1f3fb-1f3a8","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFA8":"1f468-1f3fc-1f3a8","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFA8":"1f468-1f3fd-1f3a8","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFA8":"1f468-1f3fe-1f3a8","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFA8":"1f468-1f3ff-1f3a8","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFA8":"1f469-1f3fb-1f3a8","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFA8":"1f469-1f3fc-1f3a8","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFA8":"1f469-1f3fd-1f3a8","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFA8":"1f469-1f3fe-1f3a8","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFA8":"1f469-1f3ff-1f3a8","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDE80":"1f468-1f3fb-1f680","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDE80":"1f468-1f3fc-1f680","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDE80":"1f468-1f3fd-1f680","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDE80":"1f468-1f3fe-1f680","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDE80":"1f468-1f3ff-1f680","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDE80":"1f469-1f3fb-1f680","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDE80":"1f469-1f3fc-1f680","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDE80":"1f469-1f3fd-1f680","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDE80":"1f469-1f3fe-1f680","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDE80":"1f469-1f3ff-1f680","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDE92":"1f468-1f3fb-1f692","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDE92":"1f468-1f3fc-1f692","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDE92":"1f468-1f3fd-1f692","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDE92":"1f468-1f3fe-1f692","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDE92":"1f468-1f3ff-1f692","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDE92":"1f469-1f3fb-1f692","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDE92":"1f469-1f3fc-1f692","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDE92":"1f469-1f3fd-1f692","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDE92":"1f469-1f3fe-1f692","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDE92":"1f469-1f3ff-1f692","\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08":"1f3f3-1f308","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2642":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2642":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2642":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2642":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2642":"1f3cc-1f3ff-2642","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2640":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2640":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2640":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2640":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2640":"1f3cc-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u200D\u2642":"1f939-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFE\u200D\u2642":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFD\u200D\u2642":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFC\u200D\u2642":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFB\u200D\u2642":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFF\u200D\u2640":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFE\u200D\u2640":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFD\u200D\u2640":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFC\u200D\u2640":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFB\u200D\u2640":"1f939-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2642":"1f93e-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2642":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2642":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2642":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2642":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2640":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2640":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2640":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2640":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2640":"1f93e-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2642":"1f93d-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2642":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2642":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2642":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2642":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2640":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2640":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2640":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2640":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2640":"1f93d-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFF\u200D\u2642":"1f938-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFE\u200D\u2642":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFD\u200D\u2642":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFC\u200D\u2642":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFB\u200D\u2642":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFF\u200D\u2640":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFE\u200D\u2640":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFD\u200D\u2640":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFC\u200D\u2640":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFB\u200D\u2640":"1f938-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2642":"1f6b6-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2642":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2642":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2642":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2642":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2640":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2640":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2640":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2640":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2640":"1f6b6-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2642":"1f6b5-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2642":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2642":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2642":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2642":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2640":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2640":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2640":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2640":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2640":"1f6b5-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2642":"1f6b4-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2642":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2642":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2642":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2642":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2640":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2640":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2640":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2640":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2640":"1f6b4-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2642":"1f6a3-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2642":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2642":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2642":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2642":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2640":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2640":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2640":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2640":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2640":"1f6a3-1f3fb-2640","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2642":"1f3cb-1f3ff-2642","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2642":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2642":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2642":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2642":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2640":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2640":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2640":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2640":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2640":"1f3cb-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2642":"1f3ca-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2642":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2642":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2642":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2642":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2640":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2640":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2640":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2640":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2640":"1f3ca-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2642":"1f3c4-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2642":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2642":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2642":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2642":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2640":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2640":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2640":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2640":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2640":"1f3c4-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2642":"1f3c3-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2642":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2642":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2642":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2642":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2640":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2640":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2640":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2640":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2640":"1f3c3-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFF\u200D\u2642":"1f937-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFE\u200D\u2642":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFD\u200D\u2642":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFC\u200D\u2642":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFB\u200D\u2642":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFF\u200D\u2640":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFE\u200D\u2640":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFD\u200D\u2640":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFC\u200D\u2640":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFB\u200D\u2640":"1f937-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFF\u200D\u2642":"1f926-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFE\u200D\u2642":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFD\u200D\u2642":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFC\u200D\u2642":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFB\u200D\u2642":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFF\u200D\u2640":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFE\u200D\u2640":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFD\u200D\u2640":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFC\u200D\u2640":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFB\u200D\u2640":"1f926-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2642":"1f64e-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2642":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2642":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2642":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2642":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2640":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2640":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2640":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2640":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2640":"1f64e-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2642":"1f64d-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2642":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2642":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2642":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2642":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2640":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2640":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2640":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2640":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2640":"1f64d-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2642":"1f64b-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2642":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2642":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2642":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2642":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2640":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2640":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2640":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2640":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2640":"1f64b-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFF\u200D\u2642":"1f647-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFE\u200D\u2642":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFD\u200D\u2642":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFC\u200D\u2642":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFB\u200D\u2642":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFF\u200D\u2640":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFE\u200D\u2640":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFD\u200D\u2640":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFC\u200D\u2640":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFB\u200D\u2640":"1f647-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFF\u200D\u2642":"1f646-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFE\u200D\u2642":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFD\u200D\u2642":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFC\u200D\u2642":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFB\u200D\u2642":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFF\u200D\u2640":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFE\u200D\u2640":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFD\u200D\u2640":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFC\u200D\u2640":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFB\u200D\u2640":"1f646-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFF\u200D\u2642":"1f645-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFE\u200D\u2642":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFD\u200D\u2642":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFC\u200D\u2642":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFB\u200D\u2642":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFF\u200D\u2640":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFE\u200D\u2640":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFD\u200D\u2640":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFC\u200D\u2640":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFB\u200D\u2640":"1f645-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFF\u200D\u2642":"1f487-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFE\u200D\u2642":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFD\u200D\u2642":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFC\u200D\u2642":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFB\u200D\u2642":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFF\u200D\u2640":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFE\u200D\u2640":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFD\u200D\u2640":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFC\u200D\u2640":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFB\u200D\u2640":"1f487-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFF\u200D\u2642":"1f486-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFE\u200D\u2642":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFD\u200D\u2642":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFC\u200D\u2642":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFB\u200D\u2642":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFF\u200D\u2640":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFE\u200D\u2640":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFD\u200D\u2640":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFC\u200D\u2640":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFB\u200D\u2640":"1f486-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFF\u200D\u2642":"1f481-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFE\u200D\u2642":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFD\u200D\u2642":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFC\u200D\u2642":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFB\u200D\u2642":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFF\u200D\u2640":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFE\u200D\u2640":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFD\u200D\u2640":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFC\u200D\u2640":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFB\u200D\u2640":"1f481-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFF\u200D\u2642":"1f471-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFE\u200D\u2642":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFD\u200D\u2642":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFC\u200D\u2642":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFB\u200D\u2642":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFF\u200D\u2640":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFE\u200D\u2640":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFD\u200D\u2640":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFC\u200D\u2640":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFB\u200D\u2640":"1f471-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFF\u200D\u2642":"1f473-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFE\u200D\u2642":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFD\u200D\u2642":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFC\u200D\u2642":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFB\u200D\u2642":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFF\u200D\u2640":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFE\u200D\u2640":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFD\u200D\u2640":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFC\u200D\u2640":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFB\u200D\u2640":"1f473-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFF\u200D\u2642":"1f482-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFE\u200D\u2642":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFD\u200D\u2642":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFC\u200D\u2642":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFB\u200D\u2642":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFF\u200D\u2640":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFE\u200D\u2640":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFD\u200D\u2640":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFC\u200D\u2640":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFB\u200D\u2640":"1f482-1f3fb-2640","\uD83D\uDD75\uD83C\uDFFF\u200D\u2642":"1f575-1f3ff-2642","\uD83D\uDD75\uD83C\uDFFE\u200D\u2642":"1f575-1f3fe-2642","\uD83D\uDD75\uD83C\uDFFD\u200D\u2642":"1f575-1f3fd-2642","\uD83D\uDD75\uD83C\uDFFC\u200D\u2642":"1f575-1f3fc-2642","\uD83D\uDD75\uD83C\uDFFB\u200D\u2642":"1f575-1f3fb-2642","\uD83D\uDD75\uD83C\uDFFF\u200D\u2640":"1f575-1f3ff-2640","\uD83D\uDD75\uD83C\uDFFE\u200D\u2640":"1f575-1f3fe-2640","\uD83D\uDD75\uD83C\uDFFD\u200D\u2640":"1f575-1f3fd-2640","\uD83D\uDD75\uD83C\uDFFC\u200D\u2640":"1f575-1f3fc-2640","\uD83D\uDD75\uD83C\uDFFB\u200D\u2640":"1f575-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFF\u200D\u2642":"1f477-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFE\u200D\u2642":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFD\u200D\u2642":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFC\u200D\u2642":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFB\u200D\u2642":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFF\u200D\u2640":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFE\u200D\u2640":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFD\u200D\u2640":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFC\u200D\u2640":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFB\u200D\u2640":"1f477-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2642":"1f46e-1f3ff-2642","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2642":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2642":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2642":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2642":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2640":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2640":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2640":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2640":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2640":"1f46e-1f3fb-2640","\uD83D\uDC68\uD83C\uDFFF\u200D\u2695":"1f468-1f3ff-2695","\uD83D\uDC68\uD83C\uDFFE\u200D\u2695":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFD\u200D\u2695":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFC\u200D\u2695":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFB\u200D\u2695":"1f468-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFF\u200D\u2695":"1f469-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFE\u200D\u2695":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFD\u200D\u2695":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFC\u200D\u2695":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFB\u200D\u2695":"1f469-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFB\u200D\u2696":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFC\u200D\u2696":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFD\u200D\u2696":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFE\u200D\u2696":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFF\u200D\u2696":"1f468-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFB\u200D\u2696":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFC\u200D\u2696":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFD\u200D\u2696":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFE\u200D\u2696":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFF\u200D\u2696":"1f469-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFB\u200D\u2708":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u200D\u2708":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u200D\u2708":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u200D\u2708":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u200D\u2708":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u200D\u2708":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u200D\u2708":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u200D\u2708":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u200D\u2708":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u200D\u2708":"1f469-1f3ff-2708","\uD83D\uDC68\u2764\uFE0F\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\uD83C\uDFFB\u2695\uFE0F":"1f468-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFB\u2696\uFE0F":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFB\u2708\uFE0F":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u2695\uFE0F":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFC\u2696\uFE0F":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFC\u2708\uFE0F":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u2695\uFE0F":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFD\u2696\uFE0F":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFD\u2708\uFE0F":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u2695\uFE0F":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFE\u2696\uFE0F":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFE\u2708\uFE0F":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u2695\uFE0F":"1f468-1f3ff-2695","\uD83D\uDC68\uD83C\uDFFF\u2696\uFE0F":"1f468-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFF\u2708\uFE0F":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u2695\uFE0F":"1f469-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFB\u2696\uFE0F":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFB\u2708\uFE0F":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u2695\uFE0F":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFC\u2696\uFE0F":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFC\u2708\uFE0F":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u2695\uFE0F":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFD\u2696\uFE0F":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFD\u2708\uFE0F":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u2695\uFE0F":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFE\u2696\uFE0F":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFE\u2708\uFE0F":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u2695\uFE0F":"1f469-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFF\u2696\uFE0F":"1f469-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFF\u2708\uFE0F":"1f469-1f3ff-2708","\uD83D\uDC6E\uD83C\uDFFB\u2640\uFE0F":"1f46e-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFB\u2642\uFE0F":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFC\u2640\uFE0F":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFC\u2642\uFE0F":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFD\u2640\uFE0F":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFD\u2642\uFE0F":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFE\u2640\uFE0F":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFE\u2642\uFE0F":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFF\u2640\uFE0F":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFF\u2642\uFE0F":"1f46e-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFB\u2640\uFE0F":"1f471-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFB\u2642\uFE0F":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFC\u2640\uFE0F":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFC\u2642\uFE0F":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFD\u2640\uFE0F":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFD\u2642\uFE0F":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFE\u2640\uFE0F":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFE\u2642\uFE0F":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFF\u2640\uFE0F":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFF\u2642\uFE0F":"1f471-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFB\u2640\uFE0F":"1f473-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFB\u2642\uFE0F":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFC\u2640\uFE0F":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFC\u2642\uFE0F":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFD\u2640\uFE0F":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFD\u2642\uFE0F":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFE\u2640\uFE0F":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFE\u2642\uFE0F":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFF\u2640\uFE0F":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFF\u2642\uFE0F":"1f473-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFB\u2640\uFE0F":"1f477-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFB\u2642\uFE0F":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFC\u2640\uFE0F":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFC\u2642\uFE0F":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFD\u2640\uFE0F":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFD\u2642\uFE0F":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFE\u2640\uFE0F":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFE\u2642\uFE0F":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFF\u2640\uFE0F":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFF\u2642\uFE0F":"1f477-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFB\u2640\uFE0F":"1f482-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFB\u2642\uFE0F":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFC\u2640\uFE0F":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFC\u2642\uFE0F":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFD\u2640\uFE0F":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFD\u2642\uFE0F":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFE\u2640\uFE0F":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFE\u2642\uFE0F":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFF\u2640\uFE0F":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFF\u2642\uFE0F":"1f482-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFB\u2640\uFE0F":"1f3c3-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFB\u2642\uFE0F":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFC\u2640\uFE0F":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFC\u2642\uFE0F":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFD\u2640\uFE0F":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFD\u2642\uFE0F":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFE\u2640\uFE0F":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFE\u2642\uFE0F":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFF\u2640\uFE0F":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFF\u2642\uFE0F":"1f3c3-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFB\u2640\uFE0F":"1f3c4-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFB\u2642\uFE0F":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFC\u2640\uFE0F":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFC\u2642\uFE0F":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFD\u2640\uFE0F":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFD\u2642\uFE0F":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFE\u2640\uFE0F":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFE\u2642\uFE0F":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFF\u2640\uFE0F":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFF\u2642\uFE0F":"1f3c4-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFB\u2640\uFE0F":"1f3ca-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFB\u2642\uFE0F":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFC\u2640\uFE0F":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFC\u2642\uFE0F":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFD\u2640\uFE0F":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFD\u2642\uFE0F":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFE\u2640\uFE0F":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFE\u2642\uFE0F":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFF\u2640\uFE0F":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFF\u2642\uFE0F":"1f3ca-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFB\u2640\uFE0F":"1f486-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFB\u2642\uFE0F":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFC\u2640\uFE0F":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFC\u2642\uFE0F":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFD\u2640\uFE0F":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFD\u2642\uFE0F":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFE\u2640\uFE0F":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFE\u2642\uFE0F":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFF\u2640\uFE0F":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFF\u2642\uFE0F":"1f486-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFB\u2640\uFE0F":"1f487-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFB\u2642\uFE0F":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFC\u2640\uFE0F":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFC\u2642\uFE0F":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFD\u2640\uFE0F":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFD\u2642\uFE0F":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFE\u2640\uFE0F":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFE\u2642\uFE0F":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFF\u2640\uFE0F":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFF\u2642\uFE0F":"1f487-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFB\u2640\uFE0F":"1f6a3-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFB\u2642\uFE0F":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFC\u2640\uFE0F":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFC\u2642\uFE0F":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFD\u2640\uFE0F":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFD\u2642\uFE0F":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFE\u2640\uFE0F":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFE\u2642\uFE0F":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFF\u2640\uFE0F":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFF\u2642\uFE0F":"1f6a3-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFB\u2640\uFE0F":"1f6b4-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFB\u2642\uFE0F":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFC\u2640\uFE0F":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFC\u2642\uFE0F":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFD\u2640\uFE0F":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFD\u2642\uFE0F":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFE\u2640\uFE0F":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFE\u2642\uFE0F":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFF\u2640\uFE0F":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFF\u2642\uFE0F":"1f6b4-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFB\u2640\uFE0F":"1f6b5-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFB\u2642\uFE0F":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFC\u2640\uFE0F":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFC\u2642\uFE0F":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFD\u2640\uFE0F":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFD\u2642\uFE0F":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFE\u2640\uFE0F":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFE\u2642\uFE0F":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFF\u2640\uFE0F":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFF\u2642\uFE0F":"1f6b5-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFB\u2640\uFE0F":"1f6b6-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFB\u2642\uFE0F":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFC\u2640\uFE0F":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFC\u2642\uFE0F":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFD\u2640\uFE0F":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFD\u2642\uFE0F":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFE\u2640\uFE0F":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFE\u2642\uFE0F":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFF\u2640\uFE0F":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFF\u2642\uFE0F":"1f6b6-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFB\u2640\uFE0F":"1f938-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFB\u2642\uFE0F":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFC\u2640\uFE0F":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFC\u2642\uFE0F":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFD\u2640\uFE0F":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFD\u2642\uFE0F":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFE\u2640\uFE0F":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFE\u2642\uFE0F":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFF\u2640\uFE0F":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFF\u2642\uFE0F":"1f938-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFB\u2640\uFE0F":"1f939-1f3fb-2640","\uD83E\uDD39\uD83C\uDFFB\u2642\uFE0F":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFC\u2640\uFE0F":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFC\u2642\uFE0F":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFD\u2640\uFE0F":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFD\u2642\uFE0F":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFE\u2640\uFE0F":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFE\u2642\uFE0F":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFF\u2640\uFE0F":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u2642\uFE0F":"1f939-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFB\u2640\uFE0F":"1f93d-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFB\u2642\uFE0F":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFC\u2640\uFE0F":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFC\u2642\uFE0F":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFD\u2640\uFE0F":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFD\u2642\uFE0F":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFE\u2640\uFE0F":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFE\u2642\uFE0F":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFF\u2640\uFE0F":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFF\u2642\uFE0F":"1f93d-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFB\u2640\uFE0F":"1f93e-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFB\u2642\uFE0F":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFC\u2640\uFE0F":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFC\u2642\uFE0F":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFD\u2640\uFE0F":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFD\u2642\uFE0F":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFE\u2640\uFE0F":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFE\u2642\uFE0F":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFF\u2640\uFE0F":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFF\u2642\uFE0F":"1f93e-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFB\u2640\uFE0F":"1f481-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFB\u2642\uFE0F":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFC\u2640\uFE0F":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFC\u2642\uFE0F":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFD\u2640\uFE0F":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFD\u2642\uFE0F":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFE\u2640\uFE0F":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFE\u2642\uFE0F":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFF\u2640\uFE0F":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFF\u2642\uFE0F":"1f481-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFB\u2640\uFE0F":"1f645-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFB\u2642\uFE0F":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFC\u2640\uFE0F":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFC\u2642\uFE0F":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFD\u2640\uFE0F":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFD\u2642\uFE0F":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFE\u2640\uFE0F":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFE\u2642\uFE0F":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFF\u2640\uFE0F":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFF\u2642\uFE0F":"1f645-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFB\u2640\uFE0F":"1f646-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFB\u2642\uFE0F":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFC\u2640\uFE0F":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFC\u2642\uFE0F":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFD\u2640\uFE0F":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFD\u2642\uFE0F":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFE\u2640\uFE0F":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFE\u2642\uFE0F":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFF\u2640\uFE0F":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFF\u2642\uFE0F":"1f646-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFB\u2640\uFE0F":"1f647-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFB\u2642\uFE0F":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFC\u2640\uFE0F":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFC\u2642\uFE0F":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFD\u2640\uFE0F":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFD\u2642\uFE0F":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFE\u2640\uFE0F":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFE\u2642\uFE0F":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFF\u2640\uFE0F":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFF\u2642\uFE0F":"1f647-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFB\u2640\uFE0F":"1f64b-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFB\u2642\uFE0F":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFC\u2640\uFE0F":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFC\u2642\uFE0F":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFD\u2640\uFE0F":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFD\u2642\uFE0F":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFE\u2640\uFE0F":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFE\u2642\uFE0F":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFF\u2640\uFE0F":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFF\u2642\uFE0F":"1f64b-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFB\u2640\uFE0F":"1f64d-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFB\u2642\uFE0F":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFC\u2640\uFE0F":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFC\u2642\uFE0F":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFD\u2640\uFE0F":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFD\u2642\uFE0F":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFE\u2640\uFE0F":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFE\u2642\uFE0F":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFF\u2640\uFE0F":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFF\u2642\uFE0F":"1f64d-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFB\u2640\uFE0F":"1f64e-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFB\u2642\uFE0F":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFC\u2640\uFE0F":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFC\u2642\uFE0F":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFD\u2640\uFE0F":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFD\u2642\uFE0F":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFE\u2640\uFE0F":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFE\u2642\uFE0F":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFF\u2640\uFE0F":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFF\u2642\uFE0F":"1f64e-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFB\u2640\uFE0F":"1f926-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFB\u2642\uFE0F":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFC\u2640\uFE0F":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFC\u2642\uFE0F":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFD\u2640\uFE0F":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFD\u2642\uFE0F":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFE\u2640\uFE0F":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFE\u2642\uFE0F":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFF\u2640\uFE0F":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFF\u2642\uFE0F":"1f926-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFB\u2640\uFE0F":"1f937-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFB\u2642\uFE0F":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFC\u2640\uFE0F":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFC\u2642\uFE0F":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFD\u2640\uFE0F":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFD\u2642\uFE0F":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFE\u2640\uFE0F":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFE\u2642\uFE0F":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFF\u2640\uFE0F":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFF\u2642\uFE0F":"1f937-1f3ff-2642","\uD83D\uDC41\uFE0F\uD83D\uDDE8\uFE0F":"1f441-1f5e8","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2640":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u2640\uFE0F":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2642":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFB\u2642\uFE0F":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2640":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u2640\uFE0F":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2642":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFC\u2642\uFE0F":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2640":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u2640\uFE0F":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2642":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFD\u2642\uFE0F":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2640":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u2640\uFE0F":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2642":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFE\u2642\uFE0F":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2640":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u2640\uFE0F":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2642":"1f9d9-1f3ff-2642","\uD83E\uDDD9\uD83C\uDFFF\u2642\uFE0F":"1f9d9-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2640":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u2640\uFE0F":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2642":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFB\u2642\uFE0F":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2640":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u2640\uFE0F":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2642":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFC\u2642\uFE0F":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2640":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u2640\uFE0F":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2642":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFD\u2642\uFE0F":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2640":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u2640\uFE0F":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2642":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFE\u2642\uFE0F":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2640":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u2640\uFE0F":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2642":"1f9da-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFF\u2642\uFE0F":"1f9da-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2640":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u2640\uFE0F":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2642":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFB\u2642\uFE0F":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2640":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u2640\uFE0F":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2642":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFC\u2642\uFE0F":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2640":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u2640\uFE0F":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2642":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFD\u2642\uFE0F":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2640":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u2640\uFE0F":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2642":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFE\u2642\uFE0F":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2640":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u2640\uFE0F":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2642":"1f9db-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFF\u2642\uFE0F":"1f9db-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2640":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u2640\uFE0F":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2642":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFB\u2642\uFE0F":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2640":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u2640\uFE0F":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2642":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFC\u2642\uFE0F":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2640":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u2640\uFE0F":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2642":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFD\u2642\uFE0F":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2640":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u2640\uFE0F":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2642":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFE\u2642\uFE0F":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2640":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u2640\uFE0F":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2642":"1f9dc-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFF\u2642\uFE0F":"1f9dc-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2640":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u2640\uFE0F":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2642":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFB\u2642\uFE0F":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2640":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u2640\uFE0F":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2642":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFC\u2642\uFE0F":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2640":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u2640\uFE0F":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2642":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFD\u2642\uFE0F":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2640":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u2640\uFE0F":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2642":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFE\u2642\uFE0F":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2640":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u2640\uFE0F":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2642":"1f9dd-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFF\u2642\uFE0F":"1f9dd-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2640":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u2640\uFE0F":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2642":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFB\u2642\uFE0F":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2640":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u2640\uFE0F":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2642":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFC\u2642\uFE0F":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2640":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u2640\uFE0F":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2642":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFD\u2642\uFE0F":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2640":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u2640\uFE0F":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2642":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFE\u2642\uFE0F":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2640":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u2640\uFE0F":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2642":"1f9d6-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFF\u2642\uFE0F":"1f9d6-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2640":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u2640\uFE0F":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2642":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFB\u2642\uFE0F":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2640":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u2640\uFE0F":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2642":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFC\u2642\uFE0F":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2640":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u2640\uFE0F":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2642":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFD\u2642\uFE0F":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2640":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u2640\uFE0F":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2642":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFE\u2642\uFE0F":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2640":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u2640\uFE0F":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2642":"1f9d7-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFF\u2642\uFE0F":"1f9d7-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2640":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u2640\uFE0F":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2642":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFB\u2642\uFE0F":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2640":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u2640\uFE0F":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2642":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFC\u2642\uFE0F":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2640":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u2640\uFE0F":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2642":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFD\u2642\uFE0F":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2640":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u2640\uFE0F":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2642":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFE\u2642\uFE0F":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2640":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u2640\uFE0F":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2642":"1f9d8-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFF\u2642\uFE0F":"1f9d8-1f3ff-2642","\u26F9\uD83C\uDFFF\u200D\u2642":"26f9-1f3ff-2642","\u26F9\uD83C\uDFFE\u200D\u2642":"26f9-1f3fe-2642","\u26F9\uD83C\uDFFD\u200D\u2642":"26f9-1f3fd-2642","\u26F9\uD83C\uDFFC\u200D\u2642":"26f9-1f3fc-2642","\u26F9\uD83C\uDFFB\u200D\u2642":"26f9-1f3fb-2642","\u26F9\uD83C\uDFFF\u200D\u2640":"26f9-1f3ff-2640","\u26F9\uD83C\uDFFE\u200D\u2640":"26f9-1f3fe-2640","\u26F9\uD83C\uDFFD\u200D\u2640":"26f9-1f3fd-2640","\u26F9\uD83C\uDFFC\u200D\u2640":"26f9-1f3fc-2640","\u26F9\uD83C\uDFFB\u200D\u2640":"26f9-1f3fb-2640","\uD83D\uDC68\u200D\u2695\uFE0F":"1f468-2695","\uD83D\uDC68\u200D\u2696\uFE0F":"1f468-2696","\uD83D\uDC68\u200D\u2708\uFE0F":"1f468-2708","\uD83D\uDC69\u200D\u2695\uFE0F":"1f469-2695","\uD83D\uDC69\u200D\u2696\uFE0F":"1f469-2696","\uD83D\uDC69\u200D\u2708\uFE0F":"1f469-2708","\uD83D\uDC6E\u200D\u2640\uFE0F":"1f46e-2640","\uD83D\uDC6E\u200D\u2642\uFE0F":"1f46e-2642","\uD83D\uDC71\u200D\u2640\uFE0F":"1f471-2640","\uD83D\uDC71\u200D\u2642\uFE0F":"1f471-2642","\uD83D\uDC73\u200D\u2640\uFE0F":"1f473-2640","\uD83D\uDC73\u200D\u2642\uFE0F":"1f473-2642","\uD83D\uDC77\u200D\u2640\uFE0F":"1f477-2640","\uD83D\uDC77\u200D\u2642\uFE0F":"1f477-2642","\uD83D\uDC82\u200D\u2640\uFE0F":"1f482-2640","\uD83D\uDC82\u200D\u2642\uFE0F":"1f482-2642","\uD83D\uDD75\uFE0F\u2640\uFE0F":"1f575-2640","\uD83D\uDD75\uFE0F\u2642\uFE0F":"1f575-2642","\uD83C\uDFC3\u200D\u2640\uFE0F":"1f3c3-2640","\uD83C\uDFC3\u200D\u2642\uFE0F":"1f3c3-2642","\uD83C\uDFC4\u200D\u2640\uFE0F":"1f3c4-2640","\uD83C\uDFC4\u200D\u2642\uFE0F":"1f3c4-2642","\uD83C\uDFCA\u200D\u2640\uFE0F":"1f3ca-2640","\uD83C\uDFCA\u200D\u2642\uFE0F":"1f3ca-2642","\uD83C\uDFCB\uFE0F\u2640\uFE0F":"1f3cb-2640","\uD83C\uDFCB\uFE0F\u2642\uFE0F":"1f3cb-2642","\uD83C\uDFCC\uFE0F\u2640\uFE0F":"1f3cc-2640","\uD83C\uDFCC\uFE0F\u2642\uFE0F":"1f3cc-2642","\uD83D\uDC6F\u200D\u2640\uFE0F":"1f46f-2640","\uD83D\uDC6F\u200D\u2642\uFE0F":"1f46f-2642","\uD83D\uDC86\u200D\u2640\uFE0F":"1f486-2640","\uD83D\uDC86\u200D\u2642\uFE0F":"1f486-2642","\uD83D\uDC87\u200D\u2640\uFE0F":"1f487-2640","\uD83D\uDC87\u200D\u2642\uFE0F":"1f487-2642","\uD83D\uDEA3\u200D\u2640\uFE0F":"1f6a3-2640","\uD83D\uDEA3\u200D\u2642\uFE0F":"1f6a3-2642","\uD83D\uDEB4\u200D\u2640\uFE0F":"1f6b4-2640","\uD83D\uDEB4\u200D\u2642\uFE0F":"1f6b4-2642","\uD83D\uDEB5\u200D\u2640\uFE0F":"1f6b5-2640","\uD83D\uDEB5\u200D\u2642\uFE0F":"1f6b5-2642","\uD83D\uDEB6\u200D\u2640\uFE0F":"1f6b6-2640","\uD83D\uDEB6\u200D\u2642\uFE0F":"1f6b6-2642","\uD83E\uDD38\u200D\u2640\uFE0F":"1f938-2640","\uD83E\uDD38\u200D\u2642\uFE0F":"1f938-2642","\uD83E\uDD39\u200D\u2640\uFE0F":"1f939-2640","\uD83E\uDD39\u200D\u2642\uFE0F":"1f939-2642","\uD83E\uDD3C\u200D\u2640\uFE0F":"1f93c-2640","\uD83E\uDD3C\u200D\u2642\uFE0F":"1f93c-2642","\uD83E\uDD3D\u200D\u2640\uFE0F":"1f93d-2640","\uD83E\uDD3D\u200D\u2642\uFE0F":"1f93d-2642","\uD83E\uDD3E\u200D\u2640\uFE0F":"1f93e-2640","\uD83E\uDD3E\u200D\u2642\uFE0F":"1f93e-2642","\uD83D\uDC81\u200D\u2640\uFE0F":"1f481-2640","\uD83D\uDC81\u200D\u2642\uFE0F":"1f481-2642","\uD83D\uDE45\u200D\u2640\uFE0F":"1f645-2640","\uD83D\uDE45\u200D\u2642\uFE0F":"1f645-2642","\uD83D\uDE46\u200D\u2640\uFE0F":"1f646-2640","\uD83D\uDE46\u200D\u2642\uFE0F":"1f646-2642","\uD83D\uDE47\u200D\u2640\uFE0F":"1f647-2640","\uD83D\uDE47\u200D\u2642\uFE0F":"1f647-2642","\uD83D\uDE4B\u200D\u2640\uFE0F":"1f64b-2640","\uD83D\uDE4B\u200D\u2642\uFE0F":"1f64b-2642","\uD83D\uDE4D\u200D\u2640\uFE0F":"1f64d-2640","\uD83D\uDE4D\u200D\u2642\uFE0F":"1f64d-2642","\uD83D\uDE4E\u200D\u2640\uFE0F":"1f64e-2640","\uD83D\uDE4E\u200D\u2642\uFE0F":"1f64e-2642","\uD83E\uDD26\u200D\u2640\uFE0F":"1f926-2640","\uD83E\uDD26\u200D\u2642\uFE0F":"1f926-2642","\uD83E\uDD37\u200D\u2640\uFE0F":"1f937-2640","\uD83E\uDD37\u200D\u2642\uFE0F":"1f937-2642","\uD83E\uDDD9\u200D\u2640\uFE0F":"1f9d9-2640","\uD83E\uDDD9\u200D\u2642\uFE0F":"1f9d9-2642","\uD83E\uDDDA\u200D\u2640\uFE0F":"1f9da-2640","\uD83E\uDDDA\u200D\u2642\uFE0F":"1f9da-2642","\uD83E\uDDDB\u200D\u2640\uFE0F":"1f9db-2640","\uD83E\uDDDB\u200D\u2642\uFE0F":"1f9db-2642","\uD83E\uDDDC\u200D\u2640\uFE0F":"1f9dc-2640","\uD83E\uDDDC\u200D\u2642\uFE0F":"1f9dc-2642","\uD83E\uDDDD\u200D\u2640\uFE0F":"1f9dd-2640","\uD83E\uDDDD\u200D\u2642\uFE0F":"1f9dd-2642","\uD83E\uDDDE\u200D\u2640\uFE0F":"1f9de-2640","\uD83E\uDDDE\u200D\u2642\uFE0F":"1f9de-2642","\uD83E\uDDDF\u200D\u2640\uFE0F":"1f9df-2640","\uD83E\uDDDF\u200D\u2642\uFE0F":"1f9df-2642","\uD83E\uDDD6\u200D\u2640\uFE0F":"1f9d6-2640","\uD83E\uDDD6\u200D\u2642\uFE0F":"1f9d6-2642","\uD83E\uDDD7\u200D\u2640\uFE0F":"1f9d7-2640","\uD83E\uDDD7\u200D\u2642\uFE0F":"1f9d7-2642","\uD83E\uDDD8\u200D\u2640\uFE0F":"1f9d8-2640","\uD83E\uDDD8\u200D\u2642\uFE0F":"1f9d8-2642","\u26F9\uFE0F\u2640\uFE0F":"26f9-2640","\u26F9\uFE0F\u2642\uFE0F":"26f9-2642","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC66":"1f468-1f468-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67":"1f468-1f468-1f467","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67":"1f468-1f469-1f467","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66":"1f469-1f469-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67":"1f469-1f469-1f467","\uD83D\uDC68\uD83D\uDC66\uD83D\uDC66":"1f468-1f466-1f466","\uD83D\uDC68\uD83D\uDC67\uD83D\uDC66":"1f468-1f467-1f466","\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f469-1f466-1f466","\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f469-1f467-1f466","\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f469-1f467-1f467","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFA8":"1f468-1f3fb-1f3a8","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFA8":"1f468-1f3fc-1f3a8","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFA8":"1f468-1f3fd-1f3a8","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFA8":"1f468-1f3fe-1f3a8","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFA8":"1f468-1f3ff-1f3a8","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFA8":"1f469-1f3fb-1f3a8","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFA8":"1f469-1f3fc-1f3a8","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFA8":"1f469-1f3fd-1f3a8","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFA8":"1f469-1f3fe-1f3a8","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFA8":"1f469-1f3ff-1f3a8","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDE80":"1f468-1f3fb-1f680","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDE80":"1f468-1f3fc-1f680","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDE80":"1f468-1f3fd-1f680","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDE80":"1f468-1f3fe-1f680","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDE80":"1f468-1f3ff-1f680","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDE80":"1f469-1f3fb-1f680","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDE80":"1f469-1f3fc-1f680","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDE80":"1f469-1f3fd-1f680","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDE80":"1f469-1f3fe-1f680","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDE80":"1f469-1f3ff-1f680","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDE92":"1f468-1f3fb-1f692","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDE92":"1f468-1f3fc-1f692","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDE92":"1f468-1f3fd-1f692","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDE92":"1f468-1f3fe-1f692","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDE92":"1f468-1f3ff-1f692","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDE92":"1f469-1f3fb-1f692","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDE92":"1f469-1f3fc-1f692","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDE92":"1f469-1f3fd-1f692","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDE92":"1f469-1f3fe-1f692","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDE92":"1f469-1f3ff-1f692","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC66":"1f468-1f469-1f466","\uD83D\uDC68\uD83D\uDC67\uD83D\uDC67":"1f468-1f467-1f467","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDF3E":"1f468-1f3fb-1f33e","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDF73":"1f468-1f3fb-1f373","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDF93":"1f468-1f3fb-1f393","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFA4":"1f468-1f3fb-1f3a4","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFEB":"1f468-1f3fb-1f3eb","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFED":"1f468-1f3fb-1f3ed","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDCBB":"1f468-1f3fb-1f4bb","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDCBC":"1f468-1f3fb-1f4bc","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDD27":"1f468-1f3fb-1f527","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDD2C":"1f468-1f3fb-1f52c","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDF3E":"1f468-1f3fc-1f33e","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDF73":"1f468-1f3fc-1f373","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDF93":"1f468-1f3fc-1f393","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFA4":"1f468-1f3fc-1f3a4","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFEB":"1f468-1f3fc-1f3eb","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFED":"1f468-1f3fc-1f3ed","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDCBB":"1f468-1f3fc-1f4bb","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDCBC":"1f468-1f3fc-1f4bc","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDD27":"1f468-1f3fc-1f527","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDD2C":"1f468-1f3fc-1f52c","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDF3E":"1f468-1f3fd-1f33e","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDF73":"1f468-1f3fd-1f373","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDF93":"1f468-1f3fd-1f393","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFA4":"1f468-1f3fd-1f3a4","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFEB":"1f468-1f3fd-1f3eb","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFED":"1f468-1f3fd-1f3ed","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDCBB":"1f468-1f3fd-1f4bb","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDCBC":"1f468-1f3fd-1f4bc","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDD27":"1f468-1f3fd-1f527","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDD2C":"1f468-1f3fd-1f52c","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDF3E":"1f468-1f3fe-1f33e","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDF73":"1f468-1f3fe-1f373","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDF93":"1f468-1f3fe-1f393","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFA4":"1f468-1f3fe-1f3a4","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFEB":"1f468-1f3fe-1f3eb","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFED":"1f468-1f3fe-1f3ed","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDCBB":"1f468-1f3fe-1f4bb","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDCBC":"1f468-1f3fe-1f4bc","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDD27":"1f468-1f3fe-1f527","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDD2C":"1f468-1f3fe-1f52c","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDF3E":"1f468-1f3ff-1f33e","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDF73":"1f468-1f3ff-1f373","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDF93":"1f468-1f3ff-1f393","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFA4":"1f468-1f3ff-1f3a4","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFEB":"1f468-1f3ff-1f3eb","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFED":"1f468-1f3ff-1f3ed","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDCBB":"1f468-1f3ff-1f4bb","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDCBC":"1f468-1f3ff-1f4bc","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDD27":"1f468-1f3ff-1f527","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDD2C":"1f468-1f3ff-1f52c","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDF3E":"1f469-1f3fb-1f33e","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDF73":"1f469-1f3fb-1f373","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDF93":"1f469-1f3fb-1f393","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFA4":"1f469-1f3fb-1f3a4","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFEB":"1f469-1f3fb-1f3eb","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFED":"1f469-1f3fb-1f3ed","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDCBB":"1f469-1f3fb-1f4bb","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDCBC":"1f469-1f3fb-1f4bc","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDD27":"1f469-1f3fb-1f527","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDD2C":"1f469-1f3fb-1f52c","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDF3E":"1f469-1f3fc-1f33e","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDF73":"1f469-1f3fc-1f373","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDF93":"1f469-1f3fc-1f393","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFA4":"1f469-1f3fc-1f3a4","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFEB":"1f469-1f3fc-1f3eb","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFED":"1f469-1f3fc-1f3ed","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDCBB":"1f469-1f3fc-1f4bb","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDCBC":"1f469-1f3fc-1f4bc","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDD27":"1f469-1f3fc-1f527","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDD2C":"1f469-1f3fc-1f52c","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E":"1f469-1f3fd-1f33e","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF73":"1f469-1f3fd-1f373","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF93":"1f469-1f3fd-1f393","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFA4":"1f469-1f3fd-1f3a4","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFEB":"1f469-1f3fd-1f3eb","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFED":"1f469-1f3fd-1f3ed","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDCBB":"1f469-1f3fd-1f4bb","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDCBC":"1f469-1f3fd-1f4bc","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDD27":"1f469-1f3fd-1f527","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDD2C":"1f469-1f3fd-1f52c","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDF3E":"1f469-1f3fe-1f33e","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDF73":"1f469-1f3fe-1f373","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDF93":"1f469-1f3fe-1f393","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFA4":"1f469-1f3fe-1f3a4","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFEB":"1f469-1f3fe-1f3eb","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFED":"1f469-1f3fe-1f3ed","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDCBB":"1f469-1f3fe-1f4bb","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDCBC":"1f469-1f3fe-1f4bc","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDD27":"1f469-1f3fe-1f527","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDD2C":"1f469-1f3fe-1f52c","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDF3E":"1f469-1f3ff-1f33e","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDF73":"1f469-1f3ff-1f373","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDF93":"1f469-1f3ff-1f393","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFA4":"1f469-1f3ff-1f3a4","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFEB":"1f469-1f3ff-1f3eb","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFED":"1f469-1f3ff-1f3ed","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDCBB":"1f469-1f3ff-1f4bb","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDCBC":"1f469-1f3ff-1f4bc","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDD27":"1f469-1f3ff-1f527","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDD2C":"1f469-1f3ff-1f52c","\uD83D\uDC41\u200D\uD83D\uDDE8":"1f441-1f5e8","\uD83D\uDC68\u200D\uD83D\uDCBB":"1f468-1f4bb","\uD83D\uDC69\u200D\uD83D\uDCBB":"1f469-1f4bb","\uD83D\uDC68\u200D\uD83C\uDFEB":"1f468-1f3eb","\uD83D\uDC69\u200D\uD83C\uDFEB":"1f469-1f3eb","\uD83D\uDC68\u200D\uD83C\uDF93":"1f468-1f393","\uD83D\uDC69\u200D\uD83C\uDF93":"1f469-1f393","\uD83D\uDC68\u200D\uD83C\uDFA4":"1f468-1f3a4","\uD83D\uDC69\u200D\uD83C\uDFA4":"1f469-1f3a4","\uD83D\uDC68\u200D\uD83D\uDD2C":"1f468-1f52c","\uD83D\uDC69\u200D\uD83D\uDD2C":"1f469-1f52c","\uD83D\uDC68\u200D\uD83D\uDCBC":"1f468-1f4bc","\uD83D\uDC69\u200D\uD83D\uDCBC":"1f469-1f4bc","\uD83D\uDC68\u200D\uD83D\uDD27":"1f468-1f527","\uD83D\uDC69\u200D\uD83D\uDD27":"1f469-1f527","\uD83D\uDC68\u200D\uD83C\uDFED":"1f468-1f3ed","\uD83D\uDC69\u200D\uD83C\uDFED":"1f469-1f3ed","\uD83D\uDC68\u200D\uD83C\uDF73":"1f468-1f373","\uD83D\uDC69\u200D\uD83C\uDF73":"1f469-1f373","\uD83D\uDC68\u200D\uD83C\uDF3E":"1f468-1f33e","\uD83D\uDC69\u200D\uD83C\uDF3E":"1f469-1f33e","\uD83D\uDC68\u200D\uD83D\uDC66":"1f468-1f466","\uD83D\uDC68\u200D\uD83D\uDC67":"1f468-1f467","\uD83D\uDC69\u200D\uD83D\uDC66":"1f469-1f466","\uD83D\uDC69\u200D\uD83D\uDC67":"1f469-1f467","\uD83D\uDC68\u200D\uD83C\uDFA8":"1f468-1f3a8","\uD83D\uDC69\u200D\uD83C\uDFA8":"1f469-1f3a8","\uD83D\uDC68\u200D\uD83D\uDE80":"1f468-1f680","\uD83D\uDC69\u200D\uD83D\uDE80":"1f469-1f680","\uD83D\uDC68\u200D\uD83D\uDE92":"1f468-1f692","\uD83D\uDC69\u200D\uD83D\uDE92":"1f469-1f692","\uD83C\uDFCB\uFE0F\uD83C\uDFFB":"1f3cb-1f3fb","\uD83C\uDFCB\uFE0F\uD83C\uDFFC":"1f3cb-1f3fc","\uD83C\uDFCB\uFE0F\uD83C\uDFFD":"1f3cb-1f3fd","\uD83C\uDFCB\uFE0F\uD83C\uDFFE":"1f3cb-1f3fe","\uD83C\uDFCB\uFE0F\uD83C\uDFFF":"1f3cb-1f3ff","\uD83C\uDFCC\uFE0F\uD83C\uDFFB":"1f3cc-1f3fb","\uD83C\uDFCC\uFE0F\uD83C\uDFFC":"1f3cc-1f3fc","\uD83C\uDFCC\uFE0F\uD83C\uDFFD":"1f3cc-1f3fd","\uD83C\uDFCC\uFE0F\uD83C\uDFFE":"1f3cc-1f3fe","\uD83C\uDFCC\uFE0F\uD83C\uDFFF":"1f3cc-1f3ff","\uD83D\uDD74\uFE0F\uD83C\uDFFB":"1f574-1f3fb","\uD83D\uDD74\uFE0F\uD83C\uDFFC":"1f574-1f3fc","\uD83D\uDD74\uFE0F\uD83C\uDFFD":"1f574-1f3fd","\uD83D\uDD74\uFE0F\uD83C\uDFFE":"1f574-1f3fe","\uD83D\uDD74\uFE0F\uD83C\uDFFF":"1f574-1f3ff","\uD83D\uDD75\uFE0F\uD83C\uDFFB":"1f575-1f3fb","\uD83D\uDD75\uFE0F\uD83C\uDFFC":"1f575-1f3fc","\uD83D\uDD75\uFE0F\uD83C\uDFFD":"1f575-1f3fd","\uD83D\uDD75\uFE0F\uD83C\uDFFE":"1f575-1f3fe","\uD83D\uDD75\uFE0F\uD83C\uDFFF":"1f575-1f3ff","\uD83D\uDD90\uFE0F\uD83C\uDFFB":"1f590-1f3fb","\uD83D\uDD90\uFE0F\uD83C\uDFFC":"1f590-1f3fc","\uD83D\uDD90\uFE0F\uD83C\uDFFD":"1f590-1f3fd","\uD83D\uDD90\uFE0F\uD83C\uDFFE":"1f590-1f3fe","\uD83D\uDD90\uFE0F\uD83C\uDFFF":"1f590-1f3ff","\uD83C\uDFF3\u200D\uD83C\uDF08":"1f3f3-1f308","\uD83C\uDFF3\uFE0F\uD83C\uDF08":"1f3f3-1f308","\uD83D\uDC6F\u200D\u2642":"1f46f-2642","\uD83D\uDC6F\u200D\u2640":"1f46f-2640","\uD83E\uDD3C\u200D\u2642":"1f93c-2642","\uD83E\uDD3C\u200D\u2640":"1f93c-2640","\uD83E\uDD39\u200D\u2642":"1f939-2642","\uD83E\uDD39\u200D\u2640":"1f939-2640","\uD83E\uDD3E\u200D\u2642":"1f93e-2642","\uD83E\uDD3E\u200D\u2640":"1f93e-2640","\uD83E\uDD3D\u200D\u2642":"1f93d-2642","\uD83E\uDD3D\u200D\u2640":"1f93d-2640","\uD83E\uDD38\u200D\u2642":"1f938-2642","\uD83E\uDD38\u200D\u2640":"1f938-2640","\uD83D\uDEB6\u200D\u2642":"1f6b6-2642","\uD83D\uDEB6\u200D\u2640":"1f6b6-2640","\uD83D\uDEB5\u200D\u2642":"1f6b5-2642","\uD83D\uDEB5\u200D\u2640":"1f6b5-2640","\uD83D\uDEB4\u200D\u2642":"1f6b4-2642","\uD83D\uDEB4\u200D\u2640":"1f6b4-2640","\uD83D\uDEA3\u200D\u2642":"1f6a3-2642","\uD83D\uDEA3\u200D\u2640":"1f6a3-2640","\uD83C\uDFCA\u200D\u2642":"1f3ca-2642","\uD83C\uDFCA\u200D\u2640":"1f3ca-2640","\uD83C\uDFC4\u200D\u2642":"1f3c4-2642","\uD83C\uDFC4\u200D\u2640":"1f3c4-2640","\uD83C\uDFC3\u200D\u2642":"1f3c3-2642","\uD83C\uDFC3\u200D\u2640":"1f3c3-2640","\uD83E\uDD37\u200D\u2642":"1f937-2642","\uD83E\uDD37\u200D\u2640":"1f937-2640","\uD83E\uDD26\u200D\u2642":"1f926-2642","\uD83E\uDD26\u200D\u2640":"1f926-2640","\uD83D\uDE4E\u200D\u2642":"1f64e-2642","\uD83D\uDE4E\u200D\u2640":"1f64e-2640","\uD83D\uDE4D\u200D\u2642":"1f64d-2642","\uD83D\uDE4D\u200D\u2640":"1f64d-2640","\uD83D\uDE4B\u200D\u2642":"1f64b-2642","\uD83D\uDE4B\u200D\u2640":"1f64b-2640","\uD83D\uDE47\u200D\u2642":"1f647-2642","\uD83D\uDE47\u200D\u2640":"1f647-2640","\uD83D\uDE46\u200D\u2642":"1f646-2642","\uD83D\uDE46\u200D\u2640":"1f646-2640","\uD83D\uDE45\u200D\u2642":"1f645-2642","\uD83D\uDE45\u200D\u2640":"1f645-2640","\uD83D\uDC87\u200D\u2642":"1f487-2642","\uD83D\uDC87\u200D\u2640":"1f487-2640","\uD83D\uDC86\u200D\u2642":"1f486-2642","\uD83D\uDC86\u200D\u2640":"1f486-2640","\uD83D\uDC81\u200D\u2642":"1f481-2642","\uD83D\uDC81\u200D\u2640":"1f481-2640","\uD83D\uDC71\u200D\u2642":"1f471-2642","\uD83D\uDC71\u200D\u2640":"1f471-2640","\uD83D\uDC73\u200D\u2642":"1f473-2642","\uD83D\uDC73\u200D\u2640":"1f473-2640","\uD83D\uDC82\u200D\u2642":"1f482-2642","\uD83D\uDC82\u200D\u2640":"1f482-2640","\uD83D\uDC77\u200D\u2642":"1f477-2642","\uD83D\uDC77\u200D\u2640":"1f477-2640","\uD83D\uDC6E\u200D\u2642":"1f46e-2642","\uD83D\uDC6E\u200D\u2640":"1f46e-2640","\uD83D\uDC68\u200D\u2695":"1f468-2695","\uD83D\uDC69\u200D\u2695":"1f469-2695","\uD83D\uDC68\u200D\u2696":"1f468-2696","\uD83D\uDC69\u200D\u2696":"1f469-2696","\uD83D\uDC68\u200D\u2708":"1f468-2708","\uD83D\uDC69\u200D\u2708":"1f469-2708","\u261D\uFE0F\uD83C\uDFFB":"261d-1f3fb","\u261D\uFE0F\uD83C\uDFFC":"261d-1f3fc","\u261D\uFE0F\uD83C\uDFFD":"261d-1f3fd","\u261D\uFE0F\uD83C\uDFFE":"261d-1f3fe","\u261D\uFE0F\uD83C\uDFFF":"261d-1f3ff","\u26F9\uFE0F\uD83C\uDFFB":"26f9-1f3fb","\u26F9\uFE0F\uD83C\uDFFC":"26f9-1f3fc","\u26F9\uFE0F\uD83C\uDFFD":"26f9-1f3fd","\u26F9\uFE0F\uD83C\uDFFE":"26f9-1f3fe","\u26F9\uFE0F\uD83C\uDFFF":"26f9-1f3ff","\u270C\uFE0F\uD83C\uDFFB":"270c-1f3fb","\u270C\uFE0F\uD83C\uDFFC":"270c-1f3fc","\u270C\uFE0F\uD83C\uDFFD":"270c-1f3fd","\u270C\uFE0F\uD83C\uDFFE":"270c-1f3fe","\u270C\uFE0F\uD83C\uDFFF":"270c-1f3ff","\u270D\uFE0F\uD83C\uDFFB":"270d-1f3fb","\u270D\uFE0F\uD83C\uDFFC":"270d-1f3fc","\u270D\uFE0F\uD83C\uDFFD":"270d-1f3fd","\u270D\uFE0F\uD83C\uDFFE":"270d-1f3fe","\u270D\uFE0F\uD83C\uDFFF":"270d-1f3ff","\uD83D\uDC68\u2695\uFE0F":"1f468-2695","\uD83D\uDC68\u2696\uFE0F":"1f468-2696","\uD83D\uDC68\u2708\uFE0F":"1f468-2708","\uD83D\uDC69\u2695\uFE0F":"1f469-2695","\uD83D\uDC69\u2696\uFE0F":"1f469-2696","\uD83D\uDC69\u2708\uFE0F":"1f469-2708","\uD83D\uDC6E\u2640\uFE0F":"1f46e-2640","\uD83D\uDC6E\u2642\uFE0F":"1f46e-2642","\uD83D\uDC71\u2640\uFE0F":"1f471-2640","\uD83D\uDC71\u2642\uFE0F":"1f471-2642","\uD83D\uDC73\u2640\uFE0F":"1f473-2640","\uD83D\uDC73\u2642\uFE0F":"1f473-2642","\uD83D\uDC77\u2640\uFE0F":"1f477-2640","\uD83D\uDC77\u2642\uFE0F":"1f477-2642","\uD83D\uDC82\u2640\uFE0F":"1f482-2640","\uD83D\uDC82\u2642\uFE0F":"1f482-2642","\uD83D\uDD75\u200D\u2640":"1f575-2640","\uD83D\uDD75\u200D\u2642":"1f575-2642","\uD83C\uDFC3\u2640\uFE0F":"1f3c3-2640","\uD83C\uDFC3\u2642\uFE0F":"1f3c3-2642","\uD83C\uDFC4\u2640\uFE0F":"1f3c4-2640","\uD83C\uDFC4\u2642\uFE0F":"1f3c4-2642","\uD83C\uDFCA\u2640\uFE0F":"1f3ca-2640","\uD83C\uDFCA\u2642\uFE0F":"1f3ca-2642","\uD83C\uDFCB\u200D\u2640":"1f3cb-2640","\uD83C\uDFCB\u200D\u2642":"1f3cb-2642","\uD83C\uDFCC\u200D\u2640":"1f3cc-2640","\uD83C\uDFCC\u200D\u2642":"1f3cc-2642","\uD83D\uDC6F\u2640\uFE0F":"1f46f-2640","\uD83D\uDC6F\u2642\uFE0F":"1f46f-2642","\uD83D\uDC86\u2640\uFE0F":"1f486-2640","\uD83D\uDC86\u2642\uFE0F":"1f486-2642","\uD83D\uDC87\u2640\uFE0F":"1f487-2640","\uD83D\uDC87\u2642\uFE0F":"1f487-2642","\uD83D\uDEA3\u2640\uFE0F":"1f6a3-2640","\uD83D\uDEA3\u2642\uFE0F":"1f6a3-2642","\uD83D\uDEB4\u2640\uFE0F":"1f6b4-2640","\uD83D\uDEB4\u2642\uFE0F":"1f6b4-2642","\uD83D\uDEB5\u2640\uFE0F":"1f6b5-2640","\uD83D\uDEB5\u2642\uFE0F":"1f6b5-2642","\uD83D\uDEB6\u2640\uFE0F":"1f6b6-2640","\uD83D\uDEB6\u2642\uFE0F":"1f6b6-2642","\uD83E\uDD38\u2640\uFE0F":"1f938-2640","\uD83E\uDD38\u2642\uFE0F":"1f938-2642","\uD83E\uDD39\u2640\uFE0F":"1f939-2640","\uD83E\uDD39\u2642\uFE0F":"1f939-2642","\uD83E\uDD3C\u2640\uFE0F":"1f93c-2640","\uD83E\uDD3C\u2642\uFE0F":"1f93c-2642","\uD83E\uDD3D\u2640\uFE0F":"1f93d-2640","\uD83E\uDD3D\u2642\uFE0F":"1f93d-2642","\uD83E\uDD3E\u2640\uFE0F":"1f93e-2640","\uD83E\uDD3E\u2642\uFE0F":"1f93e-2642","\uD83D\uDC81\u2640\uFE0F":"1f481-2640","\uD83D\uDC81\u2642\uFE0F":"1f481-2642","\uD83D\uDE45\u2640\uFE0F":"1f645-2640","\uD83D\uDE45\u2642\uFE0F":"1f645-2642","\uD83D\uDE46\u2640\uFE0F":"1f646-2640","\uD83D\uDE46\u2642\uFE0F":"1f646-2642","\uD83D\uDE47\u2640\uFE0F":"1f647-2640","\uD83D\uDE47\u2642\uFE0F":"1f647-2642","\uD83D\uDE4B\u2640\uFE0F":"1f64b-2640","\uD83D\uDE4B\u2642\uFE0F":"1f64b-2642","\uD83D\uDE4D\u2640\uFE0F":"1f64d-2640","\uD83D\uDE4D\u2642\uFE0F":"1f64d-2642","\uD83D\uDE4E\u2640\uFE0F":"1f64e-2640","\uD83D\uDE4E\u2642\uFE0F":"1f64e-2642","\uD83E\uDD26\u2640\uFE0F":"1f926-2640","\uD83E\uDD26\u2642\uFE0F":"1f926-2642","\uD83E\uDD37\u2640\uFE0F":"1f937-2640","\uD83E\uDD37\u2642\uFE0F":"1f937-2642","\uD83E\uDDD9\u200D\u2640":"1f9d9-2640","\uD83E\uDDD9\u2640\uFE0F":"1f9d9-2640","\uD83E\uDDD9\u200D\u2642":"1f9d9-2642","\uD83E\uDDD9\u2642\uFE0F":"1f9d9-2642","\uD83E\uDDDA\u200D\u2640":"1f9da-2640","\uD83E\uDDDA\u2640\uFE0F":"1f9da-2640","\uD83E\uDDDA\u200D\u2642":"1f9da-2642","\uD83E\uDDDA\u2642\uFE0F":"1f9da-2642","\uD83E\uDDDB\u200D\u2640":"1f9db-2640","\uD83E\uDDDB\u2640\uFE0F":"1f9db-2640","\uD83E\uDDDB\u200D\u2642":"1f9db-2642","\uD83E\uDDDB\u2642\uFE0F":"1f9db-2642","\uD83E\uDDDC\u200D\u2640":"1f9dc-2640","\uD83E\uDDDC\u2640\uFE0F":"1f9dc-2640","\uD83E\uDDDC\u200D\u2642":"1f9dc-2642","\uD83E\uDDDC\u2642\uFE0F":"1f9dc-2642","\uD83E\uDDDD\u200D\u2640":"1f9dd-2640","\uD83E\uDDDD\u2640\uFE0F":"1f9dd-2640","\uD83E\uDDDD\u200D\u2642":"1f9dd-2642","\uD83E\uDDDD\u2642\uFE0F":"1f9dd-2642","\uD83E\uDDDE\u200D\u2640":"1f9de-2640","\uD83E\uDDDE\u2640\uFE0F":"1f9de-2640","\uD83E\uDDDE\u200D\u2642":"1f9de-2642","\uD83E\uDDDE\u2642\uFE0F":"1f9de-2642","\uD83E\uDDDF\u200D\u2640":"1f9df-2640","\uD83E\uDDDF\u2640\uFE0F":"1f9df-2640","\uD83E\uDDDF\u200D\u2642":"1f9df-2642","\uD83E\uDDDF\u2642\uFE0F":"1f9df-2642","\uD83E\uDDD6\u200D\u2640":"1f9d6-2640","\uD83E\uDDD6\u2640\uFE0F":"1f9d6-2640","\uD83E\uDDD6\u200D\u2642":"1f9d6-2642","\uD83E\uDDD6\u2642\uFE0F":"1f9d6-2642","\uD83E\uDDD7\u200D\u2640":"1f9d7-2640","\uD83E\uDDD7\u2640\uFE0F":"1f9d7-2640","\uD83E\uDDD7\u200D\u2642":"1f9d7-2642","\uD83E\uDDD7\u2642\uFE0F":"1f9d7-2642","\uD83E\uDDD8\u200D\u2640":"1f9d8-2640","\uD83E\uDDD8\u2640\uFE0F":"1f9d8-2640","\uD83E\uDDD8\u200D\u2642":"1f9d8-2642","\uD83E\uDDD8\u2642\uFE0F":"1f9d8-2642","#\uFE0F\u20E3":"0023-20e3","0\uFE0F\u20E3":"0030-20e3","1\uFE0F\u20E3":"0031-20e3","2\uFE0F\u20E3":"0032-20e3","3\uFE0F\u20E3":"0033-20e3","4\uFE0F\u20E3":"0034-20e3","5\uFE0F\u20E3":"0035-20e3","6\uFE0F\u20E3":"0036-20e3","7\uFE0F\u20E3":"0037-20e3","8\uFE0F\u20E3":"0038-20e3","9\uFE0F\u20E3":"0039-20e3","*\uFE0F\u20E3":"002a-20e3","\u26F9\u200D\u2640":"26f9-2640","\u26F9\u200D\u2642":"26f9-2642","\uD83C\uDDE8\uD83C\uDDF3":"1f1e8-1f1f3","\uD83C\uDDE9\uD83C\uDDEA":"1f1e9-1f1ea","\uD83C\uDDEA\uD83C\uDDF8":"1f1ea-1f1f8","\uD83C\uDDEB\uD83C\uDDF7":"1f1eb-1f1f7","\uD83C\uDDEC\uD83C\uDDE7":"1f1ec-1f1e7","\uD83C\uDDEE\uD83C\uDDF9":"1f1ee-1f1f9","\uD83C\uDDEF\uD83C\uDDF5":"1f1ef-1f1f5","\uD83C\uDDF0\uD83C\uDDF7":"1f1f0-1f1f7","\uD83C\uDDFA\uD83C\uDDF8":"1f1fa-1f1f8","\uD83C\uDDF7\uD83C\uDDFA":"1f1f7-1f1fa","\uD83E\uDD34\uD83C\uDFFB":"1f934-1f3fb","\uD83E\uDD34\uD83C\uDFFC":"1f934-1f3fc","\uD83E\uDD34\uD83C\uDFFD":"1f934-1f3fd","\uD83E\uDD34\uD83C\uDFFE":"1f934-1f3fe","\uD83E\uDD34\uD83C\uDFFF":"1f934-1f3ff","\uD83E\uDD36\uD83C\uDFFB":"1f936-1f3fb","\uD83E\uDD36\uD83C\uDFFC":"1f936-1f3fc","\uD83E\uDD36\uD83C\uDFFD":"1f936-1f3fd","\uD83E\uDD36\uD83C\uDFFE":"1f936-1f3fe","\uD83E\uDD36\uD83C\uDFFF":"1f936-1f3ff","\uD83E\uDD35\uD83C\uDFFB":"1f935-1f3fb","\uD83E\uDD35\uD83C\uDFFC":"1f935-1f3fc","\uD83E\uDD35\uD83C\uDFFD":"1f935-1f3fd","\uD83E\uDD35\uD83C\uDFFE":"1f935-1f3fe","\uD83E\uDD35\uD83C\uDFFF":"1f935-1f3ff","\uD83E\uDD37\uD83C\uDFFB":"1f937-1f3fb","\uD83E\uDD37\uD83C\uDFFC":"1f937-1f3fc","\uD83E\uDD37\uD83C\uDFFD":"1f937-1f3fd","\uD83E\uDD37\uD83C\uDFFE":"1f937-1f3fe","\uD83E\uDD37\uD83C\uDFFF":"1f937-1f3ff","\uD83E\uDD26\uD83C\uDFFB":"1f926-1f3fb","\uD83E\uDD26\uD83C\uDFFC":"1f926-1f3fc","\uD83E\uDD26\uD83C\uDFFD":"1f926-1f3fd","\uD83E\uDD26\uD83C\uDFFE":"1f926-1f3fe","\uD83E\uDD26\uD83C\uDFFF":"1f926-1f3ff","\uD83E\uDD30\uD83C\uDFFB":"1f930-1f3fb","\uD83E\uDD30\uD83C\uDFFC":"1f930-1f3fc","\uD83E\uDD30\uD83C\uDFFD":"1f930-1f3fd","\uD83E\uDD30\uD83C\uDFFE":"1f930-1f3fe","\uD83E\uDD30\uD83C\uDFFF":"1f930-1f3ff","\uD83D\uDD7A\uD83C\uDFFB":"1f57a-1f3fb","\uD83D\uDD7A\uD83C\uDFFC":"1f57a-1f3fc","\uD83D\uDD7A\uD83C\uDFFD":"1f57a-1f3fd","\uD83D\uDD7A\uD83C\uDFFE":"1f57a-1f3fe","\uD83D\uDD7A\uD83C\uDFFF":"1f57a-1f3ff","\uD83E\uDD33\uD83C\uDFFB":"1f933-1f3fb","\uD83E\uDD33\uD83C\uDFFC":"1f933-1f3fc","\uD83E\uDD33\uD83C\uDFFD":"1f933-1f3fd","\uD83E\uDD33\uD83C\uDFFE":"1f933-1f3fe","\uD83E\uDD33\uD83C\uDFFF":"1f933-1f3ff","\uD83E\uDD1E\uD83C\uDFFB":"1f91e-1f3fb","\uD83E\uDD1E\uD83C\uDFFC":"1f91e-1f3fc","\uD83E\uDD1E\uD83C\uDFFD":"1f91e-1f3fd","\uD83E\uDD1E\uD83C\uDFFE":"1f91e-1f3fe","\uD83E\uDD1E\uD83C\uDFFF":"1f91e-1f3ff","\uD83E\uDD19\uD83C\uDFFB":"1f919-1f3fb","\uD83E\uDD19\uD83C\uDFFC":"1f919-1f3fc","\uD83E\uDD19\uD83C\uDFFD":"1f919-1f3fd","\uD83C\uDDE6\uD83C\uDDEB":"1f1e6-1f1eb","\uD83C\uDDE6\uD83C\uDDF1":"1f1e6-1f1f1","\uD83C\uDDE9\uD83C\uDDFF":"1f1e9-1f1ff","\uD83C\uDDE6\uD83C\uDDE9":"1f1e6-1f1e9","\uD83C\uDDE6\uD83C\uDDF4":"1f1e6-1f1f4","\uD83C\uDDE6\uD83C\uDDEC":"1f1e6-1f1ec","\uD83C\uDDE6\uD83C\uDDF7":"1f1e6-1f1f7","\uD83C\uDDE6\uD83C\uDDF2":"1f1e6-1f1f2","\uD83C\uDDE6\uD83C\uDDFA":"1f1e6-1f1fa","\uD83C\uDDE6\uD83C\uDDF9":"1f1e6-1f1f9","\uD83C\uDDE6\uD83C\uDDFF":"1f1e6-1f1ff","\uD83C\uDDE7\uD83C\uDDF8":"1f1e7-1f1f8","\uD83C\uDDE7\uD83C\uDDED":"1f1e7-1f1ed","\uD83C\uDDE7\uD83C\uDDE9":"1f1e7-1f1e9","\uD83C\uDDE7\uD83C\uDDE7":"1f1e7-1f1e7","\uD83C\uDDE7\uD83C\uDDFE":"1f1e7-1f1fe","\uD83C\uDDE7\uD83C\uDDEA":"1f1e7-1f1ea","\uD83C\uDDE7\uD83C\uDDFF":"1f1e7-1f1ff","\uD83C\uDDE7\uD83C\uDDEF":"1f1e7-1f1ef","\uD83C\uDDE7\uD83C\uDDF9":"1f1e7-1f1f9","\uD83C\uDDE7\uD83C\uDDF4":"1f1e7-1f1f4","\uD83C\uDDE7\uD83C\uDDE6":"1f1e7-1f1e6","\uD83C\uDDE7\uD83C\uDDFC":"1f1e7-1f1fc","\uD83C\uDDE7\uD83C\uDDF7":"1f1e7-1f1f7","\uD83C\uDDE7\uD83C\uDDF3":"1f1e7-1f1f3","\uD83C\uDDE7\uD83C\uDDEC":"1f1e7-1f1ec","\uD83C\uDDE7\uD83C\uDDEB":"1f1e7-1f1eb","\uD83C\uDDE7\uD83C\uDDEE":"1f1e7-1f1ee","\uD83C\uDDF0\uD83C\uDDED":"1f1f0-1f1ed","\uD83C\uDDE8\uD83C\uDDF2":"1f1e8-1f1f2","\uD83C\uDDE8\uD83C\uDDE6":"1f1e8-1f1e6","\uD83C\uDDE8\uD83C\uDDFB":"1f1e8-1f1fb","\uD83E\uDD19\uD83C\uDFFE":"1f919-1f3fe","\uD83C\uDDE8\uD83C\uDDEB":"1f1e8-1f1eb","\uD83C\uDDF9\uD83C\uDDE9":"1f1f9-1f1e9","\uD83C\uDDE8\uD83C\uDDF1":"1f1e8-1f1f1","\uD83C\uDDE8\uD83C\uDDF4":"1f1e8-1f1f4","\uD83C\uDDF0\uD83C\uDDF2":"1f1f0-1f1f2","\uD83C\uDDE8\uD83C\uDDF7":"1f1e8-1f1f7","\uD83C\uDDE8\uD83C\uDDEE":"1f1e8-1f1ee","\uD83C\uDDED\uD83C\uDDF7":"1f1ed-1f1f7","\uD83C\uDDE8\uD83C\uDDFA":"1f1e8-1f1fa","\uD83C\uDDE8\uD83C\uDDFE":"1f1e8-1f1fe","\uD83C\uDDE8\uD83C\uDDFF":"1f1e8-1f1ff","\uD83E\uDD19\uD83C\uDFFF":"1f919-1f3ff","\uD83C\uDDE8\uD83C\uDDE9":"1f1e8-1f1e9","\uD83E\uDD1B\uD83C\uDFFB":"1f91b-1f3fb","\uD83C\uDDE9\uD83C\uDDF0":"1f1e9-1f1f0","\uD83C\uDDE9\uD83C\uDDEF":"1f1e9-1f1ef","\uD83C\uDDE9\uD83C\uDDF2":"1f1e9-1f1f2","\uD83C\uDDE9\uD83C\uDDF4":"1f1e9-1f1f4","\uD83C\uDDF9\uD83C\uDDF1":"1f1f9-1f1f1","\uD83C\uDDEA\uD83C\uDDE8":"1f1ea-1f1e8","\uD83C\uDDEA\uD83C\uDDEC":"1f1ea-1f1ec","\uD83C\uDDF8\uD83C\uDDFB":"1f1f8-1f1fb","\uD83C\uDDEC\uD83C\uDDF6":"1f1ec-1f1f6","\uD83C\uDDEA\uD83C\uDDF7":"1f1ea-1f1f7","\uD83C\uDDEA\uD83C\uDDEA":"1f1ea-1f1ea","\uD83C\uDDEA\uD83C\uDDF9":"1f1ea-1f1f9","\uD83E\uDD1B\uD83C\uDFFC":"1f91b-1f3fc","\uD83C\uDDEB\uD83C\uDDEF":"1f1eb-1f1ef","\uD83C\uDDEB\uD83C\uDDEE":"1f1eb-1f1ee","\uD83C\uDDEC\uD83C\uDDE6":"1f1ec-1f1e6","\uD83C\uDDEC\uD83C\uDDF2":"1f1ec-1f1f2","\uD83C\uDDEC\uD83C\uDDEA":"1f1ec-1f1ea","\uD83C\uDDEC\uD83C\uDDED":"1f1ec-1f1ed","\uD83C\uDDEC\uD83C\uDDF7":"1f1ec-1f1f7","\uD83C\uDDEC\uD83C\uDDE9":"1f1ec-1f1e9","\uD83C\uDDEC\uD83C\uDDF9":"1f1ec-1f1f9","\uD83C\uDDEC\uD83C\uDDF3":"1f1ec-1f1f3","\uD83C\uDDEC\uD83C\uDDFC":"1f1ec-1f1fc","\uD83C\uDDEC\uD83C\uDDFE":"1f1ec-1f1fe","\uD83C\uDDED\uD83C\uDDF9":"1f1ed-1f1f9","\uD83C\uDDED\uD83C\uDDF3":"1f1ed-1f1f3","\uD83C\uDDED\uD83C\uDDFA":"1f1ed-1f1fa","\uD83C\uDDEE\uD83C\uDDF8":"1f1ee-1f1f8","\uD83C\uDDEE\uD83C\uDDF3":"1f1ee-1f1f3","\uD83C\uDDEE\uD83C\uDDE9":"1f1ee-1f1e9","\uD83C\uDDEE\uD83C\uDDF7":"1f1ee-1f1f7","\uD83C\uDDEE\uD83C\uDDF6":"1f1ee-1f1f6","\uD83C\uDDEE\uD83C\uDDEA":"1f1ee-1f1ea","\uD83C\uDDEE\uD83C\uDDF1":"1f1ee-1f1f1","\uD83C\uDDEF\uD83C\uDDF2":"1f1ef-1f1f2","\uD83C\uDDEF\uD83C\uDDF4":"1f1ef-1f1f4","\uD83C\uDDF0\uD83C\uDDFF":"1f1f0-1f1ff","\uD83C\uDDF0\uD83C\uDDEA":"1f1f0-1f1ea","\uD83C\uDDF0\uD83C\uDDEE":"1f1f0-1f1ee","\uD83C\uDDFD\uD83C\uDDF0":"1f1fd-1f1f0","\uD83C\uDDF0\uD83C\uDDFC":"1f1f0-1f1fc","\uD83C\uDDF0\uD83C\uDDEC":"1f1f0-1f1ec","\uD83E\uDD1B\uD83C\uDFFD":"1f91b-1f3fd","\uD83C\uDDF1\uD83C\uDDE6":"1f1f1-1f1e6","\uD83C\uDDF1\uD83C\uDDFB":"1f1f1-1f1fb","\uD83C\uDDF1\uD83C\uDDE7":"1f1f1-1f1e7","\uD83C\uDDF1\uD83C\uDDF8":"1f1f1-1f1f8","\uD83C\uDDF1\uD83C\uDDF7":"1f1f1-1f1f7","\uD83C\uDDF1\uD83C\uDDFE":"1f1f1-1f1fe","\uD83C\uDDF1\uD83C\uDDEE":"1f1f1-1f1ee","\uD83C\uDDF1\uD83C\uDDF9":"1f1f1-1f1f9","\uD83C\uDDF1\uD83C\uDDFA":"1f1f1-1f1fa","\uD83C\uDDF2\uD83C\uDDF0":"1f1f2-1f1f0","\uD83C\uDDF2\uD83C\uDDEC":"1f1f2-1f1ec","\uD83C\uDDF2\uD83C\uDDFC":"1f1f2-1f1fc","\uD83C\uDDF2\uD83C\uDDFE":"1f1f2-1f1fe","\uD83C\uDDF2\uD83C\uDDFB":"1f1f2-1f1fb","\uD83C\uDDF2\uD83C\uDDF1":"1f1f2-1f1f1","\uD83C\uDDF2\uD83C\uDDF9":"1f1f2-1f1f9","\uD83C\uDDF2\uD83C\uDDED":"1f1f2-1f1ed","\uD83C\uDDF2\uD83C\uDDF7":"1f1f2-1f1f7","\uD83C\uDDF2\uD83C\uDDFA":"1f1f2-1f1fa","\uD83C\uDDF2\uD83C\uDDFD":"1f1f2-1f1fd","\uD83C\uDDEB\uD83C\uDDF2":"1f1eb-1f1f2","\uD83C\uDDF2\uD83C\uDDE9":"1f1f2-1f1e9","\uD83C\uDDF2\uD83C\uDDE8":"1f1f2-1f1e8","\uD83C\uDDF2\uD83C\uDDF3":"1f1f2-1f1f3","\uD83C\uDDF2\uD83C\uDDEA":"1f1f2-1f1ea","\uD83C\uDDF2\uD83C\uDDE6":"1f1f2-1f1e6","\uD83C\uDDF2\uD83C\uDDFF":"1f1f2-1f1ff","\uD83C\uDDF2\uD83C\uDDF2":"1f1f2-1f1f2","\uD83C\uDDF3\uD83C\uDDE6":"1f1f3-1f1e6","\uD83C\uDDF3\uD83C\uDDF7":"1f1f3-1f1f7","\uD83C\uDDF3\uD83C\uDDF5":"1f1f3-1f1f5","\uD83C\uDDF3\uD83C\uDDF1":"1f1f3-1f1f1","\uD83C\uDDF3\uD83C\uDDFF":"1f1f3-1f1ff","\uD83C\uDDF3\uD83C\uDDEE":"1f1f3-1f1ee","\uD83C\uDDF3\uD83C\uDDEA":"1f1f3-1f1ea","\uD83C\uDDF3\uD83C\uDDEC":"1f1f3-1f1ec","\uD83C\uDDF0\uD83C\uDDF5":"1f1f0-1f1f5","\uD83C\uDDF3\uD83C\uDDF4":"1f1f3-1f1f4","\uD83C\uDDF4\uD83C\uDDF2":"1f1f4-1f1f2","\uD83C\uDDF5\uD83C\uDDF0":"1f1f5-1f1f0","\uD83C\uDDF5\uD83C\uDDFC":"1f1f5-1f1fc","\uD83C\uDDF5\uD83C\uDDE6":"1f1f5-1f1e6","\uD83C\uDDF5\uD83C\uDDEC":"1f1f5-1f1ec","\uD83E\uDD1B\uD83C\uDFFE":"1f91b-1f3fe","\uD83C\uDDF5\uD83C\uDDFE":"1f1f5-1f1fe","\uD83C\uDDF5\uD83C\uDDEA":"1f1f5-1f1ea","\uD83C\uDDF5\uD83C\uDDED":"1f1f5-1f1ed","\uD83C\uDDF5\uD83C\uDDF1":"1f1f5-1f1f1","\uD83C\uDDF5\uD83C\uDDF9":"1f1f5-1f1f9","\uD83C\uDDF6\uD83C\uDDE6":"1f1f6-1f1e6","\uD83C\uDDF9\uD83C\uDDFC":"1f1f9-1f1fc","\uD83C\uDDE8\uD83C\uDDEC":"1f1e8-1f1ec","\uD83C\uDDF7\uD83C\uDDF4":"1f1f7-1f1f4","\uD83C\uDDF7\uD83C\uDDFC":"1f1f7-1f1fc","\uD83C\uDDF0\uD83C\uDDF3":"1f1f0-1f1f3","\uD83C\uDDF1\uD83C\uDDE8":"1f1f1-1f1e8","\uD83C\uDDFB\uD83C\uDDE8":"1f1fb-1f1e8","\uD83C\uDDFC\uD83C\uDDF8":"1f1fc-1f1f8","\uD83C\uDDF8\uD83C\uDDF2":"1f1f8-1f1f2","\uD83C\uDDF8\uD83C\uDDF9":"1f1f8-1f1f9","\uD83C\uDDF8\uD83C\uDDE6":"1f1f8-1f1e6","\uD83E\uDD1B\uD83C\uDFFF":"1f91b-1f3ff","\uD83C\uDDF8\uD83C\uDDF3":"1f1f8-1f1f3","\uD83C\uDDF7\uD83C\uDDF8":"1f1f7-1f1f8","\uD83C\uDDF8\uD83C\uDDE8":"1f1f8-1f1e8","\uD83C\uDDF8\uD83C\uDDF1":"1f1f8-1f1f1","\uD83C\uDDF8\uD83C\uDDEC":"1f1f8-1f1ec","\uD83C\uDDF8\uD83C\uDDF0":"1f1f8-1f1f0","\uD83C\uDDF8\uD83C\uDDEE":"1f1f8-1f1ee","\uD83C\uDDF8\uD83C\uDDE7":"1f1f8-1f1e7","\uD83C\uDDF8\uD83C\uDDF4":"1f1f8-1f1f4","\uD83C\uDDFF\uD83C\uDDE6":"1f1ff-1f1e6","\uD83C\uDDF1\uD83C\uDDF0":"1f1f1-1f1f0","\uD83C\uDDF8\uD83C\uDDE9":"1f1f8-1f1e9","\uD83C\uDDF8\uD83C\uDDF7":"1f1f8-1f1f7","\uD83C\uDDF8\uD83C\uDDFF":"1f1f8-1f1ff","\uD83C\uDDF8\uD83C\uDDEA":"1f1f8-1f1ea","\uD83C\uDDE8\uD83C\uDDED":"1f1e8-1f1ed","\uD83C\uDDF8\uD83C\uDDFE":"1f1f8-1f1fe","\uD83C\uDDF9\uD83C\uDDEF":"1f1f9-1f1ef","\uD83C\uDDF9\uD83C\uDDFF":"1f1f9-1f1ff","\uD83C\uDDF9\uD83C\uDDED":"1f1f9-1f1ed","\uD83C\uDDF9\uD83C\uDDEC":"1f1f9-1f1ec","\uD83C\uDDF9\uD83C\uDDF4":"1f1f9-1f1f4","\uD83C\uDDF9\uD83C\uDDF9":"1f1f9-1f1f9","\uD83C\uDDF9\uD83C\uDDF3":"1f1f9-1f1f3","\uD83C\uDDF9\uD83C\uDDF7":"1f1f9-1f1f7","\uD83C\uDDF9\uD83C\uDDF2":"1f1f9-1f1f2","\uD83C\uDDF9\uD83C\uDDFB":"1f1f9-1f1fb","\uD83C\uDDFA\uD83C\uDDEC":"1f1fa-1f1ec","\uD83C\uDDFA\uD83C\uDDE6":"1f1fa-1f1e6","\uD83C\uDDE6\uD83C\uDDEA":"1f1e6-1f1ea","\uD83C\uDDFA\uD83C\uDDFE":"1f1fa-1f1fe","\uD83C\uDDFA\uD83C\uDDFF":"1f1fa-1f1ff","\uD83C\uDDFB\uD83C\uDDFA":"1f1fb-1f1fa","\uD83C\uDDFB\uD83C\uDDE6":"1f1fb-1f1e6","\uD83C\uDDFB\uD83C\uDDEA":"1f1fb-1f1ea","\uD83C\uDDFB\uD83C\uDDF3":"1f1fb-1f1f3","\uD83C\uDDEA\uD83C\uDDED":"1f1ea-1f1ed","\uD83E\uDD1C\uD83C\uDFFB":"1f91c-1f3fb","\uD83C\uDDFE\uD83C\uDDEA":"1f1fe-1f1ea","\uD83C\uDDFF\uD83C\uDDF2":"1f1ff-1f1f2","\uD83C\uDDFF\uD83C\uDDFC":"1f1ff-1f1fc","\uD83C\uDDF5\uD83C\uDDF7":"1f1f5-1f1f7","\uD83C\uDDF0\uD83C\uDDFE":"1f1f0-1f1fe","\uD83C\uDDE7\uD83C\uDDF2":"1f1e7-1f1f2","\uD83C\uDDF5\uD83C\uDDEB":"1f1f5-1f1eb","\uD83C\uDDF5\uD83C\uDDF8":"1f1f5-1f1f8","\uD83C\uDDF3\uD83C\uDDE8":"1f1f3-1f1e8","\uD83E\uDD1C\uD83C\uDFFC":"1f91c-1f3fc","\uD83C\uDDF8\uD83C\uDDED":"1f1f8-1f1ed","\uD83C\uDDE6\uD83C\uDDFC":"1f1e6-1f1fc","\uD83C\uDDFB\uD83C\uDDEE":"1f1fb-1f1ee","\uD83C\uDDED\uD83C\uDDF0":"1f1ed-1f1f0","\uD83C\uDDE6\uD83C\uDDE8":"1f1e6-1f1e8","\uD83C\uDDF2\uD83C\uDDF8":"1f1f2-1f1f8","\uD83C\uDDEC\uD83C\uDDFA":"1f1ec-1f1fa","\uD83C\uDDEC\uD83C\uDDF1":"1f1ec-1f1f1","\uD83C\uDDF3\uD83C\uDDFA":"1f1f3-1f1fa","\uD83C\uDDFC\uD83C\uDDEB":"1f1fc-1f1eb","\uD83C\uDDF2\uD83C\uDDF4":"1f1f2-1f1f4","\uD83E\uDD1C\uD83C\uDFFD":"1f91c-1f3fd","\uD83C\uDDEB\uD83C\uDDF4":"1f1eb-1f1f4","\uD83C\uDDEB\uD83C\uDDF0":"1f1eb-1f1f0","\uD83C\uDDEF\uD83C\uDDEA":"1f1ef-1f1ea","\uD83C\uDDE6\uD83C\uDDEE":"1f1e6-1f1ee","\uD83C\uDDEC\uD83C\uDDEE":"1f1ec-1f1ee","\uD83E\uDD1C\uD83C\uDFFE":"1f91c-1f3fe","\uD83E\uDD1C\uD83C\uDFFF":"1f91c-1f3ff","\uD83E\uDD1A\uD83C\uDFFB":"1f91a-1f3fb","\uD83E\uDD1A\uD83C\uDFFC":"1f91a-1f3fc","\uD83E\uDD1A\uD83C\uDFFD":"1f91a-1f3fd","\uD83E\uDD1A\uD83C\uDFFE":"1f91a-1f3fe","\uD83D\uDC76\uD83C\uDFFB":"1f476-1f3fb","\uD83D\uDC76\uD83C\uDFFC":"1f476-1f3fc","\uD83D\uDC76\uD83C\uDFFD":"1f476-1f3fd","\uD83D\uDC76\uD83C\uDFFE":"1f476-1f3fe","\uD83D\uDC76\uD83C\uDFFF":"1f476-1f3ff","\uD83D\uDC66\uD83C\uDFFB":"1f466-1f3fb","\uD83D\uDC66\uD83C\uDFFC":"1f466-1f3fc","\uD83D\uDC66\uD83C\uDFFD":"1f466-1f3fd","\uD83D\uDC66\uD83C\uDFFE":"1f466-1f3fe","\uD83D\uDC66\uD83C\uDFFF":"1f466-1f3ff","\uD83D\uDC67\uD83C\uDFFB":"1f467-1f3fb","\uD83D\uDC67\uD83C\uDFFC":"1f467-1f3fc","\uD83D\uDC67\uD83C\uDFFD":"1f467-1f3fd","\uD83D\uDC67\uD83C\uDFFE":"1f467-1f3fe","\uD83D\uDC67\uD83C\uDFFF":"1f467-1f3ff","\uD83D\uDC68\uD83C\uDFFB":"1f468-1f3fb","\uD83D\uDC68\uD83C\uDFFC":"1f468-1f3fc","\uD83D\uDC68\uD83C\uDFFD":"1f468-1f3fd","\uD83D\uDC68\uD83C\uDFFE":"1f468-1f3fe","\uD83D\uDC68\uD83C\uDFFF":"1f468-1f3ff","\uD83D\uDC69\uD83C\uDFFB":"1f469-1f3fb","\uD83D\uDC69\uD83C\uDFFC":"1f469-1f3fc","\uD83D\uDC69\uD83C\uDFFD":"1f469-1f3fd","\uD83D\uDC69\uD83C\uDFFE":"1f469-1f3fe","\uD83D\uDC69\uD83C\uDFFF":"1f469-1f3ff","\uD83D\uDC70\uD83C\uDFFB":"1f470-1f3fb","\uD83D\uDC70\uD83C\uDFFC":"1f470-1f3fc","\uD83E\uDD1A\uD83C\uDFFF":"1f91a-1f3ff","\uD83D\uDC70\uD83C\uDFFD":"1f470-1f3fd","\uD83D\uDC70\uD83C\uDFFE":"1f470-1f3fe","\uD83D\uDC70\uD83C\uDFFF":"1f470-1f3ff","\uD83D\uDC71\uD83C\uDFFB":"1f471-1f3fb","\uD83D\uDC71\uD83C\uDFFC":"1f471-1f3fc","\uD83D\uDC71\uD83C\uDFFD":"1f471-1f3fd","\uD83D\uDC71\uD83C\uDFFE":"1f471-1f3fe","\uD83D\uDC71\uD83C\uDFFF":"1f471-1f3ff","\uD83D\uDC72\uD83C\uDFFB":"1f472-1f3fb","\uD83D\uDC72\uD83C\uDFFC":"1f472-1f3fc","\uD83D\uDC72\uD83C\uDFFD":"1f472-1f3fd","\uD83D\uDC72\uD83C\uDFFE":"1f472-1f3fe","\uD83D\uDC72\uD83C\uDFFF":"1f472-1f3ff","\uD83D\uDC73\uD83C\uDFFB":"1f473-1f3fb","\uD83D\uDC73\uD83C\uDFFC":"1f473-1f3fc","\uD83D\uDC73\uD83C\uDFFD":"1f473-1f3fd","\uD83D\uDC73\uD83C\uDFFE":"1f473-1f3fe","\uD83D\uDC73\uD83C\uDFFF":"1f473-1f3ff","\uD83D\uDC74\uD83C\uDFFB":"1f474-1f3fb","\uD83D\uDC74\uD83C\uDFFC":"1f474-1f3fc","\uD83D\uDC74\uD83C\uDFFD":"1f474-1f3fd","\uD83D\uDC74\uD83C\uDFFE":"1f474-1f3fe","\uD83D\uDC74\uD83C\uDFFF":"1f474-1f3ff","\uD83D\uDC75\uD83C\uDFFB":"1f475-1f3fb","\uD83D\uDC75\uD83C\uDFFC":"1f475-1f3fc","\uD83D\uDC75\uD83C\uDFFD":"1f475-1f3fd","\uD83D\uDC75\uD83C\uDFFE":"1f475-1f3fe","\uD83D\uDC75\uD83C\uDFFF":"1f475-1f3ff","\uD83D\uDC6E\uD83C\uDFFB":"1f46e-1f3fb","\uD83D\uDC6E\uD83C\uDFFC":"1f46e-1f3fc","\uD83D\uDC6E\uD83C\uDFFD":"1f46e-1f3fd","\uD83D\uDC6E\uD83C\uDFFE":"1f46e-1f3fe","\uD83D\uDC6E\uD83C\uDFFF":"1f46e-1f3ff","\uD83D\uDC77\uD83C\uDFFB":"1f477-1f3fb","\uD83D\uDC77\uD83C\uDFFC":"1f477-1f3fc","\uD83D\uDC77\uD83C\uDFFD":"1f477-1f3fd","\uD83D\uDC77\uD83C\uDFFE":"1f477-1f3fe","\uD83D\uDC77\uD83C\uDFFF":"1f477-1f3ff","\uD83D\uDC78\uD83C\uDFFB":"1f478-1f3fb","\uD83D\uDC78\uD83C\uDFFC":"1f478-1f3fc","\uD83D\uDC78\uD83C\uDFFD":"1f478-1f3fd","\uD83D\uDC78\uD83C\uDFFE":"1f478-1f3fe","\uD83E\uDD38\uD83C\uDFFB":"1f938-1f3fb","\uD83D\uDC78\uD83C\uDFFF":"1f478-1f3ff","\uD83D\uDC82\uD83C\uDFFB":"1f482-1f3fb","\uD83D\uDC82\uD83C\uDFFC":"1f482-1f3fc","\uD83E\uDD38\uD83C\uDFFC":"1f938-1f3fc","\uD83D\uDC82\uD83C\uDFFD":"1f482-1f3fd","\uD83D\uDC82\uD83C\uDFFE":"1f482-1f3fe","\uD83D\uDC82\uD83C\uDFFF":"1f482-1f3ff","\uD83E\uDD38\uD83C\uDFFD":"1f938-1f3fd","\uD83D\uDC7C\uD83C\uDFFB":"1f47c-1f3fb","\uD83D\uDC7C\uD83C\uDFFC":"1f47c-1f3fc","\uD83D\uDC7C\uD83C\uDFFD":"1f47c-1f3fd","\uD83D\uDC7C\uD83C\uDFFE":"1f47c-1f3fe","\uD83D\uDC7C\uD83C\uDFFF":"1f47c-1f3ff","\uD83D\uDE47\uD83C\uDFFB":"1f647-1f3fb","\uD83D\uDE47\uD83C\uDFFC":"1f647-1f3fc","\uD83D\uDE47\uD83C\uDFFD":"1f647-1f3fd","\uD83D\uDE47\uD83C\uDFFE":"1f647-1f3fe","\uD83D\uDE47\uD83C\uDFFF":"1f647-1f3ff","\uD83D\uDC81\uD83C\uDFFB":"1f481-1f3fb","\uD83D\uDC81\uD83C\uDFFC":"1f481-1f3fc","\uD83D\uDC81\uD83C\uDFFD":"1f481-1f3fd","\uD83E\uDD38\uD83C\uDFFE":"1f938-1f3fe","\uD83D\uDC81\uD83C\uDFFE":"1f481-1f3fe","\uD83D\uDC81\uD83C\uDFFF":"1f481-1f3ff","\uD83D\uDE45\uD83C\uDFFB":"1f645-1f3fb","\uD83E\uDD38\uD83C\uDFFF":"1f938-1f3ff","\uD83D\uDE45\uD83C\uDFFC":"1f645-1f3fc","\uD83D\uDE45\uD83C\uDFFD":"1f645-1f3fd","\uD83D\uDE45\uD83C\uDFFE":"1f645-1f3fe","\uD83D\uDE45\uD83C\uDFFF":"1f645-1f3ff","\uD83D\uDE46\uD83C\uDFFB":"1f646-1f3fb","\uD83D\uDE46\uD83C\uDFFC":"1f646-1f3fc","\uD83D\uDE46\uD83C\uDFFD":"1f646-1f3fd","\uD83D\uDE46\uD83C\uDFFE":"1f646-1f3fe","\uD83D\uDE46\uD83C\uDFFF":"1f646-1f3ff","\uD83D\uDE4B\uD83C\uDFFB":"1f64b-1f3fb","\uD83D\uDE4B\uD83C\uDFFC":"1f64b-1f3fc","\uD83D\uDE4B\uD83C\uDFFD":"1f64b-1f3fd","\uD83D\uDE4B\uD83C\uDFFE":"1f64b-1f3fe","\uD83D\uDE4B\uD83C\uDFFF":"1f64b-1f3ff","\uD83D\uDE4E\uD83C\uDFFB":"1f64e-1f3fb","\uD83D\uDE4E\uD83C\uDFFC":"1f64e-1f3fc","\uD83D\uDE4E\uD83C\uDFFD":"1f64e-1f3fd","\uD83D\uDE4E\uD83C\uDFFE":"1f64e-1f3fe","\uD83D\uDE4E\uD83C\uDFFF":"1f64e-1f3ff","\uD83D\uDE4D\uD83C\uDFFB":"1f64d-1f3fb","\uD83D\uDE4D\uD83C\uDFFC":"1f64d-1f3fc","\uD83D\uDE4D\uD83C\uDFFD":"1f64d-1f3fd","\uD83D\uDE4D\uD83C\uDFFE":"1f64d-1f3fe","\uD83D\uDE4D\uD83C\uDFFF":"1f64d-1f3ff","\uD83D\uDC86\uD83C\uDFFB":"1f486-1f3fb","\uD83D\uDC86\uD83C\uDFFC":"1f486-1f3fc","\uD83D\uDC86\uD83C\uDFFD":"1f486-1f3fd","\uD83D\uDC86\uD83C\uDFFE":"1f486-1f3fe","\uD83D\uDC86\uD83C\uDFFF":"1f486-1f3ff","\uD83D\uDC87\uD83C\uDFFB":"1f487-1f3fb","\uD83D\uDC87\uD83C\uDFFC":"1f487-1f3fc","\uD83D\uDC87\uD83C\uDFFD":"1f487-1f3fd","\uD83D\uDC87\uD83C\uDFFE":"1f487-1f3fe","\uD83D\uDC87\uD83C\uDFFF":"1f487-1f3ff","\uD83D\uDE4C\uD83C\uDFFB":"1f64c-1f3fb","\uD83D\uDE4C\uD83C\uDFFC":"1f64c-1f3fc","\uD83D\uDE4C\uD83C\uDFFD":"1f64c-1f3fd","\uD83D\uDE4C\uD83C\uDFFE":"1f64c-1f3fe","\uD83D\uDE4C\uD83C\uDFFF":"1f64c-1f3ff","\uD83D\uDC4F\uD83C\uDFFB":"1f44f-1f3fb","\uD83D\uDC4F\uD83C\uDFFC":"1f44f-1f3fc","\uD83D\uDC4F\uD83C\uDFFD":"1f44f-1f3fd","\uD83E\uDD3D\uD83C\uDFFB":"1f93d-1f3fb","\uD83D\uDC4F\uD83C\uDFFE":"1f44f-1f3fe","\uD83D\uDC4F\uD83C\uDFFF":"1f44f-1f3ff","\uD83E\uDD3D\uD83C\uDFFC":"1f93d-1f3fc","\uD83D\uDC42\uD83C\uDFFB":"1f442-1f3fb","\uD83D\uDC42\uD83C\uDFFC":"1f442-1f3fc","\uD83D\uDC42\uD83C\uDFFD":"1f442-1f3fd","\uD83D\uDC42\uD83C\uDFFE":"1f442-1f3fe","\uD83D\uDC42\uD83C\uDFFF":"1f442-1f3ff","\uD83D\uDC43\uD83C\uDFFB":"1f443-1f3fb","\uD83D\uDC43\uD83C\uDFFC":"1f443-1f3fc","\uD83D\uDC43\uD83C\uDFFD":"1f443-1f3fd","\uD83D\uDC43\uD83C\uDFFE":"1f443-1f3fe","\uD83D\uDC43\uD83C\uDFFF":"1f443-1f3ff","\uD83D\uDC85\uD83C\uDFFB":"1f485-1f3fb","\uD83D\uDC85\uD83C\uDFFC":"1f485-1f3fc","\uD83D\uDC85\uD83C\uDFFD":"1f485-1f3fd","\uD83D\uDC85\uD83C\uDFFE":"1f485-1f3fe","\uD83D\uDC85\uD83C\uDFFF":"1f485-1f3ff","\uD83D\uDC4B\uD83C\uDFFB":"1f44b-1f3fb","\uD83D\uDC4B\uD83C\uDFFC":"1f44b-1f3fc","\uD83D\uDC4B\uD83C\uDFFD":"1f44b-1f3fd","\uD83D\uDC4B\uD83C\uDFFE":"1f44b-1f3fe","\uD83D\uDC4B\uD83C\uDFFF":"1f44b-1f3ff","\uD83D\uDC4D\uD83C\uDFFB":"1f44d-1f3fb","\uD83D\uDC4D\uD83C\uDFFC":"1f44d-1f3fc","\uD83D\uDC4D\uD83C\uDFFD":"1f44d-1f3fd","\uD83D\uDC4D\uD83C\uDFFE":"1f44d-1f3fe","\uD83D\uDC4D\uD83C\uDFFF":"1f44d-1f3ff","\uD83D\uDC4E\uD83C\uDFFB":"1f44e-1f3fb","\uD83D\uDC4E\uD83C\uDFFC":"1f44e-1f3fc","\uD83D\uDC4E\uD83C\uDFFD":"1f44e-1f3fd","\uD83D\uDC4E\uD83C\uDFFE":"1f44e-1f3fe","\uD83D\uDC4E\uD83C\uDFFF":"1f44e-1f3ff","\uD83D\uDC46\uD83C\uDFFB":"1f446-1f3fb","\uD83D\uDC46\uD83C\uDFFC":"1f446-1f3fc","\uD83D\uDC46\uD83C\uDFFD":"1f446-1f3fd","\uD83D\uDC46\uD83C\uDFFE":"1f446-1f3fe","\uD83D\uDC46\uD83C\uDFFF":"1f446-1f3ff","\uD83D\uDC47\uD83C\uDFFB":"1f447-1f3fb","\uD83D\uDC47\uD83C\uDFFC":"1f447-1f3fc","\uD83D\uDC47\uD83C\uDFFD":"1f447-1f3fd","\uD83D\uDC47\uD83C\uDFFE":"1f447-1f3fe","\uD83D\uDC47\uD83C\uDFFF":"1f447-1f3ff","\uD83D\uDC48\uD83C\uDFFB":"1f448-1f3fb","\uD83D\uDC48\uD83C\uDFFC":"1f448-1f3fc","\uD83D\uDC48\uD83C\uDFFD":"1f448-1f3fd","\uD83D\uDC48\uD83C\uDFFE":"1f448-1f3fe","\uD83D\uDC48\uD83C\uDFFF":"1f448-1f3ff","\uD83D\uDC49\uD83C\uDFFB":"1f449-1f3fb","\uD83D\uDC49\uD83C\uDFFC":"1f449-1f3fc","\uD83D\uDC49\uD83C\uDFFD":"1f449-1f3fd","\uD83D\uDC49\uD83C\uDFFE":"1f449-1f3fe","\uD83D\uDC49\uD83C\uDFFF":"1f449-1f3ff","\uD83D\uDC4C\uD83C\uDFFB":"1f44c-1f3fb","\uD83D\uDC4C\uD83C\uDFFC":"1f44c-1f3fc","\uD83E\uDD3D\uD83C\uDFFD":"1f93d-1f3fd","\uD83D\uDC4C\uD83C\uDFFD":"1f44c-1f3fd","\uD83D\uDC4C\uD83C\uDFFE":"1f44c-1f3fe","\uD83E\uDD3D\uD83C\uDFFE":"1f93d-1f3fe","\uD83D\uDC4C\uD83C\uDFFF":"1f44c-1f3ff","\uD83D\uDC4A\uD83C\uDFFB":"1f44a-1f3fb","\uD83D\uDC4A\uD83C\uDFFC":"1f44a-1f3fc","\uD83D\uDC4A\uD83C\uDFFD":"1f44a-1f3fd","\uD83D\uDC4A\uD83C\uDFFE":"1f44a-1f3fe","\uD83D\uDC4A\uD83C\uDFFF":"1f44a-1f3ff","\uD83D\uDCAA\uD83C\uDFFB":"1f4aa-1f3fb","\uD83D\uDCAA\uD83C\uDFFC":"1f4aa-1f3fc","\uD83D\uDCAA\uD83C\uDFFD":"1f4aa-1f3fd","\uD83D\uDCAA\uD83C\uDFFE":"1f4aa-1f3fe","\uD83D\uDCAA\uD83C\uDFFF":"1f4aa-1f3ff","\uD83D\uDC50\uD83C\uDFFB":"1f450-1f3fb","\uD83D\uDC50\uD83C\uDFFC":"1f450-1f3fc","\uD83D\uDC50\uD83C\uDFFD":"1f450-1f3fd","\uD83D\uDC50\uD83C\uDFFE":"1f450-1f3fe","\uD83D\uDC50\uD83C\uDFFF":"1f450-1f3ff","\uD83D\uDE4F\uD83C\uDFFB":"1f64f-1f3fb","\uD83E\uDD3D\uD83C\uDFFF":"1f93d-1f3ff","\uD83D\uDE4F\uD83C\uDFFC":"1f64f-1f3fc","\uD83D\uDE4F\uD83C\uDFFD":"1f64f-1f3fd","\uD83E\uDD3E\uD83C\uDFFB":"1f93e-1f3fb","\uD83D\uDE4F\uD83C\uDFFE":"1f64f-1f3fe","\uD83D\uDE4F\uD83C\uDFFF":"1f64f-1f3ff","\uD83E\uDD3E\uD83C\uDFFC":"1f93e-1f3fc","\uD83C\uDFC3\uD83C\uDFFB":"1f3c3-1f3fb","\uD83C\uDFC3\uD83C\uDFFC":"1f3c3-1f3fc","\uD83C\uDFC3\uD83C\uDFFD":"1f3c3-1f3fd","\uD83C\uDFC3\uD83C\uDFFE":"1f3c3-1f3fe","\uD83E\uDD3E\uD83C\uDFFD":"1f93e-1f3fd","\uD83C\uDFC3\uD83C\uDFFF":"1f3c3-1f3ff","\uD83D\uDEB6\uD83C\uDFFB":"1f6b6-1f3fb","\uD83D\uDEB6\uD83C\uDFFC":"1f6b6-1f3fc","\uD83D\uDEB6\uD83C\uDFFD":"1f6b6-1f3fd","\uD83D\uDEB6\uD83C\uDFFE":"1f6b6-1f3fe","\uD83D\uDEB6\uD83C\uDFFF":"1f6b6-1f3ff","\uD83D\uDC83\uD83C\uDFFB":"1f483-1f3fb","\uD83E\uDD3E\uD83C\uDFFE":"1f93e-1f3fe","\uD83D\uDC83\uD83C\uDFFC":"1f483-1f3fc","\uD83D\uDC83\uD83C\uDFFD":"1f483-1f3fd","\uD83E\uDD3E\uD83C\uDFFF":"1f93e-1f3ff","\uD83D\uDC83\uD83C\uDFFE":"1f483-1f3fe","\uD83D\uDC83\uD83C\uDFFF":"1f483-1f3ff","\uD83E\uDD39\uD83C\uDFFB":"1f939-1f3fb","\uD83D\uDEA3\uD83C\uDFFB":"1f6a3-1f3fb","\uD83D\uDEA3\uD83C\uDFFC":"1f6a3-1f3fc","\uD83D\uDEA3\uD83C\uDFFD":"1f6a3-1f3fd","\uD83D\uDEA3\uD83C\uDFFE":"1f6a3-1f3fe","\uD83D\uDEA3\uD83C\uDFFF":"1f6a3-1f3ff","\uD83C\uDFCA\uD83C\uDFFB":"1f3ca-1f3fb","\uD83C\uDFCA\uD83C\uDFFC":"1f3ca-1f3fc","\uD83E\uDD39\uD83C\uDFFC":"1f939-1f3fc","\uD83C\uDFCA\uD83C\uDFFD":"1f3ca-1f3fd","\uD83C\uDFCA\uD83C\uDFFE":"1f3ca-1f3fe","\uD83C\uDFCA\uD83C\uDFFF":"1f3ca-1f3ff","\uD83E\uDD39\uD83C\uDFFD":"1f939-1f3fd","\uD83C\uDFC4\uD83C\uDFFB":"1f3c4-1f3fb","\uD83C\uDFC4\uD83C\uDFFC":"1f3c4-1f3fc","\uD83C\uDFC4\uD83C\uDFFD":"1f3c4-1f3fd","\uD83C\uDFC4\uD83C\uDFFE":"1f3c4-1f3fe","\uD83C\uDFC4\uD83C\uDFFF":"1f3c4-1f3ff","\uD83D\uDEC0\uD83C\uDFFB":"1f6c0-1f3fb","\uD83D\uDEC0\uD83C\uDFFC":"1f6c0-1f3fc","\uD83E\uDD39\uD83C\uDFFE":"1f939-1f3fe","\uD83D\uDEC0\uD83C\uDFFD":"1f6c0-1f3fd","\uD83D\uDEC0\uD83C\uDFFE":"1f6c0-1f3fe","\uD83D\uDEC0\uD83C\uDFFF":"1f6c0-1f3ff","\uD83E\uDD39\uD83C\uDFFF":"1f939-1f3ff","\uD83D\uDEB4\uD83C\uDFFB":"1f6b4-1f3fb","\uD83D\uDEB4\uD83C\uDFFC":"1f6b4-1f3fc","\uD83D\uDEB4\uD83C\uDFFD":"1f6b4-1f3fd","\uD83D\uDEB4\uD83C\uDFFE":"1f6b4-1f3fe","\uD83D\uDEB4\uD83C\uDFFF":"1f6b4-1f3ff","\uD83D\uDEB5\uD83C\uDFFB":"1f6b5-1f3fb","\uD83D\uDEB5\uD83C\uDFFC":"1f6b5-1f3fc","\uD83D\uDEB5\uD83C\uDFFD":"1f6b5-1f3fd","\uD83D\uDEB5\uD83C\uDFFE":"1f6b5-1f3fe","\uD83D\uDEB5\uD83C\uDFFF":"1f6b5-1f3ff","\uD83C\uDFC7\uD83C\uDFFB":"1f3c7-1f3fb","\uD83C\uDFC7\uD83C\uDFFC":"1f3c7-1f3fc","\uD83C\uDFC7\uD83C\uDFFD":"1f3c7-1f3fd","\uD83C\uDFC7\uD83C\uDFFE":"1f3c7-1f3fe","\uD83C\uDFC7\uD83C\uDFFF":"1f3c7-1f3ff","\uD83D\uDD90\uD83C\uDFFB":"1f590-1f3fb","\uD83D\uDD90\uD83C\uDFFC":"1f590-1f3fc","\uD83D\uDD90\uD83C\uDFFD":"1f590-1f3fd","\uD83D\uDD90\uD83C\uDFFE":"1f590-1f3fe","\uD83D\uDD90\uD83C\uDFFF":"1f590-1f3ff","\uD83D\uDD95\uD83C\uDFFB":"1f595-1f3fb","\uD83D\uDD95\uD83C\uDFFC":"1f595-1f3fc","\uD83D\uDD95\uD83C\uDFFD":"1f595-1f3fd","\uD83D\uDD95\uD83C\uDFFE":"1f595-1f3fe","\uD83D\uDD95\uD83C\uDFFF":"1f595-1f3ff","\uD83D\uDD96\uD83C\uDFFB":"1f596-1f3fb","\uD83D\uDD96\uD83C\uDFFC":"1f596-1f3fc","\uD83D\uDD96\uD83C\uDFFD":"1f596-1f3fd","\uD83D\uDD96\uD83C\uDFFE":"1f596-1f3fe","\uD83D\uDD96\uD83C\uDFFF":"1f596-1f3ff","\uD83C\uDF85\uD83C\uDFFB":"1f385-1f3fb","\uD83C\uDF85\uD83C\uDFFC":"1f385-1f3fc","\uD83C\uDF85\uD83C\uDFFD":"1f385-1f3fd","\uD83C\uDF85\uD83C\uDFFE":"1f385-1f3fe","\uD83C\uDF85\uD83C\uDFFF":"1f385-1f3ff","\uD83E\uDD18\uD83C\uDFFB":"1f918-1f3fb","\uD83E\uDD18\uD83C\uDFFC":"1f918-1f3fc","\uD83E\uDD18\uD83C\uDFFD":"1f918-1f3fd","\uD83E\uDD18\uD83C\uDFFE":"1f918-1f3fe","\uD83E\uDD18\uD83C\uDFFF":"1f918-1f3ff","\uD83C\uDFCB\uD83C\uDFFB":"1f3cb-1f3fb","\uD83C\uDFCB\uD83C\uDFFC":"1f3cb-1f3fc","\uD83C\uDFCB\uD83C\uDFFD":"1f3cb-1f3fd","\uD83C\uDFCB\uD83C\uDFFE":"1f3cb-1f3fe","\uD83C\uDFCB\uD83C\uDFFF":"1f3cb-1f3ff","\uD83C\uDDE6\uD83C\uDDFD":"1f1e6-1f1fd","\uD83C\uDDF9\uD83C\uDDE6":"1f1f9-1f1e6","\uD83C\uDDEE\uD83C\uDDF4":"1f1ee-1f1f4","\uD83C\uDDE7\uD83C\uDDF6":"1f1e7-1f1f6","\uD83C\uDDE8\uD83C\uDDFD":"1f1e8-1f1fd","\uD83C\uDDE8\uD83C\uDDE8":"1f1e8-1f1e8","\uD83C\uDDEC\uD83C\uDDEC":"1f1ec-1f1ec","\uD83C\uDDEE\uD83C\uDDF2":"1f1ee-1f1f2","\uD83C\uDDFE\uD83C\uDDF9":"1f1fe-1f1f9","\uD83C\uDDF3\uD83C\uDDEB":"1f1f3-1f1eb","\uD83C\uDDF5\uD83C\uDDF3":"1f1f5-1f1f3","\uD83C\uDDE7\uD83C\uDDF1":"1f1e7-1f1f1","\uD83C\uDDF5\uD83C\uDDF2":"1f1f5-1f1f2","\uD83C\uDDEC\uD83C\uDDF8":"1f1ec-1f1f8","\uD83C\uDDF9\uD83C\uDDF0":"1f1f9-1f1f0","\uD83C\uDDE7\uD83C\uDDFB":"1f1e7-1f1fb","\uD83C\uDDED\uD83C\uDDF2":"1f1ed-1f1f2","\uD83C\uDDF8\uD83C\uDDEF":"1f1f8-1f1ef","\uD83C\uDDFA\uD83C\uDDF2":"1f1fa-1f1f2","\uD83C\uDDEE\uD83C\uDDE8":"1f1ee-1f1e8","\uD83C\uDDEA\uD83C\uDDE6":"1f1ea-1f1e6","\uD83C\uDDE8\uD83C\uDDF5":"1f1e8-1f1f5","\uD83C\uDDE9\uD83C\uDDEC":"1f1e9-1f1ec","\uD83C\uDDE6\uD83C\uDDF8":"1f1e6-1f1f8","\uD83C\uDDE6\uD83C\uDDF6":"1f1e6-1f1f6","\uD83C\uDDFB\uD83C\uDDEC":"1f1fb-1f1ec","\uD83C\uDDE8\uD83C\uDDF0":"1f1e8-1f1f0","\uD83C\uDDE8\uD83C\uDDFC":"1f1e8-1f1fc","\uD83C\uDDEA\uD83C\uDDFA":"1f1ea-1f1fa","\uD83C\uDDEC\uD83C\uDDEB":"1f1ec-1f1eb","\uD83C\uDDF9\uD83C\uDDEB":"1f1f9-1f1eb","\uD83C\uDDEC\uD83C\uDDF5":"1f1ec-1f1f5","\uD83C\uDDF2\uD83C\uDDF6":"1f1f2-1f1f6","\uD83C\uDDF2\uD83C\uDDF5":"1f1f2-1f1f5","\uD83C\uDDF7\uD83C\uDDEA":"1f1f7-1f1ea","\uD83C\uDDF8\uD83C\uDDFD":"1f1f8-1f1fd","\uD83C\uDDF8\uD83C\uDDF8":"1f1f8-1f1f8","\uD83C\uDDF9\uD83C\uDDE8":"1f1f9-1f1e8","\uD83C\uDDF2\uD83C\uDDEB":"1f1f2-1f1eb","\uD83D\uDD75\uD83C\uDFFB":"1f575-1f3fb","\uD83D\uDD75\uD83C\uDFFC":"1f575-1f3fc","\uD83D\uDD75\uD83C\uDFFD":"1f575-1f3fd","\uD83D\uDD75\uD83C\uDFFE":"1f575-1f3fe","\uD83D\uDD75\uD83C\uDFFF":"1f575-1f3ff","\uD83C\uDFC2\uD83C\uDFFB":"1f3c2-1f3fb","\uD83D\uDC68\uD83D\uDCBB":"1f468-1f4bb","\uD83D\uDC69\uD83D\uDCBB":"1f469-1f4bb","\uD83D\uDC68\uD83C\uDFEB":"1f468-1f3eb","\uD83D\uDC69\uD83C\uDFEB":"1f469-1f3eb","\uD83D\uDC68\uD83C\uDF93":"1f468-1f393","\uD83D\uDC69\uD83C\uDF93":"1f469-1f393","\uD83D\uDC68\uD83C\uDFA4":"1f468-1f3a4","\uD83D\uDC69\uD83C\uDFA4":"1f469-1f3a4","\uD83D\uDC68\uD83D\uDD2C":"1f468-1f52c","\uD83D\uDC69\uD83D\uDD2C":"1f469-1f52c","\uD83D\uDC68\uD83D\uDCBC":"1f468-1f4bc","\uD83D\uDC69\uD83D\uDCBC":"1f469-1f4bc","\uD83D\uDC68\uD83D\uDD27":"1f468-1f527","\uD83D\uDC69\uD83D\uDD27":"1f469-1f527","\uD83D\uDC68\uD83C\uDFED":"1f468-1f3ed","\uD83D\uDC69\uD83C\uDFED":"1f469-1f3ed","\uD83D\uDC68\uD83C\uDF73":"1f468-1f373","\uD83D\uDC69\uD83C\uDF73":"1f469-1f373","\uD83D\uDC68\uD83C\uDF3E":"1f468-1f33e","\uD83D\uDC69\uD83C\uDF3E":"1f469-1f33e","\uD83D\uDD74\uD83C\uDFFB":"1f574-1f3fb","\uD83D\uDD74\uD83C\uDFFC":"1f574-1f3fc","\uD83D\uDD74\uD83C\uDFFD":"1f574-1f3fd","\uD83D\uDD74\uD83C\uDFFE":"1f574-1f3fe","\uD83D\uDD74\uD83C\uDFFF":"1f574-1f3ff","\uD83D\uDECC\uD83C\uDFFB":"1f6cc-1f3fb","\uD83D\uDECC\uD83C\uDFFC":"1f6cc-1f3fc","\uD83D\uDECC\uD83C\uDFFD":"1f6cc-1f3fd","\uD83D\uDECC\uD83C\uDFFE":"1f6cc-1f3fe","\uD83D\uDECC\uD83C\uDFFF":"1f6cc-1f3ff","\uD83D\uDC68\uD83D\uDC66":"1f468-1f466","\uD83D\uDC68\uD83D\uDC67":"1f468-1f467","\uD83D\uDC69\uD83D\uDC66":"1f469-1f466","\uD83D\uDC69\uD83D\uDC67":"1f469-1f467","\uD83D\uDC68\uD83C\uDFA8":"1f468-1f3a8","\uD83D\uDC69\uD83C\uDFA8":"1f469-1f3a8","\uD83D\uDC68\uD83D\uDE80":"1f468-1f680","\uD83D\uDC69\uD83D\uDE80":"1f469-1f680","\uD83D\uDC68\uD83D\uDE92":"1f468-1f692","\uD83D\uDC69\uD83D\uDE92":"1f469-1f692","\uD83C\uDDFA\uD83C\uDDF3":"1f1fa-1f1f3","\uD83C\uDFC2\uD83C\uDFFC":"1f3c2-1f3fc","\uD83C\uDFC2\uD83C\uDFFD":"1f3c2-1f3fd","\uD83C\uDFC2\uD83C\uDFFE":"1f3c2-1f3fe","\uD83C\uDFC2\uD83C\uDFFF":"1f3c2-1f3ff","\uD83C\uDFCC\uD83C\uDFFB":"1f3cc-1f3fb","\uD83C\uDFCC\uD83C\uDFFC":"1f3cc-1f3fc","\uD83C\uDFCC\uD83C\uDFFD":"1f3cc-1f3fd","\uD83C\uDFCC\uD83C\uDFFE":"1f3cc-1f3fe","\uD83C\uDFCC\uD83C\uDFFF":"1f3cc-1f3ff","\uD83E\uDD1F\uD83C\uDFFB":"1f91f-1f3fb","\uD83E\uDD1F\uD83C\uDFFC":"1f91f-1f3fc","\uD83E\uDD1F\uD83C\uDFFD":"1f91f-1f3fd","\uD83E\uDD1F\uD83C\uDFFE":"1f91f-1f3fe","\uD83E\uDD1F\uD83C\uDFFF":"1f91f-1f3ff","\uD83E\uDD31\uD83C\uDFFB":"1f931-1f3fb","\uD83E\uDD31\uD83C\uDFFC":"1f931-1f3fc","\uD83E\uDD31\uD83C\uDFFD":"1f931-1f3fd","\uD83E\uDD31\uD83C\uDFFE":"1f931-1f3fe","\uD83E\uDD31\uD83C\uDFFF":"1f931-1f3ff","\uD83E\uDD32\uD83C\uDFFB":"1f932-1f3fb","\uD83E\uDD32\uD83C\uDFFC":"1f932-1f3fc","\uD83E\uDD32\uD83C\uDFFD":"1f932-1f3fd","\uD83E\uDD32\uD83C\uDFFE":"1f932-1f3fe","\uD83E\uDD32\uD83C\uDFFF":"1f932-1f3ff","\uD83E\uDDD1\uD83C\uDFFB":"1f9d1-1f3fb","\uD83E\uDDD1\uD83C\uDFFC":"1f9d1-1f3fc","\uD83E\uDDD1\uD83C\uDFFD":"1f9d1-1f3fd","\uD83E\uDDD1\uD83C\uDFFE":"1f9d1-1f3fe","\uD83E\uDDD1\uD83C\uDFFF":"1f9d1-1f3ff","\uD83E\uDDD2\uD83C\uDFFB":"1f9d2-1f3fb","\uD83E\uDDD2\uD83C\uDFFC":"1f9d2-1f3fc","\uD83E\uDDD2\uD83C\uDFFD":"1f9d2-1f3fd","\uD83E\uDDD2\uD83C\uDFFE":"1f9d2-1f3fe","\uD83E\uDDD2\uD83C\uDFFF":"1f9d2-1f3ff","\uD83E\uDDD3\uD83C\uDFFB":"1f9d3-1f3fb","\uD83E\uDDD3\uD83C\uDFFC":"1f9d3-1f3fc","\uD83E\uDDD3\uD83C\uDFFD":"1f9d3-1f3fd","\uD83E\uDDD3\uD83C\uDFFE":"1f9d3-1f3fe","\uD83E\uDDD3\uD83C\uDFFF":"1f9d3-1f3ff","\uD83E\uDDD4\uD83C\uDFFB":"1f9d4-1f3fb","\uD83E\uDDD4\uD83C\uDFFC":"1f9d4-1f3fc","\uD83E\uDDD4\uD83C\uDFFD":"1f9d4-1f3fd","\uD83E\uDDD4\uD83C\uDFFE":"1f9d4-1f3fe","\uD83E\uDDD4\uD83C\uDFFF":"1f9d4-1f3ff","\uD83E\uDDD5\uD83C\uDFFB":"1f9d5-1f3fb","\uD83E\uDDD5\uD83C\uDFFC":"1f9d5-1f3fc","\uD83E\uDDD5\uD83C\uDFFD":"1f9d5-1f3fd","\uD83E\uDDD5\uD83C\uDFFE":"1f9d5-1f3fe","\uD83E\uDDD5\uD83C\uDFFF":"1f9d5-1f3ff","\uD83E\uDDD6\uD83C\uDFFB":"1f9d6-1f3fb","\uD83E\uDDD6\uD83C\uDFFC":"1f9d6-1f3fc","\uD83E\uDDD6\uD83C\uDFFD":"1f9d6-1f3fd","\uD83E\uDDD6\uD83C\uDFFE":"1f9d6-1f3fe","\uD83E\uDDD6\uD83C\uDFFF":"1f9d6-1f3ff","\uD83E\uDDD7\uD83C\uDFFB":"1f9d7-1f3fb","\uD83E\uDDD7\uD83C\uDFFC":"1f9d7-1f3fc","\uD83E\uDDD7\uD83C\uDFFD":"1f9d7-1f3fd","\uD83E\uDDD7\uD83C\uDFFE":"1f9d7-1f3fe","\uD83E\uDDD7\uD83C\uDFFF":"1f9d7-1f3ff","\uD83E\uDDD8\uD83C\uDFFB":"1f9d8-1f3fb","\uD83E\uDDD8\uD83C\uDFFC":"1f9d8-1f3fc","\uD83E\uDDD8\uD83C\uDFFD":"1f9d8-1f3fd","\uD83E\uDDD8\uD83C\uDFFE":"1f9d8-1f3fe","\uD83E\uDDD8\uD83C\uDFFF":"1f9d8-1f3ff","\uD83E\uDDD9\uD83C\uDFFB":"1f9d9-1f3fb","\uD83E\uDDD9\uD83C\uDFFC":"1f9d9-1f3fc","\uD83E\uDDD9\uD83C\uDFFD":"1f9d9-1f3fd","\uD83E\uDDD9\uD83C\uDFFE":"1f9d9-1f3fe","\uD83E\uDDD9\uD83C\uDFFF":"1f9d9-1f3ff","\uD83E\uDDDA\uD83C\uDFFB":"1f9da-1f3fb","\uD83E\uDDDA\uD83C\uDFFC":"1f9da-1f3fc","\uD83E\uDDDA\uD83C\uDFFD":"1f9da-1f3fd","\uD83E\uDDDA\uD83C\uDFFE":"1f9da-1f3fe","\uD83E\uDDDA\uD83C\uDFFF":"1f9da-1f3ff","\uD83E\uDDDB\uD83C\uDFFB":"1f9db-1f3fb","\uD83E\uDDDB\uD83C\uDFFC":"1f9db-1f3fc","\uD83E\uDDDB\uD83C\uDFFD":"1f9db-1f3fd","\uD83E\uDDDB\uD83C\uDFFE":"1f9db-1f3fe","\uD83E\uDDDB\uD83C\uDFFF":"1f9db-1f3ff","\uD83E\uDDDC\uD83C\uDFFB":"1f9dc-1f3fb","\uD83E\uDDDC\uD83C\uDFFC":"1f9dc-1f3fc","\uD83E\uDDDC\uD83C\uDFFD":"1f9dc-1f3fd","\uD83E\uDDDC\uD83C\uDFFE":"1f9dc-1f3fe","\uD83E\uDDDC\uD83C\uDFFF":"1f9dc-1f3ff","\uD83E\uDDDD\uD83C\uDFFB":"1f9dd-1f3fb","\uD83E\uDDDD\uD83C\uDFFC":"1f9dd-1f3fc","\uD83E\uDDDD\uD83C\uDFFD":"1f9dd-1f3fd","\uD83E\uDDDD\uD83C\uDFFE":"1f9dd-1f3fe","\uD83E\uDDDD\uD83C\uDFFF":"1f9dd-1f3ff","\uD83C\uDD7F\uFE0F":"1f17f","\uD83C\uDE02\uFE0F":"1f202","\uD83C\uDE37\uFE0F":"1f237","\uD83C\uDF9E\uFE0F":"1f39e","\uD83C\uDF9F\uFE0F":"1f39f","\uD83C\uDFCB\uFE0F":"1f3cb","\uD83C\uDFCC\uFE0F":"1f3cc","\uD83C\uDFCD\uFE0F":"1f3cd","\uD83C\uDFCE\uFE0F":"1f3ce","\uD83C\uDF96\uFE0F":"1f396","\uD83C\uDF97\uFE0F":"1f397","\uD83C\uDF36\uFE0F":"1f336","\uD83C\uDF27\uFE0F":"1f327","\uD83C\uDF28\uFE0F":"1f328","\uD83C\uDF29\uFE0F":"1f329","\uD83C\uDF2A\uFE0F":"1f32a","\uD83C\uDF2B\uFE0F":"1f32b","\uD83C\uDF2C\uFE0F":"1f32c","\uD83D\uDC3F\uFE0F":"1f43f","\uD83D\uDD77\uFE0F":"1f577","\uD83D\uDD78\uFE0F":"1f578","\uD83C\uDF21\uFE0F":"1f321","\uD83C\uDF99\uFE0F":"1f399","\uD83C\uDF9A\uFE0F":"1f39a","\uD83C\uDF9B\uFE0F":"1f39b","\uD83C\uDFF3\uFE0F":"1f3f3","\uD83C\uDFF5\uFE0F":"1f3f5","\uD83C\uDFF7\uFE0F":"1f3f7","\uD83D\uDCFD\uFE0F":"1f4fd","\uD83D\uDD49\uFE0F":"1f549","\uD83D\uDD4A\uFE0F":"1f54a","\uD83D\uDD6F\uFE0F":"1f56f","\uD83D\uDD70\uFE0F":"1f570","\uD83D\uDD73\uFE0F":"1f573","\uD83D\uDD76\uFE0F":"1f576","\uD83D\uDD79\uFE0F":"1f579","\uD83D\uDD87\uFE0F":"1f587","\uD83D\uDD8A\uFE0F":"1f58a","\uD83D\uDD8B\uFE0F":"1f58b","\uD83D\uDD8C\uFE0F":"1f58c","\uD83D\uDD8D\uFE0F":"1f58d","\uD83D\uDDA5\uFE0F":"1f5a5","\uD83D\uDDA8\uFE0F":"1f5a8","\uD83D\uDDB2\uFE0F":"1f5b2","\uD83D\uDDBC\uFE0F":"1f5bc","\uD83D\uDDC2\uFE0F":"1f5c2","\uD83D\uDDC3\uFE0F":"1f5c3","\uD83D\uDDC4\uFE0F":"1f5c4","\uD83D\uDDD1\uFE0F":"1f5d1","\uD83D\uDDD2\uFE0F":"1f5d2","\uD83D\uDDD3\uFE0F":"1f5d3","\uD83D\uDDDC\uFE0F":"1f5dc","\uD83D\uDDDD\uFE0F":"1f5dd","\uD83D\uDDDE\uFE0F":"1f5de","\uD83D\uDDE1\uFE0F":"1f5e1","\uD83D\uDDE3\uFE0F":"1f5e3","\uD83D\uDDE8\uFE0F":"1f5e8","\uD83D\uDDEF\uFE0F":"1f5ef","\uD83D\uDDF3\uFE0F":"1f5f3","\uD83D\uDDFA\uFE0F":"1f5fa","\uD83D\uDEE0\uFE0F":"1f6e0","\uD83D\uDEE1\uFE0F":"1f6e1","\uD83D\uDEE2\uFE0F":"1f6e2","\uD83D\uDEF0\uFE0F":"1f6f0","\uD83C\uDF7D\uFE0F":"1f37d","\uD83D\uDC41\uFE0F":"1f441","\uD83D\uDD74\uFE0F":"1f574","\uD83D\uDD75\uFE0F":"1f575","\uD83D\uDD90\uFE0F":"1f590","\uD83C\uDFD4\uFE0F":"1f3d4","\uD83C\uDFD5\uFE0F":"1f3d5","\uD83C\uDFD6\uFE0F":"1f3d6","\uD83C\uDFD7\uFE0F":"1f3d7","\uD83C\uDFD8\uFE0F":"1f3d8","\uD83C\uDFD9\uFE0F":"1f3d9","\uD83C\uDFDA\uFE0F":"1f3da","\uD83C\uDFDB\uFE0F":"1f3db","\uD83C\uDFDC\uFE0F":"1f3dc","\uD83C\uDFDD\uFE0F":"1f3dd","\uD83C\uDFDE\uFE0F":"1f3de","\uD83C\uDFDF\uFE0F":"1f3df","\uD83D\uDECB\uFE0F":"1f6cb","\uD83D\uDECD\uFE0F":"1f6cd","\uD83D\uDECE\uFE0F":"1f6ce","\uD83D\uDECF\uFE0F":"1f6cf","\uD83D\uDEE3\uFE0F":"1f6e3","\uD83D\uDEE4\uFE0F":"1f6e4","\uD83D\uDEE5\uFE0F":"1f6e5","\uD83D\uDEE9\uFE0F":"1f6e9","\uD83D\uDEF3\uFE0F":"1f6f3","\u261D\uD83C\uDFFB":"261d-1f3fb","\u261D\uD83C\uDFFC":"261d-1f3fc","\u261D\uD83C\uDFFD":"261d-1f3fd","\u261D\uD83C\uDFFE":"261d-1f3fe","\u261D\uD83C\uDFFF":"261d-1f3ff","\u270C\uD83C\uDFFB":"270c-1f3fb","\u270C\uD83C\uDFFC":"270c-1f3fc","\u270C\uD83C\uDFFD":"270c-1f3fd","\u270C\uD83C\uDFFE":"270c-1f3fe","\u270C\uD83C\uDFFF":"270c-1f3ff","\u270A\uD83C\uDFFB":"270a-1f3fb","\u270A\uD83C\uDFFC":"270a-1f3fc","\u270A\uD83C\uDFFD":"270a-1f3fd","\u270A\uD83C\uDFFE":"270a-1f3fe","\u270A\uD83C\uDFFF":"270a-1f3ff","\u270B\uD83C\uDFFB":"270b-1f3fb","\u270B\uD83C\uDFFC":"270b-1f3fc","\u270B\uD83C\uDFFD":"270b-1f3fd","\u270B\uD83C\uDFFE":"270b-1f3fe","\u270B\uD83C\uDFFF":"270b-1f3ff","\u270D\uD83C\uDFFB":"270d-1f3fb","\u270D\uD83C\uDFFC":"270d-1f3fc","\u270D\uD83C\uDFFD":"270d-1f3fd","\u270D\uD83C\uDFFE":"270d-1f3fe","\u270D\uD83C\uDFFF":"270d-1f3ff","\uD83C\uDF24\uFE0F":"1f324","\uD83C\uDF25\uFE0F":"1f325","\uD83C\uDF26\uFE0F":"1f326","\uD83D\uDDB1\uFE0F":"1f5b1","\u26F9\uD83C\uDFFB":"26f9-1f3fb","\u26F9\uD83C\uDFFC":"26f9-1f3fc","\u26F9\uD83C\uDFFD":"26f9-1f3fd","\u26F9\uD83C\uDFFE":"26f9-1f3fe","\u26F9\uD83C\uDFFF":"26f9-1f3ff","\uD83C\uDD70\uFE0F":"1f170","\uD83C\uDD71\uFE0F":"1f171","\uD83C\uDD7E\uFE0F":"1f17e","#\u20E3":"0023-20e3","0\u20E3":"0030-20e3","1\u20E3":"0031-20e3","2\u20E3":"0032-20e3","3\u20E3":"0033-20e3","4\u20E3":"0034-20e3","5\u20E3":"0035-20e3","6\u20E3":"0036-20e3","7\u20E3":"0037-20e3","8\u20E3":"0038-20e3","9\u20E3":"0039-20e3","\u00A9\uFE0F":"00a9","\u00AE\uFE0F":"00ae","\u203C\uFE0F":"203c","\u2049\uFE0F":"2049","\u2122\uFE0F":"2122","\u2139\uFE0F":"2139","\u2194\uFE0F":"2194","\u2195\uFE0F":"2195","\u2196\uFE0F":"2196","\u2197\uFE0F":"2197","\u2198\uFE0F":"2198","\u2199\uFE0F":"2199","\u21A9\uFE0F":"21a9","\u21AA\uFE0F":"21aa","\u24C2\uFE0F":"24c2","\u25AA\uFE0F":"25aa","\u25AB\uFE0F":"25ab","\u25B6\uFE0F":"25b6","\u25C0\uFE0F":"25c0","\u25FB\uFE0F":"25fb","\u25FC\uFE0F":"25fc","\u2600\uFE0F":"2600","\u2601\uFE0F":"2601","\u260E\uFE0F":"260e","\u2611\uFE0F":"2611","\u261D\uFE0F":"261d","\u263A\uFE0F":"263a","\u2660\uFE0F":"2660","\u2663\uFE0F":"2663","\u2665\uFE0F":"2665","\u2666\uFE0F":"2666","\u2668\uFE0F":"2668","\u267B\uFE0F":"267b","\u26A0\uFE0F":"26a0","\u2702\uFE0F":"2702","\u2708\uFE0F":"2708","\u2709\uFE0F":"2709","\u270C\uFE0F":"270c","\u270F\uFE0F":"270f","\u2712\uFE0F":"2712","\u2714\uFE0F":"2714","\u2716\uFE0F":"2716","\u2733\uFE0F":"2733","\u2734\uFE0F":"2734","\u2744\uFE0F":"2744","\u2747\uFE0F":"2747","\u2764\uFE0F":"2764","\u27A1\uFE0F":"27a1","\u2934\uFE0F":"2934","\u2935\uFE0F":"2935","\u2B05\uFE0F":"2b05","\u2B06\uFE0F":"2b06","\u2B07\uFE0F":"2b07","\u3030\uFE0F":"3030","\u303D\uFE0F":"303d","\u3297\uFE0F":"3297","\u3299\uFE0F":"3299","\u271D\uFE0F":"271d","\u2328\uFE0F":"2328","\u270D\uFE0F":"270d","*\u20E3":"002a-20e3","\u23CF\uFE0F":"23cf","\u23ED\uFE0F":"23ed","\u23EE\uFE0F":"23ee","\u23EF\uFE0F":"23ef","\u23F1\uFE0F":"23f1","\u23F2\uFE0F":"23f2","\u23F8\uFE0F":"23f8","\u23F9\uFE0F":"23f9","\u23FA\uFE0F":"23fa","\u2602\uFE0F":"2602","\u2603\uFE0F":"2603","\u2604\uFE0F":"2604","\u2618\uFE0F":"2618","\u2620\uFE0F":"2620","\u2622\uFE0F":"2622","\u2623\uFE0F":"2623","\u2626\uFE0F":"2626","\u262A\uFE0F":"262a","\u262E\uFE0F":"262e","\u262F\uFE0F":"262f","\u2638\uFE0F":"2638","\u2639\uFE0F":"2639","\u2692\uFE0F":"2692","\u2694\uFE0F":"2694","\u2696\uFE0F":"2696","\u2697\uFE0F":"2697","\u2699\uFE0F":"2699","\u269B\uFE0F":"269b","\u269C\uFE0F":"269c","\u26B0\uFE0F":"26b0","\u26B1\uFE0F":"26b1","\u26C8\uFE0F":"26c8","\u26CF\uFE0F":"26cf","\u26D1\uFE0F":"26d1","\u26D3\uFE0F":"26d3","\u26E9\uFE0F":"26e9","\u26F0\uFE0F":"26f0","\u26F1\uFE0F":"26f1","\u26F4\uFE0F":"26f4","\u26F7\uFE0F":"26f7","\u26F8\uFE0F":"26f8","\u26F9\uFE0F":"26f9","\u2721\uFE0F":"2721","\u2763\uFE0F":"2763","#\uFE0F":"0023","*\uFE0F":"002a","0\uFE0F":"0030","1\uFE0F":"0031","2\uFE0F":"0032","3\uFE0F":"0033","4\uFE0F":"0034","5\uFE0F":"0035","6\uFE0F":"0036","7\uFE0F":"0037","8\uFE0F":"0038","9\uFE0F":"0039","\u2640\uFE0F":"2640","\u2642\uFE0F":"2642","\u2695\uFE0F":"2695","\uD83E\uDD49":"1f949","\uD83E\uDD48":"1f948","\uD83E\uDD47":"1f947","\uD83E\uDD3A":"1f93a","\uD83E\uDD45":"1f945","\uD83E\uDD3E":"1f93e","\uD83C\uDDFF":"1f1ff","\uD83E\uDD3D":"1f93d","\uD83E\uDD4B":"1f94b","\uD83E\uDD4A":"1f94a","\uD83E\uDD3C":"1f93c","\uD83E\uDD39":"1f939","\uD83E\uDD38":"1f938","\uD83D\uDEF6":"1f6f6","\uD83D\uDEF5":"1f6f5","\uD83D\uDEF4":"1f6f4","\uD83D\uDED2":"1f6d2","\uD83C\uDC04":"1f004","\uD83C\uDCCF":"1f0cf","\uD83D\uDED1":"1f6d1","\uD83C\uDD8E":"1f18e","\uD83C\uDD91":"1f191","\uD83C\uDDFE":"1f1fe","\uD83C\uDD92":"1f192","\uD83C\uDD93":"1f193","\uD83C\uDD94":"1f194","\uD83C\uDD95":"1f195","\uD83C\uDD96":"1f196","\uD83C\uDD97":"1f197","\uD83C\uDD98":"1f198","\uD83E\uDD44":"1f944","\uD83C\uDD99":"1f199","\uD83C\uDD9A":"1f19a","\uD83E\uDD42":"1f942","\uD83E\uDD43":"1f943","\uD83C\uDE01":"1f201","\uD83C\uDE1A":"1f21a","\uD83C\uDE2F":"1f22f","\uD83E\uDD59":"1f959","\uD83C\uDE32":"1f232","\uD83C\uDE33":"1f233","\uD83C\uDE34":"1f234","\uD83C\uDE35":"1f235","\uD83C\uDE36":"1f236","\uD83E\uDD58":"1f958","\uD83C\uDE38":"1f238","\uD83C\uDE39":"1f239","\uD83E\uDD57":"1f957","\uD83C\uDE3A":"1f23a","\uD83C\uDE50":"1f250","\uD83C\uDE51":"1f251","\uD83C\uDF00":"1f300","\uD83E\uDD56":"1f956","\uD83C\uDF01":"1f301","\uD83C\uDF02":"1f302","\uD83C\uDF03":"1f303","\uD83C\uDF04":"1f304","\uD83C\uDF05":"1f305","\uD83C\uDF06":"1f306","\uD83E\uDD55":"1f955","\uD83C\uDF07":"1f307","\uD83C\uDF08":"1f308","\uD83E\uDD54":"1f954","\uD83C\uDF09":"1f309","\uD83C\uDF0A":"1f30a","\uD83C\uDF0B":"1f30b","\uD83C\uDF0C":"1f30c","\uD83C\uDF0F":"1f30f","\uD83C\uDF11":"1f311","\uD83E\uDD53":"1f953","\uD83C\uDF13":"1f313","\uD83C\uDF14":"1f314","\uD83C\uDF15":"1f315","\uD83C\uDF19":"1f319","\uD83C\uDF1B":"1f31b","\uD83C\uDF1F":"1f31f","\uD83E\uDD52":"1f952","\uD83C\uDF20":"1f320","\uD83C\uDF30":"1f330","\uD83E\uDD51":"1f951","\uD83C\uDF31":"1f331","\uD83C\uDF34":"1f334","\uD83C\uDF35":"1f335","\uD83C\uDF37":"1f337","\uD83C\uDF38":"1f338","\uD83C\uDF39":"1f339","\uD83C\uDF3A":"1f33a","\uD83C\uDF3B":"1f33b","\uD83C\uDF3C":"1f33c","\uD83C\uDF3D":"1f33d","\uD83E\uDD50":"1f950","\uD83C\uDF3E":"1f33e","\uD83C\uDF3F":"1f33f","\uD83C\uDF40":"1f340","\uD83C\uDF41":"1f341","\uD83C\uDF42":"1f342","\uD83C\uDF43":"1f343","\uD83C\uDF44":"1f344","\uD83C\uDF45":"1f345","\uD83C\uDF46":"1f346","\uD83C\uDF47":"1f347","\uD83C\uDF48":"1f348","\uD83C\uDF49":"1f349","\uD83C\uDF4A":"1f34a","\uD83E\uDD40":"1f940","\uD83C\uDF4C":"1f34c","\uD83C\uDF4D":"1f34d","\uD83C\uDF4E":"1f34e","\uD83C\uDF4F":"1f34f","\uD83C\uDF51":"1f351","\uD83C\uDF52":"1f352","\uD83C\uDF53":"1f353","\uD83E\uDD8F":"1f98f","\uD83C\uDF54":"1f354","\uD83C\uDF55":"1f355","\uD83C\uDF56":"1f356","\uD83E\uDD8E":"1f98e","\uD83C\uDF57":"1f357","\uD83C\uDF58":"1f358","\uD83C\uDF59":"1f359","\uD83E\uDD8D":"1f98d","\uD83C\uDF5A":"1f35a","\uD83C\uDF5B":"1f35b","\uD83E\uDD8C":"1f98c","\uD83C\uDF5C":"1f35c","\uD83C\uDF5D":"1f35d","\uD83C\uDF5E":"1f35e","\uD83C\uDF5F":"1f35f","\uD83E\uDD8B":"1f98b","\uD83C\uDF60":"1f360","\uD83C\uDF61":"1f361","\uD83E\uDD8A":"1f98a","\uD83C\uDF62":"1f362","\uD83C\uDF63":"1f363","\uD83E\uDD89":"1f989","\uD83C\uDF64":"1f364","\uD83C\uDF65":"1f365","\uD83E\uDD88":"1f988","\uD83C\uDF66":"1f366","\uD83E\uDD87":"1f987","\uD83C\uDF67":"1f367","\uD83C\uDDFD":"1f1fd","\uD83C\uDF68":"1f368","\uD83E\uDD86":"1f986","\uD83C\uDF69":"1f369","\uD83E\uDD85":"1f985","\uD83C\uDF6A":"1f36a","\uD83D\uDDA4":"1f5a4","\uD83C\uDF6B":"1f36b","\uD83C\uDF6C":"1f36c","\uD83C\uDF6D":"1f36d","\uD83C\uDF6E":"1f36e","\uD83C\uDF6F":"1f36f","\uD83E\uDD1E":"1f91e","\uD83C\uDF70":"1f370","\uD83C\uDF71":"1f371","\uD83C\uDF72":"1f372","\uD83E\uDD1D":"1f91d","\uD83C\uDF73":"1f373","\uD83C\uDF74":"1f374","\uD83C\uDF75":"1f375","\uD83C\uDF76":"1f376","\uD83C\uDF77":"1f377","\uD83C\uDF78":"1f378","\uD83C\uDF79":"1f379","\uD83C\uDF7A":"1f37a","\uD83C\uDF7B":"1f37b","\uD83C\uDF80":"1f380","\uD83C\uDF81":"1f381","\uD83C\uDF82":"1f382","\uD83C\uDF83":"1f383","\uD83E\uDD1B":"1f91b","\uD83E\uDD1C":"1f91c","\uD83C\uDF84":"1f384","\uD83C\uDF85":"1f385","\uD83C\uDF86":"1f386","\uD83E\uDD1A":"1f91a","\uD83C\uDF87":"1f387","\uD83C\uDF88":"1f388","\uD83C\uDF89":"1f389","\uD83C\uDF8A":"1f38a","\uD83C\uDF8B":"1f38b","\uD83C\uDF8C":"1f38c","\uD83E\uDD19":"1f919","\uD83C\uDF8D":"1f38d","\uD83D\uDD7A":"1f57a","\uD83C\uDF8E":"1f38e","\uD83E\uDD33":"1f933","\uD83C\uDF8F":"1f38f","\uD83E\uDD30":"1f930","\uD83C\uDF90":"1f390","\uD83E\uDD26":"1f926","\uD83E\uDD37":"1f937","\uD83C\uDF91":"1f391","\uD83C\uDF92":"1f392","\uD83C\uDF93":"1f393","\uD83C\uDFA0":"1f3a0","\uD83C\uDFA1":"1f3a1","\uD83C\uDFA2":"1f3a2","\uD83C\uDFA3":"1f3a3","\uD83C\uDFA4":"1f3a4","\uD83C\uDFA5":"1f3a5","\uD83C\uDFA6":"1f3a6","\uD83C\uDFA7":"1f3a7","\uD83E\uDD36":"1f936","\uD83C\uDFA8":"1f3a8","\uD83E\uDD35":"1f935","\uD83C\uDFA9":"1f3a9","\uD83C\uDFAA":"1f3aa","\uD83E\uDD34":"1f934","\uD83C\uDFAB":"1f3ab","\uD83C\uDFAC":"1f3ac","\uD83C\uDFAD":"1f3ad","\uD83E\uDD27":"1f927","\uD83C\uDFAE":"1f3ae","\uD83C\uDFAF":"1f3af","\uD83C\uDFB0":"1f3b0","\uD83C\uDFB1":"1f3b1","\uD83C\uDFB2":"1f3b2","\uD83C\uDFB3":"1f3b3","\uD83C\uDFB4":"1f3b4","\uD83E\uDD25":"1f925","\uD83C\uDFB5":"1f3b5","\uD83C\uDFB6":"1f3b6","\uD83C\uDFB7":"1f3b7","\uD83E\uDD24":"1f924","\uD83C\uDFB8":"1f3b8","\uD83C\uDFB9":"1f3b9","\uD83C\uDFBA":"1f3ba","\uD83E\uDD23":"1f923","\uD83C\uDFBB":"1f3bb","\uD83C\uDFBC":"1f3bc","\uD83C\uDFBD":"1f3bd","\uD83E\uDD22":"1f922","\uD83C\uDFBE":"1f3be","\uD83C\uDFBF":"1f3bf","\uD83C\uDFC0":"1f3c0","\uD83C\uDFC1":"1f3c1","\uD83E\uDD21":"1f921","\uD83C\uDFC2":"1f3c2","\uD83C\uDFC3":"1f3c3","\uD83C\uDFC4":"1f3c4","\uD83C\uDFC6":"1f3c6","\uD83C\uDFC8":"1f3c8","\uD83C\uDFCA":"1f3ca","\uD83C\uDFE0":"1f3e0","\uD83C\uDFE1":"1f3e1","\uD83C\uDFE2":"1f3e2","\uD83C\uDFE3":"1f3e3","\uD83C\uDFE5":"1f3e5","\uD83C\uDFE6":"1f3e6","\uD83C\uDFE7":"1f3e7","\uD83C\uDFE8":"1f3e8","\uD83C\uDFE9":"1f3e9","\uD83C\uDFEA":"1f3ea","\uD83C\uDFEB":"1f3eb","\uD83C\uDFEC":"1f3ec","\uD83E\uDD20":"1f920","\uD83C\uDFED":"1f3ed","\uD83C\uDFEE":"1f3ee","\uD83C\uDFEF":"1f3ef","\uD83C\uDFF0":"1f3f0","\uD83D\uDC0C":"1f40c","\uD83D\uDC0D":"1f40d","\uD83D\uDC0E":"1f40e","\uD83D\uDC11":"1f411","\uD83D\uDC12":"1f412","\uD83D\uDC14":"1f414","\uD83D\uDC17":"1f417","\uD83D\uDC18":"1f418","\uD83D\uDC19":"1f419","\uD83D\uDC1A":"1f41a","\uD83D\uDC1B":"1f41b","\uD83D\uDC1C":"1f41c","\uD83D\uDC1D":"1f41d","\uD83D\uDC1E":"1f41e","\uD83D\uDC1F":"1f41f","\uD83D\uDC20":"1f420","\uD83D\uDC21":"1f421","\uD83D\uDC22":"1f422","\uD83D\uDC23":"1f423","\uD83D\uDC24":"1f424","\uD83D\uDC25":"1f425","\uD83D\uDC26":"1f426","\uD83D\uDC27":"1f427","\uD83D\uDC28":"1f428","\uD83D\uDC29":"1f429","\uD83D\uDC2B":"1f42b","\uD83D\uDC2C":"1f42c","\uD83D\uDC2D":"1f42d","\uD83D\uDC2E":"1f42e","\uD83D\uDC2F":"1f42f","\uD83D\uDC30":"1f430","\uD83D\uDC31":"1f431","\uD83D\uDC32":"1f432","\uD83D\uDC33":"1f433","\uD83D\uDC34":"1f434","\uD83D\uDC35":"1f435","\uD83D\uDC36":"1f436","\uD83D\uDC37":"1f437","\uD83D\uDC38":"1f438","\uD83D\uDC39":"1f439","\uD83D\uDC3A":"1f43a","\uD83D\uDC3B":"1f43b","\uD83D\uDC3C":"1f43c","\uD83D\uDC3D":"1f43d","\uD83D\uDC3E":"1f43e","\uD83D\uDC40":"1f440","\uD83D\uDC42":"1f442","\uD83D\uDC43":"1f443","\uD83D\uDC44":"1f444","\uD83D\uDC45":"1f445","\uD83D\uDC46":"1f446","\uD83D\uDC47":"1f447","\uD83D\uDC48":"1f448","\uD83D\uDC49":"1f449","\uD83D\uDC4A":"1f44a","\uD83D\uDC4B":"1f44b","\uD83D\uDC4C":"1f44c","\uD83D\uDC4D":"1f44d","\uD83D\uDC4E":"1f44e","\uD83D\uDC4F":"1f44f","\uD83D\uDC50":"1f450","\uD83D\uDC51":"1f451","\uD83D\uDC52":"1f452","\uD83D\uDC53":"1f453","\uD83D\uDC54":"1f454","\uD83D\uDC55":"1f455","\uD83D\uDC56":"1f456","\uD83D\uDC57":"1f457","\uD83D\uDC58":"1f458","\uD83D\uDC59":"1f459","\uD83D\uDC5A":"1f45a","\uD83D\uDC5B":"1f45b","\uD83D\uDC5C":"1f45c","\uD83D\uDC5D":"1f45d","\uD83D\uDC5E":"1f45e","\uD83D\uDC5F":"1f45f","\uD83D\uDC60":"1f460","\uD83D\uDC61":"1f461","\uD83D\uDC62":"1f462","\uD83D\uDC63":"1f463","\uD83D\uDC64":"1f464","\uD83D\uDC66":"1f466","\uD83D\uDC67":"1f467","\uD83D\uDC68":"1f468","\uD83D\uDC69":"1f469","\uD83D\uDC6A":"1f46a","\uD83D\uDC6B":"1f46b","\uD83D\uDC6E":"1f46e","\uD83D\uDC6F":"1f46f","\uD83D\uDC70":"1f470","\uD83D\uDC71":"1f471","\uD83D\uDC72":"1f472","\uD83D\uDC73":"1f473","\uD83D\uDC74":"1f474","\uD83D\uDC75":"1f475","\uD83D\uDC76":"1f476","\uD83D\uDC77":"1f477","\uD83D\uDC78":"1f478","\uD83D\uDC79":"1f479","\uD83D\uDC7A":"1f47a","\uD83D\uDC7B":"1f47b","\uD83D\uDC7C":"1f47c","\uD83D\uDC7D":"1f47d","\uD83D\uDC7E":"1f47e","\uD83D\uDC7F":"1f47f","\uD83D\uDC80":"1f480","\uD83D\uDCC7":"1f4c7","\uD83D\uDC81":"1f481","\uD83D\uDC82":"1f482","\uD83D\uDC83":"1f483","\uD83D\uDC84":"1f484","\uD83D\uDC85":"1f485","\uD83D\uDCD2":"1f4d2","\uD83D\uDC86":"1f486","\uD83D\uDCD3":"1f4d3","\uD83D\uDC87":"1f487","\uD83D\uDCD4":"1f4d4","\uD83D\uDC88":"1f488","\uD83D\uDCD5":"1f4d5","\uD83D\uDC89":"1f489","\uD83D\uDCD6":"1f4d6","\uD83D\uDC8A":"1f48a","\uD83D\uDCD7":"1f4d7","\uD83D\uDC8B":"1f48b","\uD83D\uDCD8":"1f4d8","\uD83D\uDC8C":"1f48c","\uD83D\uDCD9":"1f4d9","\uD83D\uDC8D":"1f48d","\uD83D\uDCDA":"1f4da","\uD83D\uDC8E":"1f48e","\uD83D\uDCDB":"1f4db","\uD83D\uDC8F":"1f48f","\uD83D\uDCDC":"1f4dc","\uD83D\uDC90":"1f490","\uD83D\uDCDD":"1f4dd","\uD83D\uDC91":"1f491","\uD83D\uDCDE":"1f4de","\uD83D\uDC92":"1f492","\uD83D\uDCDF":"1f4df","\uD83D\uDCE0":"1f4e0","\uD83D\uDC93":"1f493","\uD83D\uDCE1":"1f4e1","\uD83D\uDCE2":"1f4e2","\uD83D\uDC94":"1f494","\uD83D\uDCE3":"1f4e3","\uD83D\uDCE4":"1f4e4","\uD83D\uDC95":"1f495","\uD83D\uDCE5":"1f4e5","\uD83D\uDCE6":"1f4e6","\uD83D\uDC96":"1f496","\uD83D\uDCE7":"1f4e7","\uD83D\uDCE8":"1f4e8","\uD83D\uDC97":"1f497","\uD83D\uDCE9":"1f4e9","\uD83D\uDCEA":"1f4ea","\uD83D\uDC98":"1f498","\uD83D\uDCEB":"1f4eb","\uD83D\uDCEE":"1f4ee","\uD83D\uDC99":"1f499","\uD83D\uDCF0":"1f4f0","\uD83D\uDCF1":"1f4f1","\uD83D\uDC9A":"1f49a","\uD83D\uDCF2":"1f4f2","\uD83D\uDCF3":"1f4f3","\uD83D\uDC9B":"1f49b","\uD83D\uDCF4":"1f4f4","\uD83D\uDCF6":"1f4f6","\uD83D\uDC9C":"1f49c","\uD83D\uDCF7":"1f4f7","\uD83D\uDCF9":"1f4f9","\uD83D\uDC9D":"1f49d","\uD83D\uDCFA":"1f4fa","\uD83D\uDCFB":"1f4fb","\uD83D\uDC9E":"1f49e","\uD83D\uDCFC":"1f4fc","\uD83D\uDD03":"1f503","\uD83D\uDC9F":"1f49f","\uD83D\uDD0A":"1f50a","\uD83D\uDD0B":"1f50b","\uD83D\uDCA0":"1f4a0","\uD83D\uDD0C":"1f50c","\uD83D\uDD0D":"1f50d","\uD83D\uDCA1":"1f4a1","\uD83D\uDD0E":"1f50e","\uD83D\uDD0F":"1f50f","\uD83D\uDCA2":"1f4a2","\uD83D\uDD10":"1f510","\uD83D\uDD11":"1f511","\uD83D\uDCA3":"1f4a3","\uD83D\uDD12":"1f512","\uD83D\uDD13":"1f513","\uD83D\uDCA4":"1f4a4","\uD83D\uDD14":"1f514","\uD83D\uDD16":"1f516","\uD83D\uDCA5":"1f4a5","\uD83D\uDD17":"1f517","\uD83D\uDD18":"1f518","\uD83D\uDCA6":"1f4a6","\uD83D\uDD19":"1f519","\uD83D\uDD1A":"1f51a","\uD83D\uDCA7":"1f4a7","\uD83D\uDD1B":"1f51b","\uD83D\uDD1C":"1f51c","\uD83D\uDCA8":"1f4a8","\uD83D\uDD1D":"1f51d","\uD83D\uDD1E":"1f51e","\uD83D\uDCA9":"1f4a9","\uD83D\uDD1F":"1f51f","\uD83D\uDCAA":"1f4aa","\uD83D\uDD20":"1f520","\uD83D\uDD21":"1f521","\uD83D\uDCAB":"1f4ab","\uD83D\uDD22":"1f522","\uD83D\uDD23":"1f523","\uD83D\uDCAC":"1f4ac","\uD83D\uDD24":"1f524","\uD83D\uDD25":"1f525","\uD83D\uDCAE":"1f4ae","\uD83D\uDD26":"1f526","\uD83D\uDD27":"1f527","\uD83D\uDCAF":"1f4af","\uD83D\uDD28":"1f528","\uD83D\uDD29":"1f529","\uD83D\uDCB0":"1f4b0","\uD83D\uDD2A":"1f52a","\uD83D\uDD2B":"1f52b","\uD83D\uDCB1":"1f4b1","\uD83D\uDD2E":"1f52e","\uD83D\uDCB2":"1f4b2","\uD83D\uDD2F":"1f52f","\uD83D\uDCB3":"1f4b3","\uD83D\uDD30":"1f530","\uD83D\uDD31":"1f531","\uD83D\uDCB4":"1f4b4","\uD83D\uDD32":"1f532","\uD83D\uDD33":"1f533","\uD83D\uDCB5":"1f4b5","\uD83D\uDD34":"1f534","\uD83D\uDD35":"1f535","\uD83D\uDCB8":"1f4b8","\uD83D\uDD36":"1f536","\uD83D\uDD37":"1f537","\uD83D\uDCB9":"1f4b9","\uD83D\uDD38":"1f538","\uD83D\uDD39":"1f539","\uD83D\uDCBA":"1f4ba","\uD83D\uDD3A":"1f53a","\uD83D\uDD3B":"1f53b","\uD83D\uDCBB":"1f4bb","\uD83D\uDD3C":"1f53c","\uD83D\uDCBC":"1f4bc","\uD83D\uDD3D":"1f53d","\uD83D\uDD50":"1f550","\uD83D\uDCBD":"1f4bd","\uD83D\uDD51":"1f551","\uD83D\uDCBE":"1f4be","\uD83D\uDD52":"1f552","\uD83D\uDCBF":"1f4bf","\uD83D\uDD53":"1f553","\uD83D\uDCC0":"1f4c0","\uD83D\uDD54":"1f554","\uD83D\uDD55":"1f555","\uD83D\uDCC1":"1f4c1","\uD83D\uDD56":"1f556","\uD83D\uDD57":"1f557","\uD83D\uDCC2":"1f4c2","\uD83D\uDD58":"1f558","\uD83D\uDD59":"1f559","\uD83D\uDCC3":"1f4c3","\uD83D\uDD5A":"1f55a","\uD83D\uDD5B":"1f55b","\uD83D\uDCC4":"1f4c4","\uD83D\uDDFB":"1f5fb","\uD83D\uDDFC":"1f5fc","\uD83D\uDCC5":"1f4c5","\uD83D\uDDFD":"1f5fd","\uD83D\uDDFE":"1f5fe","\uD83D\uDCC6":"1f4c6","\uD83D\uDDFF":"1f5ff","\uD83D\uDE01":"1f601","\uD83D\uDE02":"1f602","\uD83D\uDE03":"1f603","\uD83D\uDCC8":"1f4c8","\uD83D\uDE04":"1f604","\uD83D\uDE05":"1f605","\uD83D\uDCC9":"1f4c9","\uD83D\uDE06":"1f606","\uD83D\uDE09":"1f609","\uD83D\uDCCA":"1f4ca","\uD83D\uDE0A":"1f60a","\uD83D\uDE0B":"1f60b","\uD83D\uDCCB":"1f4cb","\uD83D\uDE0C":"1f60c","\uD83D\uDE0D":"1f60d","\uD83D\uDCCC":"1f4cc","\uD83D\uDE0F":"1f60f","\uD83D\uDE12":"1f612","\uD83D\uDCCD":"1f4cd","\uD83D\uDE13":"1f613","\uD83D\uDE14":"1f614","\uD83D\uDCCE":"1f4ce","\uD83D\uDE16":"1f616","\uD83D\uDE18":"1f618","\uD83D\uDCCF":"1f4cf","\uD83D\uDE1A":"1f61a","\uD83D\uDE1C":"1f61c","\uD83D\uDCD0":"1f4d0","\uD83D\uDE1D":"1f61d","\uD83D\uDE1E":"1f61e","\uD83D\uDCD1":"1f4d1","\uD83D\uDE20":"1f620","\uD83D\uDE21":"1f621","\uD83D\uDE22":"1f622","\uD83D\uDE23":"1f623","\uD83D\uDE24":"1f624","\uD83D\uDE25":"1f625","\uD83D\uDE28":"1f628","\uD83D\uDE29":"1f629","\uD83D\uDE2A":"1f62a","\uD83D\uDE2B":"1f62b","\uD83D\uDE2D":"1f62d","\uD83D\uDE30":"1f630","\uD83D\uDE31":"1f631","\uD83D\uDE32":"1f632","\uD83D\uDE33":"1f633","\uD83D\uDE35":"1f635","\uD83D\uDE37":"1f637","\uD83D\uDE38":"1f638","\uD83D\uDE39":"1f639","\uD83D\uDE3A":"1f63a","\uD83D\uDE3B":"1f63b","\uD83D\uDE3C":"1f63c","\uD83D\uDE3D":"1f63d","\uD83D\uDE3E":"1f63e","\uD83D\uDE3F":"1f63f","\uD83D\uDE40":"1f640","\uD83D\uDE45":"1f645","\uD83D\uDE46":"1f646","\uD83D\uDE47":"1f647","\uD83D\uDE48":"1f648","\uD83D\uDE49":"1f649","\uD83D\uDE4A":"1f64a","\uD83D\uDE4B":"1f64b","\uD83D\uDE4C":"1f64c","\uD83D\uDE4D":"1f64d","\uD83D\uDE4E":"1f64e","\uD83D\uDE4F":"1f64f","\uD83D\uDE80":"1f680","\uD83D\uDE83":"1f683","\uD83D\uDE84":"1f684","\uD83D\uDE85":"1f685","\uD83D\uDE87":"1f687","\uD83D\uDE89":"1f689","\uD83D\uDE8C":"1f68c","\uD83D\uDE8F":"1f68f","\uD83D\uDE91":"1f691","\uD83D\uDE92":"1f692","\uD83D\uDE93":"1f693","\uD83D\uDE95":"1f695","\uD83D\uDE97":"1f697","\uD83D\uDE99":"1f699","\uD83D\uDE9A":"1f69a","\uD83D\uDEA2":"1f6a2","\uD83D\uDEA4":"1f6a4","\uD83D\uDEA5":"1f6a5","\uD83D\uDEA7":"1f6a7","\uD83D\uDEA8":"1f6a8","\uD83D\uDEA9":"1f6a9","\uD83D\uDEAA":"1f6aa","\uD83D\uDEAB":"1f6ab","\uD83D\uDEAC":"1f6ac","\uD83D\uDEAD":"1f6ad","\uD83D\uDEB2":"1f6b2","\uD83D\uDEB6":"1f6b6","\uD83D\uDEB9":"1f6b9","\uD83D\uDEBA":"1f6ba","\uD83D\uDEBB":"1f6bb","\uD83D\uDEBC":"1f6bc","\uD83D\uDEBD":"1f6bd","\uD83D\uDEBE":"1f6be","\uD83D\uDEC0":"1f6c0","\uD83E\uDD18":"1f918","\uD83D\uDE00":"1f600","\uD83D\uDE07":"1f607","\uD83D\uDE08":"1f608","\uD83D\uDE0E":"1f60e","\uD83D\uDE10":"1f610","\uD83D\uDE11":"1f611","\uD83D\uDE15":"1f615","\uD83D\uDE17":"1f617","\uD83D\uDE19":"1f619","\uD83D\uDE1B":"1f61b","\uD83D\uDE1F":"1f61f","\uD83D\uDE26":"1f626","\uD83D\uDE27":"1f627","\uD83D\uDE2C":"1f62c","\uD83D\uDE2E":"1f62e","\uD83D\uDE2F":"1f62f","\uD83D\uDE34":"1f634","\uD83D\uDE36":"1f636","\uD83D\uDE81":"1f681","\uD83D\uDE82":"1f682","\uD83D\uDE86":"1f686","\uD83D\uDE88":"1f688","\uD83D\uDE8A":"1f68a","\uD83D\uDE8D":"1f68d","\uD83D\uDE8E":"1f68e","\uD83D\uDE90":"1f690","\uD83D\uDE94":"1f694","\uD83D\uDE96":"1f696","\uD83D\uDE98":"1f698","\uD83D\uDE9B":"1f69b","\uD83D\uDE9C":"1f69c","\uD83D\uDE9D":"1f69d","\uD83D\uDE9E":"1f69e","\uD83D\uDE9F":"1f69f","\uD83D\uDEA0":"1f6a0","\uD83D\uDEA1":"1f6a1","\uD83D\uDEA3":"1f6a3","\uD83D\uDEA6":"1f6a6","\uD83D\uDEAE":"1f6ae","\uD83D\uDEAF":"1f6af","\uD83D\uDEB0":"1f6b0","\uD83D\uDEB1":"1f6b1","\uD83D\uDEB3":"1f6b3","\uD83D\uDEB4":"1f6b4","\uD83D\uDEB5":"1f6b5","\uD83D\uDEB7":"1f6b7","\uD83D\uDEB8":"1f6b8","\uD83D\uDEBF":"1f6bf","\uD83D\uDEC1":"1f6c1","\uD83D\uDEC2":"1f6c2","\uD83D\uDEC3":"1f6c3","\uD83D\uDEC4":"1f6c4","\uD83D\uDEC5":"1f6c5","\uD83C\uDF0D":"1f30d","\uD83C\uDF0E":"1f30e","\uD83C\uDF10":"1f310","\uD83C\uDF12":"1f312","\uD83C\uDF16":"1f316","\uD83C\uDF17":"1f317","\uD83C\uDF18":"1f318","\uD83C\uDF1A":"1f31a","\uD83C\uDF1C":"1f31c","\uD83C\uDF1D":"1f31d","\uD83C\uDF1E":"1f31e","\uD83C\uDF32":"1f332","\uD83C\uDF33":"1f333","\uD83C\uDF4B":"1f34b","\uD83C\uDF50":"1f350","\uD83C\uDF7C":"1f37c","\uD83C\uDFC7":"1f3c7","\uD83C\uDFC9":"1f3c9","\uD83C\uDFE4":"1f3e4","\uD83D\uDC00":"1f400","\uD83D\uDC01":"1f401","\uD83D\uDC02":"1f402","\uD83D\uDC03":"1f403","\uD83D\uDC04":"1f404","\uD83D\uDC05":"1f405","\uD83D\uDC06":"1f406","\uD83D\uDC07":"1f407","\uD83D\uDC08":"1f408","\uD83D\uDC09":"1f409","\uD83D\uDC0A":"1f40a","\uD83D\uDC0B":"1f40b","\uD83D\uDC0F":"1f40f","\uD83D\uDC10":"1f410","\uD83D\uDC13":"1f413","\uD83D\uDC15":"1f415","\uD83D\uDC16":"1f416","\uD83D\uDC2A":"1f42a","\uD83D\uDC65":"1f465","\uD83D\uDC6C":"1f46c","\uD83D\uDC6D":"1f46d","\uD83D\uDCAD":"1f4ad","\uD83D\uDCB6":"1f4b6","\uD83D\uDCB7":"1f4b7","\uD83D\uDCEC":"1f4ec","\uD83D\uDCED":"1f4ed","\uD83D\uDCEF":"1f4ef","\uD83D\uDCF5":"1f4f5","\uD83D\uDD00":"1f500","\uD83D\uDD01":"1f501","\uD83D\uDD02":"1f502","\uD83D\uDD04":"1f504","\uD83D\uDD05":"1f505","\uD83D\uDD06":"1f506","\uD83D\uDD07":"1f507","\uD83D\uDD09":"1f509","\uD83D\uDD15":"1f515","\uD83D\uDD2C":"1f52c","\uD83D\uDD2D":"1f52d","\uD83D\uDD5C":"1f55c","\uD83D\uDD5D":"1f55d","\uD83D\uDD5E":"1f55e","\uD83D\uDD5F":"1f55f","\uD83D\uDD60":"1f560","\uD83D\uDD61":"1f561","\uD83D\uDD62":"1f562","\uD83D\uDD63":"1f563","\uD83D\uDD64":"1f564","\uD83D\uDD65":"1f565","\uD83D\uDD66":"1f566","\uD83D\uDD67":"1f567","\uD83D\uDD08":"1f508","\uD83D\uDE8B":"1f68b","\uD83C\uDFC5":"1f3c5","\uD83C\uDFF4":"1f3f4","\uD83D\uDCF8":"1f4f8","\uD83D\uDECC":"1f6cc","\uD83D\uDD95":"1f595","\uD83D\uDD96":"1f596","\uD83D\uDE41":"1f641","\uD83D\uDE42":"1f642","\uD83D\uDEEB":"1f6eb","\uD83D\uDEEC":"1f6ec","\uD83C\uDFFB":"1f3fb","\uD83C\uDFFC":"1f3fc","\uD83C\uDFFD":"1f3fd","\uD83C\uDFFE":"1f3fe","\uD83C\uDFFF":"1f3ff","\uD83D\uDE43":"1f643","\uD83E\uDD11":"1f911","\uD83E\uDD13":"1f913","\uD83E\uDD17":"1f917","\uD83D\uDE44":"1f644","\uD83E\uDD14":"1f914","\uD83E\uDD10":"1f910","\uD83E\uDD12":"1f912","\uD83E\uDD15":"1f915","\uD83E\uDD16":"1f916","\uD83E\uDD81":"1f981","\uD83E\uDD84":"1f984","\uD83E\uDD82":"1f982","\uD83E\uDD80":"1f980","\uD83E\uDD83":"1f983","\uD83E\uDDC0":"1f9c0","\uD83C\uDF2D":"1f32d","\uD83C\uDF2E":"1f32e","\uD83C\uDF2F":"1f32f","\uD83C\uDF7F":"1f37f","\uD83C\uDF7E":"1f37e","\uD83C\uDFF9":"1f3f9","\uD83C\uDFFA":"1f3fa","\uD83D\uDED0":"1f6d0","\uD83D\uDD4B":"1f54b","\uD83D\uDD4C":"1f54c","\uD83D\uDD4D":"1f54d","\uD83D\uDD4E":"1f54e","\uD83D\uDCFF":"1f4ff","\uD83C\uDFCF":"1f3cf","\uD83C\uDFD0":"1f3d0","\uD83C\uDFD1":"1f3d1","\uD83C\uDFD2":"1f3d2","\uD83C\uDFD3":"1f3d3","\uD83C\uDFF8":"1f3f8","\uD83E\uDD41":"1f941","\uD83E\uDD90":"1f990","\uD83E\uDD91":"1f991","\uD83E\uDD5A":"1f95a","\uD83E\uDD5B":"1f95b","\uD83E\uDD5C":"1f95c","\uD83E\uDD5D":"1f95d","\uD83E\uDD5E":"1f95e","\uD83C\uDDFC":"1f1fc","\uD83C\uDDFB":"1f1fb","\uD83C\uDDFA":"1f1fa","\uD83C\uDDF9":"1f1f9","\uD83C\uDDF8":"1f1f8","\uD83C\uDDF7":"1f1f7","\uD83C\uDDF6":"1f1f6","\uD83C\uDDF5":"1f1f5","\uD83C\uDDF4":"1f1f4","\uD83C\uDDF3":"1f1f3","\uD83C\uDDF2":"1f1f2","\uD83C\uDDF1":"1f1f1","\uD83C\uDDF0":"1f1f0","\uD83C\uDDEF":"1f1ef","\uD83C\uDDEE":"1f1ee","\uD83C\uDDED":"1f1ed","\uD83C\uDDEC":"1f1ec","\uD83C\uDDEB":"1f1eb","\uD83C\uDDEA":"1f1ea","\uD83C\uDDE9":"1f1e9","\uD83C\uDDE8":"1f1e8","\uD83C\uDDE7":"1f1e7","\uD83C\uDDE6":"1f1e6","\uD83D\uDEF7":"1f6f7","\uD83D\uDEF8":"1f6f8","\uD83E\uDD1F":"1f91f","\uD83E\uDD28":"1f928","\uD83E\uDD29":"1f929","\uD83E\uDD2A":"1f92a","\uD83E\uDD2B":"1f92b","\uD83E\uDD2C":"1f92c","\uD83E\uDD2D":"1f92d","\uD83E\uDD2E":"1f92e","\uD83E\uDD2F":"1f92f","\uD83E\uDD31":"1f931","\uD83E\uDD32":"1f932","\uD83E\uDD4C":"1f94c","\uD83E\uDD5F":"1f95f","\uD83E\uDD60":"1f960","\uD83E\uDD61":"1f961","\uD83E\uDD62":"1f962","\uD83E\uDD63":"1f963","\uD83E\uDD64":"1f964","\uD83E\uDD65":"1f965","\uD83E\uDD66":"1f966","\uD83E\uDD67":"1f967","\uD83E\uDD68":"1f968","\uD83E\uDD69":"1f969","\uD83E\uDD6A":"1f96a","\uD83E\uDD6B":"1f96b","\uD83E\uDD92":"1f992","\uD83E\uDD93":"1f993","\uD83E\uDD94":"1f994","\uD83E\uDD95":"1f995","\uD83E\uDD96":"1f996","\uD83E\uDD97":"1f997","\uD83E\uDDD0":"1f9d0","\uD83E\uDDD1":"1f9d1","\uD83E\uDDD2":"1f9d2","\uD83E\uDDD3":"1f9d3","\uD83E\uDDD4":"1f9d4","\uD83E\uDDD5":"1f9d5","\uD83E\uDDD6":"1f9d6","\uD83E\uDDD7":"1f9d7","\uD83E\uDDD8":"1f9d8","\uD83E\uDDD9":"1f9d9","\uD83E\uDDDA":"1f9da","\uD83E\uDDDB":"1f9db","\uD83E\uDDDC":"1f9dc","\uD83E\uDDDD":"1f9dd","\uD83E\uDDDE":"1f9de","\uD83E\uDDDF":"1f9df","\uD83E\uDDE0":"1f9e0","\uD83E\uDDE1":"1f9e1","\uD83E\uDDE2":"1f9e2","\uD83E\uDDE3":"1f9e3","\uD83E\uDDE4":"1f9e4","\uD83E\uDDE5":"1f9e5","\uD83E\uDDE6":"1f9e6","\u231A":"231a","\u231B":"231b","\u23E9":"23e9","\u23EA":"23ea","\u23EB":"23eb","\u23EC":"23ec","\u23F0":"23f0","\u23F3":"23f3","\u25FD":"25fd","\u25FE":"25fe","\u2614":"2614","\u2615":"2615","\u2648":"2648","\u2649":"2649","\u264A":"264a","\u264B":"264b","\u264C":"264c","\u264D":"264d","\u264E":"264e","\u264F":"264f","\u2650":"2650","\u2651":"2651","\u2652":"2652","\u2653":"2653","\u267F":"267f","\u2693":"2693","\u26A1":"26a1","\u26AA":"26aa","\u26AB":"26ab","\u26BD":"26bd","\u26BE":"26be","\u26C4":"26c4","\u26C5":"26c5","\u26CE":"26ce","\u26D4":"26d4","\u26EA":"26ea","\u26F2":"26f2","\u26F3":"26f3","\u26F5":"26f5","\u26FA":"26fa","\u26FD":"26fd","\u2705":"2705","\u270A":"270a","\u270B":"270b","\u2728":"2728","\u274C":"274c","\u274E":"274e","\u2753":"2753","\u2754":"2754","\u2755":"2755","\u2757":"2757","\u2795":"2795","\u2796":"2796","\u2797":"2797","\u27B0":"27b0","\u2B1B":"2b1b","\u2B1C":"2b1c","\u2B50":"2b50","\u2B55":"2b55","\u27BF":"27bf"};
  9571. ns.jsEscapeMapGreedy = {"\uD83D\uDC69\u2764\uD83D\uDC8B\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u2764\uD83D\uDC8B\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC69\u2764\uD83D\uDC8B\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83D\uDC69\u2764\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\u2764\uD83D\uDC68":"1f468-2764-1f468","\uD83C\uDFCC\uD83C\uDFFB\u2642":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uD83C\uDFFC\u2642":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uD83C\uDFFD\u2642":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uD83C\uDFFE\u2642":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uD83C\uDFFF\u2642":"1f3cc-1f3ff-2642","\uD83C\uDFCC\uD83C\uDFFB\u2640":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uD83C\uDFFC\u2640":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uD83C\uDFFD\u2640":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uD83C\uDFFE\u2640":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uD83C\uDFFF\u2640":"1f3cc-1f3ff-2640","\uD83D\uDC68\uD83C\uDFFB\u2696":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFC\u2696":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFD\u2696":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFE\u2696":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFF\u2696":"1f468-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFB\u2696":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFC\u2696":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFD\u2696":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFE\u2696":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFF\u2696":"1f469-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFB\u2708":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u2708":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u2708":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u2708":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u2708":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u2708":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u2708":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u2708":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u2708":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u2708":"1f469-1f3ff-2708","\uD83D\uDC69\u2764\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDC68\uD83C\uDFFB\u2695":"1f468-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFC\u2695":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFD\u2695":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFE\u2695":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFF\u2695":"1f468-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFB\u2695":"1f469-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFC\u2695":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFD\u2695":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFE\u2695":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFF\u2695":"1f469-1f3ff-2695","\uD83D\uDC6E\uD83C\uDFFB\u2640":"1f46e-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFB\u2642":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFC\u2640":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFC\u2642":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFD\u2640":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFD\u2642":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFE\u2640":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFE\u2642":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFF\u2640":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFF\u2642":"1f46e-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFB\u2640":"1f471-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFB\u2642":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFC\u2640":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFC\u2642":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFD\u2640":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFD\u2642":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFE\u2640":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFE\u2642":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFF\u2640":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFF\u2642":"1f471-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFB\u2640":"1f473-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFB\u2642":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFC\u2640":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFC\u2642":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFD\u2640":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFD\u2642":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFE\u2640":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFE\u2642":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFF\u2640":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFF\u2642":"1f473-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFB\u2640":"1f477-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFB\u2642":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFC\u2640":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFC\u2642":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFD\u2640":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFD\u2642":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFE\u2640":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFE\u2642":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFF\u2640":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFF\u2642":"1f477-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFB\u2640":"1f482-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFB\u2642":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFC\u2640":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFC\u2642":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFD\u2640":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFD\u2642":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFE\u2640":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFE\u2642":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFF\u2640":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFF\u2642":"1f482-1f3ff-2642","\uD83D\uDD75\uD83C\uDFFB\u2640":"1f575-1f3fb-2640","\uD83D\uDD75\uD83C\uDFFB\u2642":"1f575-1f3fb-2642","\uD83D\uDD75\uD83C\uDFFC\u2640":"1f575-1f3fc-2640","\uD83D\uDD75\uD83C\uDFFC\u2642":"1f575-1f3fc-2642","\uD83D\uDD75\uD83C\uDFFD\u2640":"1f575-1f3fd-2640","\uD83D\uDD75\uD83C\uDFFD\u2642":"1f575-1f3fd-2642","\uD83D\uDD75\uD83C\uDFFE\u2640":"1f575-1f3fe-2640","\uD83D\uDD75\uD83C\uDFFE\u2642":"1f575-1f3fe-2642","\uD83D\uDD75\uD83C\uDFFF\u2640":"1f575-1f3ff-2640","\uD83D\uDD75\uD83C\uDFFF\u2642":"1f575-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFB\u2640":"1f3c3-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFB\u2642":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFC\u2640":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFC\u2642":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFD\u2640":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFD\u2642":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFE\u2640":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFE\u2642":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFF\u2640":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFF\u2642":"1f3c3-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFB\u2640":"1f3c4-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFB\u2642":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFC\u2640":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFC\u2642":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFD\u2640":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFD\u2642":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFE\u2640":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFE\u2642":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFF\u2640":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFF\u2642":"1f3c4-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFB\u2640":"1f3ca-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFB\u2642":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFC\u2640":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFC\u2642":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFD\u2640":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFD\u2642":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFE\u2640":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFE\u2642":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFF\u2640":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFF\u2642":"1f3ca-1f3ff-2642","\uD83C\uDFCB\uD83C\uDFFB\u2640":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uD83C\uDFFB\u2642":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uD83C\uDFFC\u2640":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uD83C\uDFFC\u2642":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uD83C\uDFFD\u2640":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uD83C\uDFFD\u2642":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uD83C\uDFFE\u2640":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uD83C\uDFFE\u2642":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uD83C\uDFFF\u2640":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uD83C\uDFFF\u2642":"1f3cb-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFB\u2640":"1f486-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFB\u2642":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFC\u2640":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFC\u2642":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFD\u2640":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFD\u2642":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFE\u2640":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFE\u2642":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFF\u2640":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFF\u2642":"1f486-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFB\u2640":"1f487-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFB\u2642":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFC\u2640":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFC\u2642":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFD\u2640":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFD\u2642":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFE\u2640":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFE\u2642":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFF\u2640":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFF\u2642":"1f487-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFB\u2640":"1f6a3-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFB\u2642":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFC\u2640":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFC\u2642":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFD\u2640":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFD\u2642":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFE\u2640":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFE\u2642":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFF\u2640":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFF\u2642":"1f6a3-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFB\u2640":"1f6b4-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFB\u2642":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFC\u2640":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFC\u2642":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFD\u2640":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFD\u2642":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFE\u2640":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFE\u2642":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFF\u2640":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFF\u2642":"1f6b4-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFB\u2640":"1f6b5-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFB\u2642":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFC\u2640":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFC\u2642":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFD\u2640":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFD\u2642":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFE\u2640":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFE\u2642":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFF\u2640":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFF\u2642":"1f6b5-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFB\u2640":"1f6b6-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFB\u2642":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFC\u2640":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFC\u2642":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFD\u2640":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFD\u2642":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFE\u2640":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFE\u2642":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFF\u2640":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFF\u2642":"1f6b6-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFB\u2640":"1f938-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFB\u2642":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFC\u2640":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFC\u2642":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFD\u2640":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFD\u2642":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFE\u2640":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFE\u2642":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFF\u2640":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFF\u2642":"1f938-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFB\u2640":"1f939-1f3fb-2640","\uD83E\uDD39\uD83C\uDFFB\u2642":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFC\u2640":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFC\u2642":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFD\u2640":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFD\u2642":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFE\u2640":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFE\u2642":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFF\u2640":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u2642":"1f939-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFB\u2640":"1f93d-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFB\u2642":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFC\u2640":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFC\u2642":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFD\u2640":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFD\u2642":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFE\u2640":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFE\u2642":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFF\u2640":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFF\u2642":"1f93d-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFB\u2640":"1f93e-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFB\u2642":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFC\u2640":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFC\u2642":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFD\u2640":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFD\u2642":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFE\u2640":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFE\u2642":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFF\u2640":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFF\u2642":"1f93e-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFB\u2640":"1f481-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFB\u2642":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFC\u2640":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFC\u2642":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFD\u2640":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFD\u2642":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFE\u2640":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFE\u2642":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFF\u2640":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFF\u2642":"1f481-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFB\u2640":"1f645-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFB\u2642":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFC\u2640":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFC\u2642":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFD\u2640":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFD\u2642":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFE\u2640":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFE\u2642":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFF\u2640":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFF\u2642":"1f645-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFB\u2640":"1f646-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFB\u2642":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFC\u2640":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFC\u2642":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFD\u2640":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFD\u2642":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFE\u2640":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFE\u2642":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFF\u2640":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFF\u2642":"1f646-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFB\u2640":"1f647-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFB\u2642":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFC\u2640":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFC\u2642":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFD\u2640":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFD\u2642":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFE\u2640":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFE\u2642":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFF\u2640":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFF\u2642":"1f647-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFB\u2640":"1f64b-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFB\u2642":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFC\u2640":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFC\u2642":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFD\u2640":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFD\u2642":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFE\u2640":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFE\u2642":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFF\u2640":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFF\u2642":"1f64b-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFB\u2640":"1f64d-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFB\u2642":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFC\u2640":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFC\u2642":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFD\u2640":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFD\u2642":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFE\u2640":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFE\u2642":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFF\u2640":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFF\u2642":"1f64d-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFB\u2640":"1f64e-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFB\u2642":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFC\u2640":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFC\u2642":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFD\u2640":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFD\u2642":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFE\u2640":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFE\u2642":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFF\u2640":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFF\u2642":"1f64e-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFB\u2640":"1f926-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFB\u2642":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFC\u2640":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFC\u2642":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFD\u2640":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFD\u2642":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFE\u2640":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFE\u2642":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFF\u2640":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFF\u2642":"1f926-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFB\u2640":"1f937-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFB\u2642":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFC\u2640":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFC\u2642":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFD\u2640":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFD\u2642":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFE\u2640":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFE\u2642":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFF\u2640":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFF\u2642":"1f937-1f3ff-2642","\uD83E\uDDD9\uD83C\uDFFB\u2640":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u2642":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFC\u2640":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u2642":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFD\u2640":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u2642":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFE\u2640":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u2642":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFF\u2640":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u2642":"1f9d9-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFB\u2640":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u2642":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFC\u2640":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u2642":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFD\u2640":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u2642":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFE\u2640":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u2642":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFF\u2640":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u2642":"1f9da-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFB\u2640":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u2642":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFC\u2640":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u2642":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFD\u2640":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u2642":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFE\u2640":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u2642":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFF\u2640":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u2642":"1f9db-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFB\u2640":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u2642":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFC\u2640":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u2642":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFD\u2640":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u2642":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFE\u2640":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u2642":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFF\u2640":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u2642":"1f9dc-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFB\u2640":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u2642":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFC\u2640":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u2642":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFD\u2640":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u2642":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFE\u2640":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u2642":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFF\u2640":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u2642":"1f9dd-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFB\u2640":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u2642":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFC\u2640":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u2642":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFD\u2640":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u2642":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFE\u2640":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u2642":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFF\u2640":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u2642":"1f9d6-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFB\u2640":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u2642":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFC\u2640":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u2642":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFD\u2640":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u2642":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFE\u2640":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u2642":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFF\u2640":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u2642":"1f9d7-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFB\u2640":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u2642":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFC\u2640":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u2642":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFD\u2640":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u2642":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFE\u2640":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u2642":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFF\u2640":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u2642":"1f9d8-1f3ff-2642","\u26F9\uD83C\uDFFB\u2640":"26f9-1f3fb-2640","\u26F9\uD83C\uDFFB\u2642":"26f9-1f3fb-2642","\u26F9\uD83C\uDFFC\u2640":"26f9-1f3fc-2640","\u26F9\uD83C\uDFFC\u2642":"26f9-1f3fc-2642","\u26F9\uD83C\uDFFD\u2640":"26f9-1f3fd-2640","\u26F9\uD83C\uDFFD\u2642":"26f9-1f3fd-2642","\u26F9\uD83C\uDFFE\u2640":"26f9-1f3fe-2640","\u26F9\uD83C\uDFFE\u2642":"26f9-1f3fe-2642","\u26F9\uD83C\uDFFF\u2640":"26f9-1f3ff-2640","\u26F9\uD83C\uDFFF\u2642":"26f9-1f3ff-2642","\uD83C\uDFF3\uD83C\uDF08":"1f3f3-1f308","\uD83D\uDC41\uD83D\uDDE8":"1f441-1f5e8","\uD83D\uDC6F\u2642":"1f46f-2642","\uD83D\uDC6F\u2640":"1f46f-2640","\uD83C\uDFCC\u2642":"1f3cc-2642","\uD83C\uDFCC\u2640":"1f3cc-2640","\uD83E\uDD3C\u2642":"1f93c-2642","\uD83E\uDD3C\u2640":"1f93c-2640","\uD83E\uDD39\u2642":"1f939-2642","\uD83E\uDD39\u2640":"1f939-2640","\uD83E\uDD3E\u2642":"1f93e-2642","\uD83E\uDD3E\u2640":"1f93e-2640","\uD83E\uDD3D\u2642":"1f93d-2642","\uD83E\uDD3D\u2640":"1f93d-2640","\uD83E\uDD38\u2642":"1f938-2642","\uD83E\uDD38\u2640":"1f938-2640","\uD83D\uDEB6\u2642":"1f6b6-2642","\uD83D\uDEB6\u2640":"1f6b6-2640","\uD83D\uDEB5\u2642":"1f6b5-2642","\uD83D\uDEB5\u2640":"1f6b5-2640","\uD83D\uDEB4\u2642":"1f6b4-2642","\uD83D\uDEB4\u2640":"1f6b4-2640","\uD83D\uDEA3\u2642":"1f6a3-2642","\uD83D\uDEA3\u2640":"1f6a3-2640","\uD83C\uDFCB\u2642":"1f3cb-2642","\uD83C\uDFCB\u2640":"1f3cb-2640","\uD83C\uDFCA\u2642":"1f3ca-2642","\uD83C\uDFCA\u2640":"1f3ca-2640","\uD83C\uDFC4\u2642":"1f3c4-2642","\uD83C\uDFC4\u2640":"1f3c4-2640","\uD83C\uDFC3\u2642":"1f3c3-2642","\uD83C\uDFC3\u2640":"1f3c3-2640","\uD83E\uDD37\u2642":"1f937-2642","\uD83E\uDD37\u2640":"1f937-2640","\uD83E\uDD26\u2642":"1f926-2642","\uD83E\uDD26\u2640":"1f926-2640","\uD83D\uDE4E\u2642":"1f64e-2642","\uD83D\uDE4E\u2640":"1f64e-2640","\uD83D\uDE4D\u2642":"1f64d-2642","\uD83D\uDE4D\u2640":"1f64d-2640","\uD83D\uDE4B\u2642":"1f64b-2642","\uD83D\uDE4B\u2640":"1f64b-2640","\uD83D\uDE47\u2642":"1f647-2642","\uD83D\uDE47\u2640":"1f647-2640","\uD83D\uDE46\u2642":"1f646-2642","\uD83D\uDE46\u2640":"1f646-2640","\uD83D\uDE45\u2642":"1f645-2642","\uD83D\uDE45\u2640":"1f645-2640","\uD83D\uDC87\u2642":"1f487-2642","\uD83D\uDC87\u2640":"1f487-2640","\uD83D\uDC86\u2642":"1f486-2642","\uD83D\uDC86\u2640":"1f486-2640","\uD83D\uDC81\u2642":"1f481-2642","\uD83D\uDC81\u2640":"1f481-2640","\uD83D\uDC71\u2642":"1f471-2642","\uD83D\uDC71\u2640":"1f471-2640","\uD83D\uDC73\u2642":"1f473-2642","\uD83D\uDC73\u2640":"1f473-2640","\uD83D\uDC82\u2642":"1f482-2642","\uD83D\uDC82\u2640":"1f482-2640","\uD83D\uDD75\u2642":"1f575-2642","\uD83D\uDD75\u2640":"1f575-2640","\uD83D\uDC77\u2642":"1f477-2642","\uD83D\uDC77\u2640":"1f477-2640","\uD83D\uDC6E\u2642":"1f46e-2642","\uD83D\uDC6E\u2640":"1f46e-2640","\uD83D\uDC68\u2695":"1f468-2695","\uD83D\uDC69\u2695":"1f469-2695","\uD83D\uDC68\u2696":"1f468-2696","\uD83D\uDC69\u2696":"1f469-2696","\uD83D\uDC68\u2708":"1f468-2708","\uD83D\uDC69\u2708":"1f469-2708","\uD83E\uDDD9\u2640":"1f9d9-2640","\uD83E\uDDD9\u2642":"1f9d9-2642","\uD83E\uDDDA\u2640":"1f9da-2640","\uD83E\uDDDA\u2642":"1f9da-2642","\uD83E\uDDDB\u2640":"1f9db-2640","\uD83E\uDDDB\u2642":"1f9db-2642","\uD83E\uDDDC\u2640":"1f9dc-2640","\uD83E\uDDDC\u2642":"1f9dc-2642","\uD83E\uDDDD\u2640":"1f9dd-2640","\uD83E\uDDDD\u2642":"1f9dd-2642","\uD83E\uDDDE\u2640":"1f9de-2640","\uD83E\uDDDE\u2642":"1f9de-2642","\uD83E\uDDDF\u2640":"1f9df-2640","\uD83E\uDDDF\u2642":"1f9df-2642","\uD83E\uDDD6\u2640":"1f9d6-2640","\uD83E\uDDD6\u2642":"1f9d6-2642","\uD83E\uDDD7\u2640":"1f9d7-2640","\uD83E\uDDD7\u2642":"1f9d7-2642","\uD83E\uDDD8\u2640":"1f9d8-2640","\uD83E\uDDD8\u2642":"1f9d8-2642","\u26F9\u2642":"26f9-2642","\u26F9\u2640":"26f9-2640","\uD83C\uDD70":"1f170","\uD83C\uDD71":"1f171","\uD83C\uDD7E":"1f17e","\uD83C\uDD7F":"1f17f","\uD83C\uDE02":"1f202","\uD83C\uDE37":"1f237","\uD83C\uDF9E":"1f39e","\uD83C\uDF9F":"1f39f","\uD83C\uDFCB":"1f3cb","\uD83C\uDFCC":"1f3cc","\uD83C\uDFCD":"1f3cd","\uD83C\uDFCE":"1f3ce","\uD83C\uDF96":"1f396","\uD83C\uDF97":"1f397","\uD83C\uDF36":"1f336","\uD83C\uDF27":"1f327","\uD83C\uDF28":"1f328","\uD83C\uDF29":"1f329","\uD83C\uDF2A":"1f32a","\uD83C\uDF2B":"1f32b","\uD83C\uDF2C":"1f32c","\uD83D\uDC3F":"1f43f","\uD83D\uDD77":"1f577","\uD83D\uDD78":"1f578","\uD83C\uDF21":"1f321","\uD83C\uDF99":"1f399","\uD83C\uDF9A":"1f39a","\uD83C\uDF9B":"1f39b","\uD83C\uDFF3":"1f3f3","\uD83C\uDFF5":"1f3f5","\uD83C\uDFF7":"1f3f7","\uD83D\uDCFD":"1f4fd","\uD83D\uDD49":"1f549","\uD83D\uDD4A":"1f54a","\uD83D\uDD6F":"1f56f","\uD83D\uDD70":"1f570","\uD83D\uDD73":"1f573","\uD83D\uDD76":"1f576","\uD83D\uDD79":"1f579","\uD83D\uDD87":"1f587","\uD83D\uDD8A":"1f58a","\uD83D\uDD8B":"1f58b","\uD83D\uDD8C":"1f58c","\uD83D\uDD8D":"1f58d","\uD83D\uDDA5":"1f5a5","\uD83D\uDDA8":"1f5a8","\uD83D\uDDB2":"1f5b2","\uD83D\uDDBC":"1f5bc","\uD83D\uDDC2":"1f5c2","\uD83D\uDDC3":"1f5c3","\uD83D\uDDC4":"1f5c4","\uD83D\uDDD1":"1f5d1","\uD83D\uDDD2":"1f5d2","\uD83D\uDDD3":"1f5d3","\uD83D\uDDDC":"1f5dc","\uD83D\uDDDD":"1f5dd","\uD83D\uDDDE":"1f5de","\uD83D\uDDE1":"1f5e1","\uD83D\uDDE3":"1f5e3","\uD83D\uDDE8":"1f5e8","\uD83D\uDDEF":"1f5ef","\uD83D\uDDF3":"1f5f3","\uD83D\uDDFA":"1f5fa","\uD83D\uDEE0":"1f6e0","\uD83D\uDEE1":"1f6e1","\uD83D\uDEE2":"1f6e2","\uD83D\uDEF0":"1f6f0","\uD83C\uDF7D":"1f37d","\uD83D\uDC41":"1f441","\uD83D\uDD74":"1f574","\uD83D\uDD75":"1f575","\uD83D\uDD90":"1f590","\uD83C\uDFD4":"1f3d4","\uD83C\uDFD5":"1f3d5","\uD83C\uDFD6":"1f3d6","\uD83C\uDFD7":"1f3d7","\uD83C\uDFD8":"1f3d8","\uD83C\uDFD9":"1f3d9","\uD83C\uDFDA":"1f3da","\uD83C\uDFDB":"1f3db","\uD83C\uDFDC":"1f3dc","\uD83C\uDFDD":"1f3dd","\uD83C\uDFDE":"1f3de","\uD83C\uDFDF":"1f3df","\uD83D\uDECB":"1f6cb","\uD83D\uDECD":"1f6cd","\uD83D\uDECE":"1f6ce","\uD83D\uDECF":"1f6cf","\uD83D\uDEE3":"1f6e3","\uD83D\uDEE4":"1f6e4","\uD83D\uDEE5":"1f6e5","\uD83D\uDEE9":"1f6e9","\uD83D\uDEF3":"1f6f3","\uD83C\uDF24":"1f324","\uD83C\uDF25":"1f325","\uD83C\uDF26":"1f326","\uD83D\uDDB1":"1f5b1","\u00A9":"00a9","\u00AE":"00ae","\u203C":"203c","\u2049":"2049","\u2122":"2122","\u2139":"2139","\u2194":"2194","\u2195":"2195","\u2196":"2196","\u2197":"2197","\u2198":"2198","\u2199":"2199","\u21A9":"21a9","\u21AA":"21aa","\u24C2":"24c2","\u25AA":"25aa","\u25AB":"25ab","\u25B6":"25b6","\u25C0":"25c0","\u25FB":"25fb","\u25FC":"25fc","\u2600":"2600","\u2601":"2601","\u260E":"260e","\u2611":"2611","\u261D":"261d","\u263A":"263a","*":"002a","\u2660":"2660","\u2663":"2663","\u2665":"2665","\u2666":"2666","\u2668":"2668","\u267B":"267b","\u26A0":"26a0","\u2702":"2702","\u2708":"2708","\u2709":"2709","\u270C":"270c","\u270F":"270f","\u2712":"2712","\u2714":"2714","\u2716":"2716","\u2733":"2733","\u2734":"2734","\u2744":"2744","\u2747":"2747","\u2764":"2764","\u27A1":"27a1","\u2934":"2934","\u2935":"2935","\u2B05":"2b05","\u2B06":"2b06","\u2B07":"2b07","\u3030":"3030","\u303D":"303d","\u3297":"3297","\u3299":"3299","#":"0023","\u271D":"271d","\u2328":"2328","\u270D":"270d","\u23CF":"23cf","\u23ED":"23ed","\u23EE":"23ee","\u23EF":"23ef","\u23F1":"23f1","\u23F2":"23f2","\u23F8":"23f8","\u23F9":"23f9","\u23FA":"23fa","\u2602":"2602","\u2603":"2603","\u2604":"2604","\u2618":"2618","\u2620":"2620","\u2622":"2622","\u2623":"2623","\u2626":"2626","\u262A":"262a","\u262E":"262e","\u262F":"262f","\u2638":"2638","\u2639":"2639","\u2692":"2692","\u2694":"2694","\u2696":"2696","\u2697":"2697","\u2699":"2699","\u269B":"269b","\u269C":"269c","\u26B0":"26b0","\u26B1":"26b1","\u26C8":"26c8","\u26CF":"26cf","\u26D1":"26d1","\u26D3":"26d3","\u26E9":"26e9","\u26F0":"26f0","\u26F1":"26f1","\u26F4":"26f4","\u26F7":"26f7","\u26F8":"26f8","\u26F9":"26f9","\u2721":"2721","\u2763":"2763","9":"0039","8":"0038","7":"0037","6":"0036","5":"0035","4":"0034","3":"0033","2":"0032","1":"0031","0":"0030","\u2640":"2640","\u2642":"2642","\u2695":"2695"};
  9572. ns.asciiList = {
  9573. '*\\0/*':'1f646',
  9574. '*\\O/*':'1f646',
  9575. '-___-':'1f611',
  9576. ':\'-)':'1f602',
  9577. '\':-)':'1f605',
  9578. '\':-D':'1f605',
  9579. '>:-)':'1f606',
  9580. '\':-(':'1f613',
  9581. '>:-(':'1f620',
  9582. ':\'-(':'1f622',
  9583. 'O:-)':'1f607',
  9584. '0:-3':'1f607',
  9585. '0:-)':'1f607',
  9586. '0;^)':'1f607',
  9587. 'O;-)':'1f607',
  9588. '0;-)':'1f607',
  9589. 'O:-3':'1f607',
  9590. '-__-':'1f611',
  9591. ':-Þ':'1f61b',
  9592. '</3':'1f494',
  9593. ':\')':'1f602',
  9594. ':-D':'1f603',
  9595. '\':)':'1f605',
  9596. '\'=)':'1f605',
  9597. '\':D':'1f605',
  9598. '\'=D':'1f605',
  9599. '>:)':'1f606',
  9600. '>;)':'1f606',
  9601. '>=)':'1f606',
  9602. ';-)':'1f609',
  9603. '*-)':'1f609',
  9604. ';-]':'1f609',
  9605. ';^)':'1f609',
  9606. '\':(':'1f613',
  9607. '\'=(':'1f613',
  9608. ':-*':'1f618',
  9609. ':^*':'1f618',
  9610. '>:P':'1f61c',
  9611. 'X-P':'1f61c',
  9612. '>:[':'1f61e',
  9613. ':-(':'1f61e',
  9614. ':-[':'1f61e',
  9615. '>:(':'1f620',
  9616. ':\'(':'1f622',
  9617. ';-(':'1f622',
  9618. '>.<':'1f623',
  9619. '#-)':'1f635',
  9620. '%-)':'1f635',
  9621. 'X-)':'1f635',
  9622. '\\0/':'1f646',
  9623. '\\O/':'1f646',
  9624. '0:3':'1f607',
  9625. '0:)':'1f607',
  9626. 'O:)':'1f607',
  9627. 'O=)':'1f607',
  9628. 'O:3':'1f607',
  9629. 'B-)':'1f60e',
  9630. '8-)':'1f60e',
  9631. 'B-D':'1f60e',
  9632. '8-D':'1f60e',
  9633. '-_-':'1f611',
  9634. '>:\\':'1f615',
  9635. '>:/':'1f615',
  9636. ':-/':'1f615',
  9637. ':-.':'1f615',
  9638. ':-P':'1f61b',
  9639. ':Þ':'1f61b',
  9640. ':-b':'1f61b',
  9641. ':-O':'1f62e',
  9642. 'O_O':'1f62e',
  9643. '>:O':'1f62e',
  9644. ':-X':'1f636',
  9645. ':-#':'1f636',
  9646. ':-)':'1f642',
  9647. '(y)':'1f44d',
  9648. '<3':'2764',
  9649. ':D':'1f603',
  9650. '=D':'1f603',
  9651. ';)':'1f609',
  9652. '*)':'1f609',
  9653. ';]':'1f609',
  9654. ';D':'1f609',
  9655. ':*':'1f618',
  9656. '=*':'1f618',
  9657. ':(':'1f61e',
  9658. ':[':'1f61e',
  9659. '=(':'1f61e',
  9660. ':@':'1f620',
  9661. ';(':'1f622',
  9662. 'D:':'1f628',
  9663. ':$':'1f633',
  9664. '=$':'1f633',
  9665. '#)':'1f635',
  9666. '%)':'1f635',
  9667. 'X)':'1f635',
  9668. 'B)':'1f60e',
  9669. '8)':'1f60e',
  9670. ':/':'1f615',
  9671. ':\\':'1f615',
  9672. '=/':'1f615',
  9673. '=\\':'1f615',
  9674. ':L':'1f615',
  9675. '=L':'1f615',
  9676. ':P':'1f61b',
  9677. '=P':'1f61b',
  9678. ':b':'1f61b',
  9679. ':O':'1f62e',
  9680. ':X':'1f636',
  9681. ':#':'1f636',
  9682. '=X':'1f636',
  9683. '=#':'1f636',
  9684. ':)':'1f642',
  9685. '=]':'1f642',
  9686. '=)':'1f642',
  9687. ':]':'1f642'
  9688. };
  9689. ns.asciiRegexp = '(\\*\\\\0\\/\\*|\\*\\\\O\\/\\*|\\-___\\-|\\:\'\\-\\)|\'\\:\\-\\)|\'\\:\\-D|\\>\\:\\-\\)|>\\:\\-\\)|\'\\:\\-\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:\'\\-\\(|O\\:\\-\\)|0\\:\\-3|0\\:\\-\\)|0;\\^\\)|O;\\-\\)|0;\\-\\)|O\\:\\-3|\\-__\\-|\\:\\-Þ|\\:\\-Þ|\\<\\/3|<\\/3|\\:\'\\)|\\:\\-D|\'\\:\\)|\'\\=\\)|\'\\:D|\'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\=\\)|>\\=\\)|;\\-\\)|\\*\\-\\)|;\\-\\]|;\\^\\)|\'\\:\\(|\'\\=\\(|\\:\\-\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\-\\[|\\>\\:\\(|>\\:\\(|\\:\'\\(|;\\-\\(|\\>\\.\\<|>\\.<|#\\-\\)|%\\-\\)|X\\-\\)|\\\\0\\/|\\\\O\\/|0\\:3|0\\:\\)|O\\:\\)|O\\=\\)|O\\:3|B\\-\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\-P|\\:Þ|\\:Þ|\\:\\-b|\\:\\-O|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:\\-#|\\:\\-\\)|\\(y\\)|\\<3|<3|\\:D|\\=D|;\\)|\\*\\)|;\\]|;D|\\:\\*|\\=\\*|\\:\\(|\\:\\[|\\=\\(|\\:@|;\\(|D\\:|\\:\\$|\\=\\$|#\\)|%\\)|X\\)|B\\)|8\\)|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\=P|\\:b|\\:O|\\:X|\\:#|\\=X|\\=#|\\:\\)|\\=\\]|\\=\\)|\\:\\])';
  9690. ns.emojiVersion = '3.1'; // you can [optionally] modify this to load alternate emoji versions. see readme for backwards compatibility and version options
  9691. ns.emojiSize = '32';
  9692. ns.greedyMatch = false; // set to true for greedy unicode matching
  9693. ns.imagePathPNG = 'https://cdn.jsdelivr.net/emojione/assets/' + ns.emojiVersion + '/png/';
  9694. ns.defaultPathPNG = ns.imagePathPNG;
  9695. ns.imageTitleTag = true; // set to false to remove title attribute from img tag
  9696. ns.sprites = false; // if this is true then sprite markup will be used
  9697. ns.spriteSize = '32';
  9698. ns.unicodeAlt = true; // use the unicode char as the alt attribute (makes copy and pasting the resulting text better)
  9699. ns.ascii = false; // change to true to convert ascii smileys
  9700. ns.riskyMatchAscii = false; // set true to match ascii without leading/trailing space char
  9701. ns.regShortNames = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+ns.shortnames+")", "gi");
  9702. ns.regAscii = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+ns.asciiRegexp+"(?=\\s|$|[!,.?]))", "gi");
  9703. ns.regAsciiRisky = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(()"+ns.asciiRegexp+"())", "gi");
  9704. ns.regUnicode = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(?:\uD83C\uDFF3)\uFE0F?\u200D?(?:\uD83C\uDF08)|(?:\uD83D\uDC41)\uFE0F?\u200D?(?:\uD83D\uDDE8)\uFE0F?|[#-9]\uFE0F?\u20E3|(?:(?:\uD83C\uDFF4)(?:\uDB40[\uDC60-\uDCFF]){1,6})|(?:\uD83C[\uDDE0-\uDDFF]){2}|(?:(?:\uD83D[\uDC68\uDC69]))\uFE0F?(?:\uD83C[\uDFFA-\uDFFF])?\u200D?(?:[\u2695\u2696\u2708]|\uD83C[\uDF3E-\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92])|(?:\uD83D[\uDC68\uDC69]|\uD83E[\uDDD0-\uDDDF])(?:\uD83C[\uDFFA-\uDFFF])?\u200D?[\u2640\u2642\u2695\u2696\u2708]?\uFE0F?|(?:(?:\u2764|\uD83D[\uDC66-\uDC69\uDC8B])[\u200D\uFE0F]{0,2}){1,3}(?:\u2764|\uD83D[\uDC66-\uDC69\uDC8B])|(?:(?:\u2764|\uD83D[\uDC66-\uDC69\uDC8B])\uFE0F?){2,4}|(?:\uD83D[\uDC68\uDC69\uDC6E\uDC71-\uDC87\uDD75\uDE45-\uDE4E]|\uD83E[\uDD26\uDD37]|\uD83C[\uDFC3-\uDFCC]|\uD83E[\uDD38-\uDD3E]|\uD83D[\uDEA3-\uDEB6]|\u26f9|\uD83D\uDC6F)\uFE0F?(?:\uD83C[\uDFFB-\uDFFF])?\u200D?[\u2640\u2642]?\uFE0F?|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85-\uDFCC]|\uD83D[\uDC42-\uDCAA\uDD74-\uDD96\uDE45-\uDE4F\uDEA3-\uDECC]|\uD83E[\uDD18-\uDD3E])\uFE0F?(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u2194-\u2199\u21a9-\u21aa]\uFE0F?|[\u0023\u002a]|[\u3030\u303d]\uFE0F?|(?:\ud83c[\udd70-\udd71]|\ud83c\udd8e|\ud83c[\udd91-\udd9a])\uFE0F?|\u24c2\uFE0F?|[\u3297\u3299]\uFE0F?|(?:\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51])\uFE0F?|[\u203c\u2049]\uFE0F?|[\u25aa-\u25ab\u25b6\u25c0\u25fb-\u25fe]\uFE0F?|[\u00a9\u00ae]\uFE0F?|[\u2122\u2139]\uFE0F?|\ud83c\udc04\uFE0F?|[\u2b05-\u2b07\u2b1b-\u2b1c\u2b50\u2b55]\uFE0F?|[\u231a-\u231b\u2328\u23cf\u23e9-\u23f3\u23f8-\u23fa]\uFE0F?|\ud83c\udccf|[\u2934\u2935]\uFE0F?)|[\u2700-\u27bf]\uFE0F?|[\ud800-\udbff][\udc00-\udfff]\uFE0F?|[\u2600-\u26FF]\uFE0F?|[\u0030-\u0039]\uFE0F", "g");
  9705. ns.toImage = function(str) {
  9706. str = ns.unicodeToImage(str);
  9707. str = ns.shortnameToImage(str);
  9708. return str;
  9709. };
  9710. // Uses toShort to transform all unicode into a standard shortname
  9711. // then transforms the shortname into unicode
  9712. // This is done for standardization when converting several unicode types
  9713. ns.unifyUnicode = function(str) {
  9714. str = ns.toShort(str);
  9715. str = ns.shortnameToUnicode(str);
  9716. return str;
  9717. };
  9718. // Replace shortnames (:wink:) with Ascii equivalents ( ;^) )
  9719. // Useful for systems that dont support unicode nor images
  9720. ns.shortnameToAscii = function(str) {
  9721. var unicode,
  9722. // something to keep in mind here is that array flip will destroy
  9723. // half of the ascii text "emojis" because the unicode numbers are duplicated
  9724. // this is ok for what it's being used for
  9725. unicodeToAscii = ns.objectFlip(ns.asciiList);
  9726. str = str.replace(ns.regShortNames, function(shortname) {
  9727. if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) {
  9728. // if the shortname doesnt exist just return the entire match
  9729. return shortname;
  9730. }
  9731. else {
  9732. unicode = ns.emojioneList[shortname].uc_output;
  9733. if(typeof unicodeToAscii[unicode] !== 'undefined') {
  9734. return unicodeToAscii[unicode];
  9735. } else {
  9736. return shortname;
  9737. }
  9738. }
  9739. });
  9740. return str;
  9741. };
  9742. // will output unicode from shortname
  9743. // useful for sending emojis back to mobile devices
  9744. ns.shortnameToUnicode = function(str) {
  9745. // replace regular shortnames first
  9746. var unicode,fname;
  9747. str = str.replace(ns.regShortNames, function(shortname) {
  9748. if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) {
  9749. // if the shortname doesnt exist just return the entire matchhju
  9750. return shortname;
  9751. }
  9752. unicode = ns.emojioneList[shortname].uc_output.toUpperCase();
  9753. fname = ns.emojioneList[shortname].uc_base;
  9754. return ns.convert(unicode);
  9755. });
  9756. // if ascii smileys are turned on, then we'll replace them!
  9757. if (ns.ascii) {
  9758. var asciiRX = ns.riskyMatchAscii ? ns.regAsciiRisky : ns.regAscii;
  9759. str = str.replace(asciiRX, function(entire, m1, m2, m3) {
  9760. if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) {
  9761. // if the ascii doesnt exist just return the entire match
  9762. return entire;
  9763. }
  9764. m3 = ns.unescapeHTML(m3);
  9765. unicode = ns.asciiList[m3].toUpperCase();
  9766. return m2+ns.convert(unicode);
  9767. });
  9768. }
  9769. return str;
  9770. };
  9771. ns.shortnameToImage = function(str) {
  9772. // replace regular shortnames first
  9773. var replaceWith,shortname,unicode,fname,alt,category,title,size,ePath;
  9774. var mappedUnicode = ns.mapUnicodeToShort();
  9775. str = str.replace(ns.regShortNames, function(shortname) {
  9776. if( (typeof shortname === 'undefined') || (shortname === '') || (ns.shortnames.indexOf(shortname) === -1) ) {
  9777. // if the shortname doesnt exist just return the entire match
  9778. return shortname;
  9779. }
  9780. else {
  9781. // map shortname to parent
  9782. if (!ns.emojioneList[shortname]) {
  9783. for ( var emoji in ns.emojioneList ) {
  9784. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  9785. if (ns.emojioneList[emoji].shortnames.indexOf(shortname) === -1) continue;
  9786. shortname = emoji;
  9787. break;
  9788. }
  9789. }
  9790. unicode = ns.emojioneList[shortname].uc_output;
  9791. fname = ns.emojioneList[shortname].uc_base;
  9792. category = (fname.includes("-1f3f")) ? 'diversity' : ns.emojioneList[shortname].category;
  9793. title = ns.imageTitleTag ? 'title="' + shortname + '"' : '';
  9794. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  9795. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  9796. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  9797. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  9798. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : shortname;
  9799. if(ns.sprites) {
  9800. replaceWith = '<span class="emojione emojione-' + size + '-' + category + ' _' + fname + '" ' + title + '>' + alt + '</span>';
  9801. }
  9802. else {
  9803. replaceWith = '<img class="emojione" alt="' + alt + '" ' + title + ' src="' + ePath + fname + '.png"/>';
  9804. }
  9805. return replaceWith;
  9806. }
  9807. });
  9808. // if ascii smileys are turned on, then we'll replace them!
  9809. if (ns.ascii) {
  9810. var asciiRX = ns.riskyMatchAscii ? ns.regAsciiRisky : ns.regAscii;
  9811. str = str.replace(asciiRX, function(entire, m1, m2, m3) {
  9812. if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) {
  9813. // if the ascii doesnt exist just return the entire match
  9814. return entire;
  9815. }
  9816. m3 = ns.unescapeHTML(m3);
  9817. unicode = ns.asciiList[m3];
  9818. shortname = mappedUnicode[unicode];
  9819. category = (unicode.includes("-1f3f")) ? 'diversity' : ns.emojioneList[shortname].category;
  9820. title = ns.imageTitleTag ? 'title="' + ns.escapeHTML(m3) + '"' : '';
  9821. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  9822. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  9823. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  9824. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  9825. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : ns.escapeHTML(m3);
  9826. if(ns.sprites) {
  9827. replaceWith = m2+'<span class="emojione emojione-' + size + '-' + category + ' _' + unicode +'" ' + title + '>' + alt + '</span>';
  9828. }
  9829. else {
  9830. replaceWith = m2+'<img class="emojione" alt="'+alt+'" ' + title + ' src="' + ePath + unicode + '.png"/>';
  9831. }
  9832. return replaceWith;
  9833. });
  9834. }
  9835. return str;
  9836. };
  9837. ns.unicodeToImage = function(str) {
  9838. var replaceWith,unicode,short,fname,alt,category,title,size,ePath;
  9839. var mappedUnicode = ns.mapUnicodeToShort();
  9840. var eList = ns.emojioneList;
  9841. str = str.replace(ns.regUnicode, function(unicodeChar) {
  9842. if( (typeof unicodeChar === 'undefined') || (unicodeChar === '') )
  9843. {
  9844. return unicodeChar;
  9845. }
  9846. else if ( unicodeChar in ns.jsEscapeMap )
  9847. {
  9848. fname = ns.jsEscapeMap[unicodeChar];
  9849. }
  9850. else if ( ns.greedyMatch && unicodeChar in ns.jsEscapeMapGreedy )
  9851. {
  9852. fname = ns.jsEscapeMapGreedy[unicodeChar];
  9853. }
  9854. else
  9855. {
  9856. return unicodeChar;
  9857. }
  9858. // then map to shortname and locate the filename
  9859. short = mappedUnicode[fname];
  9860. // then pull the unicode output from emojioneList
  9861. fname = eList[short].uc_base;
  9862. unicode = eList[short].uc_output;
  9863. category = (fname.includes("-1f3f")) ? 'diversity' : eList[short].category;
  9864. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  9865. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  9866. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  9867. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  9868. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : short;
  9869. title = ns.imageTitleTag ? 'title="' + short + '"' : '';
  9870. if(ns.sprites) {
  9871. replaceWith = '<span class="emojione emojione-' + size + '-' + category + ' _' + fname + '" ' + title + '>' + alt + '</span>';
  9872. }
  9873. else {
  9874. replaceWith = '<img class="emojione" alt="' + alt + '" ' + title + ' src="' + ePath + fname + '.png"/>';
  9875. }
  9876. return replaceWith;
  9877. });
  9878. // if ascii smileys are turned on, then we'll replace them!
  9879. if (ns.ascii) {
  9880. var asciiRX = ns.riskyMatchAscii ? ns.regAsciiRisky : ns.regAscii;
  9881. str = str.replace(asciiRX, function(entire, m1, m2, m3) {
  9882. if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) {
  9883. // if the ascii doesnt exist just return the entire match
  9884. return entire;
  9885. }
  9886. m3 = ns.unescapeHTML(m3);
  9887. unicode = ns.asciiList[m3];
  9888. shortname = mappedUnicode[unicode];
  9889. category = (unicode.includes("-1f3f")) ? 'diversity' : ns.emojioneList[shortname].category;
  9890. title = ns.imageTitleTag ? 'title="' + ns.escapeHTML(m3) + '"' : '';
  9891. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  9892. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  9893. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  9894. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  9895. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : ns.escapeHTML(m3);
  9896. if(ns.sprites) {
  9897. replaceWith = m2+'<span class="emojione emojione-' + size + '-' + category + ' _' + unicode +'" ' + title + '>' + alt + '</span>';
  9898. }
  9899. else {
  9900. replaceWith = m2+'<img class="emojione" alt="'+alt+'" ' + title + ' src="' + ePath + unicode + '.png"/>';
  9901. }
  9902. return replaceWith;
  9903. });
  9904. }
  9905. return str;
  9906. };
  9907. // this is really just unicodeToShortname() but I opted for the shorthand name to match toImage()
  9908. ns.toShort = function(str) {
  9909. var find = ns.unicodeCharRegex();
  9910. return ns.replaceAll(str, find);
  9911. };
  9912. // for converting unicode code points and code pairs to their respective characters
  9913. ns.convert = function(unicode) {
  9914. if(unicode.indexOf("-") > -1) {
  9915. var parts = [];
  9916. var s = unicode.split('-');
  9917. for(var i = 0; i < s.length; i++) {
  9918. var part = parseInt(s[i], 16);
  9919. if (part >= 0x10000 && part <= 0x10FFFF) {
  9920. var hi = Math.floor((part - 0x10000) / 0x400) + 0xD800;
  9921. var lo = ((part - 0x10000) % 0x400) + 0xDC00;
  9922. part = (String.fromCharCode(hi) + String.fromCharCode(lo));
  9923. }
  9924. else {
  9925. part = String.fromCharCode(part);
  9926. }
  9927. parts.push(part);
  9928. }
  9929. return parts.join('');
  9930. }
  9931. else {
  9932. var s = parseInt(unicode, 16);
  9933. if (s >= 0x10000 && s <= 0x10FFFF) {
  9934. var hi = Math.floor((s - 0x10000) / 0x400) + 0xD800;
  9935. var lo = ((s - 0x10000) % 0x400) + 0xDC00;
  9936. return (String.fromCharCode(hi) + String.fromCharCode(lo));
  9937. }
  9938. else {
  9939. return String.fromCharCode(s);
  9940. }
  9941. }
  9942. };
  9943. ns.escapeHTML = function (string) {
  9944. var escaped = {
  9945. '&' : '&amp;',
  9946. '<' : '&lt;',
  9947. '>' : '&gt;',
  9948. '"' : '&quot;',
  9949. '\'': '&#039;'
  9950. };
  9951. return string.replace(/[&<>"']/g, function (match) {
  9952. return escaped[match];
  9953. });
  9954. };
  9955. ns.unescapeHTML = function (string) {
  9956. var unescaped = {
  9957. '&amp;' : '&',
  9958. '&#38;' : '&',
  9959. '&#x26;' : '&',
  9960. '&lt;' : '<',
  9961. '&#60;' : '<',
  9962. '&#x3C;' : '<',
  9963. '&gt;' : '>',
  9964. '&#62;' : '>',
  9965. '&#x3E;' : '>',
  9966. '&quot;' : '"',
  9967. '&#34;' : '"',
  9968. '&#x22;' : '"',
  9969. '&apos;' : '\'',
  9970. '&#39;' : '\'',
  9971. '&#x27;' : '\''
  9972. };
  9973. return string.replace(/&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/ig, function (match) {
  9974. return unescaped[match];
  9975. });
  9976. };
  9977. ns.shortnameConversionMap = function() {
  9978. var map = [], emoji;
  9979. for (emoji in ns.emojioneList) {
  9980. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  9981. map[ns.convert(ns.emojioneList[emoji].uc_output)] = emoji;
  9982. }
  9983. return map;
  9984. };
  9985. ns.unicodeCharRegex = function() {
  9986. var map = [];
  9987. for (emoji in ns.emojioneList) {
  9988. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  9989. map.push(ns.convert(ns.emojioneList[emoji].uc_output));
  9990. }
  9991. return map.join('|');
  9992. };
  9993. ns.mapEmojioneList = function (addToMapStorage) {
  9994. for (var shortname in ns.emojioneList) {
  9995. if (!ns.emojioneList.hasOwnProperty(shortname)) { continue; }
  9996. var unicode = ns.emojioneList[shortname].uc_base;
  9997. addToMapStorage(unicode, shortname);
  9998. }
  9999. };
  10000. ns.mapUnicodeToShort = function() {
  10001. if (!ns.memMapShortToUnicode) {
  10002. ns.memMapShortToUnicode = {};
  10003. ns.mapEmojioneList(function (unicode, shortname) {
  10004. ns.memMapShortToUnicode[unicode] = shortname;
  10005. });
  10006. }
  10007. return ns.memMapShortToUnicode;
  10008. };
  10009. ns.memorizeReplacement = function() {
  10010. if (!ns.unicodeReplacementRegEx || !ns.memMapShortToUnicodeCharacters) {
  10011. var unicodeList = [];
  10012. ns.memMapShortToUnicodeCharacters = {};
  10013. ns.mapEmojioneList(function (unicode, shortname) {
  10014. var emojiCharacter = ns.convert(unicode);
  10015. ns.memMapShortToUnicodeCharacters[emojiCharacter] = shortname;
  10016. unicodeList.push(emojiCharacter);
  10017. });
  10018. ns.unicodeReplacementRegEx = unicodeList.join('|');
  10019. }
  10020. };
  10021. ns.mapUnicodeCharactersToShort = function() {
  10022. ns.memorizeReplacement();
  10023. return ns.memMapShortToUnicodeCharacters;
  10024. };
  10025. //reverse an object
  10026. ns.objectFlip = function (obj) {
  10027. var key, tmp_obj = {};
  10028. for (key in obj) {
  10029. if (obj.hasOwnProperty(key)) {
  10030. tmp_obj[obj[key]] = key;
  10031. }
  10032. }
  10033. return tmp_obj;
  10034. };
  10035. ns.escapeRegExp = function(string) {
  10036. return string.replace(/[-[\]{}()*+?.,;:&\\^$#\s]/g, "\\$&");
  10037. };
  10038. ns.replaceAll = function(string, find) {
  10039. var escapedFind = ns.escapeRegExp(find); //sorted largest output to smallest output
  10040. var search = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+escapedFind+")", "gi");
  10041. // callback prevents replacing anything inside of these common html tags as well as between an <object></object> tag
  10042. var replace = function(entire, m1) {
  10043. return ((typeof m1 === 'undefined') || (m1 === '')) ? entire : ns.shortnameConversionMap()[m1];
  10044. };
  10045. return string.replace(search,replace);
  10046. };
  10047. }(this.emojione = this.emojione || {}));
  10048. if(typeof module === "object") module.exports = this.emojione;
  10049. define("emojione", (function (global) {
  10050. return function () {
  10051. var ret, fn;
  10052. return ret || global.emojione;
  10053. };
  10054. }(this)));
  10055. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  10056. /**
  10057. * default settings
  10058. *
  10059. * @author Zongmin Lei<leizongmin@gmail.com>
  10060. */
  10061. var FilterCSS = require("cssfilter").FilterCSS;
  10062. var getDefaultCSSWhiteList = require("cssfilter").getDefaultWhiteList;
  10063. var _ = require("./util");
  10064. function getDefaultWhiteList() {
  10065. return {
  10066. a: ["target", "href", "title"],
  10067. abbr: ["title"],
  10068. address: [],
  10069. area: ["shape", "coords", "href", "alt"],
  10070. article: [],
  10071. aside: [],
  10072. audio: ["autoplay", "controls", "loop", "preload", "src"],
  10073. b: [],
  10074. bdi: ["dir"],
  10075. bdo: ["dir"],
  10076. big: [],
  10077. blockquote: ["cite"],
  10078. br: [],
  10079. caption: [],
  10080. center: [],
  10081. cite: [],
  10082. code: [],
  10083. col: ["align", "valign", "span", "width"],
  10084. colgroup: ["align", "valign", "span", "width"],
  10085. dd: [],
  10086. del: ["datetime"],
  10087. details: ["open"],
  10088. div: [],
  10089. dl: [],
  10090. dt: [],
  10091. em: [],
  10092. font: ["color", "size", "face"],
  10093. footer: [],
  10094. h1: [],
  10095. h2: [],
  10096. h3: [],
  10097. h4: [],
  10098. h5: [],
  10099. h6: [],
  10100. header: [],
  10101. hr: [],
  10102. i: [],
  10103. img: ["src", "alt", "title", "width", "height"],
  10104. ins: ["datetime"],
  10105. li: [],
  10106. mark: [],
  10107. nav: [],
  10108. ol: [],
  10109. p: [],
  10110. pre: [],
  10111. s: [],
  10112. section: [],
  10113. small: [],
  10114. span: [],
  10115. sub: [],
  10116. sup: [],
  10117. strong: [],
  10118. table: ["width", "border", "align", "valign"],
  10119. tbody: ["align", "valign"],
  10120. td: ["width", "rowspan", "colspan", "align", "valign"],
  10121. tfoot: ["align", "valign"],
  10122. th: ["width", "rowspan", "colspan", "align", "valign"],
  10123. thead: ["align", "valign"],
  10124. tr: ["rowspan", "align", "valign"],
  10125. tt: [],
  10126. u: [],
  10127. ul: [],
  10128. video: ["autoplay", "controls", "loop", "preload", "src", "height", "width"]
  10129. };
  10130. }
  10131. var defaultCSSFilter = new FilterCSS();
  10132. /**
  10133. * default onTag function
  10134. *
  10135. * @param {String} tag
  10136. * @param {String} html
  10137. * @param {Object} options
  10138. * @return {String}
  10139. */
  10140. function onTag(tag, html, options) {
  10141. // do nothing
  10142. }
  10143. /**
  10144. * default onIgnoreTag function
  10145. *
  10146. * @param {String} tag
  10147. * @param {String} html
  10148. * @param {Object} options
  10149. * @return {String}
  10150. */
  10151. function onIgnoreTag(tag, html, options) {
  10152. // do nothing
  10153. }
  10154. /**
  10155. * default onTagAttr function
  10156. *
  10157. * @param {String} tag
  10158. * @param {String} name
  10159. * @param {String} value
  10160. * @return {String}
  10161. */
  10162. function onTagAttr(tag, name, value) {
  10163. // do nothing
  10164. }
  10165. /**
  10166. * default onIgnoreTagAttr function
  10167. *
  10168. * @param {String} tag
  10169. * @param {String} name
  10170. * @param {String} value
  10171. * @return {String}
  10172. */
  10173. function onIgnoreTagAttr(tag, name, value) {
  10174. // do nothing
  10175. }
  10176. /**
  10177. * default escapeHtml function
  10178. *
  10179. * @param {String} html
  10180. */
  10181. function escapeHtml(html) {
  10182. return html.replace(REGEXP_LT, "&lt;").replace(REGEXP_GT, "&gt;");
  10183. }
  10184. /**
  10185. * default safeAttrValue function
  10186. *
  10187. * @param {String} tag
  10188. * @param {String} name
  10189. * @param {String} value
  10190. * @param {Object} cssFilter
  10191. * @return {String}
  10192. */
  10193. function safeAttrValue(tag, name, value, cssFilter) {
  10194. // unescape attribute value firstly
  10195. value = friendlyAttrValue(value);
  10196. if (name === "href" || name === "src") {
  10197. // filter `href` and `src` attribute
  10198. // only allow the value that starts with `http://` | `https://` | `mailto:` | `/` | `#`
  10199. value = _.trim(value);
  10200. if (value === "#") return "#";
  10201. if (
  10202. !(
  10203. value.substr(0, 7) === "http://" ||
  10204. value.substr(0, 8) === "https://" ||
  10205. value.substr(0, 7) === "mailto:" ||
  10206. value.substr(0, 4) === "tel:" ||
  10207. value[0] === "#" ||
  10208. value[0] === "/"
  10209. )
  10210. ) {
  10211. return "";
  10212. }
  10213. } else if (name === "background") {
  10214. // filter `background` attribute (maybe no use)
  10215. // `javascript:`
  10216. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  10217. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  10218. return "";
  10219. }
  10220. } else if (name === "style") {
  10221. // `expression()`
  10222. REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0;
  10223. if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) {
  10224. return "";
  10225. }
  10226. // `url()`
  10227. REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0;
  10228. if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) {
  10229. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  10230. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  10231. return "";
  10232. }
  10233. }
  10234. if (cssFilter !== false) {
  10235. cssFilter = cssFilter || defaultCSSFilter;
  10236. value = cssFilter.process(value);
  10237. }
  10238. }
  10239. // escape `<>"` before returns
  10240. value = escapeAttrValue(value);
  10241. return value;
  10242. }
  10243. // RegExp list
  10244. var REGEXP_LT = /</g;
  10245. var REGEXP_GT = />/g;
  10246. var REGEXP_QUOTE = /"/g;
  10247. var REGEXP_QUOTE_2 = /&quot;/g;
  10248. var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/gim;
  10249. var REGEXP_ATTR_VALUE_COLON = /&colon;?/gim;
  10250. var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/gim;
  10251. var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//gm;
  10252. var REGEXP_DEFAULT_ON_TAG_ATTR_4 = /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/gi;
  10253. var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/gi;
  10254. var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//gi;
  10255. var REGEXP_DEFAULT_ON_TAG_ATTR_7 = /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/gi;
  10256. var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/gi;
  10257. /**
  10258. * escape doube quote
  10259. *
  10260. * @param {String} str
  10261. * @return {String} str
  10262. */
  10263. function escapeQuote(str) {
  10264. return str.replace(REGEXP_QUOTE, "&quot;");
  10265. }
  10266. /**
  10267. * unescape double quote
  10268. *
  10269. * @param {String} str
  10270. * @return {String} str
  10271. */
  10272. function unescapeQuote(str) {
  10273. return str.replace(REGEXP_QUOTE_2, '"');
  10274. }
  10275. /**
  10276. * escape html entities
  10277. *
  10278. * @param {String} str
  10279. * @return {String}
  10280. */
  10281. function escapeHtmlEntities(str) {
  10282. return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode(str, code) {
  10283. return code[0] === "x" || code[0] === "X"
  10284. ? String.fromCharCode(parseInt(code.substr(1), 16))
  10285. : String.fromCharCode(parseInt(code, 10));
  10286. });
  10287. }
  10288. /**
  10289. * escape html5 new danger entities
  10290. *
  10291. * @param {String} str
  10292. * @return {String}
  10293. */
  10294. function escapeDangerHtml5Entities(str) {
  10295. return str
  10296. .replace(REGEXP_ATTR_VALUE_COLON, ":")
  10297. .replace(REGEXP_ATTR_VALUE_NEWLINE, " ");
  10298. }
  10299. /**
  10300. * clear nonprintable characters
  10301. *
  10302. * @param {String} str
  10303. * @return {String}
  10304. */
  10305. function clearNonPrintableCharacter(str) {
  10306. var str2 = "";
  10307. for (var i = 0, len = str.length; i < len; i++) {
  10308. str2 += str.charCodeAt(i) < 32 ? " " : str.charAt(i);
  10309. }
  10310. return _.trim(str2);
  10311. }
  10312. /**
  10313. * get friendly attribute value
  10314. *
  10315. * @param {String} str
  10316. * @return {String}
  10317. */
  10318. function friendlyAttrValue(str) {
  10319. str = unescapeQuote(str);
  10320. str = escapeHtmlEntities(str);
  10321. str = escapeDangerHtml5Entities(str);
  10322. str = clearNonPrintableCharacter(str);
  10323. return str;
  10324. }
  10325. /**
  10326. * unescape attribute value
  10327. *
  10328. * @param {String} str
  10329. * @return {String}
  10330. */
  10331. function escapeAttrValue(str) {
  10332. str = escapeQuote(str);
  10333. str = escapeHtml(str);
  10334. return str;
  10335. }
  10336. /**
  10337. * `onIgnoreTag` function for removing all the tags that are not in whitelist
  10338. */
  10339. function onIgnoreTagStripAll() {
  10340. return "";
  10341. }
  10342. /**
  10343. * remove tag body
  10344. * specify a `tags` list, if the tag is not in the `tags` list then process by the specify function (optional)
  10345. *
  10346. * @param {array} tags
  10347. * @param {function} next
  10348. */
  10349. function StripTagBody(tags, next) {
  10350. if (typeof next !== "function") {
  10351. next = function() {};
  10352. }
  10353. var isRemoveAllTag = !Array.isArray(tags);
  10354. function isRemoveTag(tag) {
  10355. if (isRemoveAllTag) return true;
  10356. return _.indexOf(tags, tag) !== -1;
  10357. }
  10358. var removeList = [];
  10359. var posStart = false;
  10360. return {
  10361. onIgnoreTag: function(tag, html, options) {
  10362. if (isRemoveTag(tag)) {
  10363. if (options.isClosing) {
  10364. var ret = "[/removed]";
  10365. var end = options.position + ret.length;
  10366. removeList.push([
  10367. posStart !== false ? posStart : options.position,
  10368. end
  10369. ]);
  10370. posStart = false;
  10371. return ret;
  10372. } else {
  10373. if (!posStart) {
  10374. posStart = options.position;
  10375. }
  10376. return "[removed]";
  10377. }
  10378. } else {
  10379. return next(tag, html, options);
  10380. }
  10381. },
  10382. remove: function(html) {
  10383. var rethtml = "";
  10384. var lastPos = 0;
  10385. _.forEach(removeList, function(pos) {
  10386. rethtml += html.slice(lastPos, pos[0]);
  10387. lastPos = pos[1];
  10388. });
  10389. rethtml += html.slice(lastPos);
  10390. return rethtml;
  10391. }
  10392. };
  10393. }
  10394. /**
  10395. * remove html comments
  10396. *
  10397. * @param {String} html
  10398. * @return {String}
  10399. */
  10400. function stripCommentTag(html) {
  10401. return html.replace(STRIP_COMMENT_TAG_REGEXP, "");
  10402. }
  10403. var STRIP_COMMENT_TAG_REGEXP = /<!--[\s\S]*?-->/g;
  10404. /**
  10405. * remove invisible characters
  10406. *
  10407. * @param {String} html
  10408. * @return {String}
  10409. */
  10410. function stripBlankChar(html) {
  10411. var chars = html.split("");
  10412. chars = chars.filter(function(char) {
  10413. var c = char.charCodeAt(0);
  10414. if (c === 127) return false;
  10415. if (c <= 31) {
  10416. if (c === 10 || c === 13) return true;
  10417. return false;
  10418. }
  10419. return true;
  10420. });
  10421. return chars.join("");
  10422. }
  10423. exports.whiteList = getDefaultWhiteList();
  10424. exports.getDefaultWhiteList = getDefaultWhiteList;
  10425. exports.onTag = onTag;
  10426. exports.onIgnoreTag = onIgnoreTag;
  10427. exports.onTagAttr = onTagAttr;
  10428. exports.onIgnoreTagAttr = onIgnoreTagAttr;
  10429. exports.safeAttrValue = safeAttrValue;
  10430. exports.escapeHtml = escapeHtml;
  10431. exports.escapeQuote = escapeQuote;
  10432. exports.unescapeQuote = unescapeQuote;
  10433. exports.escapeHtmlEntities = escapeHtmlEntities;
  10434. exports.escapeDangerHtml5Entities = escapeDangerHtml5Entities;
  10435. exports.clearNonPrintableCharacter = clearNonPrintableCharacter;
  10436. exports.friendlyAttrValue = friendlyAttrValue;
  10437. exports.escapeAttrValue = escapeAttrValue;
  10438. exports.onIgnoreTagStripAll = onIgnoreTagStripAll;
  10439. exports.StripTagBody = StripTagBody;
  10440. exports.stripCommentTag = stripCommentTag;
  10441. exports.stripBlankChar = stripBlankChar;
  10442. exports.cssFilter = defaultCSSFilter;
  10443. exports.getDefaultCSSWhiteList = getDefaultCSSWhiteList;
  10444. },{"./util":4,"cssfilter":8}],2:[function(require,module,exports){
  10445. /**
  10446. * xss
  10447. *
  10448. * @author Zongmin Lei<leizongmin@gmail.com>
  10449. */
  10450. var DEFAULT = require("./default");
  10451. var parser = require("./parser");
  10452. var FilterXSS = require("./xss");
  10453. /**
  10454. * filter xss function
  10455. *
  10456. * @param {String} html
  10457. * @param {Object} options { whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml }
  10458. * @return {String}
  10459. */
  10460. function filterXSS(html, options) {
  10461. var xss = new FilterXSS(options);
  10462. return xss.process(html);
  10463. }
  10464. exports = module.exports = filterXSS;
  10465. exports.FilterXSS = FilterXSS;
  10466. for (var i in DEFAULT) exports[i] = DEFAULT[i];
  10467. for (var i in parser) exports[i] = parser[i];
  10468. // using `xss` on the browser, output `filterXSS` to the globals
  10469. if (typeof window !== "undefined") {
  10470. window.filterXSS = module.exports;
  10471. }
  10472. },{"./default":1,"./parser":3,"./xss":5}],3:[function(require,module,exports){
  10473. /**
  10474. * Simple HTML Parser
  10475. *
  10476. * @author Zongmin Lei<leizongmin@gmail.com>
  10477. */
  10478. var _ = require("./util");
  10479. /**
  10480. * get tag name
  10481. *
  10482. * @param {String} html e.g. '<a hef="#">'
  10483. * @return {String}
  10484. */
  10485. function getTagName(html) {
  10486. var i = _.spaceIndex(html);
  10487. if (i === -1) {
  10488. var tagName = html.slice(1, -1);
  10489. } else {
  10490. var tagName = html.slice(1, i + 1);
  10491. }
  10492. tagName = _.trim(tagName).toLowerCase();
  10493. if (tagName.slice(0, 1) === "/") tagName = tagName.slice(1);
  10494. if (tagName.slice(-1) === "/") tagName = tagName.slice(0, -1);
  10495. return tagName;
  10496. }
  10497. /**
  10498. * is close tag?
  10499. *
  10500. * @param {String} html 如:'<a hef="#">'
  10501. * @return {Boolean}
  10502. */
  10503. function isClosing(html) {
  10504. return html.slice(0, 2) === "</";
  10505. }
  10506. /**
  10507. * parse input html and returns processed html
  10508. *
  10509. * @param {String} html
  10510. * @param {Function} onTag e.g. function (sourcePosition, position, tag, html, isClosing)
  10511. * @param {Function} escapeHtml
  10512. * @return {String}
  10513. */
  10514. function parseTag(html, onTag, escapeHtml) {
  10515. "user strict";
  10516. var rethtml = "";
  10517. var lastPos = 0;
  10518. var tagStart = false;
  10519. var quoteStart = false;
  10520. var currentPos = 0;
  10521. var len = html.length;
  10522. var currentTagName = "";
  10523. var currentHtml = "";
  10524. for (currentPos = 0; currentPos < len; currentPos++) {
  10525. var c = html.charAt(currentPos);
  10526. if (tagStart === false) {
  10527. if (c === "<") {
  10528. tagStart = currentPos;
  10529. continue;
  10530. }
  10531. } else {
  10532. if (quoteStart === false) {
  10533. if (c === "<") {
  10534. rethtml += escapeHtml(html.slice(lastPos, currentPos));
  10535. tagStart = currentPos;
  10536. lastPos = currentPos;
  10537. continue;
  10538. }
  10539. if (c === ">") {
  10540. rethtml += escapeHtml(html.slice(lastPos, tagStart));
  10541. currentHtml = html.slice(tagStart, currentPos + 1);
  10542. currentTagName = getTagName(currentHtml);
  10543. rethtml += onTag(
  10544. tagStart,
  10545. rethtml.length,
  10546. currentTagName,
  10547. currentHtml,
  10548. isClosing(currentHtml)
  10549. );
  10550. lastPos = currentPos + 1;
  10551. tagStart = false;
  10552. continue;
  10553. }
  10554. if ((c === '"' || c === "'") && html.charAt(currentPos - 1) === "=") {
  10555. quoteStart = c;
  10556. continue;
  10557. }
  10558. } else {
  10559. if (c === quoteStart) {
  10560. quoteStart = false;
  10561. continue;
  10562. }
  10563. }
  10564. }
  10565. }
  10566. if (lastPos < html.length) {
  10567. rethtml += escapeHtml(html.substr(lastPos));
  10568. }
  10569. return rethtml;
  10570. }
  10571. var REGEXP_ILLEGAL_ATTR_NAME = /[^a-zA-Z0-9_:\.\-]/gim;
  10572. /**
  10573. * parse input attributes and returns processed attributes
  10574. *
  10575. * @param {String} html e.g. `href="#" target="_blank"`
  10576. * @param {Function} onAttr e.g. `function (name, value)`
  10577. * @return {String}
  10578. */
  10579. function parseAttr(html, onAttr) {
  10580. "user strict";
  10581. var lastPos = 0;
  10582. var retAttrs = [];
  10583. var tmpName = false;
  10584. var len = html.length;
  10585. function addAttr(name, value) {
  10586. name = _.trim(name);
  10587. name = name.replace(REGEXP_ILLEGAL_ATTR_NAME, "").toLowerCase();
  10588. if (name.length < 1) return;
  10589. var ret = onAttr(name, value || "");
  10590. if (ret) retAttrs.push(ret);
  10591. }
  10592. // 逐个分析字符
  10593. for (var i = 0; i < len; i++) {
  10594. var c = html.charAt(i);
  10595. var v, j;
  10596. if (tmpName === false && c === "=") {
  10597. tmpName = html.slice(lastPos, i);
  10598. lastPos = i + 1;
  10599. continue;
  10600. }
  10601. if (tmpName !== false) {
  10602. if (
  10603. i === lastPos &&
  10604. (c === '"' || c === "'") &&
  10605. html.charAt(i - 1) === "="
  10606. ) {
  10607. j = html.indexOf(c, i + 1);
  10608. if (j === -1) {
  10609. break;
  10610. } else {
  10611. v = _.trim(html.slice(lastPos + 1, j));
  10612. addAttr(tmpName, v);
  10613. tmpName = false;
  10614. i = j;
  10615. lastPos = i + 1;
  10616. continue;
  10617. }
  10618. }
  10619. }
  10620. if (/\s|\n|\t/.test(c)) {
  10621. html = html.replace(/\s|\n|\t/g, " ");
  10622. if (tmpName === false) {
  10623. j = findNextEqual(html, i);
  10624. if (j === -1) {
  10625. v = _.trim(html.slice(lastPos, i));
  10626. addAttr(v);
  10627. tmpName = false;
  10628. lastPos = i + 1;
  10629. continue;
  10630. } else {
  10631. i = j - 1;
  10632. continue;
  10633. }
  10634. } else {
  10635. j = findBeforeEqual(html, i - 1);
  10636. if (j === -1) {
  10637. v = _.trim(html.slice(lastPos, i));
  10638. v = stripQuoteWrap(v);
  10639. addAttr(tmpName, v);
  10640. tmpName = false;
  10641. lastPos = i + 1;
  10642. continue;
  10643. } else {
  10644. continue;
  10645. }
  10646. }
  10647. }
  10648. }
  10649. if (lastPos < html.length) {
  10650. if (tmpName === false) {
  10651. addAttr(html.slice(lastPos));
  10652. } else {
  10653. addAttr(tmpName, stripQuoteWrap(_.trim(html.slice(lastPos))));
  10654. }
  10655. }
  10656. return _.trim(retAttrs.join(" "));
  10657. }
  10658. function findNextEqual(str, i) {
  10659. for (; i < str.length; i++) {
  10660. var c = str[i];
  10661. if (c === " ") continue;
  10662. if (c === "=") return i;
  10663. return -1;
  10664. }
  10665. }
  10666. function findBeforeEqual(str, i) {
  10667. for (; i > 0; i--) {
  10668. var c = str[i];
  10669. if (c === " ") continue;
  10670. if (c === "=") return i;
  10671. return -1;
  10672. }
  10673. }
  10674. function isQuoteWrapString(text) {
  10675. if (
  10676. (text[0] === '"' && text[text.length - 1] === '"') ||
  10677. (text[0] === "'" && text[text.length - 1] === "'")
  10678. ) {
  10679. return true;
  10680. } else {
  10681. return false;
  10682. }
  10683. }
  10684. function stripQuoteWrap(text) {
  10685. if (isQuoteWrapString(text)) {
  10686. return text.substr(1, text.length - 2);
  10687. } else {
  10688. return text;
  10689. }
  10690. }
  10691. exports.parseTag = parseTag;
  10692. exports.parseAttr = parseAttr;
  10693. },{"./util":4}],4:[function(require,module,exports){
  10694. module.exports = {
  10695. indexOf: function(arr, item) {
  10696. var i, j;
  10697. if (Array.prototype.indexOf) {
  10698. return arr.indexOf(item);
  10699. }
  10700. for (i = 0, j = arr.length; i < j; i++) {
  10701. if (arr[i] === item) {
  10702. return i;
  10703. }
  10704. }
  10705. return -1;
  10706. },
  10707. forEach: function(arr, fn, scope) {
  10708. var i, j;
  10709. if (Array.prototype.forEach) {
  10710. return arr.forEach(fn, scope);
  10711. }
  10712. for (i = 0, j = arr.length; i < j; i++) {
  10713. fn.call(scope, arr[i], i, arr);
  10714. }
  10715. },
  10716. trim: function(str) {
  10717. if (String.prototype.trim) {
  10718. return str.trim();
  10719. }
  10720. return str.replace(/(^\s*)|(\s*$)/g, "");
  10721. },
  10722. spaceIndex: function(str) {
  10723. var reg = /\s|\n|\t/;
  10724. var match = reg.exec(str);
  10725. return match ? match.index : -1;
  10726. }
  10727. };
  10728. },{}],5:[function(require,module,exports){
  10729. /**
  10730. * filter xss
  10731. *
  10732. * @author Zongmin Lei<leizongmin@gmail.com>
  10733. */
  10734. var FilterCSS = require("cssfilter").FilterCSS;
  10735. var DEFAULT = require("./default");
  10736. var parser = require("./parser");
  10737. var parseTag = parser.parseTag;
  10738. var parseAttr = parser.parseAttr;
  10739. var _ = require("./util");
  10740. /**
  10741. * returns `true` if the input value is `undefined` or `null`
  10742. *
  10743. * @param {Object} obj
  10744. * @return {Boolean}
  10745. */
  10746. function isNull(obj) {
  10747. return obj === undefined || obj === null;
  10748. }
  10749. /**
  10750. * get attributes for a tag
  10751. *
  10752. * @param {String} html
  10753. * @return {Object}
  10754. * - {String} html
  10755. * - {Boolean} closing
  10756. */
  10757. function getAttrs(html) {
  10758. var i = _.spaceIndex(html);
  10759. if (i === -1) {
  10760. return {
  10761. html: "",
  10762. closing: html[html.length - 2] === "/"
  10763. };
  10764. }
  10765. html = _.trim(html.slice(i + 1, -1));
  10766. var isClosing = html[html.length - 1] === "/";
  10767. if (isClosing) html = _.trim(html.slice(0, -1));
  10768. return {
  10769. html: html,
  10770. closing: isClosing
  10771. };
  10772. }
  10773. /**
  10774. * shallow copy
  10775. *
  10776. * @param {Object} obj
  10777. * @return {Object}
  10778. */
  10779. function shallowCopyObject(obj) {
  10780. var ret = {};
  10781. for (var i in obj) {
  10782. ret[i] = obj[i];
  10783. }
  10784. return ret;
  10785. }
  10786. /**
  10787. * FilterXSS class
  10788. *
  10789. * @param {Object} options
  10790. * whiteList, onTag, onTagAttr, onIgnoreTag,
  10791. * onIgnoreTagAttr, safeAttrValue, escapeHtml
  10792. * stripIgnoreTagBody, allowCommentTag, stripBlankChar
  10793. * css{whiteList, onAttr, onIgnoreAttr} `css=false` means don't use `cssfilter`
  10794. */
  10795. function FilterXSS(options) {
  10796. options = shallowCopyObject(options || {});
  10797. if (options.stripIgnoreTag) {
  10798. if (options.onIgnoreTag) {
  10799. console.error(
  10800. 'Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time'
  10801. );
  10802. }
  10803. options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll;
  10804. }
  10805. options.whiteList = options.whiteList || DEFAULT.whiteList;
  10806. options.onTag = options.onTag || DEFAULT.onTag;
  10807. options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr;
  10808. options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag;
  10809. options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr;
  10810. options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue;
  10811. options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml;
  10812. this.options = options;
  10813. if (options.css === false) {
  10814. this.cssFilter = false;
  10815. } else {
  10816. options.css = options.css || {};
  10817. this.cssFilter = new FilterCSS(options.css);
  10818. }
  10819. }
  10820. /**
  10821. * start process and returns result
  10822. *
  10823. * @param {String} html
  10824. * @return {String}
  10825. */
  10826. FilterXSS.prototype.process = function(html) {
  10827. // compatible with the input
  10828. html = html || "";
  10829. html = html.toString();
  10830. if (!html) return "";
  10831. var me = this;
  10832. var options = me.options;
  10833. var whiteList = options.whiteList;
  10834. var onTag = options.onTag;
  10835. var onIgnoreTag = options.onIgnoreTag;
  10836. var onTagAttr = options.onTagAttr;
  10837. var onIgnoreTagAttr = options.onIgnoreTagAttr;
  10838. var safeAttrValue = options.safeAttrValue;
  10839. var escapeHtml = options.escapeHtml;
  10840. var cssFilter = me.cssFilter;
  10841. // remove invisible characters
  10842. if (options.stripBlankChar) {
  10843. html = DEFAULT.stripBlankChar(html);
  10844. }
  10845. // remove html comments
  10846. if (!options.allowCommentTag) {
  10847. html = DEFAULT.stripCommentTag(html);
  10848. }
  10849. // if enable stripIgnoreTagBody
  10850. var stripIgnoreTagBody = false;
  10851. if (options.stripIgnoreTagBody) {
  10852. var stripIgnoreTagBody = DEFAULT.StripTagBody(
  10853. options.stripIgnoreTagBody,
  10854. onIgnoreTag
  10855. );
  10856. onIgnoreTag = stripIgnoreTagBody.onIgnoreTag;
  10857. }
  10858. var retHtml = parseTag(
  10859. html,
  10860. function(sourcePosition, position, tag, html, isClosing) {
  10861. var info = {
  10862. sourcePosition: sourcePosition,
  10863. position: position,
  10864. isClosing: isClosing,
  10865. isWhite: whiteList.hasOwnProperty(tag)
  10866. };
  10867. // call `onTag()`
  10868. var ret = onTag(tag, html, info);
  10869. if (!isNull(ret)) return ret;
  10870. if (info.isWhite) {
  10871. if (info.isClosing) {
  10872. return "</" + tag + ">";
  10873. }
  10874. var attrs = getAttrs(html);
  10875. var whiteAttrList = whiteList[tag];
  10876. var attrsHtml = parseAttr(attrs.html, function(name, value) {
  10877. // call `onTagAttr()`
  10878. var isWhiteAttr = _.indexOf(whiteAttrList, name) !== -1;
  10879. var ret = onTagAttr(tag, name, value, isWhiteAttr);
  10880. if (!isNull(ret)) return ret;
  10881. if (isWhiteAttr) {
  10882. // call `safeAttrValue()`
  10883. value = safeAttrValue(tag, name, value, cssFilter);
  10884. if (value) {
  10885. return name + '="' + value + '"';
  10886. } else {
  10887. return name;
  10888. }
  10889. } else {
  10890. // call `onIgnoreTagAttr()`
  10891. var ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr);
  10892. if (!isNull(ret)) return ret;
  10893. return;
  10894. }
  10895. });
  10896. // build new tag html
  10897. var html = "<" + tag;
  10898. if (attrsHtml) html += " " + attrsHtml;
  10899. if (attrs.closing) html += " /";
  10900. html += ">";
  10901. return html;
  10902. } else {
  10903. // call `onIgnoreTag()`
  10904. var ret = onIgnoreTag(tag, html, info);
  10905. if (!isNull(ret)) return ret;
  10906. return escapeHtml(html);
  10907. }
  10908. },
  10909. escapeHtml
  10910. );
  10911. // if enable stripIgnoreTagBody
  10912. if (stripIgnoreTagBody) {
  10913. retHtml = stripIgnoreTagBody.remove(retHtml);
  10914. }
  10915. return retHtml;
  10916. };
  10917. module.exports = FilterXSS;
  10918. },{"./default":1,"./parser":3,"./util":4,"cssfilter":8}],6:[function(require,module,exports){
  10919. /**
  10920. * cssfilter
  10921. *
  10922. * @author 老雷<leizongmin@gmail.com>
  10923. */
  10924. var DEFAULT = require('./default');
  10925. var parseStyle = require('./parser');
  10926. var _ = require('./util');
  10927. /**
  10928. * 返回值是否为空
  10929. *
  10930. * @param {Object} obj
  10931. * @return {Boolean}
  10932. */
  10933. function isNull (obj) {
  10934. return (obj === undefined || obj === null);
  10935. }
  10936. /**
  10937. * 浅拷贝对象
  10938. *
  10939. * @param {Object} obj
  10940. * @return {Object}
  10941. */
  10942. function shallowCopyObject (obj) {
  10943. var ret = {};
  10944. for (var i in obj) {
  10945. ret[i] = obj[i];
  10946. }
  10947. return ret;
  10948. }
  10949. /**
  10950. * 创建CSS过滤器
  10951. *
  10952. * @param {Object} options
  10953. * - {Object} whiteList
  10954. * - {Function} onAttr
  10955. * - {Function} onIgnoreAttr
  10956. * - {Function} safeAttrValue
  10957. */
  10958. function FilterCSS (options) {
  10959. options = shallowCopyObject(options || {});
  10960. options.whiteList = options.whiteList || DEFAULT.whiteList;
  10961. options.onAttr = options.onAttr || DEFAULT.onAttr;
  10962. options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT.onIgnoreAttr;
  10963. options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue;
  10964. this.options = options;
  10965. }
  10966. FilterCSS.prototype.process = function (css) {
  10967. // 兼容各种奇葩输入
  10968. css = css || '';
  10969. css = css.toString();
  10970. if (!css) return '';
  10971. var me = this;
  10972. var options = me.options;
  10973. var whiteList = options.whiteList;
  10974. var onAttr = options.onAttr;
  10975. var onIgnoreAttr = options.onIgnoreAttr;
  10976. var safeAttrValue = options.safeAttrValue;
  10977. var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) {
  10978. var check = whiteList[name];
  10979. var isWhite = false;
  10980. if (check === true) isWhite = check;
  10981. else if (typeof check === 'function') isWhite = check(value);
  10982. else if (check instanceof RegExp) isWhite = check.test(value);
  10983. if (isWhite !== true) isWhite = false;
  10984. // 如果过滤后 value 为空则直接忽略
  10985. value = safeAttrValue(name, value);
  10986. if (!value) return;
  10987. var opts = {
  10988. position: position,
  10989. sourcePosition: sourcePosition,
  10990. source: source,
  10991. isWhite: isWhite
  10992. };
  10993. if (isWhite) {
  10994. var ret = onAttr(name, value, opts);
  10995. if (isNull(ret)) {
  10996. return name + ':' + value;
  10997. } else {
  10998. return ret;
  10999. }
  11000. } else {
  11001. var ret = onIgnoreAttr(name, value, opts);
  11002. if (!isNull(ret)) {
  11003. return ret;
  11004. }
  11005. }
  11006. });
  11007. return retCSS;
  11008. };
  11009. module.exports = FilterCSS;
  11010. },{"./default":7,"./parser":9,"./util":10}],7:[function(require,module,exports){
  11011. /**
  11012. * cssfilter
  11013. *
  11014. * @author 老雷<leizongmin@gmail.com>
  11015. */
  11016. function getDefaultWhiteList () {
  11017. // 白名单值说明:
  11018. // true: 允许该属性
  11019. // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许
  11020. // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许
  11021. // 除上面列出的值外均表示不允许
  11022. var whiteList = {};
  11023. whiteList['align-content'] = false; // default: auto
  11024. whiteList['align-items'] = false; // default: auto
  11025. whiteList['align-self'] = false; // default: auto
  11026. whiteList['alignment-adjust'] = false; // default: auto
  11027. whiteList['alignment-baseline'] = false; // default: baseline
  11028. whiteList['all'] = false; // default: depending on individual properties
  11029. whiteList['anchor-point'] = false; // default: none
  11030. whiteList['animation'] = false; // default: depending on individual properties
  11031. whiteList['animation-delay'] = false; // default: 0
  11032. whiteList['animation-direction'] = false; // default: normal
  11033. whiteList['animation-duration'] = false; // default: 0
  11034. whiteList['animation-fill-mode'] = false; // default: none
  11035. whiteList['animation-iteration-count'] = false; // default: 1
  11036. whiteList['animation-name'] = false; // default: none
  11037. whiteList['animation-play-state'] = false; // default: running
  11038. whiteList['animation-timing-function'] = false; // default: ease
  11039. whiteList['azimuth'] = false; // default: center
  11040. whiteList['backface-visibility'] = false; // default: visible
  11041. whiteList['background'] = true; // default: depending on individual properties
  11042. whiteList['background-attachment'] = true; // default: scroll
  11043. whiteList['background-clip'] = true; // default: border-box
  11044. whiteList['background-color'] = true; // default: transparent
  11045. whiteList['background-image'] = true; // default: none
  11046. whiteList['background-origin'] = true; // default: padding-box
  11047. whiteList['background-position'] = true; // default: 0% 0%
  11048. whiteList['background-repeat'] = true; // default: repeat
  11049. whiteList['background-size'] = true; // default: auto
  11050. whiteList['baseline-shift'] = false; // default: baseline
  11051. whiteList['binding'] = false; // default: none
  11052. whiteList['bleed'] = false; // default: 6pt
  11053. whiteList['bookmark-label'] = false; // default: content()
  11054. whiteList['bookmark-level'] = false; // default: none
  11055. whiteList['bookmark-state'] = false; // default: open
  11056. whiteList['border'] = true; // default: depending on individual properties
  11057. whiteList['border-bottom'] = true; // default: depending on individual properties
  11058. whiteList['border-bottom-color'] = true; // default: current color
  11059. whiteList['border-bottom-left-radius'] = true; // default: 0
  11060. whiteList['border-bottom-right-radius'] = true; // default: 0
  11061. whiteList['border-bottom-style'] = true; // default: none
  11062. whiteList['border-bottom-width'] = true; // default: medium
  11063. whiteList['border-collapse'] = true; // default: separate
  11064. whiteList['border-color'] = true; // default: depending on individual properties
  11065. whiteList['border-image'] = true; // default: none
  11066. whiteList['border-image-outset'] = true; // default: 0
  11067. whiteList['border-image-repeat'] = true; // default: stretch
  11068. whiteList['border-image-slice'] = true; // default: 100%
  11069. whiteList['border-image-source'] = true; // default: none
  11070. whiteList['border-image-width'] = true; // default: 1
  11071. whiteList['border-left'] = true; // default: depending on individual properties
  11072. whiteList['border-left-color'] = true; // default: current color
  11073. whiteList['border-left-style'] = true; // default: none
  11074. whiteList['border-left-width'] = true; // default: medium
  11075. whiteList['border-radius'] = true; // default: 0
  11076. whiteList['border-right'] = true; // default: depending on individual properties
  11077. whiteList['border-right-color'] = true; // default: current color
  11078. whiteList['border-right-style'] = true; // default: none
  11079. whiteList['border-right-width'] = true; // default: medium
  11080. whiteList['border-spacing'] = true; // default: 0
  11081. whiteList['border-style'] = true; // default: depending on individual properties
  11082. whiteList['border-top'] = true; // default: depending on individual properties
  11083. whiteList['border-top-color'] = true; // default: current color
  11084. whiteList['border-top-left-radius'] = true; // default: 0
  11085. whiteList['border-top-right-radius'] = true; // default: 0
  11086. whiteList['border-top-style'] = true; // default: none
  11087. whiteList['border-top-width'] = true; // default: medium
  11088. whiteList['border-width'] = true; // default: depending on individual properties
  11089. whiteList['bottom'] = false; // default: auto
  11090. whiteList['box-decoration-break'] = true; // default: slice
  11091. whiteList['box-shadow'] = true; // default: none
  11092. whiteList['box-sizing'] = true; // default: content-box
  11093. whiteList['box-snap'] = true; // default: none
  11094. whiteList['box-suppress'] = true; // default: show
  11095. whiteList['break-after'] = true; // default: auto
  11096. whiteList['break-before'] = true; // default: auto
  11097. whiteList['break-inside'] = true; // default: auto
  11098. whiteList['caption-side'] = false; // default: top
  11099. whiteList['chains'] = false; // default: none
  11100. whiteList['clear'] = true; // default: none
  11101. whiteList['clip'] = false; // default: auto
  11102. whiteList['clip-path'] = false; // default: none
  11103. whiteList['clip-rule'] = false; // default: nonzero
  11104. whiteList['color'] = true; // default: implementation dependent
  11105. whiteList['color-interpolation-filters'] = true; // default: auto
  11106. whiteList['column-count'] = false; // default: auto
  11107. whiteList['column-fill'] = false; // default: balance
  11108. whiteList['column-gap'] = false; // default: normal
  11109. whiteList['column-rule'] = false; // default: depending on individual properties
  11110. whiteList['column-rule-color'] = false; // default: current color
  11111. whiteList['column-rule-style'] = false; // default: medium
  11112. whiteList['column-rule-width'] = false; // default: medium
  11113. whiteList['column-span'] = false; // default: none
  11114. whiteList['column-width'] = false; // default: auto
  11115. whiteList['columns'] = false; // default: depending on individual properties
  11116. whiteList['contain'] = false; // default: none
  11117. whiteList['content'] = false; // default: normal
  11118. whiteList['counter-increment'] = false; // default: none
  11119. whiteList['counter-reset'] = false; // default: none
  11120. whiteList['counter-set'] = false; // default: none
  11121. whiteList['crop'] = false; // default: auto
  11122. whiteList['cue'] = false; // default: depending on individual properties
  11123. whiteList['cue-after'] = false; // default: none
  11124. whiteList['cue-before'] = false; // default: none
  11125. whiteList['cursor'] = false; // default: auto
  11126. whiteList['direction'] = false; // default: ltr
  11127. whiteList['display'] = true; // default: depending on individual properties
  11128. whiteList['display-inside'] = true; // default: auto
  11129. whiteList['display-list'] = true; // default: none
  11130. whiteList['display-outside'] = true; // default: inline-level
  11131. whiteList['dominant-baseline'] = false; // default: auto
  11132. whiteList['elevation'] = false; // default: level
  11133. whiteList['empty-cells'] = false; // default: show
  11134. whiteList['filter'] = false; // default: none
  11135. whiteList['flex'] = false; // default: depending on individual properties
  11136. whiteList['flex-basis'] = false; // default: auto
  11137. whiteList['flex-direction'] = false; // default: row
  11138. whiteList['flex-flow'] = false; // default: depending on individual properties
  11139. whiteList['flex-grow'] = false; // default: 0
  11140. whiteList['flex-shrink'] = false; // default: 1
  11141. whiteList['flex-wrap'] = false; // default: nowrap
  11142. whiteList['float'] = false; // default: none
  11143. whiteList['float-offset'] = false; // default: 0 0
  11144. whiteList['flood-color'] = false; // default: black
  11145. whiteList['flood-opacity'] = false; // default: 1
  11146. whiteList['flow-from'] = false; // default: none
  11147. whiteList['flow-into'] = false; // default: none
  11148. whiteList['font'] = true; // default: depending on individual properties
  11149. whiteList['font-family'] = true; // default: implementation dependent
  11150. whiteList['font-feature-settings'] = true; // default: normal
  11151. whiteList['font-kerning'] = true; // default: auto
  11152. whiteList['font-language-override'] = true; // default: normal
  11153. whiteList['font-size'] = true; // default: medium
  11154. whiteList['font-size-adjust'] = true; // default: none
  11155. whiteList['font-stretch'] = true; // default: normal
  11156. whiteList['font-style'] = true; // default: normal
  11157. whiteList['font-synthesis'] = true; // default: weight style
  11158. whiteList['font-variant'] = true; // default: normal
  11159. whiteList['font-variant-alternates'] = true; // default: normal
  11160. whiteList['font-variant-caps'] = true; // default: normal
  11161. whiteList['font-variant-east-asian'] = true; // default: normal
  11162. whiteList['font-variant-ligatures'] = true; // default: normal
  11163. whiteList['font-variant-numeric'] = true; // default: normal
  11164. whiteList['font-variant-position'] = true; // default: normal
  11165. whiteList['font-weight'] = true; // default: normal
  11166. whiteList['grid'] = false; // default: depending on individual properties
  11167. whiteList['grid-area'] = false; // default: depending on individual properties
  11168. whiteList['grid-auto-columns'] = false; // default: auto
  11169. whiteList['grid-auto-flow'] = false; // default: none
  11170. whiteList['grid-auto-rows'] = false; // default: auto
  11171. whiteList['grid-column'] = false; // default: depending on individual properties
  11172. whiteList['grid-column-end'] = false; // default: auto
  11173. whiteList['grid-column-start'] = false; // default: auto
  11174. whiteList['grid-row'] = false; // default: depending on individual properties
  11175. whiteList['grid-row-end'] = false; // default: auto
  11176. whiteList['grid-row-start'] = false; // default: auto
  11177. whiteList['grid-template'] = false; // default: depending on individual properties
  11178. whiteList['grid-template-areas'] = false; // default: none
  11179. whiteList['grid-template-columns'] = false; // default: none
  11180. whiteList['grid-template-rows'] = false; // default: none
  11181. whiteList['hanging-punctuation'] = false; // default: none
  11182. whiteList['height'] = true; // default: auto
  11183. whiteList['hyphens'] = false; // default: manual
  11184. whiteList['icon'] = false; // default: auto
  11185. whiteList['image-orientation'] = false; // default: auto
  11186. whiteList['image-resolution'] = false; // default: normal
  11187. whiteList['ime-mode'] = false; // default: auto
  11188. whiteList['initial-letters'] = false; // default: normal
  11189. whiteList['inline-box-align'] = false; // default: last
  11190. whiteList['justify-content'] = false; // default: auto
  11191. whiteList['justify-items'] = false; // default: auto
  11192. whiteList['justify-self'] = false; // default: auto
  11193. whiteList['left'] = false; // default: auto
  11194. whiteList['letter-spacing'] = true; // default: normal
  11195. whiteList['lighting-color'] = true; // default: white
  11196. whiteList['line-box-contain'] = false; // default: block inline replaced
  11197. whiteList['line-break'] = false; // default: auto
  11198. whiteList['line-grid'] = false; // default: match-parent
  11199. whiteList['line-height'] = false; // default: normal
  11200. whiteList['line-snap'] = false; // default: none
  11201. whiteList['line-stacking'] = false; // default: depending on individual properties
  11202. whiteList['line-stacking-ruby'] = false; // default: exclude-ruby
  11203. whiteList['line-stacking-shift'] = false; // default: consider-shifts
  11204. whiteList['line-stacking-strategy'] = false; // default: inline-line-height
  11205. whiteList['list-style'] = true; // default: depending on individual properties
  11206. whiteList['list-style-image'] = true; // default: none
  11207. whiteList['list-style-position'] = true; // default: outside
  11208. whiteList['list-style-type'] = true; // default: disc
  11209. whiteList['margin'] = true; // default: depending on individual properties
  11210. whiteList['margin-bottom'] = true; // default: 0
  11211. whiteList['margin-left'] = true; // default: 0
  11212. whiteList['margin-right'] = true; // default: 0
  11213. whiteList['margin-top'] = true; // default: 0
  11214. whiteList['marker-offset'] = false; // default: auto
  11215. whiteList['marker-side'] = false; // default: list-item
  11216. whiteList['marks'] = false; // default: none
  11217. whiteList['mask'] = false; // default: border-box
  11218. whiteList['mask-box'] = false; // default: see individual properties
  11219. whiteList['mask-box-outset'] = false; // default: 0
  11220. whiteList['mask-box-repeat'] = false; // default: stretch
  11221. whiteList['mask-box-slice'] = false; // default: 0 fill
  11222. whiteList['mask-box-source'] = false; // default: none
  11223. whiteList['mask-box-width'] = false; // default: auto
  11224. whiteList['mask-clip'] = false; // default: border-box
  11225. whiteList['mask-image'] = false; // default: none
  11226. whiteList['mask-origin'] = false; // default: border-box
  11227. whiteList['mask-position'] = false; // default: center
  11228. whiteList['mask-repeat'] = false; // default: no-repeat
  11229. whiteList['mask-size'] = false; // default: border-box
  11230. whiteList['mask-source-type'] = false; // default: auto
  11231. whiteList['mask-type'] = false; // default: luminance
  11232. whiteList['max-height'] = true; // default: none
  11233. whiteList['max-lines'] = false; // default: none
  11234. whiteList['max-width'] = true; // default: none
  11235. whiteList['min-height'] = true; // default: 0
  11236. whiteList['min-width'] = true; // default: 0
  11237. whiteList['move-to'] = false; // default: normal
  11238. whiteList['nav-down'] = false; // default: auto
  11239. whiteList['nav-index'] = false; // default: auto
  11240. whiteList['nav-left'] = false; // default: auto
  11241. whiteList['nav-right'] = false; // default: auto
  11242. whiteList['nav-up'] = false; // default: auto
  11243. whiteList['object-fit'] = false; // default: fill
  11244. whiteList['object-position'] = false; // default: 50% 50%
  11245. whiteList['opacity'] = false; // default: 1
  11246. whiteList['order'] = false; // default: 0
  11247. whiteList['orphans'] = false; // default: 2
  11248. whiteList['outline'] = false; // default: depending on individual properties
  11249. whiteList['outline-color'] = false; // default: invert
  11250. whiteList['outline-offset'] = false; // default: 0
  11251. whiteList['outline-style'] = false; // default: none
  11252. whiteList['outline-width'] = false; // default: medium
  11253. whiteList['overflow'] = false; // default: depending on individual properties
  11254. whiteList['overflow-wrap'] = false; // default: normal
  11255. whiteList['overflow-x'] = false; // default: visible
  11256. whiteList['overflow-y'] = false; // default: visible
  11257. whiteList['padding'] = true; // default: depending on individual properties
  11258. whiteList['padding-bottom'] = true; // default: 0
  11259. whiteList['padding-left'] = true; // default: 0
  11260. whiteList['padding-right'] = true; // default: 0
  11261. whiteList['padding-top'] = true; // default: 0
  11262. whiteList['page'] = false; // default: auto
  11263. whiteList['page-break-after'] = false; // default: auto
  11264. whiteList['page-break-before'] = false; // default: auto
  11265. whiteList['page-break-inside'] = false; // default: auto
  11266. whiteList['page-policy'] = false; // default: start
  11267. whiteList['pause'] = false; // default: implementation dependent
  11268. whiteList['pause-after'] = false; // default: implementation dependent
  11269. whiteList['pause-before'] = false; // default: implementation dependent
  11270. whiteList['perspective'] = false; // default: none
  11271. whiteList['perspective-origin'] = false; // default: 50% 50%
  11272. whiteList['pitch'] = false; // default: medium
  11273. whiteList['pitch-range'] = false; // default: 50
  11274. whiteList['play-during'] = false; // default: auto
  11275. whiteList['position'] = false; // default: static
  11276. whiteList['presentation-level'] = false; // default: 0
  11277. whiteList['quotes'] = false; // default: text
  11278. whiteList['region-fragment'] = false; // default: auto
  11279. whiteList['resize'] = false; // default: none
  11280. whiteList['rest'] = false; // default: depending on individual properties
  11281. whiteList['rest-after'] = false; // default: none
  11282. whiteList['rest-before'] = false; // default: none
  11283. whiteList['richness'] = false; // default: 50
  11284. whiteList['right'] = false; // default: auto
  11285. whiteList['rotation'] = false; // default: 0
  11286. whiteList['rotation-point'] = false; // default: 50% 50%
  11287. whiteList['ruby-align'] = false; // default: auto
  11288. whiteList['ruby-merge'] = false; // default: separate
  11289. whiteList['ruby-position'] = false; // default: before
  11290. whiteList['shape-image-threshold'] = false; // default: 0.0
  11291. whiteList['shape-outside'] = false; // default: none
  11292. whiteList['shape-margin'] = false; // default: 0
  11293. whiteList['size'] = false; // default: auto
  11294. whiteList['speak'] = false; // default: auto
  11295. whiteList['speak-as'] = false; // default: normal
  11296. whiteList['speak-header'] = false; // default: once
  11297. whiteList['speak-numeral'] = false; // default: continuous
  11298. whiteList['speak-punctuation'] = false; // default: none
  11299. whiteList['speech-rate'] = false; // default: medium
  11300. whiteList['stress'] = false; // default: 50
  11301. whiteList['string-set'] = false; // default: none
  11302. whiteList['tab-size'] = false; // default: 8
  11303. whiteList['table-layout'] = false; // default: auto
  11304. whiteList['text-align'] = true; // default: start
  11305. whiteList['text-align-last'] = true; // default: auto
  11306. whiteList['text-combine-upright'] = true; // default: none
  11307. whiteList['text-decoration'] = true; // default: none
  11308. whiteList['text-decoration-color'] = true; // default: currentColor
  11309. whiteList['text-decoration-line'] = true; // default: none
  11310. whiteList['text-decoration-skip'] = true; // default: objects
  11311. whiteList['text-decoration-style'] = true; // default: solid
  11312. whiteList['text-emphasis'] = true; // default: depending on individual properties
  11313. whiteList['text-emphasis-color'] = true; // default: currentColor
  11314. whiteList['text-emphasis-position'] = true; // default: over right
  11315. whiteList['text-emphasis-style'] = true; // default: none
  11316. whiteList['text-height'] = true; // default: auto
  11317. whiteList['text-indent'] = true; // default: 0
  11318. whiteList['text-justify'] = true; // default: auto
  11319. whiteList['text-orientation'] = true; // default: mixed
  11320. whiteList['text-overflow'] = true; // default: clip
  11321. whiteList['text-shadow'] = true; // default: none
  11322. whiteList['text-space-collapse'] = true; // default: collapse
  11323. whiteList['text-transform'] = true; // default: none
  11324. whiteList['text-underline-position'] = true; // default: auto
  11325. whiteList['text-wrap'] = true; // default: normal
  11326. whiteList['top'] = false; // default: auto
  11327. whiteList['transform'] = false; // default: none
  11328. whiteList['transform-origin'] = false; // default: 50% 50% 0
  11329. whiteList['transform-style'] = false; // default: flat
  11330. whiteList['transition'] = false; // default: depending on individual properties
  11331. whiteList['transition-delay'] = false; // default: 0s
  11332. whiteList['transition-duration'] = false; // default: 0s
  11333. whiteList['transition-property'] = false; // default: all
  11334. whiteList['transition-timing-function'] = false; // default: ease
  11335. whiteList['unicode-bidi'] = false; // default: normal
  11336. whiteList['vertical-align'] = false; // default: baseline
  11337. whiteList['visibility'] = false; // default: visible
  11338. whiteList['voice-balance'] = false; // default: center
  11339. whiteList['voice-duration'] = false; // default: auto
  11340. whiteList['voice-family'] = false; // default: implementation dependent
  11341. whiteList['voice-pitch'] = false; // default: medium
  11342. whiteList['voice-range'] = false; // default: medium
  11343. whiteList['voice-rate'] = false; // default: normal
  11344. whiteList['voice-stress'] = false; // default: normal
  11345. whiteList['voice-volume'] = false; // default: medium
  11346. whiteList['volume'] = false; // default: medium
  11347. whiteList['white-space'] = false; // default: normal
  11348. whiteList['widows'] = false; // default: 2
  11349. whiteList['width'] = true; // default: auto
  11350. whiteList['will-change'] = false; // default: auto
  11351. whiteList['word-break'] = true; // default: normal
  11352. whiteList['word-spacing'] = true; // default: normal
  11353. whiteList['word-wrap'] = true; // default: normal
  11354. whiteList['wrap-flow'] = false; // default: auto
  11355. whiteList['wrap-through'] = false; // default: wrap
  11356. whiteList['writing-mode'] = false; // default: horizontal-tb
  11357. whiteList['z-index'] = false; // default: auto
  11358. return whiteList;
  11359. }
  11360. /**
  11361. * 匹配到白名单上的一个属性时
  11362. *
  11363. * @param {String} name
  11364. * @param {String} value
  11365. * @param {Object} options
  11366. * @return {String}
  11367. */
  11368. function onAttr (name, value, options) {
  11369. // do nothing
  11370. }
  11371. /**
  11372. * 匹配到不在白名单上的一个属性时
  11373. *
  11374. * @param {String} name
  11375. * @param {String} value
  11376. * @param {Object} options
  11377. * @return {String}
  11378. */
  11379. function onIgnoreAttr (name, value, options) {
  11380. // do nothing
  11381. }
  11382. var REGEXP_URL_JAVASCRIPT = /javascript\s*\:/img;
  11383. /**
  11384. * 过滤属性值
  11385. *
  11386. * @param {String} name
  11387. * @param {String} value
  11388. * @return {String}
  11389. */
  11390. function safeAttrValue(name, value) {
  11391. if (REGEXP_URL_JAVASCRIPT.test(value)) return '';
  11392. return value;
  11393. }
  11394. exports.whiteList = getDefaultWhiteList();
  11395. exports.getDefaultWhiteList = getDefaultWhiteList;
  11396. exports.onAttr = onAttr;
  11397. exports.onIgnoreAttr = onIgnoreAttr;
  11398. exports.safeAttrValue = safeAttrValue;
  11399. },{}],8:[function(require,module,exports){
  11400. /**
  11401. * cssfilter
  11402. *
  11403. * @author 老雷<leizongmin@gmail.com>
  11404. */
  11405. var DEFAULT = require('./default');
  11406. var FilterCSS = require('./css');
  11407. /**
  11408. * XSS过滤
  11409. *
  11410. * @param {String} css 要过滤的CSS代码
  11411. * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr
  11412. * @return {String}
  11413. */
  11414. function filterCSS (html, options) {
  11415. var xss = new FilterCSS(options);
  11416. return xss.process(html);
  11417. }
  11418. // 输出
  11419. exports = module.exports = filterCSS;
  11420. exports.FilterCSS = FilterCSS;
  11421. for (var i in DEFAULT) exports[i] = DEFAULT[i];
  11422. // 在浏览器端使用
  11423. if (typeof window !== 'undefined') {
  11424. window.filterCSS = module.exports;
  11425. }
  11426. },{"./css":6,"./default":7}],9:[function(require,module,exports){
  11427. /**
  11428. * cssfilter
  11429. *
  11430. * @author 老雷<leizongmin@gmail.com>
  11431. */
  11432. var _ = require('./util');
  11433. /**
  11434. * 解析style
  11435. *
  11436. * @param {String} css
  11437. * @param {Function} onAttr 处理属性的函数
  11438. * 参数格式: function (sourcePosition, position, name, value, source)
  11439. * @return {String}
  11440. */
  11441. function parseStyle (css, onAttr) {
  11442. css = _.trimRight(css);
  11443. if (css[css.length - 1] !== ';') css += ';';
  11444. var cssLength = css.length;
  11445. var isParenthesisOpen = false;
  11446. var lastPos = 0;
  11447. var i = 0;
  11448. var retCSS = '';
  11449. function addNewAttr () {
  11450. // 如果没有正常的闭合圆括号,则直接忽略当前属性
  11451. if (!isParenthesisOpen) {
  11452. var source = _.trim(css.slice(lastPos, i));
  11453. var j = source.indexOf(':');
  11454. if (j !== -1) {
  11455. var name = _.trim(source.slice(0, j));
  11456. var value = _.trim(source.slice(j + 1));
  11457. // 必须有属性名称
  11458. if (name) {
  11459. var ret = onAttr(lastPos, retCSS.length, name, value, source);
  11460. if (ret) retCSS += ret + '; ';
  11461. }
  11462. }
  11463. }
  11464. lastPos = i + 1;
  11465. }
  11466. for (; i < cssLength; i++) {
  11467. var c = css[i];
  11468. if (c === '/' && css[i + 1] === '*') {
  11469. // 备注开始
  11470. var j = css.indexOf('*/', i + 2);
  11471. // 如果没有正常的备注结束,则后面的部分全部跳过
  11472. if (j === -1) break;
  11473. // 直接将当前位置调到备注结尾,并且初始化状态
  11474. i = j + 1;
  11475. lastPos = i + 1;
  11476. isParenthesisOpen = false;
  11477. } else if (c === '(') {
  11478. isParenthesisOpen = true;
  11479. } else if (c === ')') {
  11480. isParenthesisOpen = false;
  11481. } else if (c === ';') {
  11482. if (isParenthesisOpen) {
  11483. // 在圆括号里面,忽略
  11484. } else {
  11485. addNewAttr();
  11486. }
  11487. } else if (c === '\n') {
  11488. addNewAttr();
  11489. }
  11490. }
  11491. return _.trim(retCSS);
  11492. }
  11493. module.exports = parseStyle;
  11494. },{"./util":10}],10:[function(require,module,exports){
  11495. module.exports = {
  11496. indexOf: function (arr, item) {
  11497. var i, j;
  11498. if (Array.prototype.indexOf) {
  11499. return arr.indexOf(item);
  11500. }
  11501. for (i = 0, j = arr.length; i < j; i++) {
  11502. if (arr[i] === item) {
  11503. return i;
  11504. }
  11505. }
  11506. return -1;
  11507. },
  11508. forEach: function (arr, fn, scope) {
  11509. var i, j;
  11510. if (Array.prototype.forEach) {
  11511. return arr.forEach(fn, scope);
  11512. }
  11513. for (i = 0, j = arr.length; i < j; i++) {
  11514. fn.call(scope, arr[i], i, arr);
  11515. }
  11516. },
  11517. trim: function (str) {
  11518. if (String.prototype.trim) {
  11519. return str.trim();
  11520. }
  11521. return str.replace(/(^\s*)|(\s*$)/g, '');
  11522. },
  11523. trimRight: function (str) {
  11524. if (String.prototype.trimRight) {
  11525. return str.trimRight();
  11526. }
  11527. return str.replace(/(\s*$)/g, '');
  11528. }
  11529. };
  11530. },{}]},{},[2]);
  11531. define("xss", (function (global) {
  11532. return function () {
  11533. var ret, fn;
  11534. fn = function (xss_noconflict) {
  11535. return {
  11536. filterXSS: window.filterXSS,
  11537. filterCSS: window.filterCSS
  11538. }
  11539. };
  11540. ret = fn.apply(global, arguments);
  11541. return ret;
  11542. };
  11543. }(this)));
  11544. /* Lo-Dash Template Loader v1.0.1
  11545. * Copyright 2015, Tim Branyen (@tbranyen).
  11546. * loader.js may be freely distributed under the MIT license.
  11547. */
  11548. (function(global) {
  11549. "use strict";
  11550. // Cache used to map configuration options between load and write.
  11551. var buildMap = {};
  11552. // Alias the correct `nodeRequire` method.
  11553. var nodeRequire = typeof requirejs === "function" && requirejs.nodeRequire;
  11554. // Strips trailing `/` from url fragments.
  11555. var stripTrailing = function(prop) {
  11556. return prop.replace(/(\/$)/, '');
  11557. };
  11558. // Define the plugin using the CommonJS syntax.
  11559. define('tpl',['require','exports','module','lodash'],function(require, exports) {
  11560. var _ = require("lodash");
  11561. exports.version = "1.0.1";
  11562. // Invoked by the AMD builder, passed the path to resolve, the require
  11563. // function, done callback, and the configuration options.
  11564. exports.load = function(name, req, load, config) {
  11565. var isDojo;
  11566. // Dojo provides access to the config object through the req function.
  11567. if (!config) {
  11568. config = require.rawConfig;
  11569. isDojo = true;
  11570. }
  11571. var contents = "";
  11572. var settings = configure(config);
  11573. // If the baseUrl and root are the same, just null out the root.
  11574. if (stripTrailing(config.baseUrl) === stripTrailing(settings.root)) {
  11575. settings.root = '';
  11576. }
  11577. var url = require.toUrl(settings.root + name + settings.ext);
  11578. if (isDojo && url.indexOf(config.baseUrl) !== 0) {
  11579. url = stripTrailing(config.baseUrl) + url;
  11580. }
  11581. // Builds with r.js require Node.js to be installed.
  11582. if (config.isBuild) {
  11583. // If in Node, get access to the filesystem.
  11584. var fs = nodeRequire("fs");
  11585. try {
  11586. // First try reading the filepath as-is.
  11587. contents = String(fs.readFileSync(url));
  11588. } catch(ex) {
  11589. // If it failed, it's most likely because of a leading `/` and not an
  11590. // absolute path. Remove the leading slash and try again.
  11591. if (url.slice(0, 1) === "/") {
  11592. url = url.slice(1);
  11593. }
  11594. // Try reading again with the leading `/`.
  11595. contents = String(fs.readFileSync(url));
  11596. }
  11597. // Read in the file synchronously, as RequireJS expects, and return the
  11598. // contents. Process as a Lo-Dash template.
  11599. buildMap[name] = _.template(contents);
  11600. return load();
  11601. }
  11602. // Create a basic XHR.
  11603. var xhr = new XMLHttpRequest();
  11604. // Wait for it to load.
  11605. xhr.onreadystatechange = function() {
  11606. if (xhr.readyState === 4) {
  11607. var templateSettings = _.clone(settings.templateSettings);
  11608. // Attach the sourceURL.
  11609. templateSettings.sourceURL = url;
  11610. // Process as a Lo-Dash template and cache.
  11611. buildMap[name] = _.template(xhr.responseText, templateSettings);
  11612. // Return the compiled template.
  11613. load(buildMap[name]);
  11614. }
  11615. };
  11616. // Initiate the fetch.
  11617. xhr.open("GET", url, true);
  11618. xhr.send(null);
  11619. };
  11620. // Also invoked by the AMD builder, this writes out a compatible define
  11621. // call that will work with loaders such as almond.js that cannot read
  11622. // the configuration data.
  11623. exports.write = function(pluginName, moduleName, write) {
  11624. var template = buildMap[moduleName].source;
  11625. // Write out the actual definition
  11626. write(strDefine(pluginName, moduleName, template));
  11627. };
  11628. // This is for curl.js/cram.js build-time support.
  11629. exports.compile = function(pluginName, moduleName, req, io, config) {
  11630. configure(config);
  11631. // Ask cram to fetch the template file (resId) and pass it to `write`.
  11632. io.read(moduleName, write, io.error);
  11633. function write(template) {
  11634. // Write-out define(id,function(){return{/* template */}});
  11635. io.write(strDefine(pluginName, moduleName, template));
  11636. }
  11637. };
  11638. // Crafts the written definition form of the module during a build.
  11639. function strDefine(pluginName, moduleName, template) {
  11640. return [
  11641. "define('", pluginName, "!", moduleName, "', ", "['lodash'], ",
  11642. [
  11643. "function(_) {",
  11644. "return ", template, ";",
  11645. "}"
  11646. ].join(""),
  11647. ");\n"
  11648. ].join("");
  11649. }
  11650. function configure(config) {
  11651. // Default settings point to the project root and using html files.
  11652. var settings = _.extend({
  11653. ext: ".html",
  11654. root: config.baseUrl,
  11655. templateSettings: {}
  11656. }, config.lodashLoader);
  11657. // Ensure the root has been properly configured with a trailing slash,
  11658. // unless it's an empty string or undefined, in which case work off the
  11659. // baseUrl.
  11660. if (settings.root && settings.root.slice(-1) !== "/") {
  11661. settings.root += "/";
  11662. }
  11663. // Set the custom passed in template settings.
  11664. _.extend(_.templateSettings, settings.templateSettings);
  11665. return settings;
  11666. }
  11667. });
  11668. })(typeof global === "object" ? global : this);
  11669. define('tpl!action', ['lodash'], function(_) {return function(o) {
  11670. var __t, __p = '', __e = _.escape;
  11671. __p += '<div class="message chat-message ' +
  11672. __e(o.extra_classes) +
  11673. '" data-isodate="' +
  11674. __e(o.isodate) +
  11675. '">\n <span class="chat-msg-author chat-msg-' +
  11676. __e(o.sender) +
  11677. '">' +
  11678. __e(o.time) +
  11679. ' **' +
  11680. __e(o.username) +
  11681. '&nbsp;</span>\n <span class="chat-msg-content chat-action"><!-- message gets added here via renderMessage --></span>\n</div>\n';
  11682. return __p
  11683. };});
  11684. define('tpl!chatbox', ['lodash'], function(_) {return function(o) {
  11685. var __t, __p = '', __j = Array.prototype.join;
  11686. function print() { __p += __j.call(arguments, '') }
  11687. __p += '<div class="flyout box-flyout">\n <div class="chat-body">\n <div class="chat-content ';
  11688. if (o.show_send_button) { ;
  11689. __p += 'chat-content-sendbutton';
  11690. } ;
  11691. __p += '"></div>\n <div class="message-form-container"/>\n </div>\n</div>\n';
  11692. return __p
  11693. };});
  11694. define('tpl!chatbox_head', ['lodash'], function(_) {return function(o) {
  11695. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11696. function print() { __p += __j.call(arguments, '') }
  11697. __p += '<div class="chat-head chat-head-chatbox row no-gutters">\n <div class="col">\n <div class="row no-gutters">\n ';
  11698. if (o.show_avatar) { ;
  11699. __p += '\n <div class="col-auto">\n <img alt="User Avatar"\n class="avatar"\n height="' +
  11700. __e(o.avatar_height) +
  11701. 'px" width="' +
  11702. __e(o.avatar_width) +
  11703. 'px"\n src="data:' +
  11704. __e(o.image_type || o._converse.DEFAULT_IMAGE_TYPE) +
  11705. ';base64,' +
  11706. __e(o.image || o._converse.DEFAULT_IMAGE) +
  11707. '"/>\n </div>\n ';
  11708. } ;
  11709. __p += '\n <div class="col chat-title" title="' +
  11710. __e(o.jid) +
  11711. '">\n ';
  11712. if (o.url) { ;
  11713. __p += '\n <a href="' +
  11714. __e(o.url) +
  11715. '" target="_blank" rel="noopener" class="user">\n ';
  11716. } ;
  11717. __p += '\n ' +
  11718. __e( o.fullname || o.jid ) +
  11719. '\n ';
  11720. if (o.url) { ;
  11721. __p += '\n </a>\n ';
  11722. } ;
  11723. __p += '\n <p class="user-custom-message">' +
  11724. __e( o.status ) +
  11725. '</p>\n </div>\n </div>\n </div>\n <div class="chatbox-buttons row no-gutters">\n <a class="chatbox-btn close-chatbox-button fa fa-close" title=' +
  11726. __e(o.info_close) +
  11727. '></a>\n <!-- <a class="chatbox-btn fa fa-vcard" title="Contact profile" data-toggle="modal" data-target="#contactProfileModal"></a> -->\n </div>\n</div>\n';
  11728. return __p
  11729. };});
  11730. define('tpl!chatbox_message_form', ['lodash'], function(_) {return function(o) {
  11731. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11732. function print() { __p += __j.call(arguments, '') }
  11733. __p += '<div class="message-form-container">\n<div class="new-msgs-indicator hidden">▼ ' +
  11734. __e( o.unread_msgs ) +
  11735. ' ▼</div>\n<form class="sendXMPPMessage">\n ';
  11736. if (o.show_toolbar) { ;
  11737. __p += '\n <ul class="chat-toolbar no-text-select"></ul>\n ';
  11738. } ;
  11739. __p += '\n <input type="text" placeholder="' +
  11740. ((__t = (o.label_spoiler_hint)) == null ? '' : __t) +
  11741. '" value="' +
  11742. ((__t = ( o.hint_value )) == null ? '' : __t) +
  11743. '"\n class="';
  11744. if (!o.composing_spoiler) { ;
  11745. __p += ' hidden ';
  11746. } ;
  11747. __p += ' spoiler-hint"/>\n <textarea\n type="text"\n class="chat-textarea\n ';
  11748. if (o.show_send_button) { ;
  11749. __p += ' chat-textarea-send-button ';
  11750. } ;
  11751. __p += '\n ';
  11752. if (o.composing_spoiler) { ;
  11753. __p += ' spoiler ';
  11754. } ;
  11755. __p += '"\n placeholder="' +
  11756. __e(o.label_personal_message) +
  11757. '">' +
  11758. ((__t = ( o.message_value )) == null ? '' : __t) +
  11759. '</textarea>\n ';
  11760. if (o.show_send_button) { ;
  11761. __p += '\n <button type="submit" class="pure-button send-button">' +
  11762. __e( o.label_send ) +
  11763. '</button>\n ';
  11764. } ;
  11765. __p += '\n</form>\n</div>\n';
  11766. return __p
  11767. };});
  11768. define('tpl!emojis', ['lodash'], function(_) {return function(o) {
  11769. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11770. function print() { __p += __j.call(arguments, '') }
  11771. __p += '<div class="emoji-picker-container">\n';
  11772. _.forEach(o.emojis_by_category, function (obj, category) { ;
  11773. __p += '\n <ul class="emoji-picker emoji-picker-' +
  11774. __e(category) +
  11775. ' ';
  11776. if (o.current_category !== category) { ;
  11777. __p += ' hidden ';
  11778. } ;
  11779. __p += '">\n ';
  11780. _.forEach(o.emojis_by_category[category], function (emoji) { ;
  11781. __p += '\n <li class="emoji insert-emoji ';
  11782. if (o.shouldBeHidden(emoji._shortname, o.current_skintone, o.toned_emojis)) { ;
  11783. __p += ' hidden ';
  11784. }; ;
  11785. __p += '"\n data-emoji="' +
  11786. __e(emoji._shortname) +
  11787. '">\n <a href="#" data-emoji="' +
  11788. __e(emoji._shortname) +
  11789. '"> ' +
  11790. ((__t = ( o.transform(emoji._shortname) )) == null ? '' : __t) +
  11791. ' </a>\n </li>\n ';
  11792. }); ;
  11793. __p += '\n </ul>\n';
  11794. }); ;
  11795. __p += '\n<ul class="emoji-toolbar">\n <li class="emoji-category-picker">\n <ul>\n ';
  11796. _.forEach(o.emojis_by_category, function (obj, category) { ;
  11797. __p += '\n <li data-category="' +
  11798. __e(category) +
  11799. '" class="emoji-category ';
  11800. if (o.current_category === category) { ;
  11801. __p += ' picked ';
  11802. } ;
  11803. __p += '">\n <a class="pick-category" href="#" data-category="' +
  11804. __e(category) +
  11805. '"> ' +
  11806. ((__t = ( o.transform(o.emojis_by_category[category][0]._shortname) )) == null ? '' : __t) +
  11807. ' </a>\n </li>\n ';
  11808. }); ;
  11809. __p += '\n </ul>\n </li>\n <li class="emoji-skintone-picker">\n <ul>\n ';
  11810. _.forEach(o.skintones, function (skintone) { ;
  11811. __p += '\n <li data-skintone="' +
  11812. __e(skintone) +
  11813. '" class="emoji-skintone ';
  11814. if (o.current_skintone === skintone) { ;
  11815. __p += ' picked ';
  11816. } ;
  11817. __p += '">\n <a class="pick-skintone" href="#" data-skintone="' +
  11818. __e(skintone) +
  11819. '"> ' +
  11820. ((__t = ( o.transform(':'+skintone+':') )) == null ? '' : __t) +
  11821. ' </a>\n </li>\n ';
  11822. }); ;
  11823. __p += '\n </ul>\n </li>\n</ul>\n</div>\n';
  11824. return __p
  11825. };});
  11826. define('tpl!help_message', ['lodash'], function(_) {return function(o) {
  11827. var __t, __p = '', __e = _.escape;
  11828. __p += '<div class="message chat-' +
  11829. __e(o.type) +
  11830. '" data-isodate="' +
  11831. __e(o.isodate) +
  11832. '">' +
  11833. ((__t = (o.message)) == null ? '' : __t) +
  11834. '</div>\n';
  11835. return __p
  11836. };});
  11837. define('tpl!info', ['lodash'], function(_) {return function(o) {
  11838. var __t, __p = '', __e = _.escape;
  11839. __p += '<div class="message chat-info ' +
  11840. __e(o.extra_classes) +
  11841. '" data-isodate="' +
  11842. __e(o.isodate) +
  11843. '" ' +
  11844. __e(o.data) +
  11845. '>' +
  11846. __e(o.message) +
  11847. '</div>\n';
  11848. return __p
  11849. };});
  11850. define('tpl!message', ['lodash'], function(_) {return function(o) {
  11851. var __t, __p = '', __e = _.escape;
  11852. __p += '<div class="message chat-message ' +
  11853. __e(o.extra_classes) +
  11854. '" data-isodate="' +
  11855. __e(o.isodate) +
  11856. '" data-msgid="' +
  11857. __e(o.msgid) +
  11858. '">\n <span class="chat-msg-author chat-msg-' +
  11859. __e(o.sender) +
  11860. '">' +
  11861. __e(o.time) +
  11862. ' ' +
  11863. __e(o.username) +
  11864. ':&nbsp;</span>\n <span class="chat-msg-content"><!-- message gets added here via renderMessage --></span>\n</div>\n';
  11865. return __p
  11866. };});
  11867. define('tpl!new_day', ['lodash'], function(_) {return function(o) {
  11868. var __t, __p = '', __e = _.escape;
  11869. __p += '<time class="message chat-info chat-date badge badge-info" data-isodate="' +
  11870. __e(o.isodate) +
  11871. '">' +
  11872. __e(o.datestring) +
  11873. '</time>\n';
  11874. return __p
  11875. };});
  11876. define('tpl!spinner', ['lodash'], function(_) {return function(o) {
  11877. var __t, __p = '';
  11878. __p += '<span class="spinner fa fa-spinner centered"/>\n';
  11879. return __p
  11880. };});
  11881. define('tpl!spoiler_button', ['lodash'], function(_) {return function(o) {
  11882. var __t, __p = '', __j = Array.prototype.join;
  11883. function print() { __p += __j.call(arguments, '') }
  11884. __p += '<li class="toggle-compose-spoiler fa ';
  11885. if (o.composing_spoiler) { ;
  11886. __p += ' fa-eye-slash ';
  11887. } ;
  11888. __p += ' ';
  11889. if (!o.composing_spoiler) { ;
  11890. __p += ' fa-eye ';
  11891. } ;
  11892. __p += '"\n title="' +
  11893. ((__t = ( o.label_toggle_spoiler )) == null ? '' : __t) +
  11894. '"></a>\n</li>\n';
  11895. return __p
  11896. };});
  11897. define('tpl!spoiler_message', ['lodash'], function(_) {return function(o) {
  11898. var __t, __p = '', __e = _.escape;
  11899. __p += '<div class="message chat-message ' +
  11900. __e(o.extra_classes) +
  11901. '" data-isodate="' +
  11902. __e(o.isodate) +
  11903. '" data-msgid="' +
  11904. __e(o.msgid) +
  11905. '">\n <span class="chat-msg-author chat-msg-' +
  11906. __e(o.sender) +
  11907. '">' +
  11908. __e(o.time) +
  11909. ' ' +
  11910. __e(o.username) +
  11911. ':&nbsp;</span>\n <div class="spoiler-hint"><!-- message gets added here via renderMessage --></div>\n <a class="icon-eye toggle-spoiler" data-toggle-state="closed" href="#">' +
  11912. __e(o.label_show) +
  11913. '</a>\n <div class="chat-msg-content spoiler collapsed"><!-- message gets added here via renderMessage --></div>\n</div>\n';
  11914. return __p
  11915. };});
  11916. define('tpl!toolbar', ['lodash'], function(_) {return function(o) {
  11917. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11918. function print() { __p += __j.call(arguments, '') }
  11919. if (o.use_emoji) { ;
  11920. __p += '\n<li class="toggle-toolbar-menu toggle-smiley fa fa-smile-o dropup">\n <div class="emoji-picker dropdown-menu toolbar-menu"></div>\n</li>\n';
  11921. } ;
  11922. __p += '\n';
  11923. if (o.show_call_button) { ;
  11924. __p += '\n<li class="toggle-call fa fa-phone" title="' +
  11925. __e(o.label_start_call) +
  11926. '"></li>\n';
  11927. } ;
  11928. __p += '\n';
  11929. return __p
  11930. };});
  11931. define('tpl!chatboxes', ['lodash'], function(_) {return function(o) {
  11932. var __t, __p = '';
  11933. __p += '<div class="converse-chatboxes row no-gutters"></div>\n<div id="converse-modals" class="modals"></div>\n';
  11934. return __p
  11935. };});
  11936. // Converse.js (A browser based XMPP chat client)
  11937. // http://conversejs.org
  11938. //
  11939. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  11940. // Licensed under the Mozilla Public License (MPLv2)
  11941. //
  11942. /*global define */
  11943. (function (root, factory) {
  11944. define('converse-chatboxes',["converse-core", "tpl!chatboxes", "backbone.overview"], factory);
  11945. })(void 0, function (converse, tpl_chatboxes) {
  11946. "use strict";
  11947. var _converse$env = converse.env,
  11948. Backbone = _converse$env.Backbone,
  11949. Promise = _converse$env.Promise,
  11950. Strophe = _converse$env.Strophe,
  11951. b64_sha1 = _converse$env.b64_sha1,
  11952. moment = _converse$env.moment,
  11953. utils = _converse$env.utils,
  11954. _ = _converse$env._;
  11955. converse.plugins.add('converse-chatboxes', {
  11956. overrides: {
  11957. // Overrides mentioned here will be picked up by converse.js's
  11958. // plugin architecture they will replace existing methods on the
  11959. // relevant objects or classes.
  11960. disconnect: function disconnect() {
  11961. var _converse = this.__super__._converse;
  11962. _converse.chatboxviews.closeAllChatBoxes();
  11963. return this.__super__.disconnect.apply(this, arguments);
  11964. },
  11965. logOut: function logOut() {
  11966. var _converse = this.__super__._converse;
  11967. _converse.chatboxviews.closeAllChatBoxes();
  11968. return this.__super__.logOut.apply(this, arguments);
  11969. },
  11970. initStatus: function initStatus(reconnecting) {
  11971. var _converse = this.__super__._converse;
  11972. if (!reconnecting) {
  11973. _converse.chatboxviews.closeAllChatBoxes();
  11974. }
  11975. return this.__super__.initStatus.apply(this, arguments);
  11976. }
  11977. },
  11978. initialize: function initialize() {
  11979. /* The initialize function gets called as soon as the plugin is
  11980. * loaded by converse.js's plugin machinery.
  11981. */
  11982. var _converse = this._converse;
  11983. _converse.api.promises.add(['chatBoxesFetched', 'chatBoxesInitialized']);
  11984. function openChat(jid) {
  11985. if (!utils.isValidJID(jid)) {
  11986. return converse.log("Invalid JID \"".concat(jid, "\" provided in URL fragment"), Strophe.LogLevel.WARN);
  11987. }
  11988. Promise.all([_converse.api.waitUntil('rosterContactsFetched'), _converse.api.waitUntil('chatBoxesFetched')]).then(function () {
  11989. _converse.api.chats.open(jid);
  11990. });
  11991. }
  11992. _converse.router.route('converse/chat?jid=:jid', openChat);
  11993. _converse.Message = Backbone.Model.extend({
  11994. defaults: function defaults() {
  11995. return {
  11996. msgid: _converse.connection.getUniqueId()
  11997. };
  11998. }
  11999. });
  12000. _converse.Messages = Backbone.Collection.extend({
  12001. model: _converse.Message,
  12002. comparator: 'time'
  12003. });
  12004. _converse.ChatBox = Backbone.Model.extend({
  12005. defaults: {
  12006. 'bookmarked': false,
  12007. 'chat_state': undefined,
  12008. 'image': _converse.DEFAULT_IMAGE,
  12009. 'image_type': _converse.DEFAULT_IMAGE_TYPE,
  12010. 'num_unread': 0,
  12011. 'show_avatar': true,
  12012. 'type': 'chatbox',
  12013. 'url': ''
  12014. },
  12015. initialize: function initialize() {
  12016. this.messages = new _converse.Messages();
  12017. this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](b64_sha1("converse.messages".concat(this.get('jid')).concat(_converse.bare_jid)));
  12018. this.save({
  12019. // The chat_state will be set to ACTIVE once the chat box is opened
  12020. // and we listen for change:chat_state, so shouldn't set it to ACTIVE here.
  12021. 'box_id': b64_sha1(this.get('jid')),
  12022. 'time_opened': this.get('time_opened') || moment().valueOf(),
  12023. 'user_id': Strophe.getNodeFromJid(this.get('jid'))
  12024. });
  12025. },
  12026. getMessageBody: function getMessageBody(message) {
  12027. var type = message.getAttribute('type');
  12028. return type === 'error' ? _.propertyOf(message.querySelector('error text'))('textContent') : _.propertyOf(message.querySelector('body'))('textContent');
  12029. },
  12030. getMessageAttributes: function getMessageAttributes(message, delay, original_stanza) {
  12031. /* Parses a passed in message stanza and returns an object
  12032. * of attributes.
  12033. *
  12034. * Parameters:
  12035. * (XMLElement) message - The message stanza
  12036. * (XMLElement) delay - The <delay> node from the
  12037. * stanza, if there was one.
  12038. * (XMLElement) original_stanza - The original stanza,
  12039. * that contains the message stanza, if it was
  12040. * contained, otherwise it's the message stanza itself.
  12041. */
  12042. var _converse = this.__super__._converse,
  12043. __ = _converse.__;
  12044. delay = delay || message.querySelector('delay');
  12045. var type = message.getAttribute('type'),
  12046. body = this.getMessageBody(message);
  12047. var delayed = !_.isNull(delay),
  12048. is_groupchat = type === 'groupchat',
  12049. chat_state = message.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || message.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || message.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || message.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || message.getElementsByTagName(_converse.GONE).length && _converse.GONE;
  12050. var from;
  12051. if (is_groupchat) {
  12052. from = Strophe.unescapeNode(Strophe.getResourceFromJid(message.getAttribute('from')));
  12053. } else {
  12054. from = Strophe.getBareJidFromJid(message.getAttribute('from'));
  12055. }
  12056. var time = delayed ? delay.getAttribute('stamp') : moment().format();
  12057. var sender, fullname;
  12058. if (is_groupchat && from === this.get('nick') || !is_groupchat && from === _converse.bare_jid) {
  12059. sender = 'me';
  12060. fullname = _converse.xmppstatus.get('fullname') || from;
  12061. } else {
  12062. sender = 'them';
  12063. fullname = this.get('fullname') || from;
  12064. }
  12065. var spoiler = message.querySelector("spoiler[xmlns=\"".concat(Strophe.NS.SPOILER, "\"]"));
  12066. var attrs = {
  12067. 'type': type,
  12068. 'chat_state': chat_state,
  12069. 'delayed': delayed,
  12070. 'fullname': fullname,
  12071. 'message': body || undefined,
  12072. 'msgid': message.getAttribute('id'),
  12073. 'sender': sender,
  12074. 'time': time,
  12075. 'is_spoiler': !_.isNull(spoiler)
  12076. };
  12077. if (spoiler) {
  12078. attrs.spoiler_hint = spoiler.textContent.length > 0 ? spoiler.textContent : '';
  12079. }
  12080. return attrs;
  12081. },
  12082. createMessage: function createMessage(message, delay, original_stanza) {
  12083. /* Create a Backbone.Message object inside this chat box
  12084. * based on the identified message stanza.
  12085. */
  12086. return this.messages.create(this.getMessageAttributes.apply(this, arguments));
  12087. },
  12088. newMessageWillBeHidden: function newMessageWillBeHidden() {
  12089. /* Returns a boolean to indicate whether a newly received
  12090. * message will be visible to the user or not.
  12091. */
  12092. return this.get('hidden') || this.get('minimized') || this.isScrolledUp() || _converse.windowState === 'hidden';
  12093. },
  12094. incrementUnreadMsgCounter: function incrementUnreadMsgCounter(stanza) {
  12095. /* Given a newly received message, update the unread counter if
  12096. * necessary.
  12097. */
  12098. if (_.isNull(stanza.querySelector('body'))) {
  12099. return; // The message has no text
  12100. }
  12101. if (utils.isNewMessage(stanza) && this.newMessageWillBeHidden()) {
  12102. this.save({
  12103. 'num_unread': this.get('num_unread') + 1
  12104. });
  12105. _converse.incrementMsgCounter();
  12106. }
  12107. },
  12108. clearUnreadMsgCounter: function clearUnreadMsgCounter() {
  12109. this.save({
  12110. 'num_unread': 0
  12111. });
  12112. },
  12113. isScrolledUp: function isScrolledUp() {
  12114. return this.get('scrolled', true);
  12115. }
  12116. });
  12117. _converse.ChatBoxes = Backbone.Collection.extend({
  12118. comparator: 'time_opened',
  12119. model: function model(attrs, options) {
  12120. return new _converse.ChatBox(attrs, options);
  12121. },
  12122. registerMessageHandler: function registerMessageHandler() {
  12123. _converse.connection.addHandler(this.onMessage.bind(this), null, 'message', 'chat');
  12124. _converse.connection.addHandler(this.onErrorMessage.bind(this), null, 'message', 'error');
  12125. },
  12126. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  12127. return true;
  12128. },
  12129. onChatBoxesFetched: function onChatBoxesFetched(collection) {
  12130. var _this = this;
  12131. /* Show chat boxes upon receiving them from sessionStorage */
  12132. collection.each(function (chatbox) {
  12133. if (_this.chatBoxMayBeShown(chatbox)) {
  12134. chatbox.trigger('show');
  12135. }
  12136. });
  12137. _converse.emit('chatBoxesFetched');
  12138. },
  12139. onConnected: function onConnected() {
  12140. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.chatboxes-".concat(_converse.bare_jid)));
  12141. this.registerMessageHandler();
  12142. this.fetch({
  12143. add: true,
  12144. success: this.onChatBoxesFetched.bind(this)
  12145. });
  12146. },
  12147. onErrorMessage: function onErrorMessage(message) {
  12148. /* Handler method for all incoming error message stanzas
  12149. */
  12150. // TODO: we can likely just reuse "onMessage" below
  12151. var from_jid = Strophe.getBareJidFromJid(message.getAttribute('from'));
  12152. if (utils.isSameBareJID(from_jid, _converse.bare_jid)) {
  12153. return true;
  12154. } // Get chat box, but only create a new one when the message has a body.
  12155. var chatbox = this.getChatBox(from_jid);
  12156. if (!chatbox) {
  12157. return true;
  12158. }
  12159. chatbox.createMessage(message, null, message);
  12160. return true;
  12161. },
  12162. onMessage: function onMessage(message) {
  12163. /* Handler method for all incoming single-user chat "message"
  12164. * stanzas.
  12165. *
  12166. * Parameters:
  12167. * (XMLElement) message - The incoming message stanza
  12168. */
  12169. var contact_jid,
  12170. delay,
  12171. resource,
  12172. from_jid = message.getAttribute('from'),
  12173. to_jid = message.getAttribute('to');
  12174. var original_stanza = message,
  12175. to_resource = Strophe.getResourceFromJid(to_jid),
  12176. is_carbon = !_.isNull(message.querySelector("received[xmlns=\"".concat(Strophe.NS.CARBONS, "\"]")));
  12177. if (_converse.filter_by_resource && to_resource && to_resource !== _converse.resource) {
  12178. _converse.log("onMessage: Ignoring incoming message intended for a different resource: ".concat(to_jid), Strophe.LogLevel.INFO);
  12179. return true;
  12180. } else if (utils.isHeadlineMessage(_converse, message)) {
  12181. // XXX: Ideally we wouldn't have to check for headline
  12182. // messages, but Prosody sends headline messages with the
  12183. // wrong type ('chat'), so we need to filter them out here.
  12184. _converse.log("onMessage: Ignoring incoming headline message sent with type 'chat' from JID: ".concat(from_jid), Strophe.LogLevel.INFO);
  12185. return true;
  12186. }
  12187. var forwarded = message.querySelector('forwarded');
  12188. if (!_.isNull(forwarded)) {
  12189. var forwarded_message = forwarded.querySelector('message');
  12190. var forwarded_from = forwarded_message.getAttribute('from');
  12191. if (is_carbon && Strophe.getBareJidFromJid(forwarded_from) !== from_jid) {
  12192. // Prevent message forging via carbons
  12193. //
  12194. // https://xmpp.org/extensions/xep-0280.html#security
  12195. return true;
  12196. }
  12197. message = forwarded_message;
  12198. delay = forwarded.querySelector('delay');
  12199. from_jid = message.getAttribute('from');
  12200. to_jid = message.getAttribute('to');
  12201. }
  12202. var from_bare_jid = Strophe.getBareJidFromJid(from_jid),
  12203. from_resource = Strophe.getResourceFromJid(from_jid),
  12204. is_me = from_bare_jid === _converse.bare_jid;
  12205. if (is_me) {
  12206. // I am the sender, so this must be a forwarded message...
  12207. contact_jid = Strophe.getBareJidFromJid(to_jid);
  12208. resource = Strophe.getResourceFromJid(to_jid);
  12209. } else {
  12210. contact_jid = from_bare_jid;
  12211. resource = from_resource;
  12212. } // Get chat box, but only create a new one when the message has a body.
  12213. var attrs = {
  12214. 'fullname': _.get(_converse.api.contacts.get(contact_jid), 'attributes.fullname')
  12215. };
  12216. var chatbox = this.getChatBox(contact_jid, attrs, !_.isNull(message.querySelector('body'))),
  12217. msgid = message.getAttribute('id');
  12218. if (chatbox) {
  12219. var messages = msgid && chatbox.messages.findWhere({
  12220. msgid: msgid
  12221. }) || [];
  12222. if (_.isEmpty(messages)) {
  12223. // Only create the message when we're sure it's not a
  12224. // duplicate
  12225. chatbox.incrementUnreadMsgCounter(original_stanza);
  12226. chatbox.createMessage(message, delay, original_stanza);
  12227. }
  12228. }
  12229. _converse.emit('message', {
  12230. 'stanza': original_stanza,
  12231. 'chatbox': chatbox
  12232. });
  12233. return true;
  12234. },
  12235. getChatBox: function getChatBox(jid) {
  12236. var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  12237. var create = arguments.length > 2 ? arguments[2] : undefined;
  12238. /* Returns a chat box or optionally return a newly
  12239. * created one if one doesn't exist.
  12240. *
  12241. * Parameters:
  12242. * (String) jid - The JID of the user whose chat box we want
  12243. * (Boolean) create - Should a new chat box be created if none exists?
  12244. * (Object) attrs - Optional chat box atributes.
  12245. */
  12246. if (_.isObject(jid)) {
  12247. create = attrs;
  12248. attrs = jid;
  12249. jid = attrs.jid;
  12250. }
  12251. jid = Strophe.getBareJidFromJid(jid.toLowerCase());
  12252. var chatbox = this.get(Strophe.getBareJidFromJid(jid));
  12253. if (!chatbox && create) {
  12254. _.extend(attrs, {
  12255. 'jid': jid,
  12256. 'id': jid
  12257. });
  12258. chatbox = this.create(attrs, {
  12259. 'error': function error(model, response) {
  12260. _converse.log(response.responseText);
  12261. }
  12262. });
  12263. }
  12264. return chatbox;
  12265. }
  12266. });
  12267. _converse.ChatBoxViews = Backbone.Overview.extend({
  12268. _ensureElement: function _ensureElement() {
  12269. /* Override method from backbone.js
  12270. * If the #conversejs element doesn't exist, create it.
  12271. */
  12272. if (!this.el) {
  12273. var el = _converse.root.querySelector('#conversejs');
  12274. if (_.isNull(el)) {
  12275. el = document.createElement('div');
  12276. el.setAttribute('id', 'conversejs');
  12277. var body = _converse.root.querySelector('body');
  12278. if (body) {
  12279. body.appendChild(el);
  12280. } else {
  12281. // Perhaps inside a web component?
  12282. _converse.root.appendChild(el);
  12283. }
  12284. }
  12285. if (_.includes(['mobile', 'fullscreen'], _converse.view_mode)) {
  12286. el.classList.add('fullscreen');
  12287. }
  12288. el.innerHTML = '';
  12289. this.setElement(el, false);
  12290. } else {
  12291. this.setElement(_.result(this, 'el'), false);
  12292. }
  12293. },
  12294. initialize: function initialize() {
  12295. this.model.on("add", this.onChatBoxAdded, this);
  12296. this.model.on("destroy", this.removeChat, this);
  12297. this.render();
  12298. },
  12299. render: function render() {
  12300. try {
  12301. this.el.innerHTML = tpl_chatboxes();
  12302. } catch (e) {
  12303. this._ensureElement();
  12304. this.el.innerHTML = tpl_chatboxes();
  12305. }
  12306. this.row_el = this.el.querySelector('.row');
  12307. },
  12308. insertRowColumn: function insertRowColumn(el) {
  12309. /* Add a new DOM element (likely a chat box) into the
  12310. * the row managed by this overview.
  12311. */
  12312. this.row_el.insertAdjacentElement('afterBegin', el);
  12313. },
  12314. onChatBoxAdded: function onChatBoxAdded(item) {
  12315. // Views aren't created here, since the core code doesn't
  12316. // contain any views. Instead, they're created in overrides in
  12317. // plugins, such as in converse-chatview.js and converse-muc.js
  12318. return this.get(item.get('id'));
  12319. },
  12320. removeChat: function removeChat(item) {
  12321. this.remove(item.get('id'));
  12322. },
  12323. closeAllChatBoxes: function closeAllChatBoxes() {
  12324. /* This method gets overridden in src/converse-controlbox.js if
  12325. * the controlbox plugin is active.
  12326. */
  12327. this.each(function (view) {
  12328. view.close();
  12329. });
  12330. return this;
  12331. },
  12332. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  12333. return this.model.chatBoxMayBeShown(chatbox);
  12334. }
  12335. }); // TODO: move to converse-chatboxviews.js and use there in the API
  12336. _converse.getViewForChatBox = function (chatbox) {
  12337. if (!chatbox) {
  12338. return;
  12339. }
  12340. return _converse.chatboxviews.get(chatbox.get('id'));
  12341. };
  12342. /************************ BEGIN Event Handlers ************************/
  12343. _converse.api.listen.on('pluginsInitialized', function () {
  12344. _converse.chatboxes = new _converse.ChatBoxes();
  12345. _converse.chatboxviews = new _converse.ChatBoxViews({
  12346. 'model': _converse.chatboxes
  12347. });
  12348. _converse.emit('chatBoxesInitialized');
  12349. });
  12350. _converse.api.listen.on('beforeTearDown', function () {
  12351. _converse.chatboxes.remove(); // Don't call off(), events won't get re-registered upon reconnect.
  12352. delete _converse.chatboxes.browserStorage;
  12353. });
  12354. _converse.api.listen.on('statusInitialized', function () {
  12355. return _converse.chatboxes.onConnected();
  12356. });
  12357. /************************ END Event Handlers ************************/
  12358. /************************ BEGIN API ************************/
  12359. _.extend(_converse.api, {
  12360. 'chats': {
  12361. 'create': function create(jids, attrs) {
  12362. if (_.isUndefined(jids)) {
  12363. _converse.log("chats.create: You need to provide at least one JID", Strophe.LogLevel.ERROR);
  12364. return null;
  12365. }
  12366. if (_.isString(jids)) {
  12367. if (attrs && !_.get(attrs, 'fullname')) {
  12368. attrs.fullname = _.get(_converse.api.contacts.get(jids), 'attributes.fullname');
  12369. }
  12370. var chatbox = _converse.chatboxes.getChatBox(jids, attrs, true);
  12371. if (_.isNil(chatbox)) {
  12372. _converse.log("Could not open chatbox for JID: " + jids, Strophe.LogLevel.ERROR);
  12373. return;
  12374. }
  12375. return chatbox;
  12376. }
  12377. return _.map(jids, function (jid) {
  12378. attrs.fullname = _.get(_converse.api.contacts.get(jid), 'attributes.fullname');
  12379. return _converse.chatboxes.getChatBox(jid, attrs, true).trigger('show');
  12380. });
  12381. },
  12382. 'open': function open(jids, attrs) {
  12383. if (_.isUndefined(jids)) {
  12384. _converse.log("chats.open: You need to provide at least one JID", Strophe.LogLevel.ERROR);
  12385. return null;
  12386. } else if (_.isString(jids)) {
  12387. var chatbox = _converse.api.chats.create(jids, attrs);
  12388. chatbox.trigger('show');
  12389. return chatbox;
  12390. }
  12391. return _.map(jids, function (jid) {
  12392. return _converse.api.chats.create(jid, attrs).trigger('show');
  12393. });
  12394. },
  12395. 'get': function get(jids) {
  12396. if (_.isUndefined(jids)) {
  12397. var result = [];
  12398. _converse.chatboxes.each(function (chatbox) {
  12399. // FIXME: Leaky abstraction from MUC. We need to add a
  12400. // base type for chat boxes, and check for that.
  12401. if (chatbox.get('type') !== 'chatroom') {
  12402. result.push(chatbox);
  12403. }
  12404. });
  12405. return result;
  12406. } else if (_.isString(jids)) {
  12407. return _converse.chatboxes.getChatBox(jids);
  12408. }
  12409. return _.map(jids, _.partial(_converse.chatboxes.getChatBox.bind(_converse.chatboxes), _, {}, true));
  12410. }
  12411. }
  12412. });
  12413. /************************ END API ************************/
  12414. }
  12415. });
  12416. return converse;
  12417. });
  12418. //# sourceMappingURL=converse-chatboxes.js.map;
  12419. // Converse.js (A browser based XMPP chat client)
  12420. // http://conversejs.org
  12421. //
  12422. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  12423. // Licensed under the Mozilla Public License (MPLv2)
  12424. //
  12425. /*global define */
  12426. (function (root, factory) {
  12427. define('converse-chatview',["converse-core", "bootstrap", "emojione", "xss", "tpl!action", "tpl!chatbox", "tpl!chatbox_head", "tpl!chatbox_message_form", "tpl!emojis", "tpl!help_message", "tpl!info", "tpl!message", "tpl!new_day", "tpl!spinner", "tpl!spoiler_button", "tpl!spoiler_message", "tpl!toolbar", "converse-chatboxes"], factory);
  12428. })(void 0, function (converse, bootstrap, emojione, xss, tpl_action, tpl_chatbox, tpl_chatbox_head, tpl_chatbox_message_form, tpl_emojis, tpl_help_message, tpl_info, tpl_message, tpl_new_day, tpl_spinner, tpl_spoiler_button, tpl_spoiler_message, tpl_toolbar) {
  12429. "use strict";
  12430. var _converse$env = converse.env,
  12431. $msg = _converse$env.$msg,
  12432. Backbone = _converse$env.Backbone,
  12433. Promise = _converse$env.Promise,
  12434. Strophe = _converse$env.Strophe,
  12435. _ = _converse$env._,
  12436. b64_sha1 = _converse$env.b64_sha1,
  12437. f = _converse$env.f,
  12438. sizzle = _converse$env.sizzle,
  12439. moment = _converse$env.moment;
  12440. var u = converse.env.utils;
  12441. var KEY = {
  12442. ENTER: 13,
  12443. FORWARD_SLASH: 47
  12444. };
  12445. converse.plugins.add('converse-chatview', {
  12446. /* Plugin dependencies are other plugins which might be
  12447. * overridden or relied upon, and therefore need to be loaded before
  12448. * this plugin.
  12449. *
  12450. * If the setting "strict_plugin_dependencies" is set to true,
  12451. * an error will be raised if the plugin is not found. By default it's
  12452. * false, which means these plugins are only loaded opportunistically.
  12453. *
  12454. * NB: These plugins need to have already been loaded via require.js.
  12455. */
  12456. dependencies: ["converse-chatboxes", "converse-disco"],
  12457. overrides: {
  12458. // Overrides mentioned here will be picked up by converse.js's
  12459. // plugin architecture they will replace existing methods on the
  12460. // relevant objects or classes.
  12461. //
  12462. // New functions which don't exist yet can also be added.
  12463. //
  12464. ChatBoxViews: {
  12465. onChatBoxAdded: function onChatBoxAdded(item) {
  12466. var _converse = this.__super__._converse;
  12467. var view = this.get(item.get('id'));
  12468. if (!view) {
  12469. view = new _converse.ChatBoxView({
  12470. model: item
  12471. });
  12472. this.add(item.get('id'), view);
  12473. return view;
  12474. } else {
  12475. return this.__super__.onChatBoxAdded.apply(this, arguments);
  12476. }
  12477. }
  12478. }
  12479. },
  12480. initialize: function initialize() {
  12481. /* The initialize function gets called as soon as the plugin is
  12482. * loaded by converse.js's plugin machinery.
  12483. */
  12484. var _converse = this._converse,
  12485. __ = _converse.__;
  12486. _converse.api.settings.update({
  12487. 'use_emojione': false,
  12488. 'emojione_image_path': emojione.imagePathPNG,
  12489. 'chatview_avatar_height': 32,
  12490. 'chatview_avatar_width': 32,
  12491. 'show_toolbar': true,
  12492. 'show_message_load_animation': false,
  12493. 'time_format': 'HH:mm',
  12494. 'visible_toolbar_buttons': {
  12495. 'call': false,
  12496. 'clear': true,
  12497. 'emoji': true,
  12498. 'spoiler': true
  12499. }
  12500. });
  12501. emojione.imagePathPNG = _converse.emojione_image_path;
  12502. emojione.ascii = true;
  12503. function onWindowStateChanged(data) {
  12504. _converse.chatboxviews.each(function (chatboxview) {
  12505. chatboxview.onWindowStateChanged(data.state);
  12506. });
  12507. }
  12508. _converse.api.listen.on('windowStateChanged', onWindowStateChanged);
  12509. _converse.EmojiPicker = Backbone.Model.extend({
  12510. defaults: {
  12511. 'current_category': 'people',
  12512. 'current_skintone': '',
  12513. 'scroll_position': 0
  12514. },
  12515. initialize: function initialize() {
  12516. var id = "converse.emoji-".concat(_converse.bare_jid);
  12517. this.id = id;
  12518. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  12519. }
  12520. });
  12521. _converse.EmojiPickerView = Backbone.VDOMView.extend({
  12522. className: 'emoji-picker-container',
  12523. events: {
  12524. 'click .emoji-category-picker li.emoji-category': 'chooseCategory',
  12525. 'click .emoji-skintone-picker li.emoji-skintone': 'chooseSkinTone'
  12526. },
  12527. initialize: function initialize() {
  12528. this.model.on('change:current_skintone', this.render, this);
  12529. this.model.on('change:current_category', this.render, this);
  12530. },
  12531. toHTML: function toHTML() {
  12532. return tpl_emojis(_.extend(this.model.toJSON(), {
  12533. 'transform': _converse.use_emojione ? emojione.shortnameToImage : emojione.shortnameToUnicode,
  12534. 'emojis_by_category': u.getEmojisByCategory(_converse, emojione),
  12535. 'toned_emojis': u.getTonedEmojis(_converse),
  12536. 'skintones': ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'],
  12537. 'shouldBeHidden': this.shouldBeHidden
  12538. }));
  12539. },
  12540. shouldBeHidden: function shouldBeHidden(shortname, current_skintone, toned_emojis) {
  12541. /* Helper method for the template which decides whether an
  12542. * emoji should be hidden, based on which skin tone is
  12543. * currently being applied.
  12544. */
  12545. if (_.includes(shortname, '_tone')) {
  12546. if (!current_skintone || !_.includes(shortname, current_skintone)) {
  12547. return true;
  12548. }
  12549. } else {
  12550. if (current_skintone && _.includes(toned_emojis, shortname)) {
  12551. return true;
  12552. }
  12553. }
  12554. return false;
  12555. },
  12556. chooseSkinTone: function chooseSkinTone(ev) {
  12557. ev.preventDefault();
  12558. ev.stopPropagation();
  12559. var target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
  12560. var skintone = target.getAttribute("data-skintone").trim();
  12561. if (this.model.get('current_skintone') === skintone) {
  12562. this.model.save({
  12563. 'current_skintone': ''
  12564. });
  12565. } else {
  12566. this.model.save({
  12567. 'current_skintone': skintone
  12568. });
  12569. }
  12570. },
  12571. chooseCategory: function chooseCategory(ev) {
  12572. ev.preventDefault();
  12573. ev.stopPropagation();
  12574. var target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
  12575. var category = target.getAttribute("data-category").trim();
  12576. this.model.save({
  12577. 'current_category': category,
  12578. 'scroll_position': 0
  12579. });
  12580. }
  12581. });
  12582. _converse.ChatBoxHeading = Backbone.NativeView.extend({
  12583. initialize: function initialize() {
  12584. this.model.on('change:image', this.render, this);
  12585. this.model.on('change:status', this.onStatusMessageChanged, this);
  12586. this.model.on('change:fullname', this.render, this);
  12587. },
  12588. render: function render() {
  12589. this.el.innerHTML = tpl_chatbox_head(_.extend(this.model.toJSON(), {
  12590. '_converse': _converse,
  12591. 'avatar_width': _converse.chatview_avatar_width,
  12592. 'avatar_height': _converse.chatview_avatar_height,
  12593. 'info_close': __('Close this chat box')
  12594. }));
  12595. return this;
  12596. },
  12597. onStatusMessageChanged: function onStatusMessageChanged(item) {
  12598. this.render();
  12599. _converse.emit('contactStatusMessageChanged', {
  12600. 'contact': item.attributes,
  12601. 'message': item.get('status')
  12602. });
  12603. }
  12604. });
  12605. _converse.ChatBoxView = Backbone.NativeView.extend({
  12606. length: 200,
  12607. className: 'chatbox hidden',
  12608. is_chatroom: false,
  12609. // Leaky abstraction from MUC
  12610. events: {
  12611. 'click .close-chatbox-button': 'close',
  12612. 'click .new-msgs-indicator': 'viewUnreadMessages',
  12613. 'click .send-button': 'onFormSubmitted',
  12614. 'click .toggle-call': 'toggleCall',
  12615. 'click .toggle-clear': 'clearMessages',
  12616. 'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
  12617. 'click .toggle-smiley': 'toggleEmojiMenu',
  12618. 'click .toggle-spoiler': 'toggleSpoilerMessage',
  12619. 'click .toggle-compose-spoiler': 'toggleComposeSpoilerMessage',
  12620. 'keypress .chat-textarea': 'keyPressed'
  12621. },
  12622. initialize: function initialize() {
  12623. this.scrollDown = _.debounce(this._scrollDown, 250);
  12624. this.markScrolled = _.debounce(this._markScrolled, 100);
  12625. this.createEmojiPicker();
  12626. this.model.messages.on('add', this.onMessageAdded, this);
  12627. this.model.on('show', this.show, this);
  12628. this.model.on('destroy', this.remove, this); // TODO check for changed fullname as well
  12629. this.model.on('change:chat_state', this.sendChatState, this);
  12630. this.model.on('change:chat_status', this.onChatStatusChanged, this);
  12631. this.model.on('showHelpMessages', this.showHelpMessages, this);
  12632. this.model.on('sendMessage', this.sendMessage, this);
  12633. this.render();
  12634. this.fetchMessages();
  12635. _converse.emit('chatBoxOpened', this);
  12636. _converse.emit('chatBoxInitialized', this);
  12637. },
  12638. render: function render() {
  12639. // XXX: Is this still needed?
  12640. this.el.setAttribute('id', this.model.get('box_id'));
  12641. this.el.innerHTML = tpl_chatbox(_.extend(this.model.toJSON(), {
  12642. unread_msgs: __('You have unread messages')
  12643. }));
  12644. this.content = this.el.querySelector('.chat-content');
  12645. this.renderMessageForm();
  12646. this.insertHeading();
  12647. return this;
  12648. },
  12649. renderToolbar: function renderToolbar(toolbar, options) {
  12650. if (!_converse.show_toolbar) {
  12651. return this;
  12652. }
  12653. toolbar = toolbar || tpl_toolbar;
  12654. options = _.assign(this.model.toJSON(), this.getToolbarOptions(options || {}));
  12655. this.el.querySelector('.chat-toolbar').innerHTML = toolbar(options);
  12656. this.addSpoilerButton(options);
  12657. this.insertEmojiPicker();
  12658. return this;
  12659. },
  12660. renderMessageForm: function renderMessageForm() {
  12661. var placeholder;
  12662. if (this.model.get('composing_spoiler')) {
  12663. placeholder = __('Hidden message');
  12664. } else {
  12665. placeholder = __('Personal message');
  12666. }
  12667. var form_container = this.el.querySelector('.message-form-container');
  12668. form_container.innerHTML = tpl_chatbox_message_form(_.extend(this.model.toJSON(), {
  12669. 'hint_value': _.get(this.el.querySelector('.spoiler-hint'), 'value'),
  12670. 'label_personal_message': placeholder,
  12671. 'label_send': __('Send'),
  12672. 'label_spoiler_hint': __('Optional hint'),
  12673. 'message_value': _.get(this.el.querySelector('.chat-textarea'), 'value'),
  12674. 'show_send_button': _converse.show_send_button,
  12675. 'show_toolbar': _converse.show_toolbar,
  12676. 'unread_msgs': __('You have unread messages')
  12677. }));
  12678. this.renderToolbar();
  12679. },
  12680. addSpoilerButton: function addSpoilerButton(options) {
  12681. var _this = this;
  12682. /* Asynchronously adds a button for writing spoiler
  12683. * messages, based on whether the contact's client supports
  12684. * it.
  12685. */
  12686. if (!options.show_spoiler_button || this.model.get('type') === 'chatroom') {
  12687. return;
  12688. }
  12689. var contact_jid = this.model.get('jid');
  12690. var resources = this.model.get('resources');
  12691. if (_.isEmpty(resources)) {
  12692. return;
  12693. }
  12694. Promise.all(_.map(_.keys(resources), function (resource) {
  12695. return _converse.api.disco.supports(Strophe.NS.SPOILER, "".concat(contact_jid, "/").concat(resource));
  12696. })).then(function (results) {
  12697. var supported = _.every(f.map(f.get('supported'))(results));
  12698. if (supported) {
  12699. var html = tpl_spoiler_button(_this.model.toJSON());
  12700. if (_converse.visible_toolbar_buttons.emoji) {
  12701. _this.el.querySelector('.toggle-smiley').insertAdjacentHTML('afterEnd', html);
  12702. } else {
  12703. _this.el.querySelector('.chat-toolbar').insertAdjacentHTML('afterBegin', html);
  12704. }
  12705. }
  12706. });
  12707. },
  12708. insertHeading: function insertHeading() {
  12709. this.heading = new _converse.ChatBoxHeading({
  12710. 'model': this.model
  12711. });
  12712. this.heading.render();
  12713. this.heading.chatview = this;
  12714. var flyout = this.el.querySelector('.flyout');
  12715. flyout.insertBefore(this.heading.el, flyout.querySelector('.chat-body'));
  12716. return this;
  12717. },
  12718. getToolbarOptions: function getToolbarOptions(options) {
  12719. var label_toggle_spoiler;
  12720. if (this.model.get('composing_spoiler')) {
  12721. label_toggle_spoiler = __('Click to write as a normal (non-spoiler) message');
  12722. } else {
  12723. label_toggle_spoiler = __('Click to write your message as a spoiler');
  12724. }
  12725. return _.extend(options || {}, {
  12726. 'label_clear': __('Clear all messages'),
  12727. 'label_insert_smiley': __('Insert a smiley'),
  12728. 'label_start_call': __('Start a call'),
  12729. 'label_toggle_spoiler': label_toggle_spoiler,
  12730. 'show_call_button': _converse.visible_toolbar_buttons.call,
  12731. 'show_spoiler_button': _converse.visible_toolbar_buttons.spoiler,
  12732. 'use_emoji': _converse.visible_toolbar_buttons.emoji
  12733. });
  12734. },
  12735. afterMessagesFetched: function afterMessagesFetched() {
  12736. this.insertIntoDOM();
  12737. this.scrollDown();
  12738. this.content.addEventListener('scroll', this.markScrolled.bind(this));
  12739. _converse.emit('afterMessagesFetched', this);
  12740. },
  12741. fetchMessages: function fetchMessages() {
  12742. this.model.messages.fetch({
  12743. 'add': true,
  12744. 'success': this.afterMessagesFetched.bind(this),
  12745. 'error': this.afterMessagesFetched.bind(this)
  12746. });
  12747. return this;
  12748. },
  12749. insertIntoDOM: function insertIntoDOM() {
  12750. /* This method gets overridden in src/converse-controlbox.js
  12751. * as well as src/converse-muc.js (if those plugins are
  12752. * enabled).
  12753. */
  12754. _converse.chatboxviews.insertRowColumn(this.el);
  12755. return this;
  12756. },
  12757. clearStatusNotification: function clearStatusNotification() {
  12758. u.removeElement(this.content.querySelector('.chat-event'));
  12759. },
  12760. showStatusNotification: function showStatusNotification(message, keep_old, permanent) {
  12761. if (!keep_old) {
  12762. this.clearStatusNotification();
  12763. }
  12764. this.content.insertAdjacentHTML('beforeend', tpl_info({
  12765. 'extra_classes': !permanent ? 'chat-event' : '',
  12766. 'message': message,
  12767. 'isodate': moment().format(),
  12768. 'data': ''
  12769. }));
  12770. this.scrollDown();
  12771. },
  12772. addSpinner: function addSpinner() {
  12773. var append = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  12774. if (_.isNull(this.el.querySelector('.spinner'))) {
  12775. if (append) {
  12776. this.content.insertAdjacentHTML('beforeend', tpl_spinner());
  12777. this.scrollDown();
  12778. } else {
  12779. this.content.insertAdjacentHTML('afterbegin', tpl_spinner());
  12780. }
  12781. }
  12782. },
  12783. clearSpinner: function clearSpinner() {
  12784. _.each(this.content.querySelectorAll('span.spinner'), function (el) {
  12785. return el.parentNode.removeChild(el);
  12786. });
  12787. },
  12788. insertDayIndicator: function insertDayIndicator(next_msg_el) {
  12789. /* Inserts an indicator into the chat area, showing the
  12790. * day as given by the passed in date.
  12791. *
  12792. * The indicator is only inserted if necessary.
  12793. *
  12794. * Parameters:
  12795. * (HTMLElement) next_msg_el - The message element before
  12796. * which the day indicator element must be inserted.
  12797. * This element must have a "data-isodate" attribute
  12798. * which specifies its creation date.
  12799. */
  12800. var prev_msg_el = u.getPreviousElement(next_msg_el, ".message:not(.chat-event)"),
  12801. prev_msg_date = _.isNull(prev_msg_el) ? null : prev_msg_el.getAttribute('data-isodate'),
  12802. next_msg_date = next_msg_el.getAttribute('data-isodate');
  12803. if (_.isNull(prev_msg_date) || moment(next_msg_date).isAfter(prev_msg_date, 'day')) {
  12804. var day_date = moment(next_msg_date).startOf('day');
  12805. next_msg_el.insertAdjacentHTML('beforeBegin', tpl_new_day({
  12806. 'isodate': day_date.format(),
  12807. 'datestring': day_date.format("dddd MMM Do YYYY")
  12808. }));
  12809. }
  12810. },
  12811. getLastMessageDate: function getLastMessageDate(cutoff) {
  12812. /* Return the ISO8601 format date of the latest message.
  12813. *
  12814. * Parameters:
  12815. * (Object) cutoff: Moment Date cutoff date. The last
  12816. * message received cutoff this date will be returned.
  12817. */
  12818. var first_msg = u.getFirstChildElement(this.content, '.message:not(.chat-event)'),
  12819. oldest_date = first_msg ? first_msg.getAttribute('data-isodate') : null;
  12820. if (!_.isNull(oldest_date) && moment(oldest_date).isAfter(cutoff)) {
  12821. return null;
  12822. }
  12823. var last_msg = u.getLastChildElement(this.content, '.message:not(.chat-event)'),
  12824. most_recent_date = last_msg ? last_msg.getAttribute('data-isodate') : null;
  12825. if (_.isNull(most_recent_date) || moment(most_recent_date).isBefore(cutoff)) {
  12826. return most_recent_date;
  12827. }
  12828. /* XXX: We avoid .chat-event messages, since they are
  12829. * temporary and get removed once a new element is
  12830. * inserted into the chat area, so we don't query for
  12831. * them here, otherwise we get a null reference later
  12832. * upon element insertion.
  12833. */
  12834. var msg_dates = _.invokeMap(sizzle('.message:not(.chat-event)', this.content), Element.prototype.getAttribute, 'data-isodate');
  12835. if (_.isObject(cutoff)) {
  12836. cutoff = cutoff.format();
  12837. }
  12838. msg_dates.push(cutoff);
  12839. msg_dates.sort();
  12840. var idx = msg_dates.lastIndexOf(cutoff);
  12841. if (idx === 0) {
  12842. return null;
  12843. } else {
  12844. return msg_dates[idx - 1];
  12845. }
  12846. },
  12847. showMessage: function showMessage(attrs) {
  12848. /* Inserts a chat message into the content area of the chat box.
  12849. * Will also insert a new day indicator if the message is on a
  12850. * different day.
  12851. *
  12852. * The message to show may either be newer than the newest
  12853. * message, or older than the oldest message.
  12854. *
  12855. * Parameters:
  12856. * (Object) attrs: An object containing the message
  12857. * attributes.
  12858. */
  12859. var current_msg_date = moment(attrs.time) || moment,
  12860. previous_msg_date = this.getLastMessageDate(current_msg_date),
  12861. message_el = this.renderMessage(attrs);
  12862. if (_.isNull(previous_msg_date)) {
  12863. this.content.insertAdjacentElement('afterbegin', message_el);
  12864. } else {
  12865. var previous_msg_el = sizzle("[data-isodate=\"".concat(previous_msg_date, "\"]:last"), this.content).pop();
  12866. previous_msg_el.insertAdjacentElement('afterend', message_el);
  12867. }
  12868. this.insertDayIndicator(message_el);
  12869. this.clearStatusNotification();
  12870. this.setScrollPosition(message_el);
  12871. },
  12872. setScrollPosition: function setScrollPosition(message_el) {
  12873. /* Given a newly inserted message, determine whether we
  12874. * should keep the scrollbar in place (so as to not scroll
  12875. * up when using infinite scroll).
  12876. */
  12877. if (this.model.get('scrolled')) {
  12878. var next_msg_el = u.getNextElement(message_el, ".chat-message");
  12879. if (next_msg_el) {
  12880. // The currently received message is not new, there
  12881. // are newer messages after it. So let's see if we
  12882. // should maintain our current scroll position.
  12883. if (this.content.scrollTop === 0 || this.model.get('top_visible_message')) {
  12884. var top_visible_message = this.model.get('top_visible_message') || next_msg_el;
  12885. this.model.set('top_visible_message', top_visible_message);
  12886. this.content.scrollTop = top_visible_message.offsetTop - 30;
  12887. }
  12888. }
  12889. } else {
  12890. this.scrollDown();
  12891. }
  12892. },
  12893. getExtraMessageTemplateAttributes: function getExtraMessageTemplateAttributes(attrs) {
  12894. /* Provides a hook for sending more attributes to the
  12895. * message template.
  12896. *
  12897. * Parameters:
  12898. * (Object) attrs: An object containing message attributes.
  12899. */
  12900. if (attrs.is_spoiler) {
  12901. return {
  12902. 'label_show': __('Show hidden message')
  12903. };
  12904. } else {
  12905. return {};
  12906. }
  12907. },
  12908. getExtraMessageClasses: function getExtraMessageClasses(attrs) {
  12909. if (_converse.show_message_load_animation) {
  12910. return 'onload ' + (attrs.delayed && 'delayed' || '');
  12911. } else {
  12912. return attrs.delayed && 'delayed' || '';
  12913. }
  12914. },
  12915. renderSpoilerMessage: function renderSpoilerMessage(msg, attrs) {
  12916. /* Render a "spoiler" message, as defined in XEP-0382
  12917. *
  12918. * Parameters:
  12919. * (HTMLElement) msg: The chat message DOM element
  12920. * (Object) attrs: An object containing the message attributes.
  12921. */
  12922. var hint = msg.querySelector('.spoiler-hint');
  12923. hint.appendChild(document.createTextNode(attrs.spoiler_hint || ''));
  12924. },
  12925. renderMessage: function renderMessage(attrs) {
  12926. /* Renders a chat message based on the passed in attributes.
  12927. *
  12928. * Parameters:
  12929. * (Object) attrs: An object containing the message attributes.
  12930. *
  12931. * Returns:
  12932. * The DOM element representing the message.
  12933. */
  12934. var text = attrs.message,
  12935. fullname = this.model.get('fullname') || attrs.fullname,
  12936. template,
  12937. username;
  12938. var match = text.match(/^\/(.*?)(?: (.*))?$/);
  12939. if (match && match[1] === 'me') {
  12940. text = text.replace(/^\/me/, '');
  12941. template = tpl_action;
  12942. if (attrs.sender === 'me') {
  12943. fullname = _converse.xmppstatus.get('fullname') || attrs.fullname;
  12944. username = _.isNil(fullname) ? _converse.bare_jid : fullname;
  12945. } else {
  12946. username = attrs.fullname;
  12947. }
  12948. } else {
  12949. username = attrs.sender === 'me' && __('me') || fullname;
  12950. template = attrs.is_spoiler ? tpl_spoiler_message : tpl_message;
  12951. }
  12952. var msg_time = moment(attrs.time) || moment;
  12953. var msg = u.stringToElement(template(_.extend(this.getExtraMessageTemplateAttributes(attrs), {
  12954. 'msgid': attrs.msgid,
  12955. 'sender': attrs.sender,
  12956. 'time': msg_time.format(_converse.time_format),
  12957. 'isodate': msg_time.format(),
  12958. 'username': username,
  12959. 'extra_classes': this.getExtraMessageClasses(attrs)
  12960. })));
  12961. if (_converse.show_message_load_animation) {
  12962. window.setTimeout(_.partial(u.removeClass, 'onload', msg), 2000);
  12963. }
  12964. var msg_content = msg.querySelector('.chat-msg-content');
  12965. msg_content.innerHTML = u.addEmoji(_converse, emojione, u.addHyperlinks(xss.filterXSS(text, {
  12966. 'whiteList': {}
  12967. })));
  12968. if (attrs.is_spoiler) {
  12969. this.renderSpoilerMessage(msg, attrs);
  12970. }
  12971. u.renderImageURLs(msg_content).then(this.scrollDown.bind(this));
  12972. return msg;
  12973. },
  12974. showHelpMessages: function showHelpMessages(msgs, type, spinner) {
  12975. var _this2 = this;
  12976. _.each(msgs, function (msg) {
  12977. _this2.content.insertAdjacentHTML('beforeend', tpl_help_message({
  12978. 'isodate': moment().format(),
  12979. 'type': type || 'info',
  12980. 'message': xss.filterXSS(msg, {
  12981. 'whiteList': {
  12982. 'strong': []
  12983. }
  12984. })
  12985. }));
  12986. });
  12987. if (spinner === true) {
  12988. this.addSpinner();
  12989. } else if (spinner === false) {
  12990. this.clearSpinner();
  12991. }
  12992. return this.scrollDown();
  12993. },
  12994. handleChatStateMessage: function handleChatStateMessage(message) {
  12995. if (message.get('chat_state') === _converse.COMPOSING) {
  12996. if (message.get('sender') === 'me') {
  12997. this.showStatusNotification(__('Typing from another device'));
  12998. } else {
  12999. this.showStatusNotification(message.get('fullname') + ' ' + __('is typing'));
  13000. }
  13001. this.clear_status_timeout = window.setTimeout(this.clearStatusNotification.bind(this), 30000);
  13002. } else if (message.get('chat_state') === _converse.PAUSED) {
  13003. if (message.get('sender') === 'me') {
  13004. this.showStatusNotification(__('Stopped typing on the other device'));
  13005. } else {
  13006. this.showStatusNotification(message.get('fullname') + ' ' + __('has stopped typing'));
  13007. }
  13008. } else if (_.includes([_converse.INACTIVE, _converse.ACTIVE], message.get('chat_state'))) {
  13009. this.clearStatusNotification();
  13010. } else if (message.get('chat_state') === _converse.GONE) {
  13011. this.showStatusNotification(message.get('fullname') + ' ' + __('has gone away'));
  13012. }
  13013. return message;
  13014. },
  13015. shouldShowOnTextMessage: function shouldShowOnTextMessage() {
  13016. return !u.isVisible(this.el);
  13017. },
  13018. handleTextMessage: function handleTextMessage(message) {
  13019. this.showMessage(_.clone(message.attributes));
  13020. if (u.isNewMessage(message)) {
  13021. if (message.get('sender') === 'me') {
  13022. // We remove the "scrolled" flag so that the chat area
  13023. // gets scrolled down. We always want to scroll down
  13024. // when the user writes a message as opposed to when a
  13025. // message is received.
  13026. this.model.set('scrolled', false);
  13027. } else if (this.model.get('scrolled', true)) {
  13028. this.showNewMessagesIndicator();
  13029. }
  13030. }
  13031. if (this.shouldShowOnTextMessage()) {
  13032. this.show();
  13033. } else {
  13034. this.scrollDown();
  13035. }
  13036. },
  13037. handleErrorMessage: function handleErrorMessage(message) {
  13038. var message_el = this.content.querySelector("[data-msgid=\"".concat(message.get('msgid'), "\"]"));
  13039. if (!_.isNull(message_el)) {
  13040. message_el.insertAdjacentHTML('afterend', tpl_info({
  13041. 'extra_classes': 'chat-error',
  13042. 'message': message.get('message'),
  13043. 'isodate': moment().format(),
  13044. 'data': ''
  13045. }));
  13046. this.scrollDown();
  13047. }
  13048. },
  13049. onMessageAdded: function onMessageAdded(message) {
  13050. /* Handler that gets called when a new message object is created.
  13051. *
  13052. * Parameters:
  13053. * (Object) message - The message Backbone object that was added.
  13054. */
  13055. if (!_.isUndefined(this.clear_status_timeout)) {
  13056. window.clearTimeout(this.clear_status_timeout);
  13057. delete this.clear_status_timeout;
  13058. }
  13059. if (message.get('type') === 'error') {
  13060. this.handleErrorMessage(message);
  13061. } else {
  13062. if (message.get('chat_state')) {
  13063. this.handleChatStateMessage(message);
  13064. }
  13065. if (message.get('message')) {
  13066. this.handleTextMessage(message);
  13067. }
  13068. }
  13069. _converse.emit('messageAdded', {
  13070. 'message': message,
  13071. 'chatbox': this.model
  13072. });
  13073. },
  13074. createMessageStanza: function createMessageStanza(message) {
  13075. var stanza = $msg({
  13076. 'from': _converse.connection.jid,
  13077. 'to': this.model.get('jid'),
  13078. 'type': 'chat',
  13079. 'id': message.get('msgid')
  13080. }).c('body').t(message.get('message')).up().c(_converse.ACTIVE, {
  13081. 'xmlns': Strophe.NS.CHATSTATES
  13082. }).up();
  13083. if (message.get('is_spoiler')) {
  13084. if (message.get('spoiler_hint')) {
  13085. stanza.c('spoiler', {
  13086. 'xmlns': Strophe.NS.SPOILER
  13087. }, message.get('spoiler_hint'));
  13088. } else {
  13089. stanza.c('spoiler', {
  13090. 'xmlns': Strophe.NS.SPOILER
  13091. });
  13092. }
  13093. }
  13094. return stanza;
  13095. },
  13096. sendMessage: function sendMessage(message) {
  13097. /* Responsible for sending off a text message.
  13098. *
  13099. * Parameters:
  13100. * (Message) message - The chat message
  13101. */
  13102. // TODO: We might want to send to specfic resources.
  13103. // Especially in the OTR case.
  13104. var messageStanza = this.createMessageStanza(message);
  13105. _converse.connection.send(messageStanza);
  13106. if (_converse.forward_messages) {
  13107. // Forward the message, so that other connected resources are also aware of it.
  13108. _converse.connection.send($msg({
  13109. to: _converse.bare_jid,
  13110. type: 'chat',
  13111. id: message.get('msgid')
  13112. }).c('forwarded', {
  13113. 'xmlns': Strophe.NS.FORWARD
  13114. }).c('delay', {
  13115. 'xmns': Strophe.NS.DELAY,
  13116. 'stamp': moment().format()
  13117. }).up().cnode(messageStanza.tree()));
  13118. }
  13119. },
  13120. parseMessageForCommands: function parseMessageForCommands(text) {
  13121. var match = text.replace(/^\s*/, "").match(/^\/(.*)\s*$/);
  13122. if (match) {
  13123. if (match[1] === "clear") {
  13124. this.clearMessages();
  13125. return true;
  13126. } else if (match[1] === "help") {
  13127. var msgs = ["<strong>/clear</strong>: ".concat(__('Remove messages')), "<strong>/me</strong>: ".concat(__('Write in the third person')), "<strong>/help</strong>: ".concat(__('Show this menu'))];
  13128. this.showHelpMessages(msgs);
  13129. return true;
  13130. }
  13131. }
  13132. },
  13133. onMessageSubmitted: function onMessageSubmitted(text, spoiler_hint) {
  13134. /* This method gets called once the user has typed a message
  13135. * and then pressed enter in a chat box.
  13136. *
  13137. * Parameters:
  13138. * (String) text - The chat message text.
  13139. * (String) spoiler_hint - A hint in case the message
  13140. * text is a hidden/spoiler message. See XEP-0382
  13141. */
  13142. if (!_converse.connection.authenticated) {
  13143. return this.showHelpMessages(['Sorry, the connection has been lost, ' + 'and your message could not be sent'], 'error');
  13144. }
  13145. if (this.parseMessageForCommands(text)) {
  13146. return;
  13147. }
  13148. var attrs = this.getOutgoingMessageAttributes(text, spoiler_hint);
  13149. var message = this.model.messages.create(attrs);
  13150. this.sendMessage(message);
  13151. },
  13152. getOutgoingMessageAttributes: function getOutgoingMessageAttributes(text, spoiler_hint) {
  13153. /* Overridable method which returns the attributes to be
  13154. * passed to Backbone.Message's constructor.
  13155. */
  13156. var fullname = _converse.xmppstatus.get('fullname'),
  13157. is_spoiler = this.model.get('composing_spoiler'),
  13158. attrs = {
  13159. 'fullname': _.isEmpty(fullname) ? _converse.bare_jid : fullname,
  13160. 'sender': 'me',
  13161. 'time': moment().format(),
  13162. 'message': emojione.shortnameToUnicode(text),
  13163. 'is_spoiler': is_spoiler
  13164. };
  13165. if (is_spoiler) {
  13166. attrs.spoiler_hint = spoiler_hint;
  13167. }
  13168. return attrs;
  13169. },
  13170. sendChatState: function sendChatState() {
  13171. /* Sends a message with the status of the user in this chat session
  13172. * as taken from the 'chat_state' attribute of the chat box.
  13173. * See XEP-0085 Chat State Notifications.
  13174. */
  13175. _converse.connection.send($msg({
  13176. 'to': this.model.get('jid'),
  13177. 'type': 'chat'
  13178. }).c(this.model.get('chat_state'), {
  13179. 'xmlns': Strophe.NS.CHATSTATES
  13180. }).up().c('no-store', {
  13181. 'xmlns': Strophe.NS.HINTS
  13182. }).up().c('no-permanent-store', {
  13183. 'xmlns': Strophe.NS.HINTS
  13184. }));
  13185. },
  13186. setChatState: function setChatState(state, no_save) {
  13187. /* Mutator for setting the chat state of this chat session.
  13188. * Handles clearing of any chat state notification timeouts and
  13189. * setting new ones if necessary.
  13190. * Timeouts are set when the state being set is COMPOSING or PAUSED.
  13191. * After the timeout, COMPOSING will become PAUSED and PAUSED will become INACTIVE.
  13192. * See XEP-0085 Chat State Notifications.
  13193. *
  13194. * Parameters:
  13195. * (string) state - The chat state (consts ACTIVE, COMPOSING, PAUSED, INACTIVE, GONE)
  13196. * (Boolean) no_save - Just do the cleanup or setup but don't actually save the state.
  13197. */
  13198. if (!_.isUndefined(this.chat_state_timeout)) {
  13199. window.clearTimeout(this.chat_state_timeout);
  13200. delete this.chat_state_timeout;
  13201. }
  13202. if (state === _converse.COMPOSING) {
  13203. this.chat_state_timeout = window.setTimeout(this.setChatState.bind(this), _converse.TIMEOUTS.PAUSED, _converse.PAUSED);
  13204. } else if (state === _converse.PAUSED) {
  13205. this.chat_state_timeout = window.setTimeout(this.setChatState.bind(this), _converse.TIMEOUTS.INACTIVE, _converse.INACTIVE);
  13206. }
  13207. if (!no_save && this.model.get('chat_state') !== state) {
  13208. this.model.set('chat_state', state);
  13209. }
  13210. return this;
  13211. },
  13212. onFormSubmitted: function onFormSubmitted(ev) {
  13213. ev.preventDefault();
  13214. var textarea = this.el.querySelector('.chat-textarea'),
  13215. message = textarea.value;
  13216. var spoiler_hint;
  13217. if (this.model.get('composing_spoiler')) {
  13218. var hint_el = this.el.querySelector('form.sendXMPPMessage input.spoiler-hint');
  13219. spoiler_hint = hint_el.value;
  13220. hint_el.value = '';
  13221. }
  13222. textarea.value = '';
  13223. textarea.focus();
  13224. if (message !== '') {
  13225. this.onMessageSubmitted(message, spoiler_hint);
  13226. _converse.emit('messageSend', message);
  13227. }
  13228. this.setChatState(_converse.ACTIVE);
  13229. },
  13230. keyPressed: function keyPressed(ev) {
  13231. /* Event handler for when a key is pressed in a chat box textarea.
  13232. */
  13233. if (ev.keyCode === KEY.ENTER) {
  13234. this.onFormSubmitted(ev);
  13235. } else {
  13236. // Set chat state to composing if keyCode is not a forward-slash
  13237. // (which would imply an internal command and not a message).
  13238. this.setChatState(_converse.COMPOSING, ev.keyCode === KEY.FORWARD_SLASH);
  13239. }
  13240. },
  13241. clearMessages: function clearMessages(ev) {
  13242. if (ev && ev.preventDefault) {
  13243. ev.preventDefault();
  13244. }
  13245. var result = confirm(__("Are you sure you want to clear the messages from this chat box?"));
  13246. if (result === true) {
  13247. this.content.innerHTML = '';
  13248. this.model.messages.reset();
  13249. this.model.messages.browserStorage._clear();
  13250. }
  13251. return this;
  13252. },
  13253. insertIntoTextArea: function insertIntoTextArea(value) {
  13254. var textbox_el = this.el.querySelector('.chat-textarea');
  13255. var existing = textbox_el.value;
  13256. if (existing && existing[existing.length - 1] !== ' ') {
  13257. existing = existing + ' ';
  13258. }
  13259. textbox_el.value = existing + value + ' ';
  13260. textbox_el.focus();
  13261. },
  13262. createEmojiPicker: function createEmojiPicker() {
  13263. if (_.isUndefined(_converse.emojipicker)) {
  13264. _converse.emojipicker = new _converse.EmojiPicker();
  13265. _converse.emojipicker.fetch();
  13266. }
  13267. this.emoji_picker_view = new _converse.EmojiPickerView({
  13268. 'model': _converse.emojipicker
  13269. });
  13270. },
  13271. insertEmoji: function insertEmoji(ev) {
  13272. ev.stopPropagation();
  13273. var target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
  13274. this.insertIntoTextArea(target.getAttribute('data-emoji'));
  13275. },
  13276. toggleEmojiMenu: function toggleEmojiMenu(ev) {
  13277. if (_.isUndefined(this.emoji_dropdown)) {
  13278. ev.stopPropagation();
  13279. var dropdown_el = this.el.querySelector('.toggle-smiley.dropup');
  13280. this.emoji_dropdown = new bootstrap.Dropdown(dropdown_el, true);
  13281. this.emoji_dropdown.toggle();
  13282. }
  13283. },
  13284. toggleCall: function toggleCall(ev) {
  13285. ev.stopPropagation();
  13286. _converse.emit('callButtonClicked', {
  13287. connection: _converse.connection,
  13288. model: this.model
  13289. });
  13290. },
  13291. toggleComposeSpoilerMessage: function toggleComposeSpoilerMessage() {
  13292. this.model.set('composing_spoiler', !this.model.get('composing_spoiler'));
  13293. this.renderMessageForm();
  13294. this.focus();
  13295. },
  13296. toggleSpoilerMessage: function toggleSpoilerMessage(ev) {
  13297. if (ev && ev.preventDefault) {
  13298. ev.preventDefault();
  13299. }
  13300. var toggle_el = ev.target;
  13301. u.slideToggleElement(toggle_el.parentElement.querySelector('.spoiler'));
  13302. if (toggle_el.getAttribute("data-toggle-state") == "closed") {
  13303. toggle_el.textContent = __('Hide hidden message');
  13304. toggle_el.classList.remove("icon-eye");
  13305. toggle_el.classList.add("icon-eye-blocked");
  13306. toggle_el.setAttribute("data-toggle-state", "open");
  13307. } else {
  13308. toggle_el.textContent = __('Show hidden message');
  13309. toggle_el.classList.remove("icon-eye-blocked");
  13310. toggle_el.classList.add("icon-eye");
  13311. toggle_el.setAttribute("data-toggle-state", "closed");
  13312. }
  13313. },
  13314. onChatStatusChanged: function onChatStatusChanged(item) {
  13315. var chat_status = item.get('chat_status');
  13316. var fullname = item.get('fullname');
  13317. fullname = _.isEmpty(fullname) ? item.get('jid') : fullname;
  13318. if (u.isVisible(this.el)) {
  13319. if (chat_status === 'offline') {
  13320. this.showStatusNotification(fullname + ' ' + __('has gone offline'));
  13321. } else if (chat_status === 'away') {
  13322. this.showStatusNotification(fullname + ' ' + __('has gone away'));
  13323. } else if (chat_status === 'dnd') {
  13324. this.showStatusNotification(fullname + ' ' + __('is busy'));
  13325. } else if (chat_status === 'online') {
  13326. this.clearStatusNotification();
  13327. }
  13328. }
  13329. },
  13330. close: function close(ev) {
  13331. if (ev && ev.preventDefault) {
  13332. ev.preventDefault();
  13333. }
  13334. if (Backbone.history.getFragment() === "converse/chat?jid=" + this.model.get('jid')) {
  13335. _converse.router.navigate('');
  13336. }
  13337. if (_converse.connection.connected) {
  13338. // Immediately sending the chat state, because the
  13339. // model is going to be destroyed afterwards.
  13340. this.setChatState(_converse.INACTIVE);
  13341. this.sendChatState();
  13342. }
  13343. try {
  13344. this.model.destroy();
  13345. } catch (e) {
  13346. _converse.log(e, Strophe.LogLevel.ERROR);
  13347. }
  13348. this.remove();
  13349. _converse.emit('chatBoxClosed', this);
  13350. return this;
  13351. },
  13352. renderEmojiPicker: function renderEmojiPicker() {
  13353. this.emoji_picker_view.render();
  13354. },
  13355. insertEmojiPicker: function insertEmojiPicker() {
  13356. var picker_el = this.el.querySelector('.emoji-picker');
  13357. if (!_.isNull(picker_el)) {
  13358. picker_el.innerHTML = '';
  13359. picker_el.appendChild(this.emoji_picker_view.el);
  13360. }
  13361. },
  13362. focus: function focus() {
  13363. var textarea_el = this.el.querySelector('.chat-textarea');
  13364. if (!_.isNull(textarea_el)) {
  13365. textarea_el.focus();
  13366. _converse.emit('chatBoxFocused', this);
  13367. }
  13368. return this;
  13369. },
  13370. hide: function hide() {
  13371. this.el.classList.add('hidden');
  13372. return this;
  13373. },
  13374. afterShown: function afterShown() {
  13375. if (u.isPersistableModel(this.model)) {
  13376. this.model.clearUnreadMsgCounter();
  13377. this.model.save();
  13378. }
  13379. this.setChatState(_converse.ACTIVE);
  13380. this.renderEmojiPicker();
  13381. this.scrollDown();
  13382. this.focus();
  13383. },
  13384. _show: function _show(f) {
  13385. /* Inner show method that gets debounced */
  13386. if (u.isVisible(this.el)) {
  13387. this.focus();
  13388. return;
  13389. }
  13390. u.fadeIn(this.el, _.bind(this.afterShown, this));
  13391. },
  13392. show: function show() {
  13393. if (_.isUndefined(this.debouncedShow)) {
  13394. /* We wrap the method in a debouncer and set it on the
  13395. * instance, so that we have it debounced per instance.
  13396. * Debouncing it on the class-level is too broad.
  13397. */
  13398. this.debouncedShow = _.debounce(this._show, 250, {
  13399. 'leading': true
  13400. });
  13401. }
  13402. this.debouncedShow.apply(this, arguments);
  13403. return this;
  13404. },
  13405. showNewMessagesIndicator: function showNewMessagesIndicator() {
  13406. u.showElement(this.el.querySelector('.new-msgs-indicator'));
  13407. },
  13408. hideNewMessagesIndicator: function hideNewMessagesIndicator() {
  13409. var new_msgs_indicator = this.el.querySelector('.new-msgs-indicator');
  13410. if (!_.isNull(new_msgs_indicator)) {
  13411. new_msgs_indicator.classList.add('hidden');
  13412. }
  13413. },
  13414. _markScrolled: function _markScrolled(ev) {
  13415. /* Called when the chat content is scrolled up or down.
  13416. * We want to record when the user has scrolled away from
  13417. * the bottom, so that we don't automatically scroll away
  13418. * from what the user is reading when new messages are
  13419. * received.
  13420. */
  13421. if (ev && ev.preventDefault) {
  13422. ev.preventDefault();
  13423. }
  13424. var scrolled = true;
  13425. var is_at_bottom = this.content.scrollTop + this.content.clientHeight >= this.content.scrollHeight - 62; // sigh...
  13426. if (is_at_bottom) {
  13427. scrolled = false;
  13428. this.onScrolledDown();
  13429. }
  13430. u.safeSave(this.model, {
  13431. 'scrolled': scrolled,
  13432. 'top_visible_message': null
  13433. });
  13434. },
  13435. viewUnreadMessages: function viewUnreadMessages() {
  13436. this.model.save({
  13437. 'scrolled': false,
  13438. 'top_visible_message': null
  13439. });
  13440. this.scrollDown();
  13441. },
  13442. _scrollDown: function _scrollDown() {
  13443. /* Inner method that gets debounced */
  13444. if (_.isUndefined(this.content)) {
  13445. return;
  13446. }
  13447. if (u.isVisible(this.content) && !this.model.get('scrolled')) {
  13448. this.content.scrollTop = this.content.scrollHeight;
  13449. }
  13450. },
  13451. onScrolledDown: function onScrolledDown() {
  13452. this.hideNewMessagesIndicator();
  13453. if (_converse.windowState !== 'hidden') {
  13454. this.model.clearUnreadMsgCounter();
  13455. }
  13456. _converse.emit('chatBoxScrolledDown', {
  13457. 'chatbox': this.model
  13458. });
  13459. },
  13460. onWindowStateChanged: function onWindowStateChanged(state) {
  13461. if (this.model.get('num_unread', 0) && !this.model.newMessageWillBeHidden()) {
  13462. this.model.clearUnreadMsgCounter();
  13463. }
  13464. }
  13465. });
  13466. _converse.on('connected', function () {
  13467. // Advertise that we support XEP-0382 Message Spoilers
  13468. _converse.connection.disco.addFeature(Strophe.NS.SPOILER);
  13469. });
  13470. /************************ BEGIN API ************************/
  13471. _.extend(_converse.api, {
  13472. 'chatviews': {
  13473. 'get': function get(jids) {
  13474. if (_.isUndefined(jids)) {
  13475. _converse.log("chats.create: You need to provide at least one JID", Strophe.LogLevel.ERROR);
  13476. return null;
  13477. }
  13478. if (_.isString(jids)) {
  13479. return _converse.chatboxviews.get(jids);
  13480. }
  13481. return _.map(jids, function (jid) {
  13482. return _converse.chatboxviews.get(jids);
  13483. });
  13484. }
  13485. }
  13486. });
  13487. /************************ END API ************************/
  13488. }
  13489. });
  13490. return converse;
  13491. });
  13492. //# sourceMappingURL=converse-chatview.js.map;
  13493. define('tpl!converse_brand_heading', ['lodash'], function(_) {return function(o) {
  13494. var __t, __p = '';
  13495. __p += '<span class="brand-heading-container">\n <div class="brand-heading">\n <a href="https://conversejs.org" target="_blank" rel="noopener">\n <i class="icon-conversejs"></i><span class="brand-name">converse</span>\n </a>\n </div>\n</span>\n';
  13496. return __p
  13497. };});
  13498. define('tpl!controlbox', ['lodash'], function(_) {return function(o) {
  13499. var __t, __p = '', __j = Array.prototype.join;
  13500. function print() { __p += __j.call(arguments, '') }
  13501. __p += '<div class="flyout box-flyout">\n <div class="chat-head controlbox-head">\n ';
  13502. if (!o.sticky_controlbox) { ;
  13503. __p += '\n <a class="chatbox-btn close-chatbox-button fa fa-close"></a>\n ';
  13504. } ;
  13505. __p += '\n </div>\n <div class="controlbox-panes"></div>\n</div>\n';
  13506. return __p
  13507. };});
  13508. define('tpl!controlbox_toggle', ['lodash'], function(_) {return function(o) {
  13509. var __t, __p = '', __e = _.escape;
  13510. __p += '<span class="toggle-feedback">' +
  13511. __e(o.label_toggle) +
  13512. '</span>\n';
  13513. return __p
  13514. };});
  13515. define('tpl!login_panel', ['lodash'], function(_) {return function(o) {
  13516. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13517. function print() { __p += __j.call(arguments, '') }
  13518. __p += '<div id="converse-login-panel" class="controlbox-pane fade-in row">\n <form id="converse-login" class="converse-form" method="post">\n <div class="conn-feedback fade-in ';
  13519. if (!o.conn_feedback_subject) { ;
  13520. __p += ' hidden ';
  13521. } ;
  13522. __p += ' ' +
  13523. __e(o.conn_feedback_class) +
  13524. '">\n <p class="feedback-subject">' +
  13525. __e( o.conn_feedback_subject ) +
  13526. '</p>\n <p class="feedback-message ';
  13527. if (!o.conn_feedback_message) { ;
  13528. __p += ' hidden ';
  13529. } ;
  13530. __p += '">' +
  13531. __e(o.conn_feedback_message) +
  13532. '</p>\n </div>\n ';
  13533. if (o.auto_login || o._converse.CONNECTION_STATUS[o.connection_status] === 'CONNECTING') { ;
  13534. __p += '\n <span class="spinner fa fa-spinner centered"/>\n ';
  13535. } else { ;
  13536. __p += '\n ';
  13537. if (o.authentication == o.LOGIN || o.authentication == o.EXTERNAL) { ;
  13538. __p += '\n <div class="form-group">\n <label for="jid">' +
  13539. __e(o.__("XMPP Username:")) +
  13540. '</label>\n <input class="form-control" autofocus required="required" type="text" name="jid" placeholder="' +
  13541. __e(o.placeholder_username) +
  13542. '">\n </div>\n ';
  13543. if (o.authentication !== o.EXTERNAL) { ;
  13544. __p += '\n <div class="form-group">\n <label for="password">' +
  13545. __e(o.__("Password:")) +
  13546. '</label>\n <input class="form-control" required="required" type="password" name="password" placeholder="' +
  13547. __e(o.__('password')) +
  13548. '">\n </div>\n ';
  13549. } ;
  13550. __p += '\n <fieldset class="buttons">\n <input class="btn btn-primary" type="submit" value="' +
  13551. __e(o.__('Submit')) +
  13552. '">\n </fieldset>\n ';
  13553. } ;
  13554. __p += '\n ';
  13555. if (o.authentication == o.ANONYMOUS) { ;
  13556. __p += '\n <input class="btn btn-primary login-anon" type="submit" value="' +
  13557. __e(o.__('Click here to log in anonymously')) +
  13558. '"/>\n ';
  13559. } ;
  13560. __p += '\n ';
  13561. if (o.authentication == o.PREBIND) { ;
  13562. __p += '\n <p>Disconnected.</p>\n ';
  13563. } ;
  13564. __p += '\n ';
  13565. } ;
  13566. __p += '\n </form>\n</div>\n';
  13567. return __p
  13568. };});
  13569. define('tpl!add_contact_modal', ['lodash'], function(_) {return function(o) {
  13570. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13571. function print() { __p += __j.call(arguments, '') }
  13572. __p += '<!-- Add contact Modal -->\n<div class="modal fade" id="add-contact-modal" tabindex="-1" role="dialog" aria-labelledby="addContactModalLabel" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title" id="addContactModalLabel">' +
  13573. __e(o.heading_new_contact) +
  13574. '</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>\n </div>\n <form class="converse-form add-xmpp-contact">\n <div class="modal-body">\n <div class="form-group">\n <label for="jid">' +
  13575. __e(o.label_xmpp_address) +
  13576. ':</label>\n <input type="text" name="jid" required="required" value="' +
  13577. __e(o.jid) +
  13578. '"\n class="form-control ';
  13579. if (o.error_message) { ;
  13580. __p += ' is-invalid ';
  13581. } ;
  13582. __p += '"\n placeholder="' +
  13583. __e(o.contact_placeholder) +
  13584. '">\n ';
  13585. if (o.error_message) { ;
  13586. __p += '\n <div class="invalid-feedback">' +
  13587. __e(o.error_message) +
  13588. '</div>\n ';
  13589. } ;
  13590. __p += '\n </div>\n </div>\n <div class="modal-footer">\n <button type="submit" class="btn btn-primary">' +
  13591. __e(o.label_add) +
  13592. '</button>\n </div>\n </form>\n </div>\n </div>\n</div>\n';
  13593. return __p
  13594. };});
  13595. define('tpl!group_header', ['lodash'], function(_) {return function(o) {
  13596. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13597. function print() { __p += __j.call(arguments, '') }
  13598. __p += '<a href="#" class="group-toggle" title="' +
  13599. __e(o.desc_group_toggle) +
  13600. '">\n <span class="fa ';
  13601. if (o.toggle_state === o._converse.OPENED) { ;
  13602. __p += ' fa-caret-down ';
  13603. } else { ;
  13604. __p += ' fa-caret-right ';
  13605. } ;
  13606. __p += '">\n </span> ' +
  13607. __e(o.label_group) +
  13608. '</a>\n<ul class="roster-group-contacts ';
  13609. if (o.toggle_state === o._converse.CLOSED) { ;
  13610. __p += ' collapsed ';
  13611. } ;
  13612. __p += '"></ul>\n';
  13613. return __p
  13614. };});
  13615. define('tpl!pending_contact', ['lodash'], function(_) {return function(o) {
  13616. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13617. function print() { __p += __j.call(arguments, '') }
  13618. if (o.allow_chat_pending_contacts) { ;
  13619. __p += '\n<a class="open-chat w-100" href="#">\n';
  13620. } ;
  13621. __p += '\n<span class="pending-contact-name w-100" title="Name: ' +
  13622. __e(o.fullname) +
  13623. ' JID: ' +
  13624. __e(o.jid) +
  13625. '">' +
  13626. __e(o.fullname) +
  13627. '</span> \n';
  13628. if (o.allow_chat_pending_contacts) { ;
  13629. __p += '</a>\n';
  13630. } ;
  13631. __p += '\n<a class="remove-xmpp-contact fa fa-trash" title="' +
  13632. __e(o.desc_remove) +
  13633. '" href="#"></a>\n';
  13634. return __p
  13635. };});
  13636. define('tpl!requesting_contact', ['lodash'], function(_) {return function(o) {
  13637. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13638. function print() { __p += __j.call(arguments, '') }
  13639. if (o.allow_chat_pending_contacts) { ;
  13640. __p += '\n<a class="open-chat w-100"href="#">\n';
  13641. } ;
  13642. __p += '\n<span class="req-contact-name w-100" title="Name: ' +
  13643. __e(o.fullname) +
  13644. '\nJID: ' +
  13645. __e(o.jid) +
  13646. '">' +
  13647. __e(o.fullname) +
  13648. '</span>\n';
  13649. if (o.allow_chat_pending_contacts) { ;
  13650. __p += '\n</a>\n';
  13651. } ;
  13652. __p += '\n<a class="accept-xmpp-request fa fa-check"\n aria-label="' +
  13653. __e(o.desc_accept) +
  13654. '" title="' +
  13655. __e(o.desc_accept) +
  13656. '" href="#"></a>\n<a class="decline-xmpp-request fa fa-times"\n aria-label="' +
  13657. __e(o.desc_decline) +
  13658. '" title="' +
  13659. __e(o.desc_decline) +
  13660. '" href="#"></a>\n';
  13661. return __p
  13662. };});
  13663. define('tpl!roster', ['lodash'], function(_) {return function(o) {
  13664. var __t, __p = '', __e = _.escape;
  13665. __p += '<div class="d-flex">\n <span class="w-100">' +
  13666. __e(o.heading_contacts) +
  13667. '</span>\n <a class="chatbox-btn add-contact fa fa-user-plus" title="' +
  13668. __e(o.title_add_contact) +
  13669. '"\n data-toggle="modal" data-target="#add-contact-modal"></a>\n</div>\n\n<form class="roster-filter-form"></form>\n\n<div class="roster-contacts"></div>\n';
  13670. return __p
  13671. };});
  13672. define('tpl!roster_filter', ['lodash'], function(_) {return function(o) {
  13673. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13674. function print() { __p += __j.call(arguments, '') }
  13675. __p += '<form class="roster-filter-form input-button-group ';
  13676. if (!o.visible) { ;
  13677. __p += ' hidden ';
  13678. } ;
  13679. __p += '">\n <div class="form-inline flex-nowrap">\n <div class="btn-group">\n <input ';
  13680. if (o.filter_text) { ;
  13681. __p += ' value="' +
  13682. __e(o.filter_text) +
  13683. '" ';
  13684. } ;
  13685. __p += '\n class="roster-filter form-control ';
  13686. if (o.filter_type === 'state') { ;
  13687. __p += ' hidden ';
  13688. } ;
  13689. __p += '"\n placeholder="' +
  13690. __e(o.placeholder) +
  13691. '">\n <span class="clear-input fa fa-times ';
  13692. if (!o.filter_text) { ;
  13693. __p += ' hidden ';
  13694. } ;
  13695. __p += '"></span>\n </div>\n\n <select class="form-control state-type ';
  13696. if (o.filter_type !== 'state') { ;
  13697. __p += ' hidden ';
  13698. } ;
  13699. __p += '">\n <option value="">' +
  13700. __e(o.label_any) +
  13701. '</option>\n <option ';
  13702. if (o.chat_state === 'unread_messages') { ;
  13703. __p += ' selected="selected" ';
  13704. } ;
  13705. __p += '\n value="unread_messages">' +
  13706. __e(o.label_unread_messages) +
  13707. '</option>\n <option ';
  13708. if (o.chat_state === 'online') { ;
  13709. __p += ' selected="selected" ';
  13710. } ;
  13711. __p += '\n value="online">' +
  13712. __e(o.label_online) +
  13713. '</option>\n <option ';
  13714. if (o.chat_state === 'chat') { ;
  13715. __p += ' selected="selected" ';
  13716. } ;
  13717. __p += '\n value="chat">' +
  13718. __e(o.label_chatty) +
  13719. '</option>\n <option ';
  13720. if (o.chat_state === 'dnd') { ;
  13721. __p += ' selected="selected" ';
  13722. } ;
  13723. __p += '\n value="dnd">' +
  13724. __e(o.label_busy) +
  13725. '</option>\n <option ';
  13726. if (o.chat_state === 'away') { ;
  13727. __p += ' selected="selected" ';
  13728. } ;
  13729. __p += '\n value="away">' +
  13730. __e(o.label_away) +
  13731. '</option>\n <option ';
  13732. if (o.chat_state === 'xa') { ;
  13733. __p += ' selected="selected" ';
  13734. } ;
  13735. __p += '\n value="xa">' +
  13736. __e(o.label_xa) +
  13737. '</option>\n <option ';
  13738. if (o.chat_state === 'offline') { ;
  13739. __p += ' selected="selected" ';
  13740. } ;
  13741. __p += '\n value="offline">' +
  13742. __e(o.label_offline) +
  13743. '</option>\n </select>\n\n <div class="filter-by d-flex flex-nowrap">\n <span class="fa fa-user ';
  13744. if (o.filter_type === 'contacts') { ;
  13745. __p += ' selected ';
  13746. } ;
  13747. __p += '" data-type="contacts" title="' +
  13748. __e(o.title_contact_filter) +
  13749. '"></span>\n <span class="fa fa-users ';
  13750. if (o.filter_type === 'groups') { ;
  13751. __p += ' selected ';
  13752. } ;
  13753. __p += '" data-type="groups" title="' +
  13754. __e(o.title_group_filter) +
  13755. '"></span>\n <span class="fa fa-circle ';
  13756. if (o.filter_type === 'state') { ;
  13757. __p += ' selected ';
  13758. } ;
  13759. __p += '" data-type="state" title="' +
  13760. __e(o.title_status_filter) +
  13761. '"></span>\n </div>\n </div>\n</form>\n';
  13762. return __p
  13763. };});
  13764. define('tpl!roster_item', ['lodash'], function(_) {return function(o) {
  13765. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13766. function print() { __p += __j.call(arguments, '') }
  13767. __p += '<a class="open-chat w-100 ';
  13768. if (o.num_unread) { ;
  13769. __p += ' unread-msgs ';
  13770. } ;
  13771. __p += '"\n title="' +
  13772. __e(o.desc_chat) +
  13773. '" href="#">\n <span class="fa ' +
  13774. __e(o.status_icon) +
  13775. '" title="' +
  13776. __e(o.desc_status) +
  13777. '"></span>\n ';
  13778. if (o.num_unread) { ;
  13779. __p += '\n <span class="msgs-indicator">' +
  13780. __e( o.num_unread ) +
  13781. '</span>\n ';
  13782. } ;
  13783. __p += '\n <span class="contact-name ';
  13784. if (o.num_unread) { ;
  13785. __p += ' unread-msgs ';
  13786. } ;
  13787. __p += '">' +
  13788. __e(o.fullname) +
  13789. '</span></a>\n';
  13790. if (o.allow_contact_removal) { ;
  13791. __p += '\n<a class="remove-xmpp-contact fa fa-trash" title="' +
  13792. __e(o.desc_remove) +
  13793. '" href="#"></a>\n';
  13794. } ;
  13795. __p += '\n';
  13796. return __p
  13797. };});
  13798. define('tpl!search_contact', ['lodash'], function(_) {return function(o) {
  13799. var __t, __p = '', __e = _.escape;
  13800. __p += '<li>\n <form class="search-xmpp-contact">\n <input type="text"\n name="identifier"\n class="username"\n placeholder="' +
  13801. __e(o.label_contact_name) +
  13802. '"/>\n <button type="submit">' +
  13803. __e(o.label_search) +
  13804. '</button>\n </form>\n</li>\n';
  13805. return __p
  13806. };});
  13807. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('snabbdom',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  13808. "use strict";
  13809. Object.defineProperty(exports, "__esModule", { value: true });
  13810. var vnode_1 = require("./vnode");
  13811. var is = require("./is");
  13812. function addNS(data, children, sel) {
  13813. data.ns = 'http://www.w3.org/2000/svg';
  13814. if (sel !== 'foreignObject' && children !== undefined) {
  13815. for (var i = 0; i < children.length; ++i) {
  13816. var childData = children[i].data;
  13817. if (childData !== undefined) {
  13818. addNS(childData, children[i].children, children[i].sel);
  13819. }
  13820. }
  13821. }
  13822. }
  13823. function h(sel, b, c) {
  13824. var data = {}, children, text, i;
  13825. if (c !== undefined) {
  13826. data = b;
  13827. if (is.array(c)) {
  13828. children = c;
  13829. }
  13830. else if (is.primitive(c)) {
  13831. text = c;
  13832. }
  13833. else if (c && c.sel) {
  13834. children = [c];
  13835. }
  13836. }
  13837. else if (b !== undefined) {
  13838. if (is.array(b)) {
  13839. children = b;
  13840. }
  13841. else if (is.primitive(b)) {
  13842. text = b;
  13843. }
  13844. else if (b && b.sel) {
  13845. children = [b];
  13846. }
  13847. else {
  13848. data = b;
  13849. }
  13850. }
  13851. if (is.array(children)) {
  13852. for (i = 0; i < children.length; ++i) {
  13853. if (is.primitive(children[i]))
  13854. children[i] = vnode_1.vnode(undefined, undefined, undefined, children[i]);
  13855. }
  13856. }
  13857. if (sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g' &&
  13858. (sel.length === 3 || sel[3] === '.' || sel[3] === '#')) {
  13859. addNS(data, children, sel);
  13860. }
  13861. return vnode_1.vnode(sel, data, children, text, undefined);
  13862. }
  13863. exports.h = h;
  13864. ;
  13865. exports.default = h;
  13866. },{"./is":3,"./vnode":6}],2:[function(require,module,exports){
  13867. "use strict";
  13868. Object.defineProperty(exports, "__esModule", { value: true });
  13869. function createElement(tagName) {
  13870. return document.createElement(tagName);
  13871. }
  13872. function createElementNS(namespaceURI, qualifiedName) {
  13873. return document.createElementNS(namespaceURI, qualifiedName);
  13874. }
  13875. function createTextNode(text) {
  13876. return document.createTextNode(text);
  13877. }
  13878. function createComment(text) {
  13879. return document.createComment(text);
  13880. }
  13881. function insertBefore(parentNode, newNode, referenceNode) {
  13882. parentNode.insertBefore(newNode, referenceNode);
  13883. }
  13884. function removeChild(node, child) {
  13885. node.removeChild(child);
  13886. }
  13887. function appendChild(node, child) {
  13888. node.appendChild(child);
  13889. }
  13890. function parentNode(node) {
  13891. return node.parentNode;
  13892. }
  13893. function nextSibling(node) {
  13894. return node.nextSibling;
  13895. }
  13896. function tagName(elm) {
  13897. return elm.tagName;
  13898. }
  13899. function setTextContent(node, text) {
  13900. node.textContent = text;
  13901. }
  13902. function getTextContent(node) {
  13903. return node.textContent;
  13904. }
  13905. function isElement(node) {
  13906. return node.nodeType === 1;
  13907. }
  13908. function isText(node) {
  13909. return node.nodeType === 3;
  13910. }
  13911. function isComment(node) {
  13912. return node.nodeType === 8;
  13913. }
  13914. exports.htmlDomApi = {
  13915. createElement: createElement,
  13916. createElementNS: createElementNS,
  13917. createTextNode: createTextNode,
  13918. createComment: createComment,
  13919. insertBefore: insertBefore,
  13920. removeChild: removeChild,
  13921. appendChild: appendChild,
  13922. parentNode: parentNode,
  13923. nextSibling: nextSibling,
  13924. tagName: tagName,
  13925. setTextContent: setTextContent,
  13926. getTextContent: getTextContent,
  13927. isElement: isElement,
  13928. isText: isText,
  13929. isComment: isComment,
  13930. };
  13931. exports.default = exports.htmlDomApi;
  13932. },{}],3:[function(require,module,exports){
  13933. "use strict";
  13934. Object.defineProperty(exports, "__esModule", { value: true });
  13935. exports.array = Array.isArray;
  13936. function primitive(s) {
  13937. return typeof s === 'string' || typeof s === 'number';
  13938. }
  13939. exports.primitive = primitive;
  13940. },{}],4:[function(require,module,exports){
  13941. "use strict";
  13942. Object.defineProperty(exports, "__esModule", { value: true });
  13943. var vnode_1 = require("./vnode");
  13944. var is = require("./is");
  13945. var htmldomapi_1 = require("./htmldomapi");
  13946. function isUndef(s) { return s === undefined; }
  13947. function isDef(s) { return s !== undefined; }
  13948. var emptyNode = vnode_1.default('', {}, [], undefined, undefined);
  13949. function sameVnode(vnode1, vnode2) {
  13950. return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
  13951. }
  13952. function isVnode(vnode) {
  13953. return vnode.sel !== undefined;
  13954. }
  13955. function createKeyToOldIdx(children, beginIdx, endIdx) {
  13956. var i, map = {}, key, ch;
  13957. for (i = beginIdx; i <= endIdx; ++i) {
  13958. ch = children[i];
  13959. if (ch != null) {
  13960. key = ch.key;
  13961. if (key !== undefined)
  13962. map[key] = i;
  13963. }
  13964. }
  13965. return map;
  13966. }
  13967. var hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post'];
  13968. var h_1 = require("./h");
  13969. exports.h = h_1.h;
  13970. var thunk_1 = require("./thunk");
  13971. exports.thunk = thunk_1.thunk;
  13972. function init(modules, domApi) {
  13973. var i, j, cbs = {};
  13974. var api = domApi !== undefined ? domApi : htmldomapi_1.default;
  13975. for (i = 0; i < hooks.length; ++i) {
  13976. cbs[hooks[i]] = [];
  13977. for (j = 0; j < modules.length; ++j) {
  13978. var hook = modules[j][hooks[i]];
  13979. if (hook !== undefined) {
  13980. cbs[hooks[i]].push(hook);
  13981. }
  13982. }
  13983. }
  13984. function emptyNodeAt(elm) {
  13985. var id = elm.id ? '#' + elm.id : '';
  13986. var c = elm.className ? '.' + elm.className.split(' ').join('.') : '';
  13987. return vnode_1.default(api.tagName(elm).toLowerCase() + id + c, {}, [], undefined, elm);
  13988. }
  13989. function createRmCb(childElm, listeners) {
  13990. return function rmCb() {
  13991. if (--listeners === 0) {
  13992. var parent_1 = api.parentNode(childElm);
  13993. api.removeChild(parent_1, childElm);
  13994. }
  13995. };
  13996. }
  13997. function createElm(vnode, insertedVnodeQueue) {
  13998. var i, data = vnode.data;
  13999. if (data !== undefined) {
  14000. if (isDef(i = data.hook) && isDef(i = i.init)) {
  14001. i(vnode);
  14002. data = vnode.data;
  14003. }
  14004. }
  14005. var children = vnode.children, sel = vnode.sel;
  14006. if (sel === '!') {
  14007. if (isUndef(vnode.text)) {
  14008. vnode.text = '';
  14009. }
  14010. vnode.elm = api.createComment(vnode.text);
  14011. }
  14012. else if (sel !== undefined) {
  14013. // Parse selector
  14014. var hashIdx = sel.indexOf('#');
  14015. var dotIdx = sel.indexOf('.', hashIdx);
  14016. var hash = hashIdx > 0 ? hashIdx : sel.length;
  14017. var dot = dotIdx > 0 ? dotIdx : sel.length;
  14018. var tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel;
  14019. var elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? api.createElementNS(i, tag)
  14020. : api.createElement(tag);
  14021. if (hash < dot)
  14022. elm.setAttribute('id', sel.slice(hash + 1, dot));
  14023. if (dotIdx > 0)
  14024. elm.setAttribute('class', sel.slice(dot + 1).replace(/\./g, ' '));
  14025. for (i = 0; i < cbs.create.length; ++i)
  14026. cbs.create[i](emptyNode, vnode);
  14027. if (is.array(children)) {
  14028. for (i = 0; i < children.length; ++i) {
  14029. var ch = children[i];
  14030. if (ch != null) {
  14031. api.appendChild(elm, createElm(ch, insertedVnodeQueue));
  14032. }
  14033. }
  14034. }
  14035. else if (is.primitive(vnode.text)) {
  14036. api.appendChild(elm, api.createTextNode(vnode.text));
  14037. }
  14038. i = vnode.data.hook; // Reuse variable
  14039. if (isDef(i)) {
  14040. if (i.create)
  14041. i.create(emptyNode, vnode);
  14042. if (i.insert)
  14043. insertedVnodeQueue.push(vnode);
  14044. }
  14045. }
  14046. else {
  14047. vnode.elm = api.createTextNode(vnode.text);
  14048. }
  14049. return vnode.elm;
  14050. }
  14051. function addVnodes(parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
  14052. for (; startIdx <= endIdx; ++startIdx) {
  14053. var ch = vnodes[startIdx];
  14054. if (ch != null) {
  14055. api.insertBefore(parentElm, createElm(ch, insertedVnodeQueue), before);
  14056. }
  14057. }
  14058. }
  14059. function invokeDestroyHook(vnode) {
  14060. var i, j, data = vnode.data;
  14061. if (data !== undefined) {
  14062. if (isDef(i = data.hook) && isDef(i = i.destroy))
  14063. i(vnode);
  14064. for (i = 0; i < cbs.destroy.length; ++i)
  14065. cbs.destroy[i](vnode);
  14066. if (vnode.children !== undefined) {
  14067. for (j = 0; j < vnode.children.length; ++j) {
  14068. i = vnode.children[j];
  14069. if (i != null && typeof i !== "string") {
  14070. invokeDestroyHook(i);
  14071. }
  14072. }
  14073. }
  14074. }
  14075. }
  14076. function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
  14077. for (; startIdx <= endIdx; ++startIdx) {
  14078. var i_1 = void 0, listeners = void 0, rm = void 0, ch = vnodes[startIdx];
  14079. if (ch != null) {
  14080. if (isDef(ch.sel)) {
  14081. invokeDestroyHook(ch);
  14082. listeners = cbs.remove.length + 1;
  14083. rm = createRmCb(ch.elm, listeners);
  14084. for (i_1 = 0; i_1 < cbs.remove.length; ++i_1)
  14085. cbs.remove[i_1](ch, rm);
  14086. if (isDef(i_1 = ch.data) && isDef(i_1 = i_1.hook) && isDef(i_1 = i_1.remove)) {
  14087. i_1(ch, rm);
  14088. }
  14089. else {
  14090. rm();
  14091. }
  14092. }
  14093. else {
  14094. api.removeChild(parentElm, ch.elm);
  14095. }
  14096. }
  14097. }
  14098. }
  14099. function updateChildren(parentElm, oldCh, newCh, insertedVnodeQueue) {
  14100. var oldStartIdx = 0, newStartIdx = 0;
  14101. var oldEndIdx = oldCh.length - 1;
  14102. var oldStartVnode = oldCh[0];
  14103. var oldEndVnode = oldCh[oldEndIdx];
  14104. var newEndIdx = newCh.length - 1;
  14105. var newStartVnode = newCh[0];
  14106. var newEndVnode = newCh[newEndIdx];
  14107. var oldKeyToIdx;
  14108. var idxInOld;
  14109. var elmToMove;
  14110. var before;
  14111. while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
  14112. if (oldStartVnode == null) {
  14113. oldStartVnode = oldCh[++oldStartIdx]; // Vnode might have been moved left
  14114. }
  14115. else if (oldEndVnode == null) {
  14116. oldEndVnode = oldCh[--oldEndIdx];
  14117. }
  14118. else if (newStartVnode == null) {
  14119. newStartVnode = newCh[++newStartIdx];
  14120. }
  14121. else if (newEndVnode == null) {
  14122. newEndVnode = newCh[--newEndIdx];
  14123. }
  14124. else if (sameVnode(oldStartVnode, newStartVnode)) {
  14125. patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue);
  14126. oldStartVnode = oldCh[++oldStartIdx];
  14127. newStartVnode = newCh[++newStartIdx];
  14128. }
  14129. else if (sameVnode(oldEndVnode, newEndVnode)) {
  14130. patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue);
  14131. oldEndVnode = oldCh[--oldEndIdx];
  14132. newEndVnode = newCh[--newEndIdx];
  14133. }
  14134. else if (sameVnode(oldStartVnode, newEndVnode)) {
  14135. patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue);
  14136. api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.elm));
  14137. oldStartVnode = oldCh[++oldStartIdx];
  14138. newEndVnode = newCh[--newEndIdx];
  14139. }
  14140. else if (sameVnode(oldEndVnode, newStartVnode)) {
  14141. patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue);
  14142. api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
  14143. oldEndVnode = oldCh[--oldEndIdx];
  14144. newStartVnode = newCh[++newStartIdx];
  14145. }
  14146. else {
  14147. if (oldKeyToIdx === undefined) {
  14148. oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
  14149. }
  14150. idxInOld = oldKeyToIdx[newStartVnode.key];
  14151. if (isUndef(idxInOld)) {
  14152. api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
  14153. newStartVnode = newCh[++newStartIdx];
  14154. }
  14155. else {
  14156. elmToMove = oldCh[idxInOld];
  14157. if (elmToMove.sel !== newStartVnode.sel) {
  14158. api.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm);
  14159. }
  14160. else {
  14161. patchVnode(elmToMove, newStartVnode, insertedVnodeQueue);
  14162. oldCh[idxInOld] = undefined;
  14163. api.insertBefore(parentElm, elmToMove.elm, oldStartVnode.elm);
  14164. }
  14165. newStartVnode = newCh[++newStartIdx];
  14166. }
  14167. }
  14168. }
  14169. if (oldStartIdx > oldEndIdx) {
  14170. before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm;
  14171. addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue);
  14172. }
  14173. else if (newStartIdx > newEndIdx) {
  14174. removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
  14175. }
  14176. }
  14177. function patchVnode(oldVnode, vnode, insertedVnodeQueue) {
  14178. var i, hook;
  14179. if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) {
  14180. i(oldVnode, vnode);
  14181. }
  14182. var elm = vnode.elm = oldVnode.elm;
  14183. var oldCh = oldVnode.children;
  14184. var ch = vnode.children;
  14185. if (oldVnode === vnode)
  14186. return;
  14187. if (vnode.data !== undefined) {
  14188. for (i = 0; i < cbs.update.length; ++i)
  14189. cbs.update[i](oldVnode, vnode);
  14190. i = vnode.data.hook;
  14191. if (isDef(i) && isDef(i = i.update))
  14192. i(oldVnode, vnode);
  14193. }
  14194. if (isUndef(vnode.text)) {
  14195. if (isDef(oldCh) && isDef(ch)) {
  14196. if (oldCh !== ch)
  14197. updateChildren(elm, oldCh, ch, insertedVnodeQueue);
  14198. }
  14199. else if (isDef(ch)) {
  14200. if (isDef(oldVnode.text))
  14201. api.setTextContent(elm, '');
  14202. addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue);
  14203. }
  14204. else if (isDef(oldCh)) {
  14205. removeVnodes(elm, oldCh, 0, oldCh.length - 1);
  14206. }
  14207. else if (isDef(oldVnode.text)) {
  14208. api.setTextContent(elm, '');
  14209. }
  14210. }
  14211. else if (oldVnode.text !== vnode.text) {
  14212. api.setTextContent(elm, vnode.text);
  14213. }
  14214. if (isDef(hook) && isDef(i = hook.postpatch)) {
  14215. i(oldVnode, vnode);
  14216. }
  14217. }
  14218. return function patch(oldVnode, vnode) {
  14219. var i, elm, parent;
  14220. var insertedVnodeQueue = [];
  14221. for (i = 0; i < cbs.pre.length; ++i)
  14222. cbs.pre[i]();
  14223. if (!isVnode(oldVnode)) {
  14224. oldVnode = emptyNodeAt(oldVnode);
  14225. }
  14226. if (sameVnode(oldVnode, vnode)) {
  14227. patchVnode(oldVnode, vnode, insertedVnodeQueue);
  14228. }
  14229. else {
  14230. elm = oldVnode.elm;
  14231. parent = api.parentNode(elm);
  14232. createElm(vnode, insertedVnodeQueue);
  14233. if (parent !== null) {
  14234. api.insertBefore(parent, vnode.elm, api.nextSibling(elm));
  14235. removeVnodes(parent, [oldVnode], 0, 0);
  14236. }
  14237. }
  14238. for (i = 0; i < insertedVnodeQueue.length; ++i) {
  14239. insertedVnodeQueue[i].data.hook.insert(insertedVnodeQueue[i]);
  14240. }
  14241. for (i = 0; i < cbs.post.length; ++i)
  14242. cbs.post[i]();
  14243. return vnode;
  14244. };
  14245. }
  14246. exports.init = init;
  14247. },{"./h":1,"./htmldomapi":2,"./is":3,"./thunk":5,"./vnode":6}],5:[function(require,module,exports){
  14248. "use strict";
  14249. Object.defineProperty(exports, "__esModule", { value: true });
  14250. var h_1 = require("./h");
  14251. function copyToThunk(vnode, thunk) {
  14252. thunk.elm = vnode.elm;
  14253. vnode.data.fn = thunk.data.fn;
  14254. vnode.data.args = thunk.data.args;
  14255. thunk.data = vnode.data;
  14256. thunk.children = vnode.children;
  14257. thunk.text = vnode.text;
  14258. thunk.elm = vnode.elm;
  14259. }
  14260. function init(thunk) {
  14261. var cur = thunk.data;
  14262. var vnode = cur.fn.apply(undefined, cur.args);
  14263. copyToThunk(vnode, thunk);
  14264. }
  14265. function prepatch(oldVnode, thunk) {
  14266. var i, old = oldVnode.data, cur = thunk.data;
  14267. var oldArgs = old.args, args = cur.args;
  14268. if (old.fn !== cur.fn || oldArgs.length !== args.length) {
  14269. copyToThunk(cur.fn.apply(undefined, args), thunk);
  14270. return;
  14271. }
  14272. for (i = 0; i < args.length; ++i) {
  14273. if (oldArgs[i] !== args[i]) {
  14274. copyToThunk(cur.fn.apply(undefined, args), thunk);
  14275. return;
  14276. }
  14277. }
  14278. copyToThunk(oldVnode, thunk);
  14279. }
  14280. exports.thunk = function thunk(sel, key, fn, args) {
  14281. if (args === undefined) {
  14282. args = fn;
  14283. fn = key;
  14284. key = undefined;
  14285. }
  14286. return h_1.h(sel, {
  14287. key: key,
  14288. hook: { init: init, prepatch: prepatch },
  14289. fn: fn,
  14290. args: args
  14291. });
  14292. };
  14293. exports.default = exports.thunk;
  14294. },{"./h":1}],6:[function(require,module,exports){
  14295. "use strict";
  14296. Object.defineProperty(exports, "__esModule", { value: true });
  14297. function vnode(sel, data, children, text, elm) {
  14298. var key = data === undefined ? undefined : data.key;
  14299. return { sel: sel, data: data, children: children,
  14300. text: text, elm: elm, key: key };
  14301. }
  14302. exports.vnode = vnode;
  14303. exports.default = vnode;
  14304. },{}]},{},[4])(4)
  14305. });
  14306. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy8ucmVnaXN0cnkubnBtanMub3JnL2Jyb3dzZXItcGFjay82LjAuMi9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiaC5qcyIsImh0bWxkb21hcGkuanMiLCJpcy5qcyIsInNuYWJiZG9tLmpzIiwidGh1bmsuanMiLCJ2bm9kZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgdm5vZGVfMSA9IHJlcXVpcmUoXCIuL3Zub2RlXCIpO1xudmFyIGlzID0gcmVxdWlyZShcIi4vaXNcIik7XG5mdW5jdGlvbiBhZGROUyhkYXRhLCBjaGlsZHJlbiwgc2VsKSB7XG4gICAgZGF0YS5ucyA9ICdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc7XG4gICAgaWYgKHNlbCAhPT0gJ2ZvcmVpZ25PYmplY3QnICYmIGNoaWxkcmVuICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgdmFyIGNoaWxkRGF0YSA9IGNoaWxkcmVuW2ldLmRhdGE7XG4gICAgICAgICAgICBpZiAoY2hpbGREYXRhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBhZGROUyhjaGlsZERhdGEsIGNoaWxkcmVuW2ldLmNoaWxkcmVuLCBjaGlsZHJlbltpXS5zZWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gaChzZWwsIGIsIGMpIHtcbiAgICB2YXIgZGF0YSA9IHt9LCBjaGlsZHJlbiwgdGV4dCwgaTtcbiAgICBpZiAoYyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGRhdGEgPSBiO1xuICAgICAgICBpZiAoaXMuYXJyYXkoYykpIHtcbiAgICAgICAgICAgIGNoaWxkcmVuID0gYztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpcy5wcmltaXRpdmUoYykpIHtcbiAgICAgICAgICAgIHRleHQgPSBjO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGMgJiYgYy5zZWwpIHtcbiAgICAgICAgICAgIGNoaWxkcmVuID0gW2NdO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKGIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoaXMuYXJyYXkoYikpIHtcbiAgICAgICAgICAgIGNoaWxkcmVuID0gYjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpcy5wcmltaXRpdmUoYikpIHtcbiAgICAgICAgICAgIHRleHQgPSBiO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGIgJiYgYi5zZWwpIHtcbiAgICAgICAgICAgIGNoaWxkcmVuID0gW2JdO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZGF0YSA9IGI7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGlzLmFycmF5KGNoaWxkcmVuKSkge1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChpcy5wcmltaXRpdmUoY2hpbGRyZW5baV0pKVxuICAgICAgICAgICAgICAgIGNoaWxkcmVuW2ldID0gdm5vZGVfMS52bm9kZSh1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBjaGlsZHJlbltpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHNlbFswXSA9PT0gJ3MnICYmIHNlbFsxXSA9PT0gJ3YnICYmIHNlbFsyXSA9PT0gJ2cnICYmXG4gICAgICAgIChzZWwubGVuZ3RoID09PSAzIHx8IHNlbFszXSA9PT0gJy4nIHx8IHNlbFszXSA9PT0gJyMnKSkge1xuICAgICAgICBhZGROUyhkYXRhLCBjaGlsZHJlbiwgc2VsKTtcbiAgICB9XG4gICAgcmV0dXJuIHZub2RlXzEudm5vZGUoc2VsLCBkYXRhLCBjaGlsZHJlbiwgdGV4dCwgdW5kZWZpbmVkKTtcbn1cbmV4cG9ydHMuaCA9IGg7XG47XG5leHBvcnRzLmRlZmF1bHQgPSBoO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aC5qcy5tYXAiLCJcInVzZSBzdHJpY3RcIjtcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodGFnTmFtZSkge1xuICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZ05hbWUpO1xufVxuZnVuY3Rpb24gY3JlYXRlRWxlbWVudE5TKG5hbWVzcGFjZVVSSSwgcXVhbGlmaWVkTmFtZSkge1xuICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMobmFtZXNwYWNlVVJJLCBxdWFsaWZpZWROYW1lKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVRleHROb2RlKHRleHQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodGV4dCk7XG59XG5mdW5jdGlvbiBjcmVhdGVDb21tZW50KHRleHQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlQ29tbWVudCh0ZXh0KTtcbn1cbmZ1bmN0aW9uIGluc2VydEJlZm9yZShwYXJlbnROb2RlLCBuZXdOb2RlLCByZWZlcmVuY2VOb2RlKSB7XG4gICAgcGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobmV3Tm9kZSwgcmVmZXJlbmNlTm9kZSk7XG59XG5mdW5jdGlvbiByZW1vdmVDaGlsZChub2RlLCBjaGlsZCkge1xuICAgIG5vZGUucmVtb3ZlQ2hpbGQoY2hpbGQpO1xufVxuZnVuY3Rpb24gYXBwZW5kQ2hpbGQobm9kZSwgY2hpbGQpIHtcbiAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkKTtcbn1cbmZ1bmN0aW9uIHBhcmVudE5vZGUobm9kZSkge1xuICAgIHJldHVybiBub2RlLnBhcmVudE5vZGU7XG59XG5mdW5jdGlvbiBuZXh0U2libGluZyhub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUubmV4dFNpYmxpbmc7XG59XG5mdW5jdGlvbiB0YWdOYW1lKGVsbSkge1xuICAgIHJldHVybiBlbG0udGFnTmFtZTtcbn1cbmZ1bmN0aW9uIHNldFRleHRDb250ZW50KG5vZGUsIHRleHQpIHtcbiAgICBub2RlLnRleHRDb250ZW50ID0gdGV4dDtcbn1cbmZ1bmN0aW9uIGdldFRleHRDb250ZW50KG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS50ZXh0Q29udGVudDtcbn1cbmZ1bmN0aW9uIGlzRWxlbWVudChub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDE7XG59XG5mdW5jdGlvbiBpc1RleHQobm9kZSkge1xuICAgIHJldHVybiBub2RlLm5vZGVUeXBlID09PSAzO1xufVxuZnVuY3Rpb24gaXNDb21tZW50KG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gODtcbn1cbmV4cG9ydHMuaHRtbERvbUFwaSA9IHtcbiAgICBjcmVhdGVFbGVtZW50OiBjcmVhdGVFbGVtZW50LFxuICAgIGNyZWF0ZUVsZW1lbnROUzogY3JlYXRlRWxlbWVudE5TLFxuICAgIGNyZWF0ZVRleHROb2RlOiBjcmVhdGVUZXh0Tm9kZSxcbiAgICBjcmVhdGVDb21tZW50OiBjcmVhdGVDb21tZW50LFxuICAgIGluc2VydEJlZm9yZTogaW5zZXJ0QmVmb3JlLFxuICAgIHJlbW92ZUNoaWxkOiByZW1vdmVDaGlsZCxcbiAgICBhcHBlbmRDaGlsZDogYXBwZW5kQ2hpbGQsXG4gICAgcGFyZW50Tm9kZTogcGFyZW50Tm9kZSxcbiAgICBuZXh0U2libGluZzogbmV4dFNpYmxpbmcsXG4gICAgdGFnTmFtZTogdGFnTmFtZSxcbiAgICBzZXRUZXh0Q29udGVudDogc2V0VGV4dENvbnRlbnQsXG4gICAgZ2V0VGV4dENvbnRlbnQ6IGdldFRleHRDb250ZW50LFxuICAgIGlzRWxlbWVudDogaXNFbGVtZW50LFxuICAgIGlzVGV4dDogaXNUZXh0LFxuICAgIGlzQ29tbWVudDogaXNDb21tZW50LFxufTtcbmV4cG9ydHMuZGVmYXVsdCA9IGV4cG9ydHMuaHRtbERvbUFwaTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWh0bWxkb21hcGkuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5leHBvcnRzLmFycmF5ID0gQXJyYXkuaXNBcnJheTtcbmZ1bmN0aW9uIHByaW1pdGl2ZShzKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgcyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLnByaW1pdGl2ZSA9IHByaW1pdGl2ZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWlzLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIHZub2RlXzEgPSByZXF1aXJlKFwiLi92bm9kZVwiKTtcbnZhciBpcyA9IHJlcXVpcmUoXCIuL2lzXCIpO1xudmFyIGh0bWxkb21hcGlfMSA9IHJlcXVpcmUoXCIuL2h0bWxkb21hcGlcIik7XG5mdW5jdGlvbiBpc1VuZGVmKHMpIHsgcmV0dXJuIHMgPT09IHVuZGVmaW5lZDsgfVxuZnVuY3Rpb24gaXNEZWYocykgeyByZXR1cm4gcyAhPT0gdW5kZWZpbmVkOyB9XG52YXIgZW1wdHlOb2RlID0gdm5vZGVfMS5kZWZhdWx0KCcnLCB7fSwgW10sIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcbmZ1bmN0aW9uIHNhbWVWbm9kZSh2bm9kZTEsIHZub2RlMikge1xuICAgIHJldHVybiB2bm9kZTEua2V5ID09PSB2bm9kZTIua2V5ICYmIHZub2RlMS5zZWwgPT09IHZub2RlMi5zZWw7XG59XG5mdW5jdGlvbiBpc1Zub2RlKHZub2RlKSB7XG4gICAgcmV0dXJuIHZub2RlLnNlbCAhPT0gdW5kZWZpbmVkO1xufVxuZnVuY3Rpb24gY3JlYXRlS2V5VG9PbGRJZHgoY2hpbGRyZW4sIGJlZ2luSWR4LCBlbmRJZHgpIHtcbiAgICB2YXIgaSwgbWFwID0ge30sIGtleSwgY2g7XG4gICAgZm9yIChpID0gYmVnaW5JZHg7IGkgPD0gZW5kSWR4OyArK2kpIHtcbiAgICAgICAgY2ggPSBjaGlsZHJlbltpXTtcbiAgICAgICAgaWYgKGNoICE9IG51bGwpIHtcbiAgICAgICAgICAgIGtleSA9IGNoLmtleTtcbiAgICAgICAgICAgIGlmIChrZXkgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICAgICAgICBtYXBba2V5XSA9IGk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG1hcDtcbn1cbnZhciBob29rcyA9IFsnY3JlYXRlJywgJ3VwZGF0ZScsICdyZW1vdmUnLCAnZGVzdHJveScsICdwcmUnLCAncG9zdCddO1xudmFyIGhfMSA9IHJlcXVpcmUoXCIuL2hcIik7XG5leHBvcnRzLmggPSBoXzEuaDtcbnZhciB0aHVua18xID0gcmVxdWlyZShcIi4vdGh1bmtcIik7XG5leHBvcnRzLnRodW5rID0gdGh1bmtfMS50aHVuaztcbmZ1bmN0aW9uIGluaXQobW9kdWxlcywgZG9tQXBpKSB7XG4gICAgdmFyIGksIGosIGNicyA9IHt9O1xuICAgIHZhciBhcGkgPSBkb21BcGkgIT09IHVuZGVmaW5lZCA/IGRvbUFwaSA6IGh0bWxkb21hcGlfMS5kZWZhdWx0O1xuICAgIGZvciAoaSA9IDA7IGkgPCBob29rcy5sZW5ndGg7ICsraSkge1xuICAgICAgICBjYnNbaG9va3NbaV1dID0gW107XG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBtb2R1bGVzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICB2YXIgaG9vayA9IG1vZHVsZXNbal1baG9va3NbaV1dO1xuICAgICAgICAgICAgaWYgKGhvb2sgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNic1tob29rc1tpXV0ucHVzaChob29rKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBlbXB0eU5vZGVBdChlbG0pIHtcbiAgICAgICAgdmFyIGlkID0gZWxtLmlkID8gJyMnICsgZWxtLmlkIDogJyc7XG4gICAgICAgIHZhciBjID0gZWxtLmNsYXNzTmFtZSA/ICcuJyArIGVsbS5jbGFzc05hbWUuc3BsaXQoJyAnKS5qb2luKCcuJykgOiAnJztcbiAgICAgICAgcmV0dXJuIHZub2RlXzEuZGVmYXVsdChhcGkudGFnTmFtZShlbG0pLnRvTG93ZXJDYXNlKCkgKyBpZCArIGMsIHt9LCBbXSwgdW5kZWZpbmVkLCBlbG0pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjcmVhdGVSbUNiKGNoaWxkRWxtLCBsaXN0ZW5lcnMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHJtQ2IoKSB7XG4gICAgICAgICAgICBpZiAoLS1saXN0ZW5lcnMgPT09IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50XzEgPSBhcGkucGFyZW50Tm9kZShjaGlsZEVsbSk7XG4gICAgICAgICAgICAgICAgYXBpLnJlbW92ZUNoaWxkKHBhcmVudF8xLCBjaGlsZEVsbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuICAgIGZ1bmN0aW9uIGNyZWF0ZUVsbSh2bm9kZSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSB7XG4gICAgICAgIHZhciBpLCBkYXRhID0gdm5vZGUuZGF0YTtcbiAgICAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGlzRGVmKGkgPSBkYXRhLmhvb2spICYmIGlzRGVmKGkgPSBpLmluaXQpKSB7XG4gICAgICAgICAgICAgICAgaSh2bm9kZSk7XG4gICAgICAgICAgICAgICAgZGF0YSA9IHZub2RlLmRhdGE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW4sIHNlbCA9IHZub2RlLnNlbDtcbiAgICAgICAgaWYgKHNlbCA9PT0gJyEnKSB7XG4gICAgICAgICAgICBpZiAoaXNVbmRlZih2bm9kZS50ZXh0KSkge1xuICAgICAgICAgICAgICAgIHZub2RlLnRleHQgPSAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZub2RlLmVsbSA9IGFwaS5jcmVhdGVDb21tZW50KHZub2RlLnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHNlbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAvLyBQYXJzZSBzZWxlY3RvclxuICAgICAgICAgICAgdmFyIGhhc2hJZHggPSBzZWwuaW5kZXhPZignIycpO1xuICAgICAgICAgICAgdmFyIGRvdElkeCA9IHNlbC5pbmRleE9mKCcuJywgaGFzaElkeCk7XG4gICAgICAgICAgICB2YXIgaGFzaCA9IGhhc2hJZHggPiAwID8gaGFzaElkeCA6IHNlbC5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgZG90ID0gZG90SWR4ID4gMCA/IGRvdElkeCA6IHNlbC5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgdGFnID0gaGFzaElkeCAhPT0gLTEgfHwgZG90SWR4ICE9PSAtMSA/IHNlbC5zbGljZSgwLCBNYXRoLm1pbihoYXNoLCBkb3QpKSA6IHNlbDtcbiAgICAgICAgICAgIHZhciBlbG0gPSB2bm9kZS5lbG0gPSBpc0RlZihkYXRhKSAmJiBpc0RlZihpID0gZGF0YS5ucykgPyBhcGkuY3JlYXRlRWxlbWVudE5TKGksIHRhZylcbiAgICAgICAgICAgICAgICA6IGFwaS5jcmVhdGVFbGVtZW50KHRhZyk7XG4gICAgICAgICAgICBpZiAoaGFzaCA8IGRvdClcbiAgICAgICAgICAgICAgICBlbG0uc2V0QXR0cmlidXRlKCdpZCcsIHNlbC5zbGljZShoYXNoICsgMSwgZG90KSk7XG4gICAgICAgICAgICBpZiAoZG90SWR4ID4gMClcbiAgICAgICAgICAgICAgICBlbG0uc2V0QXR0cmlidXRlKCdjbGFzcycsIHNlbC5zbGljZShkb3QgKyAxKS5yZXBsYWNlKC9cXC4vZywgJyAnKSk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY2JzLmNyZWF0ZS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICBjYnMuY3JlYXRlW2ldKGVtcHR5Tm9kZSwgdm5vZGUpO1xuICAgICAgICAgICAgaWYgKGlzLmFycmF5KGNoaWxkcmVuKSkge1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2ggPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwaS5hcHBlbmRDaGlsZChlbG0sIGNyZWF0ZUVsbShjaCwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpcy5wcmltaXRpdmUodm5vZGUudGV4dCkpIHtcbiAgICAgICAgICAgICAgICBhcGkuYXBwZW5kQ2hpbGQoZWxtLCBhcGkuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaSA9IHZub2RlLmRhdGEuaG9vazsgLy8gUmV1c2UgdmFyaWFibGVcbiAgICAgICAgICAgIGlmIChpc0RlZihpKSkge1xuICAgICAgICAgICAgICAgIGlmIChpLmNyZWF0ZSlcbiAgICAgICAgICAgICAgICAgICAgaS5jcmVhdGUoZW1wdHlOb2RlLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgaWYgKGkuaW5zZXJ0KVxuICAgICAgICAgICAgICAgICAgICBpbnNlcnRlZFZub2RlUXVldWUucHVzaCh2bm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2bm9kZS5lbG0gPSBhcGkuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZub2RlLmVsbTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYWRkVm5vZGVzKHBhcmVudEVsbSwgYmVmb3JlLCB2bm9kZXMsIHN0YXJ0SWR4LCBlbmRJZHgsIGluc2VydGVkVm5vZGVRdWV1ZSkge1xuICAgICAgICBmb3IgKDsgc3RhcnRJZHggPD0gZW5kSWR4OyArK3N0YXJ0SWR4KSB7XG4gICAgICAgICAgICB2YXIgY2ggPSB2bm9kZXNbc3RhcnRJZHhdO1xuICAgICAgICAgICAgaWYgKGNoICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBhcGkuaW5zZXJ0QmVmb3JlKHBhcmVudEVsbSwgY3JlYXRlRWxtKGNoLCBpbnNlcnRlZFZub2RlUXVldWUpLCBiZWZvcmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGludm9rZURlc3Ryb3lIb29rKHZub2RlKSB7XG4gICAgICAgIHZhciBpLCBqLCBkYXRhID0gdm5vZGUuZGF0YTtcbiAgICAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgaWYgKGlzRGVmKGkgPSBkYXRhLmhvb2spICYmIGlzRGVmKGkgPSBpLmRlc3Ryb3kpKVxuICAgICAgICAgICAgICAgIGkodm5vZGUpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNicy5kZXN0cm95Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgIGNicy5kZXN0cm95W2ldKHZub2RlKTtcbiAgICAgICAgICAgIGlmICh2bm9kZS5jaGlsZHJlbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IHZub2RlLmNoaWxkcmVuLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgIGkgPSB2bm9kZS5jaGlsZHJlbltqXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgIT0gbnVsbCAmJiB0eXBlb2YgaSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW52b2tlRGVzdHJveUhvb2soaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gcmVtb3ZlVm5vZGVzKHBhcmVudEVsbSwgdm5vZGVzLCBzdGFydElkeCwgZW5kSWR4KSB7XG4gICAgICAgIGZvciAoOyBzdGFydElkeCA8PSBlbmRJZHg7ICsrc3RhcnRJZHgpIHtcbiAgICAgICAgICAgIHZhciBpXzEgPSB2b2lkIDAsIGxpc3RlbmVycyA9IHZvaWQgMCwgcm0gPSB2b2lkIDAsIGNoID0gdm5vZGVzW3N0YXJ0SWR4XTtcbiAgICAgICAgICAgIGlmIChjaCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRGVmKGNoLnNlbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgaW52b2tlRGVzdHJveUhvb2soY2gpO1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnMgPSBjYnMucmVtb3ZlLmxlbmd0aCArIDE7XG4gICAgICAgICAgICAgICAgICAgIHJtID0gY3JlYXRlUm1DYihjaC5lbG0sIGxpc3RlbmVycyk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaV8xID0gMDsgaV8xIDwgY2JzLnJlbW92ZS5sZW5ndGg7ICsraV8xKVxuICAgICAgICAgICAgICAgICAgICAgICAgY2JzLnJlbW92ZVtpXzFdKGNoLCBybSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0RlZihpXzEgPSBjaC5kYXRhKSAmJiBpc0RlZihpXzEgPSBpXzEuaG9vaykgJiYgaXNEZWYoaV8xID0gaV8xLnJlbW92ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlfMShjaCwgcm0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm0oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXBpLnJlbW92ZUNoaWxkKHBhcmVudEVsbSwgY2guZWxtKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gdXBkYXRlQ2hpbGRyZW4ocGFyZW50RWxtLCBvbGRDaCwgbmV3Q2gsIGluc2VydGVkVm5vZGVRdWV1ZSkge1xuICAgICAgICB2YXIgb2xkU3RhcnRJZHggPSAwLCBuZXdTdGFydElkeCA9IDA7XG4gICAgICAgIHZhciBvbGRFbmRJZHggPSBvbGRDaC5sZW5ndGggLSAxO1xuICAgICAgICB2YXIgb2xkU3RhcnRWbm9kZSA9IG9sZENoWzBdO1xuICAgICAgICB2YXIgb2xkRW5kVm5vZGUgPSBvbGRDaFtvbGRFbmRJZHhdO1xuICAgICAgICB2YXIgbmV3RW5kSWR4ID0gbmV3Q2gubGVuZ3RoIC0gMTtcbiAgICAgICAgdmFyIG5ld1N0YXJ0Vm5vZGUgPSBuZXdDaFswXTtcbiAgICAgICAgdmFyIG5ld0VuZFZub2RlID0gbmV3Q2hbbmV3RW5kSWR4XTtcbiAgICAgICAgdmFyIG9sZEtleVRvSWR4O1xuICAgICAgICB2YXIgaWR4SW5PbGQ7XG4gICAgICAgIHZhciBlbG1Ub01vdmU7XG4gICAgICAgIHZhciBiZWZvcmU7XG4gICAgICAgIHdoaWxlIChvbGRTdGFydElkeCA8PSBvbGRFbmRJZHggJiYgbmV3U3RhcnRJZHggPD0gbmV3RW5kSWR4KSB7XG4gICAgICAgICAgICBpZiAob2xkU3RhcnRWbm9kZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgb2xkU3RhcnRWbm9kZSA9IG9sZENoWysrb2xkU3RhcnRJZHhdOyAvLyBWbm9kZSBtaWdodCBoYXZlIGJlZW4gbW92ZWQgbGVmdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAob2xkRW5kVm5vZGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG9sZEVuZFZub2RlID0gb2xkQ2hbLS1vbGRFbmRJZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobmV3U3RhcnRWbm9kZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbmV3U3RhcnRWbm9kZSA9IG5ld0NoWysrbmV3U3RhcnRJZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAobmV3RW5kVm5vZGUgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG5ld0VuZFZub2RlID0gbmV3Q2hbLS1uZXdFbmRJZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoc2FtZVZub2RlKG9sZFN0YXJ0Vm5vZGUsIG5ld1N0YXJ0Vm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgcGF0Y2hWbm9kZShvbGRTdGFydFZub2RlLCBuZXdTdGFydFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICAgICAgICAgIG9sZFN0YXJ0Vm5vZGUgPSBvbGRDaFsrK29sZFN0YXJ0SWR4XTtcbiAgICAgICAgICAgICAgICBuZXdTdGFydFZub2RlID0gbmV3Q2hbKytuZXdTdGFydElkeF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChzYW1lVm5vZGUob2xkRW5kVm5vZGUsIG5ld0VuZFZub2RlKSkge1xuICAgICAgICAgICAgICAgIHBhdGNoVm5vZGUob2xkRW5kVm5vZGUsIG5ld0VuZFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICAgICAgICAgIG9sZEVuZFZub2RlID0gb2xkQ2hbLS1vbGRFbmRJZHhdO1xuICAgICAgICAgICAgICAgIG5ld0VuZFZub2RlID0gbmV3Q2hbLS1uZXdFbmRJZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoc2FtZVZub2RlKG9sZFN0YXJ0Vm5vZGUsIG5ld0VuZFZub2RlKSkge1xuICAgICAgICAgICAgICAgIHBhdGNoVm5vZGUob2xkU3RhcnRWbm9kZSwgbmV3RW5kVm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgICAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIG9sZFN0YXJ0Vm5vZGUuZWxtLCBhcGkubmV4dFNpYmxpbmcob2xkRW5kVm5vZGUuZWxtKSk7XG4gICAgICAgICAgICAgICAgb2xkU3RhcnRWbm9kZSA9IG9sZENoWysrb2xkU3RhcnRJZHhdO1xuICAgICAgICAgICAgICAgIG5ld0VuZFZub2RlID0gbmV3Q2hbLS1uZXdFbmRJZHhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoc2FtZVZub2RlKG9sZEVuZFZub2RlLCBuZXdTdGFydFZub2RlKSkge1xuICAgICAgICAgICAgICAgIHBhdGNoVm5vZGUob2xkRW5kVm5vZGUsIG5ld1N0YXJ0Vm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgICAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIG9sZEVuZFZub2RlLmVsbSwgb2xkU3RhcnRWbm9kZS5lbG0pO1xuICAgICAgICAgICAgICAgIG9sZEVuZFZub2RlID0gb2xkQ2hbLS1vbGRFbmRJZHhdO1xuICAgICAgICAgICAgICAgIG5ld1N0YXJ0Vm5vZGUgPSBuZXdDaFsrK25ld1N0YXJ0SWR4XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChvbGRLZXlUb0lkeCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZEtleVRvSWR4ID0gY3JlYXRlS2V5VG9PbGRJZHgob2xkQ2gsIG9sZFN0YXJ0SWR4LCBvbGRFbmRJZHgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZHhJbk9sZCA9IG9sZEtleVRvSWR4W25ld1N0YXJ0Vm5vZGUua2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoaXNVbmRlZihpZHhJbk9sZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIGNyZWF0ZUVsbShuZXdTdGFydFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpLCBvbGRTdGFydFZub2RlLmVsbSk7XG4gICAgICAgICAgICAgICAgICAgIG5ld1N0YXJ0Vm5vZGUgPSBuZXdDaFsrK25ld1N0YXJ0SWR4XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsbVRvTW92ZSA9IG9sZENoW2lkeEluT2xkXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVsbVRvTW92ZS5zZWwgIT09IG5ld1N0YXJ0Vm5vZGUuc2VsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcGkuaW5zZXJ0QmVmb3JlKHBhcmVudEVsbSwgY3JlYXRlRWxtKG5ld1N0YXJ0Vm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSksIG9sZFN0YXJ0Vm5vZGUuZWxtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoVm5vZGUoZWxtVG9Nb3ZlLCBuZXdTdGFydFZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2xkQ2hbaWR4SW5PbGRdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBpLmluc2VydEJlZm9yZShwYXJlbnRFbG0sIGVsbVRvTW92ZS5lbG0sIG9sZFN0YXJ0Vm5vZGUuZWxtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBuZXdTdGFydFZub2RlID0gbmV3Q2hbKytuZXdTdGFydElkeF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChvbGRTdGFydElkeCA+IG9sZEVuZElkeCkge1xuICAgICAgICAgICAgYmVmb3JlID0gbmV3Q2hbbmV3RW5kSWR4ICsgMV0gPT0gbnVsbCA/IG51bGwgOiBuZXdDaFtuZXdFbmRJZHggKyAxXS5lbG07XG4gICAgICAgICAgICBhZGRWbm9kZXMocGFyZW50RWxtLCBiZWZvcmUsIG5ld0NoLCBuZXdTdGFydElkeCwgbmV3RW5kSWR4LCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5ld1N0YXJ0SWR4ID4gbmV3RW5kSWR4KSB7XG4gICAgICAgICAgICByZW1vdmVWbm9kZXMocGFyZW50RWxtLCBvbGRDaCwgb2xkU3RhcnRJZHgsIG9sZEVuZElkeCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gcGF0Y2hWbm9kZShvbGRWbm9kZSwgdm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSkge1xuICAgICAgICB2YXIgaSwgaG9vaztcbiAgICAgICAgaWYgKGlzRGVmKGkgPSB2bm9kZS5kYXRhKSAmJiBpc0RlZihob29rID0gaS5ob29rKSAmJiBpc0RlZihpID0gaG9vay5wcmVwYXRjaCkpIHtcbiAgICAgICAgICAgIGkob2xkVm5vZGUsIHZub2RlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZWxtID0gdm5vZGUuZWxtID0gb2xkVm5vZGUuZWxtO1xuICAgICAgICB2YXIgb2xkQ2ggPSBvbGRWbm9kZS5jaGlsZHJlbjtcbiAgICAgICAgdmFyIGNoID0gdm5vZGUuY2hpbGRyZW47XG4gICAgICAgIGlmIChvbGRWbm9kZSA9PT0gdm5vZGUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICh2bm9kZS5kYXRhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjYnMudXBkYXRlLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgIGNicy51cGRhdGVbaV0ob2xkVm5vZGUsIHZub2RlKTtcbiAgICAgICAgICAgIGkgPSB2bm9kZS5kYXRhLmhvb2s7XG4gICAgICAgICAgICBpZiAoaXNEZWYoaSkgJiYgaXNEZWYoaSA9IGkudXBkYXRlKSlcbiAgICAgICAgICAgICAgICBpKG9sZFZub2RlLCB2bm9kZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzVW5kZWYodm5vZGUudGV4dCkpIHtcbiAgICAgICAgICAgIGlmIChpc0RlZihvbGRDaCkgJiYgaXNEZWYoY2gpKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZENoICE9PSBjaClcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlQ2hpbGRyZW4oZWxtLCBvbGRDaCwgY2gsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpc0RlZihjaCkpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNEZWYob2xkVm5vZGUudGV4dCkpXG4gICAgICAgICAgICAgICAgICAgIGFwaS5zZXRUZXh0Q29udGVudChlbG0sICcnKTtcbiAgICAgICAgICAgICAgICBhZGRWbm9kZXMoZWxtLCBudWxsLCBjaCwgMCwgY2gubGVuZ3RoIC0gMSwgaW5zZXJ0ZWRWbm9kZVF1ZXVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlzRGVmKG9sZENoKSkge1xuICAgICAgICAgICAgICAgIHJlbW92ZVZub2RlcyhlbG0sIG9sZENoLCAwLCBvbGRDaC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlzRGVmKG9sZFZub2RlLnRleHQpKSB7XG4gICAgICAgICAgICAgICAgYXBpLnNldFRleHRDb250ZW50KGVsbSwgJycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9sZFZub2RlLnRleHQgIT09IHZub2RlLnRleHQpIHtcbiAgICAgICAgICAgIGFwaS5zZXRUZXh0Q29udGVudChlbG0sIHZub2RlLnRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc0RlZihob29rKSAmJiBpc0RlZihpID0gaG9vay5wb3N0cGF0Y2gpKSB7XG4gICAgICAgICAgICBpKG9sZFZub2RlLCB2bm9kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHBhdGNoKG9sZFZub2RlLCB2bm9kZSkge1xuICAgICAgICB2YXIgaSwgZWxtLCBwYXJlbnQ7XG4gICAgICAgIHZhciBpbnNlcnRlZFZub2RlUXVldWUgPSBbXTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNicy5wcmUubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICBjYnMucHJlW2ldKCk7XG4gICAgICAgIGlmICghaXNWbm9kZShvbGRWbm9kZSkpIHtcbiAgICAgICAgICAgIG9sZFZub2RlID0gZW1wdHlOb2RlQXQob2xkVm5vZGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzYW1lVm5vZGUob2xkVm5vZGUsIHZub2RlKSkge1xuICAgICAgICAgICAgcGF0Y2hWbm9kZShvbGRWbm9kZSwgdm5vZGUsIGluc2VydGVkVm5vZGVRdWV1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBlbG0gPSBvbGRWbm9kZS5lbG07XG4gICAgICAgICAgICBwYXJlbnQgPSBhcGkucGFyZW50Tm9kZShlbG0pO1xuICAgICAgICAgICAgY3JlYXRlRWxtKHZub2RlLCBpbnNlcnRlZFZub2RlUXVldWUpO1xuICAgICAgICAgICAgaWYgKHBhcmVudCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGFwaS5pbnNlcnRCZWZvcmUocGFyZW50LCB2bm9kZS5lbG0sIGFwaS5uZXh0U2libGluZyhlbG0pKTtcbiAgICAgICAgICAgICAgICByZW1vdmVWbm9kZXMocGFyZW50LCBbb2xkVm5vZGVdLCAwLCAwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaW5zZXJ0ZWRWbm9kZVF1ZXVlLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBpbnNlcnRlZFZub2RlUXVldWVbaV0uZGF0YS5ob29rLmluc2VydChpbnNlcnRlZFZub2RlUXVldWVbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjYnMucG9zdC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgIGNicy5wb3N0W2ldKCk7XG4gICAgICAgIHJldHVybiB2bm9kZTtcbiAgICB9O1xufVxuZXhwb3J0cy5pbml0ID0gaW5pdDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNuYWJiZG9tLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIGhfMSA9IHJlcXVpcmUoXCIuL2hcIik7XG5mdW5jdGlvbiBjb3B5VG9UaHVuayh2bm9kZSwgdGh1bmspIHtcbiAgICB0aHVuay5lbG0gPSB2bm9kZS5lbG07XG4gICAgdm5vZGUuZGF0YS5mbiA9IHRodW5rLmRhdGEuZm47XG4gICAgdm5vZGUuZGF0YS5hcmdzID0gdGh1bmsuZGF0YS5hcmdzO1xuICAgIHRodW5rLmRhdGEgPSB2bm9kZS5kYXRhO1xuICAgIHRodW5rLmNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG4gICAgdGh1bmsudGV4dCA9IHZub2RlLnRleHQ7XG4gICAgdGh1bmsuZWxtID0gdm5vZGUuZWxtO1xufVxuZnVuY3Rpb24gaW5pdCh0aHVuaykge1xuICAgIHZhciBjdXIgPSB0aHVuay5kYXRhO1xuICAgIHZhciB2bm9kZSA9IGN1ci5mbi5hcHBseSh1bmRlZmluZWQsIGN1ci5hcmdzKTtcbiAgICBjb3B5VG9UaHVuayh2bm9kZSwgdGh1bmspO1xufVxuZnVuY3Rpb24gcHJlcGF0Y2gob2xkVm5vZGUsIHRodW5rKSB7XG4gICAgdmFyIGksIG9sZCA9IG9sZFZub2RlLmRhdGEsIGN1ciA9IHRodW5rLmRhdGE7XG4gICAgdmFyIG9sZEFyZ3MgPSBvbGQuYXJncywgYXJncyA9IGN1ci5hcmdzO1xuICAgIGlmIChvbGQuZm4gIT09IGN1ci5mbiB8fCBvbGRBcmdzLmxlbmd0aCAhPT0gYXJncy5sZW5ndGgpIHtcbiAgICAgICAgY29weVRvVGh1bmsoY3VyLmZuLmFwcGx5KHVuZGVmaW5lZCwgYXJncyksIHRodW5rKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7ICsraSkge1xuICAgICAgICBpZiAob2xkQXJnc1tpXSAhPT0gYXJnc1tpXSkge1xuICAgICAgICAgICAgY29weVRvVGh1bmsoY3VyLmZuLmFwcGx5KHVuZGVmaW5lZCwgYXJncyksIHRodW5rKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb3B5VG9UaHVuayhvbGRWbm9kZSwgdGh1bmspO1xufVxuZXhwb3J0cy50aHVuayA9IGZ1bmN0aW9uIHRodW5rKHNlbCwga2V5LCBmbiwgYXJncykge1xuICAgIGlmIChhcmdzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXJncyA9IGZuO1xuICAgICAgICBmbiA9IGtleTtcbiAgICAgICAga2V5ID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gaF8xLmgoc2VsLCB7XG4gICAgICAgIGtleToga2V5LFxuICAgICAgICBob29rOiB7IGluaXQ6IGluaXQsIHByZXBhdGNoOiBwcmVwYXRjaCB9LFxuICAgICAgICBmbjogZm4sXG4gICAgICAgIGFyZ3M6IGFyZ3NcbiAgICB9KTtcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBleHBvcnRzLnRodW5rO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dGh1bmsuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiB2bm9kZShzZWwsIGRhdGEsIGNoaWxkcmVuLCB0ZXh0LCBlbG0pIHtcbiAgICB2YXIga2V5ID0gZGF0YSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogZGF0YS5rZXk7XG4gICAgcmV0dXJuIHsgc2VsOiBzZWwsIGRhdGE6IGRhdGEsIGNoaWxkcmVuOiBjaGlsZHJlbixcbiAgICAgICAgdGV4dDogdGV4dCwgZWxtOiBlbG0sIGtleToga2V5IH07XG59XG5leHBvcnRzLnZub2RlID0gdm5vZGU7XG5leHBvcnRzLmRlZmF1bHQgPSB2bm9kZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXZub2RlLmpzLm1hcCJdfQ==
  14307. ;
  14308. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('snabbdom-attributes',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom_attributes = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  14309. "use strict";
  14310. Object.defineProperty(exports, "__esModule", { value: true });
  14311. var booleanAttrs = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "compact", "controls", "declare",
  14312. "default", "defaultchecked", "defaultmuted", "defaultselected", "defer", "disabled", "draggable",
  14313. "enabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "itemscope", "loop", "multiple",
  14314. "muted", "nohref", "noresize", "noshade", "novalidate", "nowrap", "open", "pauseonexit", "readonly",
  14315. "required", "reversed", "scoped", "seamless", "selected", "sortable", "spellcheck", "translate",
  14316. "truespeed", "typemustmatch", "visible"];
  14317. var xlinkNS = 'http://www.w3.org/1999/xlink';
  14318. var xmlNS = 'http://www.w3.org/XML/1998/namespace';
  14319. var colonChar = 58;
  14320. var xChar = 120;
  14321. var booleanAttrsDict = Object.create(null);
  14322. for (var i = 0, len = booleanAttrs.length; i < len; i++) {
  14323. booleanAttrsDict[booleanAttrs[i]] = true;
  14324. }
  14325. function updateAttrs(oldVnode, vnode) {
  14326. var key, elm = vnode.elm, oldAttrs = oldVnode.data.attrs, attrs = vnode.data.attrs;
  14327. if (!oldAttrs && !attrs)
  14328. return;
  14329. if (oldAttrs === attrs)
  14330. return;
  14331. oldAttrs = oldAttrs || {};
  14332. attrs = attrs || {};
  14333. // update modified attributes, add new attributes
  14334. for (key in attrs) {
  14335. var cur = attrs[key];
  14336. var old = oldAttrs[key];
  14337. if (old !== cur) {
  14338. if (booleanAttrsDict[key]) {
  14339. if (cur) {
  14340. elm.setAttribute(key, "");
  14341. }
  14342. else {
  14343. elm.removeAttribute(key);
  14344. }
  14345. }
  14346. else {
  14347. if (key.charCodeAt(0) !== xChar) {
  14348. elm.setAttribute(key, cur);
  14349. }
  14350. else if (key.charCodeAt(3) === colonChar) {
  14351. // Assume xml namespace
  14352. elm.setAttributeNS(xmlNS, key, cur);
  14353. }
  14354. else if (key.charCodeAt(5) === colonChar) {
  14355. // Assume xlink namespace
  14356. elm.setAttributeNS(xlinkNS, key, cur);
  14357. }
  14358. else {
  14359. elm.setAttribute(key, cur);
  14360. }
  14361. }
  14362. }
  14363. }
  14364. // remove removed attributes
  14365. // use `in` operator since the previous `for` iteration uses it (.i.e. add even attributes with undefined value)
  14366. // the other option is to remove all attributes with value == undefined
  14367. for (key in oldAttrs) {
  14368. if (!(key in attrs)) {
  14369. elm.removeAttribute(key);
  14370. }
  14371. }
  14372. }
  14373. exports.attributesModule = { create: updateAttrs, update: updateAttrs };
  14374. exports.default = exports.attributesModule;
  14375. },{}]},{},[1])(1)
  14376. });
  14377. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy8ucmVnaXN0cnkubnBtanMub3JnL2Jyb3dzZXItcGFjay82LjAuMi9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwibW9kdWxlcy9hdHRyaWJ1dGVzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgYm9vbGVhbkF0dHJzID0gW1wiYWxsb3dmdWxsc2NyZWVuXCIsIFwiYXN5bmNcIiwgXCJhdXRvZm9jdXNcIiwgXCJhdXRvcGxheVwiLCBcImNoZWNrZWRcIiwgXCJjb21wYWN0XCIsIFwiY29udHJvbHNcIiwgXCJkZWNsYXJlXCIsXG4gICAgXCJkZWZhdWx0XCIsIFwiZGVmYXVsdGNoZWNrZWRcIiwgXCJkZWZhdWx0bXV0ZWRcIiwgXCJkZWZhdWx0c2VsZWN0ZWRcIiwgXCJkZWZlclwiLCBcImRpc2FibGVkXCIsIFwiZHJhZ2dhYmxlXCIsXG4gICAgXCJlbmFibGVkXCIsIFwiZm9ybW5vdmFsaWRhdGVcIiwgXCJoaWRkZW5cIiwgXCJpbmRldGVybWluYXRlXCIsIFwiaW5lcnRcIiwgXCJpc21hcFwiLCBcIml0ZW1zY29wZVwiLCBcImxvb3BcIiwgXCJtdWx0aXBsZVwiLFxuICAgIFwibXV0ZWRcIiwgXCJub2hyZWZcIiwgXCJub3Jlc2l6ZVwiLCBcIm5vc2hhZGVcIiwgXCJub3ZhbGlkYXRlXCIsIFwibm93cmFwXCIsIFwib3BlblwiLCBcInBhdXNlb25leGl0XCIsIFwicmVhZG9ubHlcIixcbiAgICBcInJlcXVpcmVkXCIsIFwicmV2ZXJzZWRcIiwgXCJzY29wZWRcIiwgXCJzZWFtbGVzc1wiLCBcInNlbGVjdGVkXCIsIFwic29ydGFibGVcIiwgXCJzcGVsbGNoZWNrXCIsIFwidHJhbnNsYXRlXCIsXG4gICAgXCJ0cnVlc3BlZWRcIiwgXCJ0eXBlbXVzdG1hdGNoXCIsIFwidmlzaWJsZVwiXTtcbnZhciB4bGlua05TID0gJ2h0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsnO1xudmFyIHhtbE5TID0gJ2h0dHA6Ly93d3cudzMub3JnL1hNTC8xOTk4L25hbWVzcGFjZSc7XG52YXIgY29sb25DaGFyID0gNTg7XG52YXIgeENoYXIgPSAxMjA7XG52YXIgYm9vbGVhbkF0dHJzRGljdCA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5mb3IgKHZhciBpID0gMCwgbGVuID0gYm9vbGVhbkF0dHJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgYm9vbGVhbkF0dHJzRGljdFtib29sZWFuQXR0cnNbaV1dID0gdHJ1ZTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZUF0dHJzKG9sZFZub2RlLCB2bm9kZSkge1xuICAgIHZhciBrZXksIGVsbSA9IHZub2RlLmVsbSwgb2xkQXR0cnMgPSBvbGRWbm9kZS5kYXRhLmF0dHJzLCBhdHRycyA9IHZub2RlLmRhdGEuYXR0cnM7XG4gICAgaWYgKCFvbGRBdHRycyAmJiAhYXR0cnMpXG4gICAgICAgIHJldHVybjtcbiAgICBpZiAob2xkQXR0cnMgPT09IGF0dHJzKVxuICAgICAgICByZXR1cm47XG4gICAgb2xkQXR0cnMgPSBvbGRBdHRycyB8fCB7fTtcbiAgICBhdHRycyA9IGF0dHJzIHx8IHt9O1xuICAgIC8vIHVwZGF0ZSBtb2RpZmllZCBhdHRyaWJ1dGVzLCBhZGQgbmV3IGF0dHJpYnV0ZXNcbiAgICBmb3IgKGtleSBpbiBhdHRycykge1xuICAgICAgICB2YXIgY3VyID0gYXR0cnNba2V5XTtcbiAgICAgICAgdmFyIG9sZCA9IG9sZEF0dHJzW2tleV07XG4gICAgICAgIGlmIChvbGQgIT09IGN1cikge1xuICAgICAgICAgICAgaWYgKGJvb2xlYW5BdHRyc0RpY3Rba2V5XSkge1xuICAgICAgICAgICAgICAgIGlmIChjdXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxtLnNldEF0dHJpYnV0ZShrZXksIFwiXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZWxtLnJlbW92ZUF0dHJpYnV0ZShrZXkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChrZXkuY2hhckNvZGVBdCgwKSAhPT0geENoYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxtLnNldEF0dHJpYnV0ZShrZXksIGN1cik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGtleS5jaGFyQ29kZUF0KDMpID09PSBjb2xvbkNoYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQXNzdW1lIHhtbCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICAgICAgZWxtLnNldEF0dHJpYnV0ZU5TKHhtbE5TLCBrZXksIGN1cik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGtleS5jaGFyQ29kZUF0KDUpID09PSBjb2xvbkNoYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQXNzdW1lIHhsaW5rIG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgICAgICBlbG0uc2V0QXR0cmlidXRlTlMoeGxpbmtOUywga2V5LCBjdXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZWxtLnNldEF0dHJpYnV0ZShrZXksIGN1cik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIC8vIHJlbW92ZSByZW1vdmVkIGF0dHJpYnV0ZXNcbiAgICAvLyB1c2UgYGluYCBvcGVyYXRvciBzaW5jZSB0aGUgcHJldmlvdXMgYGZvcmAgaXRlcmF0aW9uIHVzZXMgaXQgKC5pLmUuIGFkZCBldmVuIGF0dHJpYnV0ZXMgd2l0aCB1bmRlZmluZWQgdmFsdWUpXG4gICAgLy8gdGhlIG90aGVyIG9wdGlvbiBpcyB0byByZW1vdmUgYWxsIGF0dHJpYnV0ZXMgd2l0aCB2YWx1ZSA9PSB1bmRlZmluZWRcbiAgICBmb3IgKGtleSBpbiBvbGRBdHRycykge1xuICAgICAgICBpZiAoIShrZXkgaW4gYXR0cnMpKSB7XG4gICAgICAgICAgICBlbG0ucmVtb3ZlQXR0cmlidXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5leHBvcnRzLmF0dHJpYnV0ZXNNb2R1bGUgPSB7IGNyZWF0ZTogdXBkYXRlQXR0cnMsIHVwZGF0ZTogdXBkYXRlQXR0cnMgfTtcbmV4cG9ydHMuZGVmYXVsdCA9IGV4cG9ydHMuYXR0cmlidXRlc01vZHVsZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWF0dHJpYnV0ZXMuanMubWFwIl19
  14378. ;
  14379. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('snabbdom-class',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom_class = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  14380. "use strict";
  14381. Object.defineProperty(exports, "__esModule", { value: true });
  14382. function updateClass(oldVnode, vnode) {
  14383. var cur, name, elm = vnode.elm, oldClass = oldVnode.data.class, klass = vnode.data.class;
  14384. if (!oldClass && !klass)
  14385. return;
  14386. if (oldClass === klass)
  14387. return;
  14388. oldClass = oldClass || {};
  14389. klass = klass || {};
  14390. for (name in oldClass) {
  14391. if (!klass[name]) {
  14392. elm.classList.remove(name);
  14393. }
  14394. }
  14395. for (name in klass) {
  14396. cur = klass[name];
  14397. if (cur !== oldClass[name]) {
  14398. elm.classList[cur ? 'add' : 'remove'](name);
  14399. }
  14400. }
  14401. }
  14402. exports.classModule = { create: updateClass, update: updateClass };
  14403. exports.default = exports.classModule;
  14404. },{}]},{},[1])(1)
  14405. });
  14406. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy8ucmVnaXN0cnkubnBtanMub3JnL2Jyb3dzZXItcGFjay82LjAuMi9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwibW9kdWxlcy9jbGFzcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xuZnVuY3Rpb24gdXBkYXRlQ2xhc3Mob2xkVm5vZGUsIHZub2RlKSB7XG4gICAgdmFyIGN1ciwgbmFtZSwgZWxtID0gdm5vZGUuZWxtLCBvbGRDbGFzcyA9IG9sZFZub2RlLmRhdGEuY2xhc3MsIGtsYXNzID0gdm5vZGUuZGF0YS5jbGFzcztcbiAgICBpZiAoIW9sZENsYXNzICYmICFrbGFzcylcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmIChvbGRDbGFzcyA9PT0ga2xhc3MpXG4gICAgICAgIHJldHVybjtcbiAgICBvbGRDbGFzcyA9IG9sZENsYXNzIHx8IHt9O1xuICAgIGtsYXNzID0ga2xhc3MgfHwge307XG4gICAgZm9yIChuYW1lIGluIG9sZENsYXNzKSB7XG4gICAgICAgIGlmICgha2xhc3NbbmFtZV0pIHtcbiAgICAgICAgICAgIGVsbS5jbGFzc0xpc3QucmVtb3ZlKG5hbWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZvciAobmFtZSBpbiBrbGFzcykge1xuICAgICAgICBjdXIgPSBrbGFzc1tuYW1lXTtcbiAgICAgICAgaWYgKGN1ciAhPT0gb2xkQ2xhc3NbbmFtZV0pIHtcbiAgICAgICAgICAgIGVsbS5jbGFzc0xpc3RbY3VyID8gJ2FkZCcgOiAncmVtb3ZlJ10obmFtZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5leHBvcnRzLmNsYXNzTW9kdWxlID0geyBjcmVhdGU6IHVwZGF0ZUNsYXNzLCB1cGRhdGU6IHVwZGF0ZUNsYXNzIH07XG5leHBvcnRzLmRlZmF1bHQgPSBleHBvcnRzLmNsYXNzTW9kdWxlO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y2xhc3MuanMubWFwIl19
  14407. ;
  14408. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('snabbdom-dataset',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom_dataset = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  14409. "use strict";
  14410. Object.defineProperty(exports, "__esModule", { value: true });
  14411. var CAPS_REGEX = /[A-Z]/g;
  14412. function updateDataset(oldVnode, vnode) {
  14413. var elm = vnode.elm, oldDataset = oldVnode.data.dataset, dataset = vnode.data.dataset, key;
  14414. if (!oldDataset && !dataset)
  14415. return;
  14416. if (oldDataset === dataset)
  14417. return;
  14418. oldDataset = oldDataset || {};
  14419. dataset = dataset || {};
  14420. var d = elm.dataset;
  14421. for (key in oldDataset) {
  14422. if (!dataset[key]) {
  14423. if (d) {
  14424. if (key in d) {
  14425. delete d[key];
  14426. }
  14427. }
  14428. else {
  14429. elm.removeAttribute('data-' + key.replace(CAPS_REGEX, '-$&').toLowerCase());
  14430. }
  14431. }
  14432. }
  14433. for (key in dataset) {
  14434. if (oldDataset[key] !== dataset[key]) {
  14435. if (d) {
  14436. d[key] = dataset[key];
  14437. }
  14438. else {
  14439. elm.setAttribute('data-' + key.replace(CAPS_REGEX, '-$&').toLowerCase(), dataset[key]);
  14440. }
  14441. }
  14442. }
  14443. }
  14444. exports.datasetModule = { create: updateDataset, update: updateDataset };
  14445. exports.default = exports.datasetModule;
  14446. },{}]},{},[1])(1)
  14447. });
  14448. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJtb2R1bGVzL2RhdGFzZXQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIENBUFNfUkVHRVggPSAvW0EtWl0vZztcbmZ1bmN0aW9uIHVwZGF0ZURhdGFzZXQob2xkVm5vZGUsIHZub2RlKSB7XG4gICAgdmFyIGVsbSA9IHZub2RlLmVsbSwgb2xkRGF0YXNldCA9IG9sZFZub2RlLmRhdGEuZGF0YXNldCwgZGF0YXNldCA9IHZub2RlLmRhdGEuZGF0YXNldCwga2V5O1xuICAgIGlmICghb2xkRGF0YXNldCAmJiAhZGF0YXNldClcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmIChvbGREYXRhc2V0ID09PSBkYXRhc2V0KVxuICAgICAgICByZXR1cm47XG4gICAgb2xkRGF0YXNldCA9IG9sZERhdGFzZXQgfHwge307XG4gICAgZGF0YXNldCA9IGRhdGFzZXQgfHwge307XG4gICAgdmFyIGQgPSBlbG0uZGF0YXNldDtcbiAgICBmb3IgKGtleSBpbiBvbGREYXRhc2V0KSB7XG4gICAgICAgIGlmICghZGF0YXNldFtrZXldKSB7XG4gICAgICAgICAgICBpZiAoZCkge1xuICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gZCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZFtrZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGVsbS5yZW1vdmVBdHRyaWJ1dGUoJ2RhdGEtJyArIGtleS5yZXBsYWNlKENBUFNfUkVHRVgsICctJCYnKS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGtleSBpbiBkYXRhc2V0KSB7XG4gICAgICAgIGlmIChvbGREYXRhc2V0W2tleV0gIT09IGRhdGFzZXRba2V5XSkge1xuICAgICAgICAgICAgaWYgKGQpIHtcbiAgICAgICAgICAgICAgICBkW2tleV0gPSBkYXRhc2V0W2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbG0uc2V0QXR0cmlidXRlKCdkYXRhLScgKyBrZXkucmVwbGFjZShDQVBTX1JFR0VYLCAnLSQmJykudG9Mb3dlckNhc2UoKSwgZGF0YXNldFtrZXldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cbmV4cG9ydHMuZGF0YXNldE1vZHVsZSA9IHsgY3JlYXRlOiB1cGRhdGVEYXRhc2V0LCB1cGRhdGU6IHVwZGF0ZURhdGFzZXQgfTtcbmV4cG9ydHMuZGVmYXVsdCA9IGV4cG9ydHMuZGF0YXNldE1vZHVsZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGFzZXQuanMubWFwIl19
  14449. ;
  14450. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('snabbdom-props',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom_props = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  14451. "use strict";
  14452. Object.defineProperty(exports, "__esModule", { value: true });
  14453. function updateProps(oldVnode, vnode) {
  14454. var key, cur, old, elm = vnode.elm, oldProps = oldVnode.data.props, props = vnode.data.props;
  14455. if (!oldProps && !props)
  14456. return;
  14457. if (oldProps === props)
  14458. return;
  14459. oldProps = oldProps || {};
  14460. props = props || {};
  14461. for (key in oldProps) {
  14462. if (!props[key]) {
  14463. delete elm[key];
  14464. }
  14465. }
  14466. for (key in props) {
  14467. cur = props[key];
  14468. old = oldProps[key];
  14469. if (old !== cur && (key !== 'value' || elm[key] !== cur)) {
  14470. elm[key] = cur;
  14471. }
  14472. }
  14473. }
  14474. exports.propsModule = { create: updateProps, update: updateProps };
  14475. exports.default = exports.propsModule;
  14476. },{}]},{},[1])(1)
  14477. });
  14478. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy8ucmVnaXN0cnkubnBtanMub3JnL2Jyb3dzZXItcGFjay82LjAuMi9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwibW9kdWxlcy9wcm9wcy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiB1cGRhdGVQcm9wcyhvbGRWbm9kZSwgdm5vZGUpIHtcbiAgICB2YXIga2V5LCBjdXIsIG9sZCwgZWxtID0gdm5vZGUuZWxtLCBvbGRQcm9wcyA9IG9sZFZub2RlLmRhdGEucHJvcHMsIHByb3BzID0gdm5vZGUuZGF0YS5wcm9wcztcbiAgICBpZiAoIW9sZFByb3BzICYmICFwcm9wcylcbiAgICAgICAgcmV0dXJuO1xuICAgIGlmIChvbGRQcm9wcyA9PT0gcHJvcHMpXG4gICAgICAgIHJldHVybjtcbiAgICBvbGRQcm9wcyA9IG9sZFByb3BzIHx8IHt9O1xuICAgIHByb3BzID0gcHJvcHMgfHwge307XG4gICAgZm9yIChrZXkgaW4gb2xkUHJvcHMpIHtcbiAgICAgICAgaWYgKCFwcm9wc1trZXldKSB7XG4gICAgICAgICAgICBkZWxldGUgZWxtW2tleV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChrZXkgaW4gcHJvcHMpIHtcbiAgICAgICAgY3VyID0gcHJvcHNba2V5XTtcbiAgICAgICAgb2xkID0gb2xkUHJvcHNba2V5XTtcbiAgICAgICAgaWYgKG9sZCAhPT0gY3VyICYmIChrZXkgIT09ICd2YWx1ZScgfHwgZWxtW2tleV0gIT09IGN1cikpIHtcbiAgICAgICAgICAgIGVsbVtrZXldID0gY3VyO1xuICAgICAgICB9XG4gICAgfVxufVxuZXhwb3J0cy5wcm9wc01vZHVsZSA9IHsgY3JlYXRlOiB1cGRhdGVQcm9wcywgdXBkYXRlOiB1cGRhdGVQcm9wcyB9O1xuZXhwb3J0cy5kZWZhdWx0ID0gZXhwb3J0cy5wcm9wc01vZHVsZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXByb3BzLmpzLm1hcCJdfQ==
  14479. ;
  14480. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('snabbdom-style',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.snabbdom_style = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  14481. "use strict";
  14482. Object.defineProperty(exports, "__esModule", { value: true });
  14483. var raf = (typeof window !== 'undefined' && window.requestAnimationFrame) || setTimeout;
  14484. var nextFrame = function (fn) { raf(function () { raf(fn); }); };
  14485. function setNextFrame(obj, prop, val) {
  14486. nextFrame(function () { obj[prop] = val; });
  14487. }
  14488. function updateStyle(oldVnode, vnode) {
  14489. var cur, name, elm = vnode.elm, oldStyle = oldVnode.data.style, style = vnode.data.style;
  14490. if (!oldStyle && !style)
  14491. return;
  14492. if (oldStyle === style)
  14493. return;
  14494. oldStyle = oldStyle || {};
  14495. style = style || {};
  14496. var oldHasDel = 'delayed' in oldStyle;
  14497. for (name in oldStyle) {
  14498. if (!style[name]) {
  14499. if (name[0] === '-' && name[1] === '-') {
  14500. elm.style.removeProperty(name);
  14501. }
  14502. else {
  14503. elm.style[name] = '';
  14504. }
  14505. }
  14506. }
  14507. for (name in style) {
  14508. cur = style[name];
  14509. if (name === 'delayed' && style.delayed) {
  14510. for (var name2 in style.delayed) {
  14511. cur = style.delayed[name2];
  14512. if (!oldHasDel || cur !== oldStyle.delayed[name2]) {
  14513. setNextFrame(elm.style, name2, cur);
  14514. }
  14515. }
  14516. }
  14517. else if (name !== 'remove' && cur !== oldStyle[name]) {
  14518. if (name[0] === '-' && name[1] === '-') {
  14519. elm.style.setProperty(name, cur);
  14520. }
  14521. else {
  14522. elm.style[name] = cur;
  14523. }
  14524. }
  14525. }
  14526. }
  14527. function applyDestroyStyle(vnode) {
  14528. var style, name, elm = vnode.elm, s = vnode.data.style;
  14529. if (!s || !(style = s.destroy))
  14530. return;
  14531. for (name in style) {
  14532. elm.style[name] = style[name];
  14533. }
  14534. }
  14535. function applyRemoveStyle(vnode, rm) {
  14536. var s = vnode.data.style;
  14537. if (!s || !s.remove) {
  14538. rm();
  14539. return;
  14540. }
  14541. var name, elm = vnode.elm, i = 0, compStyle, style = s.remove, amount = 0, applied = [];
  14542. for (name in style) {
  14543. applied.push(name);
  14544. elm.style[name] = style[name];
  14545. }
  14546. compStyle = getComputedStyle(elm);
  14547. var props = compStyle['transition-property'].split(', ');
  14548. for (; i < props.length; ++i) {
  14549. if (applied.indexOf(props[i]) !== -1)
  14550. amount++;
  14551. }
  14552. elm.addEventListener('transitionend', function (ev) {
  14553. if (ev.target === elm)
  14554. --amount;
  14555. if (amount === 0)
  14556. rm();
  14557. });
  14558. }
  14559. exports.styleModule = {
  14560. create: updateStyle,
  14561. update: updateStyle,
  14562. destroy: applyDestroyStyle,
  14563. remove: applyRemoveStyle
  14564. };
  14565. exports.default = exports.styleModule;
  14566. },{}]},{},[1])(1)
  14567. });
  14568. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy8ucmVnaXN0cnkubnBtanMub3JnL2Jyb3dzZXItcGFjay82LjAuMi9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwibW9kdWxlcy9zdHlsZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG52YXIgcmFmID0gKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHx8IHNldFRpbWVvdXQ7XG52YXIgbmV4dEZyYW1lID0gZnVuY3Rpb24gKGZuKSB7IHJhZihmdW5jdGlvbiAoKSB7IHJhZihmbik7IH0pOyB9O1xuZnVuY3Rpb24gc2V0TmV4dEZyYW1lKG9iaiwgcHJvcCwgdmFsKSB7XG4gICAgbmV4dEZyYW1lKGZ1bmN0aW9uICgpIHsgb2JqW3Byb3BdID0gdmFsOyB9KTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZVN0eWxlKG9sZFZub2RlLCB2bm9kZSkge1xuICAgIHZhciBjdXIsIG5hbWUsIGVsbSA9IHZub2RlLmVsbSwgb2xkU3R5bGUgPSBvbGRWbm9kZS5kYXRhLnN0eWxlLCBzdHlsZSA9IHZub2RlLmRhdGEuc3R5bGU7XG4gICAgaWYgKCFvbGRTdHlsZSAmJiAhc3R5bGUpXG4gICAgICAgIHJldHVybjtcbiAgICBpZiAob2xkU3R5bGUgPT09IHN0eWxlKVxuICAgICAgICByZXR1cm47XG4gICAgb2xkU3R5bGUgPSBvbGRTdHlsZSB8fCB7fTtcbiAgICBzdHlsZSA9IHN0eWxlIHx8IHt9O1xuICAgIHZhciBvbGRIYXNEZWwgPSAnZGVsYXllZCcgaW4gb2xkU3R5bGU7XG4gICAgZm9yIChuYW1lIGluIG9sZFN0eWxlKSB7XG4gICAgICAgIGlmICghc3R5bGVbbmFtZV0pIHtcbiAgICAgICAgICAgIGlmIChuYW1lWzBdID09PSAnLScgJiYgbmFtZVsxXSA9PT0gJy0nKSB7XG4gICAgICAgICAgICAgICAgZWxtLnN0eWxlLnJlbW92ZVByb3BlcnR5KG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZWxtLnN0eWxlW25hbWVdID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZm9yIChuYW1lIGluIHN0eWxlKSB7XG4gICAgICAgIGN1ciA9IHN0eWxlW25hbWVdO1xuICAgICAgICBpZiAobmFtZSA9PT0gJ2RlbGF5ZWQnICYmIHN0eWxlLmRlbGF5ZWQpIHtcbiAgICAgICAgICAgIGZvciAodmFyIG5hbWUyIGluIHN0eWxlLmRlbGF5ZWQpIHtcbiAgICAgICAgICAgICAgICBjdXIgPSBzdHlsZS5kZWxheWVkW25hbWUyXTtcbiAgICAgICAgICAgICAgICBpZiAoIW9sZEhhc0RlbCB8fCBjdXIgIT09IG9sZFN0eWxlLmRlbGF5ZWRbbmFtZTJdKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldE5leHRGcmFtZShlbG0uc3R5bGUsIG5hbWUyLCBjdXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChuYW1lICE9PSAncmVtb3ZlJyAmJiBjdXIgIT09IG9sZFN0eWxlW25hbWVdKSB7XG4gICAgICAgICAgICBpZiAobmFtZVswXSA9PT0gJy0nICYmIG5hbWVbMV0gPT09ICctJykge1xuICAgICAgICAgICAgICAgIGVsbS5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCBjdXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZWxtLnN0eWxlW25hbWVdID0gY3VyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gYXBwbHlEZXN0cm95U3R5bGUodm5vZGUpIHtcbiAgICB2YXIgc3R5bGUsIG5hbWUsIGVsbSA9IHZub2RlLmVsbSwgcyA9IHZub2RlLmRhdGEuc3R5bGU7XG4gICAgaWYgKCFzIHx8ICEoc3R5bGUgPSBzLmRlc3Ryb3kpKVxuICAgICAgICByZXR1cm47XG4gICAgZm9yIChuYW1lIGluIHN0eWxlKSB7XG4gICAgICAgIGVsbS5zdHlsZVtuYW1lXSA9IHN0eWxlW25hbWVdO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGFwcGx5UmVtb3ZlU3R5bGUodm5vZGUsIHJtKSB7XG4gICAgdmFyIHMgPSB2bm9kZS5kYXRhLnN0eWxlO1xuICAgIGlmICghcyB8fCAhcy5yZW1vdmUpIHtcbiAgICAgICAgcm0oKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgbmFtZSwgZWxtID0gdm5vZGUuZWxtLCBpID0gMCwgY29tcFN0eWxlLCBzdHlsZSA9IHMucmVtb3ZlLCBhbW91bnQgPSAwLCBhcHBsaWVkID0gW107XG4gICAgZm9yIChuYW1lIGluIHN0eWxlKSB7XG4gICAgICAgIGFwcGxpZWQucHVzaChuYW1lKTtcbiAgICAgICAgZWxtLnN0eWxlW25hbWVdID0gc3R5bGVbbmFtZV07XG4gICAgfVxuICAgIGNvbXBTdHlsZSA9IGdldENvbXB1dGVkU3R5bGUoZWxtKTtcbiAgICB2YXIgcHJvcHMgPSBjb21wU3R5bGVbJ3RyYW5zaXRpb24tcHJvcGVydHknXS5zcGxpdCgnLCAnKTtcbiAgICBmb3IgKDsgaSA8IHByb3BzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChhcHBsaWVkLmluZGV4T2YocHJvcHNbaV0pICE9PSAtMSlcbiAgICAgICAgICAgIGFtb3VudCsrO1xuICAgIH1cbiAgICBlbG0uYWRkRXZlbnRMaXN0ZW5lcigndHJhbnNpdGlvbmVuZCcsIGZ1bmN0aW9uIChldikge1xuICAgICAgICBpZiAoZXYudGFyZ2V0ID09PSBlbG0pXG4gICAgICAgICAgICAtLWFtb3VudDtcbiAgICAgICAgaWYgKGFtb3VudCA9PT0gMClcbiAgICAgICAgICAgIHJtKCk7XG4gICAgfSk7XG59XG5leHBvcnRzLnN0eWxlTW9kdWxlID0ge1xuICAgIGNyZWF0ZTogdXBkYXRlU3R5bGUsXG4gICAgdXBkYXRlOiB1cGRhdGVTdHlsZSxcbiAgICBkZXN0cm95OiBhcHBseURlc3Ryb3lTdHlsZSxcbiAgICByZW1vdmU6IGFwcGx5UmVtb3ZlU3R5bGVcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBleHBvcnRzLnN0eWxlTW9kdWxlO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3R5bGUuanMubWFwIl19
  14569. ;
  14570. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define('tovnode',[],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.tovnode = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  14571. "use strict";
  14572. Object.defineProperty(exports, "__esModule", { value: true });
  14573. function createElement(tagName) {
  14574. return document.createElement(tagName);
  14575. }
  14576. function createElementNS(namespaceURI, qualifiedName) {
  14577. return document.createElementNS(namespaceURI, qualifiedName);
  14578. }
  14579. function createTextNode(text) {
  14580. return document.createTextNode(text);
  14581. }
  14582. function createComment(text) {
  14583. return document.createComment(text);
  14584. }
  14585. function insertBefore(parentNode, newNode, referenceNode) {
  14586. parentNode.insertBefore(newNode, referenceNode);
  14587. }
  14588. function removeChild(node, child) {
  14589. node.removeChild(child);
  14590. }
  14591. function appendChild(node, child) {
  14592. node.appendChild(child);
  14593. }
  14594. function parentNode(node) {
  14595. return node.parentNode;
  14596. }
  14597. function nextSibling(node) {
  14598. return node.nextSibling;
  14599. }
  14600. function tagName(elm) {
  14601. return elm.tagName;
  14602. }
  14603. function setTextContent(node, text) {
  14604. node.textContent = text;
  14605. }
  14606. function getTextContent(node) {
  14607. return node.textContent;
  14608. }
  14609. function isElement(node) {
  14610. return node.nodeType === 1;
  14611. }
  14612. function isText(node) {
  14613. return node.nodeType === 3;
  14614. }
  14615. function isComment(node) {
  14616. return node.nodeType === 8;
  14617. }
  14618. exports.htmlDomApi = {
  14619. createElement: createElement,
  14620. createElementNS: createElementNS,
  14621. createTextNode: createTextNode,
  14622. createComment: createComment,
  14623. insertBefore: insertBefore,
  14624. removeChild: removeChild,
  14625. appendChild: appendChild,
  14626. parentNode: parentNode,
  14627. nextSibling: nextSibling,
  14628. tagName: tagName,
  14629. setTextContent: setTextContent,
  14630. getTextContent: getTextContent,
  14631. isElement: isElement,
  14632. isText: isText,
  14633. isComment: isComment,
  14634. };
  14635. exports.default = exports.htmlDomApi;
  14636. },{}],2:[function(require,module,exports){
  14637. "use strict";
  14638. Object.defineProperty(exports, "__esModule", { value: true });
  14639. var vnode_1 = require("./vnode");
  14640. var htmldomapi_1 = require("./htmldomapi");
  14641. function toVNode(node, domApi) {
  14642. var api = domApi !== undefined ? domApi : htmldomapi_1.default;
  14643. var text;
  14644. if (api.isElement(node)) {
  14645. var id = node.id ? '#' + node.id : '';
  14646. var cn = node.getAttribute('class');
  14647. var c = cn ? '.' + cn.split(' ').join('.') : '';
  14648. var sel = api.tagName(node).toLowerCase() + id + c;
  14649. var attrs = {};
  14650. var children = [];
  14651. var name_1;
  14652. var i = void 0, n = void 0;
  14653. var elmAttrs = node.attributes;
  14654. var elmChildren = node.childNodes;
  14655. for (i = 0, n = elmAttrs.length; i < n; i++) {
  14656. name_1 = elmAttrs[i].nodeName;
  14657. if (name_1 !== 'id' && name_1 !== 'class') {
  14658. attrs[name_1] = elmAttrs[i].nodeValue;
  14659. }
  14660. }
  14661. for (i = 0, n = elmChildren.length; i < n; i++) {
  14662. children.push(toVNode(elmChildren[i]));
  14663. }
  14664. return vnode_1.default(sel, { attrs: attrs }, children, undefined, node);
  14665. }
  14666. else if (api.isText(node)) {
  14667. text = api.getTextContent(node);
  14668. return vnode_1.default(undefined, undefined, undefined, text, node);
  14669. }
  14670. else if (api.isComment(node)) {
  14671. text = api.getTextContent(node);
  14672. return vnode_1.default('!', {}, [], text, node);
  14673. }
  14674. else {
  14675. return vnode_1.default('', {}, [], undefined, undefined);
  14676. }
  14677. }
  14678. exports.toVNode = toVNode;
  14679. exports.default = toVNode;
  14680. },{"./htmldomapi":1,"./vnode":3}],3:[function(require,module,exports){
  14681. "use strict";
  14682. Object.defineProperty(exports, "__esModule", { value: true });
  14683. function vnode(sel, data, children, text, elm) {
  14684. var key = data === undefined ? undefined : data.key;
  14685. return { sel: sel, data: data, children: children,
  14686. text: text, elm: elm, key: key };
  14687. }
  14688. exports.vnode = vnode;
  14689. exports.default = vnode;
  14690. },{}]},{},[2])(2)
  14691. });
  14692. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy8ucmVnaXN0cnkubnBtanMub3JnL2Jyb3dzZXItcGFjay82LjAuMi9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiaHRtbGRvbWFwaS5qcyIsInRvdm5vZGUuanMiLCJ2bm9kZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiBjcmVhdGVFbGVtZW50KHRhZ05hbWUpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWdOYW1lKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnROUyhuYW1lc3BhY2VVUkksIHF1YWxpZmllZE5hbWUpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKG5hbWVzcGFjZVVSSSwgcXVhbGlmaWVkTmFtZSk7XG59XG5mdW5jdGlvbiBjcmVhdGVUZXh0Tm9kZSh0ZXh0KSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHRleHQpO1xufVxuZnVuY3Rpb24gY3JlYXRlQ29tbWVudCh0ZXh0KSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQodGV4dCk7XG59XG5mdW5jdGlvbiBpbnNlcnRCZWZvcmUocGFyZW50Tm9kZSwgbmV3Tm9kZSwgcmVmZXJlbmNlTm9kZSkge1xuICAgIHBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKG5ld05vZGUsIHJlZmVyZW5jZU5vZGUpO1xufVxuZnVuY3Rpb24gcmVtb3ZlQ2hpbGQobm9kZSwgY2hpbGQpIHtcbiAgICBub2RlLnJlbW92ZUNoaWxkKGNoaWxkKTtcbn1cbmZ1bmN0aW9uIGFwcGVuZENoaWxkKG5vZGUsIGNoaWxkKSB7XG4gICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZCk7XG59XG5mdW5jdGlvbiBwYXJlbnROb2RlKG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS5wYXJlbnROb2RlO1xufVxuZnVuY3Rpb24gbmV4dFNpYmxpbmcobm9kZSkge1xuICAgIHJldHVybiBub2RlLm5leHRTaWJsaW5nO1xufVxuZnVuY3Rpb24gdGFnTmFtZShlbG0pIHtcbiAgICByZXR1cm4gZWxtLnRhZ05hbWU7XG59XG5mdW5jdGlvbiBzZXRUZXh0Q29udGVudChub2RlLCB0ZXh0KSB7XG4gICAgbm9kZS50ZXh0Q29udGVudCA9IHRleHQ7XG59XG5mdW5jdGlvbiBnZXRUZXh0Q29udGVudChub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUudGV4dENvbnRlbnQ7XG59XG5mdW5jdGlvbiBpc0VsZW1lbnQobm9kZSkge1xuICAgIHJldHVybiBub2RlLm5vZGVUeXBlID09PSAxO1xufVxuZnVuY3Rpb24gaXNUZXh0KG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS5ub2RlVHlwZSA9PT0gMztcbn1cbmZ1bmN0aW9uIGlzQ29tbWVudChub2RlKSB7XG4gICAgcmV0dXJuIG5vZGUubm9kZVR5cGUgPT09IDg7XG59XG5leHBvcnRzLmh0bWxEb21BcGkgPSB7XG4gICAgY3JlYXRlRWxlbWVudDogY3JlYXRlRWxlbWVudCxcbiAgICBjcmVhdGVFbGVtZW50TlM6IGNyZWF0ZUVsZW1lbnROUyxcbiAgICBjcmVhdGVUZXh0Tm9kZTogY3JlYXRlVGV4dE5vZGUsXG4gICAgY3JlYXRlQ29tbWVudDogY3JlYXRlQ29tbWVudCxcbiAgICBpbnNlcnRCZWZvcmU6IGluc2VydEJlZm9yZSxcbiAgICByZW1vdmVDaGlsZDogcmVtb3ZlQ2hpbGQsXG4gICAgYXBwZW5kQ2hpbGQ6IGFwcGVuZENoaWxkLFxuICAgIHBhcmVudE5vZGU6IHBhcmVudE5vZGUsXG4gICAgbmV4dFNpYmxpbmc6IG5leHRTaWJsaW5nLFxuICAgIHRhZ05hbWU6IHRhZ05hbWUsXG4gICAgc2V0VGV4dENvbnRlbnQ6IHNldFRleHRDb250ZW50LFxuICAgIGdldFRleHRDb250ZW50OiBnZXRUZXh0Q29udGVudCxcbiAgICBpc0VsZW1lbnQ6IGlzRWxlbWVudCxcbiAgICBpc1RleHQ6IGlzVGV4dCxcbiAgICBpc0NvbW1lbnQ6IGlzQ29tbWVudCxcbn07XG5leHBvcnRzLmRlZmF1bHQgPSBleHBvcnRzLmh0bWxEb21BcGk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1odG1sZG9tYXBpLmpzLm1hcCIsIlwidXNlIHN0cmljdFwiO1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7IHZhbHVlOiB0cnVlIH0pO1xudmFyIHZub2RlXzEgPSByZXF1aXJlKFwiLi92bm9kZVwiKTtcbnZhciBodG1sZG9tYXBpXzEgPSByZXF1aXJlKFwiLi9odG1sZG9tYXBpXCIpO1xuZnVuY3Rpb24gdG9WTm9kZShub2RlLCBkb21BcGkpIHtcbiAgICB2YXIgYXBpID0gZG9tQXBpICE9PSB1bmRlZmluZWQgPyBkb21BcGkgOiBodG1sZG9tYXBpXzEuZGVmYXVsdDtcbiAgICB2YXIgdGV4dDtcbiAgICBpZiAoYXBpLmlzRWxlbWVudChub2RlKSkge1xuICAgICAgICB2YXIgaWQgPSBub2RlLmlkID8gJyMnICsgbm9kZS5pZCA6ICcnO1xuICAgICAgICB2YXIgY24gPSBub2RlLmdldEF0dHJpYnV0ZSgnY2xhc3MnKTtcbiAgICAgICAgdmFyIGMgPSBjbiA/ICcuJyArIGNuLnNwbGl0KCcgJykuam9pbignLicpIDogJyc7XG4gICAgICAgIHZhciBzZWwgPSBhcGkudGFnTmFtZShub2RlKS50b0xvd2VyQ2FzZSgpICsgaWQgKyBjO1xuICAgICAgICB2YXIgYXR0cnMgPSB7fTtcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gW107XG4gICAgICAgIHZhciBuYW1lXzE7XG4gICAgICAgIHZhciBpID0gdm9pZCAwLCBuID0gdm9pZCAwO1xuICAgICAgICB2YXIgZWxtQXR0cnMgPSBub2RlLmF0dHJpYnV0ZXM7XG4gICAgICAgIHZhciBlbG1DaGlsZHJlbiA9IG5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgZm9yIChpID0gMCwgbiA9IGVsbUF0dHJzLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgbmFtZV8xID0gZWxtQXR0cnNbaV0ubm9kZU5hbWU7XG4gICAgICAgICAgICBpZiAobmFtZV8xICE9PSAnaWQnICYmIG5hbWVfMSAhPT0gJ2NsYXNzJykge1xuICAgICAgICAgICAgICAgIGF0dHJzW25hbWVfMV0gPSBlbG1BdHRyc1tpXS5ub2RlVmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMCwgbiA9IGVsbUNoaWxkcmVuLmxlbmd0aDsgaSA8IG47IGkrKykge1xuICAgICAgICAgICAgY2hpbGRyZW4ucHVzaCh0b1ZOb2RlKGVsbUNoaWxkcmVuW2ldKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZub2RlXzEuZGVmYXVsdChzZWwsIHsgYXR0cnM6IGF0dHJzIH0sIGNoaWxkcmVuLCB1bmRlZmluZWQsIG5vZGUpO1xuICAgIH1cbiAgICBlbHNlIGlmIChhcGkuaXNUZXh0KG5vZGUpKSB7XG4gICAgICAgIHRleHQgPSBhcGkuZ2V0VGV4dENvbnRlbnQobm9kZSk7XG4gICAgICAgIHJldHVybiB2bm9kZV8xLmRlZmF1bHQodW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdGV4dCwgbm9kZSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGFwaS5pc0NvbW1lbnQobm9kZSkpIHtcbiAgICAgICAgdGV4dCA9IGFwaS5nZXRUZXh0Q29udGVudChub2RlKTtcbiAgICAgICAgcmV0dXJuIHZub2RlXzEuZGVmYXVsdCgnIScsIHt9LCBbXSwgdGV4dCwgbm9kZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gdm5vZGVfMS5kZWZhdWx0KCcnLCB7fSwgW10sIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcbiAgICB9XG59XG5leHBvcnRzLnRvVk5vZGUgPSB0b1ZOb2RlO1xuZXhwb3J0cy5kZWZhdWx0ID0gdG9WTm9kZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXRvdm5vZGUuanMubWFwIiwiXCJ1c2Ugc3RyaWN0XCI7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHsgdmFsdWU6IHRydWUgfSk7XG5mdW5jdGlvbiB2bm9kZShzZWwsIGRhdGEsIGNoaWxkcmVuLCB0ZXh0LCBlbG0pIHtcbiAgICB2YXIga2V5ID0gZGF0YSA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogZGF0YS5rZXk7XG4gICAgcmV0dXJuIHsgc2VsOiBzZWwsIGRhdGE6IGRhdGEsIGNoaWxkcmVuOiBjaGlsZHJlbixcbiAgICAgICAgdGV4dDogdGV4dCwgZWxtOiBlbG0sIGtleToga2V5IH07XG59XG5leHBvcnRzLnZub2RlID0gdm5vZGU7XG5leHBvcnRzLmRlZmF1bHQgPSB2bm9kZTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXZub2RlLmpzLm1hcCJdfQ==
  14693. ;
  14694. function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  14695. /*!
  14696. * Backbone.VDOMView
  14697. *
  14698. * MIT Licensed. Copyright (c) 2017, JC Brand <jc@opkode.com>
  14699. */
  14700. (function (root, factory) {
  14701. if (typeof define === 'function' && define.amd) {
  14702. define('backbone.vdomview',["snabbdom", "snabbdom-attributes", "snabbdom-class", "snabbdom-dataset", "snabbdom-props", "snabbdom-style", "tovnode", "underscore", "backbone"], factory);
  14703. } else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === 'object' && module.exports) {
  14704. // CommonJS-like environments
  14705. module.exports = factory(require('snabbdom'), require('snabbdom-attributes'), require('snabbdom-class'), require('snabbdom-dataset'), require('snabbdom-props'), require('snabbdom-style'), require('tovnode'), require('underscore'), require('backbone'));
  14706. }
  14707. })(void 0, function (snabbdom, snabbdom_attributes, snabbdom_class, snabbdom_dataset, snabbdom_props, snabbdom_style, tovnode, _, Backbone) {
  14708. "use strict";
  14709. var domParser = new DOMParser();
  14710. var patch = snabbdom.init([snabbdom_attributes.default, snabbdom_class.default, snabbdom_dataset.default, snabbdom_props.default, snabbdom_style.default]);
  14711. var View = _.isUndefined(Backbone.NativeView) ? Backbone.View : Backbone.NativeView;
  14712. function parseHTMLToDOM(html_str) {
  14713. /* Parses a string with HTML and returns a DOM element.
  14714. *
  14715. * Forked from vdom_parser:
  14716. * https://github.com/bitinn/vdom-parser
  14717. */
  14718. if (typeof html_str !== 'string') {
  14719. throw new Error('Invalid parameter type in parseHTMLToDOM');
  14720. }
  14721. if (!('DOMParser' in window)) {
  14722. throw new Error('DOMParser is not available, ' + 'so parsing string to DOM node is not possible.');
  14723. }
  14724. if (!html_str) {
  14725. return document.createTextNode('');
  14726. }
  14727. domParser = domParser || new DOMParser();
  14728. var doc = domParser.parseFromString(html_str, 'text/html'); // most tags default to body
  14729. if (doc.body.firstChild) {
  14730. return doc.getElementsByTagName('body')[0].firstChild; // some tags, like script and style, default to head
  14731. } else if (doc.head.firstChild && (doc.head.firstChild.tagName !== 'TITLE' || doc.title)) {
  14732. return doc.head.firstChild; // special case for html comment, cdata, doctype
  14733. } else if (doc.firstChild && doc.firstChild.tagName !== 'HTML') {
  14734. return doc.firstChild; // other element, such as whitespace, or html/body/head tag, fallback to empty text node
  14735. } else {
  14736. return document.createTextNode('');
  14737. }
  14738. }
  14739. Backbone.VDOMView = View.extend({
  14740. updateEventListeners: function updateEventListeners(old_vnode, new_vnode) {
  14741. this.setElement(new_vnode.elm);
  14742. },
  14743. render: function render() {
  14744. if (_.isFunction(this.beforeRender)) {
  14745. this.beforeRender();
  14746. }
  14747. var new_vnode = tovnode.toVNode(parseHTMLToDOM(this.toHTML()));
  14748. new_vnode.data.hook = _.extend({
  14749. create: this.updateEventListeners.bind(this),
  14750. update: this.updateEventListeners.bind(this)
  14751. });
  14752. var el = this.vnode ? this.vnode.elm : this.el;
  14753. if (el.outerHTML !== new_vnode.elm.outerHTML) {
  14754. this.vnode = patch(this.vnode || this.el, new_vnode);
  14755. }
  14756. if (_.isFunction(this.afterRender)) {
  14757. this.afterRender();
  14758. }
  14759. return this;
  14760. }
  14761. });
  14762. return Backbone.VDOMView;
  14763. });
  14764. //# sourceMappingURL=backbone.vdomview.js.map;
  14765. (function (root, factory) {
  14766. if (typeof define === 'function' && define.amd) {
  14767. define('converse-modal',[
  14768. "converse-core",
  14769. "bootstrap",
  14770. "underscore",
  14771. "backbone",
  14772. "backbone.vdomview"
  14773. ], factory);
  14774. }
  14775. }(this, function (converse, bootstrap, _, Backbone) {
  14776. "use strict";
  14777. converse.plugins.add('converse-modal', {
  14778. initialize () {
  14779. const { _converse } = this;
  14780. _converse.BootstrapModal = Backbone.VDOMView.extend({
  14781. initialize () {
  14782. this.render().insertIntoDOM();
  14783. this.modal = new bootstrap.Modal(this.el, {
  14784. backdrop: 'static',
  14785. keyboard: true
  14786. });
  14787. this.el.addEventListener('hide.bs.modal', (event) => {
  14788. if (!_.isNil(this.trigger_el)) {
  14789. this.trigger_el.classList.remove('selected');
  14790. }
  14791. }, false);
  14792. },
  14793. insertIntoDOM () {
  14794. const container_el = _converse.chatboxviews.el.querySelector("#converse-modals");
  14795. container_el.insertAdjacentElement('beforeEnd', this.el);
  14796. },
  14797. show (ev) {
  14798. ev.preventDefault();
  14799. this.trigger_el = ev.target;
  14800. this.trigger_el.classList.add('selected');
  14801. this.modal.show();
  14802. }
  14803. });
  14804. }
  14805. });
  14806. }));
  14807. // Converse.js (A browser based XMPP chat client)
  14808. // http://conversejs.org
  14809. //
  14810. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  14811. // Licensed under the Mozilla Public License (MPLv2)
  14812. //
  14813. /*global define */
  14814. (function (root, factory) {
  14815. define('converse-rosterview',["converse-core", "tpl!add_contact_modal", "tpl!group_header", "tpl!pending_contact", "tpl!requesting_contact", "tpl!roster", "tpl!roster_filter", "tpl!roster_item", "tpl!search_contact", "converse-chatboxes", "converse-modal"], factory);
  14816. })(void 0, function (converse, tpl_add_contact_modal, tpl_group_header, tpl_pending_contact, tpl_requesting_contact, tpl_roster, tpl_roster_filter, tpl_roster_item, tpl_search_contact) {
  14817. "use strict";
  14818. var _converse$env = converse.env,
  14819. Backbone = _converse$env.Backbone,
  14820. Strophe = _converse$env.Strophe,
  14821. $iq = _converse$env.$iq,
  14822. b64_sha1 = _converse$env.b64_sha1,
  14823. sizzle = _converse$env.sizzle,
  14824. _ = _converse$env._;
  14825. var u = converse.env.utils;
  14826. converse.plugins.add('converse-rosterview', {
  14827. dependencies: ["converse-modal"],
  14828. overrides: {
  14829. // Overrides mentioned here will be picked up by converse.js's
  14830. // plugin architecture they will replace existing methods on the
  14831. // relevant objects or classes.
  14832. //
  14833. // New functions which don't exist yet can also be added.
  14834. afterReconnected: function afterReconnected() {
  14835. this.__super__.afterReconnected.apply(this, arguments);
  14836. },
  14837. _tearDown: function _tearDown() {
  14838. /* Remove the rosterview when tearing down. It gets created
  14839. * anew when reconnecting or logging in.
  14840. */
  14841. this.__super__._tearDown.apply(this, arguments);
  14842. if (!_.isUndefined(this.rosterview)) {
  14843. this.rosterview.remove();
  14844. }
  14845. },
  14846. RosterGroups: {
  14847. comparator: function comparator() {
  14848. // RosterGroupsComparator only gets set later (once i18n is
  14849. // set up), so we need to wrap it in this nameless function.
  14850. var _converse = this.__super__._converse;
  14851. return _converse.RosterGroupsComparator.apply(this, arguments);
  14852. }
  14853. }
  14854. },
  14855. initialize: function initialize() {
  14856. /* The initialize function gets called as soon as the plugin is
  14857. * loaded by converse.js's plugin machinery.
  14858. */
  14859. var _converse = this._converse,
  14860. __ = _converse.__;
  14861. _converse.api.settings.update({
  14862. allow_chat_pending_contacts: true,
  14863. allow_contact_removal: true,
  14864. show_toolbar: true
  14865. });
  14866. _converse.api.promises.add('rosterViewInitialized');
  14867. var STATUSES = {
  14868. 'dnd': __('This contact is busy'),
  14869. 'online': __('This contact is online'),
  14870. 'offline': __('This contact is offline'),
  14871. 'unavailable': __('This contact is unavailable'),
  14872. 'xa': __('This contact is away for an extended period'),
  14873. 'away': __('This contact is away')
  14874. };
  14875. var LABEL_CONTACTS = __('Contacts');
  14876. var LABEL_GROUPS = __('Groups');
  14877. var HEADER_CURRENT_CONTACTS = __('My contacts');
  14878. var HEADER_PENDING_CONTACTS = __('Pending contacts');
  14879. var HEADER_REQUESTING_CONTACTS = __('Contact requests');
  14880. var HEADER_UNGROUPED = __('Ungrouped');
  14881. var HEADER_WEIGHTS = {};
  14882. HEADER_WEIGHTS[HEADER_REQUESTING_CONTACTS] = 0;
  14883. HEADER_WEIGHTS[HEADER_CURRENT_CONTACTS] = 1;
  14884. HEADER_WEIGHTS[HEADER_UNGROUPED] = 2;
  14885. HEADER_WEIGHTS[HEADER_PENDING_CONTACTS] = 3;
  14886. _converse.RosterGroupsComparator = function (a, b) {
  14887. /* Groups are sorted alphabetically, ignoring case.
  14888. * However, Ungrouped, Requesting Contacts and Pending Contacts
  14889. * appear last and in that order.
  14890. */
  14891. a = a.get('name');
  14892. b = b.get('name');
  14893. var special_groups = _.keys(HEADER_WEIGHTS);
  14894. var a_is_special = _.includes(special_groups, a);
  14895. var b_is_special = _.includes(special_groups, b);
  14896. if (!a_is_special && !b_is_special) {
  14897. return a.toLowerCase() < b.toLowerCase() ? -1 : a.toLowerCase() > b.toLowerCase() ? 1 : 0;
  14898. } else if (a_is_special && b_is_special) {
  14899. return HEADER_WEIGHTS[a] < HEADER_WEIGHTS[b] ? -1 : HEADER_WEIGHTS[a] > HEADER_WEIGHTS[b] ? 1 : 0;
  14900. } else if (!a_is_special && b_is_special) {
  14901. return b === HEADER_REQUESTING_CONTACTS ? 1 : -1;
  14902. } else if (a_is_special && !b_is_special) {
  14903. return a === HEADER_REQUESTING_CONTACTS ? -1 : 1;
  14904. }
  14905. };
  14906. _converse.AddContactModal = _converse.BootstrapModal.extend({
  14907. events: {
  14908. 'submit form': 'addContactFromForm',
  14909. 'submit form.search-xmpp-contact': 'searchContacts'
  14910. },
  14911. initialize: function initialize() {
  14912. _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
  14913. this.model.on('change', this.render, this);
  14914. },
  14915. toHTML: function toHTML() {
  14916. return tpl_add_contact_modal(_.extend(this.model.toJSON(), {
  14917. 'heading_new_contact': __('Add a Contact'),
  14918. 'label_xmpp_address': __('XMPP Address'),
  14919. 'label_nickname': __('Optional nickname'),
  14920. 'contact_placeholder': __('name@example.org'),
  14921. 'label_add': __('Add')
  14922. }));
  14923. },
  14924. addContactFromForm: function addContactFromForm(ev) {
  14925. ev.preventDefault();
  14926. var data = new FormData(ev.target),
  14927. jid = data.get('jid');
  14928. if (!jid || _.compact(jid.split('@')).length < 2) {
  14929. this.model.set({
  14930. 'error_message': __('Please enter a valid XMPP address'),
  14931. 'jid': jid
  14932. });
  14933. } else {
  14934. _converse.roster.addAndSubscribe(jid);
  14935. this.model.clear();
  14936. this.modal.hide();
  14937. }
  14938. }
  14939. });
  14940. _converse.RosterFilter = Backbone.Model.extend({
  14941. initialize: function initialize() {
  14942. this.set({
  14943. 'filter_text': '',
  14944. 'filter_type': 'contacts',
  14945. 'chat_state': ''
  14946. });
  14947. }
  14948. });
  14949. _converse.RosterFilterView = Backbone.VDOMView.extend({
  14950. tagName: 'form',
  14951. className: 'roster-filter-form',
  14952. events: {
  14953. "keydown .roster-filter": "liveFilter",
  14954. "submit form.roster-filter-form": "submitFilter",
  14955. "click .clear-input": "clearFilter",
  14956. "click .filter-by span": "changeTypeFilter",
  14957. "change .state-type": "changeChatStateFilter"
  14958. },
  14959. initialize: function initialize() {
  14960. this.model.on('change:filter_type', this.render, this);
  14961. this.model.on('change:filter_text', this.render, this);
  14962. },
  14963. toHTML: function toHTML() {
  14964. return tpl_roster_filter(_.extend(this.model.toJSON(), {
  14965. visible: this.shouldBeVisible(),
  14966. placeholder: __('Filter'),
  14967. title_contact_filter: __('Filter by contact name'),
  14968. title_group_filter: __('Filter by group name'),
  14969. title_status_filter: __('Filter by status'),
  14970. label_any: __('Any'),
  14971. label_unread_messages: __('Unread'),
  14972. label_online: __('Online'),
  14973. label_chatty: __('Chatty'),
  14974. label_busy: __('Busy'),
  14975. label_away: __('Away'),
  14976. label_xa: __('Extended Away'),
  14977. label_offline: __('Offline')
  14978. }));
  14979. },
  14980. changeChatStateFilter: function changeChatStateFilter(ev) {
  14981. if (ev && ev.preventDefault) {
  14982. ev.preventDefault();
  14983. }
  14984. this.model.save({
  14985. 'chat_state': this.el.querySelector('.state-type').value
  14986. });
  14987. },
  14988. changeTypeFilter: function changeTypeFilter(ev) {
  14989. if (ev && ev.preventDefault) {
  14990. ev.preventDefault();
  14991. }
  14992. var type = ev.target.dataset.type;
  14993. if (type === 'state') {
  14994. this.model.save({
  14995. 'filter_type': type,
  14996. 'chat_state': this.el.querySelector('.state-type').value
  14997. });
  14998. } else {
  14999. this.model.save({
  15000. 'filter_type': type,
  15001. 'filter_text': this.el.querySelector('.roster-filter').value
  15002. });
  15003. }
  15004. },
  15005. liveFilter: _.debounce(function (ev) {
  15006. this.model.save({
  15007. 'filter_text': this.el.querySelector('.roster-filter').value
  15008. });
  15009. }, 250),
  15010. submitFilter: function submitFilter(ev) {
  15011. if (ev && ev.preventDefault) {
  15012. ev.preventDefault();
  15013. }
  15014. this.liveFilter();
  15015. this.render();
  15016. },
  15017. isActive: function isActive() {
  15018. /* Returns true if the filter is enabled (i.e. if the user
  15019. * has added values to the filter).
  15020. */
  15021. if (this.model.get('filter_type') === 'state' || this.model.get('filter_text')) {
  15022. return true;
  15023. }
  15024. return false;
  15025. },
  15026. shouldBeVisible: function shouldBeVisible() {
  15027. return _converse.roster.length >= 5 || this.isActive();
  15028. },
  15029. showOrHide: function showOrHide() {
  15030. if (this.shouldBeVisible()) {
  15031. this.show();
  15032. } else {
  15033. this.hide();
  15034. }
  15035. },
  15036. show: function show() {
  15037. if (u.isVisible(this.el)) {
  15038. return this;
  15039. }
  15040. this.el.classList.add('fade-in');
  15041. this.el.classList.remove('hidden');
  15042. return this;
  15043. },
  15044. hide: function hide() {
  15045. if (!u.isVisible(this.el)) {
  15046. return this;
  15047. }
  15048. this.model.save({
  15049. 'filter_text': '',
  15050. 'chat_state': ''
  15051. });
  15052. this.el.classList.add('hidden');
  15053. return this;
  15054. },
  15055. clearFilter: function clearFilter(ev) {
  15056. if (ev && ev.preventDefault) {
  15057. ev.preventDefault();
  15058. u.hideElement(this.el.querySelector('.clear-input'));
  15059. }
  15060. var roster_filter = this.el.querySelector('.roster-filter');
  15061. roster_filter.value = '';
  15062. this.model.save({
  15063. 'filter_text': ''
  15064. });
  15065. }
  15066. });
  15067. _converse.RosterContactView = Backbone.NativeView.extend({
  15068. tagName: 'li',
  15069. className: 'd-flex hidden',
  15070. events: {
  15071. "click .accept-xmpp-request": "acceptRequest",
  15072. "click .decline-xmpp-request": "declineRequest",
  15073. "click .open-chat": "openChat",
  15074. "click .remove-xmpp-contact": "removeContact"
  15075. },
  15076. initialize: function initialize() {
  15077. this.model.on("change", this.render, this);
  15078. this.model.on("remove", this.remove, this);
  15079. this.model.on("destroy", this.remove, this);
  15080. this.model.on("open", this.openChat, this);
  15081. },
  15082. render: function render() {
  15083. var that = this;
  15084. if (!this.mayBeShown()) {
  15085. u.hideElement(this.el);
  15086. return this;
  15087. }
  15088. var item = this.model,
  15089. ask = item.get('ask'),
  15090. chat_status = item.get('chat_status'),
  15091. requesting = item.get('requesting'),
  15092. subscription = item.get('subscription');
  15093. var classes_to_remove = ['current-xmpp-contact', 'pending-xmpp-contact', 'requesting-xmpp-contact'].concat(_.keys(STATUSES));
  15094. _.each(classes_to_remove, function (cls) {
  15095. if (_.includes(that.el.className, cls)) {
  15096. that.el.classList.remove(cls);
  15097. }
  15098. });
  15099. this.el.classList.add(chat_status);
  15100. this.el.setAttribute('data-status', chat_status);
  15101. if (ask === 'subscribe' || subscription === 'from') {
  15102. /* ask === 'subscribe'
  15103. * Means we have asked to subscribe to them.
  15104. *
  15105. * subscription === 'from'
  15106. * They are subscribed to use, but not vice versa.
  15107. * We assume that there is a pending subscription
  15108. * from us to them (otherwise we're in a state not
  15109. * supported by converse.js).
  15110. *
  15111. * So in both cases the user is a "pending" contact.
  15112. */
  15113. this.el.classList.add('pending-xmpp-contact');
  15114. this.el.innerHTML = tpl_pending_contact(_.extend(item.toJSON(), {
  15115. 'desc_remove': __('Click to remove %1$s as a contact', item.get('fullname')),
  15116. 'allow_chat_pending_contacts': _converse.allow_chat_pending_contacts
  15117. }));
  15118. } else if (requesting === true) {
  15119. this.el.classList.add('requesting-xmpp-contact');
  15120. this.el.innerHTML = tpl_requesting_contact(_.extend(item.toJSON(), {
  15121. 'desc_accept': __("Click to accept the contact request from %1$s", item.get('fullname')),
  15122. 'desc_decline': __("Click to decline the contact request from %1$s", item.get('fullname')),
  15123. 'allow_chat_pending_contacts': _converse.allow_chat_pending_contacts
  15124. }));
  15125. } else if (subscription === 'both' || subscription === 'to') {
  15126. this.el.classList.add('current-xmpp-contact');
  15127. this.el.classList.remove(_.without(['both', 'to'], subscription)[0]);
  15128. this.el.classList.add(subscription);
  15129. this.renderRosterItem(item);
  15130. }
  15131. return this;
  15132. },
  15133. renderRosterItem: function renderRosterItem(item) {
  15134. var status_icon = 'fa-times-circle';
  15135. var chat_status = item.get('chat_status') || 'offline';
  15136. if (chat_status === 'online') {
  15137. status_icon = 'fa-circle';
  15138. } else if (chat_status === 'away') {
  15139. status_icon = 'fa-dot-circle-o';
  15140. } else if (chat_status === 'xa') {
  15141. status_icon = 'fa-circle-o';
  15142. } else if (chat_status === 'dnd') {
  15143. status_icon = 'fa-minus-circle';
  15144. }
  15145. this.el.innerHTML = tpl_roster_item(_.extend(item.toJSON(), {
  15146. 'desc_status': STATUSES[chat_status],
  15147. 'status_icon': status_icon,
  15148. 'desc_chat': __('Click to chat with %1$s (JID: %2$s)', item.get('fullname'), item.get('jid')),
  15149. 'desc_remove': __('Click to remove %1$s as a contact', item.get('fullname')),
  15150. 'allow_contact_removal': _converse.allow_contact_removal,
  15151. 'num_unread': item.get('num_unread') || 0
  15152. }));
  15153. return this;
  15154. },
  15155. mayBeShown: function mayBeShown() {
  15156. /* Return a boolean indicating whether this contact should
  15157. * generally be visible in the roster.
  15158. *
  15159. * It doesn't check for the more specific case of whether
  15160. * the group it's in is collapsed.
  15161. */
  15162. var chatStatus = this.model.get('chat_status');
  15163. if (_converse.show_only_online_users && chatStatus !== 'online' || _converse.hide_offline_users && chatStatus === 'offline') {
  15164. // If pending or requesting, show
  15165. if (this.model.get('ask') === 'subscribe' || this.model.get('subscription') === 'from' || this.model.get('requesting') === true) {
  15166. return true;
  15167. }
  15168. return false;
  15169. }
  15170. return true;
  15171. },
  15172. openChat: function openChat(ev) {
  15173. if (ev && ev.preventDefault) {
  15174. ev.preventDefault();
  15175. }
  15176. var attrs = this.model.attributes;
  15177. _converse.api.chats.open(attrs.jid, attrs);
  15178. },
  15179. removeContact: function removeContact(ev) {
  15180. var _this = this;
  15181. if (ev && ev.preventDefault) {
  15182. ev.preventDefault();
  15183. }
  15184. if (!_converse.allow_contact_removal) {
  15185. return;
  15186. }
  15187. var result = confirm(__("Are you sure you want to remove this contact?"));
  15188. if (result === true) {
  15189. var iq = $iq({
  15190. type: 'set'
  15191. }).c('query', {
  15192. xmlns: Strophe.NS.ROSTER
  15193. }).c('item', {
  15194. jid: this.model.get('jid'),
  15195. subscription: "remove"
  15196. });
  15197. _converse.connection.sendIQ(iq, function (iq) {
  15198. _this.model.destroy();
  15199. _this.remove();
  15200. }, function (err) {
  15201. alert(__('Sorry, there was an error while trying to remove %1$s as a contact.', name));
  15202. _converse.log(err, Strophe.LogLevel.ERROR);
  15203. });
  15204. }
  15205. },
  15206. acceptRequest: function acceptRequest(ev) {
  15207. var _this2 = this;
  15208. if (ev && ev.preventDefault) {
  15209. ev.preventDefault();
  15210. }
  15211. _converse.roster.sendContactAddIQ(this.model.get('jid'), this.model.get('fullname'), [], function () {
  15212. _this2.model.authorize().subscribe();
  15213. });
  15214. },
  15215. declineRequest: function declineRequest(ev) {
  15216. if (ev && ev.preventDefault) {
  15217. ev.preventDefault();
  15218. }
  15219. var result = confirm(__("Are you sure you want to decline this contact request?"));
  15220. if (result === true) {
  15221. this.model.unauthorize().destroy();
  15222. }
  15223. return this;
  15224. }
  15225. });
  15226. _converse.RosterGroupView = Backbone.OrderedListView.extend({
  15227. tagName: 'div',
  15228. className: 'roster-group hidden',
  15229. events: {
  15230. "click a.group-toggle": "toggle"
  15231. },
  15232. ItemView: _converse.RosterContactView,
  15233. listItems: 'model.contacts',
  15234. listSelector: '.roster-group-contacts',
  15235. sortEvent: 'change:chat_status',
  15236. initialize: function initialize() {
  15237. Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
  15238. this.model.contacts.on("change:subscription", this.onContactSubscriptionChange, this);
  15239. this.model.contacts.on("change:requesting", this.onContactRequestChange, this);
  15240. this.model.contacts.on("remove", this.onRemove, this);
  15241. _converse.roster.on('change:groups', this.onContactGroupChange, this); // This event gets triggered once *all* contacts (i.e. not
  15242. // just this group's) have been fetched from browser
  15243. // storage or the XMPP server and once they've been
  15244. // assigned to their various groups.
  15245. _converse.rosterview.on('rosterContactsFetchedAndProcessed', this.sortAndPositionAllItems.bind(this));
  15246. },
  15247. render: function render() {
  15248. this.el.setAttribute('data-group', this.model.get('name'));
  15249. this.el.innerHTML = tpl_group_header({
  15250. 'label_group': this.model.get('name'),
  15251. 'desc_group_toggle': this.model.get('description'),
  15252. 'toggle_state': this.model.get('state'),
  15253. '_converse': _converse
  15254. });
  15255. this.contacts_el = this.el.querySelector('.roster-group-contacts');
  15256. return this;
  15257. },
  15258. show: function show() {
  15259. var _this3 = this;
  15260. u.showElement(this.el);
  15261. _.each(this.getAll(), function (contact_view) {
  15262. if (contact_view.mayBeShown() && _this3.model.get('state') === _converse.OPENED) {
  15263. u.showElement(contact_view.el);
  15264. }
  15265. });
  15266. return this;
  15267. },
  15268. collapse: function collapse() {
  15269. return u.slideIn(this.contacts_el);
  15270. },
  15271. filterOutContacts: function filterOutContacts() {
  15272. var _this4 = this;
  15273. var contacts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  15274. /* Given a list of contacts, make sure they're filtered out
  15275. * (aka hidden) and that all other contacts are visible.
  15276. *
  15277. * If all contacts are hidden, then also hide the group
  15278. * title.
  15279. */
  15280. var shown = 0;
  15281. var all_contact_views = this.getAll();
  15282. _.each(this.model.contacts.models, function (contact) {
  15283. var contact_view = _this4.get(contact.get('id'));
  15284. if (_.includes(contacts, contact)) {
  15285. u.hideElement(contact_view.el);
  15286. } else if (contact_view.mayBeShown()) {
  15287. u.showElement(contact_view.el);
  15288. shown += 1;
  15289. }
  15290. });
  15291. if (shown) {
  15292. u.showElement(this.el);
  15293. } else {
  15294. u.hideElement(this.el);
  15295. }
  15296. },
  15297. getFilterMatches: function getFilterMatches(q, type) {
  15298. /* Given the filter query "q" and the filter type "type",
  15299. * return a list of contacts that need to be filtered out.
  15300. */
  15301. if (q.length === 0) {
  15302. return [];
  15303. }
  15304. var matches;
  15305. q = q.toLowerCase();
  15306. if (type === 'state') {
  15307. if (this.model.get('name') === HEADER_REQUESTING_CONTACTS) {
  15308. // When filtering by chat state, we still want to
  15309. // show requesting contacts, even though they don't
  15310. // have the state in question.
  15311. matches = this.model.contacts.filter(function (contact) {
  15312. return u.contains.not('chat_status', q)(contact) && !contact.get('requesting');
  15313. });
  15314. } else if (q === 'unread_messages') {
  15315. matches = this.model.contacts.filter({
  15316. 'num_unread': 0
  15317. });
  15318. } else {
  15319. matches = this.model.contacts.filter(u.contains.not('chat_status', q));
  15320. }
  15321. } else {
  15322. matches = this.model.contacts.filter(u.contains.not('fullname', q));
  15323. }
  15324. return matches;
  15325. },
  15326. filter: function filter(q, type) {
  15327. /* Filter the group's contacts based on the query "q".
  15328. *
  15329. * If all contacts are filtered out (i.e. hidden), then the
  15330. * group must be filtered out as well.
  15331. */
  15332. if (_.isNil(q)) {
  15333. type = type || _converse.rosterview.filter_view.model.get('filter_type');
  15334. if (type === 'state') {
  15335. q = _converse.rosterview.filter_view.model.get('chat_state');
  15336. } else {
  15337. q = _converse.rosterview.filter_view.model.get('filter_text');
  15338. }
  15339. }
  15340. this.filterOutContacts(this.getFilterMatches(q, type));
  15341. },
  15342. toggle: function toggle(ev) {
  15343. if (ev && ev.preventDefault) {
  15344. ev.preventDefault();
  15345. }
  15346. var icon_el = ev.target.querySelector('.fa');
  15347. if (_.includes(icon_el.classList, "fa-caret-down")) {
  15348. this.model.save({
  15349. state: _converse.CLOSED
  15350. });
  15351. this.collapse().then(function () {
  15352. icon_el.classList.remove("fa-caret-down");
  15353. icon_el.classList.add("fa-caret-right");
  15354. });
  15355. } else {
  15356. icon_el.classList.remove("fa-caret-right");
  15357. icon_el.classList.add("fa-caret-down");
  15358. this.model.save({
  15359. state: _converse.OPENED
  15360. });
  15361. this.filter();
  15362. u.showElement(this.el);
  15363. u.slideOut(this.contacts_el);
  15364. }
  15365. },
  15366. onContactGroupChange: function onContactGroupChange(contact) {
  15367. var in_this_group = _.includes(contact.get('groups'), this.model.get('name'));
  15368. var cid = contact.get('id');
  15369. var in_this_overview = !this.get(cid);
  15370. if (in_this_group && !in_this_overview) {
  15371. this.items.trigger('add', contact);
  15372. } else if (!in_this_group) {
  15373. this.removeContact(contact);
  15374. }
  15375. },
  15376. onContactSubscriptionChange: function onContactSubscriptionChange(contact) {
  15377. if (this.model.get('name') === HEADER_PENDING_CONTACTS && contact.get('subscription') !== 'from') {
  15378. this.removeContact(contact);
  15379. }
  15380. },
  15381. onContactRequestChange: function onContactRequestChange(contact) {
  15382. if (this.model.get('name') === HEADER_REQUESTING_CONTACTS && !contact.get('requesting')) {
  15383. this.removeContact(contact);
  15384. }
  15385. },
  15386. removeContact: function removeContact(contact) {
  15387. // We suppress events, otherwise the remove event will
  15388. // also cause the contact's view to be removed from the
  15389. // "Pending Contacts" group.
  15390. this.model.contacts.remove(contact, {
  15391. 'silent': true
  15392. });
  15393. this.onRemove(contact);
  15394. },
  15395. onRemove: function onRemove(contact) {
  15396. if (this.model.contacts.length === 0) {
  15397. this.el.parentElement.removeChild(this.el);
  15398. }
  15399. }
  15400. });
  15401. _converse.RosterView = Backbone.OrderedListView.extend({
  15402. tagName: 'div',
  15403. id: 'converse-roster',
  15404. ItemView: _converse.RosterGroupView,
  15405. listItems: 'model',
  15406. listSelector: '.roster-contacts',
  15407. sortEvent: null,
  15408. // Groups are immutable, so they don't get re-sorted
  15409. subviewIndex: 'name',
  15410. events: {
  15411. 'click a.chatbox-btn.add-contact': 'showAddContactModal'
  15412. },
  15413. initialize: function initialize() {
  15414. var _this5 = this;
  15415. Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
  15416. _converse.roster.on("add", this.onContactAdded, this);
  15417. _converse.roster.on('change:groups', this.onContactAdded, this);
  15418. _converse.roster.on('change', this.onContactChange, this);
  15419. _converse.roster.on("destroy", this.update, this);
  15420. _converse.roster.on("remove", this.update, this);
  15421. this.model.on("reset", this.reset, this); // This event gets triggered once *all* contacts (i.e. not
  15422. // just this group's) have been fetched from browser
  15423. // storage or the XMPP server and once they've been
  15424. // assigned to their various groups.
  15425. _converse.on('rosterGroupsFetched', this.sortAndPositionAllItems.bind(this));
  15426. _converse.on('rosterContactsFetched', function () {
  15427. _converse.roster.each(function (contact) {
  15428. return _this5.addRosterContact(contact, {
  15429. 'silent': true
  15430. });
  15431. });
  15432. _this5.update();
  15433. _this5.updateFilter();
  15434. _this5.trigger('rosterContactsFetchedAndProcessed');
  15435. });
  15436. this.createRosterFilter();
  15437. },
  15438. render: function render() {
  15439. this.el.innerHTML = tpl_roster({
  15440. 'heading_contacts': __('Contacts'),
  15441. 'title_add_contact': __('Add a contact')
  15442. });
  15443. var form = this.el.querySelector('.roster-filter-form');
  15444. this.el.replaceChild(this.filter_view.render().el, form);
  15445. this.roster_el = this.el.querySelector('.roster-contacts');
  15446. return this;
  15447. },
  15448. showAddContactModal: function showAddContactModal(ev) {
  15449. if (_.isUndefined(this.add_contact_modal)) {
  15450. this.add_contact_modal = new _converse.AddContactModal({
  15451. 'model': new Backbone.Model()
  15452. });
  15453. }
  15454. this.add_contact_modal.show(ev);
  15455. },
  15456. createRosterFilter: function createRosterFilter() {
  15457. // Create a model on which we can store filter properties
  15458. var model = new _converse.RosterFilter();
  15459. model.id = b64_sha1("_converse.rosterfilter".concat(_converse.bare_jid));
  15460. model.browserStorage = new Backbone.BrowserStorage.local(this.filter.id);
  15461. this.filter_view = new _converse.RosterFilterView({
  15462. 'model': model
  15463. });
  15464. this.filter_view.model.on('change', this.updateFilter, this);
  15465. this.filter_view.model.fetch();
  15466. },
  15467. updateFilter: _.debounce(function () {
  15468. /* Filter the roster again.
  15469. * Called whenever the filter settings have been changed or
  15470. * when contacts have been added, removed or changed.
  15471. *
  15472. * Debounced so that it doesn't get called for every
  15473. * contact fetched from browser storage.
  15474. */
  15475. var type = this.filter_view.model.get('filter_type');
  15476. if (type === 'state') {
  15477. this.filter(this.filter_view.model.get('chat_state'), type);
  15478. } else {
  15479. this.filter(this.filter_view.model.get('filter_text'), type);
  15480. }
  15481. }, 100),
  15482. update: _.debounce(function () {
  15483. if (!u.isVisible(this.roster_el)) {
  15484. u.showElement(this.roster_el);
  15485. }
  15486. this.filter_view.showOrHide();
  15487. return this;
  15488. }, _converse.animate ? 100 : 0),
  15489. filter: function filter(query, type) {
  15490. // First we make sure the filter is restored to its
  15491. // original state
  15492. _.each(this.getAll(), function (view) {
  15493. if (view.model.contacts.length > 0) {
  15494. view.show().filter('');
  15495. }
  15496. }); // Now we can filter
  15497. query = query.toLowerCase();
  15498. if (type === 'groups') {
  15499. _.each(this.getAll(), function (view, idx) {
  15500. if (!_.includes(view.model.get('name').toLowerCase(), query.toLowerCase())) {
  15501. u.slideIn(view.el);
  15502. } else if (view.model.contacts.length > 0) {
  15503. u.slideOut(view.el);
  15504. }
  15505. });
  15506. } else {
  15507. _.each(this.getAll(), function (view) {
  15508. view.filter(query, type);
  15509. });
  15510. }
  15511. },
  15512. reset: function reset() {
  15513. _converse.roster.reset();
  15514. this.removeAll();
  15515. this.render().update();
  15516. return this;
  15517. },
  15518. onContactAdded: function onContactAdded(contact) {
  15519. this.addRosterContact(contact).update();
  15520. this.updateFilter();
  15521. },
  15522. onContactChange: function onContactChange(contact) {
  15523. this.updateChatBox(contact).update();
  15524. if (_.has(contact.changed, 'subscription')) {
  15525. if (contact.changed.subscription === 'from') {
  15526. this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
  15527. } else if (_.includes(['both', 'to'], contact.get('subscription'))) {
  15528. this.addExistingContact(contact);
  15529. }
  15530. }
  15531. if (_.has(contact.changed, 'ask') && contact.changed.ask === 'subscribe') {
  15532. this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
  15533. }
  15534. if (_.has(contact.changed, 'subscription') && contact.changed.requesting === 'true') {
  15535. this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS);
  15536. }
  15537. this.updateFilter();
  15538. },
  15539. updateChatBox: function updateChatBox(contact) {
  15540. var chatbox = _converse.chatboxes.get(contact.get('jid')),
  15541. changes = {};
  15542. if (!chatbox) {
  15543. return this;
  15544. }
  15545. if (_.has(contact.changed, 'chat_status')) {
  15546. changes.chat_status = contact.get('chat_status');
  15547. }
  15548. if (_.has(contact.changed, 'status')) {
  15549. changes.status = contact.get('status');
  15550. }
  15551. chatbox.save(changes);
  15552. return this;
  15553. },
  15554. getGroup: function getGroup(name) {
  15555. /* Returns the group as specified by name.
  15556. * Creates the group if it doesn't exist.
  15557. */
  15558. var view = this.get(name);
  15559. if (view) {
  15560. return view.model;
  15561. }
  15562. return this.model.create({
  15563. name: name,
  15564. id: b64_sha1(name)
  15565. });
  15566. },
  15567. addContactToGroup: function addContactToGroup(contact, name, options) {
  15568. this.getGroup(name).contacts.add(contact, options);
  15569. },
  15570. addExistingContact: function addExistingContact(contact, options) {
  15571. var groups;
  15572. if (_converse.roster_groups) {
  15573. groups = contact.get('groups');
  15574. if (groups.length === 0) {
  15575. groups = [HEADER_UNGROUPED];
  15576. }
  15577. } else {
  15578. groups = [HEADER_CURRENT_CONTACTS];
  15579. }
  15580. _.each(groups, _.bind(this.addContactToGroup, this, contact, _, options));
  15581. },
  15582. addRosterContact: function addRosterContact(contact, options) {
  15583. if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to') {
  15584. this.addExistingContact(contact, options);
  15585. } else {
  15586. if (contact.get('ask') === 'subscribe' || contact.get('subscription') === 'from') {
  15587. this.addContactToGroup(contact, HEADER_PENDING_CONTACTS, options);
  15588. } else if (contact.get('requesting') === true) {
  15589. this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS, options);
  15590. }
  15591. }
  15592. return this;
  15593. }
  15594. });
  15595. /* -------- Event Handlers ----------- */
  15596. var onChatBoxMaximized = function onChatBoxMaximized(chatboxview) {
  15597. /* When a chat box gets maximized, the num_unread counter needs
  15598. * to be cleared, but if chatbox is scrolled up, then num_unread should not be cleared.
  15599. */
  15600. var chatbox = chatboxview.model;
  15601. if (chatbox.get('type') !== 'chatroom') {
  15602. var contact = _.head(_converse.roster.where({
  15603. 'jid': chatbox.get('jid')
  15604. }));
  15605. if (!_.isUndefined(contact) && !chatbox.isScrolledUp()) {
  15606. contact.save({
  15607. 'num_unread': 0
  15608. });
  15609. }
  15610. }
  15611. };
  15612. var onMessageReceived = function onMessageReceived(data) {
  15613. /* Given a newly received message, update the unread counter on
  15614. * the relevant roster contact.
  15615. */
  15616. var chatbox = data.chatbox;
  15617. if (_.isUndefined(chatbox)) {
  15618. return;
  15619. }
  15620. if (_.isNull(data.stanza.querySelector('body'))) {
  15621. return; // The message has no text
  15622. }
  15623. if (chatbox.get('type') !== 'chatroom' && u.isNewMessage(data.stanza) && chatbox.newMessageWillBeHidden()) {
  15624. var contact = _.head(_converse.roster.where({
  15625. 'jid': chatbox.get('jid')
  15626. }));
  15627. if (!_.isUndefined(contact)) {
  15628. contact.save({
  15629. 'num_unread': contact.get('num_unread') + 1
  15630. });
  15631. }
  15632. }
  15633. };
  15634. var onChatBoxScrolledDown = function onChatBoxScrolledDown(data) {
  15635. var chatbox = data.chatbox;
  15636. if (_.isUndefined(chatbox)) {
  15637. return;
  15638. }
  15639. var contact = _.head(_converse.roster.where({
  15640. 'jid': chatbox.get('jid')
  15641. }));
  15642. if (!_.isUndefined(contact)) {
  15643. contact.save({
  15644. 'num_unread': 0
  15645. });
  15646. }
  15647. };
  15648. var initRoster = function initRoster() {
  15649. /* Create an instance of RosterView once the RosterGroups
  15650. * collection has been created (in converse-core.js)
  15651. */
  15652. _converse.rosterview = new _converse.RosterView({
  15653. 'model': _converse.rostergroups
  15654. });
  15655. _converse.rosterview.render();
  15656. _converse.emit('rosterViewInitialized');
  15657. };
  15658. _converse.api.listen.on('rosterInitialized', initRoster);
  15659. _converse.api.listen.on('rosterReadyAfterReconnection', initRoster);
  15660. _converse.api.listen.on('message', onMessageReceived);
  15661. _converse.api.listen.on('chatBoxMaximized', onChatBoxMaximized);
  15662. _converse.api.listen.on('chatBoxScrolledDown', onChatBoxScrolledDown);
  15663. }
  15664. });
  15665. });
  15666. //# sourceMappingURL=converse-rosterview.js.map;
  15667. define('tpl!chat_status_modal', ['lodash'], function(_) {return function(o) {
  15668. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  15669. function print() { __p += __j.call(arguments, '') }
  15670. __p += '<!-- Change status Modal -->\n<div class="modal fade" id="modal-status-change" tabindex="-1" role="dialog" aria-labelledby="changeStatusModalLabel" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title" id="changeStatusModalLabel">' +
  15671. __e(o.modal_title) +
  15672. '</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="' +
  15673. __e(o.label_close) +
  15674. '">\n <span aria-hidden="true">&times;</span>\n </button>\n </div>\n <form class="set-xmpp-status" id="set-xmpp-status">\n <div class="modal-body">\n <div class="form-group">\n <div class="custom-control custom-radio">\n <input ';
  15675. if (o.status === 'online') { ;
  15676. __p += ' checked="checked" ';
  15677. } ;
  15678. __p += '\n type="radio" id="radio-online" value="online" name="chat_status" class="custom-control-input">\n <label class="custom-control-label" for="radio-online">\n <span class="fa fa-circle"></span>&nbsp;' +
  15679. __e(o.label_online) +
  15680. '</label>\n </div>\n <div class="custom-control custom-radio">\n <input ';
  15681. if (o.status === 'busy') { ;
  15682. __p += ' checked="checked" ';
  15683. } ;
  15684. __p += '\n type="radio" id="radio-busy" value="dnd" name="chat_status" class="custom-control-input">\n <label class="custom-control-label" for="radio-busy">\n <span class="fa fa-minus-circle"></span>&nbsp;' +
  15685. __e(o.label_busy) +
  15686. '</label>\n </div>\n <div class="custom-control custom-radio">\n <input ';
  15687. if (o.status === 'away') { ;
  15688. __p += ' checked="checked" ';
  15689. } ;
  15690. __p += '\n type="radio" id="radio-away" value="away" name="chat_status" class="custom-control-input">\n <label class="custom-control-label" for="radio-away">\n <span class="fa fa-dot-circle-o"></span>&nbsp;' +
  15691. __e(o.label_away) +
  15692. '</label>\n </div>\n <div class="custom-control custom-radio">\n <input ';
  15693. if (o.status === 'xa') { ;
  15694. __p += ' checked="checked" ';
  15695. } ;
  15696. __p += '\n type="radio" id="radio-xa" value="xa" name="chat_status" class="custom-control-input">\n <label class="custom-control-label" for="radio-xa">\n <span class="fa fa-circle-o"></span>&nbsp;' +
  15697. __e(o.label_xa) +
  15698. '</label>\n </div>\n </div>\n <div class="btn-group w-100">\n <input name="status_message" type="text" class="form-control" \n value="' +
  15699. __e(o.status_message) +
  15700. '" placeholder="' +
  15701. __e(o.placeholder_status_message) +
  15702. '">\n <span class="clear-input fa fa-times ';
  15703. if (!o.status_message) { ;
  15704. __p += ' hidden ';
  15705. } ;
  15706. __p += '"></span>\n </div>\n </div>\n <div class="modal-footer">\n <button type="submit" class="btn btn-primary">' +
  15707. __e(o.label_save) +
  15708. '</button>\n </div>\n </form>\n </div>\n </div>\n</div>\n';
  15709. return __p
  15710. };});
  15711. define('tpl!profile_modal', ['lodash'], function(_) {return function(o) {
  15712. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  15713. function print() { __p += __j.call(arguments, '') }
  15714. __p += '<div class="modal fade" id="user-profile-modal" tabindex="-1" role="dialog" aria-labelledby="user-profile-modal-label" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title" id="user-profile-modal-label">' +
  15715. __e(o.heading_profile) +
  15716. '</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="' +
  15717. __e(o.label_close) +
  15718. '"><span aria-hidden="true">&times;</span></button>\n </div>\n <div class="modal-body">\n <div class="row">\n <div class="col-auto">\n ';
  15719. if (o.image) { ;
  15720. __p += '\n <a class="show-profile" href="#">\n <img alt="User Avatar" class="img-thumbnail avatar align-self-center" height="100px" width="100px" src="data:' +
  15721. __e(o.image_type) +
  15722. ';base64,' +
  15723. __e(o.image) +
  15724. '"/>\n </a>\n ';
  15725. } ;
  15726. __p += '\n </div>\n <div class="col-auto">\n <div classs="row w-100">\n <label>Fullname:</label>\n <span class="username">' +
  15727. __e(o.fullname) +
  15728. '</span>\n </div>\n <div classs="row w-100">\n <label>XMPP Address:</label>\n <span class="username">' +
  15729. __e(o.jid) +
  15730. '</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n';
  15731. return __p
  15732. };});
  15733. define('tpl!profile_view', ['lodash'], function(_) {return function(o) {
  15734. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  15735. function print() { __p += __j.call(arguments, '') }
  15736. __p += '<div class="userinfo">\n<div class="profile d-flex">\n ';
  15737. if (o.image) { ;
  15738. __p += '\n <a class="show-profile" href="#">\n <img alt="User Avatar" class="avatar align-self-center" height="40px" width="40px" src="data:' +
  15739. __e(o.image_type) +
  15740. ';base64,' +
  15741. __e(o.image) +
  15742. '"/>\n </a>\n ';
  15743. } ;
  15744. __p += '\n <span class="username w-100 align-self-center">' +
  15745. __e(o.fullname) +
  15746. '</span>\n <!-- <a class="chatbox-btn fa fa-vcard align-self-center" title="' +
  15747. __e(o.title_your_profile) +
  15748. '" data-toggle="modal" data-target="#userProfileModal"></a> -->\n <!-- <a class="chatbox-btn fa fa-cog align-self-center" title="' +
  15749. __e(o.title_change_status) +
  15750. '" data-toggle="modal" data-target="#settingsModal"></a> -->\n ';
  15751. if (o._converse.allow_logout) { ;
  15752. __p += '\n <a class="chatbox-btn logout fa fa-sign-out align-self-center" title="' +
  15753. __e(o.title_log_out) +
  15754. '"></a>\n ';
  15755. } ;
  15756. __p += '\n</div>\n<div class="d-flex xmpp-status">\n <span class="' +
  15757. __e(o.chat_status) +
  15758. ' w-100 align-self-center" data-value="' +
  15759. __e(o.chat_status) +
  15760. '">\n <span class="fa\n ';
  15761. if (o.chat_status === 'online') { ;
  15762. __p += ' fa-circle ';
  15763. } ;
  15764. __p += '\n ';
  15765. if (o.chat_status === 'dnd') { ;
  15766. __p += ' fa-minus-circle ';
  15767. } ;
  15768. __p += '\n ';
  15769. if (o.chat_status === 'away') { ;
  15770. __p += ' fa-dot-circle-o ';
  15771. } ;
  15772. __p += '\n ';
  15773. if (o.chat_status === 'xa') { ;
  15774. __p += ' fa-circle-o ';
  15775. } ;
  15776. __p += '\n ';
  15777. if (o.chat_status === 'offline') { ;
  15778. __p += ' fa-times-circle ';
  15779. } ;
  15780. __p += '"></span> ' +
  15781. __e(o.status_message) +
  15782. '</span>\n <a class="chatbox-btn change-status fa fa-pencil" title="' +
  15783. __e(o.title_change_status) +
  15784. '" data-toggle="modal" data-target="#changeStatusModal"></a>\n</div>\n</div>\n';
  15785. return __p
  15786. };});
  15787. define('tpl!status_option', ['lodash'], function(_) {return function(o) {
  15788. var __t, __p = '', __e = _.escape;
  15789. __p += '<li>\n <a href="#" class="' +
  15790. __e( o.value ) +
  15791. '" data-value="' +
  15792. __e( o.value ) +
  15793. '">\n <span class="icon-' +
  15794. __e( o.value ) +
  15795. '"></span>\n ' +
  15796. __e( o.text ) +
  15797. '\n </a>\n</li>\n';
  15798. return __p
  15799. };});
  15800. // Converse.js (A browser based XMPP chat client)
  15801. // http://conversejs.org
  15802. //
  15803. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  15804. // Licensed under the Mozilla Public License (MPLv2)
  15805. //
  15806. /*global define */
  15807. (function (root, factory) {
  15808. define('converse-vcard',["converse-core", "strophe.vcard"], factory);
  15809. })(void 0, function (converse) {
  15810. "use strict";
  15811. var _converse$env = converse.env,
  15812. Promise = _converse$env.Promise,
  15813. Strophe = _converse$env.Strophe,
  15814. _ = _converse$env._,
  15815. moment = _converse$env.moment,
  15816. sizzle = _converse$env.sizzle;
  15817. var u = converse.env.utils;
  15818. function onVCardData(_converse, jid, iq, callback) {
  15819. var vcard = iq.querySelector('vCard');
  15820. if (_.isNull(vcard)) {
  15821. // Some servers return an empty IQ
  15822. return onVCardError(_converse, jid, iq, callback);
  15823. }
  15824. var img_type = _.get(vcard.querySelector('TYPE'), 'textContent'),
  15825. img = _.get(vcard.querySelector('BINVAL'), 'textContent'),
  15826. url = _.get(vcard.querySelector('URL'), 'textContent'),
  15827. fullname = _.get(vcard.querySelector('FN'), 'textContent');
  15828. if (!u.isSameBareJID(jid, _converse.bare_jid)) {
  15829. var contact = _converse.roster.get(jid);
  15830. if (contact) {
  15831. contact.save({
  15832. 'fullname': fullname || _.get(contact, 'fullname', jid),
  15833. 'image_type': img_type,
  15834. 'image': img,
  15835. 'url': url,
  15836. 'vcard_updated': moment().format()
  15837. });
  15838. }
  15839. }
  15840. if (callback) {
  15841. callback({
  15842. 'stanza': iq,
  15843. 'fullname': fullname,
  15844. 'image': img,
  15845. 'image_type': img_type,
  15846. 'url': url
  15847. });
  15848. }
  15849. }
  15850. function onVCardError(_converse, jid, iq, errback) {
  15851. var contact = _converse.roster.get(jid);
  15852. if (contact) {
  15853. contact.save({
  15854. 'vcard_updated': moment().format()
  15855. });
  15856. }
  15857. if (errback) {
  15858. errback({
  15859. 'stanza': iq,
  15860. 'jid': jid
  15861. });
  15862. }
  15863. }
  15864. function getVCard(_converse, jid) {
  15865. /* Request the VCard of another user. Returns a promise.
  15866. *
  15867. * Parameters:
  15868. * (String) jid - The Jabber ID of the user whose VCard
  15869. * is being requested.
  15870. */
  15871. var to = Strophe.getBareJidFromJid(jid) === _converse.bare_jid ? null : jid;
  15872. return new Promise(function (resolve, reject) {
  15873. if (!_converse.use_vcards) {
  15874. if (resolve) {
  15875. resolve({
  15876. 'jid': jid
  15877. });
  15878. }
  15879. } else {
  15880. _converse.connection.vcard.get(_.partial(onVCardData, _converse, jid, _, resolve), to, _.partial(onVCardError, _converse, jid, _, resolve));
  15881. }
  15882. });
  15883. }
  15884. function updateChatBoxFromVCard(_converse, jid) {
  15885. _converse.api.vcard.get(jid).then(function (vcard) {
  15886. var chatbox = _converse.chatboxes.getChatBox(jid);
  15887. if (!_.isUndefined(chatbox)) {
  15888. chatbox.save(_.pick(vcard, ['fullname', 'url', 'image_type', 'image', 'vcard_updated']));
  15889. }
  15890. }).catch(function (e) {
  15891. _converse.log(e, Strophe.LogLevel.ERROR);
  15892. _converse.log("updateChatBoxFromVCard: Error occured while attempting to update chatbox with VCard data", Strophe.LogLevel.ERROR);
  15893. });
  15894. }
  15895. converse.plugins.add('converse-vcard', {
  15896. overrides: {
  15897. // Overrides mentioned here will be picked up by converse.js's
  15898. // plugin architecture they will replace existing methods on the
  15899. // relevant objects or classes.
  15900. //
  15901. // New functions which don't exist yet can also be added.
  15902. RosterContacts: {
  15903. createRequestingContact: function createRequestingContact(presence) {
  15904. var _converse = this.__super__._converse;
  15905. var bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from'));
  15906. _converse.api.vcard.get(bare_jid).then(_.partial(_converse.createRequestingContactFromVCard, presence)).catch(function (vcard) {
  15907. _converse.log("Error while retrieving vcard for ".concat(vcard.jid), Strophe.LogLevel.WARN);
  15908. _converse.createRequestingContactFromVCard(presence, vcard.stanza, vcard.jid);
  15909. });
  15910. }
  15911. }
  15912. },
  15913. initialize: function initialize() {
  15914. /* The initialize function gets called as soon as the plugin is
  15915. * loaded by converse.js's plugin machinery.
  15916. */
  15917. var _converse = this._converse;
  15918. _converse.api.settings.update({
  15919. 'use_vcards': true
  15920. });
  15921. _converse.createRequestingContactFromVCard = function (presence, vcard) {
  15922. var bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from'));
  15923. var fullname = vcard.fullname;
  15924. if (!fullname) {
  15925. var nick_el = sizzle("nick[xmlns=\"".concat(Strophe.NS.NICK, "\"]"), presence);
  15926. fullname = nick_el.length ? nick_el[0].textContent : bare_jid;
  15927. }
  15928. var user_data = {
  15929. 'jid': bare_jid,
  15930. 'subscription': 'none',
  15931. 'ask': null,
  15932. 'requesting': true,
  15933. 'fullname': fullname,
  15934. 'image': vcard.image,
  15935. 'image_type': vcard.image_type,
  15936. 'url': vcard.url,
  15937. 'vcard_updated': moment().format()
  15938. };
  15939. _converse.roster.create(user_data);
  15940. _converse.emit('contactRequest', user_data);
  15941. };
  15942. /* Event handlers */
  15943. _converse.on('addClientFeatures', function () {
  15944. if (_converse.use_vcards) {
  15945. _converse.connection.disco.addFeature(Strophe.NS.VCARD);
  15946. }
  15947. });
  15948. _converse.on('chatBoxInitialized', function (chatbox) {
  15949. if (!_converse.use_vcards || chatbox.model.get('type') === 'headline') {
  15950. return;
  15951. }
  15952. _converse.api.waitUntil('rosterInitialized').then(function () {
  15953. var jid = chatbox.model.get('jid'),
  15954. contact = _converse.roster.get(jid);
  15955. if (contact && !contact.get('vcard_updated') || _.isUndefined(contact) && _converse.allow_non_roster_messaging) {
  15956. updateChatBoxFromVCard(_converse, jid);
  15957. }
  15958. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  15959. });
  15960. _converse.on('initialized', function () {
  15961. _converse.roster.on("add", function (contact) {
  15962. if (!contact.get('vcard_updated')) {
  15963. _converse.api.vcard.get(contact.get('jid'));
  15964. }
  15965. });
  15966. });
  15967. _converse.on('statusInitialized', function fetchOwnVCard() {
  15968. if (_.isNil(_converse.xmppstatus.get('vcard_updated'))) {
  15969. _converse.api.disco.supports(Strophe.NS.VCARD, _converse.domain).then(function (result) {
  15970. if (result.supported) {
  15971. _converse.api.vcard.get(_converse.bare_jid).then(function (vcard) {
  15972. return _converse.xmppstatus.save(vcard);
  15973. });
  15974. }
  15975. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  15976. }
  15977. });
  15978. _.extend(_converse.api, {
  15979. 'vcard': {
  15980. 'get': function get(jid) {
  15981. return getVCard(_converse, jid);
  15982. }
  15983. }
  15984. });
  15985. }
  15986. });
  15987. });
  15988. //# sourceMappingURL=converse-vcard.js.map;
  15989. // Converse.js (A browser based XMPP chat client)
  15990. // http://conversejs.org
  15991. //
  15992. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  15993. // Licensed under the Mozilla Public License (MPLv2)
  15994. //
  15995. /*global define */
  15996. (function (root, factory) {
  15997. define('converse-profile',["converse-core", "bootstrap", "tpl!chat_status_modal", "tpl!profile_modal", "tpl!profile_view", "tpl!status_option", "converse-vcard", "converse-modal"], factory);
  15998. })(void 0, function (converse, bootstrap, tpl_chat_status_modal, tpl_profile_modal, tpl_profile_view, tpl_status_option) {
  15999. "use strict";
  16000. var _converse$env = converse.env,
  16001. Strophe = _converse$env.Strophe,
  16002. Backbone = _converse$env.Backbone,
  16003. Promise = _converse$env.Promise,
  16004. utils = _converse$env.utils,
  16005. _ = _converse$env._,
  16006. moment = _converse$env.moment;
  16007. var u = converse.env.utils;
  16008. converse.plugins.add('converse-profile', {
  16009. dependencies: ["converse-modal"],
  16010. initialize: function initialize() {
  16011. /* The initialize function gets called as soon as the plugin is
  16012. * loaded by converse.js's plugin machinery.
  16013. */
  16014. var _converse = this._converse,
  16015. __ = _converse.__;
  16016. _converse.ProfileModal = _converse.BootstrapModal.extend({
  16017. toHTML: function toHTML() {
  16018. return tpl_profile_modal(_.extend(this.model.toJSON(), {
  16019. 'heading_profile': __('Your Profile'),
  16020. 'label_close': __('Close')
  16021. }));
  16022. }
  16023. });
  16024. _converse.ChatStatusModal = _converse.BootstrapModal.extend({
  16025. events: {
  16026. "submit form#set-xmpp-status": "onFormSubmitted",
  16027. "click .clear-input": "clearStatusMessage"
  16028. },
  16029. toHTML: function toHTML() {
  16030. return tpl_chat_status_modal(_.extend(this.model.toJSON(), {
  16031. 'label_away': __('Away'),
  16032. 'label_close': __('Close'),
  16033. 'label_busy': __('Busy'),
  16034. 'label_cancel': __('Cancel'),
  16035. 'label_custom_status': __('Custom status'),
  16036. 'label_offline': __('Offline'),
  16037. 'label_online': __('Online'),
  16038. 'label_save': __('Save'),
  16039. 'label_xa': __('Away for long'),
  16040. 'modal_title': __('Change chat status'),
  16041. 'placeholder_status_message': __('Personal status message')
  16042. }));
  16043. },
  16044. clearStatusMessage: function clearStatusMessage(ev) {
  16045. if (ev && ev.preventDefault) {
  16046. ev.preventDefault();
  16047. u.hideElement(this.el.querySelector('.clear-input'));
  16048. }
  16049. var roster_filter = this.el.querySelector('input[name="status_message"]');
  16050. roster_filter.value = '';
  16051. },
  16052. onFormSubmitted: function onFormSubmitted(ev) {
  16053. ev.preventDefault();
  16054. var data = new FormData(ev.target);
  16055. this.model.save({
  16056. 'status_message': data.get('status_message'),
  16057. 'status': data.get('chat_status')
  16058. });
  16059. this.modal.hide();
  16060. }
  16061. });
  16062. _converse.XMPPStatusView = Backbone.VDOMView.extend({
  16063. tagName: "div",
  16064. events: {
  16065. "click a.show-profile": "showProfileModal",
  16066. "click a.change-status": "showStatusChangeModal",
  16067. "click .logout": "logOut"
  16068. },
  16069. initialize: function initialize() {
  16070. this.model.on("change", this.render, this);
  16071. },
  16072. toHTML: function toHTML() {
  16073. var chat_status = this.model.get('status') || 'offline';
  16074. return tpl_profile_view(_.extend(this.model.toJSON(), {
  16075. 'fullname': this.model.get('fullname') || _converse.bare_jid,
  16076. 'status_message': this.model.get('status_message') || __("I am %1$s", this.getPrettyStatus(chat_status)),
  16077. 'chat_status': chat_status,
  16078. '_converse': _converse,
  16079. 'title_change_settings': __('Change settings'),
  16080. 'title_change_status': __('Click to change your chat status'),
  16081. 'title_log_out': __('Log out'),
  16082. 'title_your_profile': __('Your profile')
  16083. }));
  16084. },
  16085. showProfileModal: function showProfileModal(ev) {
  16086. if (_.isUndefined(this.profile_modal)) {
  16087. this.profile_modal = new _converse.ProfileModal({
  16088. model: this.model
  16089. });
  16090. }
  16091. this.profile_modal.show(ev);
  16092. },
  16093. showStatusChangeModal: function showStatusChangeModal(ev) {
  16094. if (_.isUndefined(this.status_modal)) {
  16095. this.status_modal = new _converse.ChatStatusModal({
  16096. model: this.model
  16097. });
  16098. }
  16099. this.status_modal.show(ev);
  16100. },
  16101. logOut: function logOut(ev) {
  16102. ev.preventDefault();
  16103. var result = confirm(__("Are you sure you want to log out?"));
  16104. if (result === true) {
  16105. _converse.logOut();
  16106. }
  16107. },
  16108. getPrettyStatus: function getPrettyStatus(stat) {
  16109. if (stat === 'chat') {
  16110. return __('online');
  16111. } else if (stat === 'dnd') {
  16112. return __('busy');
  16113. } else if (stat === 'xa') {
  16114. return __('away for long');
  16115. } else if (stat === 'away') {
  16116. return __('away');
  16117. } else if (stat === 'offline') {
  16118. return __('offline');
  16119. } else {
  16120. return __(stat) || __('online');
  16121. }
  16122. }
  16123. });
  16124. }
  16125. });
  16126. });
  16127. //# sourceMappingURL=converse-profile.js.map;
  16128. // Converse.js (A browser based XMPP chat client)
  16129. // http://conversejs.org
  16130. //
  16131. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  16132. // Licensed under the Mozilla Public License (MPLv2)
  16133. //
  16134. /*global define */
  16135. (function (root, factory) {
  16136. define('converse-controlbox',["converse-core", "lodash.fp", "tpl!converse_brand_heading", "tpl!controlbox", "tpl!controlbox_toggle", "tpl!login_panel", "converse-chatview", "converse-rosterview", "converse-profile"], factory);
  16137. })(void 0, function (converse, fp, tpl_brand_heading, tpl_controlbox, tpl_controlbox_toggle, tpl_login_panel) {
  16138. "use strict";
  16139. var CHATBOX_TYPE = 'chatbox';
  16140. var _converse$env = converse.env,
  16141. Strophe = _converse$env.Strophe,
  16142. Backbone = _converse$env.Backbone,
  16143. Promise = _converse$env.Promise,
  16144. _ = _converse$env._,
  16145. moment = _converse$env.moment;
  16146. var u = converse.env.utils;
  16147. var CONNECTION_STATUS_CSS_CLASS = {
  16148. 'Error': 'error',
  16149. 'Connecting': 'info',
  16150. 'Connection failure': 'error',
  16151. 'Authenticating': 'info',
  16152. 'Authentication failure': 'error',
  16153. 'Connected': 'info',
  16154. 'Disconnected': 'error',
  16155. 'Disconnecting': 'warn',
  16156. 'Attached': 'info',
  16157. 'Redirect': 'info',
  16158. 'Reconnecting': 'warn'
  16159. };
  16160. var PRETTY_CONNECTION_STATUS = {
  16161. 0: 'Error',
  16162. 1: 'Connecting',
  16163. 2: 'Connection failure',
  16164. 3: 'Authenticating',
  16165. 4: 'Authentication failure',
  16166. 5: 'Connected',
  16167. 6: 'Disconnected',
  16168. 7: 'Disconnecting',
  16169. 8: 'Attached',
  16170. 9: 'Redirect',
  16171. 10: 'Reconnecting'
  16172. };
  16173. var REPORTABLE_STATUSES = [0, // ERROR'
  16174. 1, // CONNECTING
  16175. 2, // CONNFAIL
  16176. 3, // AUTHENTICATING
  16177. 4, // AUTHFAIL
  16178. 7, // DISCONNECTING
  16179. 10 // RECONNECTING
  16180. ];
  16181. converse.plugins.add('converse-controlbox', {
  16182. /* Plugin dependencies are other plugins which might be
  16183. * overridden or relied upon, and therefore need to be loaded before
  16184. * this plugin.
  16185. *
  16186. * If the setting "strict_plugin_dependencies" is set to true,
  16187. * an error will be raised if the plugin is not found. By default it's
  16188. * false, which means these plugins are only loaded opportunistically.
  16189. *
  16190. * NB: These plugins need to have already been loaded via require.js.
  16191. */
  16192. dependencies: ["converse-modal", "converse-chatboxes", "converse-rosterview", "converse-chatview"],
  16193. overrides: {
  16194. // Overrides mentioned here will be picked up by converse.js's
  16195. // plugin architecture they will replace existing methods on the
  16196. // relevant objects or classes.
  16197. //
  16198. // New functions which don't exist yet can also be added.
  16199. _tearDown: function _tearDown() {
  16200. this.__super__._tearDown.apply(this, arguments);
  16201. if (this.rosterview) {
  16202. // Removes roster groups
  16203. this.rosterview.model.off().reset();
  16204. this.rosterview.each(function (groupview) {
  16205. groupview.removeAll();
  16206. groupview.remove();
  16207. });
  16208. this.rosterview.removeAll().remove();
  16209. }
  16210. },
  16211. clearSession: function clearSession() {
  16212. this.__super__.clearSession.apply(this, arguments);
  16213. var chatboxes = _.get(this, 'chatboxes', null);
  16214. if (!_.isNil(chatboxes)) {
  16215. var controlbox = chatboxes.get('controlbox');
  16216. if (controlbox && controlbox.collection && controlbox.collection.browserStorage) {
  16217. controlbox.save({
  16218. 'connected': false
  16219. });
  16220. }
  16221. }
  16222. },
  16223. ChatBoxes: {
  16224. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  16225. return this.__super__.chatBoxMayBeShown.apply(this, arguments) && chatbox.get('id') !== 'controlbox';
  16226. }
  16227. },
  16228. ChatBoxViews: {
  16229. onChatBoxAdded: function onChatBoxAdded(item) {
  16230. var _converse = this.__super__._converse;
  16231. if (item.get('box_id') === 'controlbox') {
  16232. var view = this.get(item.get('id'));
  16233. if (view) {
  16234. view.model = item;
  16235. view.initialize();
  16236. return view;
  16237. } else {
  16238. view = new _converse.ControlBoxView({
  16239. model: item
  16240. });
  16241. return this.add(item.get('id'), view);
  16242. }
  16243. } else {
  16244. return this.__super__.onChatBoxAdded.apply(this, arguments);
  16245. }
  16246. },
  16247. closeAllChatBoxes: function closeAllChatBoxes() {
  16248. var _converse = this.__super__._converse;
  16249. this.each(function (view) {
  16250. if (view.model.get('id') === 'controlbox' && (_converse.disconnection_cause !== _converse.LOGOUT || _converse.show_controlbox_by_default)) {
  16251. return;
  16252. }
  16253. view.close();
  16254. });
  16255. return this;
  16256. },
  16257. getChatBoxWidth: function getChatBoxWidth(view) {
  16258. var _converse = this.__super__._converse;
  16259. var controlbox = this.get('controlbox');
  16260. if (view.model.get('id') === 'controlbox') {
  16261. /* We return the width of the controlbox or its toggle,
  16262. * depending on which is visible.
  16263. */
  16264. if (!controlbox || !u.isVisible(controlbox.el)) {
  16265. return u.getOuterWidth(_converse.controlboxtoggle.el, true);
  16266. } else {
  16267. return u.getOuterWidth(controlbox.el, true);
  16268. }
  16269. } else {
  16270. return this.__super__.getChatBoxWidth.apply(this, arguments);
  16271. }
  16272. }
  16273. },
  16274. ChatBox: {
  16275. initialize: function initialize() {
  16276. if (this.get('id') === 'controlbox') {
  16277. this.set({
  16278. 'time_opened': moment(0).valueOf()
  16279. });
  16280. } else {
  16281. this.__super__.initialize.apply(this, arguments);
  16282. }
  16283. }
  16284. },
  16285. ChatBoxView: {
  16286. insertIntoDOM: function insertIntoDOM() {
  16287. var view = this.__super__._converse.chatboxviews.get("controlbox");
  16288. if (view) {
  16289. view.el.insertAdjacentElement('afterend', this.el);
  16290. } else {
  16291. this.__super__.insertIntoDOM.apply(this, arguments);
  16292. }
  16293. return this;
  16294. }
  16295. }
  16296. },
  16297. initialize: function initialize() {
  16298. /* The initialize function gets called as soon as the plugin is
  16299. * loaded by converse.js's plugin machinery.
  16300. */
  16301. var _converse = this._converse,
  16302. __ = _converse.__;
  16303. _converse.api.settings.update({
  16304. allow_logout: true,
  16305. default_domain: undefined,
  16306. locked_domain: undefined,
  16307. show_controlbox_by_default: false,
  16308. sticky_controlbox: false
  16309. });
  16310. _converse.api.promises.add('controlboxInitialized');
  16311. var LABEL_CONTACTS = __('Contacts');
  16312. _converse.addControlBox = function () {
  16313. return _converse.chatboxes.add({
  16314. id: 'controlbox',
  16315. box_id: 'controlbox',
  16316. type: 'controlbox',
  16317. closed: !_converse.show_controlbox_by_default
  16318. });
  16319. };
  16320. _converse.ControlBoxView = _converse.ChatBoxView.extend({
  16321. tagName: 'div',
  16322. className: 'chatbox',
  16323. id: 'controlbox',
  16324. events: {
  16325. 'click a.close-chatbox-button': 'close'
  16326. },
  16327. initialize: function initialize() {
  16328. if (_.isUndefined(_converse.controlboxtoggle)) {
  16329. _converse.controlboxtoggle = new _converse.ControlBoxToggle();
  16330. }
  16331. _converse.controlboxtoggle.el.insertAdjacentElement('afterend', this.el);
  16332. this.model.on('change:connected', this.onConnected, this);
  16333. this.model.on('destroy', this.hide, this);
  16334. this.model.on('hide', this.hide, this);
  16335. this.model.on('show', this.show, this);
  16336. this.model.on('change:closed', this.ensureClosedState, this);
  16337. this.render();
  16338. if (this.model.get('connected')) {
  16339. this.insertRoster();
  16340. }
  16341. _converse.emit('controlboxInitialized', this);
  16342. },
  16343. render: function render() {
  16344. if (this.model.get('connected')) {
  16345. if (_.isUndefined(this.model.get('closed'))) {
  16346. this.model.set('closed', !_converse.show_controlbox_by_default);
  16347. }
  16348. }
  16349. this.el.innerHTML = tpl_controlbox(_.extend(this.model.toJSON()));
  16350. if (!this.model.get('closed')) {
  16351. this.show();
  16352. } else {
  16353. this.hide();
  16354. }
  16355. if (!_converse.connection.connected || !_converse.connection.authenticated || _converse.connection.disconnecting) {
  16356. this.renderLoginPanel();
  16357. } else if (this.model.get('connected') && (!this.controlbox_pane || !u.isVisible(this.controlbox_pane.el))) {
  16358. this.renderControlBoxPane();
  16359. }
  16360. return this;
  16361. },
  16362. onConnected: function onConnected() {
  16363. if (this.model.get('connected')) {
  16364. this.render();
  16365. this.insertRoster();
  16366. }
  16367. },
  16368. insertRoster: function insertRoster() {
  16369. var _this = this;
  16370. /* Place the rosterview inside the "Contacts" panel. */
  16371. _converse.api.waitUntil('rosterViewInitialized').then(function () {
  16372. return _this.controlbox_pane.el.insertAdjacentElement('beforeEnd', _converse.rosterview.el);
  16373. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  16374. },
  16375. createBrandHeadingHTML: function createBrandHeadingHTML() {
  16376. return tpl_brand_heading({
  16377. 'sticky_controlbox': _converse.sticky_controlbox
  16378. });
  16379. },
  16380. insertBrandHeading: function insertBrandHeading() {
  16381. var heading_el = this.el.querySelector('.brand-heading-container');
  16382. if (_.isNull(heading_el)) {
  16383. var el = this.el.querySelector('.controlbox-head');
  16384. el.insertAdjacentHTML('beforeend', this.createBrandHeadingHTML());
  16385. } else {
  16386. heading_el.outerHTML = this.createBrandHeadingHTML();
  16387. }
  16388. },
  16389. renderLoginPanel: function renderLoginPanel() {
  16390. this.el.classList.add("logged-out");
  16391. if (_.isNil(this.loginpanel)) {
  16392. this.loginpanel = new _converse.LoginPanel({
  16393. 'model': new _converse.LoginPanelModel()
  16394. });
  16395. var panes = this.el.querySelector('.controlbox-panes');
  16396. panes.innerHTML = '';
  16397. panes.appendChild(this.loginpanel.render().el);
  16398. this.insertBrandHeading();
  16399. } else {
  16400. this.loginpanel.render();
  16401. }
  16402. return this;
  16403. },
  16404. renderControlBoxPane: function renderControlBoxPane() {
  16405. /* Renders the "Contacts" panel of the controlbox.
  16406. *
  16407. * This will only be called after the user has already been
  16408. * logged in.
  16409. */
  16410. if (this.loginpanel) {
  16411. this.loginpanel.remove();
  16412. delete this.loginpanel;
  16413. }
  16414. this.el.classList.remove("logged-out");
  16415. this.controlbox_pane = new _converse.ControlBoxPane();
  16416. this.el.querySelector('.controlbox-panes').insertAdjacentElement('afterBegin', this.controlbox_pane.el);
  16417. },
  16418. close: function close(ev) {
  16419. if (ev && ev.preventDefault) {
  16420. ev.preventDefault();
  16421. }
  16422. if (_converse.sticky_controlbox) {
  16423. return;
  16424. }
  16425. if (_converse.connection.connected && !_converse.connection.disconnecting) {
  16426. this.model.save({
  16427. 'closed': true
  16428. });
  16429. } else {
  16430. this.model.trigger('hide');
  16431. }
  16432. _converse.emit('controlBoxClosed', this);
  16433. return this;
  16434. },
  16435. ensureClosedState: function ensureClosedState() {
  16436. if (this.model.get('closed')) {
  16437. this.hide();
  16438. } else {
  16439. this.show();
  16440. }
  16441. },
  16442. hide: function hide(callback) {
  16443. if (_converse.sticky_controlbox) {
  16444. return;
  16445. }
  16446. u.addClass('hidden', this.el);
  16447. _converse.emit('chatBoxClosed', this);
  16448. if (!_converse.connection.connected) {
  16449. _converse.controlboxtoggle.render();
  16450. }
  16451. _converse.controlboxtoggle.show(callback);
  16452. return this;
  16453. },
  16454. onControlBoxToggleHidden: function onControlBoxToggleHidden() {
  16455. this.model.set('closed', false);
  16456. this.el.classList.remove('hidden');
  16457. _converse.emit('controlBoxOpened', this);
  16458. },
  16459. show: function show() {
  16460. _converse.controlboxtoggle.hide(this.onControlBoxToggleHidden.bind(this));
  16461. return this;
  16462. },
  16463. showHelpMessages: function showHelpMessages() {
  16464. /* Override showHelpMessages in ChatBoxView, for now do nothing.
  16465. *
  16466. * Parameters:
  16467. * (Array) msgs: Array of messages
  16468. */
  16469. return;
  16470. }
  16471. });
  16472. _converse.LoginPanelModel = Backbone.Model.extend({
  16473. defaults: {
  16474. // Passed-by-reference. Fine in this case because there's
  16475. // only one such model.
  16476. 'errors': []
  16477. }
  16478. });
  16479. _converse.LoginPanel = Backbone.VDOMView.extend({
  16480. tagName: 'div',
  16481. id: "converse-login-panel",
  16482. className: 'controlbox-pane fade-in',
  16483. events: {
  16484. 'submit form#converse-login': 'authenticate',
  16485. 'change input': 'validate'
  16486. },
  16487. initialize: function initialize(cfg) {
  16488. this.model.on('change', this.render, this);
  16489. this.listenTo(_converse.connfeedback, 'change', this.render);
  16490. },
  16491. toHTML: function toHTML() {
  16492. var connection_status = _converse.connfeedback.get('connection_status');
  16493. var feedback_class, pretty_status;
  16494. if (_.includes(REPORTABLE_STATUSES, connection_status)) {
  16495. pretty_status = PRETTY_CONNECTION_STATUS[connection_status];
  16496. feedback_class = CONNECTION_STATUS_CSS_CLASS[pretty_status];
  16497. }
  16498. return tpl_login_panel(_.extend(this.model.toJSON(), {
  16499. '__': __,
  16500. '_converse': _converse,
  16501. 'ANONYMOUS': _converse.ANONYMOUS,
  16502. 'EXTERNAL': _converse.EXTERNAL,
  16503. 'LOGIN': _converse.LOGIN,
  16504. 'PREBIND': _converse.PREBIND,
  16505. 'auto_login': _converse.auto_login,
  16506. 'authentication': _converse.authentication,
  16507. 'connection_status': connection_status,
  16508. 'conn_feedback_class': feedback_class,
  16509. 'conn_feedback_subject': pretty_status,
  16510. 'conn_feedback_message': _converse.connfeedback.get('message'),
  16511. 'placeholder_username': (_converse.locked_domain || _converse.default_domain) && __('Username') || __('user@domain')
  16512. }));
  16513. },
  16514. validate: function validate() {
  16515. var form = this.el.querySelector('form');
  16516. var jid_element = form.querySelector('input[name=jid]');
  16517. if (jid_element.value && !_converse.locked_domain && !_converse.default_domain && !u.isValidJID(jid_element.value)) {
  16518. jid_element.setCustomValidity(__('Please enter a valid XMPP address'));
  16519. return false;
  16520. }
  16521. jid_element.setCustomValidity('');
  16522. return true;
  16523. },
  16524. authenticate: function authenticate(ev) {
  16525. /* Authenticate the user based on a form submission event.
  16526. */
  16527. if (ev && ev.preventDefault) {
  16528. ev.preventDefault();
  16529. }
  16530. if (_converse.authentication === _converse.ANONYMOUS) {
  16531. this.connect(_converse.jid, null);
  16532. return;
  16533. }
  16534. if (!this.validate()) {
  16535. return;
  16536. }
  16537. var jid = ev.target.querySelector('input[name=jid]').value;
  16538. if (_converse.locked_domain) {
  16539. jid = Strophe.escapeNode(jid) + '@' + _converse.locked_domain;
  16540. } else if (_converse.default_domain && !_.includes(jid, '@')) {
  16541. jid = jid + '@' + _converse.default_domain;
  16542. }
  16543. this.connect(jid, _.get(ev.target.querySelector('input[name=password]'), 'value'));
  16544. },
  16545. connect: function connect(jid, password) {
  16546. if (jid) {
  16547. var resource = Strophe.getResourceFromJid(jid);
  16548. if (!resource) {
  16549. jid = jid.toLowerCase() + _converse.generateResource();
  16550. } else {
  16551. jid = Strophe.getBareJidFromJid(jid).toLowerCase() + '/' + resource;
  16552. }
  16553. }
  16554. if (_.includes(["converse/login", "converse/register"], Backbone.history.getFragment())) {
  16555. _converse.router.navigate('', {
  16556. 'replace': true
  16557. });
  16558. }
  16559. _converse.connection.reset();
  16560. _converse.connection.connect(jid, password, _converse.onConnectStatusChanged);
  16561. }
  16562. });
  16563. _converse.ControlBoxPane = Backbone.NativeView.extend({
  16564. tagName: 'div',
  16565. className: 'controlbox-pane',
  16566. initialize: function initialize() {
  16567. _converse.xmppstatusview = new _converse.XMPPStatusView({
  16568. 'model': _converse.xmppstatus
  16569. });
  16570. this.el.insertAdjacentElement('afterBegin', _converse.xmppstatusview.render().el);
  16571. }
  16572. });
  16573. _converse.ControlBoxToggle = Backbone.NativeView.extend({
  16574. tagName: 'a',
  16575. className: 'toggle-controlbox hidden',
  16576. id: 'toggle-controlbox',
  16577. events: {
  16578. 'click': 'onClick'
  16579. },
  16580. attributes: {
  16581. 'href': "#"
  16582. },
  16583. initialize: function initialize() {
  16584. _converse.chatboxviews.insertRowColumn(this.render().el);
  16585. _converse.api.waitUntil('initialized').then(this.render.bind(this)).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  16586. },
  16587. render: function render() {
  16588. // We let the render method of ControlBoxView decide whether
  16589. // the ControlBox or the Toggle must be shown. This prevents
  16590. // artifacts (i.e. on page load the toggle is shown only to then
  16591. // seconds later be hidden in favor of the control box).
  16592. this.el.innerHTML = tpl_controlbox_toggle({
  16593. 'label_toggle': _converse.connection.connected ? __('Contacts') : __('Toggle chat')
  16594. });
  16595. return this;
  16596. },
  16597. hide: function hide(callback) {
  16598. u.hideElement(this.el);
  16599. callback();
  16600. },
  16601. show: function show(callback) {
  16602. u.fadeIn(this.el, callback);
  16603. },
  16604. showControlBox: function showControlBox() {
  16605. var controlbox = _converse.chatboxes.get('controlbox');
  16606. if (!controlbox) {
  16607. controlbox = _converse.addControlBox();
  16608. }
  16609. if (_converse.connection.connected) {
  16610. controlbox.save({
  16611. closed: false
  16612. });
  16613. } else {
  16614. controlbox.trigger('show');
  16615. }
  16616. },
  16617. onClick: function onClick(e) {
  16618. e.preventDefault();
  16619. if (u.isVisible(_converse.root.querySelector("#controlbox"))) {
  16620. var controlbox = _converse.chatboxes.get('controlbox');
  16621. if (_converse.connection.connected) {
  16622. controlbox.save({
  16623. closed: true
  16624. });
  16625. } else {
  16626. controlbox.trigger('hide');
  16627. }
  16628. } else {
  16629. this.showControlBox();
  16630. }
  16631. }
  16632. });
  16633. Promise.all([_converse.api.waitUntil('connectionInitialized'), _converse.api.waitUntil('chatBoxesInitialized')]).then(_converse.addControlBox).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  16634. _converse.on('chatBoxesFetched', function () {
  16635. var controlbox = _converse.chatboxes.get('controlbox') || _converse.addControlBox();
  16636. controlbox.save({
  16637. connected: true
  16638. });
  16639. });
  16640. var disconnect = function disconnect() {
  16641. /* Upon disconnection, set connected to `false`, so that if
  16642. * we reconnect, "onConnected" will be called,
  16643. * to fetch the roster again and to send out a presence stanza.
  16644. */
  16645. var view = _converse.chatboxviews.get('controlbox');
  16646. view.model.set({
  16647. 'connected': false
  16648. });
  16649. view.renderLoginPanel();
  16650. };
  16651. _converse.on('disconnected', disconnect);
  16652. _converse.on('will-reconnect', disconnect);
  16653. }
  16654. });
  16655. });
  16656. //# sourceMappingURL=converse-controlbox.js.map;
  16657. define('tpl!field', ['lodash'], function(_) {return function(o) {
  16658. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16659. function print() { __p += __j.call(arguments, '') }
  16660. __p += '<field var="' +
  16661. __e(o.name) +
  16662. '">\n';
  16663. if (_.isArray(o.value)) { ;
  16664. __p += '\n ';
  16665. _.each(o.value,function(arrayValue) { ;
  16666. __p += '<value>' +
  16667. __e(arrayValue) +
  16668. '</value>';
  16669. }); ;
  16670. __p += '\n';
  16671. } else { ;
  16672. __p += '\n <value>' +
  16673. __e(o.value) +
  16674. '</value>\n';
  16675. } ;
  16676. __p += '</field>\n';
  16677. return __p
  16678. };});
  16679. define('tpl!select_option', ['lodash'], function(_) {return function(o) {
  16680. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16681. function print() { __p += __j.call(arguments, '') }
  16682. __p += '<option value="' +
  16683. __e(o.value) +
  16684. '" ';
  16685. if (o.selected) { ;
  16686. __p += ' selected="selected" ';
  16687. } ;
  16688. __p += ' >' +
  16689. __e(o.label) +
  16690. '</option>\n';
  16691. return __p
  16692. };});
  16693. define('tpl!form_select', ['lodash'], function(_) {return function(o) {
  16694. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16695. function print() { __p += __j.call(arguments, '') }
  16696. __p += '<label>\n ' +
  16697. __e(o.label) +
  16698. '\n <select name="' +
  16699. __e(o.name) +
  16700. '" ';
  16701. if (o.multiple) { ;
  16702. __p += ' multiple="multiple" ';
  16703. } ;
  16704. __p += '>' +
  16705. ((__t = (o.options)) == null ? '' : __t) +
  16706. '</select>\n</label>\n';
  16707. return __p
  16708. };});
  16709. define('tpl!form_textarea', ['lodash'], function(_) {return function(o) {
  16710. var __t, __p = '', __e = _.escape;
  16711. __p += '<label class="label-ta">' +
  16712. __e(o.label) +
  16713. '</label>\n<textarea name="' +
  16714. __e(o.name) +
  16715. '">' +
  16716. __e(o.value) +
  16717. '</textarea>\n';
  16718. return __p
  16719. };});
  16720. define('tpl!form_checkbox', ['lodash'], function(_) {return function(o) {
  16721. var __t, __p = '', __e = _.escape;
  16722. __p += '<label class="checkbox" for="' +
  16723. __e(o.name) +
  16724. '">' +
  16725. __e(o.label) +
  16726. '<input name="' +
  16727. __e(o.name) +
  16728. '" type="' +
  16729. __e(o.type) +
  16730. '" ' +
  16731. __e(o.checked) +
  16732. '></label>\n\n';
  16733. return __p
  16734. };});
  16735. define('tpl!form_username', ['lodash'], function(_) {return function(o) {
  16736. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16737. function print() { __p += __j.call(arguments, '') }
  16738. if (o.label) { ;
  16739. __p += '\n<label>\n ' +
  16740. __e(o.label) +
  16741. '\n</label>\n';
  16742. } ;
  16743. __p += '\n<div class="input-group">\n <input name="' +
  16744. __e(o.name) +
  16745. '" type="' +
  16746. __e(o.type) +
  16747. '"\n ';
  16748. if (o.value) { ;
  16749. __p += ' value="' +
  16750. __e(o.value) +
  16751. '" ';
  16752. } ;
  16753. __p += '\n ';
  16754. if (o.required) { ;
  16755. __p += ' class="required" ';
  16756. } ;
  16757. __p += ' />\n <span title="' +
  16758. __e(o.domain) +
  16759. '">' +
  16760. __e(o.domain) +
  16761. '</span>\n</div>\n';
  16762. return __p
  16763. };});
  16764. define('tpl!form_input', ['lodash'], function(_) {return function(o) {
  16765. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16766. function print() { __p += __j.call(arguments, '') }
  16767. __p += '<label>\n ' +
  16768. __e(o.label) +
  16769. '\n <input name="' +
  16770. __e(o.name) +
  16771. '" type="' +
  16772. __e(o.type) +
  16773. '" \n ';
  16774. if (o.placeholder) { ;
  16775. __p += ' placeholder="' +
  16776. __e(o.placeholder) +
  16777. '" ';
  16778. } ;
  16779. __p += '\n ';
  16780. if (o.value) { ;
  16781. __p += ' value="' +
  16782. __e(o.value) +
  16783. '" ';
  16784. } ;
  16785. __p += '\n ';
  16786. if (o.required) { ;
  16787. __p += ' class="required" ';
  16788. } ;
  16789. __p += ' >\n</label>\n';
  16790. return __p
  16791. };});
  16792. define('tpl!form_captcha', ['lodash'], function(_) {return function(o) {
  16793. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16794. function print() { __p += __j.call(arguments, '') }
  16795. if (o.label) { ;
  16796. __p += '\n<label>\n ' +
  16797. __e(o.label) +
  16798. '\n</label>\n';
  16799. } ;
  16800. __p += '\n<img src="data:' +
  16801. __e(o.type) +
  16802. ';base64,' +
  16803. __e(o.data) +
  16804. '">\n<input name="' +
  16805. __e(o.name) +
  16806. '" type="text" ';
  16807. if (o.required) { ;
  16808. __p += ' class="required" ';
  16809. } ;
  16810. __p += ' >\n\n\n';
  16811. return __p
  16812. };});
  16813. define('tpl!form_url', ['lodash'], function(_) {return function(o) {
  16814. var __t, __p = '', __e = _.escape;
  16815. __p += '<label>\n ' +
  16816. __e(o.label) +
  16817. '\n <a class="form-url" target="_blank" rel="noopener" href="' +
  16818. __e(o.value) +
  16819. '">' +
  16820. __e(o.value) +
  16821. '</a>\n</label>\n';
  16822. return __p
  16823. };});
  16824. // Converse.js (A browser based XMPP chat client)
  16825. // http://conversejs.org
  16826. //
  16827. // This is the utilities module.
  16828. //
  16829. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  16830. // Licensed under the Mozilla Public License (MPLv2)
  16831. //
  16832. /*global define, escape, Jed */
  16833. (function (root, factory) {
  16834. define('form-utils',["sizzle", "lodash.noconflict", "utils", "tpl!field", "tpl!select_option", "tpl!form_select", "tpl!form_textarea", "tpl!form_checkbox", "tpl!form_username", "tpl!form_input", "tpl!form_captcha", "tpl!form_url"], factory);
  16835. })(void 0, function (sizzle, _, u, tpl_field, tpl_select_option, tpl_form_select, tpl_form_textarea, tpl_form_checkbox, tpl_form_username, tpl_form_input, tpl_form_captcha, tpl_form_url) {
  16836. "use strict";
  16837. var XFORM_TYPE_MAP = {
  16838. 'text-private': 'password',
  16839. 'text-single': 'text',
  16840. 'fixed': 'label',
  16841. 'boolean': 'checkbox',
  16842. 'hidden': 'hidden',
  16843. 'jid-multi': 'textarea',
  16844. 'list-single': 'dropdown',
  16845. 'list-multi': 'dropdown'
  16846. };
  16847. u.webForm2xForm = function (field) {
  16848. /* Takes an HTML DOM and turns it into an XForm field.
  16849. *
  16850. * Parameters:
  16851. * (DOMElement) field - the field to convert
  16852. */
  16853. var value;
  16854. if (field.getAttribute('type') === 'checkbox') {
  16855. value = field.checked && 1 || 0;
  16856. } else if (field.tagName == "textarea") {
  16857. value = _.filter(field.value.split('\n'), _.trim);
  16858. } else {
  16859. value = field.value;
  16860. }
  16861. return u.stringToNode(tpl_field({
  16862. name: field.getAttribute('name'),
  16863. value: value
  16864. }));
  16865. };
  16866. u.xForm2webForm = function (field, stanza, domain) {
  16867. /* Takes a field in XMPP XForm (XEP-004: Data Forms) format
  16868. * and turns it into an HTML field.
  16869. *
  16870. * Returns either text or a DOM element (which is not ideal, but fine
  16871. * for now).
  16872. *
  16873. * Parameters:
  16874. * (XMLElement) field - the field to convert
  16875. */
  16876. if (field.getAttribute('type')) {
  16877. if (field.getAttribute('type') === 'list-single' || field.getAttribute('type') === 'list-multi') {
  16878. var values = _.map(u.queryChildren(field, 'value'), _.partial(_.get, _, 'textContent'));
  16879. var options = _.map(u.queryChildren(field, 'option'), function (option) {
  16880. var value = _.get(option.querySelector('value'), 'textContent');
  16881. return tpl_select_option({
  16882. 'value': value,
  16883. 'label': option.getAttribute('label'),
  16884. 'selected': _.startsWith(values, value),
  16885. 'required': !_.isNil(field.querySelector('required'))
  16886. });
  16887. });
  16888. return tpl_form_select({
  16889. 'name': field.getAttribute('var'),
  16890. 'label': field.getAttribute('label'),
  16891. 'options': options.join(''),
  16892. 'multiple': field.getAttribute('type') === 'list-multi',
  16893. 'required': !_.isNil(field.querySelector('required'))
  16894. });
  16895. } else if (field.getAttribute('type') === 'fixed') {
  16896. var text = _.get(field.querySelector('value'), 'textContent');
  16897. return '<p class="form-help">' + text + '</p>';
  16898. } else if (field.getAttribute('type') === 'jid-multi') {
  16899. return tpl_form_textarea({
  16900. 'name': field.getAttribute('var'),
  16901. 'label': field.getAttribute('label') || '',
  16902. 'value': _.get(field.querySelector('value'), 'textContent'),
  16903. 'required': !_.isNil(field.querySelector('required'))
  16904. });
  16905. } else if (field.getAttribute('type') === 'boolean') {
  16906. return tpl_form_checkbox({
  16907. 'name': field.getAttribute('var'),
  16908. 'type': XFORM_TYPE_MAP[field.getAttribute('type')],
  16909. 'label': field.getAttribute('label') || '',
  16910. 'checked': _.get(field.querySelector('value'), 'textContent') === "1" && 'checked="1"' || '',
  16911. 'required': !_.isNil(field.querySelector('required'))
  16912. });
  16913. } else if (field.getAttribute('var') === 'url') {
  16914. return tpl_form_url({
  16915. 'label': field.getAttribute('label') || '',
  16916. 'value': _.get(field.querySelector('value'), 'textContent')
  16917. });
  16918. } else if (field.getAttribute('var') === 'username') {
  16919. return tpl_form_username({
  16920. 'domain': ' @' + domain,
  16921. 'name': field.getAttribute('var'),
  16922. 'type': XFORM_TYPE_MAP[field.getAttribute('type')],
  16923. 'label': field.getAttribute('label') || '',
  16924. 'value': _.get(field.querySelector('value'), 'textContent'),
  16925. 'required': !_.isNil(field.querySelector('required'))
  16926. });
  16927. } else {
  16928. return tpl_form_input({
  16929. 'label': field.getAttribute('label') || '',
  16930. 'name': field.getAttribute('var'),
  16931. 'placeholder': null,
  16932. 'required': !_.isNil(field.querySelector('required')),
  16933. 'type': XFORM_TYPE_MAP[field.getAttribute('type')],
  16934. 'value': _.get(field.querySelector('value'), 'textContent')
  16935. });
  16936. }
  16937. } else {
  16938. if (field.getAttribute('var') === 'ocr') {
  16939. // Captcha
  16940. var uri = field.querySelector('uri');
  16941. var el = sizzle('data[cid="' + uri.textContent.replace(/^cid:/, '') + '"]', stanza)[0];
  16942. return tpl_form_captcha({
  16943. 'label': field.getAttribute('label'),
  16944. 'name': field.getAttribute('var'),
  16945. 'data': _.get(el, 'textContent'),
  16946. 'type': uri.getAttribute('type'),
  16947. 'required': !_.isNil(field.querySelector('required'))
  16948. });
  16949. }
  16950. }
  16951. };
  16952. return u;
  16953. });
  16954. //# sourceMappingURL=form-utils.js.map;
  16955. // Converse.js (A browser based XMPP chat client)
  16956. // http://conversejs.org
  16957. //
  16958. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  16959. // Licensed under the Mozilla Public License (MPLv2)
  16960. //
  16961. /* This is a Converse.js plugin which add support for XEP-0030: Service Discovery */
  16962. /*global Backbone, define, window */
  16963. (function (root, factory) {
  16964. define('converse-disco',["converse-core", "sizzle", "strophe.disco"], factory);
  16965. })(void 0, function (converse, sizzle) {
  16966. var _converse$env = converse.env,
  16967. Backbone = _converse$env.Backbone,
  16968. Promise = _converse$env.Promise,
  16969. Strophe = _converse$env.Strophe,
  16970. b64_sha1 = _converse$env.b64_sha1,
  16971. utils = _converse$env.utils,
  16972. _ = _converse$env._;
  16973. converse.plugins.add('converse-disco', {
  16974. initialize: function initialize() {
  16975. /* The initialize function gets called as soon as the plugin is
  16976. * loaded by converse.js's plugin machinery.
  16977. */
  16978. var _converse = this._converse;
  16979. function onDiscoItems(stanza) {
  16980. _.each(stanza.querySelectorAll('query item'), function (item) {
  16981. if (item.getAttribute("node")) {
  16982. // XXX: ignore nodes for now.
  16983. // See: https://xmpp.org/extensions/xep-0030.html#items-nodes
  16984. return;
  16985. }
  16986. var jid = item.getAttribute('jid');
  16987. var entities = _converse.disco_entities;
  16988. if (_.isUndefined(entities.get(jid))) {
  16989. entities.create({
  16990. 'jid': jid
  16991. });
  16992. }
  16993. });
  16994. } // Promises exposed by this plugin
  16995. _converse.api.promises.add('discoInitialized');
  16996. _converse.DiscoEntity = Backbone.Model.extend({
  16997. /* A Disco Entity is a JID addressable entity that can be queried
  16998. * for features.
  16999. *
  17000. * See XEP-0030: https://xmpp.org/extensions/xep-0030.html
  17001. */
  17002. idAttribute: 'jid',
  17003. initialize: function initialize() {
  17004. this.waitUntilFeaturesDiscovered = utils.getResolveablePromise();
  17005. this.features = new Backbone.Collection();
  17006. this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.features-".concat(this.get('jid'))));
  17007. this.features.on('add', this.onFeatureAdded, this);
  17008. this.identities = new Backbone.Collection();
  17009. this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.identities-".concat(this.get('jid'))));
  17010. this.fetchFeatures();
  17011. },
  17012. getIdentity: function getIdentity(category, type) {
  17013. /* Returns a Promise which resolves with a map indicating
  17014. * whether a given identity is provided.
  17015. *
  17016. * Parameters:
  17017. * (String) category - The identity category
  17018. * (String) type - The identity type
  17019. */
  17020. var entity = this;
  17021. return new Promise(function (resolve, reject) {
  17022. function fulfillPromise() {
  17023. var model = entity.identities.findWhere({
  17024. 'category': category,
  17025. 'type': type
  17026. });
  17027. resolve(model);
  17028. }
  17029. entity.waitUntilFeaturesDiscovered.then(fulfillPromise).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  17030. });
  17031. },
  17032. hasFeature: function hasFeature(feature) {
  17033. /* Returns a Promise which resolves with a map indicating
  17034. * whether a given feature is supported.
  17035. *
  17036. * Parameters:
  17037. * (String) feature - The feature that might be supported.
  17038. */
  17039. var entity = this;
  17040. return new Promise(function (resolve, reject) {
  17041. function fulfillPromise() {
  17042. var model = entity.features.findWhere({
  17043. 'var': feature
  17044. });
  17045. if (model) {
  17046. resolve({
  17047. 'supported': true,
  17048. 'feature': model
  17049. });
  17050. } else {
  17051. resolve({
  17052. 'supported': false,
  17053. 'feature': null
  17054. });
  17055. }
  17056. }
  17057. entity.waitUntilFeaturesDiscovered.then(fulfillPromise).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  17058. });
  17059. },
  17060. onFeatureAdded: function onFeatureAdded(feature) {
  17061. feature.entity = this;
  17062. _converse.emit('serviceDiscovered', feature);
  17063. },
  17064. fetchFeatures: function fetchFeatures() {
  17065. var _this = this;
  17066. if (this.features.browserStorage.records.length === 0) {
  17067. this.queryInfo();
  17068. } else {
  17069. this.features.fetch({
  17070. add: true,
  17071. success: function success() {
  17072. _this.waitUntilFeaturesDiscovered.resolve();
  17073. _this.trigger('featuresDiscovered');
  17074. }
  17075. });
  17076. this.identities.fetch({
  17077. add: true
  17078. });
  17079. }
  17080. },
  17081. queryInfo: function queryInfo() {
  17082. _converse.connection.disco.info(this.get('jid'), null, this.onInfo.bind(this));
  17083. },
  17084. queryForItems: function queryForItems() {
  17085. if (_.isEmpty(this.identities.where({
  17086. 'category': 'server'
  17087. }))) {
  17088. // Don't fetch features and items if this is not a
  17089. // server or a conference component.
  17090. return;
  17091. }
  17092. _converse.connection.disco.items(this.get('jid'), null, onDiscoItems);
  17093. },
  17094. onInfo: function onInfo(stanza) {
  17095. var _this2 = this;
  17096. _.forEach(stanza.querySelectorAll('identity'), function (identity) {
  17097. _this2.identities.create({
  17098. 'category': identity.getAttribute('category'),
  17099. 'type': identity.getAttribute('type'),
  17100. 'name': identity.getAttribute('name')
  17101. });
  17102. });
  17103. if (stanza.querySelector('feature[var="' + Strophe.NS.DISCO_ITEMS + '"]')) {
  17104. this.queryForItems();
  17105. }
  17106. _.forEach(stanza.querySelectorAll('feature'), function (feature) {
  17107. _this2.features.create({
  17108. 'var': feature.getAttribute('var'),
  17109. 'from': stanza.getAttribute('from')
  17110. });
  17111. });
  17112. this.waitUntilFeaturesDiscovered.resolve();
  17113. this.trigger('featuresDiscovered');
  17114. }
  17115. });
  17116. _converse.DiscoEntities = Backbone.Collection.extend({
  17117. model: _converse.DiscoEntity,
  17118. initialize: function initialize() {
  17119. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.disco-entities-".concat(_converse.bare_jid)));
  17120. this.fetchEntities().then(_.partial(_converse.emit, 'discoInitialized'), _.partial(_converse.emit, 'discoInitialized')).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  17121. },
  17122. fetchEntities: function fetchEntities() {
  17123. var _this3 = this;
  17124. return new Promise(function (resolve, reject) {
  17125. _this3.fetch({
  17126. add: true,
  17127. success: function (collection) {
  17128. if (collection.length === 0 || !collection.get(_converse.domain)) {
  17129. this.create({
  17130. 'jid': _converse.domain
  17131. });
  17132. }
  17133. resolve();
  17134. }.bind(_this3),
  17135. error: function error() {
  17136. reject(new Error("Could not fetch disco entities"));
  17137. }
  17138. });
  17139. });
  17140. }
  17141. });
  17142. function addClientFeatures() {
  17143. /* The strophe.disco.js plugin keeps a list of features which
  17144. * it will advertise to any #info queries made to it.
  17145. *
  17146. * See: http://xmpp.org/extensions/xep-0030.html#info
  17147. */
  17148. // See http://xmpp.org/registrar/disco-categories.html
  17149. _converse.connection.disco.addIdentity('client', 'web', 'Converse.js');
  17150. _converse.connection.disco.addFeature(Strophe.NS.BOSH);
  17151. _converse.connection.disco.addFeature(Strophe.NS.CHATSTATES);
  17152. _converse.connection.disco.addFeature(Strophe.NS.DISCO_INFO);
  17153. _converse.connection.disco.addFeature(Strophe.NS.ROSTERX); // Limited support
  17154. if (_converse.message_carbons) {
  17155. _converse.connection.disco.addFeature(Strophe.NS.CARBONS);
  17156. }
  17157. _converse.emit('addClientFeatures');
  17158. return this;
  17159. }
  17160. function initializeDisco() {
  17161. addClientFeatures();
  17162. _converse.disco_entities = new _converse.DiscoEntities();
  17163. }
  17164. _converse.api.listen.on('reconnected', initializeDisco);
  17165. _converse.api.listen.on('connected', initializeDisco);
  17166. _converse.api.listen.on('beforeTearDown', function () {
  17167. if (_converse.disco_entities) {
  17168. _converse.disco_entities.each(function (entity) {
  17169. entity.features.reset();
  17170. entity.features.browserStorage._clear();
  17171. });
  17172. _converse.disco_entities.reset();
  17173. _converse.disco_entities.browserStorage._clear();
  17174. }
  17175. });
  17176. /* We extend the default converse.js API to add methods specific to service discovery */
  17177. _.extend(_converse.api, {
  17178. 'disco': {
  17179. 'entities': {
  17180. 'get': function get(entity_jid) {
  17181. var create = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  17182. var entity = _converse.disco_entities.get(entity_jid);
  17183. if (entity || !create) {
  17184. return entity;
  17185. }
  17186. return _converse.disco_entities.create({
  17187. 'jid': entity_jid
  17188. });
  17189. }
  17190. },
  17191. 'supports': function supports(feature, entity_jid) {
  17192. /* Returns a Promise which resolves with a map indicating
  17193. * whether a given feature is supported.
  17194. *
  17195. * Parameters:
  17196. * (String) feature - The feature that might be
  17197. * supported. In the XML stanza, this is the `var`
  17198. * attribute of the `<feature>` element. For
  17199. * example: 'http://jabber.org/protocol/muc'
  17200. * (String) entity_jid - The JID of the entity which might support the feature.
  17201. */
  17202. return _converse.api.waitUntil('discoInitialized').then(function () {
  17203. var entity = _converse.api.disco.entities.get(entity_jid, true);
  17204. return entity.hasFeature(feature);
  17205. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  17206. },
  17207. 'getIdentity': function getIdentity(category, type, entity_jid) {
  17208. /* Returns a Promise which resolves with a map indicating
  17209. * whether an identity with a given type is provided by
  17210. * the entity.
  17211. *
  17212. * Parameters:
  17213. * (String) category - The identity category.
  17214. * In the XML stanza, this is the `category`
  17215. * attribute of the `<identity>` element.
  17216. * For example: 'pubsub'
  17217. * (String) type - The identity type.
  17218. * In the XML stanza, this is the `type`
  17219. * attribute of the `<identity>` element.
  17220. * For example: 'pep'
  17221. */
  17222. return _converse.api.waitUntil('discoInitialized').then(function () {
  17223. var entity = _converse.api.disco.entities.get(entity_jid, true);
  17224. return entity.getIdentity(category, type);
  17225. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  17226. }
  17227. }
  17228. });
  17229. }
  17230. });
  17231. });
  17232. //# sourceMappingURL=converse-disco.js.map;
  17233. /*!
  17234. * Backbone.OrderedListView
  17235. *
  17236. * Copyright (c) 2017, JC Brand <jc@opkode.com>
  17237. * Licensed under the Mozilla Public License (MPL)
  17238. */
  17239. (function (root, factory) {
  17240. if (typeof define === 'function' && define.amd) {
  17241. define('backbone.orderedlistview',["underscore", "backbone", "backbone.overview"], factory);
  17242. } else {
  17243. // RequireJS isn't being used.
  17244. // Assume underscore and backbone are loaded in <script> tags
  17245. factory(_ || root._, Backbone || root.Backbone);
  17246. }
  17247. })(this, function (_, Backbone) {
  17248. "use strict";
  17249. Backbone.OrderedListView = Backbone.Overview.extend({
  17250. /* An OrderedListView is a special type of Overview which adds some
  17251. * methods and conventions for rendering an ordered list of elements.
  17252. */
  17253. // The `listItems` attribute denotes the path (from this View) to the
  17254. // list of items.
  17255. listItems: 'model',
  17256. // The `sortEvent` attribute specifies the event which should cause the
  17257. // ordered list to be sorted.
  17258. sortEvent: 'change',
  17259. // The `listSelector` is the selector used to query for the DOM list
  17260. // element which contains the ordered items.
  17261. listSelector: '.ordered-items',
  17262. // The `itemView` is constructor which should be called to create a
  17263. // View for a new item.
  17264. ItemView: undefined,
  17265. // The `subviewIndex` is the attribute of the list element model which
  17266. // acts as the index of the subview in the overview.
  17267. // An overview is a "Collection" of views, and they can be retrieved
  17268. // via an index. By default this is the 'id' attribute, but it could be
  17269. // set to something else.
  17270. subviewIndex: 'id',
  17271. initialize: function initialize() {
  17272. this.sortEventually = _.debounce(this.sortAndPositionAllItems.bind(this), 500);
  17273. this.items = _.get(this, this.listItems);
  17274. this.items.on('add', this.sortAndPositionAllItems, this);
  17275. this.items.on('remove', this.removeView, this);
  17276. if (!_.isNil(this.sortEvent)) {
  17277. this.items.on(this.sortEvent, this.sortEventually, this);
  17278. }
  17279. },
  17280. createItemView: function createItemView(item) {
  17281. var item_view = this.get(item.get(this.subviewIndex));
  17282. if (!item_view) {
  17283. item_view = new this.ItemView({
  17284. model: item
  17285. });
  17286. this.add(item.get(this.subviewIndex), item_view);
  17287. } else {
  17288. item_view.model = item;
  17289. item_view.initialize();
  17290. }
  17291. item_view.render();
  17292. return item_view;
  17293. },
  17294. removeView: function removeView(item) {
  17295. this.remove(item.get(this.subviewIndex));
  17296. },
  17297. sortAndPositionAllItems: function sortAndPositionAllItems() {
  17298. var _this = this;
  17299. if (!this.items.length) {
  17300. return;
  17301. }
  17302. this.items.sort();
  17303. var list_el = this.el.querySelector(this.listSelector);
  17304. var div = document.createElement('div');
  17305. list_el.parentNode.replaceChild(div, list_el);
  17306. this.items.each(function (item) {
  17307. var view = _this.get(item.get(_this.subviewIndex));
  17308. if (_.isUndefined(view)) {
  17309. view = _this.createItemView(item);
  17310. }
  17311. list_el.insertAdjacentElement('beforeend', view.el);
  17312. });
  17313. div.parentNode.replaceChild(list_el, div);
  17314. }
  17315. });
  17316. return Backbone.OrderedListView;
  17317. });
  17318. //# sourceMappingURL=backbone.orderedlistview.js.map;
  17319. // Converse.js (A browser based XMPP chat client)
  17320. // http://conversejs.org
  17321. //
  17322. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  17323. // Licensed under the Mozilla Public License (MPLv2)
  17324. //
  17325. /*global define */
  17326. /* This is a Converse.js plugin which add support for multi-user chat rooms, as
  17327. * specified in XEP-0045 Multi-user chat.
  17328. */
  17329. (function (root, factory) {
  17330. define('converse-muc',["form-utils", "converse-core", "converse-chatview", "converse-disco", "backbone.overview", "backbone.orderedlistview", "backbone.vdomview"], factory);
  17331. })(void 0, function (u, converse) {
  17332. "use strict";
  17333. var MUC_ROLE_WEIGHTS = {
  17334. 'moderator': 1,
  17335. 'participant': 2,
  17336. 'visitor': 3,
  17337. 'none': 4
  17338. };
  17339. var _converse$env = converse.env,
  17340. Strophe = _converse$env.Strophe,
  17341. Backbone = _converse$env.Backbone,
  17342. Promise = _converse$env.Promise,
  17343. $iq = _converse$env.$iq,
  17344. $build = _converse$env.$build,
  17345. $msg = _converse$env.$msg,
  17346. $pres = _converse$env.$pres,
  17347. b64_sha1 = _converse$env.b64_sha1,
  17348. sizzle = _converse$env.sizzle,
  17349. _ = _converse$env._,
  17350. moment = _converse$env.moment; // Add Strophe Namespaces
  17351. Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
  17352. Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner");
  17353. Strophe.addNamespace('MUC_REGISTER', "jabber:iq:register");
  17354. Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
  17355. Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
  17356. converse.CHATROOMS_TYPE = 'chatroom';
  17357. converse.ROOM_FEATURES = ['passwordprotected', 'unsecured', 'hidden', 'publicroom', 'membersonly', 'open', 'persistent', 'temporary', 'nonanonymous', 'semianonymous', 'moderated', 'unmoderated', 'mam_enabled'];
  17358. converse.ROOMSTATUS = {
  17359. CONNECTED: 0,
  17360. CONNECTING: 1,
  17361. NICKNAME_REQUIRED: 2,
  17362. PASSWORD_REQUIRED: 3,
  17363. DISCONNECTED: 4,
  17364. ENTERED: 5
  17365. };
  17366. converse.plugins.add('converse-muc', {
  17367. /* Optional dependencies are other plugins which might be
  17368. * overridden or relied upon, and therefore need to be loaded before
  17369. * this plugin. They are called "optional" because they might not be
  17370. * available, in which case any overrides applicable to them will be
  17371. * ignored.
  17372. *
  17373. * It's possible however to make optional dependencies non-optional.
  17374. * If the setting "strict_plugin_dependencies" is set to true,
  17375. * an error will be raised if the plugin is not found.
  17376. *
  17377. * NB: These plugins need to have already been loaded via require.js.
  17378. */
  17379. dependencies: ["converse-controlbox", "converse-chatview"],
  17380. overrides: {
  17381. // Overrides mentioned here will be picked up by converse.js's
  17382. // plugin architecture they will replace existing methods on the
  17383. // relevant objects or classes.
  17384. //
  17385. // New functions which don't exist yet can also be added.
  17386. _tearDown: function _tearDown() {
  17387. var rooms = this.chatboxes.where({
  17388. 'type': converse.CHATROOMS_TYPE
  17389. });
  17390. _.each(rooms, function (room) {
  17391. u.safeSave(room, {
  17392. 'connection_status': converse.ROOMSTATUS.DISCONNECTED
  17393. });
  17394. });
  17395. this.__super__._tearDown.call(this, arguments);
  17396. },
  17397. ChatBoxes: {
  17398. model: function model(attrs, options) {
  17399. var _converse = this.__super__._converse;
  17400. if (attrs.type == converse.CHATROOMS_TYPE) {
  17401. return new _converse.ChatRoom(attrs, options);
  17402. } else {
  17403. return this.__super__.model.apply(this, arguments);
  17404. }
  17405. }
  17406. }
  17407. },
  17408. initialize: function initialize() {
  17409. /* The initialize function gets called as soon as the plugin is
  17410. * loaded by converse.js's plugin machinery.
  17411. */
  17412. var _converse = this._converse,
  17413. __ = _converse.__;
  17414. function ___(str) {
  17415. /* This is part of a hack to get gettext to scan strings to be
  17416. * translated. Strings we cannot send to the function above because
  17417. * they require variable interpolation and we don't yet have the
  17418. * variables at scan time.
  17419. *
  17420. * See actionInfoMessages further below.
  17421. */
  17422. return str;
  17423. } // XXX: Inside plugins, all calls to the translation machinery
  17424. // (e.g. u.__) should only be done in the initialize function.
  17425. // If called before, we won't know what language the user wants,
  17426. // and it'll fall back to English.
  17427. /* http://xmpp.org/extensions/xep-0045.html
  17428. * ----------------------------------------
  17429. * 100 message Entering a room Inform user that any occupant is allowed to see the user's full JID
  17430. * 101 message (out of band) Affiliation change Inform user that his or her affiliation changed while not in the room
  17431. * 102 message Configuration change Inform occupants that room now shows unavailable members
  17432. * 103 message Configuration change Inform occupants that room now does not show unavailable members
  17433. * 104 message Configuration change Inform occupants that a non-privacy-related room configuration change has occurred
  17434. * 110 presence Any room presence Inform user that presence refers to one of its own room occupants
  17435. * 170 message or initial presence Configuration change Inform occupants that room logging is now enabled
  17436. * 171 message Configuration change Inform occupants that room logging is now disabled
  17437. * 172 message Configuration change Inform occupants that the room is now non-anonymous
  17438. * 173 message Configuration change Inform occupants that the room is now semi-anonymous
  17439. * 174 message Configuration change Inform occupants that the room is now fully-anonymous
  17440. * 201 presence Entering a room Inform user that a new room has been created
  17441. * 210 presence Entering a room Inform user that the service has assigned or modified the occupant's roomnick
  17442. * 301 presence Removal from room Inform user that he or she has been banned from the room
  17443. * 303 presence Exiting a room Inform all occupants of new room nickname
  17444. * 307 presence Removal from room Inform user that he or she has been kicked from the room
  17445. * 321 presence Removal from room Inform user that he or she is being removed from the room because of an affiliation change
  17446. * 322 presence Removal from room Inform user that he or she is being removed from the room because the room has been changed to members-only and the user is not a member
  17447. * 332 presence Removal from room Inform user that he or she is being removed from the room because of a system shutdown
  17448. */
  17449. _converse.muc = {
  17450. info_messages: {
  17451. 100: __('This room is not anonymous'),
  17452. 102: __('This room now shows unavailable members'),
  17453. 103: __('This room does not show unavailable members'),
  17454. 104: __('The room configuration has changed'),
  17455. 170: __('Room logging is now enabled'),
  17456. 171: __('Room logging is now disabled'),
  17457. 172: __('This room is now no longer anonymous'),
  17458. 173: __('This room is now semi-anonymous'),
  17459. 174: __('This room is now fully-anonymous'),
  17460. 201: __('A new room has been created')
  17461. },
  17462. disconnect_messages: {
  17463. 301: __('You have been banned from this room'),
  17464. 307: __('You have been kicked from this room'),
  17465. 321: __("You have been removed from this room because of an affiliation change"),
  17466. 322: __("You have been removed from this room because the room has changed to members-only and you're not a member"),
  17467. 332: __("You have been removed from this room because the MUC (Multi-user chat) service is being shut down")
  17468. },
  17469. action_info_messages: {
  17470. /* XXX: Note the triple underscore function and not double
  17471. * underscore.
  17472. *
  17473. * This is a hack. We can't pass the strings to __ because we
  17474. * don't yet know what the variable to interpolate is.
  17475. *
  17476. * Triple underscore will just return the string again, but we
  17477. * can then at least tell gettext to scan for it so that these
  17478. * strings are picked up by the translation machinery.
  17479. */
  17480. 301: ___("%1$s has been banned"),
  17481. 303: ___("%1$s's nickname has changed"),
  17482. 307: ___("%1$s has been kicked out"),
  17483. 321: ___("%1$s has been removed because of an affiliation change"),
  17484. 322: ___("%1$s has been removed for not being a member")
  17485. },
  17486. new_nickname_messages: {
  17487. 210: ___('Your nickname has been automatically set to %1$s'),
  17488. 303: ___('Your nickname has been changed to %1$s')
  17489. }
  17490. }; // Configuration values for this plugin
  17491. // ====================================
  17492. // Refer to docs/source/configuration.rst for explanations of these
  17493. // configuration settings.
  17494. _converse.api.settings.update({
  17495. allow_muc: true,
  17496. allow_muc_invitations: true,
  17497. auto_join_on_invite: false,
  17498. auto_join_rooms: [],
  17499. auto_list_rooms: false,
  17500. hide_muc_server: false,
  17501. muc_disable_moderator_commands: false,
  17502. muc_domain: undefined,
  17503. muc_history_max_stanzas: undefined,
  17504. muc_instant_rooms: true,
  17505. muc_nickname_from_jid: false,
  17506. muc_show_join_leave: true,
  17507. visible_toolbar_buttons: {
  17508. 'toggle_occupants': true
  17509. }
  17510. });
  17511. _converse.api.promises.add(['roomsAutoJoined']);
  17512. function openRoom(jid) {
  17513. if (!u.isValidMUCJID(jid)) {
  17514. return _converse.log("Invalid JID \"".concat(jid, "\" provided in URL fragment"), Strophe.LogLevel.WARN);
  17515. }
  17516. var promises = [_converse.api.waitUntil('roomsAutoJoined')];
  17517. if (_converse.allow_bookmarks) {
  17518. promises.push(_converse.api.waitUntil('bookmarksInitialized'));
  17519. }
  17520. Promise.all(promises).then(function () {
  17521. _converse.api.rooms.open(jid);
  17522. });
  17523. }
  17524. _converse.router.route('converse/room?jid=:jid', openRoom);
  17525. _converse.openChatRoom = function (jid, settings, bring_to_foreground) {
  17526. /* Opens a chat room, making sure that certain attributes
  17527. * are correct, for example that the "type" is set to
  17528. * "chatroom".
  17529. */
  17530. settings.type = converse.CHATROOMS_TYPE;
  17531. settings.id = jid;
  17532. settings.box_id = b64_sha1(jid);
  17533. var chatbox = _converse.chatboxes.getChatBox(jid, settings, true);
  17534. chatbox.trigger('show', true);
  17535. return chatbox;
  17536. };
  17537. _converse.ChatRoom = _converse.ChatBox.extend({
  17538. defaults: function defaults() {
  17539. return _.assign(_.clone(_converse.ChatBox.prototype.defaults), _.zipObject(converse.ROOM_FEATURES, _.map(converse.ROOM_FEATURES, _.stubFalse)), {
  17540. // For group chats, we distinguish between generally unread
  17541. // messages and those ones that specifically mention the
  17542. // user.
  17543. //
  17544. // To keep things simple, we reuse `num_unread` from
  17545. // _converse.ChatBox to indicate unread messages which
  17546. // mention the user and `num_unread_general` to indicate
  17547. // generally unread messages (which *includes* mentions!).
  17548. 'num_unread_general': 0,
  17549. 'affiliation': null,
  17550. 'connection_status': converse.ROOMSTATUS.DISCONNECTED,
  17551. 'name': '',
  17552. 'description': '',
  17553. 'features_fetched': false,
  17554. 'roomconfig': {},
  17555. 'type': converse.CHATROOMS_TYPE
  17556. });
  17557. },
  17558. isUserMentioned: function isUserMentioned(message) {
  17559. /* Returns a boolean to indicate whether the current user
  17560. * was mentioned in a message.
  17561. *
  17562. * Parameters:
  17563. * (String): The text message
  17564. */
  17565. return new RegExp("\\b".concat(this.get('nick'), "\\b")).test(message);
  17566. },
  17567. incrementUnreadMsgCounter: function incrementUnreadMsgCounter(stanza) {
  17568. /* Given a newly received message, update the unread counter if
  17569. * necessary.
  17570. *
  17571. * Parameters:
  17572. * (XMLElement): The <messsage> stanza
  17573. */
  17574. var body = stanza.querySelector('body');
  17575. if (_.isNull(body)) {
  17576. return; // The message has no text
  17577. }
  17578. if (u.isNewMessage(stanza) && this.newMessageWillBeHidden()) {
  17579. this.save({
  17580. 'num_unread_general': this.get('num_unread_general') + 1
  17581. });
  17582. if (this.isUserMentioned(body.textContent)) {
  17583. this.save({
  17584. 'num_unread': this.get('num_unread') + 1
  17585. });
  17586. _converse.incrementMsgCounter();
  17587. }
  17588. }
  17589. },
  17590. clearUnreadMsgCounter: function clearUnreadMsgCounter() {
  17591. u.safeSave(this, {
  17592. 'num_unread': 0,
  17593. 'num_unread_general': 0
  17594. });
  17595. }
  17596. });
  17597. _converse.ChatRoomOccupant = Backbone.Model.extend({
  17598. initialize: function initialize(attributes) {
  17599. this.set(_.extend({
  17600. 'id': _converse.connection.getUniqueId()
  17601. }, attributes));
  17602. }
  17603. });
  17604. _converse.ChatRoomOccupants = Backbone.Collection.extend({
  17605. model: _converse.ChatRoomOccupant,
  17606. comparator: function comparator(occupant1, occupant2) {
  17607. var role1 = occupant1.get('role') || 'none';
  17608. var role2 = occupant2.get('role') || 'none';
  17609. if (MUC_ROLE_WEIGHTS[role1] === MUC_ROLE_WEIGHTS[role2]) {
  17610. var nick1 = occupant1.get('nick').toLowerCase();
  17611. var nick2 = occupant2.get('nick').toLowerCase();
  17612. return nick1 < nick2 ? -1 : nick1 > nick2 ? 1 : 0;
  17613. } else {
  17614. return MUC_ROLE_WEIGHTS[role1] < MUC_ROLE_WEIGHTS[role2] ? -1 : 1;
  17615. }
  17616. }
  17617. });
  17618. _converse.RoomsPanelModel = Backbone.Model.extend({
  17619. defaults: {
  17620. 'muc_domain': ''
  17621. }
  17622. });
  17623. _converse.onDirectMUCInvitation = function (message) {
  17624. /* A direct MUC invitation to join a room has been received
  17625. * See XEP-0249: Direct MUC invitations.
  17626. *
  17627. * Parameters:
  17628. * (XMLElement) message: The message stanza containing the
  17629. * invitation.
  17630. */
  17631. var x_el = sizzle('x[xmlns="jabber:x:conference"]', message).pop(),
  17632. from = Strophe.getBareJidFromJid(message.getAttribute('from')),
  17633. room_jid = x_el.getAttribute('jid'),
  17634. reason = x_el.getAttribute('reason');
  17635. var contact = _converse.roster.get(from),
  17636. result;
  17637. if (_converse.auto_join_on_invite) {
  17638. result = true;
  17639. } else {
  17640. // Invite request might come from someone not your roster list
  17641. contact = contact ? contact.get('fullname') : Strophe.getNodeFromJid(from);
  17642. if (!reason) {
  17643. result = confirm(__("%1$s has invited you to join a chat room: %2$s", contact, room_jid));
  17644. } else {
  17645. result = confirm(__('%1$s has invited you to join a chat room: %2$s, and left the following reason: "%3$s"', contact, room_jid, reason));
  17646. }
  17647. }
  17648. if (result === true) {
  17649. var chatroom = _converse.openChatRoom(room_jid, {
  17650. 'password': x_el.getAttribute('password')
  17651. });
  17652. if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
  17653. _converse.chatboxviews.get(room_jid).join();
  17654. }
  17655. }
  17656. };
  17657. if (_converse.allow_muc_invitations) {
  17658. var registerDirectInvitationHandler = function registerDirectInvitationHandler() {
  17659. _converse.connection.addHandler(function (message) {
  17660. _converse.onDirectMUCInvitation(message);
  17661. return true;
  17662. }, 'jabber:x:conference', 'message');
  17663. };
  17664. _converse.on('connected', registerDirectInvitationHandler);
  17665. _converse.on('reconnected', registerDirectInvitationHandler);
  17666. }
  17667. var getChatRoom = function getChatRoom(jid, attrs, create) {
  17668. jid = jid.toLowerCase();
  17669. attrs.type = converse.CHATROOMS_TYPE;
  17670. attrs.id = jid;
  17671. attrs.box_id = b64_sha1(jid);
  17672. return _converse.chatboxes.getChatBox(jid, attrs, create);
  17673. };
  17674. var createChatRoom = function createChatRoom(jid, attrs) {
  17675. return getChatRoom(jid, attrs, true);
  17676. };
  17677. function autoJoinRooms() {
  17678. /* Automatically join chat rooms, based on the
  17679. * "auto_join_rooms" configuration setting, which is an array
  17680. * of strings (room JIDs) or objects (with room JID and other
  17681. * settings).
  17682. */
  17683. _.each(_converse.auto_join_rooms, function (room) {
  17684. if (_converse.chatboxes.where({
  17685. 'jid': room
  17686. }).length) {
  17687. return;
  17688. }
  17689. if (_.isString(room)) {
  17690. _converse.api.rooms.open(room);
  17691. } else if (_.isObject(room)) {
  17692. _converse.api.rooms.open(room.jid, room.nick);
  17693. } else {
  17694. _converse.log('Invalid room criteria specified for "auto_join_rooms"', Strophe.LogLevel.ERROR);
  17695. }
  17696. });
  17697. _converse.emit('roomsAutoJoined');
  17698. }
  17699. function reconnectToChatRooms() {
  17700. /* Upon a reconnection event from converse, join again
  17701. * all the open chat rooms.
  17702. */
  17703. _converse.chatboxviews.each(function (view) {
  17704. if (view.model.get('type') === converse.CHATROOMS_TYPE) {
  17705. view.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  17706. view.registerHandlers();
  17707. view.join();
  17708. view.fetchMessages();
  17709. }
  17710. });
  17711. }
  17712. function disconnectChatRooms() {
  17713. /* When disconnecting, or reconnecting, mark all chat rooms as
  17714. * disconnected, so that they will be properly entered again
  17715. * when fetched from session storage.
  17716. */
  17717. _converse.chatboxes.each(function (model) {
  17718. if (model.get('type') === converse.CHATROOMS_TYPE) {
  17719. model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  17720. }
  17721. });
  17722. }
  17723. /************************ BEGIN Event Handlers ************************/
  17724. _converse.on('addClientFeatures', function () {
  17725. if (_converse.allow_muc) {
  17726. _converse.connection.disco.addFeature(Strophe.NS.MUC);
  17727. }
  17728. if (_converse.allow_muc_invitations) {
  17729. _converse.connection.disco.addFeature('jabber:x:conference'); // Invites
  17730. }
  17731. });
  17732. _converse.on('chatBoxesFetched', autoJoinRooms);
  17733. _converse.on('reconnected', reconnectToChatRooms);
  17734. _converse.on('reconnecting', disconnectChatRooms);
  17735. _converse.on('disconnecting', disconnectChatRooms);
  17736. /************************ END Event Handlers ************************/
  17737. /************************ BEGIN API ************************/
  17738. // We extend the default converse.js API to add methods specific to MUC chat rooms.
  17739. _.extend(_converse.api, {
  17740. 'rooms': {
  17741. 'close': function close(jids) {
  17742. if (_.isUndefined(jids)) {
  17743. // FIXME: can't access views here
  17744. _converse.chatboxviews.each(function (view) {
  17745. if (view.is_chatroom && view.model) {
  17746. view.close();
  17747. }
  17748. });
  17749. } else if (_.isString(jids)) {
  17750. var view = _converse.chatboxviews.get(jids);
  17751. if (view) {
  17752. view.close();
  17753. }
  17754. } else {
  17755. _.each(jids, function (jid) {
  17756. var view = _converse.chatboxviews.get(jid);
  17757. if (view) {
  17758. view.close();
  17759. }
  17760. });
  17761. }
  17762. },
  17763. 'create': function create(jids, attrs) {
  17764. if (_.isString(attrs)) {
  17765. attrs = {
  17766. 'nick': attrs
  17767. };
  17768. } else if (_.isUndefined(attrs)) {
  17769. attrs = {};
  17770. }
  17771. if (_.isUndefined(attrs.maximize)) {
  17772. attrs.maximize = false;
  17773. }
  17774. if (!attrs.nick && _converse.muc_nickname_from_jid) {
  17775. attrs.nick = Strophe.getNodeFromJid(_converse.bare_jid);
  17776. }
  17777. if (_.isUndefined(jids)) {
  17778. throw new TypeError('rooms.create: You need to provide at least one JID');
  17779. } else if (_.isString(jids)) {
  17780. return createChatRoom(jids, attrs);
  17781. }
  17782. return _.map(jids, _.partial(createChatRoom, _, attrs));
  17783. },
  17784. 'open': function open(jids, attrs) {
  17785. if (_.isUndefined(jids)) {
  17786. throw new TypeError('rooms.open: You need to provide at least one JID');
  17787. } else if (_.isString(jids)) {
  17788. return _converse.api.rooms.create(jids, attrs).trigger('show');
  17789. }
  17790. return _.map(jids, function (jid) {
  17791. return _converse.api.rooms.create(jid, attrs).trigger('show');
  17792. });
  17793. },
  17794. 'get': function get(jids, attrs, create) {
  17795. if (_.isString(attrs)) {
  17796. attrs = {
  17797. 'nick': attrs
  17798. };
  17799. } else if (_.isUndefined(attrs)) {
  17800. attrs = {};
  17801. }
  17802. if (_.isUndefined(jids)) {
  17803. var result = [];
  17804. _converse.chatboxes.each(function (chatbox) {
  17805. if (chatbox.get('type') === converse.CHATROOMS_TYPE) {
  17806. result.push(chatbox);
  17807. }
  17808. });
  17809. return result;
  17810. }
  17811. if (!attrs.nick) {
  17812. attrs.nick = Strophe.getNodeFromJid(_converse.bare_jid);
  17813. }
  17814. if (_.isString(jids)) {
  17815. return getChatRoom(jids, attrs);
  17816. }
  17817. return _.map(jids, _.partial(getChatRoom, _, attrs));
  17818. }
  17819. }
  17820. });
  17821. /************************ END API ************************/
  17822. }
  17823. });
  17824. });
  17825. //# sourceMappingURL=converse-muc.js.map;
  17826. define('tpl!chatroom_bookmark_form', ['lodash'], function(_) {return function(o) {
  17827. var __t, __p = '', __e = _.escape;
  17828. __p += '<div class="chatroom-form-container">\n <form class="converse-form chatroom-form">\n <fieldset class="form-group">\n <legend>' +
  17829. __e(o.heading) +
  17830. '</legend>\n <label>' +
  17831. __e(o.label_name) +
  17832. '</label>\n <input type="text" name="name" required="required"/>\n <label>' +
  17833. __e(o.label_autojoin) +
  17834. '</label>\n <input type="checkbox" name="autojoin"/>\n <label>' +
  17835. __e(o.label_nick) +
  17836. '</label>\n <input type="text" name="nick" value="' +
  17837. __e(o.default_nick) +
  17838. '"/>\n </fieldset>\n <fieldset class="form-group">\n <input class="btn btn-primary" type="submit" value="' +
  17839. __e(o.label_submit) +
  17840. '"/>\n <input class="btn btn-secondary button-cancel" type="button" value="' +
  17841. __e(o.label_cancel) +
  17842. '"/>\n </fieldset>\n </form>\n</div>\n';
  17843. return __p
  17844. };});
  17845. define('tpl!chatroom_bookmark_toggle', ['lodash'], function(_) {return function(o) {
  17846. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  17847. function print() { __p += __j.call(arguments, '') }
  17848. __p += '<a class="chatbox-btn toggle-bookmark fa fa-bookmark\n ';
  17849. if (o.bookmarked) {;
  17850. __p += ' button-on ';
  17851. } ;
  17852. __p += '" title="' +
  17853. __e(o.info_toggle_bookmark) +
  17854. '"></a>\n';
  17855. return __p
  17856. };});
  17857. define('tpl!bookmark', ['lodash'], function(_) {return function(o) {
  17858. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  17859. function print() { __p += __j.call(arguments, '') }
  17860. __p += '<div class="room-item">\n<div class="available-chatroom d-flex flex-row ';
  17861. if (o.hidden) { ;
  17862. __p += ' hidden ';
  17863. } ;
  17864. __p += '" data-room-jid="' +
  17865. __e(o.jid) +
  17866. '">\n <a class="open-room w-100" data-room-jid="' +
  17867. __e(o.jid) +
  17868. '" title="' +
  17869. __e(o.open_title) +
  17870. '" href="#">' +
  17871. __e(o.name) +
  17872. '</a>\n <a class="remove-bookmark fa fa-bookmark align-self-center ';
  17873. if (o.bookmarked) { ;
  17874. __p += ' button-on ';
  17875. } ;
  17876. __p += '"\n data-room-jid="' +
  17877. __e(o.jid) +
  17878. '" data-bookmark-name="' +
  17879. __e(o.name) +
  17880. '"\n title="' +
  17881. __e(o.info_remove_bookmark) +
  17882. '" href="#">&nbsp;</a>\n <a class="room-info fa fa-info-circle align-self-center" data-room-jid="' +
  17883. __e(o.jid) +
  17884. '"\n title="' +
  17885. __e(o.info_title) +
  17886. '" href="#">&nbsp;</a>\n</div>\n</div>\n';
  17887. return __p
  17888. };});
  17889. define('tpl!bookmarks_list', ['lodash'], function(_) {return function(o) {
  17890. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  17891. function print() { __p += __j.call(arguments, '') }
  17892. __p += '<a href="#" class="rooms-toggle bookmarks-toggle" title="' +
  17893. __e(o.desc_bookmarks) +
  17894. '">\n <span class="fa ';
  17895. if (o.toggle_state === o._converse.OPENED) { ;
  17896. __p += ' fa-caret-down ';
  17897. } else { ;
  17898. __p += ' fa-caret-right ';
  17899. } ;
  17900. __p += '">\n </span> ' +
  17901. __e(o.label_bookmarks) +
  17902. '</a>\n<div class="bookmarks rooms-list ';
  17903. if (o.toggle_state !== o._converse.OPENED) { ;
  17904. __p += ' hidden ';
  17905. } ;
  17906. __p += '"></div>\n';
  17907. return __p
  17908. };});
  17909. // Converse.js (A browser based XMPP chat client)
  17910. // http://conversejs.org
  17911. //
  17912. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  17913. // Licensed under the Mozilla Public License (MPLv2)
  17914. //
  17915. /*global define */
  17916. /* This is a Converse.js plugin which add support for bookmarks specified
  17917. * in XEP-0048.
  17918. */
  17919. (function (root, factory) {
  17920. define('converse-bookmarks',["converse-core", "converse-muc", "tpl!chatroom_bookmark_form", "tpl!chatroom_bookmark_toggle", "tpl!bookmark", "tpl!bookmarks_list"], factory);
  17921. })(void 0, function (converse, muc, tpl_chatroom_bookmark_form, tpl_chatroom_bookmark_toggle, tpl_bookmark, tpl_bookmarks_list) {
  17922. var _converse$env = converse.env,
  17923. Backbone = _converse$env.Backbone,
  17924. Promise = _converse$env.Promise,
  17925. Strophe = _converse$env.Strophe,
  17926. $iq = _converse$env.$iq,
  17927. b64_sha1 = _converse$env.b64_sha1,
  17928. sizzle = _converse$env.sizzle,
  17929. _ = _converse$env._;
  17930. var u = converse.env.utils;
  17931. converse.plugins.add('converse-bookmarks', {
  17932. /* Plugin dependencies are other plugins which might be
  17933. * overridden or relied upon, and therefore need to be loaded before
  17934. * this plugin.
  17935. *
  17936. * If the setting "strict_plugin_dependencies" is set to true,
  17937. * an error will be raised if the plugin is not found. By default it's
  17938. * false, which means these plugins are only loaded opportunistically.
  17939. *
  17940. * NB: These plugins need to have already been loaded via require.js.
  17941. */
  17942. dependencies: ["converse-chatboxes", "converse-muc", "converse-muc-views"],
  17943. overrides: {
  17944. // Overrides mentioned here will be picked up by converse.js's
  17945. // plugin architecture they will replace existing methods on the
  17946. // relevant objects or classes.
  17947. //
  17948. // New functions which don't exist yet can also be added.
  17949. clearSession: function clearSession() {
  17950. this.__super__.clearSession.apply(this, arguments);
  17951. if (!_.isUndefined(this.bookmarks)) {
  17952. this.bookmarks.reset();
  17953. this.bookmarks.browserStorage._clear();
  17954. window.sessionStorage.removeItem(this.bookmarks.fetched_flag);
  17955. }
  17956. },
  17957. ChatRoomView: {
  17958. events: {
  17959. 'click .toggle-bookmark': 'toggleBookmark'
  17960. },
  17961. initialize: function initialize() {
  17962. this.__super__.initialize.apply(this, arguments);
  17963. this.model.on('change:bookmarked', this.onBookmarked, this);
  17964. this.setBookmarkState();
  17965. },
  17966. renderBookmarkToggle: function renderBookmarkToggle() {
  17967. var _converse = this.__super__._converse,
  17968. __ = _converse.__;
  17969. var bookmark_button = tpl_chatroom_bookmark_toggle(_.assignIn(this.model.toJSON(), {
  17970. info_toggle_bookmark: __('Bookmark this room'),
  17971. bookmarked: this.model.get('bookmarked')
  17972. }));
  17973. var close_button = this.el.querySelector('.close-chatbox-button');
  17974. close_button.insertAdjacentHTML('afterend', bookmark_button);
  17975. },
  17976. renderHeading: function renderHeading() {
  17977. var _this = this;
  17978. this.__super__.renderHeading.apply(this, arguments);
  17979. var _converse = this.__super__._converse;
  17980. if (_converse.allow_bookmarks) {
  17981. _converse.checkBookmarksSupport().then(function (supported) {
  17982. if (supported) {
  17983. _this.renderBookmarkToggle();
  17984. }
  17985. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  17986. }
  17987. },
  17988. checkForReservedNick: function checkForReservedNick() {
  17989. /* Check if the user has a bookmark with a saved nickanme
  17990. * for this room, and if so use it.
  17991. * Otherwise delegate to the super method.
  17992. */
  17993. var _converse = this.__super__._converse;
  17994. if (_.isUndefined(_converse.bookmarks) || !_converse.allow_bookmarks) {
  17995. return this.__super__.checkForReservedNick.apply(this, arguments);
  17996. }
  17997. var model = _converse.bookmarks.findWhere({
  17998. 'jid': this.model.get('jid')
  17999. });
  18000. if (!_.isUndefined(model) && model.get('nick')) {
  18001. this.join(model.get('nick'));
  18002. } else {
  18003. return this.__super__.checkForReservedNick.apply(this, arguments);
  18004. }
  18005. },
  18006. onBookmarked: function onBookmarked() {
  18007. var icon = this.el.querySelector('.toggle-bookmark');
  18008. if (_.isNull(icon)) {
  18009. return;
  18010. }
  18011. if (this.model.get('bookmarked')) {
  18012. icon.classList.add('button-on');
  18013. } else {
  18014. icon.classList.remove('button-on');
  18015. }
  18016. },
  18017. setBookmarkState: function setBookmarkState() {
  18018. /* Set whether the room is bookmarked or not.
  18019. */
  18020. var _converse = this.__super__._converse;
  18021. if (!_.isUndefined(_converse.bookmarks)) {
  18022. var models = _converse.bookmarks.where({
  18023. 'jid': this.model.get('jid')
  18024. });
  18025. if (!models.length) {
  18026. this.model.save('bookmarked', false);
  18027. } else {
  18028. this.model.save('bookmarked', true);
  18029. }
  18030. }
  18031. },
  18032. renderBookmarkForm: function renderBookmarkForm() {
  18033. var _converse = this.__super__._converse,
  18034. __ = _converse.__,
  18035. body = this.el.querySelector('.chatroom-body');
  18036. _.each(body.children, function (child) {
  18037. child.classList.add('hidden');
  18038. }); // Remove any existing forms
  18039. _.each(body.querySelectorAll('.chatroom-form-container'), u.removeElement);
  18040. body.insertAdjacentHTML('beforeend', tpl_chatroom_bookmark_form({
  18041. heading: __('Bookmark this room'),
  18042. label_name: __('The name for this bookmark:'),
  18043. label_autojoin: __('Would you like this room to be automatically joined upon startup?'),
  18044. label_nick: __('What should your nickname for this room be?'),
  18045. default_nick: this.model.get('nick'),
  18046. label_submit: __('Save'),
  18047. label_cancel: __('Cancel')
  18048. }));
  18049. var form = body.querySelector('form.chatroom-form');
  18050. form.addEventListener('submit', this.onBookmarkFormSubmitted.bind(this));
  18051. form.querySelector('.button-cancel').addEventListener('click', this.closeForm.bind(this));
  18052. },
  18053. onBookmarkFormSubmitted: function onBookmarkFormSubmitted(ev) {
  18054. ev.preventDefault();
  18055. var _converse = this.__super__._converse;
  18056. _converse.bookmarks.createBookmark({
  18057. 'jid': this.model.get('jid'),
  18058. 'autojoin': _.get(ev.target.querySelector('input[name="autojoin"]'), 'checked') || false,
  18059. 'name': _.get(ev.target.querySelector('input[name=name]'), 'value'),
  18060. 'nick': _.get(ev.target.querySelector('input[name=nick]'), 'value')
  18061. });
  18062. u.removeElement(this.el.querySelector('div.chatroom-form-container'));
  18063. this.renderAfterTransition();
  18064. },
  18065. toggleBookmark: function toggleBookmark(ev) {
  18066. if (ev) {
  18067. ev.preventDefault();
  18068. ev.stopPropagation();
  18069. }
  18070. var _converse = this.__super__._converse;
  18071. var models = _converse.bookmarks.where({
  18072. 'jid': this.model.get('jid')
  18073. });
  18074. if (!models.length) {
  18075. this.renderBookmarkForm();
  18076. } else {
  18077. _.forEach(models, function (model) {
  18078. model.destroy();
  18079. });
  18080. this.el.querySelector('.toggle-bookmark').classList.remove('button-on');
  18081. }
  18082. }
  18083. }
  18084. },
  18085. initialize: function initialize() {
  18086. /* The initialize function gets called as soon as the plugin is
  18087. * loaded by converse.js's plugin machinery.
  18088. */
  18089. var _converse = this._converse,
  18090. __ = _converse.__; // Configuration values for this plugin
  18091. // ====================================
  18092. // Refer to docs/source/configuration.rst for explanations of these
  18093. // configuration settings.
  18094. _converse.api.settings.update({
  18095. allow_bookmarks: true,
  18096. allow_public_bookmarks: false,
  18097. hide_open_bookmarks: true
  18098. }); // Promises exposed by this plugin
  18099. _converse.api.promises.add('bookmarksInitialized'); // Pure functions on the _converse object
  18100. _.extend(_converse, {
  18101. removeBookmarkViaEvent: function removeBookmarkViaEvent(ev) {
  18102. /* Remove a bookmark as determined by the passed in
  18103. * event.
  18104. */
  18105. ev.preventDefault();
  18106. var name = ev.target.getAttribute('data-bookmark-name');
  18107. var jid = ev.target.getAttribute('data-room-jid');
  18108. if (confirm(__("Are you sure you want to remove the bookmark \"%1$s\"?", name))) {
  18109. _.invokeMap(_converse.bookmarks.where({
  18110. 'jid': jid
  18111. }), Backbone.Model.prototype.destroy);
  18112. }
  18113. },
  18114. addBookmarkViaEvent: function addBookmarkViaEvent(ev) {
  18115. /* Add a bookmark as determined by the passed in
  18116. * event.
  18117. */
  18118. ev.preventDefault();
  18119. var jid = ev.target.getAttribute('data-room-jid');
  18120. var chatroom = _converse.api.rooms.open(jid, {
  18121. 'bring_to_foreground': true
  18122. });
  18123. _converse.chatboxviews.get(jid).renderBookmarkForm();
  18124. }
  18125. });
  18126. _converse.Bookmark = Backbone.Model;
  18127. _converse.Bookmarks = Backbone.Collection.extend({
  18128. model: _converse.Bookmark,
  18129. comparator: 'name',
  18130. initialize: function initialize() {
  18131. this.on('add', _.flow(this.openBookmarkedRoom, this.markRoomAsBookmarked));
  18132. this.on('remove', this.markRoomAsUnbookmarked, this);
  18133. this.on('remove', this.sendBookmarkStanza, this);
  18134. var cache_key = "converse.room-bookmarks".concat(_converse.bare_jid);
  18135. this.fetched_flag = b64_sha1(cache_key + 'fetched');
  18136. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1(cache_key));
  18137. },
  18138. openBookmarkedRoom: function openBookmarkedRoom(bookmark) {
  18139. if (bookmark.get('autojoin')) {
  18140. var room = _converse.api.rooms.create(bookmark.get('jid'), bookmark.get('nick'));
  18141. if (!room.get('hidden')) {
  18142. room.trigger('show');
  18143. }
  18144. }
  18145. return bookmark;
  18146. },
  18147. fetchBookmarks: function fetchBookmarks() {
  18148. var deferred = u.getResolveablePromise();
  18149. if (this.browserStorage.records.length > 0) {
  18150. this.fetch({
  18151. 'success': _.bind(this.onCachedBookmarksFetched, this, deferred),
  18152. 'error': _.bind(this.onCachedBookmarksFetched, this, deferred)
  18153. });
  18154. } else if (!window.sessionStorage.getItem(this.fetched_flag)) {
  18155. // There aren't any cached bookmarks and the
  18156. // `fetched_flag` is off, so we query the XMPP server.
  18157. // If nothing is returned from the XMPP server, we set
  18158. // the `fetched_flag` to avoid calling the server again.
  18159. this.fetchBookmarksFromServer(deferred);
  18160. } else {
  18161. deferred.resolve();
  18162. }
  18163. return deferred;
  18164. },
  18165. onCachedBookmarksFetched: function onCachedBookmarksFetched(deferred) {
  18166. return deferred.resolve();
  18167. },
  18168. createBookmark: function createBookmark(options) {
  18169. _converse.bookmarks.create(options);
  18170. _converse.bookmarks.sendBookmarkStanza();
  18171. },
  18172. sendBookmarkStanza: function sendBookmarkStanza() {
  18173. var stanza = $iq({
  18174. 'type': 'set',
  18175. 'from': _converse.connection.jid
  18176. }).c('pubsub', {
  18177. 'xmlns': Strophe.NS.PUBSUB
  18178. }).c('publish', {
  18179. 'node': 'storage:bookmarks'
  18180. }).c('item', {
  18181. 'id': 'current'
  18182. }).c('storage', {
  18183. 'xmlns': 'storage:bookmarks'
  18184. });
  18185. this.each(function (model) {
  18186. stanza = stanza.c('conference', {
  18187. 'name': model.get('name'),
  18188. 'autojoin': model.get('autojoin'),
  18189. 'jid': model.get('jid')
  18190. }).c('nick').t(model.get('nick')).up().up();
  18191. });
  18192. stanza.up().up().up();
  18193. stanza.c('publish-options').c('x', {
  18194. 'xmlns': Strophe.NS.XFORM,
  18195. 'type': 'submit'
  18196. }).c('field', {
  18197. 'var': 'FORM_TYPE',
  18198. 'type': 'hidden'
  18199. }).c('value').t('http://jabber.org/protocol/pubsub#publish-options').up().up().c('field', {
  18200. 'var': 'pubsub#persist_items'
  18201. }).c('value').t('true').up().up().c('field', {
  18202. 'var': 'pubsub#access_model'
  18203. }).c('value').t('whitelist');
  18204. _converse.connection.sendIQ(stanza, null, this.onBookmarkError.bind(this));
  18205. },
  18206. onBookmarkError: function onBookmarkError(iq) {
  18207. _converse.log("Error while trying to add bookmark", Strophe.LogLevel.ERROR);
  18208. _converse.log(iq); // We remove all locally cached bookmarks and fetch them
  18209. // again from the server.
  18210. this.reset();
  18211. this.fetchBookmarksFromServer(null);
  18212. window.alert(__("Sorry, something went wrong while trying to save your bookmark."));
  18213. },
  18214. fetchBookmarksFromServer: function fetchBookmarksFromServer(deferred) {
  18215. var stanza = $iq({
  18216. 'from': _converse.connection.jid,
  18217. 'type': 'get'
  18218. }).c('pubsub', {
  18219. 'xmlns': Strophe.NS.PUBSUB
  18220. }).c('items', {
  18221. 'node': 'storage:bookmarks'
  18222. });
  18223. _converse.connection.sendIQ(stanza, _.bind(this.onBookmarksReceived, this, deferred), _.bind(this.onBookmarksReceivedError, this, deferred));
  18224. },
  18225. markRoomAsBookmarked: function markRoomAsBookmarked(bookmark) {
  18226. var room = _converse.chatboxes.get(bookmark.get('jid'));
  18227. if (!_.isUndefined(room)) {
  18228. room.save('bookmarked', true);
  18229. }
  18230. },
  18231. markRoomAsUnbookmarked: function markRoomAsUnbookmarked(bookmark) {
  18232. var room = _converse.chatboxes.get(bookmark.get('jid'));
  18233. if (!_.isUndefined(room)) {
  18234. room.save('bookmarked', false);
  18235. }
  18236. },
  18237. createBookmarksFromStanza: function createBookmarksFromStanza(stanza) {
  18238. var _this2 = this;
  18239. var bookmarks = sizzle('items[node="storage:bookmarks"] ' + 'item#current ' + 'storage[xmlns="storage:bookmarks"] ' + 'conference', stanza);
  18240. _.forEach(bookmarks, function (bookmark) {
  18241. _this2.create({
  18242. 'jid': bookmark.getAttribute('jid'),
  18243. 'name': bookmark.getAttribute('name'),
  18244. 'autojoin': bookmark.getAttribute('autojoin') === 'true',
  18245. 'nick': bookmark.querySelector('nick').textContent
  18246. });
  18247. });
  18248. },
  18249. onBookmarksReceived: function onBookmarksReceived(deferred, iq) {
  18250. this.createBookmarksFromStanza(iq);
  18251. if (!_.isUndefined(deferred)) {
  18252. return deferred.resolve();
  18253. }
  18254. },
  18255. onBookmarksReceivedError: function onBookmarksReceivedError(deferred, iq) {
  18256. window.sessionStorage.setItem(this.fetched_flag, true);
  18257. _converse.log('Error while fetching bookmarks', Strophe.LogLevel.WARN);
  18258. _converse.log(iq.outerHTML, Strophe.LogLevel.DEBUG);
  18259. if (!_.isNil(deferred)) {
  18260. if (iq.querySelector('error[type="cancel"] item-not-found')) {
  18261. // Not an exception, the user simply doesn't have
  18262. // any bookmarks.
  18263. return deferred.resolve();
  18264. } else {
  18265. return deferred.reject(new Error("Could not fetch bookmarks"));
  18266. }
  18267. }
  18268. }
  18269. });
  18270. _converse.BookmarksList = Backbone.Model.extend({
  18271. defaults: {
  18272. "toggle-state": _converse.OPENED
  18273. }
  18274. });
  18275. _converse.BookmarkView = Backbone.VDOMView.extend({
  18276. toHTML: function toHTML() {
  18277. return tpl_bookmark({
  18278. 'hidden': _converse.hide_open_bookmarks && _converse.chatboxes.where({
  18279. 'jid': this.model.get('jid')
  18280. }).length,
  18281. 'bookmarked': true,
  18282. 'info_leave_room': __('Leave this room'),
  18283. 'info_remove': __('Remove this bookmark'),
  18284. 'info_remove_bookmark': __('Unbookmark this room'),
  18285. 'info_title': __('Show more information on this room'),
  18286. 'jid': this.model.get('jid'),
  18287. 'name': Strophe.xmlunescape(this.model.get('name')),
  18288. 'open_title': __('Click to open this room')
  18289. });
  18290. }
  18291. });
  18292. _converse.BookmarksView = Backbone.OrderedListView.extend({
  18293. tagName: 'div',
  18294. className: 'bookmarks-list list-container rooms-list-container',
  18295. events: {
  18296. 'click .add-bookmark': 'addBookmark',
  18297. 'click .bookmarks-toggle': 'toggleBookmarksList',
  18298. 'click .remove-bookmark': 'removeBookmark',
  18299. 'click .open-room': 'openRoom'
  18300. },
  18301. listSelector: '.rooms-list',
  18302. ItemView: _converse.BookmarkView,
  18303. subviewIndex: 'jid',
  18304. initialize: function initialize() {
  18305. Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
  18306. this.model.on('add', this.showOrHide, this);
  18307. this.model.on('remove', this.showOrHide, this);
  18308. _converse.chatboxes.on('add', this.renderBookmarkListElement, this);
  18309. _converse.chatboxes.on('remove', this.renderBookmarkListElement, this);
  18310. var cachekey = "converse.room-bookmarks".concat(_converse.bare_jid, "-list-model");
  18311. this.list_model = new _converse.BookmarksList();
  18312. this.list_model.id = cachekey;
  18313. this.list_model.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1(cachekey));
  18314. this.list_model.fetch();
  18315. this.render();
  18316. this.sortAndPositionAllItems();
  18317. },
  18318. render: function render() {
  18319. this.el.innerHTML = tpl_bookmarks_list({
  18320. 'toggle_state': this.list_model.get('toggle-state'),
  18321. 'desc_bookmarks': __('Click to toggle the bookmarks list'),
  18322. 'label_bookmarks': __('Bookmarks'),
  18323. '_converse': _converse
  18324. });
  18325. this.showOrHide();
  18326. this.insertIntoControlBox();
  18327. return this;
  18328. },
  18329. insertIntoControlBox: function insertIntoControlBox() {
  18330. var controlboxview = _converse.chatboxviews.get('controlbox');
  18331. if (!_.isUndefined(controlboxview) && !_converse.root.contains(this.el)) {
  18332. var el = controlboxview.el.querySelector('.bookmarks-list');
  18333. if (!_.isNull(el)) {
  18334. el.parentNode.replaceChild(this.el, el);
  18335. }
  18336. }
  18337. },
  18338. openRoom: function openRoom(ev) {
  18339. ev.preventDefault();
  18340. var name = ev.target.textContent;
  18341. var jid = ev.target.getAttribute('data-room-jid');
  18342. var data = {
  18343. 'name': name || Strophe.unescapeNode(Strophe.getNodeFromJid(jid)) || jid
  18344. };
  18345. _converse.api.rooms.open(jid, data);
  18346. },
  18347. removeBookmark: _converse.removeBookmarkViaEvent,
  18348. addBookmark: _converse.addBookmarkViaEvent,
  18349. renderBookmarkListElement: function renderBookmarkListElement(chatbox) {
  18350. var bookmarkview = this.get(chatbox.get('jid'));
  18351. if (_.isNil(bookmarkview)) {
  18352. // A chat box has been closed, but we don't have a
  18353. // bookmark for it, so nothing further to do here.
  18354. return;
  18355. }
  18356. bookmarkview.render();
  18357. this.showOrHide();
  18358. },
  18359. showOrHide: function showOrHide(item) {
  18360. if (_converse.hide_open_bookmarks) {
  18361. var bookmarks = this.model.filter(function (bookmark) {
  18362. return !_converse.chatboxes.get(bookmark.get('jid'));
  18363. });
  18364. if (!bookmarks.length) {
  18365. u.hideElement(this.el);
  18366. return;
  18367. }
  18368. }
  18369. if (this.model.models.length) {
  18370. u.showElement(this.el);
  18371. }
  18372. },
  18373. toggleBookmarksList: function toggleBookmarksList(ev) {
  18374. if (ev && ev.preventDefault) {
  18375. ev.preventDefault();
  18376. }
  18377. var icon_el = ev.target.querySelector('.fa');
  18378. if (u.hasClass('fa-caret-down', icon_el)) {
  18379. u.slideIn(this.el.querySelector('.bookmarks'));
  18380. this.list_model.save({
  18381. 'toggle-state': _converse.CLOSED
  18382. });
  18383. icon_el.classList.remove("fa-caret-down");
  18384. icon_el.classList.add("fa-caret-right");
  18385. } else {
  18386. icon_el.classList.remove("fa-caret-right");
  18387. icon_el.classList.add("fa-caret-down");
  18388. u.slideOut(this.el.querySelector('.bookmarks'));
  18389. this.list_model.save({
  18390. 'toggle-state': _converse.OPENED
  18391. });
  18392. }
  18393. }
  18394. });
  18395. _converse.checkBookmarksSupport = function () {
  18396. return new Promise(function (resolve, reject) {
  18397. Promise.all([_converse.api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid), _converse.api.disco.supports(Strophe.NS.PUBSUB + '#publish-options', _converse.bare_jid)]).then(function (args) {
  18398. resolve(args[0] && (args[1].supported || _converse.allow_public_bookmarks));
  18399. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  18400. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  18401. };
  18402. var initBookmarks = function initBookmarks() {
  18403. if (!_converse.allow_bookmarks) {
  18404. return;
  18405. }
  18406. _converse.checkBookmarksSupport().then(function (supported) {
  18407. if (supported) {
  18408. _converse.bookmarks = new _converse.Bookmarks();
  18409. _converse.bookmarksview = new _converse.BookmarksView({
  18410. 'model': _converse.bookmarks
  18411. });
  18412. _converse.bookmarks.fetchBookmarks().catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)).then(function () {
  18413. return _converse.emit('bookmarksInitialized');
  18414. });
  18415. } else {
  18416. _converse.emit('bookmarksInitialized');
  18417. }
  18418. });
  18419. };
  18420. u.onMultipleEvents([{
  18421. 'object': _converse,
  18422. 'event': 'chatBoxesFetched'
  18423. }, {
  18424. 'object': _converse,
  18425. 'event': 'roomsPanelRendered'
  18426. }], initBookmarks);
  18427. _converse.on('reconnected', initBookmarks);
  18428. _converse.on('connected', function () {
  18429. // Add a handler for bookmarks pushed from other connected clients
  18430. // (from the same user obviously)
  18431. _converse.connection.addHandler(function (message) {
  18432. if (message.querySelector('event[xmlns="' + Strophe.NS.PUBSUB + '#event"]')) {
  18433. _converse.bookmarks.createBookmarksFromStanza(message);
  18434. }
  18435. }, null, 'message', 'headline', null, _converse.bare_jid);
  18436. });
  18437. }
  18438. });
  18439. });
  18440. //# sourceMappingURL=converse-bookmarks.js.map;
  18441. define('tpl!rooms_list', ['lodash'], function(_) {return function(o) {
  18442. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  18443. function print() { __p += __j.call(arguments, '') }
  18444. __p += '<a href="#" class="rooms-toggle open-rooms-toggle" title="' +
  18445. __e(o.desc_rooms) +
  18446. '">\n <span class="fa ';
  18447. if (o.toggle_state === o._converse.OPENED) { ;
  18448. __p += ' fa-caret-down ';
  18449. } else { ;
  18450. __p += ' fa-caret-right ';
  18451. } ;
  18452. __p += '">\n </span> ' +
  18453. __e(o.label_rooms) +
  18454. '</a>\n<div class="rooms-list open-rooms-list"></div>\n';
  18455. return __p
  18456. };});
  18457. define('tpl!rooms_list_item', ['lodash'], function(_) {return function(o) {
  18458. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  18459. function print() { __p += __j.call(arguments, '') }
  18460. __p += '<div class="room-item">\n<div class="available-chatroom d-flex flex-row ';
  18461. if (o.num_unread_general) { ;
  18462. __p += ' unread-msgs ';
  18463. } ;
  18464. __p += '" data-room-jid="' +
  18465. __e(o.jid) +
  18466. '">\n';
  18467. if (o.num_unread) { ;
  18468. __p += '\n <span class="msgs-indicator badge badge-info">' +
  18469. __e( o.num_unread ) +
  18470. '</span>\n';
  18471. } ;
  18472. __p += '\n<a class="open-room available-room w-100"\n data-room-jid="' +
  18473. __e(o.jid) +
  18474. '"\n title="' +
  18475. __e(o.open_title) +
  18476. '" href="#">' +
  18477. __e(o.name || o.jid) +
  18478. '</a>\n\n<a class="right close-room icon-leave"\n data-room-jid="' +
  18479. __e(o.jid) +
  18480. '"\n data-room-name="' +
  18481. __e(o.name || o.jid) +
  18482. '"\n title="' +
  18483. __e(o.info_leave_room) +
  18484. '" href="#">&nbsp;</a>\n\n';
  18485. if (o.allow_bookmarks) { ;
  18486. __p += '\n<a class="fa align-self-center ';
  18487. if (o.bookmarked) { ;
  18488. __p += ' fa-bookmark remove-bookmark button-on ';
  18489. } else { ;
  18490. __p += ' add-bookmark fa-bookmark-o ';
  18491. } ;
  18492. __p += '"\n data-room-jid="' +
  18493. __e(o.jid) +
  18494. '" data-bookmark-name="' +
  18495. __e(o.name) +
  18496. '"\n title="';
  18497. if (o.bookmarked) { ;
  18498. __p += ' ' +
  18499. __e(o.info_remove_bookmark) +
  18500. ' ';
  18501. } else { ;
  18502. __p += ' ' +
  18503. __e(o.info_add_bookmark) +
  18504. ' ';
  18505. } ;
  18506. __p += '"\n href="#">&nbsp;</a>\n';
  18507. } ;
  18508. __p += '\n<a class="room-info fa fa-info-circle align-self-center" data-room-jid="' +
  18509. __e(o.jid) +
  18510. '"\n title="' +
  18511. __e(o.info_title) +
  18512. '" href="#">&nbsp;</a>\n</div>\n<div>\n';
  18513. return __p
  18514. };});
  18515. // Converse.js (A browser based XMPP chat client)
  18516. // http://conversejs.org
  18517. //
  18518. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  18519. // Licensed under the Mozilla Public License (MPLv2)
  18520. //
  18521. /*global define */
  18522. /* This is a non-core Converse.js plugin which shows a list of currently open
  18523. * rooms in the "Rooms Panel" of the ControlBox.
  18524. */
  18525. (function (root, factory) {
  18526. define('converse-roomslist',["utils", "converse-core", "converse-muc", "tpl!rooms_list", "tpl!rooms_list_item"], factory);
  18527. })(void 0, function (utils, converse, muc, tpl_rooms_list, tpl_rooms_list_item) {
  18528. var _converse$env = converse.env,
  18529. Backbone = _converse$env.Backbone,
  18530. Promise = _converse$env.Promise,
  18531. Strophe = _converse$env.Strophe,
  18532. b64_sha1 = _converse$env.b64_sha1,
  18533. sizzle = _converse$env.sizzle,
  18534. _ = _converse$env._;
  18535. var u = converse.env.utils;
  18536. converse.plugins.add('converse-roomslist', {
  18537. /* Optional dependencies are other plugins which might be
  18538. * overridden or relied upon, and therefore need to be loaded before
  18539. * this plugin. They are called "optional" because they might not be
  18540. * available, in which case any overrides applicable to them will be
  18541. * ignored.
  18542. *
  18543. * It's possible however to make optional dependencies non-optional.
  18544. * If the setting "strict_plugin_dependencies" is set to true,
  18545. * an error will be raised if the plugin is not found.
  18546. *
  18547. * NB: These plugins need to have already been loaded via require.js.
  18548. */
  18549. dependencies: ["converse-controlbox", "converse-muc", "converse-bookmarks"],
  18550. initialize: function initialize() {
  18551. /* The initialize function gets called as soon as the plugin is
  18552. * loaded by converse.js's plugin machinery.
  18553. */
  18554. var _converse = this._converse,
  18555. __ = _converse.__;
  18556. _converse.OpenRooms = Backbone.Collection.extend({
  18557. comparator: function comparator(room) {
  18558. if (room.get('bookmarked')) {
  18559. var bookmark = _.head(_converse.bookmarksview.model.where({
  18560. 'jid': room.get('jid')
  18561. }));
  18562. return bookmark.get('name');
  18563. } else {
  18564. return room.get('name');
  18565. }
  18566. },
  18567. initialize: function initialize() {
  18568. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.open-rooms-{_converse.bare_jid}"));
  18569. _converse.chatboxes.on('add', this.onChatBoxAdded, this);
  18570. _converse.chatboxes.on('change:bookmarked', this.onChatBoxChanged, this);
  18571. _converse.chatboxes.on('change:name', this.onChatBoxChanged, this);
  18572. _converse.chatboxes.on('change:num_unread', this.onChatBoxChanged, this);
  18573. _converse.chatboxes.on('change:num_unread_general', this.onChatBoxChanged, this);
  18574. _converse.chatboxes.on('remove', this.onChatBoxRemoved, this);
  18575. this.reset(_.map(_converse.chatboxes.where({
  18576. 'type': 'chatroom'
  18577. }), 'attributes'));
  18578. },
  18579. onChatBoxAdded: function onChatBoxAdded(item) {
  18580. if (item.get('type') === 'chatroom') {
  18581. this.create(item.attributes);
  18582. }
  18583. },
  18584. onChatBoxChanged: function onChatBoxChanged(item) {
  18585. if (item.get('type') === 'chatroom') {
  18586. var room = this.get(item.get('jid'));
  18587. if (!_.isNil(room)) {
  18588. room.set(item.attributes);
  18589. }
  18590. }
  18591. },
  18592. onChatBoxRemoved: function onChatBoxRemoved(item) {
  18593. if (item.get('type') === 'chatroom') {
  18594. var room = this.get(item.get('jid'));
  18595. this.remove(room);
  18596. }
  18597. }
  18598. });
  18599. _converse.RoomsList = Backbone.Model.extend({
  18600. defaults: {
  18601. "toggle-state": _converse.OPENED
  18602. }
  18603. });
  18604. _converse.RoomsListElementView = Backbone.VDOMView.extend({
  18605. initialize: function initialize() {
  18606. this.model.on('destroy', this.remove, this);
  18607. this.model.on('remove', this.remove, this);
  18608. this.model.on('change:bookmarked', this.render, this);
  18609. this.model.on('change:name', this.render, this);
  18610. this.model.on('change:num_unread', this.render, this);
  18611. this.model.on('change:num_unread_general', this.render, this);
  18612. },
  18613. getRoomsListElementName: function getRoomsListElementName() {
  18614. if (this.model.get('bookmarked') && _converse.bookmarksview) {
  18615. var bookmark = _.head(_converse.bookmarksview.model.where({
  18616. 'jid': this.model.get('jid')
  18617. }));
  18618. return bookmark.get('name');
  18619. } else {
  18620. return this.model.get('name');
  18621. }
  18622. },
  18623. toHTML: function toHTML() {
  18624. return tpl_rooms_list_item(_.extend(this.model.toJSON(), {
  18625. // XXX: By the time this renders, the _converse.bookmarks
  18626. // collection should already exist if bookmarks are
  18627. // supported by the XMPP server. So we can use it
  18628. // as a check for support (other ways of checking are async).
  18629. 'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
  18630. 'info_leave_room': __('Leave this room'),
  18631. 'info_remove_bookmark': __('Unbookmark this room'),
  18632. 'info_add_bookmark': __('Bookmark this room'),
  18633. 'info_title': __('Show more information on this room'),
  18634. 'name': this.getRoomsListElementName(),
  18635. 'open_title': __('Click to open this room')
  18636. }));
  18637. }
  18638. });
  18639. _converse.RoomsListView = Backbone.OrderedListView.extend({
  18640. tagName: 'div',
  18641. className: 'open-rooms-list list-container rooms-list-container',
  18642. events: {
  18643. 'click .add-bookmark': 'addBookmark',
  18644. 'click .close-room': 'closeRoom',
  18645. 'click .rooms-toggle': 'toggleRoomsList',
  18646. 'click .remove-bookmark': 'removeBookmark',
  18647. 'click .open-room': 'openRoom'
  18648. },
  18649. listSelector: '.rooms-list',
  18650. ItemView: _converse.RoomsListElementView,
  18651. subviewIndex: 'jid',
  18652. initialize: function initialize() {
  18653. Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
  18654. this.model.on('add', this.showOrHide, this);
  18655. this.model.on('remove', this.showOrHide, this);
  18656. var cachekey = "converse.roomslist".concat(_converse.bare_jid);
  18657. this.list_model = new _converse.RoomsList();
  18658. this.list_model.id = cachekey;
  18659. this.list_model.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1(cachekey));
  18660. this.list_model.fetch();
  18661. this.render();
  18662. this.sortAndPositionAllItems();
  18663. },
  18664. render: function render() {
  18665. this.el.innerHTML = tpl_rooms_list({
  18666. 'toggle_state': this.list_model.get('toggle-state'),
  18667. 'desc_rooms': __('Click to toggle the rooms list'),
  18668. 'label_rooms': __('Open Rooms'),
  18669. '_converse': _converse
  18670. });
  18671. if (this.list_model.get('toggle-state') !== _converse.OPENED) {
  18672. this.el.querySelector('.open-rooms-list').classList.add('collapsed');
  18673. }
  18674. this.showOrHide();
  18675. this.insertIntoControlBox();
  18676. return this;
  18677. },
  18678. insertIntoControlBox: function insertIntoControlBox() {
  18679. var controlboxview = _converse.chatboxviews.get('controlbox');
  18680. if (!_.isUndefined(controlboxview) && !_converse.root.contains(this.el)) {
  18681. var el = controlboxview.el.querySelector('.open-rooms-list');
  18682. if (!_.isNull(el)) {
  18683. el.parentNode.replaceChild(this.el, el);
  18684. }
  18685. }
  18686. },
  18687. hide: function hide() {
  18688. u.hideElement(this.el);
  18689. },
  18690. show: function show() {
  18691. u.showElement(this.el);
  18692. },
  18693. openRoom: function openRoom(ev) {
  18694. ev.preventDefault();
  18695. var name = ev.target.textContent;
  18696. var jid = ev.target.getAttribute('data-room-jid');
  18697. var data = {
  18698. 'name': name || Strophe.unescapeNode(Strophe.getNodeFromJid(jid)) || jid
  18699. };
  18700. _converse.api.rooms.open(jid, data);
  18701. },
  18702. closeRoom: function closeRoom(ev) {
  18703. ev.preventDefault();
  18704. var name = ev.target.getAttribute('data-room-name');
  18705. var jid = ev.target.getAttribute('data-room-jid');
  18706. if (confirm(__("Are you sure you want to leave the room %1$s?", name))) {
  18707. _converse.chatboxviews.get(jid).leave();
  18708. }
  18709. },
  18710. showOrHide: function showOrHide(item) {
  18711. if (!this.model.models.length) {
  18712. u.hideElement(this.el);
  18713. } else {
  18714. u.showElement(this.el);
  18715. }
  18716. },
  18717. removeBookmark: _converse.removeBookmarkViaEvent,
  18718. addBookmark: _converse.addBookmarkViaEvent,
  18719. toggleRoomsList: function toggleRoomsList(ev) {
  18720. var _this = this;
  18721. if (ev && ev.preventDefault) {
  18722. ev.preventDefault();
  18723. }
  18724. var icon_el = ev.target.querySelector('.fa');
  18725. if (icon_el.classList.contains("fa-caret-down")) {
  18726. utils.slideIn(this.el.querySelector('.open-rooms-list')).then(function () {
  18727. _this.list_model.save({
  18728. 'toggle-state': _converse.CLOSED
  18729. });
  18730. icon_el.classList.remove("fa-caret-down");
  18731. icon_el.classList.add("fa-caret-right");
  18732. });
  18733. } else {
  18734. utils.slideOut(this.el.querySelector('.open-rooms-list')).then(function () {
  18735. _this.list_model.save({
  18736. 'toggle-state': _converse.OPENED
  18737. });
  18738. icon_el.classList.remove("fa-caret-right");
  18739. icon_el.classList.add("fa-caret-down");
  18740. });
  18741. }
  18742. }
  18743. });
  18744. var initRoomsListView = function initRoomsListView() {
  18745. _converse.rooms_list_view = new _converse.RoomsListView({
  18746. 'model': new _converse.OpenRooms()
  18747. });
  18748. };
  18749. if (_converse.allow_bookmarks) {
  18750. u.onMultipleEvents([{
  18751. 'object': _converse,
  18752. 'event': 'chatBoxesFetched'
  18753. }, {
  18754. 'object': _converse,
  18755. 'event': 'roomsPanelRendered'
  18756. }, {
  18757. 'object': _converse,
  18758. 'event': 'bookmarksInitialized'
  18759. }], initRoomsListView);
  18760. } else {
  18761. u.onMultipleEvents([{
  18762. 'object': _converse,
  18763. 'event': 'chatBoxesFetched'
  18764. }, {
  18765. 'object': _converse,
  18766. 'event': 'roomsPanelRendered'
  18767. }], initRoomsListView);
  18768. }
  18769. _converse.api.listen.on('reconnected', initRoomsListView);
  18770. }
  18771. });
  18772. });
  18773. //# sourceMappingURL=converse-roomslist.js.map;
  18774. // Converse.js (A browser based XMPP chat client)
  18775. // http://conversejs.org
  18776. //
  18777. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  18778. // Licensed under the Mozilla Public License (MPLv2)
  18779. //
  18780. /*global define */
  18781. // XEP-0059 Result Set Management
  18782. (function (root, factory) {
  18783. define('converse-mam',["sizzle", "converse-core", "utils", "converse-disco", "strophe.rsm"], factory);
  18784. })(void 0, function (sizzle, converse, utils) {
  18785. "use strict";
  18786. var CHATROOMS_TYPE = 'chatroom';
  18787. var _converse$env = converse.env,
  18788. Promise = _converse$env.Promise,
  18789. Strophe = _converse$env.Strophe,
  18790. $iq = _converse$env.$iq,
  18791. _ = _converse$env._,
  18792. moment = _converse$env.moment;
  18793. var RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count']; // XEP-0313 Message Archive Management
  18794. var MAM_ATTRIBUTES = ['with', 'start', 'end'];
  18795. function getMessageArchiveID(stanza) {
  18796. var result = sizzle("result[xmlns=\"".concat(Strophe.NS.MAM, "\"]"), stanza).pop();
  18797. if (!_.isUndefined(result)) {
  18798. return result.getAttribute('id');
  18799. }
  18800. var stanza_id = sizzle("stanza-id[xmlns=\"".concat(Strophe.NS.SID, "\"]"), stanza).pop();
  18801. if (!_.isUndefined(stanza_id)) {
  18802. return stanza_id.getAttribute('id');
  18803. }
  18804. }
  18805. function queryForArchivedMessages(_converse, options, callback, errback) {
  18806. /* Internal function, called by the "archive.query" API method.
  18807. */
  18808. var date;
  18809. if (_.isFunction(options)) {
  18810. callback = options;
  18811. errback = callback;
  18812. }
  18813. var queryid = _converse.connection.getUniqueId();
  18814. var attrs = {
  18815. 'type': 'set'
  18816. };
  18817. if (!_.isUndefined(options) && options.groupchat) {
  18818. if (!options['with']) {
  18819. // eslint-disable-line dot-notation
  18820. throw new Error('You need to specify a "with" value containing ' + 'the chat room JID, when querying groupchat messages.');
  18821. }
  18822. attrs.to = options['with']; // eslint-disable-line dot-notation
  18823. }
  18824. var stanza = $iq(attrs).c('query', {
  18825. 'xmlns': Strophe.NS.MAM,
  18826. 'queryid': queryid
  18827. });
  18828. if (!_.isUndefined(options)) {
  18829. stanza.c('x', {
  18830. 'xmlns': Strophe.NS.XFORM,
  18831. 'type': 'submit'
  18832. }).c('field', {
  18833. 'var': 'FORM_TYPE',
  18834. 'type': 'hidden'
  18835. }).c('value').t(Strophe.NS.MAM).up().up();
  18836. if (options['with'] && !options.groupchat) {
  18837. // eslint-disable-line dot-notation
  18838. stanza.c('field', {
  18839. 'var': 'with'
  18840. }).c('value').t(options['with']).up().up(); // eslint-disable-line dot-notation
  18841. }
  18842. _.each(['start', 'end'], function (t) {
  18843. if (options[t]) {
  18844. date = moment(options[t]);
  18845. if (date.isValid()) {
  18846. stanza.c('field', {
  18847. 'var': t
  18848. }).c('value').t(date.format()).up().up();
  18849. } else {
  18850. throw new TypeError("archive.query: invalid date provided for: ".concat(t));
  18851. }
  18852. }
  18853. });
  18854. stanza.up();
  18855. if (options instanceof Strophe.RSM) {
  18856. stanza.cnode(options.toXML());
  18857. } else if (_.intersection(RSM_ATTRIBUTES, _.keys(options)).length) {
  18858. stanza.cnode(new Strophe.RSM(options).toXML());
  18859. }
  18860. }
  18861. var messages = [];
  18862. var message_handler = _converse.connection.addHandler(function (message) {
  18863. if (options.groupchat && message.getAttribute('from') !== options['with']) {
  18864. // eslint-disable-line dot-notation
  18865. return true;
  18866. }
  18867. var result = message.querySelector('result');
  18868. if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
  18869. messages.push(message);
  18870. }
  18871. return true;
  18872. }, Strophe.NS.MAM);
  18873. _converse.connection.sendIQ(stanza, function (iq) {
  18874. _converse.connection.deleteHandler(message_handler);
  18875. if (_.isFunction(callback)) {
  18876. var set = iq.querySelector('set');
  18877. var rsm;
  18878. if (!_.isUndefined(set)) {
  18879. rsm = new Strophe.RSM({
  18880. xml: set
  18881. });
  18882. _.extend(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
  18883. }
  18884. callback(messages, rsm);
  18885. }
  18886. }, function () {
  18887. _converse.connection.deleteHandler(message_handler);
  18888. if (_.isFunction(errback)) {
  18889. errback.apply(this, arguments);
  18890. }
  18891. }, _converse.message_archiving_timeout);
  18892. }
  18893. converse.plugins.add('converse-mam', {
  18894. dependencies: ['converse-chatview', 'converse-muc', 'converse-muc-views'],
  18895. overrides: {
  18896. // Overrides mentioned here will be picked up by converse.js's
  18897. // plugin architecture they will replace existing methods on the
  18898. // relevant objects or classes.
  18899. //
  18900. // New functions which don't exist yet can also be added.
  18901. ChatBox: {
  18902. getMessageAttributes: function getMessageAttributes(message, delay, original_stanza) {
  18903. var attrs = this.__super__.getMessageAttributes.apply(this, arguments);
  18904. var archive_id = getMessageArchiveID(original_stanza);
  18905. if (archive_id) {
  18906. attrs.archive_id = archive_id;
  18907. }
  18908. return attrs;
  18909. }
  18910. },
  18911. ChatBoxView: {
  18912. render: function render() {
  18913. var result = this.__super__.render.apply(this, arguments);
  18914. if (!this.disable_mam) {
  18915. this.content.addEventListener('scroll', _.debounce(this.onScroll.bind(this), 100));
  18916. }
  18917. return result;
  18918. },
  18919. fetchNewestMessages: function fetchNewestMessages() {
  18920. var _this = this;
  18921. /* Fetches messages that might have been archived *after*
  18922. * the last archived message in our local cache.
  18923. */
  18924. if (this.disable_mam) {
  18925. return;
  18926. }
  18927. var _converse = this.__super__._converse;
  18928. _converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid).then(function (result) {
  18929. // Success
  18930. if (result.supported) {
  18931. var most_recent_msg = utils.getMostRecentMessage(_this.model);
  18932. if (_.isNil(most_recent_msg)) {
  18933. _this.fetchArchivedMessages();
  18934. } else {
  18935. var archive_id = most_recent_msg.get('archive_id');
  18936. if (archive_id) {
  18937. _this.fetchArchivedMessages({
  18938. 'after': most_recent_msg.get('archive_id')
  18939. });
  18940. } else {
  18941. _this.fetchArchivedMessages({
  18942. 'start': most_recent_msg.get('time')
  18943. });
  18944. }
  18945. }
  18946. }
  18947. }, function () {
  18948. // Error
  18949. _converse.log("Error or timeout while checking for MAM support", Strophe.LogLevel.ERROR);
  18950. }).catch(function (msg) {
  18951. _this.clearSpinner();
  18952. _converse.log(msg, Strophe.LogLevel.FATAL);
  18953. });
  18954. },
  18955. fetchArchivedMessagesIfNecessary: function fetchArchivedMessagesIfNecessary() {
  18956. var _this2 = this;
  18957. /* Check if archived messages should be fetched, and if so, do so. */
  18958. if (this.disable_mam || this.model.get('mam_initialized')) {
  18959. return;
  18960. }
  18961. var _converse = this.__super__._converse;
  18962. _converse.api.disco.supports(Strophe.NS.MAM, _converse.bare_jid).then(function (result) {
  18963. // Success
  18964. if (result.supported) {
  18965. _this2.fetchArchivedMessages();
  18966. }
  18967. _this2.model.save({
  18968. 'mam_initialized': true
  18969. });
  18970. }, function () {
  18971. // Error
  18972. _converse.log("Error or timeout while checking for MAM support", Strophe.LogLevel.ERROR);
  18973. }).catch(function (msg) {
  18974. _this2.clearSpinner();
  18975. _converse.log(msg, Strophe.LogLevel.FATAL);
  18976. });
  18977. },
  18978. fetchArchivedMessages: function fetchArchivedMessages(options) {
  18979. var _this3 = this;
  18980. /* Fetch archived chat messages from the XMPP server.
  18981. *
  18982. * Then, upon receiving them, call onMessage on the chat
  18983. * box, so that they are displayed inside it.
  18984. */
  18985. var _converse = this.__super__._converse;
  18986. if (!_converse.disco_entities.get(_converse.bare_jid).features.findWhere({
  18987. 'var': Strophe.NS.MAM
  18988. })) {
  18989. _converse.log("Attempted to fetch archived messages but this " + "user's server doesn't support XEP-0313", Strophe.LogLevel.WARN);
  18990. return;
  18991. }
  18992. if (this.disable_mam) {
  18993. return;
  18994. }
  18995. this.addSpinner();
  18996. _converse.api.archive.query(_.extend({
  18997. 'before': '',
  18998. // Page backwards from the most recent message
  18999. 'max': _converse.archived_messages_page_size,
  19000. 'with': this.model.get('jid')
  19001. }, options), function (messages) {
  19002. // Success
  19003. _this3.clearSpinner();
  19004. if (messages.length) {
  19005. _.each(messages, _converse.chatboxes.onMessage.bind(_converse.chatboxes));
  19006. }
  19007. }, function () {
  19008. // Error
  19009. _this3.clearSpinner();
  19010. _converse.log("Error or timeout while trying to fetch " + "archived messages", Strophe.LogLevel.ERROR);
  19011. });
  19012. },
  19013. onScroll: function onScroll(ev) {
  19014. var _converse = this.__super__._converse;
  19015. if (this.content.scrollTop === 0 && this.model.messages.length) {
  19016. var oldest_message = this.model.messages.at(0);
  19017. var archive_id = oldest_message.get('archive_id');
  19018. if (archive_id) {
  19019. this.fetchArchivedMessages({
  19020. 'before': archive_id
  19021. });
  19022. } else {
  19023. this.fetchArchivedMessages({
  19024. 'end': oldest_message.get('time')
  19025. });
  19026. }
  19027. }
  19028. }
  19029. },
  19030. ChatRoomView: {
  19031. initialize: function initialize() {
  19032. var _converse = this.__super__._converse;
  19033. this.__super__.initialize.apply(this, arguments);
  19034. this.model.on('change:mam_enabled', this.fetchArchivedMessagesIfNecessary, this);
  19035. this.model.on('change:connection_status', this.fetchArchivedMessagesIfNecessary, this);
  19036. },
  19037. isDuplicate: function isDuplicate(message, original_stanza) {
  19038. var result = this.__super__.isDuplicate.apply(this, arguments);
  19039. if (result) {
  19040. return result;
  19041. }
  19042. var archive_id = getMessageArchiveID(original_stanza);
  19043. if (archive_id) {
  19044. return this.model.messages.filter({
  19045. 'archive_id': archive_id
  19046. }).length > 0;
  19047. }
  19048. },
  19049. renderChatArea: function renderChatArea() {
  19050. var result = this.__super__.renderChatArea.apply(this, arguments);
  19051. if (!this.disable_mam) {
  19052. this.content.addEventListener('scroll', _.debounce(this.onScroll.bind(this), 100));
  19053. }
  19054. return result;
  19055. },
  19056. handleMUCMessage: function handleMUCMessage(stanza) {
  19057. /* MAM (message archive management XEP-0313) messages are
  19058. * ignored, since they're handled separately.
  19059. */
  19060. if (sizzle("[xmlns=\"".concat(Strophe.NS.MAM, "\"]"), stanza).length > 0) {
  19061. return true;
  19062. }
  19063. return this.__super__.handleMUCMessage.apply(this, arguments);
  19064. },
  19065. fetchArchivedMessagesIfNecessary: function fetchArchivedMessagesIfNecessary() {
  19066. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED || !this.model.get('mam_enabled') || this.model.get('mam_initialized')) {
  19067. return;
  19068. }
  19069. this.fetchArchivedMessages();
  19070. this.model.save({
  19071. 'mam_initialized': true
  19072. });
  19073. },
  19074. fetchArchivedMessages: function fetchArchivedMessages(options) {
  19075. /* Fetch archived chat messages for this Chat Room
  19076. *
  19077. * Then, upon receiving them, call onChatRoomMessage
  19078. * so that they are displayed inside it.
  19079. */
  19080. var that = this;
  19081. var _converse = this.__super__._converse;
  19082. this.addSpinner();
  19083. _converse.api.archive.query(_.extend({
  19084. 'groupchat': true,
  19085. 'before': '',
  19086. // Page backwards from the most recent message
  19087. 'with': this.model.get('jid'),
  19088. 'max': _converse.archived_messages_page_size
  19089. }, options), function (messages) {
  19090. that.clearSpinner();
  19091. if (messages.length) {
  19092. _.each(messages, that.onChatRoomMessage.bind(that));
  19093. }
  19094. }, function () {
  19095. that.clearSpinner();
  19096. _converse.log("Error while trying to fetch archived messages", Strophe.LogLevel.WARN);
  19097. });
  19098. }
  19099. }
  19100. },
  19101. initialize: function initialize() {
  19102. /* The initialize function gets called as soon as the plugin is
  19103. * loaded by Converse.js's plugin machinery.
  19104. */
  19105. var _converse = this._converse;
  19106. _converse.api.settings.update({
  19107. archived_messages_page_size: '50',
  19108. message_archiving: undefined,
  19109. // Supported values are 'always', 'never', 'roster' (https://xmpp.org/extensions/xep-0313.html#prefs)
  19110. message_archiving_timeout: 8000 // Time (in milliseconds) to wait before aborting MAM request
  19111. });
  19112. _converse.onMAMError = function (iq) {
  19113. if (iq.querySelectorAll('feature-not-implemented').length) {
  19114. _converse.log("Message Archive Management (XEP-0313) not supported by this server", Strophe.LogLevel.WARN);
  19115. } else {
  19116. _converse.log("An error occured while trying to set archiving preferences.", Strophe.LogLevel.ERROR);
  19117. _converse.log(iq);
  19118. }
  19119. };
  19120. _converse.onMAMPreferences = function (feature, iq) {
  19121. /* Handle returned IQ stanza containing Message Archive
  19122. * Management (XEP-0313) preferences.
  19123. *
  19124. * XXX: For now we only handle the global default preference.
  19125. * The XEP also provides for per-JID preferences, which is
  19126. * currently not supported in converse.js.
  19127. *
  19128. * Per JID preferences will be set in chat boxes, so it'll
  19129. * probbaly be handled elsewhere in any case.
  19130. */
  19131. var preference = sizzle("prefs[xmlns=\"".concat(Strophe.NS.MAM, "\"]"), iq).pop();
  19132. var default_pref = preference.getAttribute('default');
  19133. if (default_pref !== _converse.message_archiving) {
  19134. var stanza = $iq({
  19135. 'type': 'set'
  19136. }).c('prefs', {
  19137. 'xmlns': Strophe.NS.MAM,
  19138. 'default': _converse.message_archiving
  19139. });
  19140. _.each(preference.children, function (child) {
  19141. stanza.cnode(child).up();
  19142. });
  19143. _converse.connection.sendIQ(stanza, _.partial(function (feature, iq) {
  19144. // XXX: Strictly speaking, the server should respond with the updated prefs
  19145. // (see example 18: https://xmpp.org/extensions/xep-0313.html#config)
  19146. // but Prosody doesn't do this, so we don't rely on it.
  19147. feature.save({
  19148. 'preferences': {
  19149. 'default': _converse.message_archiving
  19150. }
  19151. });
  19152. }, feature), _converse.onMAMError);
  19153. } else {
  19154. feature.save({
  19155. 'preferences': {
  19156. 'default': _converse.message_archiving
  19157. }
  19158. });
  19159. }
  19160. };
  19161. /* Event handlers */
  19162. _converse.on('serviceDiscovered', function (feature) {
  19163. var prefs = feature.get('preferences') || {};
  19164. if (feature.get('var') === Strophe.NS.MAM && prefs['default'] !== _converse.message_archiving && // eslint-disable-line dot-notation
  19165. !_.isUndefined(_converse.message_archiving)) {
  19166. // Ask the server for archiving preferences
  19167. _converse.connection.sendIQ($iq({
  19168. 'type': 'get'
  19169. }).c('prefs', {
  19170. 'xmlns': Strophe.NS.MAM
  19171. }), _.partial(_converse.onMAMPreferences, feature), _.partial(_converse.onMAMError, feature));
  19172. }
  19173. });
  19174. _converse.on('addClientFeatures', function () {
  19175. _converse.connection.disco.addFeature(Strophe.NS.MAM);
  19176. });
  19177. _converse.on('afterMessagesFetched', function (chatboxview) {
  19178. chatboxview.fetchNewestMessages();
  19179. });
  19180. _converse.on('reconnected', function () {
  19181. var private_chats = _converse.chatboxviews.filter(function (view) {
  19182. return _.at(view, 'model.attributes.type')[0] === 'chatbox';
  19183. });
  19184. _.each(private_chats, function (view) {
  19185. return view.fetchNewestMessages();
  19186. });
  19187. });
  19188. _.extend(_converse.api, {
  19189. /* Extend default converse.js API to add methods specific to MAM
  19190. */
  19191. 'archive': {
  19192. 'query': function query(options, callback, errback) {
  19193. /* Do a MAM (XEP-0313) query for archived messages.
  19194. *
  19195. * Parameters:
  19196. * (Object) options - Query parameters, either
  19197. * MAM-specific or also for Result Set Management.
  19198. * (Function) callback - A function to call whenever
  19199. * we receive query-relevant stanza.
  19200. * (Function) errback - A function to call when an
  19201. * error stanza is received.
  19202. *
  19203. * The options parameter can also be an instance of
  19204. * Strophe.RSM to enable easy querying between results pages.
  19205. *
  19206. * When the the callback is called, a Strophe.RSM object is
  19207. * returned on which "next" or "previous" can be called
  19208. * before passing it in again to this method, to
  19209. * get the next or previous page in the result set.
  19210. */
  19211. if (!_converse.api.connection.connected()) {
  19212. throw new Error('Can\'t call `api.archive.query` before having established an XMPP session');
  19213. }
  19214. return queryForArchivedMessages(_converse, options, callback, errback);
  19215. }
  19216. }
  19217. });
  19218. }
  19219. });
  19220. });
  19221. //# sourceMappingURL=converse-mam.js.map;
  19222. define('tpl!add_chatroom_modal', ['lodash'], function(_) {return function(o) {
  19223. var __t, __p = '', __e = _.escape;
  19224. __p += '<div class="modal fade" id="add-chatroom-modal" tabindex="-1" role="dialog" aria-labelledby="add-chatroom-modal-label" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title"\n id="add-chatroom-modal-label">' +
  19225. __e(o.heading_new_chatroom) +
  19226. '</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="Close">\n <span aria-hidden="true">&times;</span>\n </button>\n </div>\n <div class="modal-body">\n <form class="converse-form add-chatroom">\n <div class="form-group">\n <label for="chatroom">' +
  19227. __e(o.label_room_address) +
  19228. ':</label>\n <input type="text" required="required" name="chatroom" class="form-control" placeholder="' +
  19229. __e(o.chatroom_placeholder) +
  19230. '">\n </div>\n <div class="form-group">\n <label for="nickname">' +
  19231. __e(o.label_nickname) +
  19232. ':</label>\n <input type="text" name="nickname" value="' +
  19233. __e(o.nick) +
  19234. '" class="form-control">\n </div>\n <input type="submit" class="btn btn-primary" name="join" value="' +
  19235. __e(o.label_join) +
  19236. '">\n </form>\n </div>\n </div>\n </div>\n</div>\n';
  19237. return __p
  19238. };});
  19239. define('tpl!chatarea', ['lodash'], function(_) {return function(o) {
  19240. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19241. function print() { __p += __j.call(arguments, '') }
  19242. __p += '<div class="chat-area col-md-9 col-8">\n <div class="chat-content ';
  19243. if (o.show_send_button) { ;
  19244. __p += 'chat-content-sendbutton';
  19245. } ;
  19246. __p += '"></div>\n <div class="new-msgs-indicator hidden">▼ ' +
  19247. __e( o.unread_msgs ) +
  19248. ' ▼</div>\n <form class="sendXMPPMessage">\n ';
  19249. if (o.show_toolbar) { ;
  19250. __p += '\n <ul class="chat-toolbar no-text-select"></ul>\n ';
  19251. } ;
  19252. __p += '\n <textarea type="text" class="chat-textarea ';
  19253. if (o.show_send_button) { ;
  19254. __p += 'chat-textarea-send-button';
  19255. } ;
  19256. __p += '"\n placeholder="' +
  19257. __e(o.label_message) +
  19258. '"></textarea>\n ';
  19259. if (o.show_send_button) { ;
  19260. __p += '\n <button type="submit" class="pure-button send-button">' +
  19261. __e( o.label_send ) +
  19262. '</button>\n ';
  19263. } ;
  19264. __p += '\n </form>\n</div>\n';
  19265. return __p
  19266. };});
  19267. define('tpl!chatroom', ['lodash'], function(_) {return function(o) {
  19268. var __t, __p = '';
  19269. __p += '<div class="flyout box-flyout">\n <div class="chat-head chat-head-chatroom row no-gutters"></div>\n <div class="chat-body chatroom-body row no-gutters"></div>\n</div>\n';
  19270. return __p
  19271. };});
  19272. define('tpl!chatroom_disconnect', ['lodash'], function(_) {return function(o) {
  19273. var __t, __p = '', __e = _.escape;
  19274. __p += '<p class="disconnect-msg">' +
  19275. __e(o.disconnect_message) +
  19276. '</p>\n';
  19277. return __p
  19278. };});
  19279. define('tpl!chatroom_features', ['lodash'], function(_) {return function(o) {
  19280. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19281. function print() { __p += __j.call(arguments, '') }
  19282. if (o.has_features) { ;
  19283. __p += '\n<p class="occupants-heading">' +
  19284. __e(o.label_features) +
  19285. '</p>\n';
  19286. } ;
  19287. __p += '\n<ul class="features-list">\n';
  19288. if (o.passwordprotected) { ;
  19289. __p += '\n<li class="feature" title="' +
  19290. __e( o.tt_passwordprotected ) +
  19291. '"><span class="fa fa-lock"></span>' +
  19292. __e( o.label_passwordprotected ) +
  19293. '</li>\n';
  19294. } ;
  19295. __p += '\n';
  19296. if (o.unsecured) { ;
  19297. __p += '\n<li class="feature" title="' +
  19298. __e( o.tt_unsecured ) +
  19299. '"><span class="fa fa-unlock"></span>' +
  19300. __e( o.label_unsecured ) +
  19301. '</li>\n';
  19302. } ;
  19303. __p += '\n';
  19304. if (o.hidden) { ;
  19305. __p += '\n<li class="feature" title="' +
  19306. __e( o.tt_hidden ) +
  19307. '"><span class="fa fa-eye-slash"></span>' +
  19308. __e( o.label_hidden ) +
  19309. '</li>\n';
  19310. } ;
  19311. __p += '\n';
  19312. if (o.public_room) { ;
  19313. __p += '\n<li class="feature" title="' +
  19314. __e( o.tt_public ) +
  19315. '"><span class="fa fa-eye"></span>' +
  19316. __e( o.label_public ) +
  19317. '</li>\n';
  19318. } ;
  19319. __p += '\n';
  19320. if (o.membersonly) { ;
  19321. __p += '\n<li class="feature" title="' +
  19322. __e( o.tt_membersonly ) +
  19323. '"><span class="fa fa-address-book"></span>' +
  19324. __e( o.label_membersonly ) +
  19325. '</li>\n';
  19326. } ;
  19327. __p += '\n';
  19328. if (o.open) { ;
  19329. __p += '\n<li class="feature" title="' +
  19330. __e( o.tt_open ) +
  19331. '"><span class="fa fa-globe"></span>' +
  19332. __e( o.label_open ) +
  19333. '</li>\n';
  19334. } ;
  19335. __p += '\n';
  19336. if (o.persistent) { ;
  19337. __p += '\n<li class="feature" title="' +
  19338. __e( o.tt_persistent ) +
  19339. '"><span class="fa fa-save"></span>' +
  19340. __e( o.label_persistent ) +
  19341. '</li>\n';
  19342. } ;
  19343. __p += '\n';
  19344. if (o.temporary) { ;
  19345. __p += '\n<li class="feature" title="' +
  19346. __e( o.tt_temporary ) +
  19347. '"><span class="fa fa-snowflake-o"></span>' +
  19348. __e( o.label_temporary ) +
  19349. '</li>\n';
  19350. } ;
  19351. __p += '\n';
  19352. if (o.nonanonymous) { ;
  19353. __p += '\n<li class="feature" title="' +
  19354. __e( o.tt_nonanonymous ) +
  19355. '"><span class="fa fa-idcard-dark"></span>' +
  19356. __e( o.label_nonanonymous ) +
  19357. '</li>\n';
  19358. } ;
  19359. __p += '\n';
  19360. if (o.semianonymous) { ;
  19361. __p += '\n<li class="feature" title="' +
  19362. __e( o.tt_semianonymous ) +
  19363. '"><span class="fa fa-user-secret"></span>' +
  19364. __e( o.label_semianonymous ) +
  19365. '</li>\n';
  19366. } ;
  19367. __p += '\n';
  19368. if (o.moderated) { ;
  19369. __p += '\n<li class="feature" title="' +
  19370. __e( o.tt_moderated ) +
  19371. '"><span class="fa fa-gavel"></span>' +
  19372. __e( o.label_moderated ) +
  19373. '</li>\n';
  19374. } ;
  19375. __p += '\n';
  19376. if (o.unmoderated) { ;
  19377. __p += '\n<li class="feature" title="' +
  19378. __e( o.tt_unmoderated ) +
  19379. '"><span class="fa fa-info-circle"></span>' +
  19380. __e( o.label_unmoderated ) +
  19381. '</li>\n';
  19382. } ;
  19383. __p += '\n';
  19384. if (o.mam_enabled) { ;
  19385. __p += '\n<li class="feature" title="' +
  19386. __e( o.tt_mam_enabled ) +
  19387. '"><span class="fa fa-database"></span>' +
  19388. __e( o.label_mam_enabled ) +
  19389. '</li>\n';
  19390. } ;
  19391. __p += '\n</ul>\n';
  19392. return __p
  19393. };});
  19394. define('tpl!chatroom_form', ['lodash'], function(_) {return function(o) {
  19395. var __t, __p = '';
  19396. __p += '<div class="chatroom-form-container">\n <form class="converse-form chatroom-form">\n <fieldset class="form-group">\n <span class="spinner fa fa-spinner centered"/>\n </fieldset>\n </form>\n</div>\n';
  19397. return __p
  19398. };});
  19399. define('tpl!chatroom_head', ['lodash'], function(_) {return function(o) {
  19400. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19401. function print() { __p += __j.call(arguments, '') }
  19402. __p += '<div class="col">\n <div class="chat-title" title="' +
  19403. __e(o.jid) +
  19404. '">\n ';
  19405. if (o.name && o.name !== o.Strophe.getNodeFromJid(o.jid)) { ;
  19406. __p += '\n <span class="chatroom-name">' +
  19407. __e( o.name ) +
  19408. '</span>\n ';
  19409. } else { ;
  19410. __p += '\n <span class="chatroom-name">' +
  19411. __e( o.Strophe.getNodeFromJid(o.jid) ) +
  19412. '</span>@' +
  19413. __e( o.Strophe.getDomainFromJid(o.jid) ) +
  19414. '\n ';
  19415. } ;
  19416. __p += '\n <p class="chatroom-description">' +
  19417. __e( o.description ) +
  19418. '<p/>\n </div>\n</div>\n<div class="chatbox-buttons row no-gutters">\n <a class="chatbox-btn close-chatbox-button fa fa-sign-out" title="' +
  19419. __e(o.info_close) +
  19420. '"></a>\n ';
  19421. if (o.affiliation == 'owner') { ;
  19422. __p += '\n <a class="chatbox-btn configure-chatroom-button fa fa-wrench" title="' +
  19423. __e(o.info_configure) +
  19424. ' "></a>\n ';
  19425. } ;
  19426. __p += '\n</div>\n';
  19427. return __p
  19428. };});
  19429. define('tpl!chatroom_invite', ['lodash'], function(_) {return function(o) {
  19430. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19431. function print() { __p += __j.call(arguments, '') }
  19432. __p += '<form class="room-invite">\n ';
  19433. if (o.error_message) { ;
  19434. __p += '\n <span class="pure-form-message error">' +
  19435. __e(o.error_message) +
  19436. '</span>\n ';
  19437. } ;
  19438. __p += '\n <input class="form-control invited-contact" placeholder="' +
  19439. __e(o.label_invitation) +
  19440. '" type="text"/>\n</form>\n';
  19441. return __p
  19442. };});
  19443. define('tpl!chatroom_nickname_form', ['lodash'], function(_) {return function(o) {
  19444. var __t, __p = '', __e = _.escape;
  19445. __p += '<div class="chatroom-form-container">\n <form class="converse-form chatroom-form converse-centered-form">\n <fieldset class="form-group">\n <label>' +
  19446. __e(o.heading) +
  19447. '</label>\n <p class="validation-message">' +
  19448. __e(o.validation_message) +
  19449. '</p>\n <input type="text" required="required" name="nick" class="form-control" placeholder="' +
  19450. __e(o.label_nickname) +
  19451. '"/>\n </fieldset>\n <input type="submit" class="btn btn-primary" name="join" value="' +
  19452. __e(o.label_join) +
  19453. '"/>\n </form>\n</div>\n';
  19454. return __p
  19455. };});
  19456. define('tpl!chatroom_password_form', ['lodash'], function(_) {return function(o) {
  19457. var __t, __p = '', __e = _.escape;
  19458. __p += '<div class="chatroom-form-container">\n <form class="pure-form converse-form chatroom-form">\n <fieldset class="form-group">\n <legend>' +
  19459. __e(o.heading) +
  19460. '</legend>\n <label>' +
  19461. __e(o.label_password) +
  19462. '</label>\n <input type="password" name="password"/>\n </fieldset>\n <input class="btn btn-primary" type="submit" value="' +
  19463. __e(o.label_submit) +
  19464. '"/>\n </form>\n</div>\n';
  19465. return __p
  19466. };});
  19467. define('tpl!chatroom_sidebar', ['lodash'], function(_) {return function(o) {
  19468. var __t, __p = '', __e = _.escape;
  19469. __p += '<!-- <div class="occupants"> -->\n<p class="occupants-heading">' +
  19470. __e(o.label_occupants) +
  19471. '</p>\n<ul class="occupant-list"></ul>\n<div class="chatroom-features"></div>\n<!-- </div> -->\n';
  19472. return __p
  19473. };});
  19474. define('tpl!chatroom_toolbar', ['lodash'], function(_) {return function(o) {
  19475. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19476. function print() { __p += __j.call(arguments, '') }
  19477. if (o.use_emoji) { ;
  19478. __p += '\n<li class="toggle-toolbar-menu toggle-smiley dropup">\n <a class="btn toggle-smiley fa fa-smile-o" title="' +
  19479. __e(o.label_insert_smiley) +
  19480. '" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></a> \n <div class="emoji-picker dropdown-menu toolbar-menu"></div>\n</li>\n';
  19481. } ;
  19482. __p += '\n';
  19483. if (o.show_call_button) { ;
  19484. __p += '\n<li class="toggle-call fa fa-phone" title="' +
  19485. __e(o.label_start_call) +
  19486. '"></li>\n';
  19487. } ;
  19488. __p += '\n';
  19489. if (o.show_occupants_toggle) { ;
  19490. __p += '\n<li class="toggle-occupants fa fa-users" title="' +
  19491. __e(o.label_hide_occupants) +
  19492. '"></li>\n';
  19493. } ;
  19494. __p += '\n';
  19495. return __p
  19496. };});
  19497. define('tpl!list_chatrooms_modal', ['lodash'], function(_) {return function(o) {
  19498. var __t, __p = '', __e = _.escape;
  19499. __p += '<div class="modal fade" id="list-chatrooms-modal" tabindex="-1" role="dialog" aria-labelledby="list-chatrooms-modal-label" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title"\n id="list-chatrooms-modal-label">' +
  19500. __e(o.heading_list_chatrooms) +
  19501. '</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="Close">\n <span aria-hidden="true">&times;</span>\n </button>\n </div>\n <div class="modal-body">\n <form class="converse-form list-chatrooms">\n <div class="form-group">\n <label for="chatroom">' +
  19502. __e(o.label_server_address) +
  19503. ':</label>\n <input type="text" value="' +
  19504. __e(o.muc_domain) +
  19505. '" required="required" name="server" class="form-control" placeholder="' +
  19506. __e(o.server_placeholder) +
  19507. '">\n </div>\n <input type="submit" class="btn btn-primary" name="join" value="' +
  19508. __e(o.label_query) +
  19509. '">\n </form>\n <ul class="available-chatrooms list-group"></ul>\n </div>\n </div>\n </div>\n</div>\n';
  19510. return __p
  19511. };});
  19512. define('tpl!occupant', ['lodash'], function(_) {return function(o) {
  19513. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19514. function print() { __p += __j.call(arguments, '') }
  19515. __p += '<li class="' +
  19516. __e( o.role ) +
  19517. ' occupant" id="' +
  19518. __e( o.id ) +
  19519. '"\n ';
  19520. if (o.role === "moderator") { ;
  19521. __p += '\n title="' +
  19522. __e( o.jid ) +
  19523. ' ' +
  19524. __e( o.desc_moderator ) +
  19525. ' ' +
  19526. __e( o.hint_occupant ) +
  19527. '"\n ';
  19528. } ;
  19529. __p += '\n ';
  19530. if (o.role === "occupant") { ;
  19531. __p += '\n title="' +
  19532. __e( o.jid ) +
  19533. ' ' +
  19534. __e( o.desc_occupant ) +
  19535. ' ' +
  19536. __e( o.hint_occupant ) +
  19537. '"\n ';
  19538. } ;
  19539. __p += '\n ';
  19540. if (o.role === "visitor") { ;
  19541. __p += '\n title="' +
  19542. __e( o.jid ) +
  19543. ' ' +
  19544. __e( o.desc_visitor ) +
  19545. ' ' +
  19546. __e( o.hint_occupant ) +
  19547. '"\n ';
  19548. } ;
  19549. __p += '\n ';
  19550. if (!_.includes(["visitor", "occupant", "moderator"], o.role)) { ;
  19551. __p += '\n title="' +
  19552. __e( o.jid ) +
  19553. ' ' +
  19554. __e( o.hint_occupant ) +
  19555. '"\n ';
  19556. } ;
  19557. __p += '><div class="occupant-status occupant-' +
  19558. __e(o.show) +
  19559. ' circle" title="' +
  19560. __e(o.hint_show) +
  19561. '"></div>' +
  19562. __e(o.nick) +
  19563. '</li>\n';
  19564. return __p
  19565. };});
  19566. define('tpl!room_description', ['lodash'], function(_) {return function(o) {
  19567. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  19568. function print() { __p += __j.call(arguments, '') }
  19569. __p += '<!-- FIXME: check markup in mockup -->\n<div class="room-info">\n<p class="room-info"><strong>' +
  19570. __e(o.label_jid) +
  19571. '</strong> ' +
  19572. __e(o.jid) +
  19573. '</p>\n<p class="room-info"><strong>' +
  19574. __e(o.label_desc) +
  19575. '</strong> ' +
  19576. __e(o.desc) +
  19577. '</p>\n<p class="room-info"><strong>' +
  19578. __e(o.label_occ) +
  19579. '</strong> ' +
  19580. __e(o.occ) +
  19581. '</p>\n<p class="room-info"><strong>' +
  19582. __e(o.label_features) +
  19583. '</strong>\n <ul>\n ';
  19584. if (o.passwordprotected) { ;
  19585. __p += '\n <li class="room-info locked">' +
  19586. __e(o.label_requires_auth) +
  19587. '</li>\n ';
  19588. } ;
  19589. __p += '\n ';
  19590. if (o.hidden) { ;
  19591. __p += '\n <li class="room-info">' +
  19592. __e(o.label_hidden) +
  19593. '</li>\n ';
  19594. } ;
  19595. __p += '\n ';
  19596. if (o.membersonly) { ;
  19597. __p += '\n <li class="room-info">' +
  19598. __e(o.label_requires_invite) +
  19599. '</li>\n ';
  19600. } ;
  19601. __p += '\n ';
  19602. if (o.moderated) { ;
  19603. __p += '\n <li class="room-info">' +
  19604. __e(o.label_moderated) +
  19605. '</li>\n ';
  19606. } ;
  19607. __p += '\n ';
  19608. if (o.nonanonymous) { ;
  19609. __p += '\n <li class="room-info">' +
  19610. __e(o.label_non_anon) +
  19611. '</li>\n ';
  19612. } ;
  19613. __p += '\n ';
  19614. if (o.open) { ;
  19615. __p += '\n <li class="room-info">' +
  19616. __e(o.label_open_room) +
  19617. '</li>\n ';
  19618. } ;
  19619. __p += '\n ';
  19620. if (o.persistent) { ;
  19621. __p += '\n <li class="room-info">' +
  19622. __e(o.label_permanent_room) +
  19623. '</li>\n ';
  19624. } ;
  19625. __p += '\n ';
  19626. if (o.publicroom) { ;
  19627. __p += '\n <li class="room-info">' +
  19628. __e(o.label_public) +
  19629. '</li>\n ';
  19630. } ;
  19631. __p += '\n ';
  19632. if (o.semianonymous) { ;
  19633. __p += '\n <li class="room-info">' +
  19634. __e(o.label_semi_anon) +
  19635. '</li>\n ';
  19636. } ;
  19637. __p += '\n ';
  19638. if (o.temporary) { ;
  19639. __p += '\n <li class="room-info">' +
  19640. __e(o.label_temp_room) +
  19641. '</li>\n ';
  19642. } ;
  19643. __p += '\n ';
  19644. if (o.unmoderated) { ;
  19645. __p += '\n <li class="room-info">' +
  19646. __e(o.label_unmoderated) +
  19647. '</li>\n ';
  19648. } ;
  19649. __p += '\n </ul>\n</p>\n</div>\n';
  19650. return __p
  19651. };});
  19652. define('tpl!room_item', ['lodash'], function(_) {return function(o) {
  19653. var __t, __p = '', __e = _.escape;
  19654. __p += '<li class="room-item list-group-item">\n <div class="available-chatroom d-flex flex-row">\n <a class="open-room available-room w-100"\n data-room-jid="' +
  19655. __e(o.jid) +
  19656. '"\n data-room-name="' +
  19657. __e(o.name) +
  19658. '"\n title="' +
  19659. __e(o.open_title) +
  19660. '"\n href="#">' +
  19661. __e(o.name) +
  19662. '</a>\n <a class="right room-info icon-room-info"\n data-room-jid="' +
  19663. __e(o.jid) +
  19664. '"\n title="' +
  19665. __e(o.info_title) +
  19666. '" href="#">&nbsp;</a>\n </div>\n</li>\n';
  19667. return __p
  19668. };});
  19669. define('tpl!room_panel', ['lodash'], function(_) {return function(o) {
  19670. var __t, __p = '', __e = _.escape;
  19671. __p += '<!-- <div id="chatrooms"> -->\n<div class="d-flex">\n <span class="w-100">' +
  19672. __e(o.heading_chatrooms) +
  19673. '</span>\n <a class="chatbox-btn trigger-list-chatrooms-modal fa fa-list-ul" title="' +
  19674. __e(o.title_list_rooms) +
  19675. '" data-toggle="modal" data-target="#list-chatrooms-modal"></a>\n <a class="chatbox-btn trigger-add-chatrooms-modal fa fa-users" title="' +
  19676. __e(o.title_new_room) +
  19677. '" data-toggle="modal" data-target="#add-chatrooms-modal"></a>\n</div>\n<div class="list-container open-rooms-list rooms-list-container"></div>\n<div class="list-container bookmarks-list rooms-list-container"></div>\n<!-- </div> -->\n';
  19678. return __p
  19679. };});
  19680. define('tpl!rooms_results', ['lodash'], function(_) {return function(o) {
  19681. var __t, __p = '', __e = _.escape;
  19682. __p += '<li class="list-group-item active">' +
  19683. __e( o.feedback_text ) +
  19684. '</dt>\n';
  19685. return __p
  19686. };});
  19687. // Converse.js (A browser based XMPP chat client)
  19688. // http://conversejs.org
  19689. //
  19690. // Copyright (c) 2012-2018, Jan-Carel Brand <jc@opkode.com>
  19691. // Licensed under the Mozilla Public License (MPLv2)
  19692. //
  19693. /* This is a Converse.js plugin which add support for multi-user chat rooms, as
  19694. * specified in XEP-0045 Multi-user chat.
  19695. */
  19696. (function (root, factory) {
  19697. define('converse-muc-views',[
  19698. "converse-core",
  19699. "emojione",
  19700. "tpl!add_chatroom_modal",
  19701. "tpl!chatarea",
  19702. "tpl!chatroom",
  19703. "tpl!chatroom_disconnect",
  19704. "tpl!chatroom_features",
  19705. "tpl!chatroom_form",
  19706. "tpl!chatroom_head",
  19707. "tpl!chatroom_invite",
  19708. "tpl!chatroom_nickname_form",
  19709. "tpl!chatroom_password_form",
  19710. "tpl!chatroom_sidebar",
  19711. "tpl!chatroom_toolbar",
  19712. "tpl!info",
  19713. "tpl!list_chatrooms_modal",
  19714. "tpl!occupant",
  19715. "tpl!room_description",
  19716. "tpl!room_item",
  19717. "tpl!room_panel",
  19718. "tpl!rooms_results",
  19719. "tpl!spinner",
  19720. "awesomplete",
  19721. "converse-modal"
  19722. ], factory);
  19723. }(this, function (
  19724. converse,
  19725. emojione,
  19726. tpl_add_chatroom_modal,
  19727. tpl_chatarea,
  19728. tpl_chatroom,
  19729. tpl_chatroom_disconnect,
  19730. tpl_chatroom_features,
  19731. tpl_chatroom_form,
  19732. tpl_chatroom_head,
  19733. tpl_chatroom_invite,
  19734. tpl_chatroom_nickname_form,
  19735. tpl_chatroom_password_form,
  19736. tpl_chatroom_sidebar,
  19737. tpl_chatroom_toolbar,
  19738. tpl_info,
  19739. tpl_list_chatrooms_modal,
  19740. tpl_occupant,
  19741. tpl_room_description,
  19742. tpl_room_item,
  19743. tpl_room_panel,
  19744. tpl_rooms_results,
  19745. tpl_spinner,
  19746. Awesomplete
  19747. ) {
  19748. "use strict";
  19749. const { Backbone, Promise, Strophe, b64_sha1, moment, f, sizzle, _, $build, $iq, $msg, $pres } = converse.env;
  19750. const u = converse.env.utils;
  19751. const ROOM_FEATURES_MAP = {
  19752. 'passwordprotected': 'unsecured',
  19753. 'unsecured': 'passwordprotected',
  19754. 'hidden': 'publicroom',
  19755. 'publicroom': 'hidden',
  19756. 'membersonly': 'open',
  19757. 'open': 'membersonly',
  19758. 'persistent': 'temporary',
  19759. 'temporary': 'persistent',
  19760. 'nonanonymous': 'semianonymous',
  19761. 'semianonymous': 'nonanonymous',
  19762. 'moderated': 'unmoderated',
  19763. 'unmoderated': 'moderated'
  19764. };
  19765. converse.plugins.add('converse-muc-views', {
  19766. /* Dependencies are other plugins which might be
  19767. * overridden or relied upon, and therefore need to be loaded before
  19768. * this plugin. They are "optional" because they might not be
  19769. * available, in which case any overrides applicable to them will be
  19770. * ignored.
  19771. *
  19772. * NB: These plugins need to have already been loaded via require.js.
  19773. *
  19774. * It's possible to make these dependencies "non-optional".
  19775. * If the setting "strict_plugin_dependencies" is set to true,
  19776. * an error will be raised if the plugin is not found.
  19777. */
  19778. dependencies: ["converse-modal", "converse-controlbox", "converse-chatview"],
  19779. overrides: {
  19780. ControlBoxView: {
  19781. renderRoomsPanel () {
  19782. const { _converse } = this.__super__;
  19783. this.roomspanel = new _converse.RoomsPanel({
  19784. 'model': new (_converse.RoomsPanelModel.extend({
  19785. id: b64_sha1(`converse.roomspanel${_converse.bare_jid}`), // Required by sessionStorage
  19786. browserStorage: new Backbone.BrowserStorage[_converse.storage](
  19787. b64_sha1(`converse.roomspanel${_converse.bare_jid}`))
  19788. }))()
  19789. });
  19790. this.roomspanel.model.fetch();
  19791. this.el.querySelector('.controlbox-pane').insertAdjacentElement(
  19792. 'beforeEnd', this.roomspanel.render().el);
  19793. if (!this.roomspanel.model.get('nick')) {
  19794. this.roomspanel.model.save({
  19795. nick: Strophe.getNodeFromJid(_converse.bare_jid)
  19796. });
  19797. }
  19798. _converse.emit('roomsPanelRendered');
  19799. },
  19800. renderControlBoxPane () {
  19801. const { _converse } = this.__super__;
  19802. this.__super__.renderControlBoxPane.apply(this, arguments);
  19803. if (_converse.allow_muc) {
  19804. this.renderRoomsPanel();
  19805. }
  19806. },
  19807. },
  19808. ChatBoxViews: {
  19809. onChatBoxAdded (item) {
  19810. const { _converse } = this.__super__;
  19811. let view = this.get(item.get('id'));
  19812. if (!view && item.get('type') === converse.CHATROOMS_TYPE) {
  19813. view = new _converse.ChatRoomView({'model': item});
  19814. return this.add(item.get('id'), view);
  19815. } else {
  19816. return this.__super__.onChatBoxAdded.apply(this, arguments);
  19817. }
  19818. }
  19819. }
  19820. },
  19821. initialize () {
  19822. const { _converse } = this,
  19823. { __ } = _converse;
  19824. _converse.api.promises.add(['roomsPanelRendered']);
  19825. function insertRoomInfo (el, stanza) {
  19826. /* Insert room info (based on returned #disco IQ stanza)
  19827. *
  19828. * Parameters:
  19829. * (HTMLElement) el: The HTML DOM element that should
  19830. * contain the info.
  19831. * (XMLElement) stanza: The IQ stanza containing the room
  19832. * info.
  19833. */
  19834. // All MUC features found here: http://xmpp.org/registrar/disco-features.html
  19835. el.querySelector('span.spinner').remove();
  19836. el.querySelector('a.room-info').classList.add('selected');
  19837. el.insertAdjacentHTML(
  19838. 'beforeEnd',
  19839. tpl_room_description({
  19840. 'jid': stanza.getAttribute('from'),
  19841. 'desc': _.get(_.head(sizzle('field[var="muc#roominfo_description"] value', stanza)), 'textContent'),
  19842. 'occ': _.get(_.head(sizzle('field[var="muc#roominfo_occupants"] value', stanza)), 'textContent'),
  19843. 'hidden': sizzle('feature[var="muc_hidden"]', stanza).length,
  19844. 'membersonly': sizzle('feature[var="muc_membersonly"]', stanza).length,
  19845. 'moderated': sizzle('feature[var="muc_moderated"]', stanza).length,
  19846. 'nonanonymous': sizzle('feature[var="muc_nonanonymous"]', stanza).length,
  19847. 'open': sizzle('feature[var="muc_open"]', stanza).length,
  19848. 'passwordprotected': sizzle('feature[var="muc_passwordprotected"]', stanza).length,
  19849. 'persistent': sizzle('feature[var="muc_persistent"]', stanza).length,
  19850. 'publicroom': sizzle('feature[var="muc_publicroom"]', stanza).length,
  19851. 'semianonymous': sizzle('feature[var="muc_semianonymous"]', stanza).length,
  19852. 'temporary': sizzle('feature[var="muc_temporary"]', stanza).length,
  19853. 'unmoderated': sizzle('feature[var="muc_unmoderated"]', stanza).length,
  19854. 'label_desc': __('Description:'),
  19855. 'label_jid': __('Room Address (JID):'),
  19856. 'label_occ': __('Occupants:'),
  19857. 'label_features': __('Features:'),
  19858. 'label_requires_auth': __('Requires authentication'),
  19859. 'label_hidden': __('Hidden'),
  19860. 'label_requires_invite': __('Requires an invitation'),
  19861. 'label_moderated': __('Moderated'),
  19862. 'label_non_anon': __('Non-anonymous'),
  19863. 'label_open_room': __('Open room'),
  19864. 'label_permanent_room': __('Permanent room'),
  19865. 'label_public': __('Public'),
  19866. 'label_semi_anon': __('Semi-anonymous'),
  19867. 'label_temp_room': __('Temporary room'),
  19868. 'label_unmoderated': __('Unmoderated')
  19869. }));
  19870. }
  19871. function toggleRoomInfo (ev) {
  19872. /* Show/hide extra information about a room in a listing. */
  19873. const parent_el = u.ancestor(ev.target, '.room-item'),
  19874. div_el = parent_el.querySelector('div.room-info');
  19875. if (div_el) {
  19876. u.slideIn(div_el).then(u.removeElement)
  19877. parent_el.querySelector('a.room-info').classList.remove('selected');
  19878. } else {
  19879. parent_el.insertAdjacentHTML('beforeend', tpl_spinner());
  19880. _converse.connection.disco.info(
  19881. ev.target.getAttribute('data-room-jid'),
  19882. null,
  19883. _.partial(insertRoomInfo, parent_el)
  19884. );
  19885. }
  19886. }
  19887. _converse.ListChatRoomsModal = _converse.BootstrapModal.extend({
  19888. events: {
  19889. 'submit form': 'showRooms',
  19890. 'click a.room-info': 'toggleRoomInfo',
  19891. 'change input[name=nick]': 'setNick',
  19892. 'change input[name=server]': 'setDomain',
  19893. 'click .open-room': 'openRoom'
  19894. },
  19895. initialize () {
  19896. _converse.BootstrapModal.prototype.initialize.apply(this, arguments);
  19897. this.model.on('change:muc_domain', this.onDomainChange, this);
  19898. },
  19899. toHTML () {
  19900. return tpl_list_chatrooms_modal(_.extend(this.model.toJSON(), {
  19901. 'heading_list_chatrooms': __('Query for Chatrooms'),
  19902. 'label_server_address': __('Server address'),
  19903. 'label_query': __('Show rooms'),
  19904. 'server_placeholder': __('conference.example.org')
  19905. }));
  19906. },
  19907. openRoom (ev) {
  19908. ev.preventDefault();
  19909. const jid = ev.target.getAttribute('data-room-jid');
  19910. const name = ev.target.getAttribute('data-room-name');
  19911. this.modal.hide();
  19912. _converse.api.rooms.open(jid, {'name': name});
  19913. },
  19914. toggleRoomInfo (ev) {
  19915. ev.preventDefault();
  19916. toggleRoomInfo(ev);
  19917. },
  19918. onDomainChange (model) {
  19919. if (_converse.auto_list_rooms) {
  19920. this.updateRoomsList();
  19921. }
  19922. },
  19923. roomStanzaItemToHTMLElement (room) {
  19924. const name = Strophe.unescapeNode(
  19925. room.getAttribute('name') ||
  19926. room.getAttribute('jid')
  19927. );
  19928. const div = document.createElement('div');
  19929. div.innerHTML = tpl_room_item({
  19930. 'name': Strophe.xmlunescape(name),
  19931. 'jid': room.getAttribute('jid'),
  19932. 'open_title': __('Click to open this room'),
  19933. 'info_title': __('Show more information on this room')
  19934. });
  19935. return div.firstChild;
  19936. },
  19937. removeSpinner () {
  19938. _.each(this.el.querySelectorAll('span.spinner'),
  19939. (el) => el.parentNode.removeChild(el)
  19940. );
  19941. },
  19942. informNoRoomsFound () {
  19943. const chatrooms_el = this.el.querySelector('.available-chatrooms');
  19944. chatrooms_el.innerHTML = tpl_rooms_results({
  19945. 'feedback_text': __('No rooms found')
  19946. });
  19947. const input_el = this.el.querySelector('input[name="server"]');
  19948. input_el.classList.remove('hidden')
  19949. this.removeSpinner();
  19950. },
  19951. onRoomsFound (iq) {
  19952. /* Handle the IQ stanza returned from the server, containing
  19953. * all its public rooms.
  19954. */
  19955. const available_chatrooms = this.el.querySelector('.available-chatrooms');
  19956. this.rooms = iq.querySelectorAll('query item');
  19957. if (this.rooms.length) {
  19958. // For translators: %1$s is a variable and will be
  19959. // replaced with the XMPP server name
  19960. available_chatrooms.innerHTML = tpl_rooms_results({
  19961. 'feedback_text': __('Rooms found:')
  19962. });
  19963. const fragment = document.createDocumentFragment();
  19964. const children = _.reject(_.map(this.rooms, this.roomStanzaItemToHTMLElement), _.isNil)
  19965. _.each(children, (child) => fragment.appendChild(child));
  19966. available_chatrooms.appendChild(fragment);
  19967. this.removeSpinner();
  19968. } else {
  19969. this.informNoRoomsFound();
  19970. }
  19971. return true;
  19972. },
  19973. updateRoomsList () {
  19974. /* Send an IQ stanza to the server asking for all rooms
  19975. */
  19976. _converse.connection.sendIQ(
  19977. $iq({
  19978. to: this.model.get('muc_domain'),
  19979. from: _converse.connection.jid,
  19980. type: "get"
  19981. }).c("query", {xmlns: Strophe.NS.DISCO_ITEMS}),
  19982. this.onRoomsFound.bind(this),
  19983. this.informNoRoomsFound.bind(this),
  19984. 5000
  19985. );
  19986. },
  19987. showRooms (ev) {
  19988. ev.preventDefault();
  19989. const data = new FormData(ev.target);
  19990. this.model.save('muc_domain', data.get('server'));
  19991. this.updateRoomsList();
  19992. },
  19993. setDomain (ev) {
  19994. this.model.save({muc_domain: ev.target.value});
  19995. },
  19996. setNick (ev) {
  19997. this.model.save({nick: ev.target.value});
  19998. }
  19999. });
  20000. _converse.AddChatRoomModal = _converse.BootstrapModal.extend({
  20001. events: {
  20002. 'submit form.add-chatroom': 'openChatRoom'
  20003. },
  20004. toHTML () {
  20005. return tpl_add_chatroom_modal(_.extend(this.model.toJSON(), {
  20006. 'heading_new_chatroom': __('Enter a new Chatroom'),
  20007. 'label_room_address': __('Room address'),
  20008. 'label_nickname': __('Optional nickname'),
  20009. 'chatroom_placeholder': __('name@conference.example.org'),
  20010. 'label_join': __('Join'),
  20011. }));
  20012. },
  20013. parseRoomDataFromEvent (form) {
  20014. const data = new FormData(form);
  20015. const jid = data.get('chatroom');
  20016. const server = Strophe.getDomainFromJid(jid);
  20017. this.model.save('muc_domain', server);
  20018. return {
  20019. 'jid': jid,
  20020. 'nick': data.get('nickname')
  20021. }
  20022. },
  20023. openChatRoom (ev) {
  20024. ev.preventDefault();
  20025. const data = this.parseRoomDataFromEvent(ev.target);
  20026. _converse.api.rooms.open(data.jid, data);
  20027. this.modal.hide();
  20028. ev.target.reset();
  20029. }
  20030. });
  20031. _converse.ChatRoomView = _converse.ChatBoxView.extend({
  20032. /* Backbone.NativeView which renders a chat room, based upon the view
  20033. * for normal one-on-one chat boxes.
  20034. */
  20035. length: 300,
  20036. tagName: 'div',
  20037. className: 'chatbox chatroom hidden',
  20038. is_chatroom: true,
  20039. events: {
  20040. 'click .close-chatbox-button': 'close',
  20041. 'click .configure-chatroom-button': 'getAndRenderConfigurationForm',
  20042. 'click .toggle-smiley': 'toggleEmojiMenu',
  20043. 'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
  20044. 'click .toggle-clear': 'clearChatRoomMessages',
  20045. 'click .toggle-call': 'toggleCall',
  20046. 'click .toggle-occupants': 'toggleOccupants',
  20047. 'click .new-msgs-indicator': 'viewUnreadMessages',
  20048. 'click .occupant': 'onOccupantClicked',
  20049. 'keypress .chat-textarea': 'keyPressed',
  20050. 'click .send-button': 'onFormSubmitted'
  20051. },
  20052. initialize () {
  20053. this.scrollDown = _.debounce(this._scrollDown, 250);
  20054. this.markScrolled = _.debounce(this._markScrolled, 100);
  20055. this.model.messages.on('add', this.onMessageAdded, this);
  20056. this.model.on('show', this.show, this);
  20057. this.model.on('destroy', this.hide, this);
  20058. this.model.on('change:connection_status', this.afterConnected, this);
  20059. this.model.on('change:affiliation', this.renderHeading, this);
  20060. this.model.on('change:chat_state', this.sendChatState, this);
  20061. this.model.on('change:description', this.renderHeading, this);
  20062. this.model.on('change:name', this.renderHeading, this);
  20063. this.createEmojiPicker();
  20064. this.createOccupantsView();
  20065. this.render().insertIntoDOM();
  20066. this.registerHandlers();
  20067. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
  20068. const handler = () => {
  20069. this.join();
  20070. this.fetchMessages();
  20071. _converse.emit('chatRoomOpened', this);
  20072. }
  20073. this.getRoomFeatures().then(handler, handler);
  20074. } else {
  20075. this.fetchMessages();
  20076. _converse.emit('chatRoomOpened', this);
  20077. }
  20078. },
  20079. render () {
  20080. this.el.setAttribute('id', this.model.get('box_id'));
  20081. this.el.innerHTML = tpl_chatroom();
  20082. this.renderHeading();
  20083. this.renderChatArea();
  20084. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
  20085. this.showSpinner();
  20086. }
  20087. return this;
  20088. },
  20089. renderHeading () {
  20090. /* Render the heading UI of the chat room. */
  20091. this.el.querySelector('.chat-head-chatroom').innerHTML = this.generateHeadingHTML();
  20092. },
  20093. renderChatArea () {
  20094. /* Render the UI container in which chat room messages will appear.
  20095. */
  20096. if (_.isNull(this.el.querySelector('.chat-area'))) {
  20097. const container_el = this.el.querySelector('.chatroom-body');
  20098. container_el.innerHTML = tpl_chatarea({
  20099. 'label_message': __('Message'),
  20100. 'label_send': __('Send'),
  20101. 'show_send_button': _converse.show_send_button,
  20102. 'show_toolbar': _converse.show_toolbar,
  20103. 'unread_msgs': __('You have unread messages')
  20104. });
  20105. container_el.insertAdjacentElement('beforeend', this.occupantsview.el);
  20106. this.renderToolbar(tpl_chatroom_toolbar);
  20107. this.content = this.el.querySelector('.chat-content');
  20108. this.toggleOccupants(null, true);
  20109. }
  20110. return this;
  20111. },
  20112. createOccupantsView () {
  20113. /* Create the ChatRoomOccupantsView Backbone.NativeView
  20114. */
  20115. const model = new _converse.ChatRoomOccupants();
  20116. model.chatroomview = this;
  20117. this.occupantsview = new _converse.ChatRoomOccupantsView({'model': model});
  20118. this.occupantsview.model.on('change:role', this.informOfOccupantsRoleChange, this);
  20119. return this;
  20120. },
  20121. informOfOccupantsRoleChange (occupant, changed) {
  20122. const previous_role = occupant._previousAttributes.role;
  20123. if (previous_role === 'moderator') {
  20124. this.showStatusNotification(
  20125. __("%1$s is no longer a moderator.", occupant.get('nick')),
  20126. false, true)
  20127. }
  20128. if (previous_role === 'visitor') {
  20129. this.showStatusNotification(
  20130. __("%1$s has been given a voice again.", occupant.get('nick')),
  20131. false, true)
  20132. }
  20133. if (occupant.get('role') === 'visitor') {
  20134. this.showStatusNotification(
  20135. __("%1$s has been muted.", occupant.get('nick')),
  20136. false, true)
  20137. }
  20138. if (occupant.get('role') === 'moderator') {
  20139. this.showStatusNotification(
  20140. __("%1$s is now a moderator.", occupant.get('nick')),
  20141. false, true)
  20142. }
  20143. },
  20144. generateHeadingHTML () {
  20145. /* Returns the heading HTML to be rendered.
  20146. */
  20147. return tpl_chatroom_head(
  20148. _.extend(this.model.toJSON(), {
  20149. Strophe: Strophe,
  20150. info_close: __('Close and leave this room'),
  20151. info_configure: __('Configure this room'),
  20152. description: this.model.get('description') || ''
  20153. }));
  20154. },
  20155. afterShown () {
  20156. /* Override from converse-chatview, specifically to avoid
  20157. * the 'active' chat state from being sent out prematurely.
  20158. *
  20159. * This is instead done in `afterConnected` below.
  20160. */
  20161. if (u.isPersistableModel(this.model)) {
  20162. this.model.clearUnreadMsgCounter();
  20163. this.model.save();
  20164. }
  20165. this.occupantsview.setOccupantsHeight();
  20166. this.scrollDown();
  20167. this.renderEmojiPicker();
  20168. },
  20169. show () {
  20170. if (u.isVisible(this.el)) {
  20171. this.focus();
  20172. return;
  20173. }
  20174. // Override from converse-chatview in order to not use
  20175. // "fadeIn", which causes flashing.
  20176. u.showElement(this.el);
  20177. this.afterShown();
  20178. },
  20179. afterConnected () {
  20180. if (this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
  20181. this.setChatState(_converse.ACTIVE);
  20182. this.scrollDown();
  20183. this.focus();
  20184. }
  20185. },
  20186. getExtraMessageClasses (attrs) {
  20187. let extra_classes = _converse.ChatBoxView.prototype
  20188. .getExtraMessageClasses.apply(this, arguments);
  20189. if (this.is_chatroom && attrs.sender === 'them' &&
  20190. this.model.isUserMentioned(attrs.message)) {
  20191. // Add special class to mark groupchat messages
  20192. // in which we are mentioned.
  20193. extra_classes += ' mentioned';
  20194. }
  20195. return extra_classes;
  20196. },
  20197. getToolbarOptions () {
  20198. return _.extend(
  20199. _converse.ChatBoxView.prototype.getToolbarOptions.apply(this, arguments),
  20200. {
  20201. label_hide_occupants: __('Hide the list of occupants'),
  20202. show_occupants_toggle: this.is_chatroom && _converse.visible_toolbar_buttons.toggle_occupants
  20203. }
  20204. );
  20205. },
  20206. close (ev) {
  20207. /* Close this chat box, which implies leaving the room as
  20208. * well.
  20209. */
  20210. this.leave();
  20211. },
  20212. setOccupantsVisibility () {
  20213. const icon_el = this.el.querySelector('.toggle-occupants');
  20214. if (this.model.get('hidden_occupants')) {
  20215. this.el.querySelector('.chat-area').classList.add('full');
  20216. u.hideElement(this.el.querySelector('.occupants'));
  20217. } else {
  20218. this.el.querySelector('.chat-area').classList.remove('full');
  20219. this.el.querySelector('.occupants').classList.remove('hidden');
  20220. }
  20221. this.occupantsview.setOccupantsHeight();
  20222. },
  20223. toggleOccupants (ev, preserve_state) {
  20224. /* Show or hide the right sidebar containing the chat
  20225. * occupants (and the invite widget).
  20226. */
  20227. if (ev) {
  20228. ev.preventDefault();
  20229. ev.stopPropagation();
  20230. }
  20231. if (!preserve_state) {
  20232. this.model.set({'hidden_occupants': !this.model.get('hidden_occupants')});
  20233. }
  20234. this.setOccupantsVisibility();
  20235. this.scrollDown();
  20236. },
  20237. onOccupantClicked (ev) {
  20238. /* When an occupant is clicked, insert their nickname into
  20239. * the chat textarea input.
  20240. */
  20241. this.insertIntoTextArea(ev.target.textContent);
  20242. },
  20243. requestMemberList (chatroom_jid, affiliation) {
  20244. /* Send an IQ stanza to the server, asking it for the
  20245. * member-list of this room.
  20246. *
  20247. * See: http://xmpp.org/extensions/xep-0045.html#modifymember
  20248. *
  20249. * Parameters:
  20250. * (String) chatroom_jid: The JID of the chatroom for
  20251. * which the member-list is being requested
  20252. * (String) affiliation: The specific member list to
  20253. * fetch. 'admin', 'owner' or 'member'.
  20254. *
  20255. * Returns:
  20256. * A promise which resolves once the list has been
  20257. * retrieved.
  20258. */
  20259. return new Promise((resolve, reject) => {
  20260. affiliation = affiliation || 'member';
  20261. const iq = $iq({to: chatroom_jid, type: "get"})
  20262. .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
  20263. .c("item", {'affiliation': affiliation});
  20264. _converse.connection.sendIQ(iq, resolve, reject);
  20265. });
  20266. },
  20267. parseMemberListIQ (iq) {
  20268. /* Given an IQ stanza with a member list, create an array of member
  20269. * objects.
  20270. */
  20271. return _.map(
  20272. sizzle(`query[xmlns="${Strophe.NS.MUC_ADMIN}"] item`, iq),
  20273. (item) => ({
  20274. 'jid': item.getAttribute('jid'),
  20275. 'affiliation': item.getAttribute('affiliation'),
  20276. })
  20277. );
  20278. },
  20279. computeAffiliationsDelta (exclude_existing, remove_absentees, new_list, old_list) {
  20280. /* Given two lists of objects with 'jid', 'affiliation' and
  20281. * 'reason' properties, return a new list containing
  20282. * those objects that are new, changed or removed
  20283. * (depending on the 'remove_absentees' boolean).
  20284. *
  20285. * The affiliations for new and changed members stay the
  20286. * same, for removed members, the affiliation is set to 'none'.
  20287. *
  20288. * The 'reason' property is not taken into account when
  20289. * comparing whether affiliations have been changed.
  20290. *
  20291. * Parameters:
  20292. * (Boolean) exclude_existing: Indicates whether JIDs from
  20293. * the new list which are also in the old list
  20294. * (regardless of affiliation) should be excluded
  20295. * from the delta. One reason to do this
  20296. * would be when you want to add a JID only if it
  20297. * doesn't have *any* existing affiliation at all.
  20298. * (Boolean) remove_absentees: Indicates whether JIDs
  20299. * from the old list which are not in the new list
  20300. * should be considered removed and therefore be
  20301. * included in the delta with affiliation set
  20302. * to 'none'.
  20303. * (Array) new_list: Array containing the new affiliations
  20304. * (Array) old_list: Array containing the old affiliations
  20305. */
  20306. const new_jids = _.map(new_list, 'jid');
  20307. const old_jids = _.map(old_list, 'jid');
  20308. // Get the new affiliations
  20309. let delta = _.map(
  20310. _.difference(new_jids, old_jids),
  20311. (jid) => new_list[_.indexOf(new_jids, jid)]
  20312. );
  20313. if (!exclude_existing) {
  20314. // Get the changed affiliations
  20315. delta = delta.concat(_.filter(new_list, function (item) {
  20316. const idx = _.indexOf(old_jids, item.jid);
  20317. if (idx >= 0) {
  20318. return item.affiliation !== old_list[idx].affiliation;
  20319. }
  20320. return false;
  20321. }));
  20322. }
  20323. if (remove_absentees) {
  20324. // Get the removed affiliations
  20325. delta = delta.concat(
  20326. _.map(
  20327. _.difference(old_jids, new_jids),
  20328. (jid) => ({'jid': jid, 'affiliation': 'none'})
  20329. )
  20330. );
  20331. }
  20332. return delta;
  20333. },
  20334. sendAffiliationIQ (chatroom_jid, affiliation, member) {
  20335. /* Send an IQ stanza specifying an affiliation change.
  20336. *
  20337. * Paremeters:
  20338. * (String) chatroom_jid: JID of the relevant room
  20339. * (String) affiliation: affiliation (could also be stored
  20340. * on the member object).
  20341. * (Object) member: Map containing the member's jid and
  20342. * optionally a reason and affiliation.
  20343. */
  20344. return new Promise((resolve, reject) => {
  20345. const iq = $iq({to: chatroom_jid, type: "set"})
  20346. .c("query", {xmlns: Strophe.NS.MUC_ADMIN})
  20347. .c("item", {
  20348. 'affiliation': member.affiliation || affiliation,
  20349. 'jid': member.jid
  20350. });
  20351. if (!_.isUndefined(member.reason)) {
  20352. iq.c("reason", member.reason);
  20353. }
  20354. _converse.connection.sendIQ(iq, resolve, reject);
  20355. });
  20356. },
  20357. setAffiliation (affiliation, members) {
  20358. /* Send IQ stanzas to the server to set an affiliation for
  20359. * the provided JIDs.
  20360. *
  20361. * See: http://xmpp.org/extensions/xep-0045.html#modifymember
  20362. *
  20363. * XXX: Prosody doesn't accept multiple JIDs' affiliations
  20364. * being set in one IQ stanza, so as a workaround we send
  20365. * a separate stanza for each JID.
  20366. * Related ticket: https://prosody.im/issues/issue/795
  20367. *
  20368. * Parameters:
  20369. * (String) affiliation: The affiliation
  20370. * (Object) members: A map of jids, affiliations and
  20371. * optionally reasons. Only those entries with the
  20372. * same affiliation as being currently set will be
  20373. * considered.
  20374. *
  20375. * Returns:
  20376. * A promise which resolves and fails depending on the
  20377. * XMPP server response.
  20378. */
  20379. members = _.filter(members, (member) =>
  20380. // We only want those members who have the right
  20381. // affiliation (or none, which implies the provided
  20382. // one).
  20383. _.isUndefined(member.affiliation) ||
  20384. member.affiliation === affiliation
  20385. );
  20386. const promises = _.map(
  20387. members,
  20388. _.partial(this.sendAffiliationIQ, this.model.get('jid'), affiliation)
  20389. );
  20390. return Promise.all(promises);
  20391. },
  20392. setAffiliations (members) {
  20393. /* Send IQ stanzas to the server to modify the
  20394. * affiliations in this room.
  20395. *
  20396. * See: http://xmpp.org/extensions/xep-0045.html#modifymember
  20397. *
  20398. * Parameters:
  20399. * (Object) members: A map of jids, affiliations and optionally reasons
  20400. * (Function) onSuccess: callback for a succesful response
  20401. * (Function) onError: callback for an error response
  20402. */
  20403. const affiliations = _.uniq(_.map(members, 'affiliation'));
  20404. _.each(affiliations, _.partial(this.setAffiliation.bind(this), _, members));
  20405. },
  20406. marshallAffiliationIQs () {
  20407. /* Marshall a list of IQ stanzas into a map of JIDs and
  20408. * affiliations.
  20409. *
  20410. * Parameters:
  20411. * Any amount of XMLElement objects, representing the IQ
  20412. * stanzas.
  20413. */
  20414. return _.flatMap(arguments[0], this.parseMemberListIQ);
  20415. },
  20416. getJidsWithAffiliations (affiliations) {
  20417. /* Returns a map of JIDs that have the affiliations
  20418. * as provided.
  20419. */
  20420. if (_.isString(affiliations)) {
  20421. affiliations = [affiliations];
  20422. }
  20423. return new Promise((resolve, reject) => {
  20424. const promises = _.map(
  20425. affiliations,
  20426. _.partial(this.requestMemberList, this.model.get('jid'))
  20427. );
  20428. Promise.all(promises).then(
  20429. _.flow(this.marshallAffiliationIQs.bind(this), resolve),
  20430. _.flow(this.marshallAffiliationIQs.bind(this), resolve)
  20431. );
  20432. });
  20433. },
  20434. updateMemberLists (members, affiliations, deltaFunc) {
  20435. /* Fetch the lists of users with the given affiliations.
  20436. * Then compute the delta between those users and
  20437. * the passed in members, and if it exists, send the delta
  20438. * to the XMPP server to update the member list.
  20439. *
  20440. * Parameters:
  20441. * (Object) members: Map of member jids and affiliations.
  20442. * (String|Array) affiliation: An array of affiliations or
  20443. * a string if only one affiliation.
  20444. * (Function) deltaFunc: The function to compute the delta
  20445. * between old and new member lists.
  20446. *
  20447. * Returns:
  20448. * A promise which is resolved once the list has been
  20449. * updated or once it's been established there's no need
  20450. * to update the list.
  20451. */
  20452. this.getJidsWithAffiliations(affiliations).then((old_members) => {
  20453. this.setAffiliations(deltaFunc(members, old_members));
  20454. });
  20455. },
  20456. directInvite (recipient, reason) {
  20457. /* Send a direct invitation as per XEP-0249
  20458. *
  20459. * Parameters:
  20460. * (String) recipient - JID of the person being invited
  20461. * (String) reason - Optional reason for the invitation
  20462. */
  20463. if (this.model.get('membersonly')) {
  20464. // When inviting to a members-only room, we first add
  20465. // the person to the member list by giving them an
  20466. // affiliation of 'member' (if they're not affiliated
  20467. // already), otherwise they won't be able to join.
  20468. const map = {}; map[recipient] = 'member';
  20469. const deltaFunc = _.partial(this.computeAffiliationsDelta, true, false);
  20470. this.updateMemberLists(
  20471. [{'jid': recipient, 'affiliation': 'member', 'reason': reason}],
  20472. ['member', 'owner', 'admin'],
  20473. deltaFunc
  20474. );
  20475. }
  20476. const attrs = {
  20477. 'xmlns': 'jabber:x:conference',
  20478. 'jid': this.model.get('jid')
  20479. };
  20480. if (reason !== null) { attrs.reason = reason; }
  20481. if (this.model.get('password')) { attrs.password = this.model.get('password'); }
  20482. const invitation = $msg({
  20483. from: _converse.connection.jid,
  20484. to: recipient,
  20485. id: _converse.connection.getUniqueId()
  20486. }).c('x', attrs);
  20487. _converse.connection.send(invitation);
  20488. _converse.emit('roomInviteSent', {
  20489. 'room': this,
  20490. 'recipient': recipient,
  20491. 'reason': reason
  20492. });
  20493. },
  20494. handleChatStateMessage (message) {
  20495. /* Override the method on the ChatBoxView base class to
  20496. * ignore <gone/> notifications in groupchats.
  20497. *
  20498. * As laid out in the business rules in XEP-0085
  20499. * http://xmpp.org/extensions/xep-0085.html#bizrules-groupchat
  20500. */
  20501. if (message.get('fullname') === this.model.get('nick')) {
  20502. // Don't know about other servers, but OpenFire sends
  20503. // back to you your own chat state notifications.
  20504. // We ignore them here...
  20505. return;
  20506. }
  20507. if (message.get('chat_state') !== _converse.GONE) {
  20508. _converse.ChatBoxView.prototype.handleChatStateMessage.apply(this, arguments);
  20509. }
  20510. },
  20511. sendChatState () {
  20512. /* Sends a message with the status of the user in this chat session
  20513. * as taken from the 'chat_state' attribute of the chat box.
  20514. * See XEP-0085 Chat State Notifications.
  20515. */
  20516. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
  20517. return;
  20518. }
  20519. const chat_state = this.model.get('chat_state');
  20520. if (chat_state === _converse.GONE) {
  20521. // <gone/> is not applicable within MUC context
  20522. return;
  20523. }
  20524. _converse.connection.send(
  20525. $msg({'to':this.model.get('jid'), 'type': 'groupchat'})
  20526. .c(chat_state, {'xmlns': Strophe.NS.CHATSTATES}).up()
  20527. .c('no-store', {'xmlns': Strophe.NS.HINTS}).up()
  20528. .c('no-permanent-store', {'xmlns': Strophe.NS.HINTS})
  20529. );
  20530. },
  20531. sendChatRoomMessage (text) {
  20532. /* Constuct a message stanza to be sent to this chat room,
  20533. * and send it to the server.
  20534. *
  20535. * Parameters:
  20536. * (String) text: The message text to be sent.
  20537. */
  20538. text = emojione.shortnameToUnicode(text)
  20539. const msgid = _converse.connection.getUniqueId();
  20540. const msg = $msg({
  20541. to: this.model.get('jid'),
  20542. from: _converse.connection.jid,
  20543. type: 'groupchat',
  20544. id: msgid
  20545. }).c("body").t(text).up()
  20546. .c("x", {xmlns: "jabber:x:event"}).c(_converse.COMPOSING);
  20547. _converse.connection.send(msg);
  20548. this.model.messages.create({
  20549. fullname: this.model.get('nick'),
  20550. sender: 'me',
  20551. time: moment().format(),
  20552. message: text,
  20553. msgid
  20554. });
  20555. },
  20556. modifyRole(room, nick, role, reason, onSuccess, onError) {
  20557. const item = $build("item", {nick, role});
  20558. const iq = $iq({to: room, type: "set"}).c("query", {xmlns: Strophe.NS.MUC_ADMIN}).cnode(item.node);
  20559. if (reason !== null) { iq.c("reason", reason); }
  20560. return _converse.connection.sendIQ(iq, onSuccess, onError);
  20561. },
  20562. validateRoleChangeCommand (command, args) {
  20563. /* Check that a command to change a chat room user's role or
  20564. * affiliation has anough arguments.
  20565. */
  20566. // TODO check if first argument is valid
  20567. if (args.length < 1 || args.length > 2) {
  20568. this.showStatusNotification(
  20569. __('Error: the "%1$s" command takes two arguments, the user\'s nickname and optionally a reason.',
  20570. command),
  20571. true
  20572. );
  20573. return false;
  20574. }
  20575. return true;
  20576. },
  20577. clearChatRoomMessages (ev) {
  20578. /* Remove all messages from the chat room UI.
  20579. */
  20580. if (!_.isUndefined(ev)) { ev.stopPropagation(); }
  20581. const result = confirm(__("Are you sure you want to clear the messages from this room?"));
  20582. if (result === true) {
  20583. this.content.innerHTML = '';
  20584. }
  20585. return this;
  20586. },
  20587. onCommandError () {
  20588. this.showStatusNotification(__("Error: could not execute the command"), true);
  20589. },
  20590. onMessageSubmitted (text) {
  20591. /* Gets called when the user presses enter to send off a
  20592. * message in a chat room.
  20593. *
  20594. * Parameters:
  20595. * (String) text - The message text.
  20596. */
  20597. if (_converse.muc_disable_moderator_commands) {
  20598. return this.sendChatRoomMessage(text);
  20599. }
  20600. const match = text.replace(/^\s*/, "").match(/^\/(.*?)(?: (.*))?$/) || [false, '', ''],
  20601. args = match[2] && match[2].splitOnce(' ') || [],
  20602. command = match[1].toLowerCase();
  20603. switch (command) {
  20604. case 'admin':
  20605. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20606. this.setAffiliation('admin',
  20607. [{ 'jid': args[0],
  20608. 'reason': args[1]
  20609. }]).then(null, this.onCommandError.bind(this));
  20610. break;
  20611. case 'ban':
  20612. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20613. this.setAffiliation('outcast',
  20614. [{ 'jid': args[0],
  20615. 'reason': args[1]
  20616. }]).then(null, this.onCommandError.bind(this));
  20617. break;
  20618. case 'clear':
  20619. this.clearChatRoomMessages();
  20620. break;
  20621. case 'deop':
  20622. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20623. this.modifyRole(
  20624. this.model.get('jid'), args[0], 'participant', args[1],
  20625. undefined, this.onCommandError.bind(this));
  20626. break;
  20627. case 'help':
  20628. this.showHelpMessages([
  20629. `<strong>/admin</strong>: ${__("Change user's affiliation to admin")}`,
  20630. `<strong>/ban</strong>: ${__('Ban user from room')}`,
  20631. `<strong>/clear</strong>: ${__('Remove messages')}`,
  20632. `<strong>/deop</strong>: ${__('Change user role to participant')}`,
  20633. `<strong>/help</strong>: ${__('Show this menu')}`,
  20634. `<strong>/kick</strong>: ${__('Kick user from room')}`,
  20635. `<strong>/me</strong>: ${__('Write in 3rd person')}`,
  20636. `<strong>/member</strong>: ${__('Grant membership to a user')}`,
  20637. `<strong>/mute</strong>: ${__("Remove user's ability to post messages")}`,
  20638. `<strong>/nick</strong>: ${__('Change your nickname')}`,
  20639. `<strong>/op</strong>: ${__('Grant moderator role to user')}`,
  20640. `<strong>/owner</strong>: ${__('Grant ownership of this room')}`,
  20641. `<strong>/revoke</strong>: ${__("Revoke user's membership")}`,
  20642. `<strong>/subject</strong>: ${__('Set room subject')}`,
  20643. `<strong>/topic</strong>: ${__('Set room subject (alias for /subject)')}`,
  20644. `<strong>/voice</strong>: ${__('Allow muted user to post messages')}`
  20645. ]);
  20646. break;
  20647. case 'kick':
  20648. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20649. this.modifyRole(
  20650. this.model.get('jid'), args[0], 'none', args[1],
  20651. undefined, this.onCommandError.bind(this));
  20652. break;
  20653. case 'mute':
  20654. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20655. this.modifyRole(
  20656. this.model.get('jid'), args[0], 'visitor', args[1],
  20657. undefined, this.onCommandError.bind(this));
  20658. break;
  20659. case 'member':
  20660. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20661. this.setAffiliation('member',
  20662. [{ 'jid': args[0],
  20663. 'reason': args[1]
  20664. }]).then(null, this.onCommandError.bind(this));
  20665. break;
  20666. case 'nick':
  20667. _converse.connection.send($pres({
  20668. from: _converse.connection.jid,
  20669. to: this.getRoomJIDAndNick(match[2]),
  20670. id: _converse.connection.getUniqueId()
  20671. }).tree());
  20672. break;
  20673. case 'owner':
  20674. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20675. this.setAffiliation('owner',
  20676. [{ 'jid': args[0],
  20677. 'reason': args[1]
  20678. }]).then(null, this.onCommandError.bind(this));
  20679. break;
  20680. case 'op':
  20681. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20682. this.modifyRole(
  20683. this.model.get('jid'), args[0], 'moderator', args[1],
  20684. undefined, this.onCommandError.bind(this));
  20685. break;
  20686. case 'revoke':
  20687. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20688. this.setAffiliation('none',
  20689. [{ 'jid': args[0],
  20690. 'reason': args[1]
  20691. }]).then(null, this.onCommandError.bind(this));
  20692. break;
  20693. case 'topic':
  20694. case 'subject':
  20695. _converse.connection.send(
  20696. $msg({
  20697. to: this.model.get('jid'),
  20698. from: _converse.connection.jid,
  20699. type: "groupchat"
  20700. }).c("subject", {xmlns: "jabber:client"}).t(match[2]).tree()
  20701. );
  20702. break;
  20703. case 'voice':
  20704. if (!this.validateRoleChangeCommand(command, args)) { break; }
  20705. this.modifyRole(
  20706. this.model.get('jid'), args[0], 'participant', args[1],
  20707. undefined, this.onCommandError.bind(this));
  20708. break;
  20709. default:
  20710. this.sendChatRoomMessage(text);
  20711. break;
  20712. }
  20713. },
  20714. handleMUCMessage (stanza) {
  20715. /* Handler for all MUC messages sent to this chat room.
  20716. *
  20717. * Parameters:
  20718. * (XMLElement) stanza: The message stanza.
  20719. */
  20720. const configuration_changed = stanza.querySelector("status[code='104']");
  20721. const logging_enabled = stanza.querySelector("status[code='170']");
  20722. const logging_disabled = stanza.querySelector("status[code='171']");
  20723. const room_no_longer_anon = stanza.querySelector("status[code='172']");
  20724. const room_now_semi_anon = stanza.querySelector("status[code='173']");
  20725. const room_now_fully_anon = stanza.querySelector("status[code='173']");
  20726. if (configuration_changed || logging_enabled || logging_disabled ||
  20727. room_no_longer_anon || room_now_semi_anon || room_now_fully_anon) {
  20728. this.getRoomFeatures();
  20729. }
  20730. _.flow(this.showStatusMessages.bind(this), this.onChatRoomMessage.bind(this))(stanza);
  20731. return true;
  20732. },
  20733. getRoomJIDAndNick (nick) {
  20734. /* Utility method to construct the JID for the current user
  20735. * as occupant of the room.
  20736. *
  20737. * This is the room JID, with the user's nick added at the
  20738. * end.
  20739. *
  20740. * For example: room@conference.example.org/nickname
  20741. */
  20742. if (nick) {
  20743. this.model.save({'nick': nick});
  20744. } else {
  20745. nick = this.model.get('nick');
  20746. }
  20747. const room = this.model.get('jid');
  20748. const jid = Strophe.getBareJidFromJid(room);
  20749. return jid + (nick !== null ? `/${nick}` : "");
  20750. },
  20751. registerHandlers () {
  20752. /* Register presence and message handlers for this chat
  20753. * room
  20754. */
  20755. const room_jid = this.model.get('jid');
  20756. this.removeHandlers();
  20757. this.presence_handler = _converse.connection.addHandler(
  20758. this.onChatRoomPresence.bind(this),
  20759. Strophe.NS.MUC, 'presence', null, null, room_jid,
  20760. {'ignoreNamespaceFragment': true, 'matchBareFromJid': true}
  20761. );
  20762. this.message_handler = _converse.connection.addHandler(
  20763. this.handleMUCMessage.bind(this),
  20764. null, 'message', 'groupchat', null, room_jid,
  20765. {'matchBareFromJid': true}
  20766. );
  20767. },
  20768. removeHandlers () {
  20769. /* Remove the presence and message handlers that were
  20770. * registered for this chat room.
  20771. */
  20772. if (this.message_handler) {
  20773. _converse.connection.deleteHandler(this.message_handler);
  20774. delete this.message_handler;
  20775. }
  20776. if (this.presence_handler) {
  20777. _converse.connection.deleteHandler(this.presence_handler);
  20778. delete this.presence_handler;
  20779. }
  20780. return this;
  20781. },
  20782. join (nick, password) {
  20783. /* Join the chat room.
  20784. *
  20785. * Parameters:
  20786. * (String) nick: The user's nickname
  20787. * (String) password: Optional password, if required by
  20788. * the room.
  20789. */
  20790. nick = nick ? nick : this.model.get('nick');
  20791. if (!nick) {
  20792. return this.checkForReservedNick();
  20793. }
  20794. if (this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
  20795. // We have restored a chat room from session storage,
  20796. // so we don't send out a presence stanza again.
  20797. return this;
  20798. }
  20799. const stanza = $pres({
  20800. 'from': _converse.connection.jid,
  20801. 'to': this.getRoomJIDAndNick(nick)
  20802. }).c("x", {'xmlns': Strophe.NS.MUC})
  20803. .c("history", {'maxstanzas': _converse.muc_history_max_stanzas}).up();
  20804. if (password) {
  20805. stanza.cnode(Strophe.xmlElement("password", [], password));
  20806. }
  20807. this.model.save('connection_status', converse.ROOMSTATUS.CONNECTING);
  20808. _converse.connection.send(stanza);
  20809. return this;
  20810. },
  20811. sendUnavailablePresence (exit_msg) {
  20812. const presence = $pres({
  20813. type: "unavailable",
  20814. from: _converse.connection.jid,
  20815. to: this.getRoomJIDAndNick()
  20816. });
  20817. if (exit_msg !== null) {
  20818. presence.c("status", exit_msg);
  20819. }
  20820. _converse.connection.sendPresence(presence);
  20821. },
  20822. leave(exit_msg) {
  20823. /* Leave the chat room.
  20824. *
  20825. * Parameters:
  20826. * (String) exit_msg: Optional message to indicate your
  20827. * reason for leaving.
  20828. */
  20829. this.hide();
  20830. if (Backbone.history.getFragment() === "converse/room?jid="+this.model.get('jid')) {
  20831. _converse.router.navigate('');
  20832. }
  20833. this.occupantsview.model.reset();
  20834. this.occupantsview.model.browserStorage._clear();
  20835. if (_converse.connection.connected) {
  20836. this.sendUnavailablePresence(exit_msg);
  20837. }
  20838. u.safeSave(
  20839. this.model,
  20840. {'connection_status': converse.ROOMSTATUS.DISCONNECTED}
  20841. );
  20842. this.removeHandlers();
  20843. _converse.ChatBoxView.prototype.close.apply(this, arguments);
  20844. },
  20845. renderConfigurationForm (stanza) {
  20846. /* Renders a form given an IQ stanza containing the current
  20847. * room configuration.
  20848. *
  20849. * Returns a promise which resolves once the user has
  20850. * either submitted the form, or canceled it.
  20851. *
  20852. * Parameters:
  20853. * (XMLElement) stanza: The IQ stanza containing the room
  20854. * config.
  20855. */
  20856. const container_el = this.el.querySelector('.chatroom-body');
  20857. _.each(container_el.querySelectorAll('.chatroom-form-container'), u.removeElement);
  20858. _.each(container_el.children, u.hideElement);
  20859. container_el.insertAdjacentHTML('beforeend', tpl_chatroom_form());
  20860. const form_el = container_el.querySelector('form.chatroom-form'),
  20861. fieldset_el = form_el.querySelector('fieldset'),
  20862. fields = stanza.querySelectorAll('field'),
  20863. title = _.get(stanza.querySelector('title'), 'textContent'),
  20864. instructions = _.get(stanza.querySelector('instructions'), 'textContent');
  20865. u.removeElement(fieldset_el.querySelector('span.spinner'));
  20866. fieldset_el.insertAdjacentHTML('beforeend', `<legend>${title}</legend>`);
  20867. if (instructions && instructions !== title) {
  20868. fieldset_el.insertAdjacentHTML('beforeend', `<p class="instructions">${instructions}</p>`);
  20869. }
  20870. _.each(fields, function (field) {
  20871. fieldset_el.insertAdjacentHTML('beforeend', u.xForm2webForm(field, stanza));
  20872. });
  20873. // Render save/cancel buttons
  20874. const last_fieldset_el = document.createElement('fieldset');
  20875. last_fieldset_el.insertAdjacentHTML(
  20876. 'beforeend',
  20877. `<input type="submit" class="pure-button button-primary" value="${__('Save')}"/>`);
  20878. last_fieldset_el.insertAdjacentHTML(
  20879. 'beforeend',
  20880. `<input type="button" class="pure-button button-cancel" value="${__('Cancel')}"/>`);
  20881. form_el.insertAdjacentElement('beforeend', last_fieldset_el);
  20882. last_fieldset_el.querySelector('input[type=button]').addEventListener('click', (ev) => {
  20883. ev.preventDefault();
  20884. this.closeForm();
  20885. });
  20886. form_el.addEventListener('submit', (ev) => {
  20887. ev.preventDefault();
  20888. this.saveConfiguration(ev.target).then(
  20889. this.getRoomFeatures.bind(this)
  20890. );
  20891. },
  20892. false
  20893. );
  20894. },
  20895. sendConfiguration(config, onSuccess, onError) {
  20896. /* Send an IQ stanza with the room configuration.
  20897. *
  20898. * Parameters:
  20899. * (Array) config: The room configuration
  20900. * (Function) onSuccess: Callback upon succesful IQ response
  20901. * The first parameter passed in is IQ containing the
  20902. * room configuration.
  20903. * The second is the response IQ from the server.
  20904. * (Function) onError: Callback upon error IQ response
  20905. * The first parameter passed in is IQ containing the
  20906. * room configuration.
  20907. * The second is the response IQ from the server.
  20908. */
  20909. const iq = $iq({to: this.model.get('jid'), type: "set"})
  20910. .c("query", {xmlns: Strophe.NS.MUC_OWNER})
  20911. .c("x", {xmlns: Strophe.NS.XFORM, type: "submit"});
  20912. _.each(config || [], function (node) { iq.cnode(node).up(); });
  20913. onSuccess = _.isUndefined(onSuccess) ? _.noop : _.partial(onSuccess, iq.nodeTree);
  20914. onError = _.isUndefined(onError) ? _.noop : _.partial(onError, iq.nodeTree);
  20915. return _converse.connection.sendIQ(iq, onSuccess, onError);
  20916. },
  20917. saveConfiguration (form) {
  20918. /* Submit the room configuration form by sending an IQ
  20919. * stanza to the server.
  20920. *
  20921. * Returns a promise which resolves once the XMPP server
  20922. * has return a response IQ.
  20923. *
  20924. * Parameters:
  20925. * (HTMLElement) form: The configuration form DOM element.
  20926. */
  20927. return new Promise((resolve, reject) => {
  20928. const inputs = form ? sizzle(':input:not([type=button]):not([type=submit])', form) : [],
  20929. configArray = _.map(inputs, u.webForm2xForm);
  20930. this.sendConfiguration(configArray, resolve, reject);
  20931. this.closeForm();
  20932. });
  20933. },
  20934. autoConfigureChatRoom () {
  20935. /* Automatically configure room based on the
  20936. * 'roomconfig' data on this view's model.
  20937. *
  20938. * Returns a promise which resolves once a response IQ has
  20939. * been received.
  20940. *
  20941. * Parameters:
  20942. * (XMLElement) stanza: IQ stanza from the server,
  20943. * containing the configuration.
  20944. */
  20945. const that = this;
  20946. return new Promise((resolve, reject) => {
  20947. this.fetchRoomConfiguration().then(function (stanza) {
  20948. const configArray = [],
  20949. fields = stanza.querySelectorAll('field'),
  20950. config = that.model.get('roomconfig');
  20951. let count = fields.length;
  20952. _.each(fields, function (field) {
  20953. const fieldname = field.getAttribute('var').replace('muc#roomconfig_', ''),
  20954. type = field.getAttribute('type');
  20955. let value;
  20956. if (fieldname in config) {
  20957. switch (type) {
  20958. case 'boolean':
  20959. value = config[fieldname] ? 1 : 0;
  20960. break;
  20961. case 'list-multi':
  20962. // TODO: we don't yet handle "list-multi" types
  20963. value = field.innerHTML;
  20964. break;
  20965. default:
  20966. value = config[fieldname];
  20967. }
  20968. field.innerHTML = $build('value').t(value);
  20969. }
  20970. configArray.push(field);
  20971. if (!--count) {
  20972. that.sendConfiguration(configArray, resolve, reject);
  20973. }
  20974. });
  20975. });
  20976. });
  20977. },
  20978. closeForm () {
  20979. /* Remove the configuration form without submitting and
  20980. * return to the chat view.
  20981. */
  20982. u.removeElement(this.el.querySelector('.chatroom-form-container'));
  20983. this.renderAfterTransition();
  20984. },
  20985. fetchRoomConfiguration (handler) {
  20986. /* Send an IQ stanza to fetch the room configuration data.
  20987. * Returns a promise which resolves once the response IQ
  20988. * has been received.
  20989. *
  20990. * Parameters:
  20991. * (Function) handler: The handler for the response IQ
  20992. */
  20993. return new Promise((resolve, reject) => {
  20994. _converse.connection.sendIQ(
  20995. $iq({
  20996. 'to': this.model.get('jid'),
  20997. 'type': "get"
  20998. }).c("query", {xmlns: Strophe.NS.MUC_OWNER}),
  20999. (iq) => {
  21000. if (handler) {
  21001. handler.apply(this, arguments);
  21002. }
  21003. resolve(iq);
  21004. },
  21005. reject // errback
  21006. );
  21007. });
  21008. },
  21009. parseRoomFeatures (iq) {
  21010. /* See http://xmpp.org/extensions/xep-0045.html#disco-roominfo
  21011. *
  21012. * <identity
  21013. * category='conference'
  21014. * name='A Dark Cave'
  21015. * type='text'/>
  21016. * <feature var='http://jabber.org/protocol/muc'/>
  21017. * <feature var='muc_passwordprotected'/>
  21018. * <feature var='muc_hidden'/>
  21019. * <feature var='muc_temporary'/>
  21020. * <feature var='muc_open'/>
  21021. * <feature var='muc_unmoderated'/>
  21022. * <feature var='muc_nonanonymous'/>
  21023. * <feature var='urn:xmpp:mam:0'/>
  21024. */
  21025. const features = {
  21026. 'features_fetched': true,
  21027. 'name': iq.querySelector('identity').getAttribute('name')
  21028. }
  21029. _.each(iq.querySelectorAll('feature'), function (field) {
  21030. const fieldname = field.getAttribute('var');
  21031. if (!fieldname.startsWith('muc_')) {
  21032. if (fieldname === Strophe.NS.MAM) {
  21033. features.mam_enabled = true;
  21034. }
  21035. return;
  21036. }
  21037. features[fieldname.replace('muc_', '')] = true;
  21038. });
  21039. const desc_field = iq.querySelector('field[var="muc#roominfo_description"] value');
  21040. if (!_.isNull(desc_field)) {
  21041. features.description = desc_field.textContent;
  21042. }
  21043. this.model.save(features);
  21044. },
  21045. getRoomFeatures () {
  21046. /* Fetch the room disco info, parse it and then
  21047. * save it on the Backbone.Model of this chat rooms.
  21048. */
  21049. return new Promise((resolve, reject) => {
  21050. _converse.connection.disco.info(
  21051. this.model.get('jid'),
  21052. null,
  21053. _.flow(this.parseRoomFeatures.bind(this), resolve),
  21054. () => { reject(new Error("Could not parse the room features")) },
  21055. 5000
  21056. );
  21057. });
  21058. },
  21059. getAndRenderConfigurationForm (ev) {
  21060. /* Start the process of configuring a chat room, either by
  21061. * rendering a configuration form, or by auto-configuring
  21062. * based on the "roomconfig" data stored on the
  21063. * Backbone.Model.
  21064. *
  21065. * Stores the new configuration on the Backbone.Model once
  21066. * completed.
  21067. *
  21068. * Paremeters:
  21069. * (Event) ev: DOM event that might be passed in if this
  21070. * method is called due to a user action. In this
  21071. * case, auto-configure won't happen, regardless of
  21072. * the settings.
  21073. */
  21074. this.showSpinner();
  21075. this.fetchRoomConfiguration()
  21076. .then(this.renderConfigurationForm.bind(this))
  21077. .catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
  21078. },
  21079. submitNickname (ev) {
  21080. /* Get the nickname value from the form and then join the
  21081. * chat room with it.
  21082. */
  21083. ev.preventDefault();
  21084. const nick_el = ev.target.nick;
  21085. const nick = nick_el.value;
  21086. if (!nick) {
  21087. nick_el.classList.add('error');
  21088. return;
  21089. }
  21090. else {
  21091. nick_el.classList.remove('error');
  21092. }
  21093. this.el.querySelector('.chatroom-form-container').outerHTML = tpl_spinner();
  21094. this.join(nick);
  21095. },
  21096. checkForReservedNick () {
  21097. /* User service-discovery to ask the XMPP server whether
  21098. * this user has a reserved nickname for this room.
  21099. * If so, we'll use that, otherwise we render the nickname
  21100. * form.
  21101. */
  21102. this.showSpinner();
  21103. _converse.connection.sendIQ(
  21104. $iq({
  21105. 'to': this.model.get('jid'),
  21106. 'from': _converse.connection.jid,
  21107. 'type': "get"
  21108. }).c("query", {
  21109. 'xmlns': Strophe.NS.DISCO_INFO,
  21110. 'node': 'x-roomuser-item'
  21111. }),
  21112. this.onNickNameFound.bind(this),
  21113. this.onNickNameNotFound.bind(this)
  21114. );
  21115. return this;
  21116. },
  21117. onNickNameFound (iq) {
  21118. /* We've received an IQ response from the server which
  21119. * might contain the user's reserved nickname.
  21120. * If no nickname is found we either render a form for
  21121. * them to specify one, or we try to join the room with the
  21122. * node of the user's JID.
  21123. *
  21124. * Parameters:
  21125. * (XMLElement) iq: The received IQ stanza
  21126. */
  21127. const identity_el = iq.querySelector('query[node="x-roomuser-item"] identity'),
  21128. nick = identity_el ? identity_el.getAttribute('name') : null;
  21129. if (!nick) {
  21130. this.onNickNameNotFound();
  21131. } else {
  21132. this.join(nick);
  21133. }
  21134. },
  21135. onNickNameNotFound (message) {
  21136. if (_converse.muc_nickname_from_jid) {
  21137. // We try to enter the room with the node part of
  21138. // the user's JID.
  21139. this.join(this.getDefaultNickName());
  21140. } else {
  21141. this.renderNicknameForm(message);
  21142. }
  21143. },
  21144. getDefaultNickName () {
  21145. /* The default nickname (used when muc_nickname_from_jid is true)
  21146. * is the node part of the user's JID.
  21147. * We put this in a separate method so that it can be
  21148. * overridden by plugins.
  21149. */
  21150. return Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid));
  21151. },
  21152. onNicknameClash (presence) {
  21153. /* When the nickname is already taken, we either render a
  21154. * form for the user to choose a new nickname, or we
  21155. * try to make the nickname unique by adding an integer to
  21156. * it. So john will become john-2, and then john-3 and so on.
  21157. *
  21158. * Which option is take depends on the value of
  21159. * muc_nickname_from_jid.
  21160. */
  21161. if (_converse.muc_nickname_from_jid) {
  21162. const nick = presence.getAttribute('from').split('/')[1];
  21163. if (nick === this.getDefaultNickName()) {
  21164. this.join(nick + '-2');
  21165. } else {
  21166. const del= nick.lastIndexOf("-");
  21167. const num = nick.substring(del+1, nick.length);
  21168. this.join(nick.substring(0, del+1) + String(Number(num)+1));
  21169. }
  21170. } else {
  21171. this.renderNicknameForm(
  21172. __("The nickname you chose is reserved or "+
  21173. "currently in use, please choose a different one.")
  21174. );
  21175. }
  21176. },
  21177. hideChatRoomContents () {
  21178. const container_el = this.el.querySelector('.chatroom-body');
  21179. if (!_.isNull(container_el)) {
  21180. _.each(container_el.children, (child) => { child.classList.add('hidden'); });
  21181. }
  21182. },
  21183. renderNicknameForm (message) {
  21184. /* Render a form which allows the user to choose their
  21185. * nickname.
  21186. */
  21187. this.hideChatRoomContents();
  21188. _.each(this.el.querySelectorAll('span.centered.spinner'), u.removeElement);
  21189. if (!_.isString(message)) {
  21190. message = '';
  21191. }
  21192. const container_el = this.el.querySelector('.chatroom-body');
  21193. container_el.insertAdjacentHTML(
  21194. 'beforeend',
  21195. tpl_chatroom_nickname_form({
  21196. heading: __('Please choose your nickname'),
  21197. label_nickname: __('Nickname'),
  21198. label_join: __('Enter room'),
  21199. validation_message: message
  21200. }));
  21201. this.model.save('connection_status', converse.ROOMSTATUS.NICKNAME_REQUIRED);
  21202. const form_el = this.el.querySelector('.chatroom-form');
  21203. form_el.addEventListener('submit', this.submitNickname.bind(this), false);
  21204. },
  21205. submitPassword (ev) {
  21206. ev.preventDefault();
  21207. const password = this.el.querySelector('.chatroom-form input[type=password]').value;
  21208. this.showSpinner();
  21209. this.join(this.model.get('nick'), password);
  21210. },
  21211. renderPasswordForm () {
  21212. const container_el = this.el.querySelector('.chatroom-body');
  21213. _.each(container_el.children, u.hideElement);
  21214. _.each(this.el.querySelectorAll('.spinner'), u.removeElement);
  21215. container_el.insertAdjacentHTML('beforeend',
  21216. tpl_chatroom_password_form({
  21217. heading: __('This chatroom requires a password'),
  21218. label_password: __('Password: '),
  21219. label_submit: __('Submit')
  21220. }));
  21221. this.model.save('connection_status', converse.ROOMSTATUS.PASSWORD_REQUIRED);
  21222. this.el.querySelector('.chatroom-form').addEventListener(
  21223. 'submit', this.submitPassword.bind(this), false);
  21224. },
  21225. showDisconnectMessage (msg) {
  21226. u.hideElement(this.el.querySelector('.chat-area'));
  21227. u.hideElement(this.el.querySelector('.occupants'));
  21228. _.each(this.el.querySelectorAll('.spinner'), u.removeElement);
  21229. this.el.querySelector('.chatroom-body').insertAdjacentHTML(
  21230. 'beforeend',
  21231. tpl_chatroom_disconnect({
  21232. 'disconnect_message': msg
  21233. })
  21234. );
  21235. },
  21236. getMessageFromStatus (stat, stanza, is_self) {
  21237. /* Parameters:
  21238. * (XMLElement) stat: A <status> element.
  21239. * (Boolean) is_self: Whether the element refers to the
  21240. * current user.
  21241. * (XMLElement) stanza: The original stanza received.
  21242. */
  21243. const code = stat.getAttribute('code');
  21244. if (code === '110') { return; }
  21245. if (code in _converse.muc.info_messages) {
  21246. return _converse.muc.info_messages[code];
  21247. }
  21248. let nick;
  21249. if (!is_self) {
  21250. if (code in _converse.muc.action_info_messages) {
  21251. nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  21252. return __(_converse.muc.action_info_messages[code], nick);
  21253. }
  21254. } else if (code in _converse.muc.new_nickname_messages) {
  21255. if (is_self && code === "210") {
  21256. nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  21257. } else if (is_self && code === "303") {
  21258. nick = stanza.querySelector('x item').getAttribute('nick');
  21259. }
  21260. return __(_converse.muc.new_nickname_messages[code], nick);
  21261. }
  21262. return;
  21263. },
  21264. saveAffiliationAndRole (pres) {
  21265. /* Parse the presence stanza for the current user's
  21266. * affiliation.
  21267. *
  21268. * Parameters:
  21269. * (XMLElement) pres: A <presence> stanza.
  21270. */
  21271. const item = sizzle(`x[xmlns="${Strophe.NS.MUC_USER}"] item`, pres).pop();
  21272. const is_self = pres.querySelector("status[code='110']");
  21273. if (is_self && !_.isNil(item)) {
  21274. const affiliation = item.getAttribute('affiliation');
  21275. const role = item.getAttribute('role');
  21276. if (affiliation) {
  21277. this.model.save({'affiliation': affiliation});
  21278. }
  21279. if (role) {
  21280. this.model.save({'role': role});
  21281. }
  21282. }
  21283. },
  21284. parseXUserElement (x, stanza, is_self) {
  21285. /* Parse the passed-in <x xmlns='http://jabber.org/protocol/muc#user'>
  21286. * element and construct a map containing relevant
  21287. * information.
  21288. */
  21289. // 1. Get notification messages based on the <status> elements.
  21290. const statuses = x.querySelectorAll('status');
  21291. const mapper = _.partial(this.getMessageFromStatus, _, stanza, is_self);
  21292. const notification = {};
  21293. const messages = _.reject(_.map(statuses, mapper), _.isUndefined);
  21294. if (messages.length) {
  21295. notification.messages = messages;
  21296. }
  21297. // 2. Get disconnection messages based on the <status> elements
  21298. const codes = _.invokeMap(statuses, Element.prototype.getAttribute, 'code');
  21299. const disconnection_codes = _.intersection(codes, _.keys(_converse.muc.disconnect_messages));
  21300. const disconnected = is_self && disconnection_codes.length > 0;
  21301. if (disconnected) {
  21302. notification.disconnected = true;
  21303. notification.disconnection_message = _converse.muc.disconnect_messages[disconnection_codes[0]];
  21304. }
  21305. // 3. Find the reason and actor from the <item> element
  21306. const item = x.querySelector('item');
  21307. // By using querySelector above, we assume here there is
  21308. // one <item> per <x xmlns='http://jabber.org/protocol/muc#user'>
  21309. // element. This appears to be a safe assumption, since
  21310. // each <x/> element pertains to a single user.
  21311. if (!_.isNull(item)) {
  21312. const reason = item.querySelector('reason');
  21313. if (reason) {
  21314. notification.reason = reason ? reason.textContent : undefined;
  21315. }
  21316. const actor = item.querySelector('actor');
  21317. if (actor) {
  21318. notification.actor = actor ? actor.getAttribute('nick') : undefined;
  21319. }
  21320. }
  21321. return notification;
  21322. },
  21323. displayNotificationsforUser (notification) {
  21324. /* Given the notification object generated by
  21325. * parseXUserElement, display any relevant messages and
  21326. * information to the user.
  21327. */
  21328. if (notification.disconnected) {
  21329. this.showDisconnectMessage(notification.disconnection_message);
  21330. if (notification.actor) {
  21331. this.showDisconnectMessage(__('This action was done by %1$s.', notification.actor));
  21332. }
  21333. if (notification.reason) {
  21334. this.showDisconnectMessage(__('The reason given is: "%1$s".', notification.reason));
  21335. }
  21336. this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  21337. return;
  21338. }
  21339. _.each(notification.messages, (message) => {
  21340. this.content.insertAdjacentHTML(
  21341. 'beforeend',
  21342. tpl_info({
  21343. 'data': '',
  21344. 'isodate': moment().format(),
  21345. 'extra_classes': 'chat-event',
  21346. 'message': message
  21347. }));
  21348. });
  21349. if (notification.reason) {
  21350. this.showStatusNotification(__('The reason given is: "%1$s".', notification.reason), true);
  21351. }
  21352. if (_.get(notification.messages, 'length')) {
  21353. this.scrollDown();
  21354. }
  21355. },
  21356. displayJoinNotification (stanza) {
  21357. const nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  21358. const stat = stanza.querySelector('status');
  21359. const last_el = this.content.lastElementChild;
  21360. if (_.includes(_.get(last_el, 'classList', []), 'chat-info') &&
  21361. _.get(last_el, 'dataset', {}).leave === `"${nick}"`) {
  21362. last_el.outerHTML =
  21363. tpl_info({
  21364. 'data': `data-leavejoin="${nick}"`,
  21365. 'isodate': moment().format(),
  21366. 'extra_classes': 'chat-event',
  21367. 'message': __('%1$s has left and re-entered the room', nick)
  21368. });
  21369. } else {
  21370. let message;
  21371. if (_.get(stat, 'textContent')) {
  21372. message = __('%1$s has entered the room. "%2$s"', nick, stat.textContent);
  21373. } else {
  21374. message = __('%1$s has entered the room', nick);
  21375. }
  21376. const data = {
  21377. 'data': `data-join="${nick}"`,
  21378. 'isodate': moment().format(),
  21379. 'extra_classes': 'chat-event',
  21380. 'message': message
  21381. };
  21382. if (_.includes(_.get(last_el, 'classList', []), 'chat-info') &&
  21383. _.get(last_el, 'dataset', {}).joinleave === `"${nick}"`) {
  21384. last_el.outerHTML = tpl_info(data);
  21385. } else {
  21386. const el = u.stringToElement(tpl_info(data));
  21387. this.content.insertAdjacentElement('beforeend', el);
  21388. this.insertDayIndicator(el);
  21389. }
  21390. }
  21391. this.scrollDown();
  21392. },
  21393. displayLeaveNotification (stanza) {
  21394. const nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  21395. const stat = stanza.querySelector('status');
  21396. const last_el = this.content.lastElementChild;
  21397. if (_.includes(_.get(last_el, 'classList', []), 'chat-info') &&
  21398. _.get(last_el, 'dataset', {}).join === `"${nick}"`) {
  21399. let message;
  21400. if (_.get(stat, 'textContent')) {
  21401. message = __('%1$s has entered and left the room. "%2$s"', nick, stat.textContent);
  21402. } else {
  21403. message = __('%1$s has entered and left the room', nick);
  21404. }
  21405. last_el.outerHTML =
  21406. tpl_info({
  21407. 'data': `data-joinleave="${nick}"`,
  21408. 'isodate': moment().format(),
  21409. 'extra_classes': 'chat-event',
  21410. 'message': message
  21411. });
  21412. } else {
  21413. let message;
  21414. if (_.get(stat, 'textContent')) {
  21415. message = __('%1$s has left the room. "%2$s"', nick, stat.textContent);
  21416. } else {
  21417. message = __('%1$s has left the room', nick);
  21418. }
  21419. const data = {
  21420. 'message': message,
  21421. 'isodate': moment().format(),
  21422. 'extra_classes': 'chat-event',
  21423. 'data': `data-leave="${nick}"`
  21424. }
  21425. if (_.includes(_.get(last_el, 'classList', []), 'chat-info') &&
  21426. _.get(last_el, 'dataset', {}).leavejoin === `"${nick}"`) {
  21427. last_el.outerHTML = tpl_info(data);
  21428. } else {
  21429. const el = u.stringToElement(tpl_info(data));
  21430. this.content.insertAdjacentElement('beforeend', el);
  21431. this.insertDayIndicator(el);
  21432. }
  21433. }
  21434. this.scrollDown();
  21435. },
  21436. displayJoinOrLeaveNotification (stanza) {
  21437. if (stanza.getAttribute('type') === 'unavailable') {
  21438. this.displayLeaveNotification(stanza);
  21439. } else {
  21440. const nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  21441. if (!this.occupantsview.model.find({'nick': nick})) {
  21442. // Only show join message if we don't already have the
  21443. // occupant model. Doing so avoids showing duplicate
  21444. // join messages.
  21445. this.displayJoinNotification(stanza);
  21446. }
  21447. }
  21448. },
  21449. showStatusMessages (stanza) {
  21450. /* Check for status codes and communicate their purpose to the user.
  21451. * See: http://xmpp.org/registrar/mucstatus.html
  21452. *
  21453. * Parameters:
  21454. * (XMLElement) stanza: The message or presence stanza
  21455. * containing the status codes.
  21456. */
  21457. const elements = sizzle(`x[xmlns="${Strophe.NS.MUC_USER}"]`, stanza);
  21458. const is_self = stanza.querySelectorAll("status[code='110']").length;
  21459. const iteratee = _.partial(this.parseXUserElement.bind(this), _, stanza, is_self);
  21460. const notifications = _.reject(_.map(elements, iteratee), _.isEmpty);
  21461. if (_.isEmpty(notifications)) {
  21462. if (_converse.muc_show_join_leave &&
  21463. stanza.nodeName === 'presence' &&
  21464. this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
  21465. this.displayJoinOrLeaveNotification(stanza);
  21466. }
  21467. } else {
  21468. _.each(notifications, this.displayNotificationsforUser.bind(this));
  21469. }
  21470. return stanza;
  21471. },
  21472. showErrorMessage (presence) {
  21473. // We didn't enter the room, so we must remove it from the MUC add-on
  21474. const error = presence.querySelector('error');
  21475. if (error.getAttribute('type') === 'auth') {
  21476. if (!_.isNull(error.querySelector('not-authorized'))) {
  21477. this.renderPasswordForm();
  21478. } else if (!_.isNull(error.querySelector('registration-required'))) {
  21479. this.showDisconnectMessage(__('You are not on the member list of this room.'));
  21480. } else if (!_.isNull(error.querySelector('forbidden'))) {
  21481. this.showDisconnectMessage(__('You have been banned from this room.'));
  21482. }
  21483. } else if (error.getAttribute('type') === 'modify') {
  21484. if (!_.isNull(error.querySelector('jid-malformed'))) {
  21485. this.showDisconnectMessage(__('No nickname was specified.'));
  21486. }
  21487. } else if (error.getAttribute('type') === 'cancel') {
  21488. if (!_.isNull(error.querySelector('not-allowed'))) {
  21489. this.showDisconnectMessage(__('You are not allowed to create new rooms.'));
  21490. } else if (!_.isNull(error.querySelector('not-acceptable'))) {
  21491. this.showDisconnectMessage(__("Your nickname doesn't conform to this room's policies."));
  21492. } else if (!_.isNull(error.querySelector('conflict'))) {
  21493. this.onNicknameClash(presence);
  21494. } else if (!_.isNull(error.querySelector('item-not-found'))) {
  21495. this.showDisconnectMessage(__("This room does not (yet) exist."));
  21496. } else if (!_.isNull(error.querySelector('service-unavailable'))) {
  21497. this.showDisconnectMessage(__("This room has reached its maximum number of occupants."));
  21498. }
  21499. }
  21500. },
  21501. renderAfterTransition () {
  21502. /* Rerender the room after some kind of transition. For
  21503. * example after the spinner has been removed or after a
  21504. * form has been submitted and removed.
  21505. */
  21506. if (this.model.get('connection_status') == converse.ROOMSTATUS.NICKNAME_REQUIRED) {
  21507. this.renderNicknameForm();
  21508. } else if (this.model.get('connection_status') == converse.ROOMSTATUS.PASSWORD_REQUIRED) {
  21509. this.renderPasswordForm();
  21510. } else {
  21511. this.el.querySelector('.chat-area').classList.remove('hidden');
  21512. this.setOccupantsVisibility();
  21513. this.scrollDown();
  21514. }
  21515. },
  21516. showSpinner () {
  21517. u.removeElement(this.el.querySelector('.spinner'));
  21518. const container_el = this.el.querySelector('.chatroom-body');
  21519. const children = Array.prototype.slice.call(container_el.children, 0);
  21520. container_el.insertAdjacentHTML('afterbegin', tpl_spinner());
  21521. _.each(children, u.hideElement);
  21522. },
  21523. hideSpinner () {
  21524. /* Check if the spinner is being shown and if so, hide it.
  21525. * Also make sure then that the chat area and occupants
  21526. * list are both visible.
  21527. */
  21528. const spinner = this.el.querySelector('.spinner');
  21529. if (!_.isNull(spinner)) {
  21530. u.removeElement(spinner);
  21531. this.renderAfterTransition();
  21532. }
  21533. return this;
  21534. },
  21535. onOwnChatRoomPresence (pres) {
  21536. /* Handles a received presence relating to the current
  21537. * user.
  21538. *
  21539. * For locked rooms (which are by definition "new"), the
  21540. * room will either be auto-configured or created instantly
  21541. * (with default config) or a configuration room will be
  21542. * rendered.
  21543. *
  21544. * If the room is not locked, then the room will be
  21545. * auto-configured only if applicable and if the current
  21546. * user is the room's owner.
  21547. *
  21548. * Parameters:
  21549. * (XMLElement) pres: The stanza
  21550. */
  21551. this.saveAffiliationAndRole(pres);
  21552. const locked_room = pres.querySelector("status[code='201']");
  21553. if (locked_room) {
  21554. if (this.model.get('auto_configure')) {
  21555. this.autoConfigureChatRoom().then(this.getRoomFeatures.bind(this));
  21556. } else if (_converse.muc_instant_rooms) {
  21557. // Accept default configuration
  21558. this.saveConfiguration().then(this.getRoomFeatures.bind(this));
  21559. } else {
  21560. this.getAndRenderConfigurationForm();
  21561. return; // We haven't yet entered the room, so bail here.
  21562. }
  21563. } else if (!this.model.get('features_fetched')) {
  21564. // The features for this room weren't fetched.
  21565. // That must mean it's a new room without locking
  21566. // (in which case Prosody doesn't send a 201 status),
  21567. // otherwise the features would have been fetched in
  21568. // the "initialize" method already.
  21569. if (this.model.get('affiliation') === 'owner' && this.model.get('auto_configure')) {
  21570. this.autoConfigureChatRoom().then(this.getRoomFeatures.bind(this));
  21571. } else {
  21572. this.getRoomFeatures();
  21573. }
  21574. }
  21575. this.model.save('connection_status', converse.ROOMSTATUS.ENTERED);
  21576. },
  21577. onChatRoomPresence (pres) {
  21578. /* Handles all MUC presence stanzas.
  21579. *
  21580. * Parameters:
  21581. * (XMLElement) pres: The stanza
  21582. */
  21583. if (pres.getAttribute('type') === 'error') {
  21584. this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  21585. this.showErrorMessage(pres);
  21586. return true;
  21587. }
  21588. const is_self = pres.querySelector("status[code='110']");
  21589. if (is_self && pres.getAttribute('type') !== 'unavailable') {
  21590. this.onOwnChatRoomPresence(pres);
  21591. }
  21592. this.hideSpinner().showStatusMessages(pres);
  21593. // This must be called after showStatusMessages so that
  21594. // "join" messages are correctly shown.
  21595. this.occupantsview.updateOccupantsOnPresence(pres);
  21596. if (this.model.get('role') !== 'none' &&
  21597. this.model.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
  21598. this.model.save('connection_status', converse.ROOMSTATUS.CONNECTED);
  21599. }
  21600. return true;
  21601. },
  21602. setChatRoomSubject (sender, subject) {
  21603. // For translators: the %1$s and %2$s parts will get
  21604. // replaced by the user and topic text respectively
  21605. // Example: Topic set by JC Brand to: Hello World!
  21606. this.content.insertAdjacentHTML(
  21607. 'beforeend',
  21608. tpl_info({
  21609. 'data': '',
  21610. 'isodate': moment().format(),
  21611. 'extra_classes': 'chat-event',
  21612. 'message': __('Topic set by %1$s', sender)
  21613. }));
  21614. this.content.insertAdjacentHTML(
  21615. 'beforeend',
  21616. tpl_info({
  21617. 'data': '',
  21618. 'isodate': moment().format(),
  21619. 'extra_classes': 'chat-topic',
  21620. 'message': subject
  21621. }));
  21622. this.scrollDown();
  21623. },
  21624. isDuplicateBasedOnTime (message) {
  21625. /* Checks whether a received messages is actually a
  21626. * duplicate based on whether it has a "ts" attribute
  21627. * with a unix timestamp.
  21628. *
  21629. * This is used for better integration with Slack's XMPP
  21630. * gateway, which doesn't use message IDs but instead the
  21631. * aforementioned "ts" attributes.
  21632. */
  21633. const entity = _converse.disco_entities.get(_converse.domain);
  21634. if (entity.identities.where({'name': "Slack-XMPP"})) {
  21635. const ts = message.getAttribute('ts');
  21636. if (_.isNull(ts)) {
  21637. return false;
  21638. } else {
  21639. return this.model.messages.where({
  21640. 'sender': 'me',
  21641. 'message': this.model.getMessageBody(message)
  21642. }).filter(
  21643. (msg) => Math.abs(moment(msg.get('time')).diff(moment.unix(ts))) < 5000
  21644. ).length > 0;
  21645. }
  21646. }
  21647. return false;
  21648. },
  21649. isDuplicate (message, original_stanza) {
  21650. const msgid = message.getAttribute('id'),
  21651. jid = message.getAttribute('from'),
  21652. resource = Strophe.getResourceFromJid(jid),
  21653. sender = resource && Strophe.unescapeNode(resource) || '';
  21654. if (msgid) {
  21655. return this.model.messages.filter(
  21656. // Some bots (like HAL in the prosody chatroom)
  21657. // respond to commands with the same ID as the
  21658. // original message. So we also check the sender.
  21659. (msg) => msg.get('msgid') === msgid && msg.get('fullname') === sender
  21660. ).length > 0;
  21661. }
  21662. return this.isDuplicateBasedOnTime(message);
  21663. },
  21664. onChatRoomMessage (message) {
  21665. /* Given a <message> stanza, create a message
  21666. * Backbone.Model if appropriate.
  21667. *
  21668. * Parameters:
  21669. * (XMLElement) msg: The received message stanza
  21670. */
  21671. const original_stanza = message,
  21672. forwarded = message.querySelector('forwarded');
  21673. let delay;
  21674. if (!_.isNull(forwarded)) {
  21675. message = forwarded.querySelector('message');
  21676. delay = forwarded.querySelector('delay');
  21677. }
  21678. const jid = message.getAttribute('from'),
  21679. resource = Strophe.getResourceFromJid(jid),
  21680. sender = resource && Strophe.unescapeNode(resource) || '',
  21681. subject = _.propertyOf(message.querySelector('subject'))('textContent');
  21682. if (this.isDuplicate(message, original_stanza)) {
  21683. return true;
  21684. }
  21685. if (subject) {
  21686. this.setChatRoomSubject(sender, subject);
  21687. }
  21688. if (sender === '') {
  21689. return true;
  21690. }
  21691. this.model.incrementUnreadMsgCounter(original_stanza);
  21692. this.model.createMessage(message, delay, original_stanza);
  21693. if (sender !== this.model.get('nick')) {
  21694. // We only emit an event if it's not our own message
  21695. _converse.emit(
  21696. 'message',
  21697. {'stanza': original_stanza, 'chatbox': this.model}
  21698. );
  21699. }
  21700. return true;
  21701. }
  21702. });
  21703. _converse.RoomsPanel = Backbone.NativeView.extend({
  21704. /* Backbone.NativeView which renders MUC section of the control box.
  21705. *
  21706. * Chat rooms can be listed, joined and new rooms can be created.
  21707. */
  21708. tagName: 'div',
  21709. className: 'controlbox-pane',
  21710. id: 'chatrooms',
  21711. events: {
  21712. 'click a.chatbox-btn.fa-users': 'showAddRoomModal',
  21713. 'click a.chatbox-btn.fa-list-ul': 'showListRoomsModal',
  21714. 'click a.room-info': 'toggleRoomInfo'
  21715. },
  21716. render () {
  21717. this.el.innerHTML = tpl_room_panel({
  21718. 'heading_chatrooms': __('Chatrooms'),
  21719. 'title_new_room': __('Add a new room'),
  21720. 'title_list_rooms': __('Query for rooms')
  21721. });
  21722. return this;
  21723. },
  21724. toggleRoomInfo (ev) {
  21725. ev.preventDefault();
  21726. toggleRoomInfo(ev);
  21727. },
  21728. showAddRoomModal (ev) {
  21729. if (_.isUndefined(this.add_room_modal)) {
  21730. this.add_room_modal = new _converse.AddChatRoomModal({'model': this.model});
  21731. }
  21732. this.add_room_modal.show(ev);
  21733. },
  21734. showListRoomsModal(ev) {
  21735. if (_.isUndefined(this.list_rooms_modal)) {
  21736. this.list_rooms_modal = new _converse.ListChatRoomsModal({'model': this.model});
  21737. }
  21738. this.list_rooms_modal.show(ev);
  21739. }
  21740. });
  21741. _converse.ChatRoomOccupantView = Backbone.VDOMView.extend({
  21742. tagName: 'li',
  21743. initialize () {
  21744. this.model.on('change', this.render, this);
  21745. },
  21746. toHTML () {
  21747. const show = this.model.get('show') || 'online';
  21748. return tpl_occupant(
  21749. _.extend(
  21750. { 'jid': '',
  21751. 'show': show,
  21752. 'hint_show': _converse.PRETTY_CHAT_STATUS[show],
  21753. 'hint_occupant': __('Click to mention %1$s in your message.', this.model.get('nick')),
  21754. 'desc_moderator': __('This user is a moderator.'),
  21755. 'desc_occupant': __('This user can send messages in this room.'),
  21756. 'desc_visitor': __('This user can NOT send messages in this room.')
  21757. }, this.model.toJSON())
  21758. );
  21759. },
  21760. destroy () {
  21761. this.el.parentElement.removeChild(this.el);
  21762. }
  21763. });
  21764. _converse.ChatRoomOccupantsView = Backbone.OrderedListView.extend({
  21765. tagName: 'div',
  21766. className: 'occupants col-md-3 col-4',
  21767. listItems: 'model',
  21768. sortEvent: 'change:role',
  21769. listSelector: '.occupant-list',
  21770. ItemView: _converse.ChatRoomOccupantView,
  21771. initialize () {
  21772. Backbone.OrderedListView.prototype.initialize.apply(this, arguments);
  21773. this.chatroomview = this.model.chatroomview;
  21774. this.chatroomview.model.on('change:open', this.renderInviteWidget, this);
  21775. this.chatroomview.model.on('change:affiliation', this.renderInviteWidget, this);
  21776. this.chatroomview.model.on('change:hidden', this.onFeatureChanged, this);
  21777. this.chatroomview.model.on('change:mam_enabled', this.onFeatureChanged, this);
  21778. this.chatroomview.model.on('change:membersonly', this.onFeatureChanged, this);
  21779. this.chatroomview.model.on('change:moderated', this.onFeatureChanged, this);
  21780. this.chatroomview.model.on('change:nonanonymous', this.onFeatureChanged, this);
  21781. this.chatroomview.model.on('change:open', this.onFeatureChanged, this);
  21782. this.chatroomview.model.on('change:passwordprotected', this.onFeatureChanged, this);
  21783. this.chatroomview.model.on('change:persistent', this.onFeatureChanged, this);
  21784. this.chatroomview.model.on('change:publicroom', this.onFeatureChanged, this);
  21785. this.chatroomview.model.on('change:semianonymous', this.onFeatureChanged, this);
  21786. this.chatroomview.model.on('change:temporary', this.onFeatureChanged, this);
  21787. this.chatroomview.model.on('change:unmoderated', this.onFeatureChanged, this);
  21788. this.chatroomview.model.on('change:unsecured', this.onFeatureChanged, this);
  21789. const id = b64_sha1(`converse.occupants${_converse.bare_jid}${this.chatroomview.model.get('jid')}`);
  21790. this.model.browserStorage = new Backbone.BrowserStorage.session(id);
  21791. this.render();
  21792. this.model.fetch({
  21793. 'add': true,
  21794. 'silent': true,
  21795. 'success': this.sortAndPositionAllItems.bind(this)
  21796. });
  21797. },
  21798. render () {
  21799. this.el.innerHTML = tpl_chatroom_sidebar(
  21800. _.extend(this.chatroomview.model.toJSON(), {
  21801. 'allow_muc_invitations': _converse.allow_muc_invitations,
  21802. 'label_occupants': __('Occupants')
  21803. })
  21804. );
  21805. if (_converse.allow_muc_invitations) {
  21806. _converse.api.waitUntil('rosterContactsFetched').then(
  21807. this.renderInviteWidget.bind(this)
  21808. );
  21809. }
  21810. return this.renderRoomFeatures();
  21811. },
  21812. renderInviteWidget () {
  21813. const form = this.el.querySelector('form.room-invite');
  21814. if (this.shouldInviteWidgetBeShown()) {
  21815. if (_.isNull(form)) {
  21816. const heading = this.el.querySelector('.occupants-heading');
  21817. heading.insertAdjacentHTML(
  21818. 'afterend',
  21819. tpl_chatroom_invite({
  21820. 'error_message': null,
  21821. 'label_invitation': __('Invite'),
  21822. })
  21823. );
  21824. this.initInviteWidget();
  21825. }
  21826. } else if (!_.isNull(form)) {
  21827. form.remove();
  21828. }
  21829. return this;
  21830. },
  21831. renderRoomFeatures () {
  21832. const picks = _.pick(this.chatroomview.model.attributes, converse.ROOM_FEATURES),
  21833. iteratee = (a, v) => a || v,
  21834. el = this.el.querySelector('.chatroom-features');
  21835. el.innerHTML = tpl_chatroom_features(
  21836. _.extend(this.chatroomview.model.toJSON(), {
  21837. 'has_features': _.reduce(_.values(picks), iteratee),
  21838. 'label_features': __('Features'),
  21839. 'label_hidden': __('Hidden'),
  21840. 'label_mam_enabled': __('Message archiving'),
  21841. 'label_membersonly': __('Members only'),
  21842. 'label_moderated': __('Moderated'),
  21843. 'label_nonanonymous': __('Non-anonymous'),
  21844. 'label_open': __('Open'),
  21845. 'label_passwordprotected': __('Password protected'),
  21846. 'label_persistent': __('Persistent'),
  21847. 'label_public': __('Public'),
  21848. 'label_semianonymous': __('Semi-anonymous'),
  21849. 'label_temporary': __('Temporary'),
  21850. 'label_unmoderated': __('Unmoderated'),
  21851. 'label_unsecured': __('No password'),
  21852. 'tt_hidden': __('This room is not publicly searchable'),
  21853. 'tt_mam_enabled': __('Messages are archived on the server'),
  21854. 'tt_membersonly': __('This room is restricted to members only'),
  21855. 'tt_moderated': __('This room is being moderated'),
  21856. 'tt_nonanonymous': __('All other room occupants can see your XMPP username'),
  21857. 'tt_open': __('Anyone can join this room'),
  21858. 'tt_passwordprotected': __('This room requires a password before entry'),
  21859. 'tt_persistent': __('This room persists even if it\'s unoccupied'),
  21860. 'tt_public': __('This room is publicly searchable'),
  21861. 'tt_semianonymous': __('Only moderators can see your XMPP username'),
  21862. 'tt_temporary': __('This room will disappear once the last person leaves'),
  21863. 'tt_unmoderated': __('This room is not being moderated'),
  21864. 'tt_unsecured': __('This room does not require a password upon entry')
  21865. }));
  21866. this.setOccupantsHeight();
  21867. return this;
  21868. },
  21869. onFeatureChanged (model) {
  21870. /* When a feature has been changed, it's logical opposite
  21871. * must be set to the opposite value.
  21872. *
  21873. * So for example, if "temporary" was set to "false", then
  21874. * "persistent" will be set to "true" in this method.
  21875. *
  21876. * Additionally a debounced render method is called to make
  21877. * sure the features widget gets updated.
  21878. */
  21879. if (_.isUndefined(this.debouncedRenderRoomFeatures)) {
  21880. this.debouncedRenderRoomFeatures = _.debounce(
  21881. this.renderRoomFeatures, 100, {'leading': false}
  21882. );
  21883. }
  21884. const changed_features = {};
  21885. _.each(_.keys(model.changed), function (k) {
  21886. if (!_.isNil(ROOM_FEATURES_MAP[k])) {
  21887. changed_features[ROOM_FEATURES_MAP[k]] = !model.changed[k];
  21888. }
  21889. });
  21890. this.chatroomview.model.save(changed_features, {'silent': true});
  21891. this.debouncedRenderRoomFeatures();
  21892. },
  21893. setOccupantsHeight () {
  21894. const el = this.el.querySelector('.chatroom-features');
  21895. this.el.querySelector('.occupant-list').style.cssText =
  21896. `height: calc(100% - ${el.offsetHeight}px - 5em);`;
  21897. },
  21898. parsePresence (pres) {
  21899. const id = Strophe.getResourceFromJid(pres.getAttribute("from"));
  21900. const data = {
  21901. nick: id,
  21902. type: pres.getAttribute("type"),
  21903. states: []
  21904. };
  21905. _.each(pres.childNodes, function (child) {
  21906. switch (child.nodeName) {
  21907. case "status":
  21908. data.status = child.textContent || null;
  21909. break;
  21910. case "show":
  21911. data.show = child.textContent || 'online';
  21912. break;
  21913. case "x":
  21914. if (child.getAttribute("xmlns") === Strophe.NS.MUC_USER) {
  21915. _.each(child.childNodes, function (item) {
  21916. switch (item.nodeName) {
  21917. case "item":
  21918. data.affiliation = item.getAttribute("affiliation");
  21919. data.role = item.getAttribute("role");
  21920. data.jid = item.getAttribute("jid");
  21921. data.nick = item.getAttribute("nick") || data.nick;
  21922. break;
  21923. case "status":
  21924. if (item.getAttribute("code")) {
  21925. data.states.push(item.getAttribute("code"));
  21926. }
  21927. }
  21928. });
  21929. }
  21930. }
  21931. });
  21932. return data;
  21933. },
  21934. findOccupant (data) {
  21935. /* Try to find an existing occupant based on the passed in
  21936. * data object.
  21937. *
  21938. * If we have a JID, we use that as lookup variable,
  21939. * otherwise we use the nick. We don't always have both,
  21940. * but should have at least one or the other.
  21941. */
  21942. const jid = Strophe.getBareJidFromJid(data.jid);
  21943. if (jid !== null) {
  21944. return this.model.where({'jid': jid}).pop();
  21945. } else {
  21946. return this.model.where({'nick': data.nick}).pop();
  21947. }
  21948. },
  21949. updateOccupantsOnPresence (pres) {
  21950. /* Given a presence stanza, update the occupant models
  21951. * based on its contents.
  21952. *
  21953. * Parameters:
  21954. * (XMLElement) pres: The presence stanza
  21955. */
  21956. const data = this.parsePresence(pres);
  21957. if (data.type === 'error') {
  21958. return true;
  21959. }
  21960. const occupant = this.findOccupant(data);
  21961. if (data.type === 'unavailable') {
  21962. if (occupant) { occupant.destroy(); }
  21963. } else {
  21964. const jid = Strophe.getBareJidFromJid(data.jid);
  21965. const attributes = _.extend(data, {
  21966. 'jid': jid ? jid : undefined,
  21967. 'resource': data.jid ? Strophe.getResourceFromJid(data.jid) : undefined
  21968. });
  21969. if (occupant) {
  21970. occupant.save(attributes);
  21971. } else {
  21972. this.model.create(attributes);
  21973. }
  21974. }
  21975. },
  21976. promptForInvite (suggestion) {
  21977. const reason = prompt(
  21978. __('You are about to invite %1$s to the chat room "%2$s". '+
  21979. 'You may optionally include a message, explaining the reason for the invitation.',
  21980. suggestion.text.label, this.model.get('id'))
  21981. );
  21982. if (reason !== null) {
  21983. this.chatroomview.directInvite(suggestion.text.value, reason);
  21984. }
  21985. const form = suggestion.target.form,
  21986. error = form.querySelector('.pure-form-message.error');
  21987. if (!_.isNull(error)) {
  21988. error.parentNode.removeChild(error);
  21989. }
  21990. suggestion.target.value = '';
  21991. },
  21992. inviteFormSubmitted (evt) {
  21993. evt.preventDefault();
  21994. const el = evt.target.querySelector('input.invited-contact'),
  21995. jid = el.value;
  21996. if (!jid || _.compact(jid.split('@')).length < 2) {
  21997. evt.target.outerHTML = tpl_chatroom_invite({
  21998. 'error_message': __('Please enter a valid XMPP username'),
  21999. 'label_invitation': __('Invite'),
  22000. });
  22001. this.initInviteWidget();
  22002. return;
  22003. }
  22004. this.promptForInvite({
  22005. 'target': el,
  22006. 'text': {
  22007. 'label': jid,
  22008. 'value': jid
  22009. }});
  22010. },
  22011. shouldInviteWidgetBeShown () {
  22012. return _converse.allow_muc_invitations &&
  22013. (this.chatroomview.model.get('open') ||
  22014. this.chatroomview.model.get('affiliation') === "owner"
  22015. );
  22016. },
  22017. initInviteWidget () {
  22018. const form = this.el.querySelector('form.room-invite');
  22019. if (_.isNull(form)) {
  22020. return;
  22021. }
  22022. form.addEventListener('submit', this.inviteFormSubmitted.bind(this), false);
  22023. const el = this.el.querySelector('input.invited-contact');
  22024. const list = _converse.roster.map(function (item) {
  22025. const label = item.get('fullname') || item.get('jid');
  22026. return {'label': label, 'value':item.get('jid')};
  22027. });
  22028. const awesomplete = new Awesomplete(el, {
  22029. 'minChars': 1,
  22030. 'list': list
  22031. });
  22032. el.addEventListener('awesomplete-selectcomplete',
  22033. this.promptForInvite.bind(this));
  22034. }
  22035. });
  22036. function setMUCDomain (domain, controlboxview) {
  22037. _converse.muc_domain = domain;
  22038. controlboxview.roomspanel.model.save({'muc_domain': domain});
  22039. }
  22040. function setMUCDomainFromDisco (controlboxview) {
  22041. /* Check whether service discovery for the user's domain
  22042. * returned MUC information and use that to automatically
  22043. * set the MUC domain for the "Rooms" panel of the controlbox.
  22044. */
  22045. function featureAdded (feature) {
  22046. if (feature.get('var') === Strophe.NS.MUC &&
  22047. f.includes('conference', feature.entity.identities.pluck('category'))) {
  22048. setMUCDomain(feature.get('from'), controlboxview);
  22049. }
  22050. }
  22051. _converse.api.waitUntil('discoInitialized').then(() => {
  22052. _converse.api.listen.on('serviceDiscovered', featureAdded);
  22053. // Features could have been added before the controlbox was
  22054. // initialized. We're only interested in MUC
  22055. _converse.disco_entities.each((entity) => {
  22056. const feature = entity.features.findWhere({'var': Strophe.NS.MUC });
  22057. if (feature) {
  22058. featureAdded(feature)
  22059. }
  22060. });
  22061. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
  22062. }
  22063. function fetchAndSetMUCDomain (controlboxview) {
  22064. if (controlboxview.model.get('connected')) {
  22065. if (!controlboxview.roomspanel.model.get('muc_domain')) {
  22066. if (_.isUndefined(_converse.muc_domain)) {
  22067. setMUCDomainFromDisco(controlboxview);
  22068. } else {
  22069. setMUCDomain(_converse.muc_domain, controlboxview);
  22070. }
  22071. }
  22072. }
  22073. }
  22074. /************************ BEGIN Event Handlers ************************/
  22075. _converse.on('controlboxInitialized', (view) => {
  22076. if (!_converse.allow_muc) {
  22077. return;
  22078. }
  22079. fetchAndSetMUCDomain(view);
  22080. view.model.on('change:connected', _.partial(fetchAndSetMUCDomain, view));
  22081. });
  22082. /************************ END Event Handlers ************************/
  22083. }
  22084. });
  22085. }));
  22086. // Converse.js (A browser based XMPP chat client)
  22087. // http://conversejs.org
  22088. //
  22089. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  22090. // Licensed under the Mozilla Public License (MPLv2)
  22091. //
  22092. (function (root, factory) {
  22093. define('converse-muc-embedded',["converse-core", "converse-muc"], factory);
  22094. })(void 0, function (converse) {
  22095. "use strict";
  22096. var _converse$env = converse.env,
  22097. Backbone = _converse$env.Backbone,
  22098. _ = _converse$env._;
  22099. converse.plugins.add('converse-muc-embedded', {
  22100. enabled: function enabled(_converse) {
  22101. return _converse.view_mode === 'embedded';
  22102. },
  22103. overrides: {
  22104. // Overrides mentioned here will be picked up by converse.js's
  22105. // plugin architecture they will replace existing methods on the
  22106. // relevant objects or classes.
  22107. //
  22108. // New functions which don't exist yet can also be added.
  22109. ChatBoxViews: {
  22110. initialize: function initialize() {
  22111. this.__super__.initialize.apply(this, arguments);
  22112. this.el.classList.add('converse-embedded');
  22113. }
  22114. }
  22115. },
  22116. initialize: function initialize() {
  22117. /* The initialize function gets called as soon as the plugin is
  22118. * loaded by converse.js's plugin machinery.
  22119. */
  22120. this._converse.api.settings.update({
  22121. 'allow_logout': false,
  22122. // No point in logging out when we have auto_login as true.
  22123. 'allow_muc_invitations': false,
  22124. // Doesn't make sense to allow because only
  22125. // roster contacts can be invited
  22126. 'hide_muc_server': true // Federation is disabled, so no use in
  22127. // showing the MUC server.
  22128. });
  22129. var _converse = this._converse;
  22130. if (!_.isArray(_converse.auto_join_rooms)) {
  22131. throw new Error("converse-muc-embedded: auto_join_rooms must be an Array");
  22132. }
  22133. if (_converse.auto_join_rooms.length !== 1) {
  22134. throw new Error("converse-muc-embedded: It doesn't make " + "sense to have the auto_join_rooms setting to zero or " + "more then one, since only one chat room can be open " + "at any time.");
  22135. }
  22136. }
  22137. });
  22138. });
  22139. //# sourceMappingURL=converse-muc-embedded.js.map;
  22140. define('tpl!toolbar_otr', ['lodash'], function(_) {return function(o) {
  22141. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  22142. function print() { __p += __j.call(arguments, '') }
  22143. if (o.allow_otr) { ;
  22144. __p += '\n <li class="toggle-toolbar-menu dropup right" title="' +
  22145. __e(o.otr_tooltip) +
  22146. '">\n <a class="toggle-otr ' +
  22147. __e(o.otr_status_class) +
  22148. '" title="' +
  22149. __e(o.label_insert_smiley) +
  22150. '" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">\n\n <span class="chat-toolbar-text">' +
  22151. __e(o.otr_translated_status) +
  22152. '</span>\n ';
  22153. if (o.otr_status == o.UNENCRYPTED) { ;
  22154. __p += '\n <span class="fa fa-unlock"></span>\n ';
  22155. } ;
  22156. __p += '\n ';
  22157. if (o.otr_status == o.UNVERIFIED) { ;
  22158. __p += '\n <span class="fa fa-lock"></span>\n ';
  22159. } ;
  22160. __p += '\n ';
  22161. if (o.otr_status == o.VERIFIED) { ;
  22162. __p += '\n <span class="fa fa-lock"></span>\n ';
  22163. } ;
  22164. __p += ' ';
  22165. if (o.otr_status == o.FINISHED) { ;
  22166. __p += '\n <span class="fa fa-unlock"></span>\n ';
  22167. } ;
  22168. __p += '\n </a> \n\n <ul class="otr-menu toolbar-menu dropdown-menu">\n ';
  22169. if (o.otr_status == o.UNENCRYPTED) { ;
  22170. __p += '\n <li class="dropdown-item"><a class="start-otr" href="#">' +
  22171. __e(o.label_start_encrypted_conversation) +
  22172. '</a></li>\n ';
  22173. } ;
  22174. __p += '\n ';
  22175. if (o.otr_status != o.UNENCRYPTED) { ;
  22176. __p += '\n <li class="dropdown-item"><a class="start-otr" href="#">' +
  22177. __e(o.label_refresh_encrypted_conversation) +
  22178. '</a></li>\n <li class="dropdown-item"><a class="end-otr" href="#">' +
  22179. __e(o.label_end_encrypted_conversation) +
  22180. '</a></li>\n <li class="dropdown-item"><a class="auth-otr" data-scheme="smp" href="#">' +
  22181. __e(o.label_verify_with_smp) +
  22182. '</a></li>\n ';
  22183. } ;
  22184. __p += '\n ';
  22185. if (o.otr_status == o.UNVERIFIED) { ;
  22186. __p += '\n <li class="dropdown-item"><a class="auth-otr" data-scheme="fingerprint" href="#">' +
  22187. __e(o.label_verify_with_fingerprints) +
  22188. '</a></li>\n ';
  22189. } ;
  22190. __p += '\n <li class="dropdown-item"><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank" rel="noopener">' +
  22191. __e(o.label_whats_this) +
  22192. '</a></li>\n </ul>\n </li>\n';
  22193. } ;
  22194. __p += '\n';
  22195. return __p
  22196. };});
  22197. // Converse.js (A browser based XMPP chat client)
  22198. // http://conversejs.org
  22199. //
  22200. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  22201. // Licensed under the Mozilla Public License (MPLv2)
  22202. //
  22203. /*global define, window, crypto, CryptoJS */
  22204. /* This is a Converse.js plugin which add support Off-the-record (OTR)
  22205. * encryption of one-on-one chat messages.
  22206. */
  22207. (function (root, factory) {
  22208. define('converse-otr',["converse-chatview", "bootstrap", "tpl!toolbar_otr", 'otr'], factory);
  22209. })(void 0, function (converse, bootstrap, tpl_toolbar_otr, otr) {
  22210. "use strict";
  22211. var _converse$env = converse.env,
  22212. Strophe = _converse$env.Strophe,
  22213. utils = _converse$env.utils,
  22214. b64_sha1 = _converse$env.b64_sha1,
  22215. _ = _converse$env._;
  22216. var HAS_CSPRNG = _.isUndefined(window.crypto) ? false : _.isFunction(window.crypto.randomBytes) || _.isFunction(window.crypto.getRandomValues);
  22217. var HAS_CRYPTO = HAS_CSPRNG && !_.isUndefined(otr.OTR) && !_.isUndefined(otr.DSA);
  22218. var UNENCRYPTED = 0;
  22219. var UNVERIFIED = 1;
  22220. var VERIFIED = 2;
  22221. var FINISHED = 3;
  22222. var OTR_TRANSLATED_MAPPING = {}; // Populated in initialize
  22223. var OTR_CLASS_MAPPING = {};
  22224. OTR_CLASS_MAPPING[UNENCRYPTED] = 'unencrypted';
  22225. OTR_CLASS_MAPPING[UNVERIFIED] = 'unverified';
  22226. OTR_CLASS_MAPPING[VERIFIED] = 'verified';
  22227. OTR_CLASS_MAPPING[FINISHED] = 'finished';
  22228. converse.plugins.add('converse-otr', {
  22229. /* Plugin dependencies are other plugins which might be
  22230. * overridden or relied upon, and therefore need to be loaded before
  22231. * this plugin.
  22232. *
  22233. * If the setting "strict_plugin_dependencies" is set to true,
  22234. * an error will be raised if the plugin is not found. By default it's
  22235. * false, which means these plugins are only loaded opportunistically.
  22236. *
  22237. * NB: These plugins need to have already been loaded via require.js.
  22238. */
  22239. dependencies: ["converse-chatview"],
  22240. overrides: {
  22241. // Overrides mentioned here will be picked up by converse.js's
  22242. // plugin architecture they will replace existing methods on the
  22243. // relevant objects or classes.
  22244. //
  22245. // New functions which don't exist yet can also be added.
  22246. ChatBox: {
  22247. initialize: function initialize() {
  22248. this.__super__.initialize.apply(this, arguments);
  22249. if (this.get('box_id') !== 'controlbox') {
  22250. this.save({
  22251. 'otr_status': this.get('otr_status') || UNENCRYPTED
  22252. });
  22253. }
  22254. },
  22255. shouldPlayNotification: function shouldPlayNotification($message) {
  22256. /* Don't play a notification if this is an OTR message but
  22257. * encryption is not yet set up. That would mean that the
  22258. * OTR session is still being established, so there are no
  22259. * "visible" OTR messages being exchanged.
  22260. */
  22261. return this.__super__.shouldPlayNotification.apply(this, arguments) && !(utils.isOTRMessage($message[0]) && !_.includes([UNVERIFIED, VERIFIED], this.get('otr_status')));
  22262. },
  22263. createMessage: function createMessage(message, delay, original_stanza) {
  22264. var _converse = this.__super__._converse,
  22265. text = _.propertyOf(message.querySelector('body'))('textContent');
  22266. if (!text || !_converse.allow_otr) {
  22267. return this.__super__.createMessage.apply(this, arguments);
  22268. }
  22269. if (utils.isNewMessage(original_stanza)) {
  22270. if (text.match(/^\?OTRv23?/)) {
  22271. return this.initiateOTR(text);
  22272. } else if (_.includes([UNVERIFIED, VERIFIED], this.get('otr_status'))) {
  22273. return this.otr.receiveMsg(text);
  22274. } else if (text.match(/^\?OTR/)) {
  22275. if (!this.otr) {
  22276. return this.initiateOTR(text);
  22277. } else {
  22278. return this.otr.receiveMsg(text);
  22279. }
  22280. }
  22281. } // Normal unencrypted message (or archived message)
  22282. return this.__super__.createMessage.apply(this, arguments);
  22283. },
  22284. generatePrivateKey: function generatePrivateKey(instance_tag) {
  22285. var _converse = this.__super__._converse;
  22286. var key = new otr.DSA();
  22287. var jid = _converse.connection.jid;
  22288. if (_converse.cache_otr_key) {
  22289. this.save({
  22290. 'otr_priv_key': key.packPrivate(),
  22291. 'otr_instance_tag': instance_tag
  22292. });
  22293. }
  22294. return key;
  22295. },
  22296. getSession: function getSession(callback) {
  22297. var _converse = this.__super__._converse,
  22298. __ = _converse.__;
  22299. var instance_tag, saved_key, encrypted_key;
  22300. if (_converse.cache_otr_key) {
  22301. encrypted_key = this.get('otr_priv_key');
  22302. if (_.isString(encrypted_key)) {
  22303. instance_tag = this.get('otr_instance_tag');
  22304. saved_key = otr.DSA.parsePrivate(encrypted_key);
  22305. if (saved_key && instance_tag) {
  22306. this.trigger('showHelpMessages', [__('Re-establishing encrypted session')]);
  22307. callback({
  22308. 'key': saved_key,
  22309. 'instance_tag': instance_tag
  22310. });
  22311. return; // Our work is done here
  22312. }
  22313. }
  22314. } // We need to generate a new key and instance tag
  22315. this.trigger('showHelpMessages', [__('Generating private key.'), __('Your browser might become unresponsive.')], null, true // show spinner
  22316. );
  22317. var that = this;
  22318. window.setTimeout(function () {
  22319. callback({
  22320. 'key': that.generatePrivateKey(instance_tag),
  22321. 'instance_tag': otr.OTR.makeInstanceTag()
  22322. });
  22323. }, 500);
  22324. },
  22325. updateOTRStatus: function updateOTRStatus(state) {
  22326. switch (state) {
  22327. case otr.OTR.CONST.STATUS_AKE_SUCCESS:
  22328. if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_ENCRYPTED) {
  22329. this.save({
  22330. 'otr_status': UNVERIFIED
  22331. });
  22332. }
  22333. break;
  22334. case otr.OTR.CONST.STATUS_END_OTR:
  22335. if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_FINISHED) {
  22336. this.save({
  22337. 'otr_status': FINISHED
  22338. });
  22339. } else if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_PLAINTEXT) {
  22340. this.save({
  22341. 'otr_status': UNENCRYPTED
  22342. });
  22343. }
  22344. break;
  22345. }
  22346. },
  22347. onSMP: function onSMP(type, data) {
  22348. // Event handler for SMP (Socialist's Millionaire Protocol)
  22349. // used by OTR (off-the-record).
  22350. var _converse = this.__super__._converse,
  22351. __ = _converse.__;
  22352. switch (type) {
  22353. case 'question':
  22354. this.otr.smpSecret(prompt(__('Authentication request from %1$s\n\nYour chat contact is attempting to verify your identity, by asking you the question below.\n\n%2$s', [this.get('fullname'), data])));
  22355. break;
  22356. case 'trust':
  22357. if (data === true) {
  22358. this.save({
  22359. 'otr_status': VERIFIED
  22360. });
  22361. } else {
  22362. this.trigger('showHelpMessages', [__("Could not verify this user's identify.")], 'error');
  22363. this.save({
  22364. 'otr_status': UNVERIFIED
  22365. });
  22366. }
  22367. break;
  22368. default:
  22369. throw new TypeError('ChatBox.onSMP: Unknown type for SMP');
  22370. }
  22371. },
  22372. initiateOTR: function initiateOTR(query_msg) {
  22373. var _this = this;
  22374. // Sets up an OTR object through which we can send and receive
  22375. // encrypted messages.
  22376. //
  22377. // If 'query_msg' is passed in, it means there is an alread incoming
  22378. // query message from our contact. Otherwise, it is us who will
  22379. // send the query message to them.
  22380. var _converse = this.__super__._converse,
  22381. __ = _converse.__;
  22382. this.save({
  22383. 'otr_status': UNENCRYPTED
  22384. });
  22385. this.getSession(function (session) {
  22386. var _converse = _this.__super__._converse;
  22387. _this.otr = new otr.OTR({
  22388. fragment_size: 140,
  22389. send_interval: 200,
  22390. priv: session.key,
  22391. instance_tag: session.instance_tag,
  22392. debug: _this.debug
  22393. });
  22394. _this.otr.on('status', _this.updateOTRStatus.bind(_this));
  22395. _this.otr.on('smp', _this.onSMP.bind(_this));
  22396. _this.otr.on('ui', function (msg) {
  22397. _this.trigger('showReceivedOTRMessage', msg);
  22398. });
  22399. _this.otr.on('io', function (msg) {
  22400. _this.trigger('sendMessage', new _converse.Message({
  22401. message: msg
  22402. }));
  22403. });
  22404. _this.otr.on('error', function (msg) {
  22405. _this.trigger('showOTRError', msg);
  22406. });
  22407. _this.trigger('showHelpMessages', [__('Exchanging private key with contact.')]);
  22408. if (query_msg) {
  22409. _this.otr.receiveMsg(query_msg);
  22410. } else {
  22411. _this.otr.sendQueryMsg();
  22412. }
  22413. });
  22414. },
  22415. endOTR: function endOTR() {
  22416. if (this.otr) {
  22417. this.otr.endOtr();
  22418. }
  22419. this.save({
  22420. 'otr_status': UNENCRYPTED
  22421. });
  22422. }
  22423. },
  22424. ChatBoxView: {
  22425. events: {
  22426. 'click .toggle-otr': 'toggleOTRMenu',
  22427. 'click .start-otr': 'startOTRFromToolbar',
  22428. 'click .end-otr': 'endOTR',
  22429. 'click .auth-otr': 'authOTR'
  22430. },
  22431. initialize: function initialize() {
  22432. var _converse = this.__super__._converse;
  22433. this.__super__.initialize.apply(this, arguments);
  22434. this.model.on('change:otr_status', this.onOTRStatusChanged, this);
  22435. this.model.on('showOTRError', this.showOTRError, this);
  22436. this.model.on('showSentOTRMessage', function (text) {
  22437. this.showMessage({
  22438. 'message': text,
  22439. 'sender': 'me'
  22440. });
  22441. }, this);
  22442. this.model.on('showReceivedOTRMessage', function (text) {
  22443. this.showMessage({
  22444. 'message': text,
  22445. 'sender': 'them'
  22446. });
  22447. }, this);
  22448. if (_.includes([UNVERIFIED, VERIFIED], this.model.get('otr_status')) || _converse.use_otr_by_default) {
  22449. this.model.initiateOTR();
  22450. }
  22451. },
  22452. createMessageStanza: function createMessageStanza() {
  22453. var stanza = this.__super__.createMessageStanza.apply(this, arguments);
  22454. if (this.model.get('otr_status') !== UNENCRYPTED || utils.isOTRMessage(stanza.nodeTree)) {
  22455. // OTR messages aren't carbon copied
  22456. stanza.c('private', {
  22457. 'xmlns': Strophe.NS.CARBONS
  22458. }).up().c('no-store', {
  22459. 'xmlns': Strophe.NS.HINTS
  22460. }).up().c('no-permanent-store', {
  22461. 'xmlns': Strophe.NS.HINTS
  22462. }).up().c('no-copy', {
  22463. 'xmlns': Strophe.NS.HINTS
  22464. });
  22465. }
  22466. return stanza;
  22467. },
  22468. parseMessageForCommands: function parseMessageForCommands(text) {
  22469. var _converse = this.__super__._converse;
  22470. var match = text.replace(/^\s*/, "").match(/^\/(.*)\s*$/);
  22471. if (match) {
  22472. if (_converse.allow_otr && match[1] === "endotr") {
  22473. this.endOTR();
  22474. return true;
  22475. } else if (_converse.allow_otr && match[1] === "otr") {
  22476. this.model.initiateOTR();
  22477. return true;
  22478. }
  22479. }
  22480. return this.__super__.parseMessageForCommands.apply(this, arguments);
  22481. },
  22482. isOTREncryptedSession: function isOTREncryptedSession() {
  22483. return _.includes([UNVERIFIED, VERIFIED], this.model.get('otr_status'));
  22484. },
  22485. onMessageSubmitted: function onMessageSubmitted(text, spoiler_hint) {
  22486. var _converse = this.__super__._converse;
  22487. if (!_converse.connection.authenticated) {
  22488. this.__super__.onMessageSubmitted.apply(this, arguments);
  22489. }
  22490. if (this.parseMessageForCommands(text)) {
  22491. return;
  22492. }
  22493. if (this.isOTREncryptedSession()) {
  22494. this.model.otr.sendMsg(text);
  22495. this.model.trigger('showSentOTRMessage', text);
  22496. } else {
  22497. this.__super__.onMessageSubmitted.apply(this, arguments);
  22498. }
  22499. },
  22500. onOTRStatusChanged: function onOTRStatusChanged() {
  22501. this.renderToolbar().informOTRChange();
  22502. },
  22503. informOTRChange: function informOTRChange() {
  22504. var _converse = this.__super__._converse,
  22505. __ = _converse.__,
  22506. data = this.model.toJSON(),
  22507. msgs = [];
  22508. if (data.otr_status === UNENCRYPTED) {
  22509. msgs.push(__("Your messages are not encrypted anymore"));
  22510. } else if (data.otr_status === UNVERIFIED) {
  22511. msgs.push(__("Your messages are now encrypted but your contact's identity has not been verified."));
  22512. } else if (data.otr_status === VERIFIED) {
  22513. msgs.push(__("Your contact's identify has been verified."));
  22514. } else if (data.otr_status === FINISHED) {
  22515. msgs.push(__("Your contact has ended encryption on their end, you should do the same."));
  22516. }
  22517. return this.showHelpMessages(msgs, 'info', false);
  22518. },
  22519. showOTRError: function showOTRError(msg) {
  22520. var _converse = this.__super__._converse,
  22521. __ = _converse.__;
  22522. if (msg === 'Message cannot be sent at this time.') {
  22523. this.showHelpMessages([__('Your message could not be sent')], 'error');
  22524. } else if (msg === 'Received an unencrypted message.') {
  22525. this.showHelpMessages([__('We received an unencrypted message')], 'error');
  22526. } else if (msg === 'Received an unreadable encrypted message.') {
  22527. this.showHelpMessages([__('We received an unreadable encrypted message')], 'error');
  22528. } else {
  22529. this.showHelpMessages(["Encryption error occured: ".concat(msg)], 'error');
  22530. }
  22531. _converse.log("OTR ERROR:".concat(msg), Strophe.LogLevel.ERROR);
  22532. },
  22533. startOTRFromToolbar: function startOTRFromToolbar(ev) {
  22534. ev.stopPropagation();
  22535. this.model.initiateOTR();
  22536. },
  22537. endOTR: function endOTR(ev) {
  22538. if (!_.isUndefined(ev)) {
  22539. ev.preventDefault();
  22540. ev.stopPropagation();
  22541. }
  22542. this.model.endOTR();
  22543. },
  22544. authOTR: function authOTR(ev) {
  22545. var _converse = this.__super__._converse,
  22546. __ = _converse.__,
  22547. scheme = ev.target.getAttribute('data-scheme');
  22548. var result, question, answer;
  22549. if (scheme === 'fingerprint') {
  22550. result = confirm(__('Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\nFingerprint for you, %2$s: %3$s\n\nFingerprint for %1$s: %4$s\n\nIf you have confirmed that the fingerprints match, click OK, otherwise click Cancel.', [this.model.get('fullname'), _converse.xmppstatus.get('fullname') || _converse.bare_jid, this.model.otr.priv.fingerprint(), this.model.otr.their_priv_pk.fingerprint()]));
  22551. if (result === true) {
  22552. this.model.save({
  22553. 'otr_status': VERIFIED
  22554. });
  22555. } else {
  22556. this.model.save({
  22557. 'otr_status': UNVERIFIED
  22558. });
  22559. }
  22560. } else if (scheme === 'smp') {
  22561. alert(__('You will be prompted to provide a security question and then an answer to that question.\n\nYour contact will then be prompted the same question and if they type the exact same answer (case sensitive), their identity will be verified.'));
  22562. question = prompt(__('What is your security question?'));
  22563. if (question) {
  22564. answer = prompt(__('What is the answer to the security question?'));
  22565. this.model.otr.smpSecret(answer, question);
  22566. }
  22567. } else {
  22568. this.showHelpMessages([__('Invalid authentication scheme provided')], 'error');
  22569. }
  22570. },
  22571. toggleOTRMenu: function toggleOTRMenu(ev) {
  22572. if (_.isUndefined(this.otr_dropdown)) {
  22573. ev.stopPropagation();
  22574. var dropdown_el = this.el.querySelector('.toggle-otr');
  22575. this.otr_dropdown = new bootstrap.Dropdown(dropdown_el, true);
  22576. this.otr_dropdown.toggle();
  22577. }
  22578. },
  22579. getOTRTooltip: function getOTRTooltip() {
  22580. var _converse = this.__super__._converse,
  22581. __ = _converse.__,
  22582. data = this.model.toJSON();
  22583. if (data.otr_status === UNENCRYPTED) {
  22584. return __('Your messages are not encrypted. Click here to enable OTR encryption.');
  22585. } else if (data.otr_status === UNVERIFIED) {
  22586. return __('Your messages are encrypted, but your contact has not been verified.');
  22587. } else if (data.otr_status === VERIFIED) {
  22588. return __('Your messages are encrypted and your contact verified.');
  22589. } else if (data.otr_status === FINISHED) {
  22590. return __('Your contact has closed their end of the private session, you should do the same');
  22591. }
  22592. },
  22593. addOTRToolbarButton: function addOTRToolbarButton(options) {
  22594. var _converse = this.__super__._converse,
  22595. __ = _converse.__,
  22596. data = this.model.toJSON();
  22597. options = _.extend(options || {}, {
  22598. FINISHED: FINISHED,
  22599. UNENCRYPTED: UNENCRYPTED,
  22600. UNVERIFIED: UNVERIFIED,
  22601. VERIFIED: VERIFIED,
  22602. // FIXME: Leaky abstraction MUC
  22603. allow_otr: _converse.allow_otr && !this.is_chatroom,
  22604. label_end_encrypted_conversation: __('End encrypted conversation'),
  22605. label_refresh_encrypted_conversation: __('Refresh encrypted conversation'),
  22606. label_start_encrypted_conversation: __('Start encrypted conversation'),
  22607. label_verify_with_fingerprints: __('Verify with fingerprints'),
  22608. label_verify_with_smp: __('Verify with SMP'),
  22609. label_whats_this: __("What\'s this?"),
  22610. otr_status_class: OTR_CLASS_MAPPING[data.otr_status],
  22611. otr_tooltip: this.getOTRTooltip(),
  22612. otr_translated_status: OTR_TRANSLATED_MAPPING[data.otr_status]
  22613. });
  22614. this.el.querySelector('.chat-toolbar').insertAdjacentHTML('beforeend', tpl_toolbar_otr(_.extend(data, options || {})));
  22615. },
  22616. getToolbarOptions: function getToolbarOptions(options) {
  22617. options = this.__super__.getToolbarOptions();
  22618. if (this.isOTREncryptedSession()) {
  22619. options.show_spoiler_button = false;
  22620. }
  22621. return options;
  22622. },
  22623. renderToolbar: function renderToolbar(toolbar, options) {
  22624. var result = this.__super__.renderToolbar.apply(this, arguments);
  22625. this.addOTRToolbarButton(options);
  22626. return result;
  22627. }
  22628. }
  22629. },
  22630. initialize: function initialize() {
  22631. /* The initialize function gets called as soon as the plugin is
  22632. * loaded by converse.js's plugin machinery.
  22633. */
  22634. var _converse = this._converse,
  22635. __ = _converse.__;
  22636. _converse.api.settings.update({
  22637. allow_otr: true,
  22638. cache_otr_key: false,
  22639. use_otr_by_default: false
  22640. }); // Translation aware constants
  22641. // ---------------------------
  22642. // We can only call the __ translation method *after* converse.js
  22643. // has been initialized and with it the i18n machinery. That's why
  22644. // we do it here in the "initialize" method and not at the top of
  22645. // the module.
  22646. OTR_TRANSLATED_MAPPING[UNENCRYPTED] = __('unencrypted');
  22647. OTR_TRANSLATED_MAPPING[UNVERIFIED] = __('unverified');
  22648. OTR_TRANSLATED_MAPPING[VERIFIED] = __('verified');
  22649. OTR_TRANSLATED_MAPPING[FINISHED] = __('finished'); // Only allow OTR if we have the capability
  22650. _converse.allow_otr = _converse.allow_otr && HAS_CRYPTO; // Only use OTR by default if allow OTR is enabled to begin with
  22651. _converse.use_otr_by_default = _converse.use_otr_by_default && _converse.allow_otr;
  22652. }
  22653. });
  22654. });
  22655. //# sourceMappingURL=converse-otr.js.map;
  22656. define('tpl!register_link', ['lodash'], function(_) {return function(o) {
  22657. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  22658. function print() { __p += __j.call(arguments, '') }
  22659. __p += '<div class="switch-form">\n ';
  22660. if (!o._converse.auto_login && o._converse.CONNECTION_STATUS[o.connection_status] !== 'CONNECTING') { ;
  22661. __p += '\n <p>' +
  22662. __e( o.__("Don't have a chat account?") ) +
  22663. '</p>\n <p><a class="register-account toggle-register-login" href="#converse/register">' +
  22664. __e(o.__("Create an account")) +
  22665. '</a></p>\n ';
  22666. } ;
  22667. __p += '\n</div>\n';
  22668. return __p
  22669. };});
  22670. define('tpl!register_panel', ['lodash'], function(_) {return function(o) {
  22671. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  22672. function print() { __p += __j.call(arguments, '') }
  22673. __p += '<div class="row">\n <form id="converse-register" class="converse-form">\n <legend>' +
  22674. __e(o.__("Create your account")) +
  22675. '</legend>\n\n <div class="form-group">\n <label>' +
  22676. __e(o.__("Please enter the XMPP provider to register with:")) +
  22677. '</label>\n <div class="form-errors hidden"></div>\n\n ';
  22678. if (o.default_domain) { ;
  22679. __p += '\n ' +
  22680. __e(o.default_domain) +
  22681. '\n </div>\n ';
  22682. } ;
  22683. __p += '\n ';
  22684. if (!o.default_domain) { ;
  22685. __p += '\n <input class="form-control" autofocus="autofocus" required="required" type="text" name="domain" placeholder="' +
  22686. __e(o.domain_placeholder) +
  22687. '">\n <p class="form-text text-muted">' +
  22688. __e(o.help_providers) +
  22689. ' <a href="' +
  22690. __e(o.href_providers) +
  22691. '" class="url" target="_blank" rel="noopener">' +
  22692. __e(o.help_providers_link) +
  22693. '</a>.</p>\n </div>\n <fieldset class="buttons">\n <input class="btn btn-primary" type="submit" value="' +
  22694. __e(o.label_register) +
  22695. '">\n <div class="switch-form">\n <p>' +
  22696. __e( o.__("Already have a chat account?") ) +
  22697. '</p>\n <p><a class="login-here toggle-register-login" href="#converse/login">' +
  22698. __e(o.__("Log in here")) +
  22699. '</a></p>\n </div>\n </fieldset>\n ';
  22700. } ;
  22701. __p += '\n </div>\n </form>\n</div>\n';
  22702. return __p
  22703. };});
  22704. define('tpl!registration_form', ['lodash'], function(_) {return function(o) {
  22705. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  22706. function print() { __p += __j.call(arguments, '') }
  22707. __p += '<legend>' +
  22708. __e(o.__("Account Registration:")) +
  22709. ' ' +
  22710. __e(o.domain) +
  22711. '</legend>\n<p class="title">' +
  22712. __e(o.title) +
  22713. '</p>\n<p class="instructions">' +
  22714. __e(o.instructions) +
  22715. '</p>\n<div class="form-errors hidden"></div>\n\n<fieldset class="buttons">\n <input type="submit" class="btn btn-primary" value="' +
  22716. __e(o.__('Register')) +
  22717. '"/>\n ';
  22718. if (!o.registration_domain) { ;
  22719. __p += '\n <input type="button" class="btn btn-secondary button-cancel" value="' +
  22720. __e(o.__('Choose a different provider')) +
  22721. '"/>\n ';
  22722. } ;
  22723. __p += '\n</fieldset>\n';
  22724. return __p
  22725. };});
  22726. define('tpl!registration_request', ['lodash'], function(_) {return function(o) {
  22727. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  22728. function print() { __p += __j.call(arguments, '') }
  22729. __p += '<span class="spinner login-submit fa fa-spinner"></span>\n<p class="info">' +
  22730. __e(o.__("Hold tight, we're fetching the registration form…")) +
  22731. '</p>\n';
  22732. if (o.cancel) { ;
  22733. __p += '\n <button class="btn btn-secondary button-cancel hor_centered">' +
  22734. __e(o.__('Cancel')) +
  22735. '</button>\n';
  22736. } ;
  22737. __p += '\n';
  22738. return __p
  22739. };});
  22740. // Converse.js (A browser based XMPP chat client)
  22741. // http://conversejs.org
  22742. //
  22743. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  22744. // Licensed under the Mozilla Public License (MPLv2)
  22745. //
  22746. /*global define */
  22747. /* This is a Converse.js plugin which add support for in-band registration
  22748. * as specified in XEP-0077.
  22749. */
  22750. (function (root, factory) {
  22751. define('converse-register',["form-utils", "converse-core", "tpl!form_username", "tpl!register_link", "tpl!register_panel", "tpl!registration_form", "tpl!registration_request", "tpl!form_input", "tpl!spinner", "converse-controlbox"], factory);
  22752. })(void 0, function (utils, converse, tpl_form_username, tpl_register_link, tpl_register_panel, tpl_registration_form, tpl_registration_request, tpl_form_input, tpl_spinner) {
  22753. "use strict"; // Strophe methods for building stanzas
  22754. var _converse$env = converse.env,
  22755. Strophe = _converse$env.Strophe,
  22756. Backbone = _converse$env.Backbone,
  22757. sizzle = _converse$env.sizzle,
  22758. $iq = _converse$env.$iq,
  22759. _ = _converse$env._; // Add Strophe Namespaces
  22760. Strophe.addNamespace('REGISTER', 'jabber:iq:register'); // Add Strophe Statuses
  22761. var i = 0;
  22762. _.each(_.keys(Strophe.Status), function (key) {
  22763. i = Math.max(i, Strophe.Status[key]);
  22764. });
  22765. Strophe.Status.REGIFAIL = i + 1;
  22766. Strophe.Status.REGISTERED = i + 2;
  22767. Strophe.Status.CONFLICT = i + 3;
  22768. Strophe.Status.NOTACCEPTABLE = i + 5;
  22769. converse.plugins.add('converse-register', {
  22770. 'overrides': {
  22771. // Overrides mentioned here will be picked up by converse.js's
  22772. // plugin architecture they will replace existing methods on the
  22773. // relevant objects or classes.
  22774. //
  22775. // New functions which don't exist yet can also be added.
  22776. LoginPanel: {
  22777. render: function render(cfg) {
  22778. var _converse = this.__super__._converse;
  22779. this.__super__.render.apply(this, arguments);
  22780. if (_converse.allow_registration) {
  22781. if (_.isUndefined(this.registerlinkview)) {
  22782. this.registerlinkview = new _converse.RegisterLinkView({
  22783. 'model': this.model
  22784. });
  22785. this.registerlinkview.render();
  22786. this.el.querySelector('.buttons').insertAdjacentElement('beforeend', this.registerlinkview.el);
  22787. }
  22788. this.registerlinkview.render();
  22789. }
  22790. return this;
  22791. }
  22792. },
  22793. ControlBoxView: {
  22794. initialize: function initialize() {
  22795. this.__super__.initialize.apply(this, arguments);
  22796. this.model.on('change:active-form', this.showLoginOrRegisterForm.bind(this));
  22797. },
  22798. showLoginOrRegisterForm: function showLoginOrRegisterForm() {
  22799. var _converse = this.__super__._converse;
  22800. if (_.isNil(this.registerpanel)) {
  22801. return;
  22802. }
  22803. if (this.model.get('active-form') == "register") {
  22804. this.loginpanel.el.classList.add('hidden');
  22805. this.registerpanel.el.classList.remove('hidden');
  22806. } else {
  22807. this.loginpanel.el.classList.remove('hidden');
  22808. this.registerpanel.el.classList.add('hidden');
  22809. }
  22810. },
  22811. renderRegistrationPanel: function renderRegistrationPanel() {
  22812. var _converse = this.__super__._converse;
  22813. if (_converse.allow_registration) {
  22814. this.registerpanel = new _converse.RegisterPanel({
  22815. 'model': this.model
  22816. });
  22817. this.registerpanel.render();
  22818. this.registerpanel.el.classList.add('hidden');
  22819. this.el.querySelector('#converse-login-panel').insertAdjacentElement('afterend', this.registerpanel.el);
  22820. this.showLoginOrRegisterForm();
  22821. }
  22822. return this;
  22823. },
  22824. renderLoginPanel: function renderLoginPanel() {
  22825. /* Also render a registration panel, when rendering the
  22826. * login panel.
  22827. */
  22828. this.__super__.renderLoginPanel.apply(this, arguments);
  22829. this.renderRegistrationPanel();
  22830. return this;
  22831. }
  22832. }
  22833. },
  22834. initialize: function initialize() {
  22835. /* The initialize function gets called as soon as the plugin is
  22836. * loaded by converse.js's plugin machinery.
  22837. */
  22838. var _converse = this._converse,
  22839. __ = _converse.__;
  22840. _converse.CONNECTION_STATUS[Strophe.Status.REGIFAIL] = 'REGIFAIL';
  22841. _converse.CONNECTION_STATUS[Strophe.Status.REGISTERED] = 'REGISTERED';
  22842. _converse.CONNECTION_STATUS[Strophe.Status.CONFLICT] = 'CONFLICT';
  22843. _converse.CONNECTION_STATUS[Strophe.Status.NOTACCEPTABLE] = 'NOTACCEPTABLE';
  22844. _converse.api.settings.update({
  22845. allow_registration: true,
  22846. domain_placeholder: __(" e.g. conversejs.org"),
  22847. // Placeholder text shown in the domain input on the registration form
  22848. providers_link: 'https://xmpp.net/directory.php' // Link to XMPP providers shown on registration page
  22849. });
  22850. function setActiveForm(value) {
  22851. _converse.api.waitUntil('controlboxInitialized').then(function () {
  22852. var controlbox = _converse.chatboxes.get('controlbox');
  22853. controlbox.set({
  22854. 'active-form': value
  22855. });
  22856. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  22857. }
  22858. _converse.router.route('converse/login', _.partial(setActiveForm, 'login'));
  22859. _converse.router.route('converse/register', _.partial(setActiveForm, 'register'));
  22860. _converse.RegisterLinkView = Backbone.VDOMView.extend({
  22861. toHTML: function toHTML() {
  22862. return tpl_register_link(_.extend(this.model.toJSON(), {
  22863. '__': _converse.__,
  22864. '_converse': _converse,
  22865. 'connection_status': _converse.connfeedback.get('connection_status')
  22866. }));
  22867. }
  22868. });
  22869. _converse.RegisterPanel = Backbone.NativeView.extend({
  22870. tagName: 'div',
  22871. id: "converse-register-panel",
  22872. className: 'controlbox-pane fade-in',
  22873. events: {
  22874. 'submit form#converse-register': 'onFormSubmission',
  22875. 'click .button-cancel': 'renderProviderChoiceForm'
  22876. },
  22877. initialize: function initialize(cfg) {
  22878. this.reset();
  22879. this.registerHooks();
  22880. },
  22881. render: function render() {
  22882. this.model.set('registration_form_rendered', false);
  22883. this.el.innerHTML = tpl_register_panel({
  22884. '__': __,
  22885. 'default_domain': _converse.registration_domain,
  22886. 'label_register': __('Fetch registration form'),
  22887. 'help_providers': __('Tip: A list of public XMPP providers is available'),
  22888. 'help_providers_link': __('here'),
  22889. 'href_providers': _converse.providers_link,
  22890. 'domain_placeholder': _converse.domain_placeholder
  22891. });
  22892. if (_converse.registration_domain) {
  22893. this.fetchRegistrationForm(_converse.registration_domain);
  22894. }
  22895. return this;
  22896. },
  22897. registerHooks: function registerHooks() {
  22898. var _this = this;
  22899. /* Hook into Strophe's _connect_cb, so that we can send an IQ
  22900. * requesting the registration fields.
  22901. */
  22902. var conn = _converse.connection;
  22903. var connect_cb = conn._connect_cb.bind(conn);
  22904. conn._connect_cb = function (req, callback, raw) {
  22905. if (!_this._registering) {
  22906. connect_cb(req, callback, raw);
  22907. } else {
  22908. if (_this.getRegistrationFields(req, callback, raw)) {
  22909. _this._registering = false;
  22910. }
  22911. }
  22912. };
  22913. },
  22914. getRegistrationFields: function getRegistrationFields(req, _callback, raw) {
  22915. /* Send an IQ stanza to the XMPP server asking for the
  22916. * registration fields.
  22917. * Parameters:
  22918. * (Strophe.Request) req - The current request
  22919. * (Function) callback
  22920. */
  22921. var conn = _converse.connection;
  22922. conn.connected = true;
  22923. var body = conn._proto._reqToData(req);
  22924. if (!body) {
  22925. return;
  22926. }
  22927. if (conn._proto._connect_cb(body) === Strophe.Status.CONNFAIL) {
  22928. this.showValidationError(__("Sorry, we're unable to connect to your chosen provider."));
  22929. return false;
  22930. }
  22931. var register = body.getElementsByTagName("register");
  22932. var mechanisms = body.getElementsByTagName("mechanism");
  22933. if (register.length === 0 && mechanisms.length === 0) {
  22934. conn._proto._no_auth_received(_callback);
  22935. return false;
  22936. }
  22937. if (register.length === 0) {
  22938. conn._changeConnectStatus(Strophe.Status.REGIFAIL);
  22939. this.showValidationError(__("Sorry, the given provider does not support in " + "band account registration. Please try with a " + "different provider."));
  22940. return true;
  22941. } // Send an IQ stanza to get all required data fields
  22942. conn._addSysHandler(this.onRegistrationFields.bind(this), null, "iq", null, null);
  22943. var stanza = $iq({
  22944. type: "get"
  22945. }).c("query", {
  22946. xmlns: Strophe.NS.REGISTER
  22947. }).tree();
  22948. stanza.setAttribute("id", conn.getUniqueId("sendIQ"));
  22949. conn.send(stanza);
  22950. conn.connected = false;
  22951. return true;
  22952. },
  22953. onRegistrationFields: function onRegistrationFields(stanza) {
  22954. /* Handler for Registration Fields Request.
  22955. *
  22956. * Parameters:
  22957. * (XMLElement) elem - The query stanza.
  22958. */
  22959. if (stanza.getAttribute("type") === "error") {
  22960. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, __('Something went wrong while establishing a connection with "%1$s". ' + 'Are you sure it exists?', this.domain));
  22961. return false;
  22962. }
  22963. if (stanza.getElementsByTagName("query").length !== 1) {
  22964. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
  22965. return false;
  22966. }
  22967. this.setFields(stanza);
  22968. if (!this.model.get('registration_form_rendered')) {
  22969. this.renderRegistrationForm(stanza);
  22970. }
  22971. return false;
  22972. },
  22973. reset: function reset(settings) {
  22974. var defaults = {
  22975. fields: {},
  22976. urls: [],
  22977. title: "",
  22978. instructions: "",
  22979. registered: false,
  22980. _registering: false,
  22981. domain: null,
  22982. form_type: null
  22983. };
  22984. _.extend(this, defaults);
  22985. if (settings) {
  22986. _.extend(this, _.pick(settings, _.keys(defaults)));
  22987. }
  22988. },
  22989. onFormSubmission: function onFormSubmission(ev) {
  22990. /* Event handler when the #converse-register form is
  22991. * submitted.
  22992. *
  22993. * Depending on the available input fields, we delegate to
  22994. * other methods.
  22995. */
  22996. if (ev && ev.preventDefault) {
  22997. ev.preventDefault();
  22998. }
  22999. if (_.isNull(ev.target.querySelector('input[name=domain]'))) {
  23000. this.submitRegistrationForm(ev.target);
  23001. } else {
  23002. this.onProviderChosen(ev.target);
  23003. }
  23004. },
  23005. onProviderChosen: function onProviderChosen(form) {
  23006. /* Callback method that gets called when the user has chosen an
  23007. * XMPP provider.
  23008. *
  23009. * Parameters:
  23010. * (HTMLElement) form - The form that was submitted
  23011. */
  23012. var domain_input = form.querySelector('input[name=domain]'),
  23013. domain = _.get(domain_input, 'value');
  23014. if (!domain) {
  23015. // TODO: add validation message
  23016. domain_input.classList.add('error');
  23017. return;
  23018. }
  23019. form.querySelector('input[type=submit]').classList.add('hidden');
  23020. this.fetchRegistrationForm(domain.trim());
  23021. },
  23022. fetchRegistrationForm: function fetchRegistrationForm(domain_name) {
  23023. /* This is called with a domain name based on which, it fetches a
  23024. * registration form from the requested domain.
  23025. *
  23026. * Parameters:
  23027. * (String) domain_name - XMPP server domain
  23028. */
  23029. if (!this.model.get('registration_form_rendered')) {
  23030. this.renderRegistrationRequest();
  23031. }
  23032. this.reset({
  23033. domain: Strophe.getDomainFromJid(domain_name),
  23034. _registering: true
  23035. });
  23036. _converse.connection.connect(this.domain, "", this.onConnectStatusChanged.bind(this));
  23037. return false;
  23038. },
  23039. renderRegistrationRequest: function renderRegistrationRequest() {
  23040. /* Clear the form and inform the user that the registration
  23041. * form is being fetched.
  23042. */
  23043. this.clearRegistrationForm().insertAdjacentHTML('beforeend', tpl_registration_request({
  23044. '__': _converse.__,
  23045. 'cancel': _converse.registration_domain
  23046. }));
  23047. },
  23048. giveFeedback: function giveFeedback(message, klass) {
  23049. var feedback = this.el.querySelector('.reg-feedback');
  23050. if (!_.isNull(feedback)) {
  23051. feedback.parentNode.removeChild(feedback);
  23052. }
  23053. var form = this.el.querySelector('form');
  23054. form.insertAdjacentHTML('afterbegin', '<span class="reg-feedback"></span>');
  23055. feedback = form.querySelector('.reg-feedback');
  23056. feedback.textContent = message;
  23057. if (klass) {
  23058. feedback.classList.add(klass);
  23059. }
  23060. },
  23061. clearRegistrationForm: function clearRegistrationForm() {
  23062. var form = this.el.querySelector('form');
  23063. form.innerHTML = '';
  23064. this.model.set('registration_form_rendered', false);
  23065. return form;
  23066. },
  23067. showSpinner: function showSpinner() {
  23068. var form = this.el.querySelector('form');
  23069. form.innerHTML = tpl_spinner();
  23070. this.model.set('registration_form_rendered', false);
  23071. return this;
  23072. },
  23073. onConnectStatusChanged: function onConnectStatusChanged(status_code) {
  23074. /* Callback function called by Strophe whenever the
  23075. * connection status changes.
  23076. *
  23077. * Passed to Strophe specifically during a registration
  23078. * attempt.
  23079. *
  23080. * Parameters:
  23081. * (Integer) status_code - The Stroph.Status status code
  23082. */
  23083. _converse.log('converse-register: onConnectStatusChanged');
  23084. if (_.includes([Strophe.Status.DISCONNECTED, Strophe.Status.CONNFAIL, Strophe.Status.REGIFAIL, Strophe.Status.NOTACCEPTABLE, Strophe.Status.CONFLICT], status_code)) {
  23085. _converse.log("Problem during registration: Strophe.Status is ".concat(_converse.CONNECTION_STATUS[status_code]), Strophe.LogLevel.ERROR);
  23086. this.abortRegistration();
  23087. } else if (status_code === Strophe.Status.REGISTERED) {
  23088. _converse.log("Registered successfully.");
  23089. _converse.connection.reset();
  23090. this.showSpinner();
  23091. if (_.includes(["converse/login", "converse/register"], Backbone.history.getFragment())) {
  23092. _converse.router.navigate('', {
  23093. 'replace': true
  23094. });
  23095. }
  23096. if (this.fields.password && this.fields.username) {
  23097. // automatically log the user in
  23098. _converse.connection.connect(this.fields.username.toLowerCase() + '@' + this.domain.toLowerCase(), this.fields.password, _converse.onConnectStatusChanged);
  23099. this.giveFeedback(__('Now logging you in'), 'info');
  23100. } else {
  23101. _converse.chatboxviews.get('controlbox').renderLoginPanel();
  23102. _converse.giveFeedback(__('Registered successfully'));
  23103. }
  23104. this.reset();
  23105. }
  23106. },
  23107. renderLegacyRegistrationForm: function renderLegacyRegistrationForm(form) {
  23108. var _this2 = this;
  23109. _.each(_.keys(this.fields), function (key) {
  23110. if (key === "username") {
  23111. form.insertAdjacentHTML('beforeend', tpl_form_username({
  23112. 'domain': " @".concat(_this2.domain),
  23113. 'name': key,
  23114. 'type': "text",
  23115. 'label': key,
  23116. 'value': '',
  23117. 'required': true
  23118. }));
  23119. } else {
  23120. form.insertAdjacentHTML('beforeend', tpl_form_input({
  23121. 'label': key,
  23122. 'name': key,
  23123. 'placeholder': key,
  23124. 'required': true,
  23125. 'type': key === 'password' || key === 'email' ? key : "text",
  23126. 'value': ''
  23127. }));
  23128. }
  23129. }); // Show urls
  23130. _.each(this.urls, function (url) {
  23131. form.insertAdjacentHTML('afterend', '<a target="blank" rel="noopener" href="' + url + '">' + url + '</a>');
  23132. });
  23133. },
  23134. renderRegistrationForm: function renderRegistrationForm(stanza) {
  23135. var _this3 = this;
  23136. /* Renders the registration form based on the XForm fields
  23137. * received from the XMPP server.
  23138. *
  23139. * Parameters:
  23140. * (XMLElement) stanza - The IQ stanza received from the XMPP server.
  23141. */
  23142. var form = this.el.querySelector('form');
  23143. form.innerHTML = tpl_registration_form({
  23144. '__': _converse.__,
  23145. 'domain': this.domain,
  23146. 'title': this.title,
  23147. 'instructions': this.instructions,
  23148. 'registration_domain': _converse.registration_domain
  23149. });
  23150. var buttons = form.querySelector('fieldset.buttons');
  23151. if (this.form_type === 'xform') {
  23152. _.each(stanza.querySelectorAll('field'), function (field) {
  23153. buttons.insertAdjacentHTML('beforebegin', utils.xForm2webForm(field, stanza, _this3.domain));
  23154. });
  23155. } else {
  23156. this.renderLegacyRegistrationForm(form);
  23157. }
  23158. if (!this.fields) {
  23159. form.querySelector('.button-primary').classList.add('hidden');
  23160. }
  23161. form.classList.remove('hidden');
  23162. this.model.set('registration_form_rendered', true);
  23163. },
  23164. showValidationError: function showValidationError(message) {
  23165. var form = this.el.querySelector('form');
  23166. var flash = form.querySelector('.form-errors');
  23167. if (_.isNull(flash)) {
  23168. flash = '<div class="form-errors hidden"></div>';
  23169. var instructions = form.querySelector('p.instructions');
  23170. if (_.isNull(instructions)) {
  23171. form.insertAdjacentHTML('afterbegin', flash);
  23172. } else {
  23173. instructions.insertAdjacentHTML('afterend', flash);
  23174. }
  23175. flash = form.querySelector('.form-errors');
  23176. } else {
  23177. flash.innerHTML = '';
  23178. }
  23179. flash.insertAdjacentHTML('beforeend', '<p class="form-help error">' + message + '</p>');
  23180. flash.classList.remove('hidden');
  23181. },
  23182. reportErrors: function reportErrors(stanza) {
  23183. var _this4 = this;
  23184. /* Report back to the user any error messages received from the
  23185. * XMPP server after attempted registration.
  23186. *
  23187. * Parameters:
  23188. * (XMLElement) stanza - The IQ stanza received from the
  23189. * XMPP server.
  23190. */
  23191. var errors = stanza.querySelectorAll('error');
  23192. _.each(errors, function (error) {
  23193. _this4.showValidationError(error.textContent);
  23194. });
  23195. if (!errors.length) {
  23196. var message = __('The provider rejected your registration attempt. ' + 'Please check the values you entered for correctness.');
  23197. this.showValidationError(message);
  23198. }
  23199. },
  23200. renderProviderChoiceForm: function renderProviderChoiceForm(ev) {
  23201. if (ev && ev.preventDefault) {
  23202. ev.preventDefault();
  23203. }
  23204. _converse.connection._proto._abortAllRequests();
  23205. _converse.connection.reset();
  23206. this.render();
  23207. },
  23208. abortRegistration: function abortRegistration() {
  23209. _converse.connection._proto._abortAllRequests();
  23210. _converse.connection.reset();
  23211. if (this.model.get('registration_form_rendered')) {
  23212. if (_converse.registration_domain && this.model.get('registration_form_rendered')) {
  23213. this.fetchRegistrationForm(_converse.registration_domain);
  23214. }
  23215. } else {
  23216. this.render();
  23217. }
  23218. },
  23219. submitRegistrationForm: function submitRegistrationForm(form) {
  23220. /* Handler, when the user submits the registration form.
  23221. * Provides form error feedback or starts the registration
  23222. * process.
  23223. *
  23224. * Parameters:
  23225. * (HTMLElement) form - The HTML form that was submitted
  23226. */
  23227. var has_empty_inputs = _.reduce(this.el.querySelectorAll('input.required'), function (result, input) {
  23228. if (input.value === '') {
  23229. input.classList.add('error');
  23230. return result + 1;
  23231. }
  23232. return result;
  23233. }, 0);
  23234. if (has_empty_inputs) {
  23235. return;
  23236. }
  23237. var inputs = sizzle(':input:not([type=button]):not([type=submit])', form),
  23238. iq = $iq({
  23239. 'type': 'set',
  23240. 'id': _converse.connection.getUniqueId()
  23241. }).c("query", {
  23242. xmlns: Strophe.NS.REGISTER
  23243. });
  23244. if (this.form_type === 'xform') {
  23245. iq.c("x", {
  23246. xmlns: Strophe.NS.XFORM,
  23247. type: 'submit'
  23248. });
  23249. _.each(inputs, function (input) {
  23250. iq.cnode(utils.webForm2xForm(input)).up();
  23251. });
  23252. } else {
  23253. _.each(inputs, function (input) {
  23254. iq.c(input.getAttribute('name'), {}, input.value);
  23255. });
  23256. }
  23257. _converse.connection._addSysHandler(this._onRegisterIQ.bind(this), null, "iq", null, null);
  23258. _converse.connection.send(iq);
  23259. this.setFields(iq.tree());
  23260. },
  23261. setFields: function setFields(stanza) {
  23262. /* Stores the values that will be sent to the XMPP server
  23263. * during attempted registration.
  23264. *
  23265. * Parameters:
  23266. * (XMLElement) stanza - the IQ stanza that will be sent to the XMPP server.
  23267. */
  23268. var query = stanza.querySelector('query');
  23269. var xform = sizzle("x[xmlns=\"".concat(Strophe.NS.XFORM, "\"]"), query);
  23270. if (xform.length > 0) {
  23271. this._setFieldsFromXForm(xform.pop());
  23272. } else {
  23273. this._setFieldsFromLegacy(query);
  23274. }
  23275. },
  23276. _setFieldsFromLegacy: function _setFieldsFromLegacy(query) {
  23277. var _this5 = this;
  23278. _.each(query.children, function (field) {
  23279. if (field.tagName.toLowerCase() === 'instructions') {
  23280. _this5.instructions = Strophe.getText(field);
  23281. return;
  23282. } else if (field.tagName.toLowerCase() === 'x') {
  23283. if (field.getAttribute('xmlns') === 'jabber:x:oob') {
  23284. _this5.urls.concat(_.map(field.querySelectorAll('url'), 'textContent'));
  23285. }
  23286. return;
  23287. }
  23288. _this5.fields[field.tagName.toLowerCase()] = Strophe.getText(field);
  23289. });
  23290. this.form_type = 'legacy';
  23291. },
  23292. _setFieldsFromXForm: function _setFieldsFromXForm(xform) {
  23293. var _this6 = this;
  23294. this.title = _.get(xform.querySelector('title'), 'textContent');
  23295. this.instructions = _.get(xform.querySelector('instructions'), 'textContent');
  23296. _.each(xform.querySelectorAll('field'), function (field) {
  23297. var _var = field.getAttribute('var');
  23298. if (_var) {
  23299. _this6.fields[_var.toLowerCase()] = _.get(field.querySelector('value'), 'textContent', '');
  23300. } else {
  23301. // TODO: other option seems to be type="fixed"
  23302. _converse.log("Found field we couldn't parse", Strophe.LogLevel.WARN);
  23303. }
  23304. });
  23305. this.form_type = 'xform';
  23306. },
  23307. _onRegisterIQ: function _onRegisterIQ(stanza) {
  23308. /* Callback method that gets called when a return IQ stanza
  23309. * is received from the XMPP server, after attempting to
  23310. * register a new user.
  23311. *
  23312. * Parameters:
  23313. * (XMLElement) stanza - The IQ stanza.
  23314. */
  23315. if (stanza.getAttribute("type") === "error") {
  23316. _converse.log("Registration failed.", Strophe.LogLevel.ERROR);
  23317. this.reportErrors(stanza);
  23318. var error = stanza.getElementsByTagName("error");
  23319. if (error.length !== 1) {
  23320. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
  23321. return false;
  23322. }
  23323. error = error[0].firstChild.tagName.toLowerCase();
  23324. if (error === 'conflict') {
  23325. _converse.connection._changeConnectStatus(Strophe.Status.CONFLICT, error);
  23326. } else if (error === 'not-acceptable') {
  23327. _converse.connection._changeConnectStatus(Strophe.Status.NOTACCEPTABLE, error);
  23328. } else {
  23329. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, error);
  23330. }
  23331. } else {
  23332. _converse.connection._changeConnectStatus(Strophe.Status.REGISTERED, null);
  23333. }
  23334. return false;
  23335. }
  23336. });
  23337. }
  23338. });
  23339. });
  23340. //# sourceMappingURL=converse-register.js.map;
  23341. // Converse.js (A browser based XMPP chat client)
  23342. // http://conversejs.org
  23343. //
  23344. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  23345. // Licensed under the Mozilla Public License (MPLv2)
  23346. //
  23347. /*global define */
  23348. /* This is a Converse.js plugin which add support for application-level pings
  23349. * as specified in XEP-0199 XMPP Ping.
  23350. */
  23351. (function (root, factory) {
  23352. define('converse-ping',["converse-core", "strophe.ping"], factory);
  23353. })(void 0, function (converse) {
  23354. "use strict"; // Strophe methods for building stanzas
  23355. var _converse$env = converse.env,
  23356. Strophe = _converse$env.Strophe,
  23357. _ = _converse$env._;
  23358. converse.plugins.add('converse-ping', {
  23359. initialize: function initialize() {
  23360. /* The initialize function gets called as soon as the plugin is
  23361. * loaded by converse.js's plugin machinery.
  23362. */
  23363. var _converse = this._converse;
  23364. _converse.api.settings.update({
  23365. ping_interval: 180 //in seconds
  23366. });
  23367. _converse.ping = function (jid, success, error, timeout) {
  23368. // XXX: We could first check here if the server advertised that
  23369. // it supports PING.
  23370. // However, some servers don't advertise while still keeping the
  23371. // connection option due to pings.
  23372. //
  23373. // var feature = _converse.disco_entities[_converse.domain].features.findWhere({'var': Strophe.NS.PING});
  23374. _converse.lastStanzaDate = new Date();
  23375. if (_.isNil(jid)) {
  23376. jid = Strophe.getDomainFromJid(_converse.bare_jid);
  23377. }
  23378. if (_.isUndefined(timeout)) {
  23379. timeout = null;
  23380. }
  23381. if (_.isUndefined(success)) {
  23382. success = null;
  23383. }
  23384. if (_.isUndefined(error)) {
  23385. error = null;
  23386. }
  23387. if (_converse.connection) {
  23388. _converse.connection.ping.ping(jid, success, error, timeout);
  23389. return true;
  23390. }
  23391. return false;
  23392. };
  23393. _converse.pong = function (ping) {
  23394. _converse.lastStanzaDate = new Date();
  23395. _converse.connection.ping.pong(ping);
  23396. return true;
  23397. };
  23398. _converse.registerPongHandler = function () {
  23399. if (!_.isUndefined(_converse.connection.disco)) {
  23400. _converse.connection.disco.addFeature(Strophe.NS.PING);
  23401. }
  23402. _converse.connection.ping.addPingHandler(_converse.pong);
  23403. };
  23404. _converse.registerPingHandler = function () {
  23405. _converse.registerPongHandler();
  23406. if (_converse.ping_interval > 0) {
  23407. _converse.connection.addHandler(function () {
  23408. /* Handler on each stanza, saves the received date
  23409. * in order to ping only when needed.
  23410. */
  23411. _converse.lastStanzaDate = new Date();
  23412. return true;
  23413. });
  23414. _converse.connection.addTimedHandler(1000, function () {
  23415. var now = new Date();
  23416. if (!_converse.lastStanzaDate) {
  23417. _converse.lastStanzaDate = now;
  23418. }
  23419. if ((now - _converse.lastStanzaDate) / 1000 > _converse.ping_interval) {
  23420. return _converse.ping();
  23421. }
  23422. return true;
  23423. });
  23424. }
  23425. };
  23426. var onConnected = function onConnected() {
  23427. // Wrapper so that we can spy on registerPingHandler in tests
  23428. _converse.registerPingHandler();
  23429. };
  23430. _converse.on('connected', onConnected);
  23431. _converse.on('reconnected', onConnected);
  23432. }
  23433. });
  23434. });
  23435. //# sourceMappingURL=converse-ping.js.map;
  23436. // Converse.js (A browser based XMPP chat client)
  23437. // http://conversejs.org
  23438. //
  23439. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  23440. // Licensed under the Mozilla Public License (MPLv2)
  23441. //
  23442. /*global define */
  23443. (function (root, factory) {
  23444. define('converse-notification',["converse-core"], factory);
  23445. })(void 0, function (converse) {
  23446. "use strict";
  23447. var _converse$env = converse.env,
  23448. utils = _converse$env.utils,
  23449. Strophe = _converse$env.Strophe,
  23450. _ = _converse$env._;
  23451. converse.plugins.add('converse-notification', {
  23452. initialize: function initialize() {
  23453. /* The initialize function gets called as soon as the plugin is
  23454. * loaded by converse.js's plugin machinery.
  23455. */
  23456. var _converse = this._converse;
  23457. var __ = _converse.__;
  23458. _converse.supports_html5_notification = "Notification" in window;
  23459. _converse.api.settings.update({
  23460. notify_all_room_messages: false,
  23461. show_desktop_notifications: true,
  23462. show_chatstate_notifications: false,
  23463. chatstate_notification_blacklist: [],
  23464. // ^ a list of JIDs to ignore concerning chat state notifications
  23465. play_sounds: true,
  23466. sounds_path: '/sounds/',
  23467. notification_icon: '/logo/conversejs128.png'
  23468. });
  23469. _converse.isOnlyChatStateNotification = function (msg) {
  23470. return (// See XEP-0085 Chat State Notification
  23471. _.isNull(msg.querySelector('body')) && (_.isNull(msg.querySelector(_converse.ACTIVE)) || _.isNull(msg.querySelector(_converse.COMPOSING)) || _.isNull(msg.querySelector(_converse.INACTIVE)) || _.isNull(msg.querySelector(_converse.PAUSED)) || _.isNull(msg.querySelector(_converse.GONE)))
  23472. );
  23473. };
  23474. _converse.shouldNotifyOfGroupMessage = function (message) {
  23475. /* Is this a group message worthy of notification?
  23476. */
  23477. var notify_all = _converse.notify_all_room_messages;
  23478. var jid = message.getAttribute('from'),
  23479. resource = Strophe.getResourceFromJid(jid),
  23480. room_jid = Strophe.getBareJidFromJid(jid),
  23481. sender = resource && Strophe.unescapeNode(resource) || '';
  23482. if (sender === '' || message.querySelectorAll('delay').length > 0) {
  23483. return false;
  23484. }
  23485. var room = _converse.chatboxes.get(room_jid);
  23486. var body = message.querySelector('body');
  23487. if (_.isNull(body)) {
  23488. return false;
  23489. }
  23490. var mentioned = new RegExp("\\b".concat(room.get('nick'), "\\b")).test(body.textContent);
  23491. notify_all = notify_all === true || _.isArray(notify_all) && _.includes(notify_all, room_jid);
  23492. if (sender === room.get('nick') || !notify_all && !mentioned) {
  23493. return false;
  23494. }
  23495. return true;
  23496. };
  23497. _converse.isMessageToHiddenChat = function (message) {
  23498. if (_.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode)) {
  23499. var jid = Strophe.getBareJidFromJid(message.getAttribute('from'));
  23500. var model = _converse.chatboxes.get(jid);
  23501. if (!_.isNil(model)) {
  23502. return model.get('hidden') || _converse.windowState === 'hidden';
  23503. }
  23504. return true;
  23505. }
  23506. return _converse.windowState === 'hidden';
  23507. };
  23508. _converse.shouldNotifyOfMessage = function (message) {
  23509. /* Is this a message worthy of notification?
  23510. */
  23511. if (utils.isOTRMessage(message)) {
  23512. return false;
  23513. }
  23514. var forwarded = message.querySelector('forwarded');
  23515. if (!_.isNull(forwarded)) {
  23516. return false;
  23517. } else if (message.getAttribute('type') === 'groupchat') {
  23518. return _converse.shouldNotifyOfGroupMessage(message);
  23519. } else if (utils.isHeadlineMessage(_converse, message)) {
  23520. // We want to show notifications for headline messages.
  23521. return _converse.isMessageToHiddenChat(message);
  23522. }
  23523. var is_me = Strophe.getBareJidFromJid(message.getAttribute('from')) === _converse.bare_jid;
  23524. return !_converse.isOnlyChatStateNotification(message) && !is_me && _converse.isMessageToHiddenChat(message);
  23525. };
  23526. _converse.playSoundNotification = function () {
  23527. /* Plays a sound to notify that a new message was recieved.
  23528. */
  23529. // XXX Eventually this can be refactored to use Notification's sound
  23530. // feature, but no browser currently supports it.
  23531. // https://developer.mozilla.org/en-US/docs/Web/API/notification/sound
  23532. var audio;
  23533. if (_converse.play_sounds && !_.isUndefined(window.Audio)) {
  23534. audio = new Audio(_converse.sounds_path + "msg_received.ogg");
  23535. if (audio.canPlayType('audio/ogg')) {
  23536. audio.play();
  23537. } else {
  23538. audio = new Audio(_converse.sounds_path + "msg_received.mp3");
  23539. if (audio.canPlayType('audio/mp3')) {
  23540. audio.play();
  23541. }
  23542. }
  23543. }
  23544. };
  23545. _converse.areDesktopNotificationsEnabled = function () {
  23546. return _converse.supports_html5_notification && _converse.show_desktop_notifications && Notification.permission === "granted";
  23547. };
  23548. _converse.showMessageNotification = function (message) {
  23549. /* Shows an HTML5 Notification to indicate that a new chat
  23550. * message was received.
  23551. */
  23552. var title, roster_item;
  23553. var full_from_jid = message.getAttribute('from'),
  23554. from_jid = Strophe.getBareJidFromJid(full_from_jid);
  23555. if (message.getAttribute('type') === 'headline') {
  23556. if (!_.includes(from_jid, '@') || _converse.allow_non_roster_messaging) {
  23557. title = __("Notification from %1$s", from_jid);
  23558. } else {
  23559. return;
  23560. }
  23561. } else if (!_.includes(from_jid, '@')) {
  23562. // workaround for Prosody which doesn't give type "headline"
  23563. title = __("Notification from %1$s", from_jid);
  23564. } else if (message.getAttribute('type') === 'groupchat') {
  23565. title = __("%1$s says", Strophe.getResourceFromJid(full_from_jid));
  23566. } else {
  23567. if (_.isUndefined(_converse.roster)) {
  23568. _converse.log("Could not send notification, because roster is undefined", Strophe.LogLevel.ERROR);
  23569. return;
  23570. }
  23571. roster_item = _converse.roster.get(from_jid);
  23572. if (!_.isUndefined(roster_item)) {
  23573. title = __("%1$s says", roster_item.get('fullname'));
  23574. } else {
  23575. if (_converse.allow_non_roster_messaging) {
  23576. title = __("%1$s says", from_jid);
  23577. } else {
  23578. return;
  23579. }
  23580. }
  23581. }
  23582. var n = new Notification(title, {
  23583. body: message.querySelector('body').textContent,
  23584. lang: _converse.locale,
  23585. icon: _converse.notification_icon
  23586. });
  23587. setTimeout(n.close.bind(n), 5000);
  23588. };
  23589. _converse.showChatStateNotification = function (contact) {
  23590. /* Creates an HTML5 Notification to inform of a change in a
  23591. * contact's chat state.
  23592. */
  23593. if (_.includes(_converse.chatstate_notification_blacklist, contact.jid)) {
  23594. // Don't notify if the user is being ignored.
  23595. return;
  23596. }
  23597. var chat_state = contact.chat_status;
  23598. var message = null;
  23599. if (chat_state === 'offline') {
  23600. message = __('has gone offline');
  23601. } else if (chat_state === 'away') {
  23602. message = __('has gone away');
  23603. } else if (chat_state === 'dnd') {
  23604. message = __('is busy');
  23605. } else if (chat_state === 'online') {
  23606. message = __('has come online');
  23607. }
  23608. if (message === null) {
  23609. return;
  23610. }
  23611. var n = new Notification(contact.fullname, {
  23612. body: message,
  23613. lang: _converse.locale,
  23614. icon: _converse.notification_icon
  23615. });
  23616. setTimeout(n.close.bind(n), 5000);
  23617. };
  23618. _converse.showContactRequestNotification = function (contact) {
  23619. var n = new Notification(contact.fullname, {
  23620. body: __('wants to be your contact'),
  23621. lang: _converse.locale,
  23622. icon: _converse.notification_icon
  23623. });
  23624. setTimeout(n.close.bind(n), 5000);
  23625. };
  23626. _converse.showFeedbackNotification = function (data) {
  23627. if (data.klass === 'error' || data.klass === 'warn') {
  23628. var n = new Notification(data.subject, {
  23629. body: data.message,
  23630. lang: _converse.locale,
  23631. icon: _converse.notification_icon
  23632. });
  23633. setTimeout(n.close.bind(n), 5000);
  23634. }
  23635. };
  23636. _converse.handleChatStateNotification = function (contact) {
  23637. /* Event handler for on('contactStatusChanged').
  23638. * Will show an HTML5 notification to indicate that the chat
  23639. * status has changed.
  23640. */
  23641. if (_converse.areDesktopNotificationsEnabled() && _converse.show_chatstate_notifications) {
  23642. _converse.showChatStateNotification(contact);
  23643. }
  23644. };
  23645. _converse.handleMessageNotification = function (data) {
  23646. /* Event handler for the on('message') event. Will call methods
  23647. * to play sounds and show HTML5 notifications.
  23648. */
  23649. var message = data.stanza;
  23650. if (!_converse.shouldNotifyOfMessage(message)) {
  23651. return false;
  23652. }
  23653. _converse.playSoundNotification();
  23654. if (_converse.areDesktopNotificationsEnabled()) {
  23655. _converse.showMessageNotification(message);
  23656. }
  23657. };
  23658. _converse.handleContactRequestNotification = function (contact) {
  23659. if (_converse.areDesktopNotificationsEnabled(true)) {
  23660. _converse.showContactRequestNotification(contact);
  23661. }
  23662. };
  23663. _converse.handleFeedback = function (data) {
  23664. if (_converse.areDesktopNotificationsEnabled(true)) {
  23665. _converse.showFeedbackNotification(data);
  23666. }
  23667. };
  23668. _converse.requestPermission = function () {
  23669. if (_converse.supports_html5_notification && !_.includes(['denied', 'granted'], Notification.permission)) {
  23670. // Ask user to enable HTML5 notifications
  23671. Notification.requestPermission();
  23672. }
  23673. };
  23674. _converse.on('pluginsInitialized', function () {
  23675. // We only register event handlers after all plugins are
  23676. // registered, because other plugins might override some of our
  23677. // handlers.
  23678. _converse.on('contactRequest', _converse.handleContactRequestNotification);
  23679. _converse.on('contactStatusChanged', _converse.handleChatStateNotification);
  23680. _converse.on('message', _converse.handleMessageNotification);
  23681. _converse.on('feedback', _converse.handleFeedback);
  23682. _converse.on('connected', _converse.requestPermission);
  23683. });
  23684. }
  23685. });
  23686. });
  23687. //# sourceMappingURL=converse-notification.js.map;
  23688. define('tpl!chatbox_minimize', ['lodash'], function(_) {return function(o) {
  23689. var __t, __p = '', __e = _.escape;
  23690. __p += '<a class="chatbox-btn toggle-chatbox-button fa fa-minus" title="' +
  23691. __e(o.info_minimize) +
  23692. '"></a>\n';
  23693. return __p
  23694. };});
  23695. define('tpl!toggle_chats', ['lodash'], function(_) {return function(o) {
  23696. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  23697. function print() { __p += __j.call(arguments, '') }
  23698. __p +=
  23699. __e(o.num_minimized) +
  23700. ' ' +
  23701. __e(o.Minimized) +
  23702. '\n<span class="unread-message-count ';
  23703. if (!o.num_unread) { ;
  23704. __p += ' unread-message-count-hidden ';
  23705. } ;
  23706. __p += '" href="#">' +
  23707. __e(o.num_unread) +
  23708. '</span>\n';
  23709. return __p
  23710. };});
  23711. define('tpl!trimmed_chat', ['lodash'], function(_) {return function(o) {
  23712. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  23713. function print() { __p += __j.call(arguments, '') }
  23714. __p += '<a href="#" class="restore-chat w-100 align-self-center" title="' +
  23715. __e(o.tooltip) +
  23716. '">\n ';
  23717. if (o.num_unread) { ;
  23718. __p += ' \n <span class="message-count badge badge-light">' +
  23719. __e(o.num_unread) +
  23720. '</span>\n ';
  23721. } ;
  23722. __p += '\n ' +
  23723. __e(o.title || o.jid ) +
  23724. '\n</a>\n<a class="chatbox-btn close-chatbox-button fa fa-times"></a>\n';
  23725. return __p
  23726. };});
  23727. define('tpl!chats_panel', ['lodash'], function(_) {return function(o) {
  23728. var __t, __p = '';
  23729. __p += '<a id="toggle-minimized-chats" href="#" class="row no-gutters"></a>\n<div class="flyout minimized-chats-flyout row no-gutters"></div>\n';
  23730. return __p
  23731. };});
  23732. // Converse.js (A browser based XMPP chat client)
  23733. // http://conversejs.org
  23734. //
  23735. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  23736. // Licensed under the Mozilla Public License (MPLv2)
  23737. //
  23738. /*global define, window, document */
  23739. (function (root, factory) {
  23740. define('converse-minimize',["converse-core", "tpl!chatbox_minimize", "tpl!toggle_chats", "tpl!trimmed_chat", "tpl!chats_panel", "converse-chatview"], factory);
  23741. })(void 0, function (converse, tpl_chatbox_minimize, tpl_toggle_chats, tpl_trimmed_chat, tpl_chats_panel) {
  23742. "use strict";
  23743. var _converse$env = converse.env,
  23744. _ = _converse$env._,
  23745. Backbone = _converse$env.Backbone,
  23746. Promise = _converse$env.Promise,
  23747. Strophe = _converse$env.Strophe,
  23748. b64_sha1 = _converse$env.b64_sha1,
  23749. moment = _converse$env.moment;
  23750. var u = converse.env.utils;
  23751. converse.plugins.add('converse-minimize', {
  23752. /* Optional dependencies are other plugins which might be
  23753. * overridden or relied upon, and therefore need to be loaded before
  23754. * this plugin. They are called "optional" because they might not be
  23755. * available, in which case any overrides applicable to them will be
  23756. * ignored.
  23757. *
  23758. * It's possible however to make optional dependencies non-optional.
  23759. * If the setting "strict_plugin_dependencies" is set to true,
  23760. * an error will be raised if the plugin is not found.
  23761. *
  23762. * NB: These plugins need to have already been loaded via require.js.
  23763. */
  23764. dependencies: ["converse-chatview", "converse-controlbox", "converse-muc", "converse-muc-views", "converse-headline"],
  23765. enabled: function enabled(_converse) {
  23766. return _converse.view_mode == 'overlayed';
  23767. },
  23768. overrides: {
  23769. // Overrides mentioned here will be picked up by converse.js's
  23770. // plugin architecture they will replace existing methods on the
  23771. // relevant objects or classes.
  23772. //
  23773. // New functions which don't exist yet can also be added.
  23774. registerGlobalEventHandlers: function registerGlobalEventHandlers() {
  23775. var _converse = this.__super__._converse;
  23776. window.addEventListener("resize", _.debounce(function (ev) {
  23777. if (_converse.connection.connected) {
  23778. _converse.chatboxviews.trimChats();
  23779. }
  23780. }, 200));
  23781. return this.__super__.registerGlobalEventHandlers.apply(this, arguments);
  23782. },
  23783. ChatBox: {
  23784. initialize: function initialize() {
  23785. this.__super__.initialize.apply(this, arguments);
  23786. this.on('show', this.maximize, this);
  23787. if (this.get('id') === 'controlbox') {
  23788. return;
  23789. }
  23790. this.save({
  23791. 'minimized': this.get('minimized') || false,
  23792. 'time_minimized': this.get('time_minimized') || moment()
  23793. });
  23794. },
  23795. maximize: function maximize() {
  23796. u.safeSave(this, {
  23797. 'minimized': false,
  23798. 'time_opened': moment().valueOf()
  23799. });
  23800. },
  23801. minimize: function minimize() {
  23802. u.safeSave(this, {
  23803. 'minimized': true,
  23804. 'time_minimized': moment().format()
  23805. });
  23806. }
  23807. },
  23808. ChatBoxView: {
  23809. events: {
  23810. 'click .toggle-chatbox-button': 'minimize'
  23811. },
  23812. initialize: function initialize() {
  23813. this.model.on('change:minimized', this.onMinimizedChanged, this);
  23814. return this.__super__.initialize.apply(this, arguments);
  23815. },
  23816. _show: function _show() {
  23817. var _converse = this.__super__._converse;
  23818. if (!this.model.get('minimized')) {
  23819. this.__super__._show.apply(this, arguments);
  23820. _converse.chatboxviews.trimChats(this);
  23821. } else {
  23822. this.minimize();
  23823. }
  23824. },
  23825. isNewMessageHidden: function isNewMessageHidden() {
  23826. return this.model.get('minimized') || this.__super__.isNewMessageHidden.apply(this, arguments);
  23827. },
  23828. shouldShowOnTextMessage: function shouldShowOnTextMessage() {
  23829. return !this.model.get('minimized') && this.__super__.shouldShowOnTextMessage.apply(this, arguments);
  23830. },
  23831. setChatBoxHeight: function setChatBoxHeight(height) {
  23832. if (!this.model.get('minimized')) {
  23833. return this.__super__.setChatBoxHeight.apply(this, arguments);
  23834. }
  23835. },
  23836. setChatBoxWidth: function setChatBoxWidth(width) {
  23837. if (!this.model.get('minimized')) {
  23838. return this.__super__.setChatBoxWidth.apply(this, arguments);
  23839. }
  23840. },
  23841. onMinimizedChanged: function onMinimizedChanged(item) {
  23842. if (item.get('minimized')) {
  23843. this.minimize();
  23844. } else {
  23845. this.maximize();
  23846. }
  23847. },
  23848. maximize: function maximize() {
  23849. // Restores a minimized chat box
  23850. var _converse = this.__super__._converse;
  23851. this.insertIntoDOM();
  23852. if (!this.model.isScrolledUp()) {
  23853. this.model.clearUnreadMsgCounter();
  23854. }
  23855. this.show();
  23856. this.__super__._converse.emit('chatBoxMaximized', this);
  23857. return this;
  23858. },
  23859. minimize: function minimize(ev) {
  23860. var _converse = this.__super__._converse;
  23861. if (ev && ev.preventDefault) {
  23862. ev.preventDefault();
  23863. } // save the scroll position to restore it on maximize
  23864. if (this.model.collection && this.model.collection.browserStorage) {
  23865. this.model.save({
  23866. 'scroll': this.content.scrollTop
  23867. });
  23868. } else {
  23869. this.model.set({
  23870. 'scroll': this.content.scrollTop
  23871. });
  23872. }
  23873. this.setChatState(_converse.INACTIVE).model.minimize();
  23874. this.hide();
  23875. _converse.emit('chatBoxMinimized', this);
  23876. }
  23877. },
  23878. ChatRoomView: {
  23879. events: {
  23880. 'click .toggle-chatbox-button': 'minimize'
  23881. },
  23882. initialize: function initialize() {
  23883. this.model.on('change:minimized', function (item) {
  23884. if (item.get('minimized')) {
  23885. this.hide();
  23886. } else {
  23887. this.maximize();
  23888. }
  23889. }, this);
  23890. var result = this.__super__.initialize.apply(this, arguments);
  23891. if (this.model.get('minimized')) {
  23892. this.hide();
  23893. }
  23894. return result;
  23895. },
  23896. generateHeadingHTML: function generateHeadingHTML() {
  23897. var _converse = this.__super__._converse,
  23898. __ = _converse.__;
  23899. var html = this.__super__.generateHeadingHTML.apply(this, arguments);
  23900. var div = document.createElement('div');
  23901. div.innerHTML = html;
  23902. var button = div.querySelector('.close-chatbox-button');
  23903. button.insertAdjacentHTML('afterend', tpl_chatbox_minimize({
  23904. 'info_minimize': __('Minimize this chat box')
  23905. }));
  23906. return div.innerHTML;
  23907. }
  23908. },
  23909. ChatBoxes: {
  23910. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  23911. return this.__super__.chatBoxMayBeShown.apply(this, arguments) && !chatbox.get('minimized');
  23912. }
  23913. },
  23914. ChatBoxViews: {
  23915. getChatBoxWidth: function getChatBoxWidth(view) {
  23916. if (!view.model.get('minimized') && u.isVisible(view.el)) {
  23917. return u.getOuterWidth(view.el, true);
  23918. }
  23919. return 0;
  23920. },
  23921. getShownChats: function getShownChats() {
  23922. return this.filter(function (view) {
  23923. return (// The controlbox can take a while to close,
  23924. // so we need to check its state. That's why we checked
  23925. // the 'closed' state.
  23926. !view.model.get('minimized') && !view.model.get('closed') && u.isVisible(view.el)
  23927. );
  23928. });
  23929. },
  23930. trimChats: function trimChats(newchat) {
  23931. var _this = this;
  23932. /* This method is called when a newly created chat box will
  23933. * be shown.
  23934. *
  23935. * It checks whether there is enough space on the page to show
  23936. * another chat box. Otherwise it minimizes the oldest chat box
  23937. * to create space.
  23938. */
  23939. var _converse = this.__super__._converse,
  23940. shown_chats = this.getShownChats(),
  23941. body_width = u.getOuterWidth(document.querySelector('body'), true);
  23942. if (_converse.no_trimming || shown_chats.length <= 1) {
  23943. return;
  23944. }
  23945. if (this.getChatBoxWidth(shown_chats[0]) === body_width) {
  23946. // If the chats shown are the same width as the body,
  23947. // then we're in responsive mode and the chats are
  23948. // fullscreen. In this case we don't trim.
  23949. return;
  23950. }
  23951. _converse.api.waitUntil('minimizedChatsInitialized').then(function () {
  23952. var minimized_el = _.get(_converse.minimized_chats, 'el'),
  23953. new_id = newchat ? newchat.model.get('id') : null;
  23954. if (minimized_el) {
  23955. var minimized_width = _.includes(_this.model.pluck('minimized'), true) ? u.getOuterWidth(minimized_el, true) : 0;
  23956. var boxes_width = _.reduce(_this.xget(new_id), function (memo, view) {
  23957. return memo + _this.getChatBoxWidth(view);
  23958. }, newchat ? u.getOuterWidth(newchat.el, true) : 0);
  23959. if (minimized_width + boxes_width > body_width) {
  23960. var oldest_chat = _this.getOldestMaximizedChat([new_id]);
  23961. if (oldest_chat) {
  23962. // We hide the chat immediately, because waiting
  23963. // for the event to fire (and letting the
  23964. // ChatBoxView hide it then) causes race
  23965. // conditions.
  23966. var view = _this.get(oldest_chat.get('id'));
  23967. if (view) {
  23968. view.hide();
  23969. }
  23970. oldest_chat.minimize();
  23971. }
  23972. }
  23973. }
  23974. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  23975. },
  23976. getOldestMaximizedChat: function getOldestMaximizedChat(exclude_ids) {
  23977. // Get oldest view (if its id is not excluded)
  23978. exclude_ids.push('controlbox');
  23979. var i = 0;
  23980. var model = this.model.sort().at(i);
  23981. while (_.includes(exclude_ids, model.get('id')) || model.get('minimized') === true) {
  23982. i++;
  23983. model = this.model.at(i);
  23984. if (!model) {
  23985. return null;
  23986. }
  23987. }
  23988. return model;
  23989. }
  23990. }
  23991. },
  23992. initialize: function initialize() {
  23993. /* The initialize function gets called as soon as the plugin is
  23994. * loaded by Converse.js's plugin machinery.
  23995. */
  23996. var _converse = this._converse,
  23997. __ = _converse.__; // Add new HTML templates.
  23998. _converse.templates.chatbox_minimize = tpl_chatbox_minimize;
  23999. _converse.templates.toggle_chats = tpl_toggle_chats;
  24000. _converse.templates.trimmed_chat = tpl_trimmed_chat;
  24001. _converse.templates.chats_panel = tpl_chats_panel;
  24002. _converse.api.settings.update({
  24003. no_trimming: false // Set to true for phantomjs tests (where browser apparently has no width)
  24004. });
  24005. _converse.api.promises.add('minimizedChatsInitialized');
  24006. _converse.MinimizedChatBoxView = Backbone.NativeView.extend({
  24007. tagName: 'div',
  24008. className: 'chat-head row no-gutters',
  24009. events: {
  24010. 'click .close-chatbox-button': 'close',
  24011. 'click .restore-chat': 'restore'
  24012. },
  24013. initialize: function initialize() {
  24014. this.model.on('change:num_unread', this.render, this);
  24015. },
  24016. render: function render() {
  24017. var data = _.extend(this.model.toJSON(), {
  24018. 'tooltip': __('Click to restore this chat')
  24019. });
  24020. if (this.model.get('type') === 'chatroom') {
  24021. data.title = this.model.get('name');
  24022. u.addClass('chat-head-chatroom', this.el);
  24023. } else {
  24024. data.title = this.model.get('fullname');
  24025. u.addClass('chat-head-chatbox', this.el);
  24026. }
  24027. this.el.innerHTML = tpl_trimmed_chat(data);
  24028. return this.el;
  24029. },
  24030. close: function close(ev) {
  24031. if (ev && ev.preventDefault) {
  24032. ev.preventDefault();
  24033. }
  24034. this.remove();
  24035. var view = _converse.chatboxviews.get(this.model.get('id'));
  24036. if (view) {
  24037. // This will call model.destroy(), removing it from the
  24038. // collection and will also emit 'chatBoxClosed'
  24039. view.close();
  24040. } else {
  24041. this.model.destroy();
  24042. _converse.emit('chatBoxClosed', this);
  24043. }
  24044. return this;
  24045. },
  24046. restore: _.debounce(function (ev) {
  24047. if (ev && ev.preventDefault) {
  24048. ev.preventDefault();
  24049. }
  24050. this.model.off('change:num_unread', null, this);
  24051. this.remove();
  24052. this.model.maximize();
  24053. }, 200, {
  24054. 'leading': true
  24055. })
  24056. });
  24057. _converse.MinimizedChats = Backbone.Overview.extend({
  24058. tagName: 'div',
  24059. id: "minimized-chats",
  24060. className: 'hidden',
  24061. events: {
  24062. "click #toggle-minimized-chats": "toggle"
  24063. },
  24064. initialize: function initialize() {
  24065. this.render();
  24066. this.initToggle();
  24067. this.addMultipleChats(this.model.where({
  24068. 'minimized': true
  24069. }));
  24070. this.model.on("add", this.onChanged, this);
  24071. this.model.on("destroy", this.removeChat, this);
  24072. this.model.on("change:minimized", this.onChanged, this);
  24073. this.model.on('change:num_unread', this.updateUnreadMessagesCounter, this);
  24074. },
  24075. render: function render() {
  24076. if (!this.el.parentElement) {
  24077. this.el.innerHTML = tpl_chats_panel();
  24078. _converse.chatboxviews.insertRowColumn(this.el);
  24079. }
  24080. if (this.keys().length === 0) {
  24081. this.el.classList.add('hidden');
  24082. } else if (this.keys().length > 0 && !u.isVisible(this.el)) {
  24083. this.el.classList.remove('hidden');
  24084. _converse.chatboxviews.trimChats();
  24085. }
  24086. return this.el;
  24087. },
  24088. tearDown: function tearDown() {
  24089. this.model.off("add", this.onChanged);
  24090. this.model.off("destroy", this.removeChat);
  24091. this.model.off("change:minimized", this.onChanged);
  24092. this.model.off('change:num_unread', this.updateUnreadMessagesCounter);
  24093. return this;
  24094. },
  24095. initToggle: function initToggle() {
  24096. this.toggleview = new _converse.MinimizedChatsToggleView({
  24097. model: new _converse.MinimizedChatsToggle()
  24098. });
  24099. var id = b64_sha1("converse.minchatstoggle".concat(_converse.bare_jid));
  24100. this.toggleview.model.id = id; // Appears to be necessary for backbone.browserStorage
  24101. this.toggleview.model.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  24102. this.toggleview.model.fetch();
  24103. },
  24104. toggle: function toggle(ev) {
  24105. if (ev && ev.preventDefault) {
  24106. ev.preventDefault();
  24107. }
  24108. this.toggleview.model.save({
  24109. 'collapsed': !this.toggleview.model.get('collapsed')
  24110. });
  24111. u.slideToggleElement(this.el.querySelector('.minimized-chats-flyout'), 200);
  24112. },
  24113. onChanged: function onChanged(item) {
  24114. if (item.get('id') === 'controlbox') {
  24115. // The ControlBox has it's own minimize toggle
  24116. return;
  24117. }
  24118. if (item.get('minimized')) {
  24119. this.addChat(item);
  24120. } else if (this.get(item.get('id'))) {
  24121. this.removeChat(item);
  24122. }
  24123. },
  24124. addChatView: function addChatView(item) {
  24125. var existing = this.get(item.get('id'));
  24126. if (existing && existing.el.parentNode) {
  24127. return;
  24128. }
  24129. var view = new _converse.MinimizedChatBoxView({
  24130. model: item
  24131. });
  24132. this.el.querySelector('.minimized-chats-flyout').insertAdjacentElement('beforeEnd', view.render());
  24133. this.add(item.get('id'), view);
  24134. },
  24135. addMultipleChats: function addMultipleChats(items) {
  24136. _.each(items, this.addChatView.bind(this));
  24137. this.toggleview.model.set({
  24138. 'num_minimized': this.keys().length
  24139. });
  24140. this.render();
  24141. },
  24142. addChat: function addChat(item) {
  24143. this.addChatView(item);
  24144. this.toggleview.model.set({
  24145. 'num_minimized': this.keys().length
  24146. });
  24147. this.render();
  24148. },
  24149. removeChat: function removeChat(item) {
  24150. this.remove(item.get('id'));
  24151. this.toggleview.model.set({
  24152. 'num_minimized': this.keys().length
  24153. });
  24154. this.render();
  24155. },
  24156. updateUnreadMessagesCounter: function updateUnreadMessagesCounter() {
  24157. var ls = this.model.pluck('num_unread');
  24158. var count = 0,
  24159. i;
  24160. for (i = 0; i < ls.length; i++) {
  24161. count += ls[i];
  24162. }
  24163. this.toggleview.model.save({
  24164. 'num_unread': count
  24165. });
  24166. this.render();
  24167. }
  24168. });
  24169. _converse.MinimizedChatsToggle = Backbone.Model.extend({
  24170. defaults: {
  24171. 'collapsed': false,
  24172. 'num_minimized': 0,
  24173. 'num_unread': 0
  24174. }
  24175. });
  24176. _converse.MinimizedChatsToggleView = Backbone.NativeView.extend({
  24177. el: '#toggle-minimized-chats',
  24178. initialize: function initialize() {
  24179. this.model.on('change:num_minimized', this.render, this);
  24180. this.model.on('change:num_unread', this.render, this);
  24181. this.flyout = this.el.parentElement.querySelector('.minimized-chats-flyout');
  24182. },
  24183. render: function render() {
  24184. this.el.innerHTML = tpl_toggle_chats(_.extend(this.model.toJSON(), {
  24185. 'Minimized': __('Minimized')
  24186. }));
  24187. if (this.model.get('collapsed')) {
  24188. u.hideElement(this.flyout);
  24189. } else {
  24190. u.showElement(this.flyout);
  24191. }
  24192. return this.el;
  24193. }
  24194. });
  24195. Promise.all([_converse.api.waitUntil('connectionInitialized'), _converse.api.waitUntil('chatBoxesInitialized')]).then(function () {
  24196. _converse.minimized_chats = new _converse.MinimizedChats({
  24197. model: _converse.chatboxes
  24198. });
  24199. _converse.emit('minimizedChatsInitialized');
  24200. }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  24201. _converse.on('chatBoxOpened', function renderMinimizeButton(view) {
  24202. // Inserts a "minimize" button in the chatview's header
  24203. var new_html = tpl_chatbox_minimize({
  24204. info_minimize: __('Minimize this chat box')
  24205. });
  24206. var el = view.el.querySelector('.toggle-chatbox-button');
  24207. if (el) {
  24208. el.outerHTML = new_html;
  24209. } else {
  24210. var button = view.el.querySelector('.close-chatbox-button');
  24211. button.insertAdjacentHTML('afterEnd', new_html);
  24212. }
  24213. });
  24214. _converse.on('controlBoxOpened', function (chatbox) {
  24215. // Wrapped in anon method because at scan time, chatboxviews
  24216. // attr not set yet.
  24217. if (_converse.connection.connected) {
  24218. _converse.chatboxviews.trimChats(chatbox);
  24219. }
  24220. });
  24221. }
  24222. });
  24223. });
  24224. //# sourceMappingURL=converse-minimize.js.map;
  24225. define('tpl!dragresize', ['lodash'], function(_) {return function(o) {
  24226. var __t, __p = '';
  24227. __p += '<div class="dragresize dragresize-top"></div>\n<div class="dragresize dragresize-topleft"></div>\n<div class="dragresize dragresize-left"></div>\n';
  24228. return __p
  24229. };});
  24230. // Converse.js (A browser based XMPP chat client)
  24231. // http://conversejs.org
  24232. //
  24233. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  24234. // Licensed under the Mozilla Public License (MPLv2)
  24235. //
  24236. /*global define, window, document */
  24237. (function (root, factory) {
  24238. define('converse-dragresize',["converse-core", "tpl!dragresize", "converse-chatview", "converse-controlbox"], factory);
  24239. })(void 0, function (converse, tpl_dragresize) {
  24240. "use strict";
  24241. var _ = converse.env._;
  24242. function renderDragResizeHandles(_converse, view) {
  24243. var flyout = view.el.querySelector('.box-flyout');
  24244. var div = document.createElement('div');
  24245. div.innerHTML = tpl_dragresize();
  24246. flyout.insertBefore(div, flyout.firstChild);
  24247. }
  24248. converse.plugins.add('converse-dragresize', {
  24249. /* Plugin dependencies are other plugins which might be
  24250. * overridden or relied upon, and therefore need to be loaded before
  24251. * this plugin.
  24252. *
  24253. * If the setting "strict_plugin_dependencies" is set to true,
  24254. * an error will be raised if the plugin is not found. By default it's
  24255. * false, which means these plugins are only loaded opportunistically.
  24256. *
  24257. * NB: These plugins need to have already been loaded via require.js.
  24258. */
  24259. dependencies: ["converse-chatview", "converse-headline", "converse-muc-views"],
  24260. enabled: function enabled(_converse) {
  24261. return _converse.view_mode == 'overlayed';
  24262. },
  24263. overrides: {
  24264. // Overrides mentioned here will be picked up by converse.js's
  24265. // plugin architecture they will replace existing methods on the
  24266. // relevant objects or classes.
  24267. //
  24268. // New functions which don't exist yet can also be added.
  24269. registerGlobalEventHandlers: function registerGlobalEventHandlers() {
  24270. var that = this;
  24271. document.addEventListener('mousemove', function (ev) {
  24272. if (!that.resizing || !that.allow_dragresize) {
  24273. return true;
  24274. }
  24275. ev.preventDefault();
  24276. that.resizing.chatbox.resizeChatBox(ev);
  24277. });
  24278. document.addEventListener('mouseup', function (ev) {
  24279. if (!that.resizing || !that.allow_dragresize) {
  24280. return true;
  24281. }
  24282. ev.preventDefault();
  24283. var height = that.applyDragResistance(that.resizing.chatbox.height, that.resizing.chatbox.model.get('default_height'));
  24284. var width = that.applyDragResistance(that.resizing.chatbox.width, that.resizing.chatbox.model.get('default_width'));
  24285. if (that.connection.connected) {
  24286. that.resizing.chatbox.model.save({
  24287. 'height': height
  24288. });
  24289. that.resizing.chatbox.model.save({
  24290. 'width': width
  24291. });
  24292. } else {
  24293. that.resizing.chatbox.model.set({
  24294. 'height': height
  24295. });
  24296. that.resizing.chatbox.model.set({
  24297. 'width': width
  24298. });
  24299. }
  24300. that.resizing = null;
  24301. });
  24302. return this.__super__.registerGlobalEventHandlers.apply(this, arguments);
  24303. },
  24304. ChatBox: {
  24305. initialize: function initialize() {
  24306. var _converse = this.__super__._converse;
  24307. var result = this.__super__.initialize.apply(this, arguments),
  24308. height = this.get('height'),
  24309. width = this.get('width'),
  24310. save = this.get('id') === 'controlbox' ? this.set.bind(this) : this.save.bind(this);
  24311. save({
  24312. 'height': _converse.applyDragResistance(height, this.get('default_height')),
  24313. 'width': _converse.applyDragResistance(width, this.get('default_width'))
  24314. });
  24315. return result;
  24316. }
  24317. },
  24318. ChatBoxView: {
  24319. events: {
  24320. 'mousedown .dragresize-top': 'onStartVerticalResize',
  24321. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  24322. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  24323. },
  24324. initialize: function initialize() {
  24325. window.addEventListener('resize', _.debounce(this.setDimensions.bind(this), 100));
  24326. this.__super__.initialize.apply(this, arguments);
  24327. },
  24328. render: function render() {
  24329. var result = this.__super__.render.apply(this, arguments);
  24330. renderDragResizeHandles(this.__super__._converse, this);
  24331. this.setWidth();
  24332. return result;
  24333. },
  24334. setWidth: function setWidth() {
  24335. // If a custom width is applied (due to drag-resizing),
  24336. // then we need to set the width of the .chatbox element as well.
  24337. if (this.model.get('width')) {
  24338. this.el.style.width = this.model.get('width');
  24339. }
  24340. },
  24341. _show: function _show() {
  24342. this.initDragResize().setDimensions();
  24343. this.__super__._show.apply(this, arguments);
  24344. },
  24345. initDragResize: function initDragResize() {
  24346. /* Determine and store the default box size.
  24347. * We need this information for the drag-resizing feature.
  24348. */
  24349. var _converse = this.__super__._converse,
  24350. flyout = this.el.querySelector('.box-flyout'),
  24351. style = window.getComputedStyle(flyout);
  24352. if (_.isUndefined(this.model.get('height'))) {
  24353. var height = parseInt(style.height.replace(/px$/, ''), 10),
  24354. width = parseInt(style.width.replace(/px$/, ''), 10);
  24355. this.model.set('height', height);
  24356. this.model.set('default_height', height);
  24357. this.model.set('width', width);
  24358. this.model.set('default_width', width);
  24359. }
  24360. var min_width = style['min-width'];
  24361. var min_height = style['min-height'];
  24362. this.model.set('min_width', min_width.endsWith('px') ? Number(min_width.replace(/px$/, '')) : 0);
  24363. this.model.set('min_height', min_height.endsWith('px') ? Number(min_height.replace(/px$/, '')) : 0); // Initialize last known mouse position
  24364. this.prev_pageY = 0;
  24365. this.prev_pageX = 0;
  24366. if (_converse.connection.connected) {
  24367. this.height = this.model.get('height');
  24368. this.width = this.model.get('width');
  24369. }
  24370. return this;
  24371. },
  24372. setDimensions: function setDimensions() {
  24373. // Make sure the chat box has the right height and width.
  24374. this.adjustToViewport();
  24375. this.setChatBoxHeight(this.model.get('height'));
  24376. this.setChatBoxWidth(this.model.get('width'));
  24377. },
  24378. setChatBoxHeight: function setChatBoxHeight(height) {
  24379. var _converse = this.__super__._converse;
  24380. if (height) {
  24381. height = _converse.applyDragResistance(height, this.model.get('default_height')) + 'px';
  24382. } else {
  24383. height = "";
  24384. }
  24385. var flyout_el = this.el.querySelector('.box-flyout');
  24386. if (!_.isNull(flyout_el)) {
  24387. flyout_el.style.height = height;
  24388. }
  24389. },
  24390. setChatBoxWidth: function setChatBoxWidth(width) {
  24391. var _converse = this.__super__._converse;
  24392. if (width) {
  24393. width = _converse.applyDragResistance(width, this.model.get('default_width')) + 'px';
  24394. } else {
  24395. width = "";
  24396. }
  24397. this.el.style.width = width;
  24398. var flyout_el = this.el.querySelector('.box-flyout');
  24399. if (!_.isNull(flyout_el)) {
  24400. flyout_el.style.width = width;
  24401. }
  24402. },
  24403. adjustToViewport: function adjustToViewport() {
  24404. /* Event handler called when viewport gets resized. We remove
  24405. * custom width/height from chat boxes.
  24406. */
  24407. var viewport_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  24408. var viewport_height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  24409. if (viewport_width <= 480) {
  24410. this.model.set('height', undefined);
  24411. this.model.set('width', undefined);
  24412. } else if (viewport_width <= this.model.get('width')) {
  24413. this.model.set('width', undefined);
  24414. } else if (viewport_height <= this.model.get('height')) {
  24415. this.model.set('height', undefined);
  24416. }
  24417. },
  24418. onStartVerticalResize: function onStartVerticalResize(ev) {
  24419. var _converse = this.__super__._converse;
  24420. if (!_converse.allow_dragresize) {
  24421. return true;
  24422. } // Record element attributes for mouseMove().
  24423. var flyout = this.el.querySelector('.box-flyout'),
  24424. style = window.getComputedStyle(flyout);
  24425. this.height = parseInt(style.height.replace(/px$/, ''), 10);
  24426. _converse.resizing = {
  24427. 'chatbox': this,
  24428. 'direction': 'top'
  24429. };
  24430. this.prev_pageY = ev.pageY;
  24431. },
  24432. onStartHorizontalResize: function onStartHorizontalResize(ev) {
  24433. var _converse = this.__super__._converse;
  24434. if (!_converse.allow_dragresize) {
  24435. return true;
  24436. }
  24437. var flyout = this.el.querySelector('.box-flyout'),
  24438. style = window.getComputedStyle(flyout);
  24439. this.width = parseInt(style.width.replace(/px$/, ''), 10);
  24440. _converse.resizing = {
  24441. 'chatbox': this,
  24442. 'direction': 'left'
  24443. };
  24444. this.prev_pageX = ev.pageX;
  24445. },
  24446. onStartDiagonalResize: function onStartDiagonalResize(ev) {
  24447. var _converse = this.__super__._converse;
  24448. this.onStartHorizontalResize(ev);
  24449. this.onStartVerticalResize(ev);
  24450. _converse.resizing.direction = 'topleft';
  24451. },
  24452. resizeChatBox: function resizeChatBox(ev) {
  24453. var diff;
  24454. var _converse = this.__super__._converse;
  24455. if (_converse.resizing.direction.indexOf('top') === 0) {
  24456. diff = ev.pageY - this.prev_pageY;
  24457. if (diff) {
  24458. this.height = this.height - diff > (this.model.get('min_height') || 0) ? this.height - diff : this.model.get('min_height');
  24459. this.prev_pageY = ev.pageY;
  24460. this.setChatBoxHeight(this.height);
  24461. }
  24462. }
  24463. if (_.includes(_converse.resizing.direction, 'left')) {
  24464. diff = this.prev_pageX - ev.pageX;
  24465. if (diff) {
  24466. this.width = this.width + diff > (this.model.get('min_width') || 0) ? this.width + diff : this.model.get('min_width');
  24467. this.prev_pageX = ev.pageX;
  24468. this.setChatBoxWidth(this.width);
  24469. }
  24470. }
  24471. }
  24472. },
  24473. HeadlinesBoxView: {
  24474. events: {
  24475. 'mousedown .dragresize-top': 'onStartVerticalResize',
  24476. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  24477. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  24478. },
  24479. initialize: function initialize() {
  24480. window.addEventListener('resize', _.debounce(this.setDimensions.bind(this), 100));
  24481. return this.__super__.initialize.apply(this, arguments);
  24482. },
  24483. render: function render() {
  24484. var result = this.__super__.render.apply(this, arguments);
  24485. renderDragResizeHandles(this.__super__._converse, this);
  24486. this.setWidth();
  24487. return result;
  24488. }
  24489. },
  24490. ControlBoxView: {
  24491. events: {
  24492. 'mousedown .dragresize-top': 'onStartVerticalResize',
  24493. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  24494. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  24495. },
  24496. initialize: function initialize() {
  24497. window.addEventListener('resize', _.debounce(this.setDimensions.bind(this), 100));
  24498. this.__super__.initialize.apply(this, arguments);
  24499. },
  24500. render: function render() {
  24501. var result = this.__super__.render.apply(this, arguments);
  24502. renderDragResizeHandles(this.__super__._converse, this);
  24503. this.setWidth();
  24504. return result;
  24505. },
  24506. renderLoginPanel: function renderLoginPanel() {
  24507. var result = this.__super__.renderLoginPanel.apply(this, arguments);
  24508. this.initDragResize().setDimensions();
  24509. return result;
  24510. },
  24511. renderControlBoxPane: function renderControlBoxPane() {
  24512. var result = this.__super__.renderControlBoxPane.apply(this, arguments);
  24513. this.initDragResize().setDimensions();
  24514. return result;
  24515. }
  24516. },
  24517. ChatRoomView: {
  24518. events: {
  24519. 'mousedown .dragresize-top': 'onStartVerticalResize',
  24520. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  24521. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  24522. },
  24523. initialize: function initialize() {
  24524. window.addEventListener('resize', _.debounce(this.setDimensions.bind(this), 100));
  24525. this.__super__.initialize.apply(this, arguments);
  24526. },
  24527. render: function render() {
  24528. var result = this.__super__.render.apply(this, arguments);
  24529. renderDragResizeHandles(this.__super__._converse, this);
  24530. this.setWidth();
  24531. return result;
  24532. }
  24533. }
  24534. },
  24535. initialize: function initialize() {
  24536. /* The initialize function gets called as soon as the plugin is
  24537. * loaded by converse.js's plugin machinery.
  24538. */
  24539. var _converse = this._converse;
  24540. _converse.api.settings.update({
  24541. allow_dragresize: true
  24542. });
  24543. _converse.applyDragResistance = function (value, default_value) {
  24544. /* This method applies some resistance around the
  24545. * default_value. If value is close enough to
  24546. * default_value, then default_value is returned instead.
  24547. */
  24548. if (_.isUndefined(value)) {
  24549. return undefined;
  24550. } else if (_.isUndefined(default_value)) {
  24551. return value;
  24552. }
  24553. var resistance = 10;
  24554. if (value !== default_value && Math.abs(value - default_value) < resistance) {
  24555. return default_value;
  24556. }
  24557. return value;
  24558. };
  24559. }
  24560. });
  24561. });
  24562. //# sourceMappingURL=converse-dragresize.js.map;
  24563. // Converse.js (A browser based XMPP chat client)
  24564. // http://conversejs.org
  24565. //
  24566. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  24567. // Licensed under the Mozilla Public License (MPLv2)
  24568. //
  24569. /*global define */
  24570. (function (root, factory) {
  24571. define('converse-headline',["converse-core", "tpl!chatbox", "converse-chatview"], factory);
  24572. })(void 0, function (converse, tpl_chatbox) {
  24573. "use strict";
  24574. var _converse$env = converse.env,
  24575. _ = _converse$env._,
  24576. utils = _converse$env.utils;
  24577. var HEADLINES_TYPE = 'headline';
  24578. converse.plugins.add('converse-headline', {
  24579. /* Plugin dependencies are other plugins which might be
  24580. * overridden or relied upon, and therefore need to be loaded before
  24581. * this plugin.
  24582. *
  24583. * If the setting "strict_plugin_dependencies" is set to true,
  24584. * an error will be raised if the plugin is not found. By default it's
  24585. * false, which means these plugins are only loaded opportunistically.
  24586. *
  24587. * NB: These plugins need to have already been loaded via require.js.
  24588. */
  24589. dependencies: ["converse-chatview"],
  24590. overrides: {
  24591. // Overrides mentioned here will be picked up by converse.js's
  24592. // plugin architecture they will replace existing methods on the
  24593. // relevant objects or classes.
  24594. //
  24595. // New functions which don't exist yet can also be added.
  24596. ChatBoxes: {
  24597. model: function model(attrs, options) {
  24598. var _converse = this.__super__._converse;
  24599. if (attrs.type == HEADLINES_TYPE) {
  24600. return new _converse.HeadlinesBox(attrs, options);
  24601. } else {
  24602. return this.__super__.model.apply(this, arguments);
  24603. }
  24604. }
  24605. },
  24606. ChatBoxViews: {
  24607. onChatBoxAdded: function onChatBoxAdded(item) {
  24608. var _converse = this.__super__._converse;
  24609. var view = this.get(item.get('id'));
  24610. if (!view && item.get('type') === 'headline') {
  24611. view = new _converse.HeadlinesBoxView({
  24612. model: item
  24613. });
  24614. this.add(item.get('id'), view);
  24615. return view;
  24616. } else {
  24617. return this.__super__.onChatBoxAdded.apply(this, arguments);
  24618. }
  24619. }
  24620. }
  24621. },
  24622. initialize: function initialize() {
  24623. /* The initialize function gets called as soon as the plugin is
  24624. * loaded by converse.js's plugin machinery.
  24625. */
  24626. var _converse = this._converse,
  24627. __ = _converse.__;
  24628. _converse.HeadlinesBox = _converse.ChatBox.extend({
  24629. defaults: {
  24630. 'type': 'headline',
  24631. 'show_avatar': false,
  24632. 'bookmarked': false,
  24633. 'chat_state': undefined,
  24634. 'num_unread': 0,
  24635. 'url': ''
  24636. }
  24637. });
  24638. _converse.HeadlinesBoxView = _converse.ChatBoxView.extend({
  24639. className: 'chatbox headlines',
  24640. events: {
  24641. 'click .close-chatbox-button': 'close',
  24642. 'click .toggle-chatbox-button': 'minimize',
  24643. 'keypress textarea.chat-textarea': 'keyPressed'
  24644. },
  24645. initialize: function initialize() {
  24646. this.scrollDown = _.debounce(this._scrollDown, 250);
  24647. this.markScrolled = _.debounce(this._markScrolled, 100);
  24648. this.disable_mam = true; // Don't do MAM queries for this box
  24649. this.model.messages.on('add', this.onMessageAdded, this);
  24650. this.model.on('show', this.show, this);
  24651. this.model.on('destroy', this.hide, this);
  24652. this.model.on('change:minimized', this.onMinimizedChanged, this);
  24653. this.render().insertHeading().fetchMessages().insertIntoDOM().hide();
  24654. _converse.emit('chatBoxOpened', this);
  24655. _converse.emit('chatBoxInitialized', this);
  24656. },
  24657. render: function render() {
  24658. this.el.setAttribute('id', this.model.get('box_id'));
  24659. this.el.innerHTML = tpl_chatbox(_.extend(this.model.toJSON(), {
  24660. info_close: '',
  24661. label_personal_message: '',
  24662. show_send_button: false,
  24663. show_toolbar: false,
  24664. unread_msgs: ''
  24665. }));
  24666. this.content = this.el.querySelector('.chat-content');
  24667. return this;
  24668. },
  24669. // Override to avoid the methods in converse-chatview.js
  24670. 'renderMessageForm': _.noop,
  24671. 'afterShown': _.noop
  24672. });
  24673. function onHeadlineMessage(message) {
  24674. /* Handler method for all incoming messages of type "headline". */
  24675. var from_jid = message.getAttribute('from');
  24676. if (utils.isHeadlineMessage(_converse, message)) {
  24677. if (_.includes(from_jid, '@') && !_converse.allow_non_roster_messaging) {
  24678. return;
  24679. }
  24680. var chatbox = _converse.chatboxes.create({
  24681. 'id': from_jid,
  24682. 'jid': from_jid,
  24683. 'fullname': from_jid,
  24684. 'type': 'headline'
  24685. });
  24686. chatbox.createMessage(message, undefined, message);
  24687. _converse.emit('message', {
  24688. 'chatbox': chatbox,
  24689. 'stanza': message
  24690. });
  24691. }
  24692. return true;
  24693. }
  24694. function registerHeadlineHandler() {
  24695. _converse.connection.addHandler(onHeadlineMessage, null, 'message');
  24696. }
  24697. _converse.on('connected', registerHeadlineHandler);
  24698. _converse.on('reconnected', registerHeadlineHandler);
  24699. }
  24700. });
  24701. });
  24702. //# sourceMappingURL=converse-headline.js.map;
  24703. define('tpl!inverse_brand_heading', ['lodash'], function(_) {return function(o) {
  24704. var __t, __p = '';
  24705. __p += '<div class="row">\n <div class="container brand-heading-container">\n <h1 class="brand-heading"><i class="icon-conversejs"></i>inVerse</h1>\n <p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://conversejs.org">Open Source</a> XMPP chat client</p>\n <p class="brand-subtitle"><a target="_blank" rel="nofollow" href="https://hosted.weblate.org/projects/conversejs/#languages">Translate</a> into your own language</p>\n <div>\n</div>\n';
  24706. return __p
  24707. };});
  24708. // Converse.js (A browser based XMPP chat client)
  24709. // http://conversejs.org
  24710. //
  24711. // Copyright (c) 2012-2017, JC Brand <jc@opkode.com>
  24712. // Licensed under the Mozilla Public License (MPLv2)
  24713. //
  24714. /*global Backbone, define, window, JSON */
  24715. /* converse-singleton
  24716. * ******************
  24717. *
  24718. * A plugin which ensures that only one chat (private or groupchat) is
  24719. * visible at any one time. All other ongoing chats are hidden and kept in the
  24720. * background.
  24721. *
  24722. * This plugin makes sense in mobile or fullscreen chat environments (as
  24723. * configured by the `view_mode` setting).
  24724. *
  24725. */
  24726. (function (root, factory) {
  24727. define('converse-singleton',["converse-core", "converse-chatview"], factory);
  24728. })(void 0, function (converse) {
  24729. "use strict";
  24730. var _converse$env = converse.env,
  24731. _ = _converse$env._,
  24732. Strophe = _converse$env.Strophe;
  24733. function hideChat(view) {
  24734. if (view.model.get('id') === 'controlbox') {
  24735. return;
  24736. }
  24737. view.model.save({
  24738. 'hidden': true
  24739. });
  24740. view.hide();
  24741. }
  24742. converse.plugins.add('converse-singleton', {
  24743. // It's possible however to make optional dependencies non-optional.
  24744. // If the setting "strict_plugin_dependencies" is set to true,
  24745. // an error will be raised if the plugin is not found.
  24746. //
  24747. // NB: These plugins need to have already been loaded via require.js.
  24748. dependencies: ['converse-chatboxes', 'converse-muc', 'converse-controlbox', 'converse-rosterview'],
  24749. enabled: function enabled(_converse) {
  24750. return _.includes(['mobile', 'fullscreen', 'embedded'], _converse.view_mode);
  24751. },
  24752. overrides: {
  24753. // overrides mentioned here will be picked up by converse.js's
  24754. // plugin architecture they will replace existing methods on the
  24755. // relevant objects or classes.
  24756. //
  24757. // new functions which don't exist yet can also be added.
  24758. ChatBoxes: {
  24759. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  24760. return !chatbox.get('hidden');
  24761. },
  24762. createChatBox: function createChatBox(jid, attrs) {
  24763. /* Make sure new chat boxes are hidden by default. */
  24764. attrs = attrs || {};
  24765. attrs.hidden = true;
  24766. return this.__super__.createChatBox.call(this, jid, attrs);
  24767. }
  24768. },
  24769. ChatBoxView: {
  24770. shouldShowOnTextMessage: function shouldShowOnTextMessage() {
  24771. return false;
  24772. },
  24773. _show: function _show(focus) {
  24774. /* We only have one chat visible at any one
  24775. * time. So before opening a chat, we make sure all other
  24776. * chats are hidden.
  24777. */
  24778. _.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
  24779. this.model.set('hidden', false);
  24780. return this.__super__._show.apply(this, arguments);
  24781. }
  24782. },
  24783. ChatRoomView: {
  24784. show: function show(focus) {
  24785. _.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
  24786. this.model.set('hidden', false);
  24787. return this.__super__.show.apply(this, arguments);
  24788. }
  24789. }
  24790. }
  24791. });
  24792. });
  24793. //# sourceMappingURL=converse-singleton.js.map;
  24794. // Converse.js (A browser based XMPP chat client)
  24795. // http://conversejs.org
  24796. //
  24797. // Copyright (c) JC Brand <jc@opkode.com>
  24798. // Licensed under the Mozilla Public License (MPLv2)
  24799. //
  24800. /*global define */
  24801. (function (root, factory) {
  24802. define('converse-fullscreen',["converse-core", "tpl!inverse_brand_heading", "converse-chatview", "converse-controlbox", "converse-muc", "converse-singleton"], factory);
  24803. })(void 0, function (converse, tpl_brand_heading) {
  24804. "use strict";
  24805. var _converse$env = converse.env,
  24806. Strophe = _converse$env.Strophe,
  24807. _ = _converse$env._;
  24808. converse.plugins.add('converse-fullscreen', {
  24809. enabled: function enabled(_converse) {
  24810. return _.includes(['fullscreen', 'embedded'], _converse.view_mode);
  24811. },
  24812. overrides: {
  24813. // overrides mentioned here will be picked up by converse.js's
  24814. // plugin architecture they will replace existing methods on the
  24815. // relevant objects or classes.
  24816. //
  24817. // new functions which don't exist yet can also be added.
  24818. ControlBoxView: {
  24819. createBrandHeadingHTML: function createBrandHeadingHTML() {
  24820. return tpl_brand_heading();
  24821. },
  24822. insertBrandHeading: function insertBrandHeading() {
  24823. var _converse = this.__super__._converse;
  24824. var el = _converse.root.getElementById('converse-login-panel');
  24825. el.parentNode.insertAdjacentHTML('afterbegin', this.createBrandHeadingHTML());
  24826. }
  24827. }
  24828. },
  24829. initialize: function initialize() {
  24830. this._converse.api.settings.update({
  24831. chatview_avatar_height: 50,
  24832. chatview_avatar_width: 50,
  24833. hide_open_bookmarks: true,
  24834. show_controlbox_by_default: true,
  24835. sticky_controlbox: true
  24836. });
  24837. }
  24838. });
  24839. });
  24840. //# sourceMappingURL=converse-fullscreen.js.map;
  24841. /*global define */
  24842. if (typeof define !== 'undefined') {
  24843. // The section below determines which plugins will be included in a build
  24844. define('converse',[
  24845. "converse-core",
  24846. /* START: Removable components
  24847. * --------------------
  24848. * Any of the following components may be removed if they're not needed.
  24849. */
  24850. "converse-chatview", // Renders standalone chat boxes for single user chat
  24851. "converse-controlbox", // The control box
  24852. "converse-bookmarks", // XEP-0048 Bookmarks
  24853. "converse-roomslist", // Show currently open chat rooms
  24854. "converse-mam", // XEP-0313 Message Archive Management
  24855. "converse-muc", // XEP-0045 Multi-user chat
  24856. "converse-muc-views", // Views related to MUC
  24857. "converse-muc-embedded",
  24858. "converse-muc-views",
  24859. "converse-vcard", // XEP-0054 VCard-temp
  24860. "converse-otr", // Off-the-record encryption for one-on-one messages
  24861. "converse-register", // XEP-0077 In-band registration
  24862. "converse-ping", // XEP-0199 XMPP Ping
  24863. "converse-notification",// HTML5 Notifications
  24864. "converse-minimize", // Allows chat boxes to be minimized
  24865. "converse-dragresize", // Allows chat boxes to be resized by dragging them
  24866. "converse-headline", // Support for headline messages
  24867. "converse-fullscreen"
  24868. /* END: Removable components */
  24869. ], function (converse) {
  24870. return converse;
  24871. });
  24872. }
  24873. ;
  24874. define('awesomplete', [], function () { return Awesomplete; });
  24875. define('lodash', [], function () { return _; });
  24876. define('underscore', [], function () { return _; });
  24877. define('lodash.converter', [], function () { return fp; });
  24878. define('lodash.noconflict', [], function () { return _; });
  24879. define('moment', [], function () { return moment; });
  24880. define('moment/locale/af', [], function () { return moment; });
  24881. define('moment/locale/ca', [], function () { return moment; });
  24882. define('moment/locale/de', [], function () { return moment; });
  24883. define('moment/locale/es', [], function () { return moment; });
  24884. define('moment/locale/fr', [], function () { return moment; });
  24885. define('moment/locale/he', [], function () { return moment; });
  24886. define('moment/locale/hu', [], function () { return moment; });
  24887. define('moment/locale/id', [], function () { return moment; });
  24888. define('moment/locale/it', [], function () { return moment; });
  24889. define('moment/locale/ja', [], function () { return moment; });
  24890. define('moment/locale/nb', [], function () { return moment; });
  24891. define('moment/locale/nl', [], function () { return moment; });
  24892. define('moment/locale/pl', [], function () { return moment; });
  24893. define('moment/locale/pt-br', [], function () { return moment; });
  24894. define('moment/locale/ru', [], function () { return moment; });
  24895. define('moment/locale/uk', [], function () { return moment; });
  24896. define('moment/moment', [], function () { return moment; });
  24897. define('i18n', [], function () { return; });
  24898. define('es6-promise', [], function () { return Promise; });
  24899. define('strophe', [], function () {
  24900. return {
  24901. 'Strophe': Strophe,
  24902. '$build': $build,
  24903. '$iq': $iq,
  24904. '$msg': $msg,
  24905. '$pres': $pres,
  24906. 'SHA1': SHA1,
  24907. 'MD5': MD5,
  24908. 'b64_hmac_sha1': SHA1.b64_hmac_sha1,
  24909. 'b64_sha1': SHA1.b64_sha1,
  24910. 'str_hmac_sha1': SHA1.str_hmac_sha1,
  24911. 'str_sha1': SHA1.str_sha1
  24912. };
  24913. });
  24914. var strophePlugin = function () { return Strophe; };
  24915. var emptyFunction = function () { };
  24916. define('strophe.disco', ['strophe'], strophePlugin);
  24917. define('strophe.ping', ['strophe'], strophePlugin);
  24918. define('strophe.rsm', ['strophe'], strophePlugin);
  24919. define('strophe.vcard', ['strophe'], strophePlugin);
  24920. define('backbone', [], function () { return Backbone; });
  24921. define('backbone.noconflict', [], function () { return Backbone; });
  24922. define('backbone.browserStorage', ['backbone'], emptyFunction);
  24923. define('backbone.overview', ['backbone'], emptyFunction);
  24924. define('otr', [], function () { return { 'DSA': DSA, 'OTR': OTR };});
  24925. return require('converse');
  24926. }));