| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626 |
- (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){
- (function (global){
- /*
- * Copyright (c) 2012-2013 Chris Pettitt
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- graphlibDot = require("./index");
- graphlibDot.graphlib = require("graphlib");
- global.graphlibDot = graphlibDot;
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
- },{"./index":2,"graphlib":9}],2:[function(require,module,exports){
- var read = require("./lib/read-one"),
- readMany = require("./lib/read-many"),
- write = require("./lib/write-one"),
- version = require("./lib/version");
- module.exports = {
- // Parsing
- read: read,
- readMany: readMany,
- // Writing
- write: write,
- // Version
- version: version,
- // For levelup encoding
- type: "dot",
- buffer: false
- };
- },{"./lib/read-many":5,"./lib/read-one":6,"./lib/version":7,"./lib/write-one":8}],3:[function(require,module,exports){
- "use strict";
- var _ = require("lodash"),
- Graph = require("graphlib").Graph;
- module.exports = buildGraph;
- function buildGraph(parseTree) {
- var isDirected = parseTree.type !== "graph",
- isMultigraph = !parseTree.strict,
- defaultStack = [{ node: {}, edge: {} }],
- g = new Graph({ directed: isDirected, multigraph: isMultigraph, compound: true });
- g.setGraph({});
- _.each(parseTree.stmts, function(stmt) { handleStmt(g, stmt, defaultStack); });
- return g;
- }
- function handleStmt(g, stmt, defaultStack, sg) {
- switch(stmt.type) {
- case "node": handleNodeStmt(g, stmt, defaultStack, sg); break;
- case "edge": handleEdgeStmt(g, stmt, defaultStack, sg); break;
- case "subgraph": handleSubgraphStmt(g, stmt, defaultStack, sg); break;
- case "attr": handleAttrStmt(g, stmt, defaultStack); break;
- case "inlineAttr": handleInlineAttrsStmt(g, stmt, defaultStack, sg); break;
- }
- }
- function handleNodeStmt(g, stmt, defaultStack, sg) {
- var v = stmt.id,
- attrs = stmt.attrs;
- maybeCreateNode(g, v, defaultStack, sg);
- _.merge(g.node(v), attrs);
- }
- function handleEdgeStmt(g, stmt, defaultStack, sg) {
- var attrs = stmt.attrs,
- prev, curr;
- _.each(stmt.elems, function(elem) {
- handleStmt(g, elem, defaultStack, sg);
- switch(elem.type) {
- case "node": curr = [elem.id]; break;
- case "subgraph": curr = collectNodeIds(elem); break;
- }
- _.each(prev, function(v) {
- _.each(curr, function(w) {
- var name;
- if (g.hasEdge(v, w) && g.isMultigraph()) {
- name = _.uniqueId("edge");
- }
- if (!g.hasEdge(v, w, name)) {
- g.setEdge(v, w, _.clone(_.last(defaultStack).edge), name);
- }
- _.merge(g.edge(v, w, name), attrs);
- });
- });
- prev = curr;
- });
- }
- function handleSubgraphStmt(g, stmt, defaultStack, sg) {
- var id = stmt.id;
- if (id === undefined) {
- id = generateSubgraphId(g);
- }
- defaultStack.push(_.clone(_.last(defaultStack)));
- maybeCreateNode(g, id, defaultStack, sg);
- _.each(stmt.stmts, function(s) {
- handleStmt(g, s, defaultStack, id);
- });
- // If there are no statements remove the subgraph
- if (!g.children(id).length) {
- g.removeNode(id);
- }
- defaultStack.pop();
- }
- function handleAttrStmt(g, stmt, defaultStack) {
- _.merge(_.last(defaultStack)[stmt.attrType], stmt.attrs);
- }
- function handleInlineAttrsStmt(g, stmt, defaultStack, sg) {
- _.merge(sg ? g.node(sg) : g.graph(), stmt.attrs);
- }
- function generateSubgraphId(g) {
- var id;
- do {
- id = _.uniqueId("sg");
- } while (g.hasNode(id));
- return id;
- }
- function maybeCreateNode(g, v, defaultStack, sg) {
- if (!g.hasNode(v)) {
- g.setNode(v, _.clone(_.last(defaultStack).node));
- g.setParent(v, sg);
- }
- }
- // Collect all nodes involved in a subgraph statement
- function collectNodeIds(stmt) {
- var ids = {},
- stack = [],
- curr;
- var push = stack.push.bind(stack);
- push(stmt);
- while(stack.length) {
- curr = stack.pop();
- switch(curr.type) {
- case "node": ids[curr.id] = true; break;
- case "edge": _.each(curr.elems, push); break;
- case "subgraph": _.each(curr.stmts, push); break;
- }
- }
- return _.keys(ids);
- }
- },{"graphlib":9,"lodash":28}],4:[function(require,module,exports){
- module.exports = (function() {
- /*
- * Generated by PEG.js 0.8.0.
- *
- * http://pegjs.majda.cz/
- */
- function peg$subclass(child, parent) {
- function ctor() { this.constructor = child; }
- ctor.prototype = parent.prototype;
- child.prototype = new ctor();
- }
- function SyntaxError(message, expected, found, offset, line, column) {
- this.message = message;
- this.expected = expected;
- this.found = found;
- this.offset = offset;
- this.line = line;
- this.column = column;
- this.name = "SyntaxError";
- }
- peg$subclass(SyntaxError, Error);
- function parse(input) {
- var options = arguments.length > 1 ? arguments[1] : {},
- peg$FAILED = {},
- peg$startRuleFunctions = { start: peg$parsestart, graphStmt: peg$parsegraphStmt },
- peg$startRuleFunction = peg$parsestart,
- peg$c0 = [],
- peg$c1 = peg$FAILED,
- peg$c2 = null,
- peg$c3 = "{",
- peg$c4 = { type: "literal", value: "{", description: "\"{\"" },
- peg$c5 = "}",
- peg$c6 = { type: "literal", value: "}", description: "\"}\"" },
- peg$c7 = function(strict, type, id, stmts) {
- return {type: type, id: id, strict: strict !== null, stmts: stmts};
- },
- peg$c8 = ";",
- peg$c9 = { type: "literal", value: ";", description: "\";\"" },
- peg$c10 = function(first, rest) {
- var result = [first];
- for (var i = 0; i < rest.length; ++i) {
- result.push(rest[i][1]);
- }
- return result;
- },
- peg$c11 = function(type, attrs) {
- return { type: "attr", attrType: type, attrs: attrs || {}};
- },
- peg$c12 = "=",
- peg$c13 = { type: "literal", value: "=", description: "\"=\"" },
- peg$c14 = function(k, v) {
- var attrs = {};
- attrs[k] = v;
- return { type: "inlineAttr", attrs: attrs };
- },
- peg$c15 = function(id, attrs) { return {type: "node", id: id, attrs: attrs || {}}; },
- peg$c16 = function(lhs, rhs, attrs) {
- var elems = [lhs];
- for (var i = 0; i < rhs.length; ++i) {
- elems.push(rhs[i]);
- }
- return { type: "edge", elems: elems, attrs: attrs || {} };
- },
- peg$c17 = function(id, stmts) {
- id = (id && id[2]) || [];
- return { type: "subgraph", id: id[0], stmts: stmts };
- },
- peg$c18 = function(first, rest) {
- var result = first;
- for (var i = 0; i < rest.length; ++i) {
- _.merge(result, rest[i][1]);
- }
- return result;
- },
- peg$c19 = "[",
- peg$c20 = { type: "literal", value: "[", description: "\"[\"" },
- peg$c21 = "]",
- peg$c22 = { type: "literal", value: "]", description: "\"]\"" },
- peg$c23 = function(aList) { return aList; },
- peg$c24 = ",",
- peg$c25 = { type: "literal", value: ",", description: "\",\"" },
- peg$c26 = function(first, rest) {
- var result = first;
- for (var i = 0; i < rest.length; ++i) {
- _.merge(result, rest[i][3]);
- }
- return result;
- },
- peg$c27 = "--",
- peg$c28 = { type: "literal", value: "--", description: "\"--\"" },
- peg$c29 = function() { return directed; },
- peg$c30 = void 0,
- peg$c31 = "->",
- peg$c32 = { type: "literal", value: "->", description: "\"->\"" },
- peg$c33 = function(rhs, rest) {
- var result = [rhs];
- if (rest) {
- for (var i = 0; i < rest.length; ++i) {
- result.push(rest[i]);
- }
- }
- return result;
- },
- peg$c34 = function(k, v) {
- var result = {};
- result[k] = v[3];
- return result;
- },
- peg$c35 = function(id) { return { type: "node", id: id, attrs: {} }; },
- peg$c36 = function(id) { return id; },
- peg$c37 = ":",
- peg$c38 = { type: "literal", value: ":", description: "\":\"" },
- peg$c39 = "ne",
- peg$c40 = { type: "literal", value: "ne", description: "\"ne\"" },
- peg$c41 = "se",
- peg$c42 = { type: "literal", value: "se", description: "\"se\"" },
- peg$c43 = "sw",
- peg$c44 = { type: "literal", value: "sw", description: "\"sw\"" },
- peg$c45 = "nw",
- peg$c46 = { type: "literal", value: "nw", description: "\"nw\"" },
- peg$c47 = "n",
- peg$c48 = { type: "literal", value: "n", description: "\"n\"" },
- peg$c49 = "e",
- peg$c50 = { type: "literal", value: "e", description: "\"e\"" },
- peg$c51 = "s",
- peg$c52 = { type: "literal", value: "s", description: "\"s\"" },
- peg$c53 = "w",
- peg$c54 = { type: "literal", value: "w", description: "\"w\"" },
- peg$c55 = "c",
- peg$c56 = { type: "literal", value: "c", description: "\"c\"" },
- peg$c57 = "_",
- peg$c58 = { type: "literal", value: "_", description: "\"_\"" },
- peg$c59 = { type: "other", description: "identifier" },
- peg$c60 = /^[a-zA-Z\u0200-\u0377_]/,
- peg$c61 = { type: "class", value: "[a-zA-Z\\u0200-\\u0377_]", description: "[a-zA-Z\\u0200-\\u0377_]" },
- peg$c62 = /^[a-zA-Z\u0200-\u0377_0-9]/,
- peg$c63 = { type: "class", value: "[a-zA-Z\\u0200-\\u0377_0-9]", description: "[a-zA-Z\\u0200-\\u0377_0-9]" },
- peg$c64 = function(fst, rest) { return fst + rest.join(""); },
- peg$c65 = "-",
- peg$c66 = { type: "literal", value: "-", description: "\"-\"" },
- peg$c67 = ".",
- peg$c68 = { type: "literal", value: ".", description: "\".\"" },
- peg$c69 = /^[0-9]/,
- peg$c70 = { type: "class", value: "[0-9]", description: "[0-9]" },
- peg$c71 = function(sign, dot, after) {
- return (sign || "") + dot + after.join("");
- },
- peg$c72 = function(sign, before, after) {
- return (sign || "") + before.join("") + (after ? after[0] : "") + (after ? after[1].join("") : "");
- },
- peg$c73 = "\"",
- peg$c74 = { type: "literal", value: "\"", description: "\"\\\"\"" },
- peg$c75 = "\\\"",
- peg$c76 = { type: "literal", value: "\\\"", description: "\"\\\\\\\"\"" },
- peg$c77 = function() { return '"'; },
- peg$c78 = "\\",
- peg$c79 = { type: "literal", value: "\\", description: "\"\\\\\"" },
- peg$c80 = /^[^"]/,
- peg$c81 = { type: "class", value: "[^\"]", description: "[^\"]" },
- peg$c82 = function(ch) { return "\\" + ch; },
- peg$c83 = function(id) {
- return id.join("");
- },
- peg$c84 = "node",
- peg$c85 = { type: "literal", value: "node", description: "\"node\"" },
- peg$c86 = function(k) { return k.toLowerCase(); },
- peg$c87 = "edge",
- peg$c88 = { type: "literal", value: "edge", description: "\"edge\"" },
- peg$c89 = "graph",
- peg$c90 = { type: "literal", value: "graph", description: "\"graph\"" },
- peg$c91 = "digraph",
- peg$c92 = { type: "literal", value: "digraph", description: "\"digraph\"" },
- peg$c93 = "subgraph",
- peg$c94 = { type: "literal", value: "subgraph", description: "\"subgraph\"" },
- peg$c95 = "strict",
- peg$c96 = { type: "literal", value: "strict", description: "\"strict\"" },
- peg$c97 = function(graph) {
- directed = graph === "digraph";
- return graph;
- },
- peg$c98 = { type: "other", description: "whitespace" },
- peg$c99 = /^[ \t\r\n]/,
- peg$c100 = { type: "class", value: "[ \\t\\r\\n]", description: "[ \\t\\r\\n]" },
- peg$c101 = { type: "other", description: "comment" },
- peg$c102 = "//",
- peg$c103 = { type: "literal", value: "//", description: "\"//\"" },
- peg$c104 = /^[^\n]/,
- peg$c105 = { type: "class", value: "[^\\n]", description: "[^\\n]" },
- peg$c106 = "/*",
- peg$c107 = { type: "literal", value: "/*", description: "\"/*\"" },
- peg$c108 = "*/",
- peg$c109 = { type: "literal", value: "*/", description: "\"*/\"" },
- peg$c110 = { type: "any", description: "any character" },
- peg$currPos = 0,
- peg$reportedPos = 0,
- peg$cachedPos = 0,
- peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },
- peg$maxFailPos = 0,
- peg$maxFailExpected = [],
- peg$silentFails = 0,
- peg$result;
- if ("startRule" in options) {
- if (!(options.startRule in peg$startRuleFunctions)) {
- throw new Error("Can't start parsing from rule \"" + options.startRule + "\".");
- }
- peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
- }
- function text() {
- return input.substring(peg$reportedPos, peg$currPos);
- }
- function offset() {
- return peg$reportedPos;
- }
- function line() {
- return peg$computePosDetails(peg$reportedPos).line;
- }
- function column() {
- return peg$computePosDetails(peg$reportedPos).column;
- }
- function expected(description) {
- throw peg$buildException(
- null,
- [{ type: "other", description: description }],
- peg$reportedPos
- );
- }
- function error(message) {
- throw peg$buildException(message, null, peg$reportedPos);
- }
- function peg$computePosDetails(pos) {
- function advance(details, startPos, endPos) {
- var p, ch;
- for (p = startPos; p < endPos; p++) {
- ch = input.charAt(p);
- if (ch === "\n") {
- if (!details.seenCR) { details.line++; }
- details.column = 1;
- details.seenCR = false;
- } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") {
- details.line++;
- details.column = 1;
- details.seenCR = true;
- } else {
- details.column++;
- details.seenCR = false;
- }
- }
- }
- if (peg$cachedPos !== pos) {
- if (peg$cachedPos > pos) {
- peg$cachedPos = 0;
- peg$cachedPosDetails = { line: 1, column: 1, seenCR: false };
- }
- advance(peg$cachedPosDetails, peg$cachedPos, pos);
- peg$cachedPos = pos;
- }
- return peg$cachedPosDetails;
- }
- function peg$fail(expected) {
- if (peg$currPos < peg$maxFailPos) { return; }
- if (peg$currPos > peg$maxFailPos) {
- peg$maxFailPos = peg$currPos;
- peg$maxFailExpected = [];
- }
- peg$maxFailExpected.push(expected);
- }
- function peg$buildException(message, expected, pos) {
- function cleanupExpected(expected) {
- var i = 1;
- expected.sort(function(a, b) {
- if (a.description < b.description) {
- return -1;
- } else if (a.description > b.description) {
- return 1;
- } else {
- return 0;
- }
- });
- while (i < expected.length) {
- if (expected[i - 1] === expected[i]) {
- expected.splice(i, 1);
- } else {
- i++;
- }
- }
- }
- function buildMessage(expected, found) {
- function stringEscape(s) {
- function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
- return s
- .replace(/\\/g, '\\\\')
- .replace(/"/g, '\\"')
- .replace(/\x08/g, '\\b')
- .replace(/\t/g, '\\t')
- .replace(/\n/g, '\\n')
- .replace(/\f/g, '\\f')
- .replace(/\r/g, '\\r')
- .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
- .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
- .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
- .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
- }
- var expectedDescs = new Array(expected.length),
- expectedDesc, foundDesc, i;
- for (i = 0; i < expected.length; i++) {
- expectedDescs[i] = expected[i].description;
- }
- expectedDesc = expected.length > 1
- ? expectedDescs.slice(0, -1).join(", ")
- + " or "
- + expectedDescs[expected.length - 1]
- : expectedDescs[0];
- foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input";
- return "Expected " + expectedDesc + " but " + foundDesc + " found.";
- }
- var posDetails = peg$computePosDetails(pos),
- found = pos < input.length ? input.charAt(pos) : null;
- if (expected !== null) {
- cleanupExpected(expected);
- }
- return new SyntaxError(
- message !== null ? message : buildMessage(expected, found),
- expected,
- found,
- pos,
- posDetails.line,
- posDetails.column
- );
- }
- function peg$parsestart() {
- var s0, s1;
- s0 = [];
- s1 = peg$parsegraphStmt();
- if (s1 !== peg$FAILED) {
- while (s1 !== peg$FAILED) {
- s0.push(s1);
- s1 = peg$parsegraphStmt();
- }
- } else {
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsegraphStmt() {
- var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13;
- s0 = peg$currPos;
- s1 = [];
- s2 = peg$parse_();
- while (s2 !== peg$FAILED) {
- s1.push(s2);
- s2 = peg$parse_();
- }
- if (s1 !== peg$FAILED) {
- s2 = peg$currPos;
- s3 = peg$parsestrict();
- if (s3 !== peg$FAILED) {
- s4 = peg$parse_();
- if (s4 !== peg$FAILED) {
- s3 = [s3, s4];
- s2 = s3;
- } else {
- peg$currPos = s2;
- s2 = peg$c1;
- }
- } else {
- peg$currPos = s2;
- s2 = peg$c1;
- }
- if (s2 === peg$FAILED) {
- s2 = peg$c2;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parsegraphType();
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$parseid();
- if (s5 === peg$FAILED) {
- s5 = peg$c2;
- }
- if (s5 !== peg$FAILED) {
- s6 = [];
- s7 = peg$parse_();
- while (s7 !== peg$FAILED) {
- s6.push(s7);
- s7 = peg$parse_();
- }
- if (s6 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 123) {
- s7 = peg$c3;
- peg$currPos++;
- } else {
- s7 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c4); }
- }
- if (s7 !== peg$FAILED) {
- s8 = [];
- s9 = peg$parse_();
- while (s9 !== peg$FAILED) {
- s8.push(s9);
- s9 = peg$parse_();
- }
- if (s8 !== peg$FAILED) {
- s9 = peg$parsestmtList();
- if (s9 === peg$FAILED) {
- s9 = peg$c2;
- }
- if (s9 !== peg$FAILED) {
- s10 = [];
- s11 = peg$parse_();
- while (s11 !== peg$FAILED) {
- s10.push(s11);
- s11 = peg$parse_();
- }
- if (s10 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 125) {
- s11 = peg$c5;
- peg$currPos++;
- } else {
- s11 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c6); }
- }
- if (s11 !== peg$FAILED) {
- s12 = [];
- s13 = peg$parse_();
- while (s13 !== peg$FAILED) {
- s12.push(s13);
- s13 = peg$parse_();
- }
- if (s12 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c7(s2, s3, s5, s9);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsestmtList() {
- var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
- s0 = peg$currPos;
- s1 = peg$parsestmt();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 59) {
- s3 = peg$c8;
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c9); }
- }
- if (s3 === peg$FAILED) {
- s3 = peg$c2;
- }
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$currPos;
- s6 = [];
- s7 = peg$parse_();
- while (s7 !== peg$FAILED) {
- s6.push(s7);
- s7 = peg$parse_();
- }
- if (s6 !== peg$FAILED) {
- s7 = peg$parsestmt();
- if (s7 !== peg$FAILED) {
- s8 = [];
- s9 = peg$parse_();
- while (s9 !== peg$FAILED) {
- s8.push(s9);
- s9 = peg$parse_();
- }
- if (s8 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 59) {
- s9 = peg$c8;
- peg$currPos++;
- } else {
- s9 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c9); }
- }
- if (s9 === peg$FAILED) {
- s9 = peg$c2;
- }
- if (s9 !== peg$FAILED) {
- s6 = [s6, s7, s8, s9];
- s5 = s6;
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$currPos;
- s6 = [];
- s7 = peg$parse_();
- while (s7 !== peg$FAILED) {
- s6.push(s7);
- s7 = peg$parse_();
- }
- if (s6 !== peg$FAILED) {
- s7 = peg$parsestmt();
- if (s7 !== peg$FAILED) {
- s8 = [];
- s9 = peg$parse_();
- while (s9 !== peg$FAILED) {
- s8.push(s9);
- s9 = peg$parse_();
- }
- if (s8 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 59) {
- s9 = peg$c8;
- peg$currPos++;
- } else {
- s9 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c9); }
- }
- if (s9 === peg$FAILED) {
- s9 = peg$c2;
- }
- if (s9 !== peg$FAILED) {
- s6 = [s6, s7, s8, s9];
- s5 = s6;
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- }
- if (s4 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c10(s1, s4);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsestmt() {
- var s0;
- s0 = peg$parseattrStmt();
- if (s0 === peg$FAILED) {
- s0 = peg$parseedgeStmt();
- if (s0 === peg$FAILED) {
- s0 = peg$parsesubgraphStmt();
- if (s0 === peg$FAILED) {
- s0 = peg$parseinlineAttrStmt();
- if (s0 === peg$FAILED) {
- s0 = peg$parsenodeStmt();
- }
- }
- }
- }
- return s0;
- }
- function peg$parseattrStmt() {
- var s0, s1, s2, s3;
- s0 = peg$currPos;
- s1 = peg$parsegraph();
- if (s1 === peg$FAILED) {
- s1 = peg$parsenode();
- if (s1 === peg$FAILED) {
- s1 = peg$parseedge();
- }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseattrList();
- if (s3 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c11(s1, s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseinlineAttrStmt() {
- var s0, s1, s2, s3, s4, s5;
- s0 = peg$currPos;
- s1 = peg$parseid();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 61) {
- s3 = peg$c12;
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c13); }
- }
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$parseid();
- if (s5 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c14(s1, s5);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsenodeStmt() {
- var s0, s1, s2, s3;
- s0 = peg$currPos;
- s1 = peg$parsenodeId();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseattrList();
- if (s3 === peg$FAILED) {
- s3 = peg$c2;
- }
- if (s3 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c15(s1, s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseedgeStmt() {
- var s0, s1, s2, s3, s4, s5;
- s0 = peg$currPos;
- s1 = peg$parsenodeIdOrSubgraph();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseedgeRHS();
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$parseattrList();
- if (s5 === peg$FAILED) {
- s5 = peg$c2;
- }
- if (s5 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c16(s1, s3, s5);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsesubgraphStmt() {
- var s0, s1, s2, s3, s4, s5, s6, s7;
- s0 = peg$currPos;
- s1 = peg$currPos;
- s2 = peg$parsesubgraph();
- if (s2 !== peg$FAILED) {
- s3 = [];
- s4 = peg$parse_();
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$parse_();
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$currPos;
- s5 = peg$parseid();
- if (s5 !== peg$FAILED) {
- s6 = [];
- s7 = peg$parse_();
- while (s7 !== peg$FAILED) {
- s6.push(s7);
- s7 = peg$parse_();
- }
- if (s6 !== peg$FAILED) {
- s5 = [s5, s6];
- s4 = s5;
- } else {
- peg$currPos = s4;
- s4 = peg$c1;
- }
- } else {
- peg$currPos = s4;
- s4 = peg$c1;
- }
- if (s4 === peg$FAILED) {
- s4 = peg$c2;
- }
- if (s4 !== peg$FAILED) {
- s2 = [s2, s3, s4];
- s1 = s2;
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- if (s1 === peg$FAILED) {
- s1 = peg$c2;
- }
- if (s1 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 123) {
- s2 = peg$c3;
- peg$currPos++;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c4); }
- }
- if (s2 !== peg$FAILED) {
- s3 = [];
- s4 = peg$parse_();
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$parse_();
- }
- if (s3 !== peg$FAILED) {
- s4 = peg$parsestmtList();
- if (s4 === peg$FAILED) {
- s4 = peg$c2;
- }
- if (s4 !== peg$FAILED) {
- s5 = [];
- s6 = peg$parse_();
- while (s6 !== peg$FAILED) {
- s5.push(s6);
- s6 = peg$parse_();
- }
- if (s5 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 125) {
- s6 = peg$c5;
- peg$currPos++;
- } else {
- s6 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c6); }
- }
- if (s6 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c17(s1, s4);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseattrList() {
- var s0, s1, s2, s3, s4, s5;
- s0 = peg$currPos;
- s1 = peg$parseattrListBlock();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$currPos;
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$parseattrListBlock();
- if (s5 !== peg$FAILED) {
- s4 = [s4, s5];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$currPos;
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$parseattrListBlock();
- if (s5 !== peg$FAILED) {
- s4 = [s4, s5];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- }
- if (s2 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c18(s1, s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseattrListBlock() {
- var s0, s1, s2, s3, s4, s5;
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 91) {
- s1 = peg$c19;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c20); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseaList();
- if (s3 === peg$FAILED) {
- s3 = peg$c2;
- }
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 93) {
- s5 = peg$c21;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c22); }
- }
- if (s5 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c23(s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseaList() {
- var s0, s1, s2, s3, s4, s5, s6, s7;
- s0 = peg$currPos;
- s1 = peg$parseidDef();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$currPos;
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 44) {
- s5 = peg$c24;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c25); }
- }
- if (s5 === peg$FAILED) {
- s5 = peg$c2;
- }
- if (s5 !== peg$FAILED) {
- s6 = [];
- s7 = peg$parse_();
- while (s7 !== peg$FAILED) {
- s6.push(s7);
- s7 = peg$parse_();
- }
- if (s6 !== peg$FAILED) {
- s7 = peg$parseidDef();
- if (s7 !== peg$FAILED) {
- s4 = [s4, s5, s6, s7];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$currPos;
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 44) {
- s5 = peg$c24;
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c25); }
- }
- if (s5 === peg$FAILED) {
- s5 = peg$c2;
- }
- if (s5 !== peg$FAILED) {
- s6 = [];
- s7 = peg$parse_();
- while (s7 !== peg$FAILED) {
- s6.push(s7);
- s7 = peg$parse_();
- }
- if (s6 !== peg$FAILED) {
- s7 = peg$parseidDef();
- if (s7 !== peg$FAILED) {
- s4 = [s4, s5, s6, s7];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- }
- if (s2 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c26(s1, s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseedgeRHS() {
- var s0, s1, s2, s3, s4, s5;
- s0 = peg$currPos;
- s1 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c27) {
- s2 = peg$c27;
- peg$currPos += 2;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c28); }
- }
- if (s2 !== peg$FAILED) {
- peg$reportedPos = peg$currPos;
- s3 = peg$c29();
- if (s3) {
- s3 = peg$c1;
- } else {
- s3 = peg$c30;
- }
- if (s3 !== peg$FAILED) {
- s2 = [s2, s3];
- s1 = s2;
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- if (s1 === peg$FAILED) {
- s1 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c31) {
- s2 = peg$c31;
- peg$currPos += 2;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c32); }
- }
- if (s2 !== peg$FAILED) {
- peg$reportedPos = peg$currPos;
- s3 = peg$c29();
- if (s3) {
- s3 = peg$c30;
- } else {
- s3 = peg$c1;
- }
- if (s3 !== peg$FAILED) {
- s2 = [s2, s3];
- s1 = s2;
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- } else {
- peg$currPos = s1;
- s1 = peg$c1;
- }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parsenodeIdOrSubgraph();
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$parseedgeRHS();
- if (s5 === peg$FAILED) {
- s5 = peg$c2;
- }
- if (s5 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c33(s3, s5);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseidDef() {
- var s0, s1, s2, s3, s4, s5, s6;
- s0 = peg$currPos;
- s1 = peg$parseid();
- if (s1 !== peg$FAILED) {
- s2 = peg$currPos;
- s3 = [];
- s4 = peg$parse_();
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- s4 = peg$parse_();
- }
- if (s3 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 61) {
- s4 = peg$c12;
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c13); }
- }
- if (s4 !== peg$FAILED) {
- s5 = [];
- s6 = peg$parse_();
- while (s6 !== peg$FAILED) {
- s5.push(s6);
- s6 = peg$parse_();
- }
- if (s5 !== peg$FAILED) {
- s6 = peg$parseid();
- if (s6 !== peg$FAILED) {
- s3 = [s3, s4, s5, s6];
- s2 = s3;
- } else {
- peg$currPos = s2;
- s2 = peg$c1;
- }
- } else {
- peg$currPos = s2;
- s2 = peg$c1;
- }
- } else {
- peg$currPos = s2;
- s2 = peg$c1;
- }
- } else {
- peg$currPos = s2;
- s2 = peg$c1;
- }
- if (s2 === peg$FAILED) {
- s2 = peg$c2;
- }
- if (s2 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c34(s1, s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsenodeIdOrSubgraph() {
- var s0, s1;
- s0 = peg$parsesubgraphStmt();
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- s1 = peg$parsenodeId();
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c35(s1);
- }
- s0 = s1;
- }
- return s0;
- }
- function peg$parsenodeId() {
- var s0, s1, s2, s3;
- s0 = peg$currPos;
- s1 = peg$parseid();
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseport();
- if (s3 === peg$FAILED) {
- s3 = peg$c2;
- }
- if (s3 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c36(s1);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parseport() {
- var s0, s1, s2, s3, s4, s5, s6, s7, s8;
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 58) {
- s1 = peg$c37;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parse_();
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parse_();
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseid();
- if (s3 !== peg$FAILED) {
- s4 = [];
- s5 = peg$parse_();
- while (s5 !== peg$FAILED) {
- s4.push(s5);
- s5 = peg$parse_();
- }
- if (s4 !== peg$FAILED) {
- s5 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 58) {
- s6 = peg$c37;
- peg$currPos++;
- } else {
- s6 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c38); }
- }
- if (s6 !== peg$FAILED) {
- s7 = [];
- s8 = peg$parse_();
- while (s8 !== peg$FAILED) {
- s7.push(s8);
- s8 = peg$parse_();
- }
- if (s7 !== peg$FAILED) {
- s8 = peg$parsecompassPt();
- if (s8 !== peg$FAILED) {
- s6 = [s6, s7, s8];
- s5 = s6;
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- } else {
- peg$currPos = s5;
- s5 = peg$c1;
- }
- if (s5 === peg$FAILED) {
- s5 = peg$c2;
- }
- if (s5 !== peg$FAILED) {
- s1 = [s1, s2, s3, s4, s5];
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- return s0;
- }
- function peg$parsecompassPt() {
- var s0;
- if (input.substr(peg$currPos, 2) === peg$c39) {
- s0 = peg$c39;
- peg$currPos += 2;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c40); }
- }
- if (s0 === peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c41) {
- s0 = peg$c41;
- peg$currPos += 2;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c42); }
- }
- if (s0 === peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c43) {
- s0 = peg$c43;
- peg$currPos += 2;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c44); }
- }
- if (s0 === peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c45) {
- s0 = peg$c45;
- peg$currPos += 2;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c46); }
- }
- if (s0 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 110) {
- s0 = peg$c47;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c48); }
- }
- if (s0 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 101) {
- s0 = peg$c49;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c50); }
- }
- if (s0 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 115) {
- s0 = peg$c51;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c52); }
- }
- if (s0 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 119) {
- s0 = peg$c53;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c54); }
- }
- if (s0 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 99) {
- s0 = peg$c55;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c56); }
- }
- if (s0 === peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 95) {
- s0 = peg$c57;
- peg$currPos++;
- } else {
- s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c58); }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- return s0;
- }
- function peg$parseid() {
- var s0, s1, s2, s3, s4, s5, s6;
- peg$silentFails++;
- s0 = peg$currPos;
- if (peg$c60.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c61); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- if (peg$c62.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c63); }
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- if (peg$c62.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c63); }
- }
- }
- if (s2 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c64(s1, s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 45) {
- s1 = peg$c65;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c66); }
- }
- if (s1 === peg$FAILED) {
- s1 = peg$c2;
- }
- if (s1 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 46) {
- s2 = peg$c67;
- peg$currPos++;
- } else {
- s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c68); }
- }
- if (s2 !== peg$FAILED) {
- s3 = [];
- if (peg$c69.test(input.charAt(peg$currPos))) {
- s4 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c70); }
- }
- if (s4 !== peg$FAILED) {
- while (s4 !== peg$FAILED) {
- s3.push(s4);
- if (peg$c69.test(input.charAt(peg$currPos))) {
- s4 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c70); }
- }
- }
- } else {
- s3 = peg$c1;
- }
- if (s3 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c71(s1, s2, s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 45) {
- s1 = peg$c65;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c66); }
- }
- if (s1 === peg$FAILED) {
- s1 = peg$c2;
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- if (peg$c69.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c70); }
- }
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- if (peg$c69.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c70); }
- }
- }
- } else {
- s2 = peg$c1;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 46) {
- s4 = peg$c67;
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c68); }
- }
- if (s4 !== peg$FAILED) {
- s5 = [];
- if (peg$c69.test(input.charAt(peg$currPos))) {
- s6 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s6 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c70); }
- }
- while (s6 !== peg$FAILED) {
- s5.push(s6);
- if (peg$c69.test(input.charAt(peg$currPos))) {
- s6 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s6 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c70); }
- }
- }
- if (s5 !== peg$FAILED) {
- s4 = [s4, s5];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- if (s3 === peg$FAILED) {
- s3 = peg$c2;
- }
- if (s3 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c72(s1, s2, s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 34) {
- s1 = peg$c73;
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c74); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c75) {
- s4 = peg$c75;
- peg$currPos += 2;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c76); }
- }
- if (s4 !== peg$FAILED) {
- peg$reportedPos = s3;
- s4 = peg$c77();
- }
- s3 = s4;
- if (s3 === peg$FAILED) {
- s3 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 92) {
- s4 = peg$c78;
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c79); }
- }
- if (s4 !== peg$FAILED) {
- if (peg$c80.test(input.charAt(peg$currPos))) {
- s5 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c81); }
- }
- if (s5 !== peg$FAILED) {
- peg$reportedPos = s3;
- s4 = peg$c82(s5);
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- if (s3 === peg$FAILED) {
- if (peg$c80.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c81); }
- }
- }
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c75) {
- s4 = peg$c75;
- peg$currPos += 2;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c76); }
- }
- if (s4 !== peg$FAILED) {
- peg$reportedPos = s3;
- s4 = peg$c77();
- }
- s3 = s4;
- if (s3 === peg$FAILED) {
- s3 = peg$currPos;
- if (input.charCodeAt(peg$currPos) === 92) {
- s4 = peg$c78;
- peg$currPos++;
- } else {
- s4 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c79); }
- }
- if (s4 !== peg$FAILED) {
- if (peg$c80.test(input.charAt(peg$currPos))) {
- s5 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c81); }
- }
- if (s5 !== peg$FAILED) {
- peg$reportedPos = s3;
- s4 = peg$c82(s5);
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- if (s3 === peg$FAILED) {
- if (peg$c80.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c81); }
- }
- }
- }
- }
- if (s2 !== peg$FAILED) {
- if (input.charCodeAt(peg$currPos) === 34) {
- s3 = peg$c73;
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c74); }
- }
- if (s3 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c83(s2);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- }
- }
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c59); }
- }
- return s0;
- }
- function peg$parsenode() {
- var s0, s1;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c84) {
- s1 = input.substr(peg$currPos, 4);
- peg$currPos += 4;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c85); }
- }
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c86(s1);
- }
- s0 = s1;
- return s0;
- }
- function peg$parseedge() {
- var s0, s1;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 4).toLowerCase() === peg$c87) {
- s1 = input.substr(peg$currPos, 4);
- peg$currPos += 4;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c88); }
- }
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c86(s1);
- }
- s0 = s1;
- return s0;
- }
- function peg$parsegraph() {
- var s0, s1;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 5).toLowerCase() === peg$c89) {
- s1 = input.substr(peg$currPos, 5);
- peg$currPos += 5;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c90); }
- }
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c86(s1);
- }
- s0 = s1;
- return s0;
- }
- function peg$parsedigraph() {
- var s0, s1;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 7).toLowerCase() === peg$c91) {
- s1 = input.substr(peg$currPos, 7);
- peg$currPos += 7;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c92); }
- }
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c86(s1);
- }
- s0 = s1;
- return s0;
- }
- function peg$parsesubgraph() {
- var s0, s1;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 8).toLowerCase() === peg$c93) {
- s1 = input.substr(peg$currPos, 8);
- peg$currPos += 8;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c94); }
- }
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c86(s1);
- }
- s0 = s1;
- return s0;
- }
- function peg$parsestrict() {
- var s0, s1;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 6).toLowerCase() === peg$c95) {
- s1 = input.substr(peg$currPos, 6);
- peg$currPos += 6;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c96); }
- }
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c86(s1);
- }
- s0 = s1;
- return s0;
- }
- function peg$parsegraphType() {
- var s0, s1;
- s0 = peg$parsegraph();
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- s1 = peg$parsedigraph();
- if (s1 !== peg$FAILED) {
- peg$reportedPos = s0;
- s1 = peg$c97(s1);
- }
- s0 = s1;
- }
- return s0;
- }
- function peg$parsewhitespace() {
- var s0, s1;
- peg$silentFails++;
- s0 = [];
- if (peg$c99.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c100); }
- }
- if (s1 !== peg$FAILED) {
- while (s1 !== peg$FAILED) {
- s0.push(s1);
- if (peg$c99.test(input.charAt(peg$currPos))) {
- s1 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c100); }
- }
- }
- } else {
- s0 = peg$c1;
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c98); }
- }
- return s0;
- }
- function peg$parsecomment() {
- var s0, s1, s2, s3, s4, s5;
- peg$silentFails++;
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c102) {
- s1 = peg$c102;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c103); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- if (peg$c104.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c105); }
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- if (peg$c104.test(input.charAt(peg$currPos))) {
- s3 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c105); }
- }
- }
- if (s2 !== peg$FAILED) {
- s1 = [s1, s2];
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c106) {
- s1 = peg$c106;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c107); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$currPos;
- s4 = peg$currPos;
- peg$silentFails++;
- if (input.substr(peg$currPos, 2) === peg$c108) {
- s5 = peg$c108;
- peg$currPos += 2;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c109); }
- }
- peg$silentFails--;
- if (s5 === peg$FAILED) {
- s4 = peg$c30;
- } else {
- peg$currPos = s4;
- s4 = peg$c1;
- }
- if (s4 !== peg$FAILED) {
- if (input.length > peg$currPos) {
- s5 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c110); }
- }
- if (s5 !== peg$FAILED) {
- s4 = [s4, s5];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$currPos;
- s4 = peg$currPos;
- peg$silentFails++;
- if (input.substr(peg$currPos, 2) === peg$c108) {
- s5 = peg$c108;
- peg$currPos += 2;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c109); }
- }
- peg$silentFails--;
- if (s5 === peg$FAILED) {
- s4 = peg$c30;
- } else {
- peg$currPos = s4;
- s4 = peg$c1;
- }
- if (s4 !== peg$FAILED) {
- if (input.length > peg$currPos) {
- s5 = input.charAt(peg$currPos);
- peg$currPos++;
- } else {
- s5 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c110); }
- }
- if (s5 !== peg$FAILED) {
- s4 = [s4, s5];
- s3 = s4;
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- } else {
- peg$currPos = s3;
- s3 = peg$c1;
- }
- }
- if (s2 !== peg$FAILED) {
- if (input.substr(peg$currPos, 2) === peg$c108) {
- s3 = peg$c108;
- peg$currPos += 2;
- } else {
- s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c109); }
- }
- if (s3 !== peg$FAILED) {
- s1 = [s1, s2, s3];
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$c1;
- }
- }
- peg$silentFails--;
- if (s0 === peg$FAILED) {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c101); }
- }
- return s0;
- }
- function peg$parse_() {
- var s0;
- s0 = peg$parsewhitespace();
- if (s0 === peg$FAILED) {
- s0 = peg$parsecomment();
- }
- return s0;
- }
- var _ = require("lodash");
- var directed;
- peg$result = peg$startRuleFunction();
- if (peg$result !== peg$FAILED && peg$currPos === input.length) {
- return peg$result;
- } else {
- if (peg$result !== peg$FAILED && peg$currPos < input.length) {
- peg$fail({ type: "end", description: "end of input" });
- }
- throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos);
- }
- }
- return {
- SyntaxError: SyntaxError,
- parse: parse
- };
- })();
- },{"lodash":28}],5:[function(require,module,exports){
- var _ = require("lodash"),
- grammar = require("./dot-grammar"),
- buildGraph = require("./build-graph");
- module.exports = function readMany(str) {
- var parseTree = grammar.parse(str);
- return _.map(parseTree, buildGraph);
- };
- },{"./build-graph":3,"./dot-grammar":4,"lodash":28}],6:[function(require,module,exports){
- var grammar = require("./dot-grammar"),
- buildGraph = require("./build-graph");
- module.exports = function readOne(str) {
- var parseTree = grammar.parse(str, { startRule: "graphStmt" });
- return buildGraph(parseTree);
- };
- },{"./build-graph":3,"./dot-grammar":4}],7:[function(require,module,exports){
- module.exports = '0.5.2';
- },{}],8:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = writeOne;
- var UNESCAPED_ID_PATTERN = /^[a-zA-Z\200-\377_][a-zA-Z\200-\377_0-9]*$/;
- function writeOne(g) {
- var ec = g.isDirected() ? "->" : "--",
- writer = new Writer();
- if (!g.isMultigraph()) {
- writer.write("strict ");
- }
- writer.writeLine((g.isDirected() ? "digraph" : "graph") + " {");
- writer.indent();
- var graphAttrs = g.graph();
- if (_.isObject(graphAttrs)) {
- _.each(graphAttrs, function(v, k) {
- writer.writeLine(id(k) + "=" + id(v) + ";");
- });
- }
- writeSubgraph(g, undefined, writer);
- g.edges().forEach(function(edge) {
- writeEdge(g, edge, ec, writer);
- });
- writer.unindent();
- writer.writeLine("}");
- return writer.toString();
- }
- function writeSubgraph(g, v, writer) {
- var children = g.isCompound() ? g.children(v) : g.nodes();
- _.each(children, function(w) {
- if (!g.isCompound() || !g.children(w).length) {
- writeNode(g, w, writer);
- } else {
- writer.writeLine("subgraph " + id(w) + " {");
- writer.indent();
- if (_.isObject(g.node(w))) {
- _.map(g.node(w), function(val, key) {
- writer.writeLine(id(key) + "=" + id(val) + ";");
- });
- }
- writeSubgraph(g, w, writer);
- writer.unindent();
- writer.writeLine("}");
- }
- });
- }
- function writeNode(g, v, writer) {
- writer.write(id(v));
- writeAttrs(g.node(v), writer);
- writer.writeLine();
- }
- function writeEdge(g, edge, ec, writer) {
- var v = edge.v,
- w = edge.w,
- attrs = g.edge(edge);
- writer.write(id(v) + " " + ec + " " + id(w));
- writeAttrs(attrs, writer);
- writer.writeLine();
- }
- function writeAttrs(attrs, writer) {
- if (_.isObject(attrs)) {
- var attrStrs = _.map(attrs, function(val, key) {
- return id(key) + "=" + id(val);
- });
- if (attrStrs.length) {
- writer.write(" [" + attrStrs.join(",") + "]");
- }
- }
- }
- function id(obj) {
- if (typeof obj === "number" || obj.toString().match(UNESCAPED_ID_PATTERN)) {
- return obj;
- }
- return "\"" + obj.toString().replace(/"/g, "\\\"") + "\"";
- }
- // Helper object for making a pretty printer
- function Writer() {
- this._indent = "";
- this._content = "";
- this._shouldIndent = true;
- }
- Writer.prototype.INDENT = " ";
- Writer.prototype.indent = function() {
- this._indent += this.INDENT;
- };
- Writer.prototype.unindent = function() {
- this._indent = this._indent.slice(this.INDENT.length);
- };
- Writer.prototype.writeLine = function(line) {
- this.write((line || "") + "\n");
- this._shouldIndent = true;
- };
- Writer.prototype.write = function(str) {
- if (this._shouldIndent) {
- this._shouldIndent = false;
- this._content += this._indent;
- }
- this._content += str;
- };
- Writer.prototype.toString = function() {
- return this._content;
- };
- },{"lodash":28}],9:[function(require,module,exports){
- /**
- * Copyright (c) 2014, Chris Pettitt
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the copyright holder nor the names of its contributors
- * may be used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- var _ = require("lodash");
- module.exports = _.clone(require("./lib"));
- module.exports.json = require("./lib/json");
- module.exports.alg = require("./lib/alg");
- },{"./lib":25,"./lib/alg":16,"./lib/json":26,"lodash":28}],10:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = components;
- function components(g) {
- var visited = {},
- cmpts = [],
- cmpt;
- function dfs(v) {
- if (_.has(visited, v)) return;
- visited[v] = true;
- cmpt.push(v);
- _.each(g.successors(v), dfs);
- _.each(g.predecessors(v), dfs);
- }
- _.each(g.nodes(), function(v) {
- cmpt = [];
- dfs(v);
- if (cmpt.length) {
- cmpts.push(cmpt);
- }
- });
- return cmpts;
- }
- },{"lodash":28}],11:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = dfs;
- /*
- * A helper that preforms a pre- or post-order traversal on the input graph
- * and returns the nodes in the order they were visited. This algorithm treats
- * the input as undirected.
- *
- * Order must be one of "pre" or "post".
- */
- function dfs(g, vs, order) {
- if (!_.isArray(vs)) {
- vs = [vs];
- }
- var acc = [],
- visited = {};
- _.each(vs, function(v) {
- if (!g.hasNode(v)) {
- throw new Error("Graph does not have node: " + v);
- }
- doDfs(g, v, order === "post", visited, acc);
- });
- return acc;
- }
- function doDfs(g, v, postorder, visited, acc) {
- if (!_.has(visited, v)) {
- visited[v] = true;
- if (!postorder) { acc.push(v); }
- _.each(g.neighbors(v), function(w) {
- doDfs(g, w, postorder, visited, acc);
- });
- if (postorder) { acc.push(v); }
- }
- }
- },{"lodash":28}],12:[function(require,module,exports){
- var dijkstra = require("./dijkstra"),
- _ = require("lodash");
- module.exports = dijkstraAll;
- function dijkstraAll(g, weightFunc, edgeFunc) {
- return _.transform(g.nodes(), function(acc, v) {
- acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
- }, {});
- }
- },{"./dijkstra":13,"lodash":28}],13:[function(require,module,exports){
- var _ = require("lodash"),
- PriorityQueue = require("../data/priority-queue");
- module.exports = dijkstra;
- var DEFAULT_WEIGHT_FUNC = _.constant(1);
- function dijkstra(g, source, weightFn, edgeFn) {
- return runDijkstra(g, String(source),
- weightFn || DEFAULT_WEIGHT_FUNC,
- edgeFn || function(v) { return g.outEdges(v); });
- }
- function runDijkstra(g, source, weightFn, edgeFn) {
- var results = {},
- pq = new PriorityQueue(),
- v, vEntry;
- var updateNeighbors = function(edge) {
- var w = edge.v !== v ? edge.v : edge.w,
- wEntry = results[w],
- weight = weightFn(edge),
- distance = vEntry.distance + weight;
- if (weight < 0) {
- throw new Error("dijkstra does not allow negative edge weights. " +
- "Bad edge: " + edge + " Weight: " + weight);
- }
- if (distance < wEntry.distance) {
- wEntry.distance = distance;
- wEntry.predecessor = v;
- pq.decrease(w, distance);
- }
- };
- g.nodes().forEach(function(v) {
- var distance = v === source ? 0 : Number.POSITIVE_INFINITY;
- results[v] = { distance: distance };
- pq.add(v, distance);
- });
- while (pq.size() > 0) {
- v = pq.removeMin();
- vEntry = results[v];
- if (vEntry.distance === Number.POSITIVE_INFINITY) {
- break;
- }
- edgeFn(v).forEach(updateNeighbors);
- }
- return results;
- }
- },{"../data/priority-queue":23,"lodash":28}],14:[function(require,module,exports){
- var _ = require("lodash"),
- tarjan = require("./tarjan");
- module.exports = findCycles;
- function findCycles(g) {
- return _.filter(tarjan(g), function(cmpt) { return cmpt.length > 1; });
- }
- },{"./tarjan":21,"lodash":28}],15:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = floydWarshall;
- var DEFAULT_WEIGHT_FUNC = _.constant(1);
- function floydWarshall(g, weightFn, edgeFn) {
- return runFloydWarshall(g,
- weightFn || DEFAULT_WEIGHT_FUNC,
- edgeFn || function(v) { return g.outEdges(v); });
- }
- function runFloydWarshall(g, weightFn, edgeFn) {
- var results = {},
- nodes = g.nodes();
- nodes.forEach(function(v) {
- results[v] = {};
- results[v][v] = { distance: 0 };
- nodes.forEach(function(w) {
- if (v !== w) {
- results[v][w] = { distance: Number.POSITIVE_INFINITY };
- }
- });
- edgeFn(v).forEach(function(edge) {
- var w = edge.v === v ? edge.w : edge.v,
- d = weightFn(edge);
- results[v][w] = { distance: d, predecessor: v };
- });
- });
- nodes.forEach(function(k) {
- var rowK = results[k];
- nodes.forEach(function(i) {
- var rowI = results[i];
- nodes.forEach(function(j) {
- var ik = rowI[k];
- var kj = rowK[j];
- var ij = rowI[j];
- var altDistance = ik.distance + kj.distance;
- if (altDistance < ij.distance) {
- ij.distance = altDistance;
- ij.predecessor = kj.predecessor;
- }
- });
- });
- });
- return results;
- }
- },{"lodash":28}],16:[function(require,module,exports){
- module.exports = {
- components: require("./components"),
- dijkstra: require("./dijkstra"),
- dijkstraAll: require("./dijkstra-all"),
- findCycles: require("./find-cycles"),
- floydWarshall: require("./floyd-warshall"),
- isAcyclic: require("./is-acyclic"),
- postorder: require("./postorder"),
- preorder: require("./preorder"),
- prim: require("./prim"),
- tarjan: require("./tarjan"),
- topsort: require("./topsort")
- };
- },{"./components":10,"./dijkstra":13,"./dijkstra-all":12,"./find-cycles":14,"./floyd-warshall":15,"./is-acyclic":17,"./postorder":18,"./preorder":19,"./prim":20,"./tarjan":21,"./topsort":22}],17:[function(require,module,exports){
- var topsort = require("./topsort");
- module.exports = isAcyclic;
- function isAcyclic(g) {
- try {
- topsort(g);
- } catch (e) {
- if (e instanceof topsort.CycleException) {
- return false;
- }
- throw e;
- }
- return true;
- }
- },{"./topsort":22}],18:[function(require,module,exports){
- var dfs = require("./dfs");
- module.exports = postorder;
- function postorder(g, vs) {
- return dfs(g, vs, "post");
- }
- },{"./dfs":11}],19:[function(require,module,exports){
- var dfs = require("./dfs");
- module.exports = preorder;
- function preorder(g, vs) {
- return dfs(g, vs, "pre");
- }
- },{"./dfs":11}],20:[function(require,module,exports){
- var _ = require("lodash"),
- Graph = require("../graph"),
- PriorityQueue = require("../data/priority-queue");
- module.exports = prim;
- function prim(g, weightFunc) {
- var result = new Graph(),
- parents = {},
- pq = new PriorityQueue(),
- v;
- function updateNeighbors(edge) {
- var w = edge.v === v ? edge.w : edge.v,
- pri = pq.priority(w);
- if (pri !== undefined) {
- var edgeWeight = weightFunc(edge);
- if (edgeWeight < pri) {
- parents[w] = v;
- pq.decrease(w, edgeWeight);
- }
- }
- }
- if (g.nodeCount() === 0) {
- return result;
- }
- _.each(g.nodes(), function(v) {
- pq.add(v, Number.POSITIVE_INFINITY);
- result.setNode(v);
- });
- // Start from an arbitrary node
- pq.decrease(g.nodes()[0], 0);
- var init = false;
- while (pq.size() > 0) {
- v = pq.removeMin();
- if (_.has(parents, v)) {
- result.setEdge(v, parents[v]);
- } else if (init) {
- throw new Error("Input graph is not connected: " + g);
- } else {
- init = true;
- }
- g.nodeEdges(v).forEach(updateNeighbors);
- }
- return result;
- }
- },{"../data/priority-queue":23,"../graph":24,"lodash":28}],21:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = tarjan;
- function tarjan(g) {
- var index = 0,
- stack = [],
- visited = {}, // node id -> { onStack, lowlink, index }
- results = [];
- function dfs(v) {
- var entry = visited[v] = {
- onStack: true,
- lowlink: index,
- index: index++
- };
- stack.push(v);
- g.successors(v).forEach(function(w) {
- if (!_.has(visited, w)) {
- dfs(w);
- entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
- } else if (visited[w].onStack) {
- entry.lowlink = Math.min(entry.lowlink, visited[w].index);
- }
- });
- if (entry.lowlink === entry.index) {
- var cmpt = [],
- w;
- do {
- w = stack.pop();
- visited[w].onStack = false;
- cmpt.push(w);
- } while (v !== w);
- results.push(cmpt);
- }
- }
- g.nodes().forEach(function(v) {
- if (!_.has(visited, v)) {
- dfs(v);
- }
- });
- return results;
- }
- },{"lodash":28}],22:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = topsort;
- topsort.CycleException = CycleException;
- function topsort(g) {
- var visited = {},
- stack = {},
- results = [];
- function visit(node) {
- if (_.has(stack, node)) {
- throw new CycleException();
- }
- if (!_.has(visited, node)) {
- stack[node] = true;
- visited[node] = true;
- _.each(g.predecessors(node), visit);
- delete stack[node];
- results.push(node);
- }
- }
- _.each(g.sinks(), visit);
- if (_.size(visited) !== g.nodeCount()) {
- throw new CycleException();
- }
- return results;
- }
- function CycleException() {}
- },{"lodash":28}],23:[function(require,module,exports){
- var _ = require("lodash");
- module.exports = PriorityQueue;
- /**
- * A min-priority queue data structure. This algorithm is derived from Cormen,
- * et al., "Introduction to Algorithms". The basic idea of a min-priority
- * queue is that you can efficiently (in O(1) time) get the smallest key in
- * the queue. Adding and removing elements takes O(log n) time. A key can
- * have its priority decreased in O(log n) time.
- */
- function PriorityQueue() {
- this._arr = [];
- this._keyIndices = {};
- }
- /**
- * Returns the number of elements in the queue. Takes `O(1)` time.
- */
- PriorityQueue.prototype.size = function() {
- return this._arr.length;
- };
- /**
- * Returns the keys that are in the queue. Takes `O(n)` time.
- */
- PriorityQueue.prototype.keys = function() {
- return this._arr.map(function(x) { return x.key; });
- };
- /**
- * Returns `true` if **key** is in the queue and `false` if not.
- */
- PriorityQueue.prototype.has = function(key) {
- return _.has(this._keyIndices, key);
- };
- /**
- * Returns the priority for **key**. If **key** is not present in the queue
- * then this function returns `undefined`. Takes `O(1)` time.
- *
- * @param {Object} key
- */
- PriorityQueue.prototype.priority = function(key) {
- var index = this._keyIndices[key];
- if (index !== undefined) {
- return this._arr[index].priority;
- }
- };
- /**
- * Returns the key for the minimum element in this queue. If the queue is
- * empty this function throws an Error. Takes `O(1)` time.
- */
- PriorityQueue.prototype.min = function() {
- if (this.size() === 0) {
- throw new Error("Queue underflow");
- }
- return this._arr[0].key;
- };
- /**
- * Inserts a new key into the priority queue. If the key already exists in
- * the queue this function returns `false`; otherwise it will return `true`.
- * Takes `O(n)` time.
- *
- * @param {Object} key the key to add
- * @param {Number} priority the initial priority for the key
- */
- PriorityQueue.prototype.add = function(key, priority) {
- var keyIndices = this._keyIndices;
- key = String(key);
- if (!_.has(keyIndices, key)) {
- var arr = this._arr;
- var index = arr.length;
- keyIndices[key] = index;
- arr.push({key: key, priority: priority});
- this._decrease(index);
- return true;
- }
- return false;
- };
- /**
- * Removes and returns the smallest key in the queue. Takes `O(log n)` time.
- */
- PriorityQueue.prototype.removeMin = function() {
- this._swap(0, this._arr.length - 1);
- var min = this._arr.pop();
- delete this._keyIndices[min.key];
- this._heapify(0);
- return min.key;
- };
- /**
- * Decreases the priority for **key** to **priority**. If the new priority is
- * greater than the previous priority, this function will throw an Error.
- *
- * @param {Object} key the key for which to raise priority
- * @param {Number} priority the new priority for the key
- */
- PriorityQueue.prototype.decrease = function(key, priority) {
- var index = this._keyIndices[key];
- if (priority > this._arr[index].priority) {
- throw new Error("New priority is greater than current priority. " +
- "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority);
- }
- this._arr[index].priority = priority;
- this._decrease(index);
- };
- PriorityQueue.prototype._heapify = function(i) {
- var arr = this._arr;
- var l = 2 * i,
- r = l + 1,
- largest = i;
- if (l < arr.length) {
- largest = arr[l].priority < arr[largest].priority ? l : largest;
- if (r < arr.length) {
- largest = arr[r].priority < arr[largest].priority ? r : largest;
- }
- if (largest !== i) {
- this._swap(i, largest);
- this._heapify(largest);
- }
- }
- };
- PriorityQueue.prototype._decrease = function(index) {
- var arr = this._arr;
- var priority = arr[index].priority;
- var parent;
- while (index !== 0) {
- parent = index >> 1;
- if (arr[parent].priority < priority) {
- break;
- }
- this._swap(index, parent);
- index = parent;
- }
- };
- PriorityQueue.prototype._swap = function(i, j) {
- var arr = this._arr;
- var keyIndices = this._keyIndices;
- var origArrI = arr[i];
- var origArrJ = arr[j];
- arr[i] = origArrJ;
- arr[j] = origArrI;
- keyIndices[origArrJ.key] = i;
- keyIndices[origArrI.key] = j;
- };
- },{"lodash":28}],24:[function(require,module,exports){
- "use strict";
- var _ = require("lodash");
- module.exports = Graph;
- var DEFAULT_EDGE_NAME = "\x00",
- GRAPH_NODE = "\x00",
- EDGE_KEY_DELIM = "\x01";
- // Implementation notes:
- //
- // * Node id query functions should return string ids for the nodes
- // * Edge id query functions should return an "edgeObj", edge object, that is
- // composed of enough information to uniquely identify an edge: {v, w, name}.
- // * Internally we use an "edgeId", a stringified form of the edgeObj, to
- // reference edges. This is because we need a performant way to look these
- // edges up and, object properties, which have string keys, are the closest
- // we're going to get to a performant hashtable in JavaScript.
- function Graph(opts) {
- this._isDirected = _.has(opts, "directed") ? opts.directed : true;
- this._isMultigraph = _.has(opts, "multigraph") ? opts.multigraph : false;
- this._isCompound = _.has(opts, "compound") ? opts.compound : false;
- // Label for the graph itself
- this._label = undefined;
- // Defaults to be set when creating a new node
- this._defaultNodeLabelFn = _.constant(undefined);
- // Defaults to be set when creating a new edge
- this._defaultEdgeLabelFn = _.constant(undefined);
- // v -> label
- this._nodes = {};
- if (this._isCompound) {
- // v -> parent
- this._parent = {};
- // v -> children
- this._children = {};
- this._children[GRAPH_NODE] = {};
- }
- // v -> edgeObj
- this._in = {};
- // u -> v -> Number
- this._preds = {};
- // v -> edgeObj
- this._out = {};
- // v -> w -> Number
- this._sucs = {};
- // e -> edgeObj
- this._edgeObjs = {};
- // e -> label
- this._edgeLabels = {};
- }
- /* Number of nodes in the graph. Should only be changed by the implementation. */
- Graph.prototype._nodeCount = 0;
- /* Number of edges in the graph. Should only be changed by the implementation. */
- Graph.prototype._edgeCount = 0;
- /* === Graph functions ========= */
- Graph.prototype.isDirected = function() {
- return this._isDirected;
- };
- Graph.prototype.isMultigraph = function() {
- return this._isMultigraph;
- };
- Graph.prototype.isCompound = function() {
- return this._isCompound;
- };
- Graph.prototype.setGraph = function(label) {
- this._label = label;
- return this;
- };
- Graph.prototype.graph = function() {
- return this._label;
- };
- /* === Node functions ========== */
- Graph.prototype.setDefaultNodeLabel = function(newDefault) {
- if (!_.isFunction(newDefault)) {
- newDefault = _.constant(newDefault);
- }
- this._defaultNodeLabelFn = newDefault;
- return this;
- };
- Graph.prototype.nodeCount = function() {
- return this._nodeCount;
- };
- Graph.prototype.nodes = function() {
- return _.keys(this._nodes);
- };
- Graph.prototype.sources = function() {
- return _.filter(this.nodes(), function(v) {
- return _.isEmpty(this._in[v]);
- }, this);
- };
- Graph.prototype.sinks = function() {
- return _.filter(this.nodes(), function(v) {
- return _.isEmpty(this._out[v]);
- }, this);
- };
- Graph.prototype.setNodes = function(vs, value) {
- var args = arguments;
- _.each(vs, function(v) {
- if (args.length > 1) {
- this.setNode(v, value);
- } else {
- this.setNode(v);
- }
- }, this);
- return this;
- };
- Graph.prototype.setNode = function(v, value) {
- if (_.has(this._nodes, v)) {
- if (arguments.length > 1) {
- this._nodes[v] = value;
- }
- return this;
- }
- this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
- if (this._isCompound) {
- this._parent[v] = GRAPH_NODE;
- this._children[v] = {};
- this._children[GRAPH_NODE][v] = true;
- }
- this._in[v] = {};
- this._preds[v] = {};
- this._out[v] = {};
- this._sucs[v] = {};
- ++this._nodeCount;
- return this;
- };
- Graph.prototype.node = function(v) {
- return this._nodes[v];
- };
- Graph.prototype.hasNode = function(v) {
- return _.has(this._nodes, v);
- };
- Graph.prototype.removeNode = function(v) {
- var self = this;
- if (_.has(this._nodes, v)) {
- var removeEdge = function(e) { self.removeEdge(self._edgeObjs[e]); };
- delete this._nodes[v];
- if (this._isCompound) {
- this._removeFromParentsChildList(v);
- delete this._parent[v];
- _.each(this.children(v), function(child) {
- this.setParent(child);
- }, this);
- delete this._children[v];
- }
- _.each(_.keys(this._in[v]), removeEdge);
- delete this._in[v];
- delete this._preds[v];
- _.each(_.keys(this._out[v]), removeEdge);
- delete this._out[v];
- delete this._sucs[v];
- --this._nodeCount;
- }
- return this;
- };
- Graph.prototype.setParent = function(v, parent) {
- if (!this._isCompound) {
- throw new Error("Cannot set parent in a non-compound graph");
- }
- if (_.isUndefined(parent)) {
- parent = GRAPH_NODE;
- } else {
- for (var ancestor = parent;
- !_.isUndefined(ancestor);
- ancestor = this.parent(ancestor)) {
- if (ancestor === v) {
- throw new Error("Setting " + parent+ " as parent of " + v +
- " would create create a cycle");
- }
- }
- this.setNode(parent);
- }
- this.setNode(v);
- this._removeFromParentsChildList(v);
- this._parent[v] = parent;
- this._children[parent][v] = true;
- return this;
- };
- Graph.prototype._removeFromParentsChildList = function(v) {
- delete this._children[this._parent[v]][v];
- };
- Graph.prototype.parent = function(v) {
- if (this._isCompound) {
- var parent = this._parent[v];
- if (parent !== GRAPH_NODE) {
- return parent;
- }
- }
- };
- Graph.prototype.children = function(v) {
- if (_.isUndefined(v)) {
- v = GRAPH_NODE;
- }
- if (this._isCompound) {
- var children = this._children[v];
- if (children) {
- return _.keys(children);
- }
- } else if (v === GRAPH_NODE) {
- return this.nodes();
- } else if (this.hasNode(v)) {
- return [];
- }
- };
- Graph.prototype.predecessors = function(v) {
- var predsV = this._preds[v];
- if (predsV) {
- return _.keys(predsV);
- }
- };
- Graph.prototype.successors = function(v) {
- var sucsV = this._sucs[v];
- if (sucsV) {
- return _.keys(sucsV);
- }
- };
- Graph.prototype.neighbors = function(v) {
- var preds = this.predecessors(v);
- if (preds) {
- return _.union(preds, this.successors(v));
- }
- };
- /* === Edge functions ========== */
- Graph.prototype.setDefaultEdgeLabel = function(newDefault) {
- if (!_.isFunction(newDefault)) {
- newDefault = _.constant(newDefault);
- }
- this._defaultEdgeLabelFn = newDefault;
- return this;
- };
- Graph.prototype.edgeCount = function() {
- return this._edgeCount;
- };
- Graph.prototype.edges = function() {
- return _.values(this._edgeObjs);
- };
- Graph.prototype.setPath = function(vs, value) {
- var self = this,
- args = arguments;
- _.reduce(vs, function(v, w) {
- if (args.length > 1) {
- self.setEdge(v, w, value);
- } else {
- self.setEdge(v, w);
- }
- return w;
- });
- return this;
- };
- /*
- * setEdge(v, w, [value, [name]])
- * setEdge({ v, w, [name] }, [value])
- */
- Graph.prototype.setEdge = function(v, w, value, name) {
- var valueSpecified = arguments.length > 2;
- if (_.isPlainObject(arguments[0])) {
- v = arguments[0].v;
- w = arguments[0].w;
- name = arguments[0].name;
- if (arguments.length === 2) {
- value = arguments[1];
- valueSpecified = true;
- }
- }
- var e = edgeArgsToId(this._isDirected, v, w, name);
- if (_.has(this._edgeLabels, e)) {
- if (valueSpecified) {
- this._edgeLabels[e] = value;
- }
- return this;
- }
- if (!_.isUndefined(name) && !this._isMultigraph) {
- throw new Error("Cannot set a named edge when isMultigraph = false");
- }
- // It didn't exist, so we need to create it.
- // First ensure the nodes exist.
- this.setNode(v);
- this.setNode(w);
- this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
- var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
- // Ensure we add undirected edges in a consistent way.
- v = edgeObj.v;
- w = edgeObj.w;
- Object.freeze(edgeObj);
- this._edgeObjs[e] = edgeObj;
- incrementOrInitEntry(this._preds[w], v);
- incrementOrInitEntry(this._sucs[v], w);
- this._in[w][e] = edgeObj;
- this._out[v][e] = edgeObj;
- this._edgeCount++;
- return this;
- };
- Graph.prototype.edge = function(v, w, name) {
- var e = (arguments.length === 1
- ? edgeObjToId(this._isDirected, arguments[0])
- : edgeArgsToId(this._isDirected, v, w, name));
- return this._edgeLabels[e];
- };
- Graph.prototype.hasEdge = function(v, w, name) {
- var e = (arguments.length === 1
- ? edgeObjToId(this._isDirected, arguments[0])
- : edgeArgsToId(this._isDirected, v, w, name));
- return _.has(this._edgeLabels, e);
- };
- Graph.prototype.removeEdge = function(v, w, name) {
- var e = (arguments.length === 1
- ? edgeObjToId(this._isDirected, arguments[0])
- : edgeArgsToId(this._isDirected, v, w, name)),
- edge = this._edgeObjs[e];
- if (edge) {
- v = edge.v;
- w = edge.w;
- delete this._edgeLabels[e];
- delete this._edgeObjs[e];
- decrementOrRemoveEntry(this._preds[w], v);
- decrementOrRemoveEntry(this._sucs[v], w);
- delete this._in[w][e];
- delete this._out[v][e];
- this._edgeCount--;
- }
- return this;
- };
- Graph.prototype.inEdges = function(v, u) {
- var inV = this._in[v];
- if (inV) {
- var edges = _.values(inV);
- if (!u) {
- return edges;
- }
- return _.filter(edges, function(edge) { return edge.v === u; });
- }
- };
- Graph.prototype.outEdges = function(v, w) {
- var outV = this._out[v];
- if (outV) {
- var edges = _.values(outV);
- if (!w) {
- return edges;
- }
- return _.filter(edges, function(edge) { return edge.w === w; });
- }
- };
- Graph.prototype.nodeEdges = function(v, w) {
- var inEdges = this.inEdges(v, w);
- if (inEdges) {
- return inEdges.concat(this.outEdges(v, w));
- }
- };
- function incrementOrInitEntry(map, k) {
- if (_.has(map, k)) {
- map[k]++;
- } else {
- map[k] = 1;
- }
- }
- function decrementOrRemoveEntry(map, k) {
- if (!--map[k]) { delete map[k]; }
- }
- function edgeArgsToId(isDirected, v, w, name) {
- if (!isDirected && v > w) {
- var tmp = v;
- v = w;
- w = tmp;
- }
- return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM +
- (_.isUndefined(name) ? DEFAULT_EDGE_NAME : name);
- }
- function edgeArgsToObj(isDirected, v, w, name) {
- if (!isDirected && v > w) {
- var tmp = v;
- v = w;
- w = tmp;
- }
- var edgeObj = { v: v, w: w };
- if (name) {
- edgeObj.name = name;
- }
- return edgeObj;
- }
- function edgeObjToId(isDirected, edgeObj) {
- return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
- }
- },{"lodash":28}],25:[function(require,module,exports){
- // Includes only the "core" of graphlib
- module.exports = {
- Graph: require("./graph"),
- version: require("./version")
- };
- },{"./graph":24,"./version":27}],26:[function(require,module,exports){
- var _ = require("lodash"),
- Graph = require("./graph");
- module.exports = {
- write: write,
- read: read
- };
- function write(g) {
- var json = {
- options: {
- directed: g.isDirected(),
- multigraph: g.isMultigraph(),
- compound: g.isCompound()
- },
- nodes: writeNodes(g),
- edges: writeEdges(g)
- };
- if (!_.isUndefined(g.graph())) {
- json.value = _.clone(g.graph());
- }
- return json;
- }
- function writeNodes(g) {
- return _.map(g.nodes(), function(v) {
- var nodeValue = g.node(v),
- parent = g.parent(v),
- node = { v: v };
- if (!_.isUndefined(nodeValue)) {
- node.value = nodeValue;
- }
- if (!_.isUndefined(parent)) {
- node.parent = parent;
- }
- return node;
- });
- }
- function writeEdges(g) {
- return _.map(g.edges(), function(e) {
- var edgeValue = g.edge(e),
- edge = { v: e.v, w: e.w };
- if (!_.isUndefined(e.name)) {
- edge.name = e.name;
- }
- if (!_.isUndefined(edgeValue)) {
- edge.value = edgeValue;
- }
- return edge;
- });
- }
- function read(json) {
- var g = new Graph(json.options).setGraph(json.value);
- _.each(json.nodes, function(entry) {
- g.setNode(entry.v, entry.value);
- if (entry.parent) {
- g.setParent(entry.v, entry.parent);
- }
- });
- _.each(json.edges, function(entry) {
- g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
- });
- return g;
- }
- },{"./graph":24,"lodash":28}],27:[function(require,module,exports){
- module.exports = '0.8.1';
- },{}],28:[function(require,module,exports){
- (function (global){
- /**
- * @license
- * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
- * Build: `lodash modern -o ./dist/lodash.js`
- * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
- * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
- * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- * Available under MIT license <http://lodash.com/license>
- */
- ;(function() {
- /** Used as a safe reference for `undefined` in pre ES5 environments */
- var undefined;
- /** Used to pool arrays and objects used internally */
- var arrayPool = [],
- objectPool = [];
- /** Used to generate unique IDs */
- var idCounter = 0;
- /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
- var keyPrefix = +new Date + '';
- /** Used as the size when optimizations are enabled for large arrays */
- var largeArraySize = 75;
- /** Used as the max size of the `arrayPool` and `objectPool` */
- var maxPoolSize = 40;
- /** Used to detect and test whitespace */
- var whitespace = (
- // whitespace
- ' \t\x0B\f\xA0\ufeff' +
- // line terminators
- '\n\r\u2028\u2029' +
- // unicode category "Zs" space separators
- '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
- );
- /** Used to match empty string literals in compiled template source */
- var reEmptyStringLeading = /\b__p \+= '';/g,
- reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
- reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
- /**
- * Used to match ES6 template delimiters
- * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
- */
- var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
- /** Used to match regexp flags from their coerced string values */
- var reFlags = /\w*$/;
- /** Used to detected named functions */
- var reFuncName = /^\s*function[ \n\r\t]+\w/;
- /** Used to match "interpolate" template delimiters */
- var reInterpolate = /<%=([\s\S]+?)%>/g;
- /** Used to match leading whitespace and zeros to be removed */
- var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
- /** Used to ensure capturing order of template delimiters */
- var reNoMatch = /($^)/;
- /** Used to detect functions containing a `this` reference */
- var reThis = /\bthis\b/;
- /** Used to match unescaped characters in compiled string literals */
- var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
- /** Used to assign default `context` object properties */
- var contextProps = [
- 'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
- 'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
- 'parseInt', 'setTimeout'
- ];
- /** Used to make template sourceURLs easier to identify */
- var templateCounter = 0;
- /** `Object#toString` result shortcuts */
- var argsClass = '[object Arguments]',
- arrayClass = '[object Array]',
- boolClass = '[object Boolean]',
- dateClass = '[object Date]',
- funcClass = '[object Function]',
- numberClass = '[object Number]',
- objectClass = '[object Object]',
- regexpClass = '[object RegExp]',
- stringClass = '[object String]';
- /** Used to identify object classifications that `_.clone` supports */
- var cloneableClasses = {};
- cloneableClasses[funcClass] = false;
- cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
- cloneableClasses[boolClass] = cloneableClasses[dateClass] =
- cloneableClasses[numberClass] = cloneableClasses[objectClass] =
- cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
- /** Used as an internal `_.debounce` options object */
- var debounceOptions = {
- 'leading': false,
- 'maxWait': 0,
- 'trailing': false
- };
- /** Used as the property descriptor for `__bindData__` */
- var descriptor = {
- 'configurable': false,
- 'enumerable': false,
- 'value': null,
- 'writable': false
- };
- /** Used to determine if values are of the language type Object */
- var objectTypes = {
- 'boolean': false,
- 'function': true,
- 'object': true,
- 'number': false,
- 'string': false,
- 'undefined': false
- };
- /** Used to escape characters for inclusion in compiled string literals */
- var stringEscapes = {
- '\\': '\\',
- "'": "'",
- '\n': 'n',
- '\r': 'r',
- '\t': 't',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
- /** Used as a reference to the global object */
- var root = (objectTypes[typeof window] && window) || this;
- /** Detect free variable `exports` */
- var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
- /** Detect free variable `module` */
- var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
- /** Detect the popular CommonJS extension `module.exports` */
- var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
- /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
- var freeGlobal = objectTypes[typeof global] && global;
- if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
- root = freeGlobal;
- }
- /*--------------------------------------------------------------------------*/
- /**
- * The base implementation of `_.indexOf` without support for binary searches
- * or `fromIndex` constraints.
- *
- * @private
- * @param {Array} array The array to search.
- * @param {*} value The value to search for.
- * @param {number} [fromIndex=0] The index to search from.
- * @returns {number} Returns the index of the matched value or `-1`.
- */
- function baseIndexOf(array, value, fromIndex) {
- var index = (fromIndex || 0) - 1,
- length = array ? array.length : 0;
- while (++index < length) {
- if (array[index] === value) {
- return index;
- }
- }
- return -1;
- }
- /**
- * An implementation of `_.contains` for cache objects that mimics the return
- * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
- *
- * @private
- * @param {Object} cache The cache object to inspect.
- * @param {*} value The value to search for.
- * @returns {number} Returns `0` if `value` is found, else `-1`.
- */
- function cacheIndexOf(cache, value) {
- var type = typeof value;
- cache = cache.cache;
- if (type == 'boolean' || value == null) {
- return cache[value] ? 0 : -1;
- }
- if (type != 'number' && type != 'string') {
- type = 'object';
- }
- var key = type == 'number' ? value : keyPrefix + value;
- cache = (cache = cache[type]) && cache[key];
- return type == 'object'
- ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
- : (cache ? 0 : -1);
- }
- /**
- * Adds a given value to the corresponding cache object.
- *
- * @private
- * @param {*} value The value to add to the cache.
- */
- function cachePush(value) {
- var cache = this.cache,
- type = typeof value;
- if (type == 'boolean' || value == null) {
- cache[value] = true;
- } else {
- if (type != 'number' && type != 'string') {
- type = 'object';
- }
- var key = type == 'number' ? value : keyPrefix + value,
- typeCache = cache[type] || (cache[type] = {});
- if (type == 'object') {
- (typeCache[key] || (typeCache[key] = [])).push(value);
- } else {
- typeCache[key] = true;
- }
- }
- }
- /**
- * Used by `_.max` and `_.min` as the default callback when a given
- * collection is a string value.
- *
- * @private
- * @param {string} value The character to inspect.
- * @returns {number} Returns the code unit of given character.
- */
- function charAtCallback(value) {
- return value.charCodeAt(0);
- }
- /**
- * Used by `sortBy` to compare transformed `collection` elements, stable sorting
- * them in ascending order.
- *
- * @private
- * @param {Object} a The object to compare to `b`.
- * @param {Object} b The object to compare to `a`.
- * @returns {number} Returns the sort order indicator of `1` or `-1`.
- */
- function compareAscending(a, b) {
- var ac = a.criteria,
- bc = b.criteria,
- index = -1,
- length = ac.length;
- while (++index < length) {
- var value = ac[index],
- other = bc[index];
- if (value !== other) {
- if (value > other || typeof value == 'undefined') {
- return 1;
- }
- if (value < other || typeof other == 'undefined') {
- return -1;
- }
- }
- }
- // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
- // that causes it, under certain circumstances, to return the same value for
- // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
- //
- // This also ensures a stable sort in V8 and other engines.
- // See http://code.google.com/p/v8/issues/detail?id=90
- return a.index - b.index;
- }
- /**
- * Creates a cache object to optimize linear searches of large arrays.
- *
- * @private
- * @param {Array} [array=[]] The array to search.
- * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
- */
- function createCache(array) {
- var index = -1,
- length = array.length,
- first = array[0],
- mid = array[(length / 2) | 0],
- last = array[length - 1];
- if (first && typeof first == 'object' &&
- mid && typeof mid == 'object' && last && typeof last == 'object') {
- return false;
- }
- var cache = getObject();
- cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
- var result = getObject();
- result.array = array;
- result.cache = cache;
- result.push = cachePush;
- while (++index < length) {
- result.push(array[index]);
- }
- return result;
- }
- /**
- * Used by `template` to escape characters for inclusion in compiled
- * string literals.
- *
- * @private
- * @param {string} match The matched character to escape.
- * @returns {string} Returns the escaped character.
- */
- function escapeStringChar(match) {
- return '\\' + stringEscapes[match];
- }
- /**
- * Gets an array from the array pool or creates a new one if the pool is empty.
- *
- * @private
- * @returns {Array} The array from the pool.
- */
- function getArray() {
- return arrayPool.pop() || [];
- }
- /**
- * Gets an object from the object pool or creates a new one if the pool is empty.
- *
- * @private
- * @returns {Object} The object from the pool.
- */
- function getObject() {
- return objectPool.pop() || {
- 'array': null,
- 'cache': null,
- 'criteria': null,
- 'false': false,
- 'index': 0,
- 'null': false,
- 'number': null,
- 'object': null,
- 'push': null,
- 'string': null,
- 'true': false,
- 'undefined': false,
- 'value': null
- };
- }
- /**
- * Releases the given array back to the array pool.
- *
- * @private
- * @param {Array} [array] The array to release.
- */
- function releaseArray(array) {
- array.length = 0;
- if (arrayPool.length < maxPoolSize) {
- arrayPool.push(array);
- }
- }
- /**
- * Releases the given object back to the object pool.
- *
- * @private
- * @param {Object} [object] The object to release.
- */
- function releaseObject(object) {
- var cache = object.cache;
- if (cache) {
- releaseObject(cache);
- }
- object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
- if (objectPool.length < maxPoolSize) {
- objectPool.push(object);
- }
- }
- /**
- * Slices the `collection` from the `start` index up to, but not including,
- * the `end` index.
- *
- * Note: This function is used instead of `Array#slice` to support node lists
- * in IE < 9 and to ensure dense arrays are returned.
- *
- * @private
- * @param {Array|Object|string} collection The collection to slice.
- * @param {number} start The start index.
- * @param {number} end The end index.
- * @returns {Array} Returns the new array.
- */
- function slice(array, start, end) {
- start || (start = 0);
- if (typeof end == 'undefined') {
- end = array ? array.length : 0;
- }
- var index = -1,
- length = end - start || 0,
- result = Array(length < 0 ? 0 : length);
- while (++index < length) {
- result[index] = array[start + index];
- }
- return result;
- }
- /*--------------------------------------------------------------------------*/
- /**
- * Create a new `lodash` function using the given context object.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Object} [context=root] The context object.
- * @returns {Function} Returns the `lodash` function.
- */
- function runInContext(context) {
- // Avoid issues with some ES3 environments that attempt to use values, named
- // after built-in constructors like `Object`, for the creation of literals.
- // ES5 clears this up by stating that literals must use built-in constructors.
- // See http://es5.github.io/#x11.1.5.
- context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
- /** Native constructor references */
- var Array = context.Array,
- Boolean = context.Boolean,
- Date = context.Date,
- Function = context.Function,
- Math = context.Math,
- Number = context.Number,
- Object = context.Object,
- RegExp = context.RegExp,
- String = context.String,
- TypeError = context.TypeError;
- /**
- * Used for `Array` method references.
- *
- * Normally `Array.prototype` would suffice, however, using an array literal
- * avoids issues in Narwhal.
- */
- var arrayRef = [];
- /** Used for native method references */
- var objectProto = Object.prototype;
- /** Used to restore the original `_` reference in `noConflict` */
- var oldDash = context._;
- /** Used to resolve the internal [[Class]] of values */
- var toString = objectProto.toString;
- /** Used to detect if a method is native */
- var reNative = RegExp('^' +
- String(toString)
- .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
- .replace(/toString| for [^\]]+/g, '.*?') + '$'
- );
- /** Native method shortcuts */
- var ceil = Math.ceil,
- clearTimeout = context.clearTimeout,
- floor = Math.floor,
- fnToString = Function.prototype.toString,
- getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
- hasOwnProperty = objectProto.hasOwnProperty,
- push = arrayRef.push,
- setTimeout = context.setTimeout,
- splice = arrayRef.splice,
- unshift = arrayRef.unshift;
- /** Used to set meta data on functions */
- var defineProperty = (function() {
- // IE 8 only accepts DOM elements
- try {
- var o = {},
- func = isNative(func = Object.defineProperty) && func,
- result = func(o, o, o) && func;
- } catch(e) { }
- return result;
- }());
- /* Native method shortcuts for methods with the same name as other `lodash` methods */
- var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
- nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
- nativeIsFinite = context.isFinite,
- nativeIsNaN = context.isNaN,
- nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
- nativeMax = Math.max,
- nativeMin = Math.min,
- nativeParseInt = context.parseInt,
- nativeRandom = Math.random;
- /** Used to lookup a built-in constructor by [[Class]] */
- var ctorByClass = {};
- ctorByClass[arrayClass] = Array;
- ctorByClass[boolClass] = Boolean;
- ctorByClass[dateClass] = Date;
- ctorByClass[funcClass] = Function;
- ctorByClass[objectClass] = Object;
- ctorByClass[numberClass] = Number;
- ctorByClass[regexpClass] = RegExp;
- ctorByClass[stringClass] = String;
- /*--------------------------------------------------------------------------*/
- /**
- * Creates a `lodash` object which wraps the given value to enable intuitive
- * method chaining.
- *
- * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
- * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
- * and `unshift`
- *
- * Chaining is supported in custom builds as long as the `value` method is
- * implicitly or explicitly included in the build.
- *
- * The chainable wrapper functions are:
- * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
- * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
- * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
- * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
- * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
- * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
- * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
- * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
- * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
- * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
- * and `zip`
- *
- * The non-chainable wrapper functions are:
- * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
- * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
- * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
- * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
- * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
- * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
- * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
- * `template`, `unescape`, `uniqueId`, and `value`
- *
- * The wrapper functions `first` and `last` return wrapped values when `n` is
- * provided, otherwise they return unwrapped values.
- *
- * Explicit chaining can be enabled by using the `_.chain` method.
- *
- * @name _
- * @constructor
- * @category Chaining
- * @param {*} value The value to wrap in a `lodash` instance.
- * @returns {Object} Returns a `lodash` instance.
- * @example
- *
- * var wrapped = _([1, 2, 3]);
- *
- * // returns an unwrapped value
- * wrapped.reduce(function(sum, num) {
- * return sum + num;
- * });
- * // => 6
- *
- * // returns a wrapped value
- * var squares = wrapped.map(function(num) {
- * return num * num;
- * });
- *
- * _.isArray(squares);
- * // => false
- *
- * _.isArray(squares.value());
- * // => true
- */
- function lodash(value) {
- // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
- return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
- ? value
- : new lodashWrapper(value);
- }
- /**
- * A fast path for creating `lodash` wrapper objects.
- *
- * @private
- * @param {*} value The value to wrap in a `lodash` instance.
- * @param {boolean} chainAll A flag to enable chaining for all methods
- * @returns {Object} Returns a `lodash` instance.
- */
- function lodashWrapper(value, chainAll) {
- this.__chain__ = !!chainAll;
- this.__wrapped__ = value;
- }
- // ensure `new lodashWrapper` is an instance of `lodash`
- lodashWrapper.prototype = lodash.prototype;
- /**
- * An object used to flag environments features.
- *
- * @static
- * @memberOf _
- * @type Object
- */
- var support = lodash.support = {};
- /**
- * Detect if functions can be decompiled by `Function#toString`
- * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
- /**
- * Detect if `Function#name` is supported (all but IE).
- *
- * @memberOf _.support
- * @type boolean
- */
- support.funcNames = typeof Function.name == 'string';
- /**
- * By default, the template delimiters used by Lo-Dash are similar to those in
- * embedded Ruby (ERB). Change the following template settings to use alternative
- * delimiters.
- *
- * @static
- * @memberOf _
- * @type Object
- */
- lodash.templateSettings = {
- /**
- * Used to detect `data` property values to be HTML-escaped.
- *
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'escape': /<%-([\s\S]+?)%>/g,
- /**
- * Used to detect code to be evaluated.
- *
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'evaluate': /<%([\s\S]+?)%>/g,
- /**
- * Used to detect `data` property values to inject.
- *
- * @memberOf _.templateSettings
- * @type RegExp
- */
- 'interpolate': reInterpolate,
- /**
- * Used to reference the data object in the template text.
- *
- * @memberOf _.templateSettings
- * @type string
- */
- 'variable': '',
- /**
- * Used to import variables into the compiled template.
- *
- * @memberOf _.templateSettings
- * @type Object
- */
- 'imports': {
- /**
- * A reference to the `lodash` function.
- *
- * @memberOf _.templateSettings.imports
- * @type Function
- */
- '_': lodash
- }
- };
- /*--------------------------------------------------------------------------*/
- /**
- * The base implementation of `_.bind` that creates the bound function and
- * sets its meta data.
- *
- * @private
- * @param {Array} bindData The bind data array.
- * @returns {Function} Returns the new bound function.
- */
- function baseBind(bindData) {
- var func = bindData[0],
- partialArgs = bindData[2],
- thisArg = bindData[4];
- function bound() {
- // `Function#bind` spec
- // http://es5.github.io/#x15.3.4.5
- if (partialArgs) {
- // avoid `arguments` object deoptimizations by using `slice` instead
- // of `Array.prototype.slice.call` and not assigning `arguments` to a
- // variable as a ternary expression
- var args = slice(partialArgs);
- push.apply(args, arguments);
- }
- // mimic the constructor's `return` behavior
- // http://es5.github.io/#x13.2.2
- if (this instanceof bound) {
- // ensure `new bound` is an instance of `func`
- var thisBinding = baseCreate(func.prototype),
- result = func.apply(thisBinding, args || arguments);
- return isObject(result) ? result : thisBinding;
- }
- return func.apply(thisArg, args || arguments);
- }
- setBindData(bound, bindData);
- return bound;
- }
- /**
- * The base implementation of `_.clone` without argument juggling or support
- * for `thisArg` binding.
- *
- * @private
- * @param {*} value The value to clone.
- * @param {boolean} [isDeep=false] Specify a deep clone.
- * @param {Function} [callback] The function to customize cloning values.
- * @param {Array} [stackA=[]] Tracks traversed source objects.
- * @param {Array} [stackB=[]] Associates clones with source counterparts.
- * @returns {*} Returns the cloned value.
- */
- function baseClone(value, isDeep, callback, stackA, stackB) {
- if (callback) {
- var result = callback(value);
- if (typeof result != 'undefined') {
- return result;
- }
- }
- // inspect [[Class]]
- var isObj = isObject(value);
- if (isObj) {
- var className = toString.call(value);
- if (!cloneableClasses[className]) {
- return value;
- }
- var ctor = ctorByClass[className];
- switch (className) {
- case boolClass:
- case dateClass:
- return new ctor(+value);
- case numberClass:
- case stringClass:
- return new ctor(value);
- case regexpClass:
- result = ctor(value.source, reFlags.exec(value));
- result.lastIndex = value.lastIndex;
- return result;
- }
- } else {
- return value;
- }
- var isArr = isArray(value);
- if (isDeep) {
- // check for circular references and return corresponding clone
- var initedStack = !stackA;
- stackA || (stackA = getArray());
- stackB || (stackB = getArray());
- var length = stackA.length;
- while (length--) {
- if (stackA[length] == value) {
- return stackB[length];
- }
- }
- result = isArr ? ctor(value.length) : {};
- }
- else {
- result = isArr ? slice(value) : assign({}, value);
- }
- // add array properties assigned by `RegExp#exec`
- if (isArr) {
- if (hasOwnProperty.call(value, 'index')) {
- result.index = value.index;
- }
- if (hasOwnProperty.call(value, 'input')) {
- result.input = value.input;
- }
- }
- // exit for shallow clone
- if (!isDeep) {
- return result;
- }
- // add the source value to the stack of traversed objects
- // and associate it with its clone
- stackA.push(value);
- stackB.push(result);
- // recursively populate clone (susceptible to call stack limits)
- (isArr ? forEach : forOwn)(value, function(objValue, key) {
- result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
- });
- if (initedStack) {
- releaseArray(stackA);
- releaseArray(stackB);
- }
- return result;
- }
- /**
- * The base implementation of `_.create` without support for assigning
- * properties to the created object.
- *
- * @private
- * @param {Object} prototype The object to inherit from.
- * @returns {Object} Returns the new object.
- */
- function baseCreate(prototype, properties) {
- return isObject(prototype) ? nativeCreate(prototype) : {};
- }
- // fallback for browsers without `Object.create`
- if (!nativeCreate) {
- baseCreate = (function() {
- function Object() {}
- return function(prototype) {
- if (isObject(prototype)) {
- Object.prototype = prototype;
- var result = new Object;
- Object.prototype = null;
- }
- return result || context.Object();
- };
- }());
- }
- /**
- * The base implementation of `_.createCallback` without support for creating
- * "_.pluck" or "_.where" style callbacks.
- *
- * @private
- * @param {*} [func=identity] The value to convert to a callback.
- * @param {*} [thisArg] The `this` binding of the created callback.
- * @param {number} [argCount] The number of arguments the callback accepts.
- * @returns {Function} Returns a callback function.
- */
- function baseCreateCallback(func, thisArg, argCount) {
- if (typeof func != 'function') {
- return identity;
- }
- // exit early for no `thisArg` or already bound by `Function#bind`
- if (typeof thisArg == 'undefined' || !('prototype' in func)) {
- return func;
- }
- var bindData = func.__bindData__;
- if (typeof bindData == 'undefined') {
- if (support.funcNames) {
- bindData = !func.name;
- }
- bindData = bindData || !support.funcDecomp;
- if (!bindData) {
- var source = fnToString.call(func);
- if (!support.funcNames) {
- bindData = !reFuncName.test(source);
- }
- if (!bindData) {
- // checks if `func` references the `this` keyword and stores the result
- bindData = reThis.test(source);
- setBindData(func, bindData);
- }
- }
- }
- // exit early if there are no `this` references or `func` is bound
- if (bindData === false || (bindData !== true && bindData[1] & 1)) {
- return func;
- }
- switch (argCount) {
- case 1: return function(value) {
- return func.call(thisArg, value);
- };
- case 2: return function(a, b) {
- return func.call(thisArg, a, b);
- };
- case 3: return function(value, index, collection) {
- return func.call(thisArg, value, index, collection);
- };
- case 4: return function(accumulator, value, index, collection) {
- return func.call(thisArg, accumulator, value, index, collection);
- };
- }
- return bind(func, thisArg);
- }
- /**
- * The base implementation of `createWrapper` that creates the wrapper and
- * sets its meta data.
- *
- * @private
- * @param {Array} bindData The bind data array.
- * @returns {Function} Returns the new function.
- */
- function baseCreateWrapper(bindData) {
- var func = bindData[0],
- bitmask = bindData[1],
- partialArgs = bindData[2],
- partialRightArgs = bindData[3],
- thisArg = bindData[4],
- arity = bindData[5];
- var isBind = bitmask & 1,
- isBindKey = bitmask & 2,
- isCurry = bitmask & 4,
- isCurryBound = bitmask & 8,
- key = func;
- function bound() {
- var thisBinding = isBind ? thisArg : this;
- if (partialArgs) {
- var args = slice(partialArgs);
- push.apply(args, arguments);
- }
- if (partialRightArgs || isCurry) {
- args || (args = slice(arguments));
- if (partialRightArgs) {
- push.apply(args, partialRightArgs);
- }
- if (isCurry && args.length < arity) {
- bitmask |= 16 & ~32;
- return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
- }
- }
- args || (args = arguments);
- if (isBindKey) {
- func = thisBinding[key];
- }
- if (this instanceof bound) {
- thisBinding = baseCreate(func.prototype);
- var result = func.apply(thisBinding, args);
- return isObject(result) ? result : thisBinding;
- }
- return func.apply(thisBinding, args);
- }
- setBindData(bound, bindData);
- return bound;
- }
- /**
- * The base implementation of `_.difference` that accepts a single array
- * of values to exclude.
- *
- * @private
- * @param {Array} array The array to process.
- * @param {Array} [values] The array of values to exclude.
- * @returns {Array} Returns a new array of filtered values.
- */
- function baseDifference(array, values) {
- var index = -1,
- indexOf = getIndexOf(),
- length = array ? array.length : 0,
- isLarge = length >= largeArraySize && indexOf === baseIndexOf,
- result = [];
- if (isLarge) {
- var cache = createCache(values);
- if (cache) {
- indexOf = cacheIndexOf;
- values = cache;
- } else {
- isLarge = false;
- }
- }
- while (++index < length) {
- var value = array[index];
- if (indexOf(values, value) < 0) {
- result.push(value);
- }
- }
- if (isLarge) {
- releaseObject(values);
- }
- return result;
- }
- /**
- * The base implementation of `_.flatten` without support for callback
- * shorthands or `thisArg` binding.
- *
- * @private
- * @param {Array} array The array to flatten.
- * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
- * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
- * @param {number} [fromIndex=0] The index to start from.
- * @returns {Array} Returns a new flattened array.
- */
- function baseFlatten(array, isShallow, isStrict, fromIndex) {
- var index = (fromIndex || 0) - 1,
- length = array ? array.length : 0,
- result = [];
- while (++index < length) {
- var value = array[index];
- if (value && typeof value == 'object' && typeof value.length == 'number'
- && (isArray(value) || isArguments(value))) {
- // recursively flatten arrays (susceptible to call stack limits)
- if (!isShallow) {
- value = baseFlatten(value, isShallow, isStrict);
- }
- var valIndex = -1,
- valLength = value.length,
- resIndex = result.length;
- result.length += valLength;
- while (++valIndex < valLength) {
- result[resIndex++] = value[valIndex];
- }
- } else if (!isStrict) {
- result.push(value);
- }
- }
- return result;
- }
- /**
- * The base implementation of `_.isEqual`, without support for `thisArg` binding,
- * that allows partial "_.where" style comparisons.
- *
- * @private
- * @param {*} a The value to compare.
- * @param {*} b The other value to compare.
- * @param {Function} [callback] The function to customize comparing values.
- * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
- * @param {Array} [stackA=[]] Tracks traversed `a` objects.
- * @param {Array} [stackB=[]] Tracks traversed `b` objects.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- */
- function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
- // used to indicate that when comparing objects, `a` has at least the properties of `b`
- if (callback) {
- var result = callback(a, b);
- if (typeof result != 'undefined') {
- return !!result;
- }
- }
- // exit early for identical values
- if (a === b) {
- // treat `+0` vs. `-0` as not equal
- return a !== 0 || (1 / a == 1 / b);
- }
- var type = typeof a,
- otherType = typeof b;
- // exit early for unlike primitive values
- if (a === a &&
- !(a && objectTypes[type]) &&
- !(b && objectTypes[otherType])) {
- return false;
- }
- // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
- // http://es5.github.io/#x15.3.4.4
- if (a == null || b == null) {
- return a === b;
- }
- // compare [[Class]] names
- var className = toString.call(a),
- otherClass = toString.call(b);
- if (className == argsClass) {
- className = objectClass;
- }
- if (otherClass == argsClass) {
- otherClass = objectClass;
- }
- if (className != otherClass) {
- return false;
- }
- switch (className) {
- case boolClass:
- case dateClass:
- // coerce dates and booleans to numbers, dates to milliseconds and booleans
- // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
- return +a == +b;
- case numberClass:
- // treat `NaN` vs. `NaN` as equal
- return (a != +a)
- ? b != +b
- // but treat `+0` vs. `-0` as not equal
- : (a == 0 ? (1 / a == 1 / b) : a == +b);
- case regexpClass:
- case stringClass:
- // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
- // treat string primitives and their corresponding object instances as equal
- return a == String(b);
- }
- var isArr = className == arrayClass;
- if (!isArr) {
- // unwrap any `lodash` wrapped values
- var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
- bWrapped = hasOwnProperty.call(b, '__wrapped__');
- if (aWrapped || bWrapped) {
- return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
- }
- // exit for functions and DOM nodes
- if (className != objectClass) {
- return false;
- }
- // in older versions of Opera, `arguments` objects have `Array` constructors
- var ctorA = a.constructor,
- ctorB = b.constructor;
- // non `Object` object instances with different constructors are not equal
- if (ctorA != ctorB &&
- !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
- ('constructor' in a && 'constructor' in b)
- ) {
- return false;
- }
- }
- // assume cyclic structures are equal
- // the algorithm for detecting cyclic structures is adapted from ES 5.1
- // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
- var initedStack = !stackA;
- stackA || (stackA = getArray());
- stackB || (stackB = getArray());
- var length = stackA.length;
- while (length--) {
- if (stackA[length] == a) {
- return stackB[length] == b;
- }
- }
- var size = 0;
- result = true;
- // add `a` and `b` to the stack of traversed objects
- stackA.push(a);
- stackB.push(b);
- // recursively compare objects and arrays (susceptible to call stack limits)
- if (isArr) {
- // compare lengths to determine if a deep comparison is necessary
- length = a.length;
- size = b.length;
- result = size == length;
- if (result || isWhere) {
- // deep compare the contents, ignoring non-numeric properties
- while (size--) {
- var index = length,
- value = b[size];
- if (isWhere) {
- while (index--) {
- if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
- break;
- }
- }
- } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
- break;
- }
- }
- }
- }
- else {
- // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
- // which, in this case, is more costly
- forIn(b, function(value, key, b) {
- if (hasOwnProperty.call(b, key)) {
- // count the number of properties.
- size++;
- // deep compare each property value.
- return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
- }
- });
- if (result && !isWhere) {
- // ensure both objects have the same number of properties
- forIn(a, function(value, key, a) {
- if (hasOwnProperty.call(a, key)) {
- // `size` will be `-1` if `a` has more properties than `b`
- return (result = --size > -1);
- }
- });
- }
- }
- stackA.pop();
- stackB.pop();
- if (initedStack) {
- releaseArray(stackA);
- releaseArray(stackB);
- }
- return result;
- }
- /**
- * The base implementation of `_.merge` without argument juggling or support
- * for `thisArg` binding.
- *
- * @private
- * @param {Object} object The destination object.
- * @param {Object} source The source object.
- * @param {Function} [callback] The function to customize merging properties.
- * @param {Array} [stackA=[]] Tracks traversed source objects.
- * @param {Array} [stackB=[]] Associates values with source counterparts.
- */
- function baseMerge(object, source, callback, stackA, stackB) {
- (isArray(source) ? forEach : forOwn)(source, function(source, key) {
- var found,
- isArr,
- result = source,
- value = object[key];
- if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
- // avoid merging previously merged cyclic sources
- var stackLength = stackA.length;
- while (stackLength--) {
- if ((found = stackA[stackLength] == source)) {
- value = stackB[stackLength];
- break;
- }
- }
- if (!found) {
- var isShallow;
- if (callback) {
- result = callback(value, source);
- if ((isShallow = typeof result != 'undefined')) {
- value = result;
- }
- }
- if (!isShallow) {
- value = isArr
- ? (isArray(value) ? value : [])
- : (isPlainObject(value) ? value : {});
- }
- // add `source` and associated `value` to the stack of traversed objects
- stackA.push(source);
- stackB.push(value);
- // recursively merge objects and arrays (susceptible to call stack limits)
- if (!isShallow) {
- baseMerge(value, source, callback, stackA, stackB);
- }
- }
- }
- else {
- if (callback) {
- result = callback(value, source);
- if (typeof result == 'undefined') {
- result = source;
- }
- }
- if (typeof result != 'undefined') {
- value = result;
- }
- }
- object[key] = value;
- });
- }
- /**
- * The base implementation of `_.random` without argument juggling or support
- * for returning floating-point numbers.
- *
- * @private
- * @param {number} min The minimum possible value.
- * @param {number} max The maximum possible value.
- * @returns {number} Returns a random number.
- */
- function baseRandom(min, max) {
- return min + floor(nativeRandom() * (max - min + 1));
- }
- /**
- * The base implementation of `_.uniq` without support for callback shorthands
- * or `thisArg` binding.
- *
- * @private
- * @param {Array} array The array to process.
- * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
- * @param {Function} [callback] The function called per iteration.
- * @returns {Array} Returns a duplicate-value-free array.
- */
- function baseUniq(array, isSorted, callback) {
- var index = -1,
- indexOf = getIndexOf(),
- length = array ? array.length : 0,
- result = [];
- var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
- seen = (callback || isLarge) ? getArray() : result;
- if (isLarge) {
- var cache = createCache(seen);
- indexOf = cacheIndexOf;
- seen = cache;
- }
- while (++index < length) {
- var value = array[index],
- computed = callback ? callback(value, index, array) : value;
- if (isSorted
- ? !index || seen[seen.length - 1] !== computed
- : indexOf(seen, computed) < 0
- ) {
- if (callback || isLarge) {
- seen.push(computed);
- }
- result.push(value);
- }
- }
- if (isLarge) {
- releaseArray(seen.array);
- releaseObject(seen);
- } else if (callback) {
- releaseArray(seen);
- }
- return result;
- }
- /**
- * Creates a function that aggregates a collection, creating an object composed
- * of keys generated from the results of running each element of the collection
- * through a callback. The given `setter` function sets the keys and values
- * of the composed object.
- *
- * @private
- * @param {Function} setter The setter function.
- * @returns {Function} Returns the new aggregator function.
- */
- function createAggregator(setter) {
- return function(collection, callback, thisArg) {
- var result = {};
- callback = lodash.createCallback(callback, thisArg, 3);
- var index = -1,
- length = collection ? collection.length : 0;
- if (typeof length == 'number') {
- while (++index < length) {
- var value = collection[index];
- setter(result, value, callback(value, index, collection), collection);
- }
- } else {
- forOwn(collection, function(value, key, collection) {
- setter(result, value, callback(value, key, collection), collection);
- });
- }
- return result;
- };
- }
- /**
- * Creates a function that, when called, either curries or invokes `func`
- * with an optional `this` binding and partially applied arguments.
- *
- * @private
- * @param {Function|string} func The function or method name to reference.
- * @param {number} bitmask The bitmask of method flags to compose.
- * The bitmask may be composed of the following flags:
- * 1 - `_.bind`
- * 2 - `_.bindKey`
- * 4 - `_.curry`
- * 8 - `_.curry` (bound)
- * 16 - `_.partial`
- * 32 - `_.partialRight`
- * @param {Array} [partialArgs] An array of arguments to prepend to those
- * provided to the new function.
- * @param {Array} [partialRightArgs] An array of arguments to append to those
- * provided to the new function.
- * @param {*} [thisArg] The `this` binding of `func`.
- * @param {number} [arity] The arity of `func`.
- * @returns {Function} Returns the new function.
- */
- function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
- var isBind = bitmask & 1,
- isBindKey = bitmask & 2,
- isCurry = bitmask & 4,
- isCurryBound = bitmask & 8,
- isPartial = bitmask & 16,
- isPartialRight = bitmask & 32;
- if (!isBindKey && !isFunction(func)) {
- throw new TypeError;
- }
- if (isPartial && !partialArgs.length) {
- bitmask &= ~16;
- isPartial = partialArgs = false;
- }
- if (isPartialRight && !partialRightArgs.length) {
- bitmask &= ~32;
- isPartialRight = partialRightArgs = false;
- }
- var bindData = func && func.__bindData__;
- if (bindData && bindData !== true) {
- // clone `bindData`
- bindData = slice(bindData);
- if (bindData[2]) {
- bindData[2] = slice(bindData[2]);
- }
- if (bindData[3]) {
- bindData[3] = slice(bindData[3]);
- }
- // set `thisBinding` is not previously bound
- if (isBind && !(bindData[1] & 1)) {
- bindData[4] = thisArg;
- }
- // set if previously bound but not currently (subsequent curried functions)
- if (!isBind && bindData[1] & 1) {
- bitmask |= 8;
- }
- // set curried arity if not yet set
- if (isCurry && !(bindData[1] & 4)) {
- bindData[5] = arity;
- }
- // append partial left arguments
- if (isPartial) {
- push.apply(bindData[2] || (bindData[2] = []), partialArgs);
- }
- // append partial right arguments
- if (isPartialRight) {
- unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
- }
- // merge flags
- bindData[1] |= bitmask;
- return createWrapper.apply(null, bindData);
- }
- // fast path for `_.bind`
- var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
- return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
- }
- /**
- * Used by `escape` to convert characters to HTML entities.
- *
- * @private
- * @param {string} match The matched character to escape.
- * @returns {string} Returns the escaped character.
- */
- function escapeHtmlChar(match) {
- return htmlEscapes[match];
- }
- /**
- * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
- * customized, this method returns the custom method, otherwise it returns
- * the `baseIndexOf` function.
- *
- * @private
- * @returns {Function} Returns the "indexOf" function.
- */
- function getIndexOf() {
- var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
- return result;
- }
- /**
- * Checks if `value` is a native function.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
- */
- function isNative(value) {
- return typeof value == 'function' && reNative.test(value);
- }
- /**
- * Sets `this` binding data on a given function.
- *
- * @private
- * @param {Function} func The function to set data on.
- * @param {Array} value The data array to set.
- */
- var setBindData = !defineProperty ? noop : function(func, value) {
- descriptor.value = value;
- defineProperty(func, '__bindData__', descriptor);
- };
- /**
- * A fallback implementation of `isPlainObject` which checks if a given value
- * is an object created by the `Object` constructor, assuming objects created
- * by the `Object` constructor have no inherited enumerable properties and that
- * there are no `Object.prototype` extensions.
- *
- * @private
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
- */
- function shimIsPlainObject(value) {
- var ctor,
- result;
- // avoid non Object objects, `arguments` objects, and DOM elements
- if (!(value && toString.call(value) == objectClass) ||
- (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
- return false;
- }
- // In most environments an object's own properties are iterated before
- // its inherited properties. If the last iterated property is an object's
- // own property then there are no inherited enumerable properties.
- forIn(value, function(value, key) {
- result = key;
- });
- return typeof result == 'undefined' || hasOwnProperty.call(value, result);
- }
- /**
- * Used by `unescape` to convert HTML entities to characters.
- *
- * @private
- * @param {string} match The matched character to unescape.
- * @returns {string} Returns the unescaped character.
- */
- function unescapeHtmlChar(match) {
- return htmlUnescapes[match];
- }
- /*--------------------------------------------------------------------------*/
- /**
- * Checks if `value` is an `arguments` object.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
- * @example
- *
- * (function() { return _.isArguments(arguments); })(1, 2, 3);
- * // => true
- *
- * _.isArguments([1, 2, 3]);
- * // => false
- */
- function isArguments(value) {
- return value && typeof value == 'object' && typeof value.length == 'number' &&
- toString.call(value) == argsClass || false;
- }
- /**
- * Checks if `value` is an array.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
- * @example
- *
- * (function() { return _.isArray(arguments); })();
- * // => false
- *
- * _.isArray([1, 2, 3]);
- * // => true
- */
- var isArray = nativeIsArray || function(value) {
- return value && typeof value == 'object' && typeof value.length == 'number' &&
- toString.call(value) == arrayClass || false;
- };
- /**
- * A fallback implementation of `Object.keys` which produces an array of the
- * given object's own enumerable property names.
- *
- * @private
- * @type Function
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns an array of property names.
- */
- var shimKeys = function(object) {
- var index, iterable = object, result = [];
- if (!iterable) return result;
- if (!(objectTypes[typeof object])) return result;
- for (index in iterable) {
- if (hasOwnProperty.call(iterable, index)) {
- result.push(index);
- }
- }
- return result
- };
- /**
- * Creates an array composed of the own enumerable property names of an object.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns an array of property names.
- * @example
- *
- * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
- * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
- */
- var keys = !nativeKeys ? shimKeys : function(object) {
- if (!isObject(object)) {
- return [];
- }
- return nativeKeys(object);
- };
- /**
- * Used to convert characters to HTML entities:
- *
- * Though the `>` character is escaped for symmetry, characters like `>` and `/`
- * don't require escaping in HTML and have no special meaning unless they're part
- * of a tag or an unquoted attribute value.
- * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
- */
- var htmlEscapes = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": '''
- };
- /** Used to convert HTML entities to characters */
- var htmlUnescapes = invert(htmlEscapes);
- /** Used to match HTML entities and HTML characters */
- var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
- reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
- /*--------------------------------------------------------------------------*/
- /**
- * Assigns own enumerable properties of source object(s) to the destination
- * object. Subsequent sources will overwrite property assignments of previous
- * sources. If a callback is provided it will be executed to produce the
- * assigned values. The callback is bound to `thisArg` and invoked with two
- * arguments; (objectValue, sourceValue).
- *
- * @static
- * @memberOf _
- * @type Function
- * @alias extend
- * @category Objects
- * @param {Object} object The destination object.
- * @param {...Object} [source] The source objects.
- * @param {Function} [callback] The function to customize assigning values.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the destination object.
- * @example
- *
- * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
- * // => { 'name': 'fred', 'employer': 'slate' }
- *
- * var defaults = _.partialRight(_.assign, function(a, b) {
- * return typeof a == 'undefined' ? b : a;
- * });
- *
- * var object = { 'name': 'barney' };
- * defaults(object, { 'name': 'fred', 'employer': 'slate' });
- * // => { 'name': 'barney', 'employer': 'slate' }
- */
- var assign = function(object, source, guard) {
- var index, iterable = object, result = iterable;
- if (!iterable) return result;
- var args = arguments,
- argsIndex = 0,
- argsLength = typeof guard == 'number' ? 2 : args.length;
- if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
- var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
- } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
- callback = args[--argsLength];
- }
- while (++argsIndex < argsLength) {
- iterable = args[argsIndex];
- if (iterable && objectTypes[typeof iterable]) {
- var ownIndex = -1,
- ownProps = objectTypes[typeof iterable] && keys(iterable),
- length = ownProps ? ownProps.length : 0;
- while (++ownIndex < length) {
- index = ownProps[ownIndex];
- result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
- }
- }
- }
- return result
- };
- /**
- * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
- * be cloned, otherwise they will be assigned by reference. If a callback
- * is provided it will be executed to produce the cloned values. If the
- * callback returns `undefined` cloning will be handled by the method instead.
- * The callback is bound to `thisArg` and invoked with one argument; (value).
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to clone.
- * @param {boolean} [isDeep=false] Specify a deep clone.
- * @param {Function} [callback] The function to customize cloning values.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the cloned value.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * var shallow = _.clone(characters);
- * shallow[0] === characters[0];
- * // => true
- *
- * var deep = _.clone(characters, true);
- * deep[0] === characters[0];
- * // => false
- *
- * _.mixin({
- * 'clone': _.partialRight(_.clone, function(value) {
- * return _.isElement(value) ? value.cloneNode(false) : undefined;
- * })
- * });
- *
- * var clone = _.clone(document.body);
- * clone.childNodes.length;
- * // => 0
- */
- function clone(value, isDeep, callback, thisArg) {
- // allows working with "Collections" methods without using their `index`
- // and `collection` arguments for `isDeep` and `callback`
- if (typeof isDeep != 'boolean' && isDeep != null) {
- thisArg = callback;
- callback = isDeep;
- isDeep = false;
- }
- return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
- }
- /**
- * Creates a deep clone of `value`. If a callback is provided it will be
- * executed to produce the cloned values. If the callback returns `undefined`
- * cloning will be handled by the method instead. The callback is bound to
- * `thisArg` and invoked with one argument; (value).
- *
- * Note: This method is loosely based on the structured clone algorithm. Functions
- * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
- * objects created by constructors other than `Object` are cloned to plain `Object` objects.
- * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to deep clone.
- * @param {Function} [callback] The function to customize cloning values.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the deep cloned value.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * var deep = _.cloneDeep(characters);
- * deep[0] === characters[0];
- * // => false
- *
- * var view = {
- * 'label': 'docs',
- * 'node': element
- * };
- *
- * var clone = _.cloneDeep(view, function(value) {
- * return _.isElement(value) ? value.cloneNode(true) : undefined;
- * });
- *
- * clone.node == view.node;
- * // => false
- */
- function cloneDeep(value, callback, thisArg) {
- return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
- }
- /**
- * Creates an object that inherits from the given `prototype` object. If a
- * `properties` object is provided its own enumerable properties are assigned
- * to the created object.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} prototype The object to inherit from.
- * @param {Object} [properties] The properties to assign to the object.
- * @returns {Object} Returns the new object.
- * @example
- *
- * function Shape() {
- * this.x = 0;
- * this.y = 0;
- * }
- *
- * function Circle() {
- * Shape.call(this);
- * }
- *
- * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
- *
- * var circle = new Circle;
- * circle instanceof Circle;
- * // => true
- *
- * circle instanceof Shape;
- * // => true
- */
- function create(prototype, properties) {
- var result = baseCreate(prototype);
- return properties ? assign(result, properties) : result;
- }
- /**
- * Assigns own enumerable properties of source object(s) to the destination
- * object for all destination properties that resolve to `undefined`. Once a
- * property is set, additional defaults of the same property will be ignored.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Objects
- * @param {Object} object The destination object.
- * @param {...Object} [source] The source objects.
- * @param- {Object} [guard] Allows working with `_.reduce` without using its
- * `key` and `object` arguments as sources.
- * @returns {Object} Returns the destination object.
- * @example
- *
- * var object = { 'name': 'barney' };
- * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
- * // => { 'name': 'barney', 'employer': 'slate' }
- */
- var defaults = function(object, source, guard) {
- var index, iterable = object, result = iterable;
- if (!iterable) return result;
- var args = arguments,
- argsIndex = 0,
- argsLength = typeof guard == 'number' ? 2 : args.length;
- while (++argsIndex < argsLength) {
- iterable = args[argsIndex];
- if (iterable && objectTypes[typeof iterable]) {
- var ownIndex = -1,
- ownProps = objectTypes[typeof iterable] && keys(iterable),
- length = ownProps ? ownProps.length : 0;
- while (++ownIndex < length) {
- index = ownProps[ownIndex];
- if (typeof result[index] == 'undefined') result[index] = iterable[index];
- }
- }
- }
- return result
- };
- /**
- * This method is like `_.findIndex` except that it returns the key of the
- * first element that passes the callback check, instead of the element itself.
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to search.
- * @param {Function|Object|string} [callback=identity] The function called per
- * iteration. If a property name or object is provided it will be used to
- * create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {string|undefined} Returns the key of the found element, else `undefined`.
- * @example
- *
- * var characters = {
- * 'barney': { 'age': 36, 'blocked': false },
- * 'fred': { 'age': 40, 'blocked': true },
- * 'pebbles': { 'age': 1, 'blocked': false }
- * };
- *
- * _.findKey(characters, function(chr) {
- * return chr.age < 40;
- * });
- * // => 'barney' (property order is not guaranteed across environments)
- *
- * // using "_.where" callback shorthand
- * _.findKey(characters, { 'age': 1 });
- * // => 'pebbles'
- *
- * // using "_.pluck" callback shorthand
- * _.findKey(characters, 'blocked');
- * // => 'fred'
- */
- function findKey(object, callback, thisArg) {
- var result;
- callback = lodash.createCallback(callback, thisArg, 3);
- forOwn(object, function(value, key, object) {
- if (callback(value, key, object)) {
- result = key;
- return false;
- }
- });
- return result;
- }
- /**
- * This method is like `_.findKey` except that it iterates over elements
- * of a `collection` in the opposite order.
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to search.
- * @param {Function|Object|string} [callback=identity] The function called per
- * iteration. If a property name or object is provided it will be used to
- * create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {string|undefined} Returns the key of the found element, else `undefined`.
- * @example
- *
- * var characters = {
- * 'barney': { 'age': 36, 'blocked': true },
- * 'fred': { 'age': 40, 'blocked': false },
- * 'pebbles': { 'age': 1, 'blocked': true }
- * };
- *
- * _.findLastKey(characters, function(chr) {
- * return chr.age < 40;
- * });
- * // => returns `pebbles`, assuming `_.findKey` returns `barney`
- *
- * // using "_.where" callback shorthand
- * _.findLastKey(characters, { 'age': 40 });
- * // => 'fred'
- *
- * // using "_.pluck" callback shorthand
- * _.findLastKey(characters, 'blocked');
- * // => 'pebbles'
- */
- function findLastKey(object, callback, thisArg) {
- var result;
- callback = lodash.createCallback(callback, thisArg, 3);
- forOwnRight(object, function(value, key, object) {
- if (callback(value, key, object)) {
- result = key;
- return false;
- }
- });
- return result;
- }
- /**
- * Iterates over own and inherited enumerable properties of an object,
- * executing the callback for each property. The callback is bound to `thisArg`
- * and invoked with three arguments; (value, key, object). Callbacks may exit
- * iteration early by explicitly returning `false`.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns `object`.
- * @example
- *
- * function Shape() {
- * this.x = 0;
- * this.y = 0;
- * }
- *
- * Shape.prototype.move = function(x, y) {
- * this.x += x;
- * this.y += y;
- * };
- *
- * _.forIn(new Shape, function(value, key) {
- * console.log(key);
- * });
- * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
- */
- var forIn = function(collection, callback, thisArg) {
- var index, iterable = collection, result = iterable;
- if (!iterable) return result;
- if (!objectTypes[typeof iterable]) return result;
- callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
- for (index in iterable) {
- if (callback(iterable[index], index, collection) === false) return result;
- }
- return result
- };
- /**
- * This method is like `_.forIn` except that it iterates over elements
- * of a `collection` in the opposite order.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns `object`.
- * @example
- *
- * function Shape() {
- * this.x = 0;
- * this.y = 0;
- * }
- *
- * Shape.prototype.move = function(x, y) {
- * this.x += x;
- * this.y += y;
- * };
- *
- * _.forInRight(new Shape, function(value, key) {
- * console.log(key);
- * });
- * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
- */
- function forInRight(object, callback, thisArg) {
- var pairs = [];
- forIn(object, function(value, key) {
- pairs.push(key, value);
- });
- var length = pairs.length;
- callback = baseCreateCallback(callback, thisArg, 3);
- while (length--) {
- if (callback(pairs[length--], pairs[length], object) === false) {
- break;
- }
- }
- return object;
- }
- /**
- * Iterates over own enumerable properties of an object, executing the callback
- * for each property. The callback is bound to `thisArg` and invoked with three
- * arguments; (value, key, object). Callbacks may exit iteration early by
- * explicitly returning `false`.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns `object`.
- * @example
- *
- * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
- * console.log(key);
- * });
- * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
- */
- var forOwn = function(collection, callback, thisArg) {
- var index, iterable = collection, result = iterable;
- if (!iterable) return result;
- if (!objectTypes[typeof iterable]) return result;
- callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
- var ownIndex = -1,
- ownProps = objectTypes[typeof iterable] && keys(iterable),
- length = ownProps ? ownProps.length : 0;
- while (++ownIndex < length) {
- index = ownProps[ownIndex];
- if (callback(iterable[index], index, collection) === false) return result;
- }
- return result
- };
- /**
- * This method is like `_.forOwn` except that it iterates over elements
- * of a `collection` in the opposite order.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns `object`.
- * @example
- *
- * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
- * console.log(key);
- * });
- * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
- */
- function forOwnRight(object, callback, thisArg) {
- var props = keys(object),
- length = props.length;
- callback = baseCreateCallback(callback, thisArg, 3);
- while (length--) {
- var key = props[length];
- if (callback(object[key], key, object) === false) {
- break;
- }
- }
- return object;
- }
- /**
- * Creates a sorted array of property names of all enumerable properties,
- * own and inherited, of `object` that have function values.
- *
- * @static
- * @memberOf _
- * @alias methods
- * @category Objects
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns an array of property names that have function values.
- * @example
- *
- * _.functions(_);
- * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
- */
- function functions(object) {
- var result = [];
- forIn(object, function(value, key) {
- if (isFunction(value)) {
- result.push(key);
- }
- });
- return result.sort();
- }
- /**
- * Checks if the specified property name exists as a direct property of `object`,
- * instead of an inherited property.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to inspect.
- * @param {string} key The name of the property to check.
- * @returns {boolean} Returns `true` if key is a direct property, else `false`.
- * @example
- *
- * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
- * // => true
- */
- function has(object, key) {
- return object ? hasOwnProperty.call(object, key) : false;
- }
- /**
- * Creates an object composed of the inverted keys and values of the given object.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to invert.
- * @returns {Object} Returns the created inverted object.
- * @example
- *
- * _.invert({ 'first': 'fred', 'second': 'barney' });
- * // => { 'fred': 'first', 'barney': 'second' }
- */
- function invert(object) {
- var index = -1,
- props = keys(object),
- length = props.length,
- result = {};
- while (++index < length) {
- var key = props[index];
- result[object[key]] = key;
- }
- return result;
- }
- /**
- * Checks if `value` is a boolean value.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
- * @example
- *
- * _.isBoolean(null);
- * // => false
- */
- function isBoolean(value) {
- return value === true || value === false ||
- value && typeof value == 'object' && toString.call(value) == boolClass || false;
- }
- /**
- * Checks if `value` is a date.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
- * @example
- *
- * _.isDate(new Date);
- * // => true
- */
- function isDate(value) {
- return value && typeof value == 'object' && toString.call(value) == dateClass || false;
- }
- /**
- * Checks if `value` is a DOM element.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
- * @example
- *
- * _.isElement(document.body);
- * // => true
- */
- function isElement(value) {
- return value && value.nodeType === 1 || false;
- }
- /**
- * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
- * length of `0` and objects with no own enumerable properties are considered
- * "empty".
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Array|Object|string} value The value to inspect.
- * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
- * @example
- *
- * _.isEmpty([1, 2, 3]);
- * // => false
- *
- * _.isEmpty({});
- * // => true
- *
- * _.isEmpty('');
- * // => true
- */
- function isEmpty(value) {
- var result = true;
- if (!value) {
- return result;
- }
- var className = toString.call(value),
- length = value.length;
- if ((className == arrayClass || className == stringClass || className == argsClass ) ||
- (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
- return !length;
- }
- forOwn(value, function() {
- return (result = false);
- });
- return result;
- }
- /**
- * Performs a deep comparison between two values to determine if they are
- * equivalent to each other. If a callback is provided it will be executed
- * to compare values. If the callback returns `undefined` comparisons will
- * be handled by the method instead. The callback is bound to `thisArg` and
- * invoked with two arguments; (a, b).
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} a The value to compare.
- * @param {*} b The other value to compare.
- * @param {Function} [callback] The function to customize comparing values.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
- * @example
- *
- * var object = { 'name': 'fred' };
- * var copy = { 'name': 'fred' };
- *
- * object == copy;
- * // => false
- *
- * _.isEqual(object, copy);
- * // => true
- *
- * var words = ['hello', 'goodbye'];
- * var otherWords = ['hi', 'goodbye'];
- *
- * _.isEqual(words, otherWords, function(a, b) {
- * var reGreet = /^(?:hello|hi)$/i,
- * aGreet = _.isString(a) && reGreet.test(a),
- * bGreet = _.isString(b) && reGreet.test(b);
- *
- * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
- * });
- * // => true
- */
- function isEqual(a, b, callback, thisArg) {
- return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
- }
- /**
- * Checks if `value` is, or can be coerced to, a finite number.
- *
- * Note: This is not the same as native `isFinite` which will return true for
- * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
- * @example
- *
- * _.isFinite(-101);
- * // => true
- *
- * _.isFinite('10');
- * // => true
- *
- * _.isFinite(true);
- * // => false
- *
- * _.isFinite('');
- * // => false
- *
- * _.isFinite(Infinity);
- * // => false
- */
- function isFinite(value) {
- return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
- }
- /**
- * Checks if `value` is a function.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
- * @example
- *
- * _.isFunction(_);
- * // => true
- */
- function isFunction(value) {
- return typeof value == 'function';
- }
- /**
- * Checks if `value` is the language type of Object.
- * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
- * @example
- *
- * _.isObject({});
- * // => true
- *
- * _.isObject([1, 2, 3]);
- * // => true
- *
- * _.isObject(1);
- * // => false
- */
- function isObject(value) {
- // check if the value is the ECMAScript language type of Object
- // http://es5.github.io/#x8
- // and avoid a V8 bug
- // http://code.google.com/p/v8/issues/detail?id=2291
- return !!(value && objectTypes[typeof value]);
- }
- /**
- * Checks if `value` is `NaN`.
- *
- * Note: This is not the same as native `isNaN` which will return `true` for
- * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
- * @example
- *
- * _.isNaN(NaN);
- * // => true
- *
- * _.isNaN(new Number(NaN));
- * // => true
- *
- * isNaN(undefined);
- * // => true
- *
- * _.isNaN(undefined);
- * // => false
- */
- function isNaN(value) {
- // `NaN` as a primitive is the only value that is not equal to itself
- // (perform the [[Class]] check first to avoid errors with some host objects in IE)
- return isNumber(value) && value != +value;
- }
- /**
- * Checks if `value` is `null`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
- * @example
- *
- * _.isNull(null);
- * // => true
- *
- * _.isNull(undefined);
- * // => false
- */
- function isNull(value) {
- return value === null;
- }
- /**
- * Checks if `value` is a number.
- *
- * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
- * @example
- *
- * _.isNumber(8.4 * 5);
- * // => true
- */
- function isNumber(value) {
- return typeof value == 'number' ||
- value && typeof value == 'object' && toString.call(value) == numberClass || false;
- }
- /**
- * Checks if `value` is an object created by the `Object` constructor.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
- * @example
- *
- * function Shape() {
- * this.x = 0;
- * this.y = 0;
- * }
- *
- * _.isPlainObject(new Shape);
- * // => false
- *
- * _.isPlainObject([1, 2, 3]);
- * // => false
- *
- * _.isPlainObject({ 'x': 0, 'y': 0 });
- * // => true
- */
- var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
- if (!(value && toString.call(value) == objectClass)) {
- return false;
- }
- var valueOf = value.valueOf,
- objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
- return objProto
- ? (value == objProto || getPrototypeOf(value) == objProto)
- : shimIsPlainObject(value);
- };
- /**
- * Checks if `value` is a regular expression.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
- * @example
- *
- * _.isRegExp(/fred/);
- * // => true
- */
- function isRegExp(value) {
- return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
- }
- /**
- * Checks if `value` is a string.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
- * @example
- *
- * _.isString('fred');
- * // => true
- */
- function isString(value) {
- return typeof value == 'string' ||
- value && typeof value == 'object' && toString.call(value) == stringClass || false;
- }
- /**
- * Checks if `value` is `undefined`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {*} value The value to check.
- * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
- * @example
- *
- * _.isUndefined(void 0);
- * // => true
- */
- function isUndefined(value) {
- return typeof value == 'undefined';
- }
- /**
- * Creates an object with the same keys as `object` and values generated by
- * running each own enumerable property of `object` through the callback.
- * The callback is bound to `thisArg` and invoked with three arguments;
- * (value, key, object).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new object with values of the results of each `callback` execution.
- * @example
- *
- * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
- * // => { 'a': 3, 'b': 6, 'c': 9 }
- *
- * var characters = {
- * 'fred': { 'name': 'fred', 'age': 40 },
- * 'pebbles': { 'name': 'pebbles', 'age': 1 }
- * };
- *
- * // using "_.pluck" callback shorthand
- * _.mapValues(characters, 'age');
- * // => { 'fred': 40, 'pebbles': 1 }
- */
- function mapValues(object, callback, thisArg) {
- var result = {};
- callback = lodash.createCallback(callback, thisArg, 3);
- forOwn(object, function(value, key, object) {
- result[key] = callback(value, key, object);
- });
- return result;
- }
- /**
- * Recursively merges own enumerable properties of the source object(s), that
- * don't resolve to `undefined` into the destination object. Subsequent sources
- * will overwrite property assignments of previous sources. If a callback is
- * provided it will be executed to produce the merged values of the destination
- * and source properties. If the callback returns `undefined` merging will
- * be handled by the method instead. The callback is bound to `thisArg` and
- * invoked with two arguments; (objectValue, sourceValue).
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The destination object.
- * @param {...Object} [source] The source objects.
- * @param {Function} [callback] The function to customize merging properties.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the destination object.
- * @example
- *
- * var names = {
- * 'characters': [
- * { 'name': 'barney' },
- * { 'name': 'fred' }
- * ]
- * };
- *
- * var ages = {
- * 'characters': [
- * { 'age': 36 },
- * { 'age': 40 }
- * ]
- * };
- *
- * _.merge(names, ages);
- * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
- *
- * var food = {
- * 'fruits': ['apple'],
- * 'vegetables': ['beet']
- * };
- *
- * var otherFood = {
- * 'fruits': ['banana'],
- * 'vegetables': ['carrot']
- * };
- *
- * _.merge(food, otherFood, function(a, b) {
- * return _.isArray(a) ? a.concat(b) : undefined;
- * });
- * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
- */
- function merge(object) {
- var args = arguments,
- length = 2;
- if (!isObject(object)) {
- return object;
- }
- // allows working with `_.reduce` and `_.reduceRight` without using
- // their `index` and `collection` arguments
- if (typeof args[2] != 'number') {
- length = args.length;
- }
- if (length > 3 && typeof args[length - 2] == 'function') {
- var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
- } else if (length > 2 && typeof args[length - 1] == 'function') {
- callback = args[--length];
- }
- var sources = slice(arguments, 1, length),
- index = -1,
- stackA = getArray(),
- stackB = getArray();
- while (++index < length) {
- baseMerge(object, sources[index], callback, stackA, stackB);
- }
- releaseArray(stackA);
- releaseArray(stackB);
- return object;
- }
- /**
- * Creates a shallow clone of `object` excluding the specified properties.
- * Property names may be specified as individual arguments or as arrays of
- * property names. If a callback is provided it will be executed for each
- * property of `object` omitting the properties the callback returns truey
- * for. The callback is bound to `thisArg` and invoked with three arguments;
- * (value, key, object).
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The source object.
- * @param {Function|...string|string[]} [callback] The properties to omit or the
- * function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns an object without the omitted properties.
- * @example
- *
- * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
- * // => { 'name': 'fred' }
- *
- * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
- * return typeof value == 'number';
- * });
- * // => { 'name': 'fred' }
- */
- function omit(object, callback, thisArg) {
- var result = {};
- if (typeof callback != 'function') {
- var props = [];
- forIn(object, function(value, key) {
- props.push(key);
- });
- props = baseDifference(props, baseFlatten(arguments, true, false, 1));
- var index = -1,
- length = props.length;
- while (++index < length) {
- var key = props[index];
- result[key] = object[key];
- }
- } else {
- callback = lodash.createCallback(callback, thisArg, 3);
- forIn(object, function(value, key, object) {
- if (!callback(value, key, object)) {
- result[key] = value;
- }
- });
- }
- return result;
- }
- /**
- * Creates a two dimensional array of an object's key-value pairs,
- * i.e. `[[key1, value1], [key2, value2]]`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns new array of key-value pairs.
- * @example
- *
- * _.pairs({ 'barney': 36, 'fred': 40 });
- * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
- */
- function pairs(object) {
- var index = -1,
- props = keys(object),
- length = props.length,
- result = Array(length);
- while (++index < length) {
- var key = props[index];
- result[index] = [key, object[key]];
- }
- return result;
- }
- /**
- * Creates a shallow clone of `object` composed of the specified properties.
- * Property names may be specified as individual arguments or as arrays of
- * property names. If a callback is provided it will be executed for each
- * property of `object` picking the properties the callback returns truey
- * for. The callback is bound to `thisArg` and invoked with three arguments;
- * (value, key, object).
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The source object.
- * @param {Function|...string|string[]} [callback] The function called per
- * iteration or property names to pick, specified as individual property
- * names or arrays of property names.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns an object composed of the picked properties.
- * @example
- *
- * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
- * // => { 'name': 'fred' }
- *
- * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
- * return key.charAt(0) != '_';
- * });
- * // => { 'name': 'fred' }
- */
- function pick(object, callback, thisArg) {
- var result = {};
- if (typeof callback != 'function') {
- var index = -1,
- props = baseFlatten(arguments, true, false, 1),
- length = isObject(object) ? props.length : 0;
- while (++index < length) {
- var key = props[index];
- if (key in object) {
- result[key] = object[key];
- }
- }
- } else {
- callback = lodash.createCallback(callback, thisArg, 3);
- forIn(object, function(value, key, object) {
- if (callback(value, key, object)) {
- result[key] = value;
- }
- });
- }
- return result;
- }
- /**
- * An alternative to `_.reduce` this method transforms `object` to a new
- * `accumulator` object which is the result of running each of its own
- * enumerable properties through a callback, with each callback execution
- * potentially mutating the `accumulator` object. The callback is bound to
- * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
- * Callbacks may exit iteration early by explicitly returning `false`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Array|Object} object The object to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [accumulator] The custom accumulator value.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the accumulated value.
- * @example
- *
- * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
- * num *= num;
- * if (num % 2) {
- * return result.push(num) < 3;
- * }
- * });
- * // => [1, 9, 25]
- *
- * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
- * result[key] = num * 3;
- * });
- * // => { 'a': 3, 'b': 6, 'c': 9 }
- */
- function transform(object, callback, accumulator, thisArg) {
- var isArr = isArray(object);
- if (accumulator == null) {
- if (isArr) {
- accumulator = [];
- } else {
- var ctor = object && object.constructor,
- proto = ctor && ctor.prototype;
- accumulator = baseCreate(proto);
- }
- }
- if (callback) {
- callback = lodash.createCallback(callback, thisArg, 4);
- (isArr ? forEach : forOwn)(object, function(value, index, object) {
- return callback(accumulator, value, index, object);
- });
- }
- return accumulator;
- }
- /**
- * Creates an array composed of the own enumerable property values of `object`.
- *
- * @static
- * @memberOf _
- * @category Objects
- * @param {Object} object The object to inspect.
- * @returns {Array} Returns an array of property values.
- * @example
- *
- * _.values({ 'one': 1, 'two': 2, 'three': 3 });
- * // => [1, 2, 3] (property order is not guaranteed across environments)
- */
- function values(object) {
- var index = -1,
- props = keys(object),
- length = props.length,
- result = Array(length);
- while (++index < length) {
- result[index] = object[props[index]];
- }
- return result;
- }
- /*--------------------------------------------------------------------------*/
- /**
- * Creates an array of elements from the specified indexes, or keys, of the
- * `collection`. Indexes may be specified as individual arguments or as arrays
- * of indexes.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
- * to retrieve, specified as individual indexes or arrays of indexes.
- * @returns {Array} Returns a new array of elements corresponding to the
- * provided indexes.
- * @example
- *
- * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
- * // => ['a', 'c', 'e']
- *
- * _.at(['fred', 'barney', 'pebbles'], 0, 2);
- * // => ['fred', 'pebbles']
- */
- function at(collection) {
- var args = arguments,
- index = -1,
- props = baseFlatten(args, true, false, 1),
- length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
- result = Array(length);
- while(++index < length) {
- result[index] = collection[props[index]];
- }
- return result;
- }
- /**
- * Checks if a given value is present in a collection using strict equality
- * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
- * offset from the end of the collection.
- *
- * @static
- * @memberOf _
- * @alias include
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {*} target The value to check for.
- * @param {number} [fromIndex=0] The index to search from.
- * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
- * @example
- *
- * _.contains([1, 2, 3], 1);
- * // => true
- *
- * _.contains([1, 2, 3], 1, 2);
- * // => false
- *
- * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
- * // => true
- *
- * _.contains('pebbles', 'eb');
- * // => true
- */
- function contains(collection, target, fromIndex) {
- var index = -1,
- indexOf = getIndexOf(),
- length = collection ? collection.length : 0,
- result = false;
- fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
- if (isArray(collection)) {
- result = indexOf(collection, target, fromIndex) > -1;
- } else if (typeof length == 'number') {
- result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
- } else {
- forOwn(collection, function(value) {
- if (++index >= fromIndex) {
- return !(result = value === target);
- }
- });
- }
- return result;
- }
- /**
- * Creates an object composed of keys generated from the results of running
- * each element of `collection` through the callback. The corresponding value
- * of each key is the number of times the key was returned by the callback.
- * The callback is bound to `thisArg` and invoked with three arguments;
- * (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the composed aggregate object.
- * @example
- *
- * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
- * // => { '4': 1, '6': 2 }
- *
- * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
- * // => { '4': 1, '6': 2 }
- *
- * _.countBy(['one', 'two', 'three'], 'length');
- * // => { '3': 2, '5': 1 }
- */
- var countBy = createAggregator(function(result, value, key) {
- (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
- });
- /**
- * Checks if the given callback returns truey value for **all** elements of
- * a collection. The callback is bound to `thisArg` and invoked with three
- * arguments; (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias all
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {boolean} Returns `true` if all elements passed the callback check,
- * else `false`.
- * @example
- *
- * _.every([true, 1, null, 'yes']);
- * // => false
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.every(characters, 'age');
- * // => true
- *
- * // using "_.where" callback shorthand
- * _.every(characters, { 'age': 36 });
- * // => false
- */
- function every(collection, callback, thisArg) {
- var result = true;
- callback = lodash.createCallback(callback, thisArg, 3);
- var index = -1,
- length = collection ? collection.length : 0;
- if (typeof length == 'number') {
- while (++index < length) {
- if (!(result = !!callback(collection[index], index, collection))) {
- break;
- }
- }
- } else {
- forOwn(collection, function(value, index, collection) {
- return (result = !!callback(value, index, collection));
- });
- }
- return result;
- }
- /**
- * Iterates over elements of a collection, returning an array of all elements
- * the callback returns truey for. The callback is bound to `thisArg` and
- * invoked with three arguments; (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias select
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of elements that passed the callback check.
- * @example
- *
- * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
- * // => [2, 4, 6]
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'blocked': false },
- * { 'name': 'fred', 'age': 40, 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.filter(characters, 'blocked');
- * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
- *
- * // using "_.where" callback shorthand
- * _.filter(characters, { 'age': 36 });
- * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
- */
- function filter(collection, callback, thisArg) {
- var result = [];
- callback = lodash.createCallback(callback, thisArg, 3);
- var index = -1,
- length = collection ? collection.length : 0;
- if (typeof length == 'number') {
- while (++index < length) {
- var value = collection[index];
- if (callback(value, index, collection)) {
- result.push(value);
- }
- }
- } else {
- forOwn(collection, function(value, index, collection) {
- if (callback(value, index, collection)) {
- result.push(value);
- }
- });
- }
- return result;
- }
- /**
- * Iterates over elements of a collection, returning the first element that
- * the callback returns truey for. The callback is bound to `thisArg` and
- * invoked with three arguments; (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias detect, findWhere
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the found element, else `undefined`.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'blocked': false },
- * { 'name': 'fred', 'age': 40, 'blocked': true },
- * { 'name': 'pebbles', 'age': 1, 'blocked': false }
- * ];
- *
- * _.find(characters, function(chr) {
- * return chr.age < 40;
- * });
- * // => { 'name': 'barney', 'age': 36, 'blocked': false }
- *
- * // using "_.where" callback shorthand
- * _.find(characters, { 'age': 1 });
- * // => { 'name': 'pebbles', 'age': 1, 'blocked': false }
- *
- * // using "_.pluck" callback shorthand
- * _.find(characters, 'blocked');
- * // => { 'name': 'fred', 'age': 40, 'blocked': true }
- */
- function find(collection, callback, thisArg) {
- callback = lodash.createCallback(callback, thisArg, 3);
- var index = -1,
- length = collection ? collection.length : 0;
- if (typeof length == 'number') {
- while (++index < length) {
- var value = collection[index];
- if (callback(value, index, collection)) {
- return value;
- }
- }
- } else {
- var result;
- forOwn(collection, function(value, index, collection) {
- if (callback(value, index, collection)) {
- result = value;
- return false;
- }
- });
- return result;
- }
- }
- /**
- * This method is like `_.find` except that it iterates over elements
- * of a `collection` from right to left.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the found element, else `undefined`.
- * @example
- *
- * _.findLast([1, 2, 3, 4], function(num) {
- * return num % 2 == 1;
- * });
- * // => 3
- */
- function findLast(collection, callback, thisArg) {
- var result;
- callback = lodash.createCallback(callback, thisArg, 3);
- forEachRight(collection, function(value, index, collection) {
- if (callback(value, index, collection)) {
- result = value;
- return false;
- }
- });
- return result;
- }
- /**
- * Iterates over elements of a collection, executing the callback for each
- * element. The callback is bound to `thisArg` and invoked with three arguments;
- * (value, index|key, collection). Callbacks may exit iteration early by
- * explicitly returning `false`.
- *
- * Note: As with other "Collections" methods, objects with a `length` property
- * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
- * may be used for object iteration.
- *
- * @static
- * @memberOf _
- * @alias each
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array|Object|string} Returns `collection`.
- * @example
- *
- * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
- * // => logs each number and returns '1,2,3'
- *
- * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
- * // => logs each number and returns the object (property order is not guaranteed across environments)
- */
- function forEach(collection, callback, thisArg) {
- var index = -1,
- length = collection ? collection.length : 0;
- callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
- if (typeof length == 'number') {
- while (++index < length) {
- if (callback(collection[index], index, collection) === false) {
- break;
- }
- }
- } else {
- forOwn(collection, callback);
- }
- return collection;
- }
- /**
- * This method is like `_.forEach` except that it iterates over elements
- * of a `collection` from right to left.
- *
- * @static
- * @memberOf _
- * @alias eachRight
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array|Object|string} Returns `collection`.
- * @example
- *
- * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
- * // => logs each number from right to left and returns '3,2,1'
- */
- function forEachRight(collection, callback, thisArg) {
- var length = collection ? collection.length : 0;
- callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
- if (typeof length == 'number') {
- while (length--) {
- if (callback(collection[length], length, collection) === false) {
- break;
- }
- }
- } else {
- var props = keys(collection);
- length = props.length;
- forOwn(collection, function(value, key, collection) {
- key = props ? props[--length] : --length;
- return callback(collection[key], key, collection);
- });
- }
- return collection;
- }
- /**
- * Creates an object composed of keys generated from the results of running
- * each element of a collection through the callback. The corresponding value
- * of each key is an array of the elements responsible for generating the key.
- * The callback is bound to `thisArg` and invoked with three arguments;
- * (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the composed aggregate object.
- * @example
- *
- * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
- * // => { '4': [4.2], '6': [6.1, 6.4] }
- *
- * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
- * // => { '4': [4.2], '6': [6.1, 6.4] }
- *
- * // using "_.pluck" callback shorthand
- * _.groupBy(['one', 'two', 'three'], 'length');
- * // => { '3': ['one', 'two'], '5': ['three'] }
- */
- var groupBy = createAggregator(function(result, value, key) {
- (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
- });
- /**
- * Creates an object composed of keys generated from the results of running
- * each element of the collection through the given callback. The corresponding
- * value of each key is the last element responsible for generating the key.
- * The callback is bound to `thisArg` and invoked with three arguments;
- * (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Object} Returns the composed aggregate object.
- * @example
- *
- * var keys = [
- * { 'dir': 'left', 'code': 97 },
- * { 'dir': 'right', 'code': 100 }
- * ];
- *
- * _.indexBy(keys, 'dir');
- * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
- *
- * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
- * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
- *
- * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
- * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
- */
- var indexBy = createAggregator(function(result, value, key) {
- result[key] = value;
- });
- /**
- * Invokes the method named by `methodName` on each element in the `collection`
- * returning an array of the results of each invoked method. Additional arguments
- * will be provided to each invoked method. If `methodName` is a function it
- * will be invoked for, and `this` bound to, each element in the `collection`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|string} methodName The name of the method to invoke or
- * the function invoked per iteration.
- * @param {...*} [arg] Arguments to invoke the method with.
- * @returns {Array} Returns a new array of the results of each invoked method.
- * @example
- *
- * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
- * // => [[1, 5, 7], [1, 2, 3]]
- *
- * _.invoke([123, 456], String.prototype.split, '');
- * // => [['1', '2', '3'], ['4', '5', '6']]
- */
- function invoke(collection, methodName) {
- var args = slice(arguments, 2),
- index = -1,
- isFunc = typeof methodName == 'function',
- length = collection ? collection.length : 0,
- result = Array(typeof length == 'number' ? length : 0);
- forEach(collection, function(value) {
- result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
- });
- return result;
- }
- /**
- * Creates an array of values by running each element in the collection
- * through the callback. The callback is bound to `thisArg` and invoked with
- * three arguments; (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias collect
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of the results of each `callback` execution.
- * @example
- *
- * _.map([1, 2, 3], function(num) { return num * 3; });
- * // => [3, 6, 9]
- *
- * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
- * // => [3, 6, 9] (property order is not guaranteed across environments)
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.map(characters, 'name');
- * // => ['barney', 'fred']
- */
- function map(collection, callback, thisArg) {
- var index = -1,
- length = collection ? collection.length : 0;
- callback = lodash.createCallback(callback, thisArg, 3);
- if (typeof length == 'number') {
- var result = Array(length);
- while (++index < length) {
- result[index] = callback(collection[index], index, collection);
- }
- } else {
- result = [];
- forOwn(collection, function(value, key, collection) {
- result[++index] = callback(value, key, collection);
- });
- }
- return result;
- }
- /**
- * Retrieves the maximum value of a collection. If the collection is empty or
- * falsey `-Infinity` is returned. If a callback is provided it will be executed
- * for each value in the collection to generate the criterion by which the value
- * is ranked. The callback is bound to `thisArg` and invoked with three
- * arguments; (value, index, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the maximum value.
- * @example
- *
- * _.max([4, 2, 8, 6]);
- * // => 8
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * _.max(characters, function(chr) { return chr.age; });
- * // => { 'name': 'fred', 'age': 40 };
- *
- * // using "_.pluck" callback shorthand
- * _.max(characters, 'age');
- * // => { 'name': 'fred', 'age': 40 };
- */
- function max(collection, callback, thisArg) {
- var computed = -Infinity,
- result = computed;
- // allows working with functions like `_.map` without using
- // their `index` argument as a callback
- if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
- callback = null;
- }
- if (callback == null && isArray(collection)) {
- var index = -1,
- length = collection.length;
- while (++index < length) {
- var value = collection[index];
- if (value > result) {
- result = value;
- }
- }
- } else {
- callback = (callback == null && isString(collection))
- ? charAtCallback
- : lodash.createCallback(callback, thisArg, 3);
- forEach(collection, function(value, index, collection) {
- var current = callback(value, index, collection);
- if (current > computed) {
- computed = current;
- result = value;
- }
- });
- }
- return result;
- }
- /**
- * Retrieves the minimum value of a collection. If the collection is empty or
- * falsey `Infinity` is returned. If a callback is provided it will be executed
- * for each value in the collection to generate the criterion by which the value
- * is ranked. The callback is bound to `thisArg` and invoked with three
- * arguments; (value, index, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the minimum value.
- * @example
- *
- * _.min([4, 2, 8, 6]);
- * // => 2
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * _.min(characters, function(chr) { return chr.age; });
- * // => { 'name': 'barney', 'age': 36 };
- *
- * // using "_.pluck" callback shorthand
- * _.min(characters, 'age');
- * // => { 'name': 'barney', 'age': 36 };
- */
- function min(collection, callback, thisArg) {
- var computed = Infinity,
- result = computed;
- // allows working with functions like `_.map` without using
- // their `index` argument as a callback
- if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
- callback = null;
- }
- if (callback == null && isArray(collection)) {
- var index = -1,
- length = collection.length;
- while (++index < length) {
- var value = collection[index];
- if (value < result) {
- result = value;
- }
- }
- } else {
- callback = (callback == null && isString(collection))
- ? charAtCallback
- : lodash.createCallback(callback, thisArg, 3);
- forEach(collection, function(value, index, collection) {
- var current = callback(value, index, collection);
- if (current < computed) {
- computed = current;
- result = value;
- }
- });
- }
- return result;
- }
- /**
- * Retrieves the value of a specified property from all elements in the collection.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {string} property The name of the property to pluck.
- * @returns {Array} Returns a new array of property values.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * _.pluck(characters, 'name');
- * // => ['barney', 'fred']
- */
- var pluck = map;
- /**
- * Reduces a collection to a value which is the accumulated result of running
- * each element in the collection through the callback, where each successive
- * callback execution consumes the return value of the previous execution. If
- * `accumulator` is not provided the first element of the collection will be
- * used as the initial `accumulator` value. The callback is bound to `thisArg`
- * and invoked with four arguments; (accumulator, value, index|key, collection).
- *
- * @static
- * @memberOf _
- * @alias foldl, inject
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [accumulator] Initial value of the accumulator.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the accumulated value.
- * @example
- *
- * var sum = _.reduce([1, 2, 3], function(sum, num) {
- * return sum + num;
- * });
- * // => 6
- *
- * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
- * result[key] = num * 3;
- * return result;
- * }, {});
- * // => { 'a': 3, 'b': 6, 'c': 9 }
- */
- function reduce(collection, callback, accumulator, thisArg) {
- if (!collection) return accumulator;
- var noaccum = arguments.length < 3;
- callback = lodash.createCallback(callback, thisArg, 4);
- var index = -1,
- length = collection.length;
- if (typeof length == 'number') {
- if (noaccum) {
- accumulator = collection[++index];
- }
- while (++index < length) {
- accumulator = callback(accumulator, collection[index], index, collection);
- }
- } else {
- forOwn(collection, function(value, index, collection) {
- accumulator = noaccum
- ? (noaccum = false, value)
- : callback(accumulator, value, index, collection)
- });
- }
- return accumulator;
- }
- /**
- * This method is like `_.reduce` except that it iterates over elements
- * of a `collection` from right to left.
- *
- * @static
- * @memberOf _
- * @alias foldr
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function} [callback=identity] The function called per iteration.
- * @param {*} [accumulator] Initial value of the accumulator.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the accumulated value.
- * @example
- *
- * var list = [[0, 1], [2, 3], [4, 5]];
- * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
- * // => [4, 5, 2, 3, 0, 1]
- */
- function reduceRight(collection, callback, accumulator, thisArg) {
- var noaccum = arguments.length < 3;
- callback = lodash.createCallback(callback, thisArg, 4);
- forEachRight(collection, function(value, index, collection) {
- accumulator = noaccum
- ? (noaccum = false, value)
- : callback(accumulator, value, index, collection);
- });
- return accumulator;
- }
- /**
- * The opposite of `_.filter` this method returns the elements of a
- * collection that the callback does **not** return truey for.
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of elements that failed the callback check.
- * @example
- *
- * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
- * // => [1, 3, 5]
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'blocked': false },
- * { 'name': 'fred', 'age': 40, 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.reject(characters, 'blocked');
- * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
- *
- * // using "_.where" callback shorthand
- * _.reject(characters, { 'age': 36 });
- * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
- */
- function reject(collection, callback, thisArg) {
- callback = lodash.createCallback(callback, thisArg, 3);
- return filter(collection, function(value, index, collection) {
- return !callback(value, index, collection);
- });
- }
- /**
- * Retrieves a random element or `n` random elements from a collection.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to sample.
- * @param {number} [n] The number of elements to sample.
- * @param- {Object} [guard] Allows working with functions like `_.map`
- * without using their `index` arguments as `n`.
- * @returns {Array} Returns the random sample(s) of `collection`.
- * @example
- *
- * _.sample([1, 2, 3, 4]);
- * // => 2
- *
- * _.sample([1, 2, 3, 4], 2);
- * // => [3, 1]
- */
- function sample(collection, n, guard) {
- if (collection && typeof collection.length != 'number') {
- collection = values(collection);
- }
- if (n == null || guard) {
- return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
- }
- var result = shuffle(collection);
- result.length = nativeMin(nativeMax(0, n), result.length);
- return result;
- }
- /**
- * Creates an array of shuffled values, using a version of the Fisher-Yates
- * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to shuffle.
- * @returns {Array} Returns a new shuffled collection.
- * @example
- *
- * _.shuffle([1, 2, 3, 4, 5, 6]);
- * // => [4, 1, 6, 3, 5, 2]
- */
- function shuffle(collection) {
- var index = -1,
- length = collection ? collection.length : 0,
- result = Array(typeof length == 'number' ? length : 0);
- forEach(collection, function(value) {
- var rand = baseRandom(0, ++index);
- result[index] = result[rand];
- result[rand] = value;
- });
- return result;
- }
- /**
- * Gets the size of the `collection` by returning `collection.length` for arrays
- * and array-like objects or the number of own enumerable properties for objects.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to inspect.
- * @returns {number} Returns `collection.length` or number of own enumerable properties.
- * @example
- *
- * _.size([1, 2]);
- * // => 2
- *
- * _.size({ 'one': 1, 'two': 2, 'three': 3 });
- * // => 3
- *
- * _.size('pebbles');
- * // => 7
- */
- function size(collection) {
- var length = collection ? collection.length : 0;
- return typeof length == 'number' ? length : keys(collection).length;
- }
- /**
- * Checks if the callback returns a truey value for **any** element of a
- * collection. The function returns as soon as it finds a passing value and
- * does not iterate over the entire collection. The callback is bound to
- * `thisArg` and invoked with three arguments; (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias any
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {boolean} Returns `true` if any element passed the callback check,
- * else `false`.
- * @example
- *
- * _.some([null, 0, 'yes', false], Boolean);
- * // => true
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'blocked': false },
- * { 'name': 'fred', 'age': 40, 'blocked': true }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.some(characters, 'blocked');
- * // => true
- *
- * // using "_.where" callback shorthand
- * _.some(characters, { 'age': 1 });
- * // => false
- */
- function some(collection, callback, thisArg) {
- var result;
- callback = lodash.createCallback(callback, thisArg, 3);
- var index = -1,
- length = collection ? collection.length : 0;
- if (typeof length == 'number') {
- while (++index < length) {
- if ((result = callback(collection[index], index, collection))) {
- break;
- }
- }
- } else {
- forOwn(collection, function(value, index, collection) {
- return !(result = callback(value, index, collection));
- });
- }
- return !!result;
- }
- /**
- * Creates an array of elements, sorted in ascending order by the results of
- * running each element in a collection through the callback. This method
- * performs a stable sort, that is, it will preserve the original sort order
- * of equal elements. The callback is bound to `thisArg` and invoked with
- * three arguments; (value, index|key, collection).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an array of property names is provided for `callback` the collection
- * will be sorted by each property value.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Array|Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of sorted elements.
- * @example
- *
- * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
- * // => [3, 1, 2]
- *
- * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
- * // => [3, 1, 2]
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 },
- * { 'name': 'barney', 'age': 26 },
- * { 'name': 'fred', 'age': 30 }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.map(_.sortBy(characters, 'age'), _.values);
- * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
- *
- * // sorting by multiple properties
- * _.map(_.sortBy(characters, ['name', 'age']), _.values);
- * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
- */
- function sortBy(collection, callback, thisArg) {
- var index = -1,
- isArr = isArray(callback),
- length = collection ? collection.length : 0,
- result = Array(typeof length == 'number' ? length : 0);
- if (!isArr) {
- callback = lodash.createCallback(callback, thisArg, 3);
- }
- forEach(collection, function(value, key, collection) {
- var object = result[++index] = getObject();
- if (isArr) {
- object.criteria = map(callback, function(key) { return value[key]; });
- } else {
- (object.criteria = getArray())[0] = callback(value, key, collection);
- }
- object.index = index;
- object.value = value;
- });
- length = result.length;
- result.sort(compareAscending);
- while (length--) {
- var object = result[length];
- result[length] = object.value;
- if (!isArr) {
- releaseArray(object.criteria);
- }
- releaseObject(object);
- }
- return result;
- }
- /**
- * Converts the `collection` to an array.
- *
- * @static
- * @memberOf _
- * @category Collections
- * @param {Array|Object|string} collection The collection to convert.
- * @returns {Array} Returns the new converted array.
- * @example
- *
- * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
- * // => [2, 3, 4]
- */
- function toArray(collection) {
- if (collection && typeof collection.length == 'number') {
- return slice(collection);
- }
- return values(collection);
- }
- /**
- * Performs a deep comparison of each element in a `collection` to the given
- * `properties` object, returning an array of all elements that have equivalent
- * property values.
- *
- * @static
- * @memberOf _
- * @type Function
- * @category Collections
- * @param {Array|Object|string} collection The collection to iterate over.
- * @param {Object} props The object of property values to filter by.
- * @returns {Array} Returns a new array of elements that have the given properties.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
- * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
- * ];
- *
- * _.where(characters, { 'age': 36 });
- * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
- *
- * _.where(characters, { 'pets': ['dino'] });
- * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
- */
- var where = filter;
- /*--------------------------------------------------------------------------*/
- /**
- * Creates an array with all falsey values removed. The values `false`, `null`,
- * `0`, `""`, `undefined`, and `NaN` are all falsey.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to compact.
- * @returns {Array} Returns a new array of filtered values.
- * @example
- *
- * _.compact([0, 1, false, 2, '', 3]);
- * // => [1, 2, 3]
- */
- function compact(array) {
- var index = -1,
- length = array ? array.length : 0,
- result = [];
- while (++index < length) {
- var value = array[index];
- if (value) {
- result.push(value);
- }
- }
- return result;
- }
- /**
- * Creates an array excluding all values of the provided arrays using strict
- * equality for comparisons, i.e. `===`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to process.
- * @param {...Array} [values] The arrays of values to exclude.
- * @returns {Array} Returns a new array of filtered values.
- * @example
- *
- * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
- * // => [1, 3, 4]
- */
- function difference(array) {
- return baseDifference(array, baseFlatten(arguments, true, true, 1));
- }
- /**
- * This method is like `_.find` except that it returns the index of the first
- * element that passes the callback check, instead of the element itself.
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to search.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {number} Returns the index of the found element, else `-1`.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'blocked': false },
- * { 'name': 'fred', 'age': 40, 'blocked': true },
- * { 'name': 'pebbles', 'age': 1, 'blocked': false }
- * ];
- *
- * _.findIndex(characters, function(chr) {
- * return chr.age < 20;
- * });
- * // => 2
- *
- * // using "_.where" callback shorthand
- * _.findIndex(characters, { 'age': 36 });
- * // => 0
- *
- * // using "_.pluck" callback shorthand
- * _.findIndex(characters, 'blocked');
- * // => 1
- */
- function findIndex(array, callback, thisArg) {
- var index = -1,
- length = array ? array.length : 0;
- callback = lodash.createCallback(callback, thisArg, 3);
- while (++index < length) {
- if (callback(array[index], index, array)) {
- return index;
- }
- }
- return -1;
- }
- /**
- * This method is like `_.findIndex` except that it iterates over elements
- * of a `collection` from right to left.
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to search.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {number} Returns the index of the found element, else `-1`.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36, 'blocked': true },
- * { 'name': 'fred', 'age': 40, 'blocked': false },
- * { 'name': 'pebbles', 'age': 1, 'blocked': true }
- * ];
- *
- * _.findLastIndex(characters, function(chr) {
- * return chr.age > 30;
- * });
- * // => 1
- *
- * // using "_.where" callback shorthand
- * _.findLastIndex(characters, { 'age': 36 });
- * // => 0
- *
- * // using "_.pluck" callback shorthand
- * _.findLastIndex(characters, 'blocked');
- * // => 2
- */
- function findLastIndex(array, callback, thisArg) {
- var length = array ? array.length : 0;
- callback = lodash.createCallback(callback, thisArg, 3);
- while (length--) {
- if (callback(array[length], length, array)) {
- return length;
- }
- }
- return -1;
- }
- /**
- * Gets the first element or first `n` elements of an array. If a callback
- * is provided elements at the beginning of the array are returned as long
- * as the callback returns truey. The callback is bound to `thisArg` and
- * invoked with three arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias head, take
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|number|string} [callback] The function called
- * per element or the number of elements to return. If a property name or
- * object is provided it will be used to create a "_.pluck" or "_.where"
- * style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the first element(s) of `array`.
- * @example
- *
- * _.first([1, 2, 3]);
- * // => 1
- *
- * _.first([1, 2, 3], 2);
- * // => [1, 2]
- *
- * _.first([1, 2, 3], function(num) {
- * return num < 3;
- * });
- * // => [1, 2]
- *
- * var characters = [
- * { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
- * { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
- * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.first(characters, 'blocked');
- * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
- *
- * // using "_.where" callback shorthand
- * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
- * // => ['barney', 'fred']
- */
- function first(array, callback, thisArg) {
- var n = 0,
- length = array ? array.length : 0;
- if (typeof callback != 'number' && callback != null) {
- var index = -1;
- callback = lodash.createCallback(callback, thisArg, 3);
- while (++index < length && callback(array[index], index, array)) {
- n++;
- }
- } else {
- n = callback;
- if (n == null || thisArg) {
- return array ? array[0] : undefined;
- }
- }
- return slice(array, 0, nativeMin(nativeMax(0, n), length));
- }
- /**
- * Flattens a nested array (the nesting can be to any depth). If `isShallow`
- * is truey, the array will only be flattened a single level. If a callback
- * is provided each element of the array is passed through the callback before
- * flattening. The callback is bound to `thisArg` and invoked with three
- * arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to flatten.
- * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new flattened array.
- * @example
- *
- * _.flatten([1, [2], [3, [[4]]]]);
- * // => [1, 2, 3, 4];
- *
- * _.flatten([1, [2], [3, [[4]]]], true);
- * // => [1, 2, 3, [[4]]];
- *
- * var characters = [
- * { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
- * { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.flatten(characters, 'pets');
- * // => ['hoppy', 'baby puss', 'dino']
- */
- function flatten(array, isShallow, callback, thisArg) {
- // juggle arguments
- if (typeof isShallow != 'boolean' && isShallow != null) {
- thisArg = callback;
- callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
- isShallow = false;
- }
- if (callback != null) {
- array = map(array, callback, thisArg);
- }
- return baseFlatten(array, isShallow);
- }
- /**
- * Gets the index at which the first occurrence of `value` is found using
- * strict equality for comparisons, i.e. `===`. If the array is already sorted
- * providing `true` for `fromIndex` will run a faster binary search.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to search.
- * @param {*} value The value to search for.
- * @param {boolean|number} [fromIndex=0] The index to search from or `true`
- * to perform a binary search on a sorted array.
- * @returns {number} Returns the index of the matched value or `-1`.
- * @example
- *
- * _.indexOf([1, 2, 3, 1, 2, 3], 2);
- * // => 1
- *
- * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
- * // => 4
- *
- * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
- * // => 2
- */
- function indexOf(array, value, fromIndex) {
- if (typeof fromIndex == 'number') {
- var length = array ? array.length : 0;
- fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
- } else if (fromIndex) {
- var index = sortedIndex(array, value);
- return array[index] === value ? index : -1;
- }
- return baseIndexOf(array, value, fromIndex);
- }
- /**
- * Gets all but the last element or last `n` elements of an array. If a
- * callback is provided elements at the end of the array are excluded from
- * the result as long as the callback returns truey. The callback is bound
- * to `thisArg` and invoked with three arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|number|string} [callback=1] The function called
- * per element or the number of elements to exclude. If a property name or
- * object is provided it will be used to create a "_.pluck" or "_.where"
- * style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a slice of `array`.
- * @example
- *
- * _.initial([1, 2, 3]);
- * // => [1, 2]
- *
- * _.initial([1, 2, 3], 2);
- * // => [1]
- *
- * _.initial([1, 2, 3], function(num) {
- * return num > 1;
- * });
- * // => [1]
- *
- * var characters = [
- * { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
- * { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
- * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.initial(characters, 'blocked');
- * // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }]
- *
- * // using "_.where" callback shorthand
- * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
- * // => ['barney', 'fred']
- */
- function initial(array, callback, thisArg) {
- var n = 0,
- length = array ? array.length : 0;
- if (typeof callback != 'number' && callback != null) {
- var index = length;
- callback = lodash.createCallback(callback, thisArg, 3);
- while (index-- && callback(array[index], index, array)) {
- n++;
- }
- } else {
- n = (callback == null || thisArg) ? 1 : callback || n;
- }
- return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
- }
- /**
- * Creates an array of unique values present in all provided arrays using
- * strict equality for comparisons, i.e. `===`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {...Array} [array] The arrays to inspect.
- * @returns {Array} Returns an array of shared values.
- * @example
- *
- * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
- * // => [1, 2]
- */
- function intersection() {
- var args = [],
- argsIndex = -1,
- argsLength = arguments.length,
- caches = getArray(),
- indexOf = getIndexOf(),
- trustIndexOf = indexOf === baseIndexOf,
- seen = getArray();
- while (++argsIndex < argsLength) {
- var value = arguments[argsIndex];
- if (isArray(value) || isArguments(value)) {
- args.push(value);
- caches.push(trustIndexOf && value.length >= largeArraySize &&
- createCache(argsIndex ? args[argsIndex] : seen));
- }
- }
- var array = args[0],
- index = -1,
- length = array ? array.length : 0,
- result = [];
- outer:
- while (++index < length) {
- var cache = caches[0];
- value = array[index];
- if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
- argsIndex = argsLength;
- (cache || seen).push(value);
- while (--argsIndex) {
- cache = caches[argsIndex];
- if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
- continue outer;
- }
- }
- result.push(value);
- }
- }
- while (argsLength--) {
- cache = caches[argsLength];
- if (cache) {
- releaseObject(cache);
- }
- }
- releaseArray(caches);
- releaseArray(seen);
- return result;
- }
- /**
- * Gets the last element or last `n` elements of an array. If a callback is
- * provided elements at the end of the array are returned as long as the
- * callback returns truey. The callback is bound to `thisArg` and invoked
- * with three arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|number|string} [callback] The function called
- * per element or the number of elements to return. If a property name or
- * object is provided it will be used to create a "_.pluck" or "_.where"
- * style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {*} Returns the last element(s) of `array`.
- * @example
- *
- * _.last([1, 2, 3]);
- * // => 3
- *
- * _.last([1, 2, 3], 2);
- * // => [2, 3]
- *
- * _.last([1, 2, 3], function(num) {
- * return num > 1;
- * });
- * // => [2, 3]
- *
- * var characters = [
- * { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
- * { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
- * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.pluck(_.last(characters, 'blocked'), 'name');
- * // => ['fred', 'pebbles']
- *
- * // using "_.where" callback shorthand
- * _.last(characters, { 'employer': 'na' });
- * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
- */
- function last(array, callback, thisArg) {
- var n = 0,
- length = array ? array.length : 0;
- if (typeof callback != 'number' && callback != null) {
- var index = length;
- callback = lodash.createCallback(callback, thisArg, 3);
- while (index-- && callback(array[index], index, array)) {
- n++;
- }
- } else {
- n = callback;
- if (n == null || thisArg) {
- return array ? array[length - 1] : undefined;
- }
- }
- return slice(array, nativeMax(0, length - n));
- }
- /**
- * Gets the index at which the last occurrence of `value` is found using strict
- * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
- * as the offset from the end of the collection.
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to search.
- * @param {*} value The value to search for.
- * @param {number} [fromIndex=array.length-1] The index to search from.
- * @returns {number} Returns the index of the matched value or `-1`.
- * @example
- *
- * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
- * // => 4
- *
- * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
- * // => 1
- */
- function lastIndexOf(array, value, fromIndex) {
- var index = array ? array.length : 0;
- if (typeof fromIndex == 'number') {
- index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
- }
- while (index--) {
- if (array[index] === value) {
- return index;
- }
- }
- return -1;
- }
- /**
- * Removes all provided values from the given array using strict equality for
- * comparisons, i.e. `===`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to modify.
- * @param {...*} [value] The values to remove.
- * @returns {Array} Returns `array`.
- * @example
- *
- * var array = [1, 2, 3, 1, 2, 3];
- * _.pull(array, 2, 3);
- * console.log(array);
- * // => [1, 1]
- */
- function pull(array) {
- var args = arguments,
- argsIndex = 0,
- argsLength = args.length,
- length = array ? array.length : 0;
- while (++argsIndex < argsLength) {
- var index = -1,
- value = args[argsIndex];
- while (++index < length) {
- if (array[index] === value) {
- splice.call(array, index--, 1);
- length--;
- }
- }
- }
- return array;
- }
- /**
- * Creates an array of numbers (positive and/or negative) progressing from
- * `start` up to but not including `end`. If `start` is less than `stop` a
- * zero-length range is created unless a negative `step` is specified.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {number} [start=0] The start of the range.
- * @param {number} end The end of the range.
- * @param {number} [step=1] The value to increment or decrement by.
- * @returns {Array} Returns a new range array.
- * @example
- *
- * _.range(4);
- * // => [0, 1, 2, 3]
- *
- * _.range(1, 5);
- * // => [1, 2, 3, 4]
- *
- * _.range(0, 20, 5);
- * // => [0, 5, 10, 15]
- *
- * _.range(0, -4, -1);
- * // => [0, -1, -2, -3]
- *
- * _.range(1, 4, 0);
- * // => [1, 1, 1]
- *
- * _.range(0);
- * // => []
- */
- function range(start, end, step) {
- start = +start || 0;
- step = typeof step == 'number' ? step : (+step || 1);
- if (end == null) {
- end = start;
- start = 0;
- }
- // use `Array(length)` so engines like Chakra and V8 avoid slower modes
- // http://youtu.be/XAqIpGU8ZZk#t=17m25s
- var index = -1,
- length = nativeMax(0, ceil((end - start) / (step || 1))),
- result = Array(length);
- while (++index < length) {
- result[index] = start;
- start += step;
- }
- return result;
- }
- /**
- * Removes all elements from an array that the callback returns truey for
- * and returns an array of removed elements. The callback is bound to `thisArg`
- * and invoked with three arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to modify.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a new array of removed elements.
- * @example
- *
- * var array = [1, 2, 3, 4, 5, 6];
- * var evens = _.remove(array, function(num) { return num % 2 == 0; });
- *
- * console.log(array);
- * // => [1, 3, 5]
- *
- * console.log(evens);
- * // => [2, 4, 6]
- */
- function remove(array, callback, thisArg) {
- var index = -1,
- length = array ? array.length : 0,
- result = [];
- callback = lodash.createCallback(callback, thisArg, 3);
- while (++index < length) {
- var value = array[index];
- if (callback(value, index, array)) {
- result.push(value);
- splice.call(array, index--, 1);
- length--;
- }
- }
- return result;
- }
- /**
- * The opposite of `_.initial` this method gets all but the first element or
- * first `n` elements of an array. If a callback function is provided elements
- * at the beginning of the array are excluded from the result as long as the
- * callback returns truey. The callback is bound to `thisArg` and invoked
- * with three arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias drop, tail
- * @category Arrays
- * @param {Array} array The array to query.
- * @param {Function|Object|number|string} [callback=1] The function called
- * per element or the number of elements to exclude. If a property name or
- * object is provided it will be used to create a "_.pluck" or "_.where"
- * style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a slice of `array`.
- * @example
- *
- * _.rest([1, 2, 3]);
- * // => [2, 3]
- *
- * _.rest([1, 2, 3], 2);
- * // => [3]
- *
- * _.rest([1, 2, 3], function(num) {
- * return num < 3;
- * });
- * // => [3]
- *
- * var characters = [
- * { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
- * { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
- * { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
- * ];
- *
- * // using "_.pluck" callback shorthand
- * _.pluck(_.rest(characters, 'blocked'), 'name');
- * // => ['fred', 'pebbles']
- *
- * // using "_.where" callback shorthand
- * _.rest(characters, { 'employer': 'slate' });
- * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
- */
- function rest(array, callback, thisArg) {
- if (typeof callback != 'number' && callback != null) {
- var n = 0,
- index = -1,
- length = array ? array.length : 0;
- callback = lodash.createCallback(callback, thisArg, 3);
- while (++index < length && callback(array[index], index, array)) {
- n++;
- }
- } else {
- n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
- }
- return slice(array, n);
- }
- /**
- * Uses a binary search to determine the smallest index at which a value
- * should be inserted into a given sorted array in order to maintain the sort
- * order of the array. If a callback is provided it will be executed for
- * `value` and each element of `array` to compute their sort ranking. The
- * callback is bound to `thisArg` and invoked with one argument; (value).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to inspect.
- * @param {*} value The value to evaluate.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {number} Returns the index at which `value` should be inserted
- * into `array`.
- * @example
- *
- * _.sortedIndex([20, 30, 50], 40);
- * // => 2
- *
- * // using "_.pluck" callback shorthand
- * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
- * // => 2
- *
- * var dict = {
- * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
- * };
- *
- * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
- * return dict.wordToNumber[word];
- * });
- * // => 2
- *
- * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
- * return this.wordToNumber[word];
- * }, dict);
- * // => 2
- */
- function sortedIndex(array, value, callback, thisArg) {
- var low = 0,
- high = array ? array.length : low;
- // explicitly reference `identity` for better inlining in Firefox
- callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
- value = callback(value);
- while (low < high) {
- var mid = (low + high) >>> 1;
- (callback(array[mid]) < value)
- ? low = mid + 1
- : high = mid;
- }
- return low;
- }
- /**
- * Creates an array of unique values, in order, of the provided arrays using
- * strict equality for comparisons, i.e. `===`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {...Array} [array] The arrays to inspect.
- * @returns {Array} Returns an array of combined values.
- * @example
- *
- * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
- * // => [1, 2, 3, 5, 4]
- */
- function union() {
- return baseUniq(baseFlatten(arguments, true, true));
- }
- /**
- * Creates a duplicate-value-free version of an array using strict equality
- * for comparisons, i.e. `===`. If the array is sorted, providing
- * `true` for `isSorted` will use a faster algorithm. If a callback is provided
- * each element of `array` is passed through the callback before uniqueness
- * is computed. The callback is bound to `thisArg` and invoked with three
- * arguments; (value, index, array).
- *
- * If a property name is provided for `callback` the created "_.pluck" style
- * callback will return the property value of the given element.
- *
- * If an object is provided for `callback` the created "_.where" style callback
- * will return `true` for elements that have the properties of the given object,
- * else `false`.
- *
- * @static
- * @memberOf _
- * @alias unique
- * @category Arrays
- * @param {Array} array The array to process.
- * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
- * @param {Function|Object|string} [callback=identity] The function called
- * per iteration. If a property name or object is provided it will be used
- * to create a "_.pluck" or "_.where" style callback, respectively.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns a duplicate-value-free array.
- * @example
- *
- * _.uniq([1, 2, 1, 3, 1]);
- * // => [1, 2, 3]
- *
- * _.uniq([1, 1, 2, 2, 3], true);
- * // => [1, 2, 3]
- *
- * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
- * // => ['A', 'b', 'C']
- *
- * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
- * // => [1, 2.5, 3]
- *
- * // using "_.pluck" callback shorthand
- * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
- * // => [{ 'x': 1 }, { 'x': 2 }]
- */
- function uniq(array, isSorted, callback, thisArg) {
- // juggle arguments
- if (typeof isSorted != 'boolean' && isSorted != null) {
- thisArg = callback;
- callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
- isSorted = false;
- }
- if (callback != null) {
- callback = lodash.createCallback(callback, thisArg, 3);
- }
- return baseUniq(array, isSorted, callback);
- }
- /**
- * Creates an array excluding all provided values using strict equality for
- * comparisons, i.e. `===`.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {Array} array The array to filter.
- * @param {...*} [value] The values to exclude.
- * @returns {Array} Returns a new array of filtered values.
- * @example
- *
- * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
- * // => [2, 3, 4]
- */
- function without(array) {
- return baseDifference(array, slice(arguments, 1));
- }
- /**
- * Creates an array that is the symmetric difference of the provided arrays.
- * See http://en.wikipedia.org/wiki/Symmetric_difference.
- *
- * @static
- * @memberOf _
- * @category Arrays
- * @param {...Array} [array] The arrays to inspect.
- * @returns {Array} Returns an array of values.
- * @example
- *
- * _.xor([1, 2, 3], [5, 2, 1, 4]);
- * // => [3, 5, 4]
- *
- * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
- * // => [1, 4, 5]
- */
- function xor() {
- var index = -1,
- length = arguments.length;
- while (++index < length) {
- var array = arguments[index];
- if (isArray(array) || isArguments(array)) {
- var result = result
- ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
- : array;
- }
- }
- return result || [];
- }
- /**
- * Creates an array of grouped elements, the first of which contains the first
- * elements of the given arrays, the second of which contains the second
- * elements of the given arrays, and so on.
- *
- * @static
- * @memberOf _
- * @alias unzip
- * @category Arrays
- * @param {...Array} [array] Arrays to process.
- * @returns {Array} Returns a new array of grouped elements.
- * @example
- *
- * _.zip(['fred', 'barney'], [30, 40], [true, false]);
- * // => [['fred', 30, true], ['barney', 40, false]]
- */
- function zip() {
- var array = arguments.length > 1 ? arguments : arguments[0],
- index = -1,
- length = array ? max(pluck(array, 'length')) : 0,
- result = Array(length < 0 ? 0 : length);
- while (++index < length) {
- result[index] = pluck(array, index);
- }
- return result;
- }
- /**
- * Creates an object composed from arrays of `keys` and `values`. Provide
- * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
- * or two arrays, one of `keys` and one of corresponding `values`.
- *
- * @static
- * @memberOf _
- * @alias object
- * @category Arrays
- * @param {Array} keys The array of keys.
- * @param {Array} [values=[]] The array of values.
- * @returns {Object} Returns an object composed of the given keys and
- * corresponding values.
- * @example
- *
- * _.zipObject(['fred', 'barney'], [30, 40]);
- * // => { 'fred': 30, 'barney': 40 }
- */
- function zipObject(keys, values) {
- var index = -1,
- length = keys ? keys.length : 0,
- result = {};
- if (!values && length && !isArray(keys[0])) {
- values = [];
- }
- while (++index < length) {
- var key = keys[index];
- if (values) {
- result[key] = values[index];
- } else if (key) {
- result[key[0]] = key[1];
- }
- }
- return result;
- }
- /*--------------------------------------------------------------------------*/
- /**
- * Creates a function that executes `func`, with the `this` binding and
- * arguments of the created function, only after being called `n` times.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {number} n The number of times the function must be called before
- * `func` is executed.
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
- * @example
- *
- * var saves = ['profile', 'settings'];
- *
- * var done = _.after(saves.length, function() {
- * console.log('Done saving!');
- * });
- *
- * _.forEach(saves, function(type) {
- * asyncSave({ 'type': type, 'complete': done });
- * });
- * // => logs 'Done saving!', after all saves have completed
- */
- function after(n, func) {
- if (!isFunction(func)) {
- throw new TypeError;
- }
- return function() {
- if (--n < 1) {
- return func.apply(this, arguments);
- }
- };
- }
- /**
- * Creates a function that, when called, invokes `func` with the `this`
- * binding of `thisArg` and prepends any additional `bind` arguments to those
- * provided to the bound function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to bind.
- * @param {*} [thisArg] The `this` binding of `func`.
- * @param {...*} [arg] Arguments to be partially applied.
- * @returns {Function} Returns the new bound function.
- * @example
- *
- * var func = function(greeting) {
- * return greeting + ' ' + this.name;
- * };
- *
- * func = _.bind(func, { 'name': 'fred' }, 'hi');
- * func();
- * // => 'hi fred'
- */
- function bind(func, thisArg) {
- return arguments.length > 2
- ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
- : createWrapper(func, 1, null, null, thisArg);
- }
- /**
- * Binds methods of an object to the object itself, overwriting the existing
- * method. Method names may be specified as individual arguments or as arrays
- * of method names. If no method names are provided all the function properties
- * of `object` will be bound.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Object} object The object to bind and assign the bound methods to.
- * @param {...string} [methodName] The object method names to
- * bind, specified as individual method names or arrays of method names.
- * @returns {Object} Returns `object`.
- * @example
- *
- * var view = {
- * 'label': 'docs',
- * 'onClick': function() { console.log('clicked ' + this.label); }
- * };
- *
- * _.bindAll(view);
- * jQuery('#docs').on('click', view.onClick);
- * // => logs 'clicked docs', when the button is clicked
- */
- function bindAll(object) {
- var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
- index = -1,
- length = funcs.length;
- while (++index < length) {
- var key = funcs[index];
- object[key] = createWrapper(object[key], 1, null, null, object);
- }
- return object;
- }
- /**
- * Creates a function that, when called, invokes the method at `object[key]`
- * and prepends any additional `bindKey` arguments to those provided to the bound
- * function. This method differs from `_.bind` by allowing bound functions to
- * reference methods that will be redefined or don't yet exist.
- * See http://michaux.ca/articles/lazy-function-definition-pattern.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Object} object The object the method belongs to.
- * @param {string} key The key of the method.
- * @param {...*} [arg] Arguments to be partially applied.
- * @returns {Function} Returns the new bound function.
- * @example
- *
- * var object = {
- * 'name': 'fred',
- * 'greet': function(greeting) {
- * return greeting + ' ' + this.name;
- * }
- * };
- *
- * var func = _.bindKey(object, 'greet', 'hi');
- * func();
- * // => 'hi fred'
- *
- * object.greet = function(greeting) {
- * return greeting + 'ya ' + this.name + '!';
- * };
- *
- * func();
- * // => 'hiya fred!'
- */
- function bindKey(object, key) {
- return arguments.length > 2
- ? createWrapper(key, 19, slice(arguments, 2), null, object)
- : createWrapper(key, 3, null, null, object);
- }
- /**
- * Creates a function that is the composition of the provided functions,
- * where each function consumes the return value of the function that follows.
- * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
- * Each function is executed with the `this` binding of the composed function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {...Function} [func] Functions to compose.
- * @returns {Function} Returns the new composed function.
- * @example
- *
- * var realNameMap = {
- * 'pebbles': 'penelope'
- * };
- *
- * var format = function(name) {
- * name = realNameMap[name.toLowerCase()] || name;
- * return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
- * };
- *
- * var greet = function(formatted) {
- * return 'Hiya ' + formatted + '!';
- * };
- *
- * var welcome = _.compose(greet, format);
- * welcome('pebbles');
- * // => 'Hiya Penelope!'
- */
- function compose() {
- var funcs = arguments,
- length = funcs.length;
- while (length--) {
- if (!isFunction(funcs[length])) {
- throw new TypeError;
- }
- }
- return function() {
- var args = arguments,
- length = funcs.length;
- while (length--) {
- args = [funcs[length].apply(this, args)];
- }
- return args[0];
- };
- }
- /**
- * Creates a function which accepts one or more arguments of `func` that when
- * invoked either executes `func` returning its result, if all `func` arguments
- * have been provided, or returns a function that accepts one or more of the
- * remaining `func` arguments, and so on. The arity of `func` can be specified
- * if `func.length` is not sufficient.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to curry.
- * @param {number} [arity=func.length] The arity of `func`.
- * @returns {Function} Returns the new curried function.
- * @example
- *
- * var curried = _.curry(function(a, b, c) {
- * console.log(a + b + c);
- * });
- *
- * curried(1)(2)(3);
- * // => 6
- *
- * curried(1, 2)(3);
- * // => 6
- *
- * curried(1, 2, 3);
- * // => 6
- */
- function curry(func, arity) {
- arity = typeof arity == 'number' ? arity : (+arity || func.length);
- return createWrapper(func, 4, null, null, null, arity);
- }
- /**
- * Creates a function that will delay the execution of `func` until after
- * `wait` milliseconds have elapsed since the last time it was invoked.
- * Provide an options object to indicate that `func` should be invoked on
- * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
- * to the debounced function will return the result of the last `func` call.
- *
- * Note: If `leading` and `trailing` options are `true` `func` will be called
- * on the trailing edge of the timeout only if the the debounced function is
- * invoked more than once during the `wait` timeout.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to debounce.
- * @param {number} wait The number of milliseconds to delay.
- * @param {Object} [options] The options object.
- * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
- * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
- * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
- * @returns {Function} Returns the new debounced function.
- * @example
- *
- * // avoid costly calculations while the window size is in flux
- * var lazyLayout = _.debounce(calculateLayout, 150);
- * jQuery(window).on('resize', lazyLayout);
- *
- * // execute `sendMail` when the click event is fired, debouncing subsequent calls
- * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
- * 'leading': true,
- * 'trailing': false
- * });
- *
- * // ensure `batchLog` is executed once after 1 second of debounced calls
- * var source = new EventSource('/stream');
- * source.addEventListener('message', _.debounce(batchLog, 250, {
- * 'maxWait': 1000
- * }, false);
- */
- function debounce(func, wait, options) {
- var args,
- maxTimeoutId,
- result,
- stamp,
- thisArg,
- timeoutId,
- trailingCall,
- lastCalled = 0,
- maxWait = false,
- trailing = true;
- if (!isFunction(func)) {
- throw new TypeError;
- }
- wait = nativeMax(0, wait) || 0;
- if (options === true) {
- var leading = true;
- trailing = false;
- } else if (isObject(options)) {
- leading = options.leading;
- maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
- trailing = 'trailing' in options ? options.trailing : trailing;
- }
- var delayed = function() {
- var remaining = wait - (now() - stamp);
- if (remaining <= 0) {
- if (maxTimeoutId) {
- clearTimeout(maxTimeoutId);
- }
- var isCalled = trailingCall;
- maxTimeoutId = timeoutId = trailingCall = undefined;
- if (isCalled) {
- lastCalled = now();
- result = func.apply(thisArg, args);
- if (!timeoutId && !maxTimeoutId) {
- args = thisArg = null;
- }
- }
- } else {
- timeoutId = setTimeout(delayed, remaining);
- }
- };
- var maxDelayed = function() {
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
- maxTimeoutId = timeoutId = trailingCall = undefined;
- if (trailing || (maxWait !== wait)) {
- lastCalled = now();
- result = func.apply(thisArg, args);
- if (!timeoutId && !maxTimeoutId) {
- args = thisArg = null;
- }
- }
- };
- return function() {
- args = arguments;
- stamp = now();
- thisArg = this;
- trailingCall = trailing && (timeoutId || !leading);
- if (maxWait === false) {
- var leadingCall = leading && !timeoutId;
- } else {
- if (!maxTimeoutId && !leading) {
- lastCalled = stamp;
- }
- var remaining = maxWait - (stamp - lastCalled),
- isCalled = remaining <= 0;
- if (isCalled) {
- if (maxTimeoutId) {
- maxTimeoutId = clearTimeout(maxTimeoutId);
- }
- lastCalled = stamp;
- result = func.apply(thisArg, args);
- }
- else if (!maxTimeoutId) {
- maxTimeoutId = setTimeout(maxDelayed, remaining);
- }
- }
- if (isCalled && timeoutId) {
- timeoutId = clearTimeout(timeoutId);
- }
- else if (!timeoutId && wait !== maxWait) {
- timeoutId = setTimeout(delayed, wait);
- }
- if (leadingCall) {
- isCalled = true;
- result = func.apply(thisArg, args);
- }
- if (isCalled && !timeoutId && !maxTimeoutId) {
- args = thisArg = null;
- }
- return result;
- };
- }
- /**
- * Defers executing the `func` function until the current call stack has cleared.
- * Additional arguments will be provided to `func` when it is invoked.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to defer.
- * @param {...*} [arg] Arguments to invoke the function with.
- * @returns {number} Returns the timer id.
- * @example
- *
- * _.defer(function(text) { console.log(text); }, 'deferred');
- * // logs 'deferred' after one or more milliseconds
- */
- function defer(func) {
- if (!isFunction(func)) {
- throw new TypeError;
- }
- var args = slice(arguments, 1);
- return setTimeout(function() { func.apply(undefined, args); }, 1);
- }
- /**
- * Executes the `func` function after `wait` milliseconds. Additional arguments
- * will be provided to `func` when it is invoked.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to delay.
- * @param {number} wait The number of milliseconds to delay execution.
- * @param {...*} [arg] Arguments to invoke the function with.
- * @returns {number} Returns the timer id.
- * @example
- *
- * _.delay(function(text) { console.log(text); }, 1000, 'later');
- * // => logs 'later' after one second
- */
- function delay(func, wait) {
- if (!isFunction(func)) {
- throw new TypeError;
- }
- var args = slice(arguments, 2);
- return setTimeout(function() { func.apply(undefined, args); }, wait);
- }
- /**
- * Creates a function that memoizes the result of `func`. If `resolver` is
- * provided it will be used to determine the cache key for storing the result
- * based on the arguments provided to the memoized function. By default, the
- * first argument provided to the memoized function is used as the cache key.
- * The `func` is executed with the `this` binding of the memoized function.
- * The result cache is exposed as the `cache` property on the memoized function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to have its output memoized.
- * @param {Function} [resolver] A function used to resolve the cache key.
- * @returns {Function} Returns the new memoizing function.
- * @example
- *
- * var fibonacci = _.memoize(function(n) {
- * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
- * });
- *
- * fibonacci(9)
- * // => 34
- *
- * var data = {
- * 'fred': { 'name': 'fred', 'age': 40 },
- * 'pebbles': { 'name': 'pebbles', 'age': 1 }
- * };
- *
- * // modifying the result cache
- * var get = _.memoize(function(name) { return data[name]; }, _.identity);
- * get('pebbles');
- * // => { 'name': 'pebbles', 'age': 1 }
- *
- * get.cache.pebbles.name = 'penelope';
- * get('pebbles');
- * // => { 'name': 'penelope', 'age': 1 }
- */
- function memoize(func, resolver) {
- if (!isFunction(func)) {
- throw new TypeError;
- }
- var memoized = function() {
- var cache = memoized.cache,
- key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
- return hasOwnProperty.call(cache, key)
- ? cache[key]
- : (cache[key] = func.apply(this, arguments));
- }
- memoized.cache = {};
- return memoized;
- }
- /**
- * Creates a function that is restricted to execute `func` once. Repeat calls to
- * the function will return the value of the first call. The `func` is executed
- * with the `this` binding of the created function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to restrict.
- * @returns {Function} Returns the new restricted function.
- * @example
- *
- * var initialize = _.once(createApplication);
- * initialize();
- * initialize();
- * // `initialize` executes `createApplication` once
- */
- function once(func) {
- var ran,
- result;
- if (!isFunction(func)) {
- throw new TypeError;
- }
- return function() {
- if (ran) {
- return result;
- }
- ran = true;
- result = func.apply(this, arguments);
- // clear the `func` variable so the function may be garbage collected
- func = null;
- return result;
- };
- }
- /**
- * Creates a function that, when called, invokes `func` with any additional
- * `partial` arguments prepended to those provided to the new function. This
- * method is similar to `_.bind` except it does **not** alter the `this` binding.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to partially apply arguments to.
- * @param {...*} [arg] Arguments to be partially applied.
- * @returns {Function} Returns the new partially applied function.
- * @example
- *
- * var greet = function(greeting, name) { return greeting + ' ' + name; };
- * var hi = _.partial(greet, 'hi');
- * hi('fred');
- * // => 'hi fred'
- */
- function partial(func) {
- return createWrapper(func, 16, slice(arguments, 1));
- }
- /**
- * This method is like `_.partial` except that `partial` arguments are
- * appended to those provided to the new function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to partially apply arguments to.
- * @param {...*} [arg] Arguments to be partially applied.
- * @returns {Function} Returns the new partially applied function.
- * @example
- *
- * var defaultsDeep = _.partialRight(_.merge, _.defaults);
- *
- * var options = {
- * 'variable': 'data',
- * 'imports': { 'jq': $ }
- * };
- *
- * defaultsDeep(options, _.templateSettings);
- *
- * options.variable
- * // => 'data'
- *
- * options.imports
- * // => { '_': _, 'jq': $ }
- */
- function partialRight(func) {
- return createWrapper(func, 32, null, slice(arguments, 1));
- }
- /**
- * Creates a function that, when executed, will only call the `func` function
- * at most once per every `wait` milliseconds. Provide an options object to
- * indicate that `func` should be invoked on the leading and/or trailing edge
- * of the `wait` timeout. Subsequent calls to the throttled function will
- * return the result of the last `func` call.
- *
- * Note: If `leading` and `trailing` options are `true` `func` will be called
- * on the trailing edge of the timeout only if the the throttled function is
- * invoked more than once during the `wait` timeout.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {Function} func The function to throttle.
- * @param {number} wait The number of milliseconds to throttle executions to.
- * @param {Object} [options] The options object.
- * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
- * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
- * @returns {Function} Returns the new throttled function.
- * @example
- *
- * // avoid excessively updating the position while scrolling
- * var throttled = _.throttle(updatePosition, 100);
- * jQuery(window).on('scroll', throttled);
- *
- * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
- * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
- * 'trailing': false
- * }));
- */
- function throttle(func, wait, options) {
- var leading = true,
- trailing = true;
- if (!isFunction(func)) {
- throw new TypeError;
- }
- if (options === false) {
- leading = false;
- } else if (isObject(options)) {
- leading = 'leading' in options ? options.leading : leading;
- trailing = 'trailing' in options ? options.trailing : trailing;
- }
- debounceOptions.leading = leading;
- debounceOptions.maxWait = wait;
- debounceOptions.trailing = trailing;
- return debounce(func, wait, debounceOptions);
- }
- /**
- * Creates a function that provides `value` to the wrapper function as its
- * first argument. Additional arguments provided to the function are appended
- * to those provided to the wrapper function. The wrapper is executed with
- * the `this` binding of the created function.
- *
- * @static
- * @memberOf _
- * @category Functions
- * @param {*} value The value to wrap.
- * @param {Function} wrapper The wrapper function.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var p = _.wrap(_.escape, function(func, text) {
- * return '<p>' + func(text) + '</p>';
- * });
- *
- * p('Fred, Wilma, & Pebbles');
- * // => '<p>Fred, Wilma, & Pebbles</p>'
- */
- function wrap(value, wrapper) {
- return createWrapper(wrapper, 16, [value]);
- }
- /*--------------------------------------------------------------------------*/
- /**
- * Creates a function that returns `value`.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {*} value The value to return from the new function.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var object = { 'name': 'fred' };
- * var getter = _.constant(object);
- * getter() === object;
- * // => true
- */
- function constant(value) {
- return function() {
- return value;
- };
- }
- /**
- * Produces a callback bound to an optional `thisArg`. If `func` is a property
- * name the created callback will return the property value for a given element.
- * If `func` is an object the created callback will return `true` for elements
- * that contain the equivalent object properties, otherwise it will return `false`.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {*} [func=identity] The value to convert to a callback.
- * @param {*} [thisArg] The `this` binding of the created callback.
- * @param {number} [argCount] The number of arguments the callback accepts.
- * @returns {Function} Returns a callback function.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * // wrap to create custom callback shorthands
- * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
- * var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
- * return !match ? func(callback, thisArg) : function(object) {
- * return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
- * };
- * });
- *
- * _.filter(characters, 'age__gt38');
- * // => [{ 'name': 'fred', 'age': 40 }]
- */
- function createCallback(func, thisArg, argCount) {
- var type = typeof func;
- if (func == null || type == 'function') {
- return baseCreateCallback(func, thisArg, argCount);
- }
- // handle "_.pluck" style callback shorthands
- if (type != 'object') {
- return property(func);
- }
- var props = keys(func),
- key = props[0],
- a = func[key];
- // handle "_.where" style callback shorthands
- if (props.length == 1 && a === a && !isObject(a)) {
- // fast path the common case of providing an object with a single
- // property containing a primitive value
- return function(object) {
- var b = object[key];
- return a === b && (a !== 0 || (1 / a == 1 / b));
- };
- }
- return function(object) {
- var length = props.length,
- result = false;
- while (length--) {
- if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
- break;
- }
- }
- return result;
- };
- }
- /**
- * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
- * corresponding HTML entities.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {string} string The string to escape.
- * @returns {string} Returns the escaped string.
- * @example
- *
- * _.escape('Fred, Wilma, & Pebbles');
- * // => 'Fred, Wilma, & Pebbles'
- */
- function escape(string) {
- return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
- }
- /**
- * This method returns the first argument provided to it.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {*} value Any value.
- * @returns {*} Returns `value`.
- * @example
- *
- * var object = { 'name': 'fred' };
- * _.identity(object) === object;
- * // => true
- */
- function identity(value) {
- return value;
- }
- /**
- * Adds function properties of a source object to the destination object.
- * If `object` is a function methods will be added to its prototype as well.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Function|Object} [object=lodash] object The destination object.
- * @param {Object} source The object of functions to add.
- * @param {Object} [options] The options object.
- * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
- * @example
- *
- * function capitalize(string) {
- * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
- * }
- *
- * _.mixin({ 'capitalize': capitalize });
- * _.capitalize('fred');
- * // => 'Fred'
- *
- * _('fred').capitalize().value();
- * // => 'Fred'
- *
- * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
- * _('fred').capitalize();
- * // => 'Fred'
- */
- function mixin(object, source, options) {
- var chain = true,
- methodNames = source && functions(source);
- if (!source || (!options && !methodNames.length)) {
- if (options == null) {
- options = source;
- }
- ctor = lodashWrapper;
- source = object;
- object = lodash;
- methodNames = functions(source);
- }
- if (options === false) {
- chain = false;
- } else if (isObject(options) && 'chain' in options) {
- chain = options.chain;
- }
- var ctor = object,
- isFunc = isFunction(ctor);
- forEach(methodNames, function(methodName) {
- var func = object[methodName] = source[methodName];
- if (isFunc) {
- ctor.prototype[methodName] = function() {
- var chainAll = this.__chain__,
- value = this.__wrapped__,
- args = [value];
- push.apply(args, arguments);
- var result = func.apply(object, args);
- if (chain || chainAll) {
- if (value === result && isObject(result)) {
- return this;
- }
- result = new ctor(result);
- result.__chain__ = chainAll;
- }
- return result;
- };
- }
- });
- }
- /**
- * Reverts the '_' variable to its previous value and returns a reference to
- * the `lodash` function.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @returns {Function} Returns the `lodash` function.
- * @example
- *
- * var lodash = _.noConflict();
- */
- function noConflict() {
- context._ = oldDash;
- return this;
- }
- /**
- * A no-operation function.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @example
- *
- * var object = { 'name': 'fred' };
- * _.noop(object) === undefined;
- * // => true
- */
- function noop() {
- // no operation performed
- }
- /**
- * Gets the number of milliseconds that have elapsed since the Unix epoch
- * (1 January 1970 00:00:00 UTC).
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @example
- *
- * var stamp = _.now();
- * _.defer(function() { console.log(_.now() - stamp); });
- * // => logs the number of milliseconds it took for the deferred function to be called
- */
- var now = isNative(now = Date.now) && now || function() {
- return new Date().getTime();
- };
- /**
- * Converts the given value into an integer of the specified radix.
- * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
- * `value` is a hexadecimal, in which case a `radix` of `16` is used.
- *
- * Note: This method avoids differences in native ES3 and ES5 `parseInt`
- * implementations. See http://es5.github.io/#E.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {string} value The value to parse.
- * @param {number} [radix] The radix used to interpret the value to parse.
- * @returns {number} Returns the new integer value.
- * @example
- *
- * _.parseInt('08');
- * // => 8
- */
- var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
- // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
- return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
- };
- /**
- * Creates a "_.pluck" style function, which returns the `key` value of a
- * given object.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {string} key The name of the property to retrieve.
- * @returns {Function} Returns the new function.
- * @example
- *
- * var characters = [
- * { 'name': 'fred', 'age': 40 },
- * { 'name': 'barney', 'age': 36 }
- * ];
- *
- * var getName = _.property('name');
- *
- * _.map(characters, getName);
- * // => ['barney', 'fred']
- *
- * _.sortBy(characters, getName);
- * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }]
- */
- function property(key) {
- return function(object) {
- return object[key];
- };
- }
- /**
- * Produces a random number between `min` and `max` (inclusive). If only one
- * argument is provided a number between `0` and the given number will be
- * returned. If `floating` is truey or either `min` or `max` are floats a
- * floating-point number will be returned instead of an integer.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {number} [min=0] The minimum possible value.
- * @param {number} [max=1] The maximum possible value.
- * @param {boolean} [floating=false] Specify returning a floating-point number.
- * @returns {number} Returns a random number.
- * @example
- *
- * _.random(0, 5);
- * // => an integer between 0 and 5
- *
- * _.random(5);
- * // => also an integer between 0 and 5
- *
- * _.random(5, true);
- * // => a floating-point number between 0 and 5
- *
- * _.random(1.2, 5.2);
- * // => a floating-point number between 1.2 and 5.2
- */
- function random(min, max, floating) {
- var noMin = min == null,
- noMax = max == null;
- if (floating == null) {
- if (typeof min == 'boolean' && noMax) {
- floating = min;
- min = 1;
- }
- else if (!noMax && typeof max == 'boolean') {
- floating = max;
- noMax = true;
- }
- }
- if (noMin && noMax) {
- max = 1;
- }
- min = +min || 0;
- if (noMax) {
- max = min;
- min = 0;
- } else {
- max = +max || 0;
- }
- if (floating || min % 1 || max % 1) {
- var rand = nativeRandom();
- return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
- }
- return baseRandom(min, max);
- }
- /**
- * Resolves the value of property `key` on `object`. If `key` is a function
- * it will be invoked with the `this` binding of `object` and its result returned,
- * else the property value is returned. If `object` is falsey then `undefined`
- * is returned.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {Object} object The object to inspect.
- * @param {string} key The name of the property to resolve.
- * @returns {*} Returns the resolved value.
- * @example
- *
- * var object = {
- * 'cheese': 'crumpets',
- * 'stuff': function() {
- * return 'nonsense';
- * }
- * };
- *
- * _.result(object, 'cheese');
- * // => 'crumpets'
- *
- * _.result(object, 'stuff');
- * // => 'nonsense'
- */
- function result(object, key) {
- if (object) {
- var value = object[key];
- return isFunction(value) ? object[key]() : value;
- }
- }
- /**
- * A micro-templating method that handles arbitrary delimiters, preserves
- * whitespace, and correctly escapes quotes within interpolated code.
- *
- * Note: In the development build, `_.template` utilizes sourceURLs for easier
- * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
- *
- * For more information on precompiling templates see:
- * http://lodash.com/custom-builds
- *
- * For more information on Chrome extension sandboxes see:
- * http://developer.chrome.com/stable/extensions/sandboxingEval.html
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {string} text The template text.
- * @param {Object} data The data object used to populate the text.
- * @param {Object} [options] The options object.
- * @param {RegExp} [options.escape] The "escape" delimiter.
- * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
- * @param {Object} [options.imports] An object to import into the template as local variables.
- * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
- * @param {string} [sourceURL] The sourceURL of the template's compiled source.
- * @param {string} [variable] The data object variable name.
- * @returns {Function|string} Returns a compiled function when no `data` object
- * is given, else it returns the interpolated text.
- * @example
- *
- * // using the "interpolate" delimiter to create a compiled template
- * var compiled = _.template('hello <%= name %>');
- * compiled({ 'name': 'fred' });
- * // => 'hello fred'
- *
- * // using the "escape" delimiter to escape HTML in data property values
- * _.template('<b><%- value %></b>', { 'value': '<script>' });
- * // => '<b><script></b>'
- *
- * // using the "evaluate" delimiter to generate HTML
- * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
- * _.template(list, { 'people': ['fred', 'barney'] });
- * // => '<li>fred</li><li>barney</li>'
- *
- * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
- * _.template('hello ${ name }', { 'name': 'pebbles' });
- * // => 'hello pebbles'
- *
- * // using the internal `print` function in "evaluate" delimiters
- * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
- * // => 'hello barney!'
- *
- * // using a custom template delimiters
- * _.templateSettings = {
- * 'interpolate': /{{([\s\S]+?)}}/g
- * };
- *
- * _.template('hello {{ name }}!', { 'name': 'mustache' });
- * // => 'hello mustache!'
- *
- * // using the `imports` option to import jQuery
- * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
- * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
- * // => '<li>fred</li><li>barney</li>'
- *
- * // using the `sourceURL` option to specify a custom sourceURL for the template
- * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
- * compiled(data);
- * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
- *
- * // using the `variable` option to ensure a with-statement isn't used in the compiled template
- * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
- * compiled.source;
- * // => function(data) {
- * var __t, __p = '', __e = _.escape;
- * __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
- * return __p;
- * }
- *
- * // using the `source` property to inline compiled templates for meaningful
- * // line numbers in error messages and a stack trace
- * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
- * var JST = {\
- * "main": ' + _.template(mainText).source + '\
- * };\
- * ');
- */
- function template(text, data, options) {
- // based on John Resig's `tmpl` implementation
- // http://ejohn.org/blog/javascript-micro-templating/
- // and Laura Doktorova's doT.js
- // https://github.com/olado/doT
- var settings = lodash.templateSettings;
- text = String(text || '');
- // avoid missing dependencies when `iteratorTemplate` is not defined
- options = defaults({}, options, settings);
- var imports = defaults({}, options.imports, settings.imports),
- importsKeys = keys(imports),
- importsValues = values(imports);
- var isEvaluating,
- index = 0,
- interpolate = options.interpolate || reNoMatch,
- source = "__p += '";
- // compile the regexp to match each delimiter
- var reDelimiters = RegExp(
- (options.escape || reNoMatch).source + '|' +
- interpolate.source + '|' +
- (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
- (options.evaluate || reNoMatch).source + '|$'
- , 'g');
- text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
- interpolateValue || (interpolateValue = esTemplateValue);
- // escape characters that cannot be included in string literals
- source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
- // replace delimiters with snippets
- if (escapeValue) {
- source += "' +\n__e(" + escapeValue + ") +\n'";
- }
- if (evaluateValue) {
- isEvaluating = true;
- source += "';\n" + evaluateValue + ";\n__p += '";
- }
- if (interpolateValue) {
- source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
- }
- index = offset + match.length;
- // the JS engine embedded in Adobe products requires returning the `match`
- // string in order to produce the correct `offset` value
- return match;
- });
- source += "';\n";
- // if `variable` is not specified, wrap a with-statement around the generated
- // code to add the data object to the top of the scope chain
- var variable = options.variable,
- hasVariable = variable;
- if (!hasVariable) {
- variable = 'obj';
- source = 'with (' + variable + ') {\n' + source + '\n}\n';
- }
- // cleanup code by stripping empty strings
- source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
- .replace(reEmptyStringMiddle, '$1')
- .replace(reEmptyStringTrailing, '$1;');
- // frame code as the function body
- source = 'function(' + variable + ') {\n' +
- (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
- "var __t, __p = '', __e = _.escape" +
- (isEvaluating
- ? ', __j = Array.prototype.join;\n' +
- "function print() { __p += __j.call(arguments, '') }\n"
- : ';\n'
- ) +
- source +
- 'return __p\n}';
- // Use a sourceURL for easier debugging.
- // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
- var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
- try {
- var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
- } catch(e) {
- e.source = source;
- throw e;
- }
- if (data) {
- return result(data);
- }
- // provide the compiled function's source by its `toString` method, in
- // supported environments, or the `source` property as a convenience for
- // inlining compiled templates during the build process
- result.source = source;
- return result;
- }
- /**
- * Executes the callback `n` times, returning an array of the results
- * of each callback execution. The callback is bound to `thisArg` and invoked
- * with one argument; (index).
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {number} n The number of times to execute the callback.
- * @param {Function} callback The function called per iteration.
- * @param {*} [thisArg] The `this` binding of `callback`.
- * @returns {Array} Returns an array of the results of each `callback` execution.
- * @example
- *
- * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
- * // => [3, 6, 4]
- *
- * _.times(3, function(n) { mage.castSpell(n); });
- * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
- *
- * _.times(3, function(n) { this.cast(n); }, mage);
- * // => also calls `mage.castSpell(n)` three times
- */
- function times(n, callback, thisArg) {
- n = (n = +n) > -1 ? n : 0;
- var index = -1,
- result = Array(n);
- callback = baseCreateCallback(callback, thisArg, 1);
- while (++index < n) {
- result[index] = callback(index);
- }
- return result;
- }
- /**
- * The inverse of `_.escape` this method converts the HTML entities
- * `&`, `<`, `>`, `"`, and `'` in `string` to their
- * corresponding characters.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {string} string The string to unescape.
- * @returns {string} Returns the unescaped string.
- * @example
- *
- * _.unescape('Fred, Barney & Pebbles');
- * // => 'Fred, Barney & Pebbles'
- */
- function unescape(string) {
- return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
- }
- /**
- * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
- *
- * @static
- * @memberOf _
- * @category Utilities
- * @param {string} [prefix] The value to prefix the ID with.
- * @returns {string} Returns the unique ID.
- * @example
- *
- * _.uniqueId('contact_');
- * // => 'contact_104'
- *
- * _.uniqueId();
- * // => '105'
- */
- function uniqueId(prefix) {
- var id = ++idCounter;
- return String(prefix == null ? '' : prefix) + id;
- }
- /*--------------------------------------------------------------------------*/
- /**
- * Creates a `lodash` object that wraps the given value with explicit
- * method chaining enabled.
- *
- * @static
- * @memberOf _
- * @category Chaining
- * @param {*} value The value to wrap.
- * @returns {Object} Returns the wrapper object.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 },
- * { 'name': 'pebbles', 'age': 1 }
- * ];
- *
- * var youngest = _.chain(characters)
- * .sortBy('age')
- * .map(function(chr) { return chr.name + ' is ' + chr.age; })
- * .first()
- * .value();
- * // => 'pebbles is 1'
- */
- function chain(value) {
- value = new lodashWrapper(value);
- value.__chain__ = true;
- return value;
- }
- /**
- * Invokes `interceptor` with the `value` as the first argument and then
- * returns `value`. The purpose of this method is to "tap into" a method
- * chain in order to perform operations on intermediate results within
- * the chain.
- *
- * @static
- * @memberOf _
- * @category Chaining
- * @param {*} value The value to provide to `interceptor`.
- * @param {Function} interceptor The function to invoke.
- * @returns {*} Returns `value`.
- * @example
- *
- * _([1, 2, 3, 4])
- * .tap(function(array) { array.pop(); })
- * .reverse()
- * .value();
- * // => [3, 2, 1]
- */
- function tap(value, interceptor) {
- interceptor(value);
- return value;
- }
- /**
- * Enables explicit method chaining on the wrapper object.
- *
- * @name chain
- * @memberOf _
- * @category Chaining
- * @returns {*} Returns the wrapper object.
- * @example
- *
- * var characters = [
- * { 'name': 'barney', 'age': 36 },
- * { 'name': 'fred', 'age': 40 }
- * ];
- *
- * // without explicit chaining
- * _(characters).first();
- * // => { 'name': 'barney', 'age': 36 }
- *
- * // with explicit chaining
- * _(characters).chain()
- * .first()
- * .pick('age')
- * .value();
- * // => { 'age': 36 }
- */
- function wrapperChain() {
- this.__chain__ = true;
- return this;
- }
- /**
- * Produces the `toString` result of the wrapped value.
- *
- * @name toString
- * @memberOf _
- * @category Chaining
- * @returns {string} Returns the string result.
- * @example
- *
- * _([1, 2, 3]).toString();
- * // => '1,2,3'
- */
- function wrapperToString() {
- return String(this.__wrapped__);
- }
- /**
- * Extracts the wrapped value.
- *
- * @name valueOf
- * @memberOf _
- * @alias value
- * @category Chaining
- * @returns {*} Returns the wrapped value.
- * @example
- *
- * _([1, 2, 3]).valueOf();
- * // => [1, 2, 3]
- */
- function wrapperValueOf() {
- return this.__wrapped__;
- }
- /*--------------------------------------------------------------------------*/
- // add functions that return wrapped values when chaining
- lodash.after = after;
- lodash.assign = assign;
- lodash.at = at;
- lodash.bind = bind;
- lodash.bindAll = bindAll;
- lodash.bindKey = bindKey;
- lodash.chain = chain;
- lodash.compact = compact;
- lodash.compose = compose;
- lodash.constant = constant;
- lodash.countBy = countBy;
- lodash.create = create;
- lodash.createCallback = createCallback;
- lodash.curry = curry;
- lodash.debounce = debounce;
- lodash.defaults = defaults;
- lodash.defer = defer;
- lodash.delay = delay;
- lodash.difference = difference;
- lodash.filter = filter;
- lodash.flatten = flatten;
- lodash.forEach = forEach;
- lodash.forEachRight = forEachRight;
- lodash.forIn = forIn;
- lodash.forInRight = forInRight;
- lodash.forOwn = forOwn;
- lodash.forOwnRight = forOwnRight;
- lodash.functions = functions;
- lodash.groupBy = groupBy;
- lodash.indexBy = indexBy;
- lodash.initial = initial;
- lodash.intersection = intersection;
- lodash.invert = invert;
- lodash.invoke = invoke;
- lodash.keys = keys;
- lodash.map = map;
- lodash.mapValues = mapValues;
- lodash.max = max;
- lodash.memoize = memoize;
- lodash.merge = merge;
- lodash.min = min;
- lodash.omit = omit;
- lodash.once = once;
- lodash.pairs = pairs;
- lodash.partial = partial;
- lodash.partialRight = partialRight;
- lodash.pick = pick;
- lodash.pluck = pluck;
- lodash.property = property;
- lodash.pull = pull;
- lodash.range = range;
- lodash.reject = reject;
- lodash.remove = remove;
- lodash.rest = rest;
- lodash.shuffle = shuffle;
- lodash.sortBy = sortBy;
- lodash.tap = tap;
- lodash.throttle = throttle;
- lodash.times = times;
- lodash.toArray = toArray;
- lodash.transform = transform;
- lodash.union = union;
- lodash.uniq = uniq;
- lodash.values = values;
- lodash.where = where;
- lodash.without = without;
- lodash.wrap = wrap;
- lodash.xor = xor;
- lodash.zip = zip;
- lodash.zipObject = zipObject;
- // add aliases
- lodash.collect = map;
- lodash.drop = rest;
- lodash.each = forEach;
- lodash.eachRight = forEachRight;
- lodash.extend = assign;
- lodash.methods = functions;
- lodash.object = zipObject;
- lodash.select = filter;
- lodash.tail = rest;
- lodash.unique = uniq;
- lodash.unzip = zip;
- // add functions to `lodash.prototype`
- mixin(lodash);
- /*--------------------------------------------------------------------------*/
- // add functions that return unwrapped values when chaining
- lodash.clone = clone;
- lodash.cloneDeep = cloneDeep;
- lodash.contains = contains;
- lodash.escape = escape;
- lodash.every = every;
- lodash.find = find;
- lodash.findIndex = findIndex;
- lodash.findKey = findKey;
- lodash.findLast = findLast;
- lodash.findLastIndex = findLastIndex;
- lodash.findLastKey = findLastKey;
- lodash.has = has;
- lodash.identity = identity;
- lodash.indexOf = indexOf;
- lodash.isArguments = isArguments;
- lodash.isArray = isArray;
- lodash.isBoolean = isBoolean;
- lodash.isDate = isDate;
- lodash.isElement = isElement;
- lodash.isEmpty = isEmpty;
- lodash.isEqual = isEqual;
- lodash.isFinite = isFinite;
- lodash.isFunction = isFunction;
- lodash.isNaN = isNaN;
- lodash.isNull = isNull;
- lodash.isNumber = isNumber;
- lodash.isObject = isObject;
- lodash.isPlainObject = isPlainObject;
- lodash.isRegExp = isRegExp;
- lodash.isString = isString;
- lodash.isUndefined = isUndefined;
- lodash.lastIndexOf = lastIndexOf;
- lodash.mixin = mixin;
- lodash.noConflict = noConflict;
- lodash.noop = noop;
- lodash.now = now;
- lodash.parseInt = parseInt;
- lodash.random = random;
- lodash.reduce = reduce;
- lodash.reduceRight = reduceRight;
- lodash.result = result;
- lodash.runInContext = runInContext;
- lodash.size = size;
- lodash.some = some;
- lodash.sortedIndex = sortedIndex;
- lodash.template = template;
- lodash.unescape = unescape;
- lodash.uniqueId = uniqueId;
- // add aliases
- lodash.all = every;
- lodash.any = some;
- lodash.detect = find;
- lodash.findWhere = find;
- lodash.foldl = reduce;
- lodash.foldr = reduceRight;
- lodash.include = contains;
- lodash.inject = reduce;
- mixin(function() {
- var source = {}
- forOwn(lodash, function(func, methodName) {
- if (!lodash.prototype[methodName]) {
- source[methodName] = func;
- }
- });
- return source;
- }(), false);
- /*--------------------------------------------------------------------------*/
- // add functions capable of returning wrapped and unwrapped values when chaining
- lodash.first = first;
- lodash.last = last;
- lodash.sample = sample;
- // add aliases
- lodash.take = first;
- lodash.head = first;
- forOwn(lodash, function(func, methodName) {
- var callbackable = methodName !== 'sample';
- if (!lodash.prototype[methodName]) {
- lodash.prototype[methodName]= function(n, guard) {
- var chainAll = this.__chain__,
- result = func(this.__wrapped__, n, guard);
- return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
- ? result
- : new lodashWrapper(result, chainAll);
- };
- }
- });
- /*--------------------------------------------------------------------------*/
- /**
- * The semantic version number.
- *
- * @static
- * @memberOf _
- * @type string
- */
- lodash.VERSION = '2.4.1';
- // add "Chaining" functions to the wrapper
- lodash.prototype.chain = wrapperChain;
- lodash.prototype.toString = wrapperToString;
- lodash.prototype.value = wrapperValueOf;
- lodash.prototype.valueOf = wrapperValueOf;
- // add `Array` functions that return unwrapped values
- forEach(['join', 'pop', 'shift'], function(methodName) {
- var func = arrayRef[methodName];
- lodash.prototype[methodName] = function() {
- var chainAll = this.__chain__,
- result = func.apply(this.__wrapped__, arguments);
- return chainAll
- ? new lodashWrapper(result, chainAll)
- : result;
- };
- });
- // add `Array` functions that return the existing wrapped value
- forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
- var func = arrayRef[methodName];
- lodash.prototype[methodName] = function() {
- func.apply(this.__wrapped__, arguments);
- return this;
- };
- });
- // add `Array` functions that return new wrapped values
- forEach(['concat', 'slice', 'splice'], function(methodName) {
- var func = arrayRef[methodName];
- lodash.prototype[methodName] = function() {
- return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
- };
- });
- return lodash;
- }
- /*--------------------------------------------------------------------------*/
- // expose Lo-Dash
- var _ = runInContext();
- // some AMD build optimizers like r.js check for condition patterns like the following:
- if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
- // Expose Lo-Dash to the global object even when an AMD loader is present in
- // case Lo-Dash is loaded with a RequireJS shim config.
- // See http://requirejs.org/docs/api.html#config-shim
- root._ = _;
- // define as an anonymous module so, through path mapping, it can be
- // referenced as the "underscore" module
- define(function() {
- return _;
- });
- }
- // check for `exports` after `define` in case a build optimizer adds an `exports` object
- else if (freeExports && freeModule) {
- // in Node.js or RingoJS
- if (moduleExports) {
- (freeModule.exports = _)._ = _;
- }
- // in Narwhal or Rhino -require
- else {
- freeExports._ = _;
- }
- }
- else {
- // in a browser or Rhino
- root._ = _;
- }
- }.call(this));
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
- },{}]},{},[1]);
|