less.js 337 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849
  1. /*!
  2. * Less - Leaner CSS v2.4.0
  3. * http://lesscss.org
  4. *
  5. * Copyright (c) 2009-2015, Alexis Sellier <self@cloudhead.net>
  6. * Licensed under the Apache v2 License.
  7. *
  8. */
  9. /** * @license Apache v2
  10. */
  11. !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.less=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  12. var addDataAttr = require("./utils").addDataAttr,
  13. browser = require("./browser");
  14. module.exports = function(window, options) {
  15. // use options from the current script tag data attribues
  16. addDataAttr(options, browser.currentScript(window));
  17. if (options.isFileProtocol === undefined) {
  18. options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
  19. }
  20. // Load styles asynchronously (default: false)
  21. //
  22. // This is set to `false` by default, so that the body
  23. // doesn't start loading before the stylesheets are parsed.
  24. // Setting this to `true` can result in flickering.
  25. //
  26. options.async = options.async || false;
  27. options.fileAsync = options.fileAsync || false;
  28. // Interval between watch polls
  29. options.poll = options.poll || (options.isFileProtocol ? 1000 : 1500);
  30. options.env = options.env || (window.location.hostname == '127.0.0.1' ||
  31. window.location.hostname == '0.0.0.0' ||
  32. window.location.hostname == 'localhost' ||
  33. (window.location.port &&
  34. window.location.port.length > 0) ||
  35. options.isFileProtocol ? 'development'
  36. : 'production');
  37. var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(window.location.hash);
  38. if (dumpLineNumbers) {
  39. options.dumpLineNumbers = dumpLineNumbers[1];
  40. }
  41. if (options.useFileCache === undefined) {
  42. options.useFileCache = true;
  43. }
  44. if (options.onReady === undefined) {
  45. options.onReady = true;
  46. }
  47. };
  48. },{"./browser":3,"./utils":9}],2:[function(require,module,exports){
  49. /**
  50. * Kicks off less and compiles any stylesheets
  51. * used in the browser distributed version of less
  52. * to kick-start less using the browser api
  53. */
  54. /*global window */
  55. // shim Promise if required
  56. require('promise/polyfill.js');
  57. var options = window.less || {};
  58. require("./add-default-options")(window, options);
  59. var less = module.exports = require("./index")(window, options);
  60. if (options.onReady) {
  61. if (/!watch/.test(window.location.hash)) {
  62. less.watch();
  63. }
  64. less.pageLoadFinished = less.registerStylesheets().then(
  65. function () {
  66. return less.refresh(less.env === 'development');
  67. }
  68. );
  69. }
  70. },{"./add-default-options":1,"./index":7,"promise/polyfill.js":"promise/polyfill.js"}],3:[function(require,module,exports){
  71. var utils = require("./utils");
  72. module.exports = {
  73. createCSS: function (document, styles, sheet) {
  74. // Strip the query-string
  75. var href = sheet.href || '';
  76. // If there is no title set, use the filename, minus the extension
  77. var id = 'less:' + (sheet.title || utils.extractId(href));
  78. // If this has already been inserted into the DOM, we may need to replace it
  79. var oldStyleNode = document.getElementById(id);
  80. var keepOldStyleNode = false;
  81. // Create a new stylesheet node for insertion or (if necessary) replacement
  82. var styleNode = document.createElement('style');
  83. styleNode.setAttribute('type', 'text/css');
  84. if (sheet.media) {
  85. styleNode.setAttribute('media', sheet.media);
  86. }
  87. styleNode.id = id;
  88. if (!styleNode.styleSheet) {
  89. styleNode.appendChild(document.createTextNode(styles));
  90. // If new contents match contents of oldStyleNode, don't replace oldStyleNode
  91. keepOldStyleNode = (oldStyleNode !== null && oldStyleNode.childNodes.length > 0 && styleNode.childNodes.length > 0 &&
  92. oldStyleNode.firstChild.nodeValue === styleNode.firstChild.nodeValue);
  93. }
  94. var head = document.getElementsByTagName('head')[0];
  95. // If there is no oldStyleNode, just append; otherwise, only append if we need
  96. // to replace oldStyleNode with an updated stylesheet
  97. if (oldStyleNode === null || keepOldStyleNode === false) {
  98. var nextEl = sheet && sheet.nextSibling || null;
  99. if (nextEl) {
  100. nextEl.parentNode.insertBefore(styleNode, nextEl);
  101. } else {
  102. head.appendChild(styleNode);
  103. }
  104. }
  105. if (oldStyleNode && keepOldStyleNode === false) {
  106. oldStyleNode.parentNode.removeChild(oldStyleNode);
  107. }
  108. // For IE.
  109. // This needs to happen *after* the style element is added to the DOM, otherwise IE 7 and 8 may crash.
  110. // See http://social.msdn.microsoft.com/Forums/en-US/7e081b65-878a-4c22-8e68-c10d39c2ed32/internet-explorer-crashes-appending-style-element-to-head
  111. if (styleNode.styleSheet) {
  112. try {
  113. styleNode.styleSheet.cssText = styles;
  114. } catch (e) {
  115. throw new Error("Couldn't reassign styleSheet.cssText.");
  116. }
  117. }
  118. },
  119. currentScript: function(window) {
  120. var document = window.document;
  121. return document.currentScript || (function() {
  122. var scripts = document.getElementsByTagName("script");
  123. return scripts[scripts.length - 1];
  124. })();
  125. }
  126. };
  127. },{"./utils":9}],4:[function(require,module,exports){
  128. // Cache system is a bit outdated and could do with work
  129. module.exports = function(window, options, logger) {
  130. var cache = null;
  131. if (options.env !== 'development') {
  132. try {
  133. cache = (typeof window.localStorage === 'undefined') ? null : window.localStorage;
  134. } catch (_) {}
  135. }
  136. return {
  137. setCSS: function(path, lastModified, styles) {
  138. if (cache) {
  139. logger.info('saving ' + path + ' to cache.');
  140. try {
  141. cache.setItem(path, styles);
  142. cache.setItem(path + ':timestamp', lastModified);
  143. } catch(e) {
  144. //TODO - could do with adding more robust error handling
  145. logger.error('failed to save "' + path + '" to local storage for caching.');
  146. }
  147. }
  148. },
  149. getCSS: function(path, webInfo) {
  150. var css = cache && cache.getItem(path),
  151. timestamp = cache && cache.getItem(path + ':timestamp');
  152. if (timestamp && webInfo.lastModified &&
  153. (new Date(webInfo.lastModified).valueOf() ===
  154. new Date(timestamp).valueOf())) {
  155. // Use local copy
  156. return css;
  157. }
  158. }
  159. };
  160. };
  161. },{}],5:[function(require,module,exports){
  162. var utils = require("./utils"),
  163. browser = require("./browser");
  164. module.exports = function(window, less, options) {
  165. function errorHTML(e, rootHref) {
  166. var id = 'less-error-message:' + utils.extractId(rootHref || "");
  167. var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
  168. var elem = window.document.createElement('div'), timer, content, errors = [];
  169. var filename = e.filename || rootHref;
  170. var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1];
  171. elem.id = id;
  172. elem.className = "less-error-message";
  173. content = '<h3>' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
  174. '</h3>' + '<p>in <a href="' + filename + '">' + filenameNoPath + "</a> ";
  175. var errorline = function (e, i, classname) {
  176. if (e.extract[i] !== undefined) {
  177. errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
  178. .replace(/\{class\}/, classname)
  179. .replace(/\{content\}/, e.extract[i]));
  180. }
  181. };
  182. if (e.extract) {
  183. errorline(e, 0, '');
  184. errorline(e, 1, 'line');
  185. errorline(e, 2, '');
  186. content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':</p>' +
  187. '<ul>' + errors.join('') + '</ul>';
  188. }
  189. if (e.stack && (e.extract || options.logLevel >= 4)) {
  190. content += '<br/>Stack Trace</br />' + e.stack.split('\n').slice(1).join('<br/>');
  191. }
  192. elem.innerHTML = content;
  193. // CSS for error messages
  194. browser.createCSS(window.document, [
  195. '.less-error-message ul, .less-error-message li {',
  196. 'list-style-type: none;',
  197. 'margin-right: 15px;',
  198. 'padding: 4px 0;',
  199. 'margin: 0;',
  200. '}',
  201. '.less-error-message label {',
  202. 'font-size: 12px;',
  203. 'margin-right: 15px;',
  204. 'padding: 4px 0;',
  205. 'color: #cc7777;',
  206. '}',
  207. '.less-error-message pre {',
  208. 'color: #dd6666;',
  209. 'padding: 4px 0;',
  210. 'margin: 0;',
  211. 'display: inline-block;',
  212. '}',
  213. '.less-error-message pre.line {',
  214. 'color: #ff0000;',
  215. '}',
  216. '.less-error-message h3 {',
  217. 'font-size: 20px;',
  218. 'font-weight: bold;',
  219. 'padding: 15px 0 5px 0;',
  220. 'margin: 0;',
  221. '}',
  222. '.less-error-message a {',
  223. 'color: #10a',
  224. '}',
  225. '.less-error-message .error {',
  226. 'color: red;',
  227. 'font-weight: bold;',
  228. 'padding-bottom: 2px;',
  229. 'border-bottom: 1px dashed red;',
  230. '}'
  231. ].join('\n'), { title: 'error-message' });
  232. elem.style.cssText = [
  233. "font-family: Arial, sans-serif",
  234. "border: 1px solid #e00",
  235. "background-color: #eee",
  236. "border-radius: 5px",
  237. "-webkit-border-radius: 5px",
  238. "-moz-border-radius: 5px",
  239. "color: #e00",
  240. "padding: 15px",
  241. "margin-bottom: 15px"
  242. ].join(';');
  243. if (options.env === 'development') {
  244. timer = setInterval(function () {
  245. var document = window.document,
  246. body = document.body;
  247. if (body) {
  248. if (document.getElementById(id)) {
  249. body.replaceChild(elem, document.getElementById(id));
  250. } else {
  251. body.insertBefore(elem, body.firstChild);
  252. }
  253. clearInterval(timer);
  254. }
  255. }, 10);
  256. }
  257. }
  258. function error(e, rootHref) {
  259. if (!options.errorReporting || options.errorReporting === "html") {
  260. errorHTML(e, rootHref);
  261. } else if (options.errorReporting === "console") {
  262. errorConsole(e, rootHref);
  263. } else if (typeof options.errorReporting === 'function') {
  264. options.errorReporting("add", e, rootHref);
  265. }
  266. }
  267. function removeErrorHTML(path) {
  268. var node = window.document.getElementById('less-error-message:' + utils.extractId(path));
  269. if (node) {
  270. node.parentNode.removeChild(node);
  271. }
  272. }
  273. function removeErrorConsole(path) {
  274. //no action
  275. }
  276. function removeError(path) {
  277. if (!options.errorReporting || options.errorReporting === "html") {
  278. removeErrorHTML(path);
  279. } else if (options.errorReporting === "console") {
  280. removeErrorConsole(path);
  281. } else if (typeof options.errorReporting === 'function') {
  282. options.errorReporting("remove", path);
  283. }
  284. }
  285. function errorConsole(e, rootHref) {
  286. var template = '{line} {content}';
  287. var filename = e.filename || rootHref;
  288. var errors = [];
  289. var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
  290. " in " + filename + " ";
  291. var errorline = function (e, i, classname) {
  292. if (e.extract[i] !== undefined) {
  293. errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
  294. .replace(/\{class\}/, classname)
  295. .replace(/\{content\}/, e.extract[i]));
  296. }
  297. };
  298. if (e.extract) {
  299. errorline(e, 0, '');
  300. errorline(e, 1, 'line');
  301. errorline(e, 2, '');
  302. content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
  303. errors.join('\n');
  304. }
  305. if (e.stack && (e.extract || options.logLevel >= 4)) {
  306. content += '\nStack Trace\n' + e.stack;
  307. }
  308. less.logger.error(content);
  309. }
  310. return {
  311. add: error,
  312. remove: removeError
  313. };
  314. };
  315. },{"./browser":3,"./utils":9}],6:[function(require,module,exports){
  316. /*global window, XMLHttpRequest */
  317. module.exports = function(options, logger) {
  318. var AbstractFileManager = require("../less/environment/abstract-file-manager.js");
  319. var fileCache = {};
  320. //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
  321. function getXMLHttpRequest() {
  322. if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
  323. return new XMLHttpRequest();
  324. } else {
  325. try {
  326. /*global ActiveXObject */
  327. return new ActiveXObject("Microsoft.XMLHTTP");
  328. } catch (e) {
  329. logger.error("browser doesn't support AJAX.");
  330. return null;
  331. }
  332. }
  333. }
  334. var FileManager = function() {
  335. };
  336. FileManager.prototype = new AbstractFileManager();
  337. FileManager.prototype.alwaysMakePathsAbsolute = function alwaysMakePathsAbsolute() {
  338. return true;
  339. };
  340. FileManager.prototype.join = function join(basePath, laterPath) {
  341. if (!basePath) {
  342. return laterPath;
  343. }
  344. return this.extractUrlParts(laterPath, basePath).path;
  345. };
  346. FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) {
  347. var xhr = getXMLHttpRequest();
  348. var async = options.isFileProtocol ? options.fileAsync : options.async;
  349. if (typeof xhr.overrideMimeType === 'function') {
  350. xhr.overrideMimeType('text/css');
  351. }
  352. logger.debug("XHR: Getting '" + url + "'");
  353. xhr.open('GET', url, async);
  354. xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
  355. xhr.send(null);
  356. function handleResponse(xhr, callback, errback) {
  357. if (xhr.status >= 200 && xhr.status < 300) {
  358. callback(xhr.responseText,
  359. xhr.getResponseHeader("Last-Modified"));
  360. } else if (typeof errback === 'function') {
  361. errback(xhr.status, url);
  362. }
  363. }
  364. if (options.isFileProtocol && !options.fileAsync) {
  365. if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
  366. callback(xhr.responseText);
  367. } else {
  368. errback(xhr.status, url);
  369. }
  370. } else if (async) {
  371. xhr.onreadystatechange = function () {
  372. if (xhr.readyState == 4) {
  373. handleResponse(xhr, callback, errback);
  374. }
  375. };
  376. } else {
  377. handleResponse(xhr, callback, errback);
  378. }
  379. };
  380. FileManager.prototype.supports = function(filename, currentDirectory, options, environment) {
  381. return true;
  382. };
  383. FileManager.prototype.clearFileCache = function() {
  384. fileCache = {};
  385. };
  386. FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) {
  387. if (currentDirectory && !this.isPathAbsolute(filename)) {
  388. filename = currentDirectory + filename;
  389. }
  390. options = options || {};
  391. // sheet may be set to the stylesheet for the initial load or a collection of properties including
  392. // some context variables for imports
  393. var hrefParts = this.extractUrlParts(filename, window.location.href);
  394. var href = hrefParts.url;
  395. if (options.useFileCache && fileCache[href]) {
  396. try {
  397. var lessText = fileCache[href];
  398. callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
  399. } catch (e) {
  400. callback({filename: href, message: "Error loading file " + href + " error was " + e.message});
  401. }
  402. return;
  403. }
  404. this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
  405. // per file cache
  406. fileCache[href] = data;
  407. // Use remote copy (re-parse)
  408. callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }});
  409. }, function doXHRError(status, url) {
  410. callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
  411. });
  412. };
  413. return FileManager;
  414. };
  415. },{"../less/environment/abstract-file-manager.js":14}],7:[function(require,module,exports){
  416. //
  417. // index.js
  418. // Should expose the additional browser functions on to the less object
  419. //
  420. var addDataAttr = require("./utils").addDataAttr,
  421. browser = require("./browser");
  422. module.exports = function(window, options) {
  423. var document = window.document;
  424. var less = require('../less')();
  425. //module.exports = less;
  426. less.options = options;
  427. var environment = less.environment,
  428. FileManager = require("./file-manager")(options, less.logger),
  429. fileManager = new FileManager();
  430. environment.addFileManager(fileManager);
  431. less.FileManager = FileManager;
  432. require("./log-listener")(less, options);
  433. var errors = require("./error-reporting")(window, less, options);
  434. var cache = less.cache = options.cache || require("./cache")(window, options, less.logger);
  435. //Setup user functions
  436. if (options.functions) {
  437. less.functions.functionRegistry.addMultiple(options.functions);
  438. }
  439. var typePattern = /^text\/(x-)?less$/;
  440. function postProcessCSS(styles) {
  441. if (options.postProcessor && typeof options.postProcessor === 'function') {
  442. styles = options.postProcessor.call(styles, styles) || styles;
  443. }
  444. return styles;
  445. }
  446. function clone(obj) {
  447. var cloned = {};
  448. for (var prop in obj) {
  449. if (obj.hasOwnProperty(prop)) {
  450. cloned[prop] = obj[prop];
  451. }
  452. }
  453. return cloned;
  454. }
  455. // only really needed for phantom
  456. function bind(func, thisArg) {
  457. var curryArgs = Array.prototype.slice.call(arguments, 2);
  458. return function() {
  459. var args = curryArgs.concat(Array.prototype.slice.call(arguments, 0));
  460. return func.apply(thisArg, args);
  461. };
  462. }
  463. function loadStyles(modifyVars) {
  464. var styles = document.getElementsByTagName('style'),
  465. style;
  466. for (var i = 0; i < styles.length; i++) {
  467. style = styles[i];
  468. if (style.type.match(typePattern)) {
  469. var instanceOptions = clone(options);
  470. instanceOptions.modifyVars = modifyVars;
  471. var lessText = style.innerHTML || '';
  472. instanceOptions.filename = document.location.href.replace(/#.*$/, '');
  473. /*jshint loopfunc:true */
  474. // use closure to store current style
  475. less.render(lessText, instanceOptions,
  476. bind(function(style, e, result) {
  477. if (e) {
  478. errors.add(e, "inline");
  479. } else {
  480. style.type = 'text/css';
  481. if (style.styleSheet) {
  482. style.styleSheet.cssText = result.css;
  483. } else {
  484. style.innerHTML = result.css;
  485. }
  486. }
  487. }, null, style));
  488. }
  489. }
  490. }
  491. function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
  492. var instanceOptions = clone(options);
  493. addDataAttr(instanceOptions, sheet);
  494. instanceOptions.mime = sheet.type;
  495. if (modifyVars) {
  496. instanceOptions.modifyVars = modifyVars;
  497. }
  498. function loadInitialFileCallback(loadedFile) {
  499. var data = loadedFile.contents,
  500. path = loadedFile.filename,
  501. webInfo = loadedFile.webInfo;
  502. var newFileInfo = {
  503. currentDirectory: fileManager.getPath(path),
  504. filename: path,
  505. rootFilename: path,
  506. relativeUrls: instanceOptions.relativeUrls};
  507. newFileInfo.entryPath = newFileInfo.currentDirectory;
  508. newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
  509. if (webInfo) {
  510. webInfo.remaining = remaining;
  511. if (!instanceOptions.modifyVars) {
  512. var css = cache.getCSS(path, webInfo);
  513. if (!reload && css) {
  514. webInfo.local = true;
  515. callback(null, css, data, sheet, webInfo, path);
  516. return;
  517. }
  518. }
  519. }
  520. //TODO add tests around how this behaves when reloading
  521. errors.remove(path);
  522. instanceOptions.rootFileInfo = newFileInfo;
  523. less.render(data, instanceOptions, function(e, result) {
  524. if (e) {
  525. e.href = path;
  526. callback(e);
  527. } else {
  528. result.css = postProcessCSS(result.css);
  529. if (!instanceOptions.modifyVars) {
  530. cache.setCSS(sheet.href, webInfo.lastModified, result.css);
  531. }
  532. callback(null, result.css, data, sheet, webInfo, path);
  533. }
  534. });
  535. }
  536. fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) {
  537. if (e) {
  538. callback(e);
  539. return;
  540. }
  541. loadInitialFileCallback(loadedFile);
  542. });
  543. }
  544. function loadStyleSheets(callback, reload, modifyVars) {
  545. for (var i = 0; i < less.sheets.length; i++) {
  546. loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
  547. }
  548. }
  549. function initRunningMode() {
  550. if (less.env === 'development') {
  551. less.watchTimer = setInterval(function () {
  552. if (less.watchMode) {
  553. fileManager.clearFileCache();
  554. loadStyleSheets(function (e, css, _, sheet, webInfo) {
  555. if (e) {
  556. errors.add(e, e.href || sheet.href);
  557. } else if (css) {
  558. browser.createCSS(window.document, css, sheet);
  559. }
  560. });
  561. }
  562. }, options.poll);
  563. }
  564. }
  565. //
  566. // Watch mode
  567. //
  568. less.watch = function () {
  569. if (!less.watchMode ) {
  570. less.env = 'development';
  571. initRunningMode();
  572. }
  573. this.watchMode = true;
  574. return true;
  575. };
  576. less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };
  577. //
  578. // Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
  579. //
  580. less.registerStylesheets = function() {
  581. return new Promise(function(resolve, reject) {
  582. var links = document.getElementsByTagName('link');
  583. less.sheets = [];
  584. for (var i = 0; i < links.length; i++) {
  585. if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
  586. (links[i].type.match(typePattern)))) {
  587. less.sheets.push(links[i]);
  588. }
  589. }
  590. resolve();
  591. });
  592. };
  593. //
  594. // With this function, it's possible to alter variables and re-render
  595. // CSS without reloading less-files
  596. //
  597. less.modifyVars = function(record) {
  598. return less.refresh(true, record, false);
  599. };
  600. less.refresh = function (reload, modifyVars, clearFileCache) {
  601. if ((reload || clearFileCache) && clearFileCache !== false) {
  602. fileManager.clearFileCache();
  603. }
  604. return new Promise(function (resolve, reject) {
  605. var startTime, endTime, totalMilliseconds;
  606. startTime = endTime = new Date();
  607. loadStyleSheets(function (e, css, _, sheet, webInfo) {
  608. if (e) {
  609. errors.add(e, e.href || sheet.href);
  610. reject(e);
  611. return;
  612. }
  613. if (webInfo.local) {
  614. less.logger.info("loading " + sheet.href + " from cache.");
  615. } else {
  616. less.logger.info("rendered " + sheet.href + " successfully.");
  617. }
  618. browser.createCSS(window.document, css, sheet);
  619. less.logger.info("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
  620. if (webInfo.remaining === 0) {
  621. totalMilliseconds = new Date() - startTime;
  622. less.logger.info("less has finished. css generated in " + totalMilliseconds + 'ms');
  623. resolve({
  624. startTime: startTime,
  625. endTime: endTime,
  626. totalMilliseconds: totalMilliseconds,
  627. sheets: less.sheets.length
  628. });
  629. }
  630. endTime = new Date();
  631. }, reload, modifyVars);
  632. loadStyles(modifyVars);
  633. });
  634. };
  635. less.refreshStyles = loadStyles;
  636. return less;
  637. };
  638. },{"../less":29,"./browser":3,"./cache":4,"./error-reporting":5,"./file-manager":6,"./log-listener":8,"./utils":9}],8:[function(require,module,exports){
  639. module.exports = function(less, options) {
  640. var logLevel_debug = 4,
  641. logLevel_info = 3,
  642. logLevel_warn = 2,
  643. logLevel_error = 1;
  644. // The amount of logging in the javascript console.
  645. // 3 - Debug, information and errors
  646. // 2 - Information and errors
  647. // 1 - Errors
  648. // 0 - None
  649. // Defaults to 2
  650. options.logLevel = typeof options.logLevel !== 'undefined' ? options.logLevel : (options.env === 'development' ? logLevel_info : logLevel_error);
  651. if (!options.loggers) {
  652. options.loggers = [{
  653. debug: function(msg) {
  654. if (options.logLevel >= logLevel_debug) {
  655. console.log(msg);
  656. }
  657. },
  658. info: function(msg) {
  659. if (options.logLevel >= logLevel_info) {
  660. console.log(msg);
  661. }
  662. },
  663. warn: function(msg) {
  664. if (options.logLevel >= logLevel_warn) {
  665. console.warn(msg);
  666. }
  667. },
  668. error: function(msg) {
  669. if (options.logLevel >= logLevel_error) {
  670. console.error(msg);
  671. }
  672. }
  673. }];
  674. }
  675. for (var i = 0; i < options.loggers.length; i++) {
  676. less.logger.addListener(options.loggers[i]);
  677. }
  678. };
  679. },{}],9:[function(require,module,exports){
  680. module.exports = {
  681. extractId: function(href) {
  682. return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain
  683. .replace(/[\?\&]livereload=\w+/, '') // Remove LiveReload cachebuster
  684. .replace(/^\//, '') // Remove root /
  685. .replace(/\.[a-zA-Z]+$/, '') // Remove simple extension
  686. .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
  687. .replace(/\./g, ':'); // Replace dots with colons(for valid id)
  688. },
  689. addDataAttr: function(options, tag) {
  690. for (var opt in tag.dataset) {
  691. if (tag.dataset.hasOwnProperty(opt)) {
  692. if (opt === "env" || opt === "dumpLineNumbers" || opt === "rootpath" || opt === "errorReporting") {
  693. options[opt] = tag.dataset[opt];
  694. } else {
  695. try {
  696. options[opt] = JSON.parse(tag.dataset[opt]);
  697. }
  698. catch(_) {}
  699. }
  700. }
  701. }
  702. }
  703. };
  704. },{}],10:[function(require,module,exports){
  705. var contexts = {};
  706. module.exports = contexts;
  707. var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
  708. if (!original) { return; }
  709. for (var i = 0; i < propertiesToCopy.length; i++) {
  710. if (original.hasOwnProperty(propertiesToCopy[i])) {
  711. destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
  712. }
  713. }
  714. };
  715. /*
  716. parse is used whilst parsing
  717. */
  718. var parseCopyProperties = [
  719. // options
  720. 'paths', // option - unmodified - paths to search for imports on
  721. 'relativeUrls', // option - whether to adjust URL's to be relative
  722. 'rootpath', // option - rootpath to append to URL's
  723. 'strictImports', // option -
  724. 'insecure', // option - whether to allow imports from insecure ssl hosts
  725. 'dumpLineNumbers', // option - whether to dump line numbers
  726. 'compress', // option - whether to compress
  727. 'syncImport', // option - whether to import synchronously
  728. 'chunkInput', // option - whether to chunk input. more performant but causes parse issues.
  729. 'mime', // browser only - mime type for sheet import
  730. 'useFileCache', // browser only - whether to use the per file session cache
  731. // context
  732. 'processImports', // option & context - whether to process imports. if false then imports will not be imported.
  733. // Used by the import manager to stop multiple import visitors being created.
  734. 'reference', // Used to indicate that the contents are imported by reference
  735. 'pluginManager' // Used as the plugin manager for the session
  736. ];
  737. contexts.Parse = function(options) {
  738. copyFromOriginal(options, this, parseCopyProperties);
  739. if (typeof this.paths === "string") { this.paths = [this.paths]; }
  740. };
  741. var evalCopyProperties = [
  742. 'paths', // additional include paths
  743. 'compress', // whether to compress
  744. 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
  745. 'strictMath', // whether math has to be within parenthesis
  746. 'strictUnits', // whether units need to evaluate correctly
  747. 'sourceMap', // whether to output a source map
  748. 'importMultiple', // whether we are currently importing multiple copies
  749. 'urlArgs', // whether to add args into url tokens
  750. 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
  751. 'pluginManager', // Used as the plugin manager for the session
  752. 'importantScope' // used to bubble up !important statements
  753. ];
  754. contexts.Eval = function(options, frames) {
  755. copyFromOriginal(options, this, evalCopyProperties);
  756. this.frames = frames || [];
  757. this.importantScope = this.importantScope || [];
  758. };
  759. contexts.Eval.prototype.inParenthesis = function () {
  760. if (!this.parensStack) {
  761. this.parensStack = [];
  762. }
  763. this.parensStack.push(true);
  764. };
  765. contexts.Eval.prototype.outOfParenthesis = function () {
  766. this.parensStack.pop();
  767. };
  768. contexts.Eval.prototype.isMathOn = function () {
  769. return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
  770. };
  771. contexts.Eval.prototype.isPathRelative = function (path) {
  772. return !/^(?:[a-z-]+:|\/|#)/i.test(path);
  773. };
  774. contexts.Eval.prototype.normalizePath = function( path ) {
  775. var
  776. segments = path.split("/").reverse(),
  777. segment;
  778. path = [];
  779. while (segments.length !== 0 ) {
  780. segment = segments.pop();
  781. switch( segment ) {
  782. case ".":
  783. break;
  784. case "..":
  785. if ((path.length === 0) || (path[path.length - 1] === "..")) {
  786. path.push( segment );
  787. } else {
  788. path.pop();
  789. }
  790. break;
  791. default:
  792. path.push( segment );
  793. break;
  794. }
  795. }
  796. return path.join("/");
  797. };
  798. //todo - do the same for the toCSS ?
  799. },{}],11:[function(require,module,exports){
  800. module.exports = {
  801. 'aliceblue':'#f0f8ff',
  802. 'antiquewhite':'#faebd7',
  803. 'aqua':'#00ffff',
  804. 'aquamarine':'#7fffd4',
  805. 'azure':'#f0ffff',
  806. 'beige':'#f5f5dc',
  807. 'bisque':'#ffe4c4',
  808. 'black':'#000000',
  809. 'blanchedalmond':'#ffebcd',
  810. 'blue':'#0000ff',
  811. 'blueviolet':'#8a2be2',
  812. 'brown':'#a52a2a',
  813. 'burlywood':'#deb887',
  814. 'cadetblue':'#5f9ea0',
  815. 'chartreuse':'#7fff00',
  816. 'chocolate':'#d2691e',
  817. 'coral':'#ff7f50',
  818. 'cornflowerblue':'#6495ed',
  819. 'cornsilk':'#fff8dc',
  820. 'crimson':'#dc143c',
  821. 'cyan':'#00ffff',
  822. 'darkblue':'#00008b',
  823. 'darkcyan':'#008b8b',
  824. 'darkgoldenrod':'#b8860b',
  825. 'darkgray':'#a9a9a9',
  826. 'darkgrey':'#a9a9a9',
  827. 'darkgreen':'#006400',
  828. 'darkkhaki':'#bdb76b',
  829. 'darkmagenta':'#8b008b',
  830. 'darkolivegreen':'#556b2f',
  831. 'darkorange':'#ff8c00',
  832. 'darkorchid':'#9932cc',
  833. 'darkred':'#8b0000',
  834. 'darksalmon':'#e9967a',
  835. 'darkseagreen':'#8fbc8f',
  836. 'darkslateblue':'#483d8b',
  837. 'darkslategray':'#2f4f4f',
  838. 'darkslategrey':'#2f4f4f',
  839. 'darkturquoise':'#00ced1',
  840. 'darkviolet':'#9400d3',
  841. 'deeppink':'#ff1493',
  842. 'deepskyblue':'#00bfff',
  843. 'dimgray':'#696969',
  844. 'dimgrey':'#696969',
  845. 'dodgerblue':'#1e90ff',
  846. 'firebrick':'#b22222',
  847. 'floralwhite':'#fffaf0',
  848. 'forestgreen':'#228b22',
  849. 'fuchsia':'#ff00ff',
  850. 'gainsboro':'#dcdcdc',
  851. 'ghostwhite':'#f8f8ff',
  852. 'gold':'#ffd700',
  853. 'goldenrod':'#daa520',
  854. 'gray':'#808080',
  855. 'grey':'#808080',
  856. 'green':'#008000',
  857. 'greenyellow':'#adff2f',
  858. 'honeydew':'#f0fff0',
  859. 'hotpink':'#ff69b4',
  860. 'indianred':'#cd5c5c',
  861. 'indigo':'#4b0082',
  862. 'ivory':'#fffff0',
  863. 'khaki':'#f0e68c',
  864. 'lavender':'#e6e6fa',
  865. 'lavenderblush':'#fff0f5',
  866. 'lawngreen':'#7cfc00',
  867. 'lemonchiffon':'#fffacd',
  868. 'lightblue':'#add8e6',
  869. 'lightcoral':'#f08080',
  870. 'lightcyan':'#e0ffff',
  871. 'lightgoldenrodyellow':'#fafad2',
  872. 'lightgray':'#d3d3d3',
  873. 'lightgrey':'#d3d3d3',
  874. 'lightgreen':'#90ee90',
  875. 'lightpink':'#ffb6c1',
  876. 'lightsalmon':'#ffa07a',
  877. 'lightseagreen':'#20b2aa',
  878. 'lightskyblue':'#87cefa',
  879. 'lightslategray':'#778899',
  880. 'lightslategrey':'#778899',
  881. 'lightsteelblue':'#b0c4de',
  882. 'lightyellow':'#ffffe0',
  883. 'lime':'#00ff00',
  884. 'limegreen':'#32cd32',
  885. 'linen':'#faf0e6',
  886. 'magenta':'#ff00ff',
  887. 'maroon':'#800000',
  888. 'mediumaquamarine':'#66cdaa',
  889. 'mediumblue':'#0000cd',
  890. 'mediumorchid':'#ba55d3',
  891. 'mediumpurple':'#9370d8',
  892. 'mediumseagreen':'#3cb371',
  893. 'mediumslateblue':'#7b68ee',
  894. 'mediumspringgreen':'#00fa9a',
  895. 'mediumturquoise':'#48d1cc',
  896. 'mediumvioletred':'#c71585',
  897. 'midnightblue':'#191970',
  898. 'mintcream':'#f5fffa',
  899. 'mistyrose':'#ffe4e1',
  900. 'moccasin':'#ffe4b5',
  901. 'navajowhite':'#ffdead',
  902. 'navy':'#000080',
  903. 'oldlace':'#fdf5e6',
  904. 'olive':'#808000',
  905. 'olivedrab':'#6b8e23',
  906. 'orange':'#ffa500',
  907. 'orangered':'#ff4500',
  908. 'orchid':'#da70d6',
  909. 'palegoldenrod':'#eee8aa',
  910. 'palegreen':'#98fb98',
  911. 'paleturquoise':'#afeeee',
  912. 'palevioletred':'#d87093',
  913. 'papayawhip':'#ffefd5',
  914. 'peachpuff':'#ffdab9',
  915. 'peru':'#cd853f',
  916. 'pink':'#ffc0cb',
  917. 'plum':'#dda0dd',
  918. 'powderblue':'#b0e0e6',
  919. 'purple':'#800080',
  920. 'rebeccapurple':'#663399',
  921. 'red':'#ff0000',
  922. 'rosybrown':'#bc8f8f',
  923. 'royalblue':'#4169e1',
  924. 'saddlebrown':'#8b4513',
  925. 'salmon':'#fa8072',
  926. 'sandybrown':'#f4a460',
  927. 'seagreen':'#2e8b57',
  928. 'seashell':'#fff5ee',
  929. 'sienna':'#a0522d',
  930. 'silver':'#c0c0c0',
  931. 'skyblue':'#87ceeb',
  932. 'slateblue':'#6a5acd',
  933. 'slategray':'#708090',
  934. 'slategrey':'#708090',
  935. 'snow':'#fffafa',
  936. 'springgreen':'#00ff7f',
  937. 'steelblue':'#4682b4',
  938. 'tan':'#d2b48c',
  939. 'teal':'#008080',
  940. 'thistle':'#d8bfd8',
  941. 'tomato':'#ff6347',
  942. 'turquoise':'#40e0d0',
  943. 'violet':'#ee82ee',
  944. 'wheat':'#f5deb3',
  945. 'white':'#ffffff',
  946. 'whitesmoke':'#f5f5f5',
  947. 'yellow':'#ffff00',
  948. 'yellowgreen':'#9acd32'
  949. };
  950. },{}],12:[function(require,module,exports){
  951. module.exports = {
  952. colors: require("./colors"),
  953. unitConversions: require("./unit-conversions")
  954. };
  955. },{"./colors":11,"./unit-conversions":13}],13:[function(require,module,exports){
  956. module.exports = {
  957. length: {
  958. 'm': 1,
  959. 'cm': 0.01,
  960. 'mm': 0.001,
  961. 'in': 0.0254,
  962. 'px': 0.0254 / 96,
  963. 'pt': 0.0254 / 72,
  964. 'pc': 0.0254 / 72 * 12
  965. },
  966. duration: {
  967. 's': 1,
  968. 'ms': 0.001
  969. },
  970. angle: {
  971. 'rad': 1 / (2 * Math.PI),
  972. 'deg': 1 / 360,
  973. 'grad': 1 / 400,
  974. 'turn': 1
  975. }
  976. };
  977. },{}],14:[function(require,module,exports){
  978. var abstractFileManager = function() {
  979. };
  980. abstractFileManager.prototype.getPath = function (filename) {
  981. var j = filename.lastIndexOf('?');
  982. if (j > 0) {
  983. filename = filename.slice(0, j);
  984. }
  985. j = filename.lastIndexOf('/');
  986. if (j < 0) {
  987. j = filename.lastIndexOf('\\');
  988. }
  989. if (j < 0) {
  990. return "";
  991. }
  992. return filename.slice(0, j + 1);
  993. };
  994. abstractFileManager.prototype.tryAppendLessExtension = function(path) {
  995. return /(\.[a-z]*$)|([\?;].*)$/.test(path) ? path : path + '.less';
  996. };
  997. abstractFileManager.prototype.supportsSync = function() {
  998. return false;
  999. };
  1000. abstractFileManager.prototype.alwaysMakePathsAbsolute = function() {
  1001. return false;
  1002. };
  1003. abstractFileManager.prototype.isPathAbsolute = function(filename) {
  1004. return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename);
  1005. };
  1006. abstractFileManager.prototype.join = function(basePath, laterPath) {
  1007. if (!basePath) {
  1008. return laterPath;
  1009. }
  1010. return basePath + laterPath;
  1011. };
  1012. abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {
  1013. // diff between two paths to create a relative path
  1014. var urlParts = this.extractUrlParts(url),
  1015. baseUrlParts = this.extractUrlParts(baseUrl),
  1016. i, max, urlDirectories, baseUrlDirectories, diff = "";
  1017. if (urlParts.hostPart !== baseUrlParts.hostPart) {
  1018. return "";
  1019. }
  1020. max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
  1021. for (i = 0; i < max; i++) {
  1022. if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; }
  1023. }
  1024. baseUrlDirectories = baseUrlParts.directories.slice(i);
  1025. urlDirectories = urlParts.directories.slice(i);
  1026. for (i = 0; i < baseUrlDirectories.length - 1; i++) {
  1027. diff += "../";
  1028. }
  1029. for (i = 0; i < urlDirectories.length - 1; i++) {
  1030. diff += urlDirectories[i] + "/";
  1031. }
  1032. return diff;
  1033. };
  1034. // helper function, not part of API
  1035. abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, baseUrl) {
  1036. // urlParts[1] = protocol&hostname || /
  1037. // urlParts[2] = / if path relative to host base
  1038. // urlParts[3] = directories
  1039. // urlParts[4] = filename
  1040. // urlParts[5] = parameters
  1041. var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
  1042. urlParts = url.match(urlPartsRegex),
  1043. returner = {}, directories = [], i, baseUrlParts;
  1044. if (!urlParts) {
  1045. throw new Error("Could not parse sheet href - '" + url + "'");
  1046. }
  1047. // Stylesheets in IE don't always return the full path
  1048. if (baseUrl && (!urlParts[1] || urlParts[2])) {
  1049. baseUrlParts = baseUrl.match(urlPartsRegex);
  1050. if (!baseUrlParts) {
  1051. throw new Error("Could not parse page url - '" + baseUrl + "'");
  1052. }
  1053. urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
  1054. if (!urlParts[2]) {
  1055. urlParts[3] = baseUrlParts[3] + urlParts[3];
  1056. }
  1057. }
  1058. if (urlParts[3]) {
  1059. directories = urlParts[3].replace(/\\/g, "/").split("/");
  1060. // extract out . before .. so .. doesn't absorb a non-directory
  1061. for (i = 0; i < directories.length; i++) {
  1062. if (directories[i] === ".") {
  1063. directories.splice(i, 1);
  1064. i -= 1;
  1065. }
  1066. }
  1067. for (i = 0; i < directories.length; i++) {
  1068. if (directories[i] === ".." && i > 0) {
  1069. directories.splice(i - 1, 2);
  1070. i -= 2;
  1071. }
  1072. }
  1073. }
  1074. returner.hostPart = urlParts[1];
  1075. returner.directories = directories;
  1076. returner.path = (urlParts[1] || "") + directories.join("/");
  1077. returner.fileUrl = returner.path + (urlParts[4] || "");
  1078. returner.url = returner.fileUrl + (urlParts[5] || "");
  1079. return returner;
  1080. };
  1081. module.exports = abstractFileManager;
  1082. },{}],15:[function(require,module,exports){
  1083. var logger = require("../logger");
  1084. var environment = function(externalEnvironment, fileManagers) {
  1085. this.fileManagers = fileManagers || [];
  1086. externalEnvironment = externalEnvironment || {};
  1087. var optionalFunctions = ["encodeBase64", "mimeLookup", "charsetLookup", "getSourceMapGenerator"],
  1088. requiredFunctions = [],
  1089. functions = requiredFunctions.concat(optionalFunctions);
  1090. for (var i = 0; i < functions.length; i++) {
  1091. var propName = functions[i],
  1092. environmentFunc = externalEnvironment[propName];
  1093. if (environmentFunc) {
  1094. this[propName] = environmentFunc.bind(externalEnvironment);
  1095. } else if (i < requiredFunctions.length) {
  1096. this.warn("missing required function in environment - " + propName);
  1097. }
  1098. }
  1099. };
  1100. environment.prototype.getFileManager = function (filename, currentDirectory, options, environment, isSync) {
  1101. if (!filename) {
  1102. logger.warn("getFileManager called with no filename.. Please report this issue. continuing.");
  1103. }
  1104. if (currentDirectory == null) {
  1105. logger.warn("getFileManager called with null directory.. Please report this issue. continuing.");
  1106. }
  1107. var fileManagers = this.fileManagers;
  1108. if (options.pluginManager) {
  1109. fileManagers = [].concat(fileManagers).concat(options.pluginManager.getFileManagers());
  1110. }
  1111. for (var i = fileManagers.length - 1; i >= 0 ; i--) {
  1112. var fileManager = fileManagers[i];
  1113. if (fileManager[isSync ? "supportsSync" : "supports"](filename, currentDirectory, options, environment)) {
  1114. return fileManager;
  1115. }
  1116. }
  1117. return null;
  1118. };
  1119. environment.prototype.addFileManager = function (fileManager) {
  1120. this.fileManagers.push(fileManager);
  1121. };
  1122. environment.prototype.clearFileManagers = function () {
  1123. this.fileManagers = [];
  1124. };
  1125. module.exports = environment;
  1126. },{"../logger":31}],16:[function(require,module,exports){
  1127. var Color = require("../tree/color"),
  1128. functionRegistry = require("./function-registry");
  1129. // Color Blending
  1130. // ref: http://www.w3.org/TR/compositing-1
  1131. function colorBlend(mode, color1, color2) {
  1132. var ab = color1.alpha, cb, // backdrop
  1133. as = color2.alpha, cs, // source
  1134. ar, cr, r = []; // result
  1135. ar = as + ab * (1 - as);
  1136. for (var i = 0; i < 3; i++) {
  1137. cb = color1.rgb[i] / 255;
  1138. cs = color2.rgb[i] / 255;
  1139. cr = mode(cb, cs);
  1140. if (ar) {
  1141. cr = (as * cs + ab * (cb -
  1142. as * (cb + cs - cr))) / ar;
  1143. }
  1144. r[i] = cr * 255;
  1145. }
  1146. return new Color(r, ar);
  1147. }
  1148. var colorBlendModeFunctions = {
  1149. multiply: function(cb, cs) {
  1150. return cb * cs;
  1151. },
  1152. screen: function(cb, cs) {
  1153. return cb + cs - cb * cs;
  1154. },
  1155. overlay: function(cb, cs) {
  1156. cb *= 2;
  1157. return (cb <= 1) ?
  1158. colorBlendModeFunctions.multiply(cb, cs) :
  1159. colorBlendModeFunctions.screen(cb - 1, cs);
  1160. },
  1161. softlight: function(cb, cs) {
  1162. var d = 1, e = cb;
  1163. if (cs > 0.5) {
  1164. e = 1;
  1165. d = (cb > 0.25) ? Math.sqrt(cb)
  1166. : ((16 * cb - 12) * cb + 4) * cb;
  1167. }
  1168. return cb - (1 - 2 * cs) * e * (d - cb);
  1169. },
  1170. hardlight: function(cb, cs) {
  1171. return colorBlendModeFunctions.overlay(cs, cb);
  1172. },
  1173. difference: function(cb, cs) {
  1174. return Math.abs(cb - cs);
  1175. },
  1176. exclusion: function(cb, cs) {
  1177. return cb + cs - 2 * cb * cs;
  1178. },
  1179. // non-w3c functions:
  1180. average: function(cb, cs) {
  1181. return (cb + cs) / 2;
  1182. },
  1183. negation: function(cb, cs) {
  1184. return 1 - Math.abs(cb + cs - 1);
  1185. }
  1186. };
  1187. for (var f in colorBlendModeFunctions) {
  1188. if (colorBlendModeFunctions.hasOwnProperty(f)) {
  1189. colorBlend[f] = colorBlend.bind(null, colorBlendModeFunctions[f]);
  1190. }
  1191. }
  1192. functionRegistry.addMultiple(colorBlend);
  1193. },{"../tree/color":47,"./function-registry":21}],17:[function(require,module,exports){
  1194. var Dimension = require("../tree/dimension"),
  1195. Color = require("../tree/color"),
  1196. Quoted = require("../tree/quoted"),
  1197. Anonymous = require("../tree/anonymous"),
  1198. functionRegistry = require("./function-registry"),
  1199. colorFunctions;
  1200. function clamp(val) {
  1201. return Math.min(1, Math.max(0, val));
  1202. }
  1203. function hsla(color) {
  1204. return colorFunctions.hsla(color.h, color.s, color.l, color.a);
  1205. }
  1206. function number(n) {
  1207. if (n instanceof Dimension) {
  1208. return parseFloat(n.unit.is('%') ? n.value / 100 : n.value);
  1209. } else if (typeof n === 'number') {
  1210. return n;
  1211. } else {
  1212. throw {
  1213. type: "Argument",
  1214. message: "color functions take numbers as parameters"
  1215. };
  1216. }
  1217. }
  1218. function scaled(n, size) {
  1219. if (n instanceof Dimension && n.unit.is('%')) {
  1220. return parseFloat(n.value * size / 100);
  1221. } else {
  1222. return number(n);
  1223. }
  1224. }
  1225. colorFunctions = {
  1226. rgb: function (r, g, b) {
  1227. return colorFunctions.rgba(r, g, b, 1.0);
  1228. },
  1229. rgba: function (r, g, b, a) {
  1230. var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
  1231. a = number(a);
  1232. return new Color(rgb, a);
  1233. },
  1234. hsl: function (h, s, l) {
  1235. return colorFunctions.hsla(h, s, l, 1.0);
  1236. },
  1237. hsla: function (h, s, l, a) {
  1238. function hue(h) {
  1239. h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
  1240. if (h * 6 < 1) {
  1241. return m1 + (m2 - m1) * h * 6;
  1242. }
  1243. else if (h * 2 < 1) {
  1244. return m2;
  1245. }
  1246. else if (h * 3 < 2) {
  1247. return m1 + (m2 - m1) * (2 / 3 - h) * 6;
  1248. }
  1249. else {
  1250. return m1;
  1251. }
  1252. }
  1253. h = (number(h) % 360) / 360;
  1254. s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
  1255. var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
  1256. var m1 = l * 2 - m2;
  1257. return colorFunctions.rgba(hue(h + 1 / 3) * 255,
  1258. hue(h) * 255,
  1259. hue(h - 1 / 3) * 255,
  1260. a);
  1261. },
  1262. hsv: function(h, s, v) {
  1263. return colorFunctions.hsva(h, s, v, 1.0);
  1264. },
  1265. hsva: function(h, s, v, a) {
  1266. h = ((number(h) % 360) / 360) * 360;
  1267. s = number(s); v = number(v); a = number(a);
  1268. var i, f;
  1269. i = Math.floor((h / 60) % 6);
  1270. f = (h / 60) - i;
  1271. var vs = [v,
  1272. v * (1 - s),
  1273. v * (1 - f * s),
  1274. v * (1 - (1 - f) * s)];
  1275. var perm = [[0, 3, 1],
  1276. [2, 0, 1],
  1277. [1, 0, 3],
  1278. [1, 2, 0],
  1279. [3, 1, 0],
  1280. [0, 1, 2]];
  1281. return colorFunctions.rgba(vs[perm[i][0]] * 255,
  1282. vs[perm[i][1]] * 255,
  1283. vs[perm[i][2]] * 255,
  1284. a);
  1285. },
  1286. hue: function (color) {
  1287. return new Dimension(color.toHSL().h);
  1288. },
  1289. saturation: function (color) {
  1290. return new Dimension(color.toHSL().s * 100, '%');
  1291. },
  1292. lightness: function (color) {
  1293. return new Dimension(color.toHSL().l * 100, '%');
  1294. },
  1295. hsvhue: function(color) {
  1296. return new Dimension(color.toHSV().h);
  1297. },
  1298. hsvsaturation: function (color) {
  1299. return new Dimension(color.toHSV().s * 100, '%');
  1300. },
  1301. hsvvalue: function (color) {
  1302. return new Dimension(color.toHSV().v * 100, '%');
  1303. },
  1304. red: function (color) {
  1305. return new Dimension(color.rgb[0]);
  1306. },
  1307. green: function (color) {
  1308. return new Dimension(color.rgb[1]);
  1309. },
  1310. blue: function (color) {
  1311. return new Dimension(color.rgb[2]);
  1312. },
  1313. alpha: function (color) {
  1314. return new Dimension(color.toHSL().a);
  1315. },
  1316. luma: function (color) {
  1317. return new Dimension(color.luma() * color.alpha * 100, '%');
  1318. },
  1319. luminance: function (color) {
  1320. var luminance =
  1321. (0.2126 * color.rgb[0] / 255) +
  1322. (0.7152 * color.rgb[1] / 255) +
  1323. (0.0722 * color.rgb[2] / 255);
  1324. return new Dimension(luminance * color.alpha * 100, '%');
  1325. },
  1326. saturate: function (color, amount) {
  1327. // filter: saturate(3.2);
  1328. // should be kept as is, so check for color
  1329. if (!color.rgb) {
  1330. return null;
  1331. }
  1332. var hsl = color.toHSL();
  1333. hsl.s += amount.value / 100;
  1334. hsl.s = clamp(hsl.s);
  1335. return hsla(hsl);
  1336. },
  1337. desaturate: function (color, amount) {
  1338. var hsl = color.toHSL();
  1339. hsl.s -= amount.value / 100;
  1340. hsl.s = clamp(hsl.s);
  1341. return hsla(hsl);
  1342. },
  1343. lighten: function (color, amount) {
  1344. var hsl = color.toHSL();
  1345. hsl.l += amount.value / 100;
  1346. hsl.l = clamp(hsl.l);
  1347. return hsla(hsl);
  1348. },
  1349. darken: function (color, amount) {
  1350. var hsl = color.toHSL();
  1351. hsl.l -= amount.value / 100;
  1352. hsl.l = clamp(hsl.l);
  1353. return hsla(hsl);
  1354. },
  1355. fadein: function (color, amount) {
  1356. var hsl = color.toHSL();
  1357. hsl.a += amount.value / 100;
  1358. hsl.a = clamp(hsl.a);
  1359. return hsla(hsl);
  1360. },
  1361. fadeout: function (color, amount) {
  1362. var hsl = color.toHSL();
  1363. hsl.a -= amount.value / 100;
  1364. hsl.a = clamp(hsl.a);
  1365. return hsla(hsl);
  1366. },
  1367. fade: function (color, amount) {
  1368. var hsl = color.toHSL();
  1369. hsl.a = amount.value / 100;
  1370. hsl.a = clamp(hsl.a);
  1371. return hsla(hsl);
  1372. },
  1373. spin: function (color, amount) {
  1374. var hsl = color.toHSL();
  1375. var hue = (hsl.h + amount.value) % 360;
  1376. hsl.h = hue < 0 ? 360 + hue : hue;
  1377. return hsla(hsl);
  1378. },
  1379. //
  1380. // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
  1381. // http://sass-lang.com
  1382. //
  1383. mix: function (color1, color2, weight) {
  1384. if (!weight) {
  1385. weight = new Dimension(50);
  1386. }
  1387. var p = weight.value / 100.0;
  1388. var w = p * 2 - 1;
  1389. var a = color1.toHSL().a - color2.toHSL().a;
  1390. var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
  1391. var w2 = 1 - w1;
  1392. var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2,
  1393. color1.rgb[1] * w1 + color2.rgb[1] * w2,
  1394. color1.rgb[2] * w1 + color2.rgb[2] * w2];
  1395. var alpha = color1.alpha * p + color2.alpha * (1 - p);
  1396. return new Color(rgb, alpha);
  1397. },
  1398. greyscale: function (color) {
  1399. return colorFunctions.desaturate(color, new Dimension(100));
  1400. },
  1401. contrast: function (color, dark, light, threshold) {
  1402. // filter: contrast(3.2);
  1403. // should be kept as is, so check for color
  1404. if (!color.rgb) {
  1405. return null;
  1406. }
  1407. if (typeof light === 'undefined') {
  1408. light = colorFunctions.rgba(255, 255, 255, 1.0);
  1409. }
  1410. if (typeof dark === 'undefined') {
  1411. dark = colorFunctions.rgba(0, 0, 0, 1.0);
  1412. }
  1413. //Figure out which is actually light and dark!
  1414. if (dark.luma() > light.luma()) {
  1415. var t = light;
  1416. light = dark;
  1417. dark = t;
  1418. }
  1419. if (typeof threshold === 'undefined') {
  1420. threshold = 0.43;
  1421. } else {
  1422. threshold = number(threshold);
  1423. }
  1424. if (color.luma() < threshold) {
  1425. return light;
  1426. } else {
  1427. return dark;
  1428. }
  1429. },
  1430. argb: function (color) {
  1431. return new Anonymous(color.toARGB());
  1432. },
  1433. color: function(c) {
  1434. if ((c instanceof Quoted) &&
  1435. (/^#([a-f0-9]{6}|[a-f0-9]{3})$/i.test(c.value))) {
  1436. return new Color(c.value.slice(1));
  1437. }
  1438. if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
  1439. c.value = undefined;
  1440. return c;
  1441. }
  1442. throw {
  1443. type: "Argument",
  1444. message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF"
  1445. };
  1446. },
  1447. tint: function(color, amount) {
  1448. return colorFunctions.mix(colorFunctions.rgb(255, 255, 255), color, amount);
  1449. },
  1450. shade: function(color, amount) {
  1451. return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
  1452. }
  1453. };
  1454. functionRegistry.addMultiple(colorFunctions);
  1455. },{"../tree/anonymous":43,"../tree/color":47,"../tree/dimension":53,"../tree/quoted":70,"./function-registry":21}],18:[function(require,module,exports){
  1456. module.exports = function(environment) {
  1457. var Quoted = require("../tree/quoted"),
  1458. URL = require("../tree/url"),
  1459. functionRegistry = require("./function-registry"),
  1460. fallback = function(functionThis, node) {
  1461. return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context);
  1462. },
  1463. logger = require('../logger');
  1464. functionRegistry.add("data-uri", function(mimetypeNode, filePathNode) {
  1465. if (!filePathNode) {
  1466. filePathNode = mimetypeNode;
  1467. mimetypeNode = null;
  1468. }
  1469. var mimetype = mimetypeNode && mimetypeNode.value;
  1470. var filePath = filePathNode.value;
  1471. var currentFileInfo = this.currentFileInfo;
  1472. var currentDirectory = currentFileInfo.relativeUrls ?
  1473. currentFileInfo.currentDirectory : currentFileInfo.entryPath;
  1474. var fragmentStart = filePath.indexOf('#');
  1475. var fragment = '';
  1476. if (fragmentStart !== -1) {
  1477. fragment = filePath.slice(fragmentStart);
  1478. filePath = filePath.slice(0, fragmentStart);
  1479. }
  1480. var fileManager = environment.getFileManager(filePath, currentDirectory, this.context, environment, true);
  1481. if (!fileManager) {
  1482. return fallback(this, filePathNode);
  1483. }
  1484. var useBase64 = false;
  1485. // detect the mimetype if not given
  1486. if (!mimetypeNode) {
  1487. mimetype = environment.mimeLookup(filePath);
  1488. if (mimetype === "image/svg+xml") {
  1489. useBase64 = false;
  1490. } else {
  1491. // use base 64 unless it's an ASCII or UTF-8 format
  1492. var charset = environment.charsetLookup(mimetype);
  1493. useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
  1494. }
  1495. if (useBase64) { mimetype += ';base64'; }
  1496. }
  1497. else {
  1498. useBase64 = /;base64$/.test(mimetype);
  1499. }
  1500. var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment);
  1501. if (!fileSync.contents) {
  1502. logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
  1503. return fallback(this, filePathNode || mimetypeNode);
  1504. }
  1505. var buf = fileSync.contents;
  1506. if (useBase64 && !environment.encodeBase64) {
  1507. return fallback(this, filePathNode);
  1508. }
  1509. buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf);
  1510. var uri = "data:" + mimetype + ',' + buf + fragment;
  1511. // IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded
  1512. // and the --ieCompat flag is enabled, return a normal url() instead.
  1513. var DATA_URI_MAX = 32768;
  1514. if (uri.length >= DATA_URI_MAX) {
  1515. if (this.context.ieCompat !== false) {
  1516. logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length +
  1517. " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
  1518. return fallback(this, filePathNode || mimetypeNode);
  1519. }
  1520. }
  1521. return new URL(new Quoted('"' + uri + '"', uri, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
  1522. });
  1523. };
  1524. },{"../logger":31,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],19:[function(require,module,exports){
  1525. var Keyword = require("../tree/keyword"),
  1526. functionRegistry = require("./function-registry");
  1527. var defaultFunc = {
  1528. eval: function () {
  1529. var v = this.value_, e = this.error_;
  1530. if (e) {
  1531. throw e;
  1532. }
  1533. if (v != null) {
  1534. return v ? Keyword.True : Keyword.False;
  1535. }
  1536. },
  1537. value: function (v) {
  1538. this.value_ = v;
  1539. },
  1540. error: function (e) {
  1541. this.error_ = e;
  1542. },
  1543. reset: function () {
  1544. this.value_ = this.error_ = null;
  1545. }
  1546. };
  1547. functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc));
  1548. module.exports = defaultFunc;
  1549. },{"../tree/keyword":62,"./function-registry":21}],20:[function(require,module,exports){
  1550. var functionRegistry = require("./function-registry");
  1551. var functionCaller = function(name, context, index, currentFileInfo) {
  1552. this.name = name.toLowerCase();
  1553. this.func = functionRegistry.get(this.name);
  1554. this.index = index;
  1555. this.context = context;
  1556. this.currentFileInfo = currentFileInfo;
  1557. };
  1558. functionCaller.prototype.isValid = function() {
  1559. return Boolean(this.func);
  1560. };
  1561. functionCaller.prototype.call = function(args) {
  1562. return this.func.apply(this, args);
  1563. };
  1564. module.exports = functionCaller;
  1565. },{"./function-registry":21}],21:[function(require,module,exports){
  1566. module.exports = {
  1567. _data: {},
  1568. add: function(name, func) {
  1569. if (this._data.hasOwnProperty(name)) {
  1570. //TODO warn
  1571. }
  1572. this._data[name] = func;
  1573. },
  1574. addMultiple: function(functions) {
  1575. Object.keys(functions).forEach(
  1576. function(name) {
  1577. this.add(name, functions[name]);
  1578. }.bind(this));
  1579. },
  1580. get: function(name) {
  1581. return this._data[name];
  1582. }
  1583. };
  1584. },{}],22:[function(require,module,exports){
  1585. module.exports = function(environment) {
  1586. var functions = {
  1587. functionRegistry: require("./function-registry"),
  1588. functionCaller: require("./function-caller")
  1589. };
  1590. //register functions
  1591. require("./default");
  1592. require("./color");
  1593. require("./color-blending");
  1594. require("./data-uri")(environment);
  1595. require("./math");
  1596. require("./number");
  1597. require("./string");
  1598. require("./svg")(environment);
  1599. require("./types");
  1600. return functions;
  1601. };
  1602. },{"./color":17,"./color-blending":16,"./data-uri":18,"./default":19,"./function-caller":20,"./function-registry":21,"./math":23,"./number":24,"./string":25,"./svg":26,"./types":27}],23:[function(require,module,exports){
  1603. var Dimension = require("../tree/dimension"),
  1604. functionRegistry = require("./function-registry");
  1605. var mathFunctions = {
  1606. // name, unit
  1607. ceil: null,
  1608. floor: null,
  1609. sqrt: null,
  1610. abs: null,
  1611. tan: "",
  1612. sin: "",
  1613. cos: "",
  1614. atan: "rad",
  1615. asin: "rad",
  1616. acos: "rad"
  1617. };
  1618. function _math(fn, unit, n) {
  1619. if (!(n instanceof Dimension)) {
  1620. throw { type: "Argument", message: "argument must be a number" };
  1621. }
  1622. if (unit == null) {
  1623. unit = n.unit;
  1624. } else {
  1625. n = n.unify();
  1626. }
  1627. return new Dimension(fn(parseFloat(n.value)), unit);
  1628. }
  1629. for (var f in mathFunctions) {
  1630. if (mathFunctions.hasOwnProperty(f)) {
  1631. mathFunctions[f] = _math.bind(null, Math[f], mathFunctions[f]);
  1632. }
  1633. }
  1634. mathFunctions.round = function (n, f) {
  1635. var fraction = typeof f === "undefined" ? 0 : f.value;
  1636. return _math(function(num) { return num.toFixed(fraction); }, null, n);
  1637. };
  1638. functionRegistry.addMultiple(mathFunctions);
  1639. },{"../tree/dimension":53,"./function-registry":21}],24:[function(require,module,exports){
  1640. var Dimension = require("../tree/dimension"),
  1641. Anonymous = require("../tree/anonymous"),
  1642. functionRegistry = require("./function-registry");
  1643. var minMax = function (isMin, args) {
  1644. args = Array.prototype.slice.call(args);
  1645. switch(args.length) {
  1646. case 0: throw { type: "Argument", message: "one or more arguments required" };
  1647. }
  1648. var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone,
  1649. order = [], // elems only contains original argument values.
  1650. values = {}; // key is the unit.toString() for unified Dimension values,
  1651. // value is the index into the order array.
  1652. for (i = 0; i < args.length; i++) {
  1653. current = args[i];
  1654. if (!(current instanceof Dimension)) {
  1655. if (Array.isArray(args[i].value)) {
  1656. Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value));
  1657. }
  1658. continue;
  1659. }
  1660. currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify();
  1661. unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString();
  1662. unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic;
  1663. unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone;
  1664. j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit];
  1665. if (j === undefined) {
  1666. if (unitStatic !== undefined && unit !== unitStatic) {
  1667. throw{ type: "Argument", message: "incompatible types" };
  1668. }
  1669. values[unit] = order.length;
  1670. order.push(current);
  1671. continue;
  1672. }
  1673. referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify();
  1674. if ( isMin && currentUnified.value < referenceUnified.value ||
  1675. !isMin && currentUnified.value > referenceUnified.value) {
  1676. order[j] = current;
  1677. }
  1678. }
  1679. if (order.length == 1) {
  1680. return order[0];
  1681. }
  1682. args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? "," : ", ");
  1683. return new Anonymous((isMin ? "min" : "max") + "(" + args + ")");
  1684. };
  1685. functionRegistry.addMultiple({
  1686. min: function () {
  1687. return minMax(true, arguments);
  1688. },
  1689. max: function () {
  1690. return minMax(false, arguments);
  1691. },
  1692. convert: function (val, unit) {
  1693. return val.convertTo(unit.value);
  1694. },
  1695. pi: function () {
  1696. return new Dimension(Math.PI);
  1697. },
  1698. mod: function(a, b) {
  1699. return new Dimension(a.value % b.value, a.unit);
  1700. },
  1701. pow: function(x, y) {
  1702. if (typeof x === "number" && typeof y === "number") {
  1703. x = new Dimension(x);
  1704. y = new Dimension(y);
  1705. } else if (!(x instanceof Dimension) || !(y instanceof Dimension)) {
  1706. throw { type: "Argument", message: "arguments must be numbers" };
  1707. }
  1708. return new Dimension(Math.pow(x.value, y.value), x.unit);
  1709. },
  1710. percentage: function (n) {
  1711. return new Dimension(n.value * 100, '%');
  1712. }
  1713. });
  1714. },{"../tree/anonymous":43,"../tree/dimension":53,"./function-registry":21}],25:[function(require,module,exports){
  1715. var Quoted = require("../tree/quoted"),
  1716. Anonymous = require("../tree/anonymous"),
  1717. JavaScript = require("../tree/javascript"),
  1718. functionRegistry = require("./function-registry");
  1719. functionRegistry.addMultiple({
  1720. e: function (str) {
  1721. return new Anonymous(str instanceof JavaScript ? str.evaluated : str.value);
  1722. },
  1723. escape: function (str) {
  1724. return new Anonymous(
  1725. encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B")
  1726. .replace(/\(/g, "%28").replace(/\)/g, "%29"));
  1727. },
  1728. replace: function (string, pattern, replacement, flags) {
  1729. var result = string.value;
  1730. result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement.value);
  1731. return new Quoted(string.quote || '', result, string.escaped);
  1732. },
  1733. '%': function (string /* arg, arg, ...*/) {
  1734. var args = Array.prototype.slice.call(arguments, 1),
  1735. result = string.value;
  1736. for (var i = 0; i < args.length; i++) {
  1737. /*jshint loopfunc:true */
  1738. result = result.replace(/%[sda]/i, function(token) {
  1739. var value = token.match(/s/i) ? args[i].value : args[i].toCSS();
  1740. return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value;
  1741. });
  1742. }
  1743. result = result.replace(/%%/g, '%');
  1744. return new Quoted(string.quote || '', result, string.escaped);
  1745. }
  1746. });
  1747. },{"../tree/anonymous":43,"../tree/javascript":60,"../tree/quoted":70,"./function-registry":21}],26:[function(require,module,exports){
  1748. module.exports = function(environment) {
  1749. var Dimension = require("../tree/dimension"),
  1750. Color = require("../tree/color"),
  1751. Expression = require("../tree/expression"),
  1752. Quoted = require("../tree/quoted"),
  1753. URL = require("../tree/url"),
  1754. functionRegistry = require("./function-registry");
  1755. functionRegistry.add("svg-gradient", function(direction) {
  1756. function throwArgumentDescriptor() {
  1757. throw { type: "Argument",
  1758. message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
  1759. " end_color [end_position]" };
  1760. }
  1761. if (arguments.length < 3) {
  1762. throwArgumentDescriptor();
  1763. }
  1764. var stops = Array.prototype.slice.call(arguments, 1),
  1765. gradientDirectionSvg,
  1766. gradientType = "linear",
  1767. rectangleDimension = 'x="0" y="0" width="1" height="1"',
  1768. renderEnv = {compress: false},
  1769. returner,
  1770. directionValue = direction.toCSS(renderEnv),
  1771. i, color, position, positionValue, alpha;
  1772. switch (directionValue) {
  1773. case "to bottom":
  1774. gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"';
  1775. break;
  1776. case "to right":
  1777. gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"';
  1778. break;
  1779. case "to bottom right":
  1780. gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"';
  1781. break;
  1782. case "to top right":
  1783. gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"';
  1784. break;
  1785. case "ellipse":
  1786. case "ellipse at center":
  1787. gradientType = "radial";
  1788. gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"';
  1789. rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
  1790. break;
  1791. default:
  1792. throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," +
  1793. " 'to bottom right', 'to top right' or 'ellipse at center'" };
  1794. }
  1795. returner = '<?xml version="1.0" ?>' +
  1796. '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
  1797. '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
  1798. for (i = 0; i < stops.length; i+= 1) {
  1799. if (stops[i] instanceof Expression) {
  1800. color = stops[i].value[0];
  1801. position = stops[i].value[1];
  1802. } else {
  1803. color = stops[i];
  1804. position = undefined;
  1805. }
  1806. if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
  1807. throwArgumentDescriptor();
  1808. }
  1809. positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
  1810. alpha = color.alpha;
  1811. returner += '<stop offset="' + positionValue + '" stop-color="' + color.toRGB() + '"' + (alpha < 1 ? ' stop-opacity="' + alpha + '"' : '') + '/>';
  1812. }
  1813. returner += '</' + gradientType + 'Gradient>' +
  1814. '<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
  1815. returner = encodeURIComponent(returner);
  1816. returner = "data:image/svg+xml," + returner;
  1817. return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
  1818. });
  1819. };
  1820. },{"../tree/color":47,"../tree/dimension":53,"../tree/expression":56,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],27:[function(require,module,exports){
  1821. var Keyword = require("../tree/keyword"),
  1822. DetachedRuleset = require("../tree/detached-ruleset"),
  1823. Dimension = require("../tree/dimension"),
  1824. Color = require("../tree/color"),
  1825. Quoted = require("../tree/quoted"),
  1826. Anonymous = require("../tree/anonymous"),
  1827. URL = require("../tree/url"),
  1828. Operation = require("../tree/operation"),
  1829. functionRegistry = require("./function-registry");
  1830. var isa = function (n, Type) {
  1831. return (n instanceof Type) ? Keyword.True : Keyword.False;
  1832. },
  1833. isunit = function (n, unit) {
  1834. if (unit === undefined) {
  1835. throw { type: "Argument", message: "missing the required second argument to isunit." };
  1836. }
  1837. unit = typeof unit.value === "string" ? unit.value : unit;
  1838. if (typeof unit !== "string") {
  1839. throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." };
  1840. }
  1841. return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
  1842. },
  1843. getItemsFromNode = function(node) {
  1844. // handle non-array values as an array of length 1
  1845. // return 'undefined' if index is invalid
  1846. var items = Array.isArray(node.value) ?
  1847. node.value : Array(node);
  1848. return items.filter(function(item) {
  1849. if (item.type === "Comment") {
  1850. return false;
  1851. }
  1852. return true;
  1853. });
  1854. };
  1855. functionRegistry.addMultiple({
  1856. isruleset: function (n) {
  1857. return isa(n, DetachedRuleset);
  1858. },
  1859. iscolor: function (n) {
  1860. return isa(n, Color);
  1861. },
  1862. isnumber: function (n) {
  1863. return isa(n, Dimension);
  1864. },
  1865. isstring: function (n) {
  1866. return isa(n, Quoted);
  1867. },
  1868. iskeyword: function (n) {
  1869. return isa(n, Keyword);
  1870. },
  1871. isurl: function (n) {
  1872. return isa(n, URL);
  1873. },
  1874. ispixel: function (n) {
  1875. return isunit(n, 'px');
  1876. },
  1877. ispercentage: function (n) {
  1878. return isunit(n, '%');
  1879. },
  1880. isem: function (n) {
  1881. return isunit(n, 'em');
  1882. },
  1883. isunit: isunit,
  1884. unit: function (val, unit) {
  1885. if (!(val instanceof Dimension)) {
  1886. throw { type: "Argument",
  1887. message: "the first argument to unit must be a number" +
  1888. (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
  1889. }
  1890. if (unit) {
  1891. if (unit instanceof Keyword) {
  1892. unit = unit.value;
  1893. } else {
  1894. unit = unit.toCSS();
  1895. }
  1896. } else {
  1897. unit = "";
  1898. }
  1899. return new Dimension(val.value, unit);
  1900. },
  1901. "get-unit": function (n) {
  1902. return new Anonymous(n.unit);
  1903. },
  1904. extract: function(values, index) {
  1905. index = index.value - 1; // (1-based index)
  1906. return getItemsFromNode(values)[index];
  1907. },
  1908. length: function(values) {
  1909. return new Dimension(getItemsFromNode(values).length);
  1910. }
  1911. });
  1912. },{"../tree/anonymous":43,"../tree/color":47,"../tree/detached-ruleset":52,"../tree/dimension":53,"../tree/keyword":62,"../tree/operation":68,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],28:[function(require,module,exports){
  1913. var contexts = require("./contexts"),
  1914. Parser = require('./parser/parser');
  1915. module.exports = function(environment) {
  1916. // FileInfo = {
  1917. // 'relativeUrls' - option - whether to adjust URL's to be relative
  1918. // 'filename' - full resolved filename of current file
  1919. // 'rootpath' - path to append to normal URLs for this node
  1920. // 'currentDirectory' - path to the current file, absolute
  1921. // 'rootFilename' - filename of the base file
  1922. // 'entryPath' - absolute path to the entry file
  1923. // 'reference' - whether the file should not be output and only output parts that are referenced
  1924. var ImportManager = function(context, rootFileInfo) {
  1925. this.rootFilename = rootFileInfo.filename;
  1926. this.paths = context.paths || []; // Search paths, when importing
  1927. this.contents = {}; // map - filename to contents of all the files
  1928. this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
  1929. this.mime = context.mime;
  1930. this.error = null;
  1931. this.context = context;
  1932. // Deprecated? Unused outside of here, could be useful.
  1933. this.queue = []; // Files which haven't been imported yet
  1934. this.files = {}; // Holds the imported parse trees.
  1935. };
  1936. /**
  1937. * Add an import to be imported
  1938. * @param path - the raw path
  1939. * @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension)
  1940. * @param currentFileInfo - the current file info (used for instance to work out relative paths)
  1941. * @param importOptions - import options
  1942. * @param callback - callback for when it is imported
  1943. */
  1944. ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) {
  1945. var importManager = this;
  1946. this.queue.push(path);
  1947. var fileParsedFunc = function (e, root, fullPath) {
  1948. importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
  1949. var importedEqualsRoot = fullPath === importManager.rootFilename;
  1950. if (importOptions.optional && e) {
  1951. callback(null, {rules:[]}, false, null);
  1952. }
  1953. else {
  1954. importManager.files[fullPath] = root;
  1955. if (e && !importManager.error) { importManager.error = e; }
  1956. callback(e, root, importedEqualsRoot, fullPath);
  1957. }
  1958. };
  1959. var newFileInfo = {
  1960. relativeUrls: this.context.relativeUrls,
  1961. entryPath: currentFileInfo.entryPath,
  1962. rootpath: currentFileInfo.rootpath,
  1963. rootFilename: currentFileInfo.rootFilename
  1964. };
  1965. var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);
  1966. if (!fileManager) {
  1967. fileParsedFunc({ message: "Could not find a file-manager for " + path });
  1968. return;
  1969. }
  1970. if (tryAppendLessExtension) {
  1971. path = fileManager.tryAppendLessExtension(path);
  1972. }
  1973. var loadFileCallback = function(loadedFile) {
  1974. var resolvedFilename = loadedFile.filename,
  1975. contents = loadedFile.contents.replace(/^\uFEFF/, '');
  1976. // Pass on an updated rootpath if path of imported file is relative and file
  1977. // is in a (sub|sup) directory
  1978. //
  1979. // Examples:
  1980. // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
  1981. // then rootpath should become 'less/module/nav/'
  1982. // - If path of imported file is '../mixins.less' and rootpath is 'less/',
  1983. // then rootpath should become 'less/../'
  1984. newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
  1985. if (newFileInfo.relativeUrls) {
  1986. newFileInfo.rootpath = fileManager.join(
  1987. (importManager.context.rootpath || ""),
  1988. fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
  1989. if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
  1990. newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
  1991. }
  1992. }
  1993. newFileInfo.filename = resolvedFilename;
  1994. var newEnv = new contexts.Parse(importManager.context);
  1995. newEnv.processImports = false;
  1996. importManager.contents[resolvedFilename] = contents;
  1997. if (currentFileInfo.reference || importOptions.reference) {
  1998. newFileInfo.reference = true;
  1999. }
  2000. if (importOptions.inline) {
  2001. fileParsedFunc(null, contents, resolvedFilename);
  2002. } else {
  2003. new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
  2004. fileParsedFunc(e, root, resolvedFilename);
  2005. });
  2006. }
  2007. };
  2008. var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment,
  2009. function(err, loadedFile) {
  2010. if (err) {
  2011. fileParsedFunc(err);
  2012. } else {
  2013. loadFileCallback(loadedFile);
  2014. }
  2015. });
  2016. if (promise) {
  2017. promise.then(loadFileCallback, fileParsedFunc);
  2018. }
  2019. };
  2020. return ImportManager;
  2021. };
  2022. },{"./contexts":10,"./parser/parser":36}],29:[function(require,module,exports){
  2023. module.exports = function(environment, fileManagers) {
  2024. var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
  2025. var less = {
  2026. version: [2, 4, 0],
  2027. data: require('./data'),
  2028. tree: require('./tree'),
  2029. Environment: (Environment = require("./environment/environment")),
  2030. AbstractFileManager: require("./environment/abstract-file-manager"),
  2031. environment: (environment = new Environment(environment, fileManagers)),
  2032. visitors: require('./visitors'),
  2033. Parser: require('./parser/parser'),
  2034. functions: require('./functions')(environment),
  2035. contexts: require("./contexts"),
  2036. SourceMapOutput: (SourceMapOutput = require('./source-map-output')(environment)),
  2037. SourceMapBuilder: (SourceMapBuilder = require('./source-map-builder')(SourceMapOutput, environment)),
  2038. ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)),
  2039. ImportManager: (ImportManager = require('./import-manager')(environment)),
  2040. render: require("./render")(environment, ParseTree, ImportManager),
  2041. parse: require("./parse")(environment, ParseTree, ImportManager),
  2042. LessError: require('./less-error'),
  2043. transformTree: require('./transform-tree'),
  2044. utils: require('./utils'),
  2045. PluginManager: require('./plugin-manager'),
  2046. logger: require('./logger')
  2047. };
  2048. return less;
  2049. };
  2050. },{"./contexts":10,"./data":12,"./environment/abstract-file-manager":14,"./environment/environment":15,"./functions":22,"./import-manager":28,"./less-error":30,"./logger":31,"./parse":33,"./parse-tree":32,"./parser/parser":36,"./plugin-manager":37,"./render":38,"./source-map-builder":39,"./source-map-output":40,"./transform-tree":41,"./tree":59,"./utils":80,"./visitors":84}],30:[function(require,module,exports){
  2051. var utils = require("./utils");
  2052. var LessError = module.exports = function LessError(e, importManager, currentFilename) {
  2053. Error.call(this);
  2054. var filename = e.filename || currentFilename;
  2055. if (importManager && filename) {
  2056. var input = importManager.contents[filename],
  2057. loc = utils.getLocation(e.index, input),
  2058. line = loc.line,
  2059. col = loc.column,
  2060. callLine = e.call && utils.getLocation(e.call, input).line,
  2061. lines = input.split('\n');
  2062. this.type = e.type || 'Syntax';
  2063. this.filename = filename;
  2064. this.index = e.index;
  2065. this.line = typeof line === 'number' ? line + 1 : null;
  2066. this.callLine = callLine + 1;
  2067. this.callExtract = lines[callLine];
  2068. this.column = col;
  2069. this.extract = [
  2070. lines[line - 1],
  2071. lines[line],
  2072. lines[line + 1]
  2073. ];
  2074. }
  2075. this.message = e.message;
  2076. this.stack = e.stack;
  2077. };
  2078. if (typeof Object.create === 'undefined') {
  2079. var F = function () {};
  2080. F.prototype = Error.prototype;
  2081. LessError.prototype = new F();
  2082. } else {
  2083. LessError.prototype = Object.create(Error.prototype);
  2084. }
  2085. LessError.prototype.constructor = LessError;
  2086. },{"./utils":80}],31:[function(require,module,exports){
  2087. module.exports = {
  2088. error: function(msg) {
  2089. this._fireEvent("error", msg);
  2090. },
  2091. warn: function(msg) {
  2092. this._fireEvent("warn", msg);
  2093. },
  2094. info: function(msg) {
  2095. this._fireEvent("info", msg);
  2096. },
  2097. debug: function(msg) {
  2098. this._fireEvent("debug", msg);
  2099. },
  2100. addListener: function(listener) {
  2101. this._listeners.push(listener);
  2102. },
  2103. removeListener: function(listener) {
  2104. for (var i = 0; i < this._listeners.length; i++) {
  2105. if (this._listeners[i] === listener) {
  2106. this._listeners.splice(i, 1);
  2107. return;
  2108. }
  2109. }
  2110. },
  2111. _fireEvent: function(type, msg) {
  2112. for (var i = 0; i < this._listeners.length; i++) {
  2113. var logFunction = this._listeners[i][type];
  2114. if (logFunction) {
  2115. logFunction(msg);
  2116. }
  2117. }
  2118. },
  2119. _listeners: []
  2120. };
  2121. },{}],32:[function(require,module,exports){
  2122. var LessError = require('./less-error'),
  2123. transformTree = require("./transform-tree"),
  2124. logger = require("./logger");
  2125. module.exports = function(SourceMapBuilder) {
  2126. var ParseTree = function(root, imports) {
  2127. this.root = root;
  2128. this.imports = imports;
  2129. };
  2130. ParseTree.prototype.toCSS = function(options) {
  2131. var evaldRoot, result = {}, sourceMapBuilder;
  2132. try {
  2133. evaldRoot = transformTree(this.root, options);
  2134. } catch (e) {
  2135. throw new LessError(e, this.imports);
  2136. }
  2137. try {
  2138. var compress = Boolean(options.compress);
  2139. if (compress) {
  2140. logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.");
  2141. }
  2142. var toCSSOptions = {
  2143. compress: compress,
  2144. dumpLineNumbers: options.dumpLineNumbers,
  2145. strictUnits: Boolean(options.strictUnits),
  2146. numPrecision: 8};
  2147. if (options.sourceMap) {
  2148. sourceMapBuilder = new SourceMapBuilder(options.sourceMap);
  2149. result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
  2150. } else {
  2151. result.css = evaldRoot.toCSS(toCSSOptions);
  2152. }
  2153. } catch (e) {
  2154. throw new LessError(e, this.imports);
  2155. }
  2156. if (options.pluginManager) {
  2157. var postProcessors = options.pluginManager.getPostProcessors();
  2158. for (var i = 0; i < postProcessors.length; i++) {
  2159. result.css = postProcessors[i].process(result.css, { sourceMap: sourceMapBuilder, options: options, imports: this.imports });
  2160. }
  2161. }
  2162. if (options.sourceMap) {
  2163. result.map = sourceMapBuilder.getExternalSourceMap();
  2164. }
  2165. result.imports = [];
  2166. for (var file in this.imports.files) {
  2167. if (this.imports.files.hasOwnProperty(file) && file !== this.imports.rootFilename) {
  2168. result.imports.push(file);
  2169. }
  2170. }
  2171. return result;
  2172. };
  2173. return ParseTree;
  2174. };
  2175. },{"./less-error":30,"./logger":31,"./transform-tree":41}],33:[function(require,module,exports){
  2176. var PromiseConstructor,
  2177. contexts = require("./contexts"),
  2178. Parser = require('./parser/parser'),
  2179. PluginManager = require('./plugin-manager');
  2180. module.exports = function(environment, ParseTree, ImportManager) {
  2181. var parse = function (input, options, callback) {
  2182. options = options || {};
  2183. if (typeof options === 'function') {
  2184. callback = options;
  2185. options = {};
  2186. }
  2187. if (!callback) {
  2188. if (!PromiseConstructor) {
  2189. PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
  2190. }
  2191. var self = this;
  2192. return new PromiseConstructor(function (resolve, reject) {
  2193. parse.call(self, input, options, function(err, output) {
  2194. if (err) {
  2195. reject(err);
  2196. } else {
  2197. resolve(output);
  2198. }
  2199. });
  2200. });
  2201. } else {
  2202. var context,
  2203. rootFileInfo,
  2204. pluginManager = new PluginManager(this);
  2205. pluginManager.addPlugins(options.plugins);
  2206. options.pluginManager = pluginManager;
  2207. context = new contexts.Parse(options);
  2208. if (options.rootFileInfo) {
  2209. rootFileInfo = options.rootFileInfo;
  2210. } else {
  2211. var filename = options.filename || "input";
  2212. var entryPath = filename.replace(/[^\/\\]*$/, "");
  2213. rootFileInfo = {
  2214. filename: filename,
  2215. relativeUrls: context.relativeUrls,
  2216. rootpath: context.rootpath || "",
  2217. currentDirectory: entryPath,
  2218. entryPath: entryPath,
  2219. rootFilename: filename
  2220. };
  2221. // add in a missing trailing slash
  2222. if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== "/") {
  2223. rootFileInfo.rootpath += "/";
  2224. }
  2225. }
  2226. var imports = new ImportManager(context, rootFileInfo);
  2227. new Parser(context, imports, rootFileInfo)
  2228. .parse(input, function (e, root) {
  2229. if (e) { return callback(e); }
  2230. callback(null, root, imports, options);
  2231. }, options);
  2232. }
  2233. };
  2234. return parse;
  2235. };
  2236. },{"./contexts":10,"./parser/parser":36,"./plugin-manager":37,"promise":undefined}],34:[function(require,module,exports){
  2237. // Split the input into chunks.
  2238. module.exports = function (input, fail) {
  2239. var len = input.length, level = 0, parenLevel = 0,
  2240. lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace,
  2241. chunks = [], emitFrom = 0,
  2242. chunkerCurrentIndex, currentChunkStartIndex, cc, cc2, matched;
  2243. function emitChunk(force) {
  2244. var len = chunkerCurrentIndex - emitFrom;
  2245. if (((len < 512) && !force) || !len) {
  2246. return;
  2247. }
  2248. chunks.push(input.slice(emitFrom, chunkerCurrentIndex + 1));
  2249. emitFrom = chunkerCurrentIndex + 1;
  2250. }
  2251. for (chunkerCurrentIndex = 0; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
  2252. cc = input.charCodeAt(chunkerCurrentIndex);
  2253. if (((cc >= 97) && (cc <= 122)) || (cc < 34)) {
  2254. // a-z or whitespace
  2255. continue;
  2256. }
  2257. switch (cc) {
  2258. case 40: // (
  2259. parenLevel++;
  2260. lastOpeningParen = chunkerCurrentIndex;
  2261. continue;
  2262. case 41: // )
  2263. if (--parenLevel < 0) {
  2264. return fail("missing opening `(`", chunkerCurrentIndex);
  2265. }
  2266. continue;
  2267. case 59: // ;
  2268. if (!parenLevel) { emitChunk(); }
  2269. continue;
  2270. case 123: // {
  2271. level++;
  2272. lastOpening = chunkerCurrentIndex;
  2273. continue;
  2274. case 125: // }
  2275. if (--level < 0) {
  2276. return fail("missing opening `{`", chunkerCurrentIndex);
  2277. }
  2278. if (!level && !parenLevel) { emitChunk(); }
  2279. continue;
  2280. case 92: // \
  2281. if (chunkerCurrentIndex < len - 1) { chunkerCurrentIndex++; continue; }
  2282. return fail("unescaped `\\`", chunkerCurrentIndex);
  2283. case 34:
  2284. case 39:
  2285. case 96: // ", ' and `
  2286. matched = 0;
  2287. currentChunkStartIndex = chunkerCurrentIndex;
  2288. for (chunkerCurrentIndex = chunkerCurrentIndex + 1; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
  2289. cc2 = input.charCodeAt(chunkerCurrentIndex);
  2290. if (cc2 > 96) { continue; }
  2291. if (cc2 == cc) { matched = 1; break; }
  2292. if (cc2 == 92) { // \
  2293. if (chunkerCurrentIndex == len - 1) {
  2294. return fail("unescaped `\\`", chunkerCurrentIndex);
  2295. }
  2296. chunkerCurrentIndex++;
  2297. }
  2298. }
  2299. if (matched) { continue; }
  2300. return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex);
  2301. case 47: // /, check for comment
  2302. if (parenLevel || (chunkerCurrentIndex == len - 1)) { continue; }
  2303. cc2 = input.charCodeAt(chunkerCurrentIndex + 1);
  2304. if (cc2 == 47) {
  2305. // //, find lnfeed
  2306. for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
  2307. cc2 = input.charCodeAt(chunkerCurrentIndex);
  2308. if ((cc2 <= 13) && ((cc2 == 10) || (cc2 == 13))) { break; }
  2309. }
  2310. } else if (cc2 == 42) {
  2311. // /*, find */
  2312. lastMultiComment = currentChunkStartIndex = chunkerCurrentIndex;
  2313. for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len - 1; chunkerCurrentIndex++) {
  2314. cc2 = input.charCodeAt(chunkerCurrentIndex);
  2315. if (cc2 == 125) { lastMultiCommentEndBrace = chunkerCurrentIndex; }
  2316. if (cc2 != 42) { continue; }
  2317. if (input.charCodeAt(chunkerCurrentIndex + 1) == 47) { break; }
  2318. }
  2319. if (chunkerCurrentIndex == len - 1) {
  2320. return fail("missing closing `*/`", currentChunkStartIndex);
  2321. }
  2322. chunkerCurrentIndex++;
  2323. }
  2324. continue;
  2325. case 42: // *, check for unmatched */
  2326. if ((chunkerCurrentIndex < len - 1) && (input.charCodeAt(chunkerCurrentIndex + 1) == 47)) {
  2327. return fail("unmatched `/*`", chunkerCurrentIndex);
  2328. }
  2329. continue;
  2330. }
  2331. }
  2332. if (level !== 0) {
  2333. if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) {
  2334. return fail("missing closing `}` or `*/`", lastOpening);
  2335. } else {
  2336. return fail("missing closing `}`", lastOpening);
  2337. }
  2338. } else if (parenLevel !== 0) {
  2339. return fail("missing closing `)`", lastOpeningParen);
  2340. }
  2341. emitChunk(true);
  2342. return chunks;
  2343. };
  2344. },{}],35:[function(require,module,exports){
  2345. var chunker = require('./chunker');
  2346. module.exports = function() {
  2347. var input, // LeSS input string
  2348. j, // current chunk
  2349. saveStack = [], // holds state for backtracking
  2350. furthest, // furthest index the parser has gone to
  2351. furthestPossibleErrorMessage,// if this is furthest we got to, this is the probably cause
  2352. chunks, // chunkified input
  2353. current, // current chunk
  2354. currentPos, // index of current chunk, in `input`
  2355. parserInput = {};
  2356. parserInput.save = function() {
  2357. currentPos = parserInput.i;
  2358. saveStack.push( { current: current, i: parserInput.i, j: j });
  2359. };
  2360. parserInput.restore = function(possibleErrorMessage) {
  2361. if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
  2362. furthest = parserInput.i;
  2363. furthestPossibleErrorMessage = possibleErrorMessage;
  2364. }
  2365. var state = saveStack.pop();
  2366. current = state.current;
  2367. currentPos = parserInput.i = state.i;
  2368. j = state.j;
  2369. };
  2370. parserInput.forget = function() {
  2371. saveStack.pop();
  2372. };
  2373. function sync() {
  2374. if (parserInput.i > currentPos) {
  2375. current = current.slice(parserInput.i - currentPos);
  2376. currentPos = parserInput.i;
  2377. }
  2378. }
  2379. parserInput.isWhitespace = function (offset) {
  2380. var pos = parserInput.i + (offset || 0),
  2381. code = input.charCodeAt(pos);
  2382. return (code === CHARCODE_SPACE || code === CHARCODE_CR || code === CHARCODE_TAB || code === CHARCODE_LF);
  2383. };
  2384. //
  2385. // Parse from a token, regexp or string, and move forward if match
  2386. //
  2387. parserInput.$ = function(tok) {
  2388. var tokType = typeof tok,
  2389. match, length;
  2390. // Either match a single character in the input,
  2391. // or match a regexp in the current chunk (`current`).
  2392. //
  2393. if (tokType === "string") {
  2394. if (input.charAt(parserInput.i) !== tok) {
  2395. return null;
  2396. }
  2397. skipWhitespace(1);
  2398. return tok;
  2399. }
  2400. // regexp
  2401. sync();
  2402. if (! (match = tok.exec(current))) {
  2403. return null;
  2404. }
  2405. length = match[0].length;
  2406. // The match is confirmed, add the match length to `i`,
  2407. // and consume any extra white-space characters (' ' || '\n')
  2408. // which come after that. The reason for this is that LeSS's
  2409. // grammar is mostly white-space insensitive.
  2410. //
  2411. skipWhitespace(length);
  2412. if (typeof match === 'string') {
  2413. return match;
  2414. } else {
  2415. return match.length === 1 ? match[0] : match;
  2416. }
  2417. };
  2418. // Specialization of $(tok)
  2419. parserInput.$re = function(tok) {
  2420. if (parserInput.i > currentPos) {
  2421. current = current.slice(parserInput.i - currentPos);
  2422. currentPos = parserInput.i;
  2423. }
  2424. var m = tok.exec(current);
  2425. if (!m) {
  2426. return null;
  2427. }
  2428. skipWhitespace(m[0].length);
  2429. if (typeof m === "string") {
  2430. return m;
  2431. }
  2432. return m.length === 1 ? m[0] : m;
  2433. };
  2434. // Specialization of $(tok)
  2435. parserInput.$char = function(tok) {
  2436. if (input.charAt(parserInput.i) !== tok) {
  2437. return null;
  2438. }
  2439. skipWhitespace(1);
  2440. return tok;
  2441. };
  2442. var CHARCODE_SPACE = 32,
  2443. CHARCODE_TAB = 9,
  2444. CHARCODE_LF = 10,
  2445. CHARCODE_CR = 13,
  2446. CHARCODE_PLUS = 43,
  2447. CHARCODE_COMMA = 44,
  2448. CHARCODE_FORWARD_SLASH = 47,
  2449. CHARCODE_9 = 57;
  2450. parserInput.autoCommentAbsorb = true;
  2451. parserInput.commentStore = [];
  2452. parserInput.finished = false;
  2453. var skipWhitespace = function(length) {
  2454. var oldi = parserInput.i, oldj = j,
  2455. curr = parserInput.i - currentPos,
  2456. endIndex = parserInput.i + current.length - curr,
  2457. mem = (parserInput.i += length),
  2458. inp = input,
  2459. c, nextChar, comment;
  2460. for (; parserInput.i < endIndex; parserInput.i++) {
  2461. c = inp.charCodeAt(parserInput.i);
  2462. if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
  2463. nextChar = inp.charAt(parserInput.i + 1);
  2464. if (nextChar === '/') {
  2465. comment = {index: parserInput.i, isLineComment: true};
  2466. var nextNewLine = inp.indexOf("\n", parserInput.i + 1);
  2467. if (nextNewLine < 0) {
  2468. nextNewLine = endIndex;
  2469. }
  2470. parserInput.i = nextNewLine;
  2471. comment.text = inp.substr(comment.i, parserInput.i - comment.i);
  2472. parserInput.commentStore.push(comment);
  2473. continue;
  2474. } else if (nextChar === '*') {
  2475. var haystack = inp.substr(parserInput.i);
  2476. var comment_search_result = haystack.match(/^\/\*(?:[^*]|\*+[^\/*])*\*+\//);
  2477. if (comment_search_result) {
  2478. comment = {
  2479. index: parserInput.i,
  2480. text: comment_search_result[0],
  2481. isLineComment: false
  2482. };
  2483. parserInput.i += comment.text.length - 1;
  2484. parserInput.commentStore.push(comment);
  2485. continue;
  2486. }
  2487. }
  2488. break;
  2489. }
  2490. if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
  2491. break;
  2492. }
  2493. }
  2494. current = current.slice(length + parserInput.i - mem + curr);
  2495. currentPos = parserInput.i;
  2496. if (!current.length) {
  2497. if (j < chunks.length - 1)
  2498. {
  2499. current = chunks[++j];
  2500. skipWhitespace(0); // skip space at the beginning of a chunk
  2501. return true; // things changed
  2502. }
  2503. parserInput.finished = true;
  2504. }
  2505. return oldi !== parserInput.i || oldj !== j;
  2506. };
  2507. // Same as $(), but don't change the state of the parser,
  2508. // just return the match.
  2509. parserInput.peek = function(tok) {
  2510. if (typeof tok === 'string') {
  2511. return input.charAt(parserInput.i) === tok;
  2512. } else {
  2513. return tok.test(current);
  2514. }
  2515. };
  2516. // Specialization of peek()
  2517. // TODO remove or change some currentChar calls to peekChar
  2518. parserInput.peekChar = function(tok) {
  2519. return input.charAt(parserInput.i) === tok;
  2520. };
  2521. parserInput.currentChar = function() {
  2522. return input.charAt(parserInput.i);
  2523. };
  2524. parserInput.getInput = function() {
  2525. return input;
  2526. };
  2527. parserInput.peekNotNumeric = function() {
  2528. var c = input.charCodeAt(parserInput.i);
  2529. //Is the first char of the dimension 0-9, '.', '+' or '-'
  2530. return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA;
  2531. };
  2532. parserInput.start = function(str, chunkInput, failFunction) {
  2533. input = str;
  2534. parserInput.i = j = currentPos = furthest = 0;
  2535. // chunking apparantly makes things quicker (but my tests indicate
  2536. // it might actually make things slower in node at least)
  2537. // and it is a non-perfect parse - it can't recognise
  2538. // unquoted urls, meaning it can't distinguish comments
  2539. // meaning comments with quotes or {}() in them get 'counted'
  2540. // and then lead to parse errors.
  2541. // In addition if the chunking chunks in the wrong place we might
  2542. // not be able to parse a parser statement in one go
  2543. // this is officially deprecated but can be switched on via an option
  2544. // in the case it causes too much performance issues.
  2545. if (chunkInput) {
  2546. chunks = chunker(str, failFunction);
  2547. } else {
  2548. chunks = [str];
  2549. }
  2550. current = chunks[0];
  2551. skipWhitespace(0);
  2552. };
  2553. parserInput.end = function() {
  2554. var message,
  2555. isFinished = parserInput.i >= input.length;
  2556. if (parserInput.i < furthest) {
  2557. message = furthestPossibleErrorMessage;
  2558. parserInput.i = furthest;
  2559. }
  2560. return {
  2561. isFinished: isFinished,
  2562. furthest: parserInput.i,
  2563. furthestPossibleErrorMessage: message,
  2564. furthestReachedEnd: parserInput.i >= input.length - 1,
  2565. furthestChar: input[parserInput.i]
  2566. };
  2567. };
  2568. return parserInput;
  2569. };
  2570. },{"./chunker":34}],36:[function(require,module,exports){
  2571. var LessError = require('../less-error'),
  2572. tree = require("../tree"),
  2573. visitors = require("../visitors"),
  2574. getParserInput = require("./parser-input"),
  2575. utils = require("../utils");
  2576. //
  2577. // less.js - parser
  2578. //
  2579. // A relatively straight-forward predictive parser.
  2580. // There is no tokenization/lexing stage, the input is parsed
  2581. // in one sweep.
  2582. //
  2583. // To make the parser fast enough to run in the browser, several
  2584. // optimization had to be made:
  2585. //
  2586. // - Matching and slicing on a huge input is often cause of slowdowns.
  2587. // The solution is to chunkify the input into smaller strings.
  2588. // The chunks are stored in the `chunks` var,
  2589. // `j` holds the current chunk index, and `currentPos` holds
  2590. // the index of the current chunk in relation to `input`.
  2591. // This gives us an almost 4x speed-up.
  2592. //
  2593. // - In many cases, we don't need to match individual tokens;
  2594. // for example, if a value doesn't hold any variables, operations
  2595. // or dynamic references, the parser can effectively 'skip' it,
  2596. // treating it as a literal.
  2597. // An example would be '1px solid #000' - which evaluates to itself,
  2598. // we don't need to know what the individual components are.
  2599. // The drawback, of course is that you don't get the benefits of
  2600. // syntax-checking on the CSS. This gives us a 50% speed-up in the parser,
  2601. // and a smaller speed-up in the code-gen.
  2602. //
  2603. //
  2604. // Token matching is done with the `$` function, which either takes
  2605. // a terminal string or regexp, or a non-terminal function to call.
  2606. // It also takes care of moving all the indices forwards.
  2607. //
  2608. //
  2609. var Parser = function Parser(context, imports, fileInfo) {
  2610. var parsers,
  2611. parserInput = getParserInput();
  2612. function expect(arg, msg, index) {
  2613. // some older browsers return typeof 'function' for RegExp
  2614. var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$(arg);
  2615. if (result) {
  2616. return result;
  2617. }
  2618. error(msg || (typeof arg === 'string' ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'"
  2619. : "unexpected token"));
  2620. }
  2621. // Specialization of expect()
  2622. function expectChar(arg, msg) {
  2623. if (parserInput.$char(arg)) {
  2624. return arg;
  2625. }
  2626. error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'");
  2627. }
  2628. function error(msg, type) {
  2629. throw new LessError(
  2630. {
  2631. index: parserInput.i,
  2632. filename: fileInfo.filename,
  2633. type: type || 'Syntax',
  2634. message: msg
  2635. },
  2636. imports
  2637. );
  2638. }
  2639. function getDebugInfo(index) {
  2640. var filename = fileInfo.filename;
  2641. return {
  2642. lineNumber: utils.getLocation(index, parserInput.getInput()).line + 1,
  2643. fileName: filename
  2644. };
  2645. }
  2646. //
  2647. // The Parser
  2648. //
  2649. return {
  2650. //
  2651. // Parse an input string into an abstract syntax tree,
  2652. // @param str A string containing 'less' markup
  2653. // @param callback call `callback` when done.
  2654. // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
  2655. //
  2656. parse: function (str, callback, additionalData) {
  2657. var root, error = null, globalVars, modifyVars, ignored, preText = "";
  2658. globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : '';
  2659. modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + Parser.serializeVars(additionalData.modifyVars) : '';
  2660. if (context.pluginManager) {
  2661. var preProcessors = context.pluginManager.getPreProcessors();
  2662. for (var i = 0; i < preProcessors.length; i++) {
  2663. str = preProcessors[i].process(str, { context: context, imports: imports, fileInfo: fileInfo });
  2664. }
  2665. }
  2666. if (globalVars || (additionalData && additionalData.banner)) {
  2667. preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars;
  2668. ignored = imports.contentsIgnoredChars;
  2669. ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0;
  2670. ignored[fileInfo.filename] += preText.length;
  2671. }
  2672. str = str.replace(/\r\n?/g, '\n');
  2673. // Remove potential UTF Byte Order Mark
  2674. str = preText + str.replace(/^\uFEFF/, '') + modifyVars;
  2675. imports.contents[fileInfo.filename] = str;
  2676. // Start with the primary rule.
  2677. // The whole syntax tree is held under a Ruleset node,
  2678. // with the `root` property set to true, so no `{}` are
  2679. // output. The callback is called when the input is parsed.
  2680. try {
  2681. parserInput.start(str, context.chunkInput, function fail(msg, index) {
  2682. throw LessError({
  2683. index: index,
  2684. type: 'Parse',
  2685. message: msg,
  2686. filename: fileInfo.filename
  2687. }, imports);
  2688. });
  2689. root = new(tree.Ruleset)(null, this.parsers.primary());
  2690. root.root = true;
  2691. root.firstRoot = true;
  2692. } catch (e) {
  2693. return callback(new LessError(e, imports, fileInfo.filename));
  2694. }
  2695. // If `i` is smaller than the `input.length - 1`,
  2696. // it means the parser wasn't able to parse the whole
  2697. // string, so we've got a parsing error.
  2698. //
  2699. // We try to extract a \n delimited string,
  2700. // showing the line where the parse error occurred.
  2701. // We split it up into two parts (the part which parsed,
  2702. // and the part which didn't), so we can color them differently.
  2703. var endInfo = parserInput.end();
  2704. if (!endInfo.isFinished) {
  2705. var message = endInfo.furthestPossibleErrorMessage;
  2706. if (!message) {
  2707. message = "Unrecognised input";
  2708. if (endInfo.furthestChar === '}') {
  2709. message += ". Possibly missing opening '{'";
  2710. } else if (endInfo.furthestChar === ')') {
  2711. message += ". Possibly missing opening '('";
  2712. } else if (endInfo.furthestReachedEnd) {
  2713. message += ". Possibly missing something";
  2714. }
  2715. }
  2716. error = new LessError({
  2717. type: "Parse",
  2718. message: message,
  2719. index: endInfo.furthest,
  2720. filename: fileInfo.filename
  2721. }, imports);
  2722. }
  2723. var finish = function (e) {
  2724. e = error || e || imports.error;
  2725. if (e) {
  2726. if (!(e instanceof LessError)) {
  2727. e = new LessError(e, imports, fileInfo.filename);
  2728. }
  2729. return callback(e);
  2730. }
  2731. else {
  2732. return callback(null, root);
  2733. }
  2734. };
  2735. if (context.processImports !== false) {
  2736. new visitors.ImportVisitor(imports, finish)
  2737. .run(root);
  2738. } else {
  2739. return finish();
  2740. }
  2741. },
  2742. //
  2743. // Here in, the parsing rules/functions
  2744. //
  2745. // The basic structure of the syntax tree generated is as follows:
  2746. //
  2747. // Ruleset -> Rule -> Value -> Expression -> Entity
  2748. //
  2749. // Here's some Less code:
  2750. //
  2751. // .class {
  2752. // color: #fff;
  2753. // border: 1px solid #000;
  2754. // width: @w + 4px;
  2755. // > .child {...}
  2756. // }
  2757. //
  2758. // And here's what the parse tree might look like:
  2759. //
  2760. // Ruleset (Selector '.class', [
  2761. // Rule ("color", Value ([Expression [Color #fff]]))
  2762. // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
  2763. // Rule ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]]))
  2764. // Ruleset (Selector [Element '>', '.child'], [...])
  2765. // ])
  2766. //
  2767. // In general, most rules will try to parse a token with the `$()` function, and if the return
  2768. // value is truly, will return a new node, of the relevant type. Sometimes, we need to check
  2769. // first, before parsing, that's when we use `peek()`.
  2770. //
  2771. parsers: parsers = {
  2772. //
  2773. // The `primary` rule is the *entry* and *exit* point of the parser.
  2774. // The rules here can appear at any level of the parse tree.
  2775. //
  2776. // The recursive nature of the grammar is an interplay between the `block`
  2777. // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule,
  2778. // as represented by this simplified grammar:
  2779. //
  2780. // primary → (ruleset | rule)+
  2781. // ruleset → selector+ block
  2782. // block → '{' primary '}'
  2783. //
  2784. // Only at one point is the primary rule not called from the
  2785. // block rule: at the root level.
  2786. //
  2787. primary: function () {
  2788. var mixin = this.mixin, root = [], node;
  2789. while (true)
  2790. {
  2791. while (true) {
  2792. node = this.comment();
  2793. if (!node) { break; }
  2794. root.push(node);
  2795. }
  2796. // always process comments before deciding if finished
  2797. if (parserInput.finished) {
  2798. break;
  2799. }
  2800. if (parserInput.peek('}')) {
  2801. break;
  2802. }
  2803. node = this.extendRule();
  2804. if (node) {
  2805. root = root.concat(node);
  2806. continue;
  2807. }
  2808. node = mixin.definition() || this.rule() || this.ruleset() ||
  2809. mixin.call() || this.rulesetCall() || this.directive();
  2810. if (node) {
  2811. root.push(node);
  2812. } else {
  2813. if (!(parserInput.$re(/^[\s\n]+/) || parserInput.$re(/^;+/))) {
  2814. break;
  2815. }
  2816. }
  2817. }
  2818. return root;
  2819. },
  2820. // comments are collected by the main parsing mechanism and then assigned to nodes
  2821. // where the current structure allows it
  2822. comment: function () {
  2823. if (parserInput.commentStore.length) {
  2824. var comment = parserInput.commentStore.shift();
  2825. return new(tree.Comment)(comment.text, comment.isLineComment, comment.index, fileInfo);
  2826. }
  2827. },
  2828. //
  2829. // Entities are tokens which can be found inside an Expression
  2830. //
  2831. entities: {
  2832. //
  2833. // A string, which supports escaping " and '
  2834. //
  2835. // "milky way" 'he\'s the one!'
  2836. //
  2837. quoted: function () {
  2838. var str, index = parserInput.i;
  2839. str = parserInput.$re(/^(~)?("((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)')/);
  2840. if (str) {
  2841. return new(tree.Quoted)(str[2], str[3] || str[4], Boolean(str[1]), index, fileInfo);
  2842. }
  2843. },
  2844. //
  2845. // A catch-all word, such as:
  2846. //
  2847. // black border-collapse
  2848. //
  2849. keyword: function () {
  2850. var k = parserInput.$re(/^%|^[_A-Za-z-][_A-Za-z0-9-]*/);
  2851. if (k) {
  2852. return tree.Color.fromKeyword(k) || new(tree.Keyword)(k);
  2853. }
  2854. },
  2855. //
  2856. // A function call
  2857. //
  2858. // rgb(255, 0, 255)
  2859. //
  2860. // We also try to catch IE's `alpha()`, but let the `alpha` parser
  2861. // deal with the details.
  2862. //
  2863. // The arguments are parsed with the `entities.arguments` parser.
  2864. //
  2865. call: function () {
  2866. var name, nameLC, args, alpha, index = parserInput.i;
  2867. if (parserInput.peek(/^url\(/i)) {
  2868. return;
  2869. }
  2870. parserInput.save();
  2871. name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/);
  2872. if (!name) { parserInput.forget(); return; }
  2873. name = name[1];
  2874. nameLC = name.toLowerCase();
  2875. if (nameLC === 'alpha') {
  2876. alpha = parsers.alpha();
  2877. if (alpha) {
  2878. return alpha;
  2879. }
  2880. }
  2881. args = this.arguments();
  2882. if (! parserInput.$char(')')) {
  2883. parserInput.restore("Could not parse call arguments or missing ')'");
  2884. return;
  2885. }
  2886. parserInput.forget();
  2887. return new(tree.Call)(name, args, index, fileInfo);
  2888. },
  2889. arguments: function () {
  2890. var args = [], arg;
  2891. while (true) {
  2892. arg = this.assignment() || parsers.expression();
  2893. if (!arg) {
  2894. break;
  2895. }
  2896. args.push(arg);
  2897. if (! parserInput.$char(',')) {
  2898. break;
  2899. }
  2900. }
  2901. return args;
  2902. },
  2903. literal: function () {
  2904. return this.dimension() ||
  2905. this.color() ||
  2906. this.quoted() ||
  2907. this.unicodeDescriptor();
  2908. },
  2909. // Assignments are argument entities for calls.
  2910. // They are present in ie filter properties as shown below.
  2911. //
  2912. // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* )
  2913. //
  2914. assignment: function () {
  2915. var key, value;
  2916. key = parserInput.$re(/^\w+(?=\s?=)/i);
  2917. if (!key) {
  2918. return;
  2919. }
  2920. if (!parserInput.$char('=')) {
  2921. return;
  2922. }
  2923. value = parsers.entity();
  2924. if (value) {
  2925. return new(tree.Assignment)(key, value);
  2926. }
  2927. },
  2928. //
  2929. // Parse url() tokens
  2930. //
  2931. // We use a specific rule for urls, because they don't really behave like
  2932. // standard function calls. The difference is that the argument doesn't have
  2933. // to be enclosed within a string, so it can't be parsed as an Expression.
  2934. //
  2935. url: function () {
  2936. var value, index = parserInput.i;
  2937. parserInput.autoCommentAbsorb = false;
  2938. if (parserInput.currentChar() !== 'u' || !parserInput.$re(/^url\(/)) {
  2939. parserInput.autoCommentAbsorb = true;
  2940. return;
  2941. }
  2942. value = this.quoted() || this.variable() ||
  2943. parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || "";
  2944. parserInput.autoCommentAbsorb = true;
  2945. expectChar(')');
  2946. return new(tree.URL)((value.value != null || value instanceof tree.Variable) ?
  2947. value : new(tree.Anonymous)(value), index, fileInfo);
  2948. },
  2949. //
  2950. // A Variable entity, such as `@fink`, in
  2951. //
  2952. // width: @fink + 2px
  2953. //
  2954. // We use a different parser for variable definitions,
  2955. // see `parsers.variable`.
  2956. //
  2957. variable: function () {
  2958. var name, index = parserInput.i;
  2959. if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) {
  2960. return new(tree.Variable)(name, index, fileInfo);
  2961. }
  2962. },
  2963. // A variable entity useing the protective {} e.g. @{var}
  2964. variableCurly: function () {
  2965. var curly, index = parserInput.i;
  2966. if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) {
  2967. return new(tree.Variable)("@" + curly[1], index, fileInfo);
  2968. }
  2969. },
  2970. //
  2971. // A Hexadecimal color
  2972. //
  2973. // #4F3C2F
  2974. //
  2975. // `rgb` and `hsl` colors are parsed through the `entities.call` parser.
  2976. //
  2977. color: function () {
  2978. var rgb;
  2979. if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
  2980. // strip colons, brackets, whitespaces and other characters that should not
  2981. // definitely be part of color string
  2982. var colorCandidateString = rgb.input.match(/^#([\w]+).*/);
  2983. colorCandidateString = colorCandidateString[1];
  2984. if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
  2985. error("Invalid HEX color code");
  2986. }
  2987. return new(tree.Color)(rgb[1]);
  2988. }
  2989. },
  2990. //
  2991. // A Dimension, that is, a number and a unit
  2992. //
  2993. // 0.5em 95%
  2994. //
  2995. dimension: function () {
  2996. if (parserInput.peekNotNumeric()) {
  2997. return;
  2998. }
  2999. var value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/i);
  3000. if (value) {
  3001. return new(tree.Dimension)(value[1], value[2]);
  3002. }
  3003. },
  3004. //
  3005. // A unicode descriptor, as is used in unicode-range
  3006. //
  3007. // U+0?? or U+00A1-00A9
  3008. //
  3009. unicodeDescriptor: function () {
  3010. var ud;
  3011. ud = parserInput.$re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/);
  3012. if (ud) {
  3013. return new(tree.UnicodeDescriptor)(ud[0]);
  3014. }
  3015. },
  3016. //
  3017. // JavaScript code to be evaluated
  3018. //
  3019. // `window.location.href`
  3020. //
  3021. javascript: function () {
  3022. var js, index = parserInput.i;
  3023. js = parserInput.$re(/^(~)?`([^`]*)`/);
  3024. if (js) {
  3025. return new(tree.JavaScript)(js[2], Boolean(js[1]), index, fileInfo);
  3026. }
  3027. }
  3028. },
  3029. //
  3030. // The variable part of a variable definition. Used in the `rule` parser
  3031. //
  3032. // @fink:
  3033. //
  3034. variable: function () {
  3035. var name;
  3036. if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) { return name[1]; }
  3037. },
  3038. //
  3039. // The variable part of a variable definition. Used in the `rule` parser
  3040. //
  3041. // @fink();
  3042. //
  3043. rulesetCall: function () {
  3044. var name;
  3045. if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) {
  3046. return new tree.RulesetCall(name[1]);
  3047. }
  3048. },
  3049. //
  3050. // extend syntax - used to extend selectors
  3051. //
  3052. extend: function(isRule) {
  3053. var elements, e, index = parserInput.i, option, extendList, extend;
  3054. if (!(isRule ? parserInput.$re(/^&:extend\(/) : parserInput.$re(/^:extend\(/))) { return; }
  3055. do {
  3056. option = null;
  3057. elements = null;
  3058. while (! (option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
  3059. e = this.element();
  3060. if (!e) {
  3061. break;
  3062. }
  3063. if (elements) {
  3064. elements.push(e);
  3065. } else {
  3066. elements = [ e ];
  3067. }
  3068. }
  3069. option = option && option[1];
  3070. if (!elements) {
  3071. error("Missing target selector for :extend().");
  3072. }
  3073. extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
  3074. if (extendList) {
  3075. extendList.push(extend);
  3076. } else {
  3077. extendList = [ extend ];
  3078. }
  3079. } while (parserInput.$char(","));
  3080. expect(/^\)/);
  3081. if (isRule) {
  3082. expect(/^;/);
  3083. }
  3084. return extendList;
  3085. },
  3086. //
  3087. // extendRule - used in a rule to extend all the parent selectors
  3088. //
  3089. extendRule: function() {
  3090. return this.extend(true);
  3091. },
  3092. //
  3093. // Mixins
  3094. //
  3095. mixin: {
  3096. //
  3097. // A Mixin call, with an optional argument list
  3098. //
  3099. // #mixins > .square(#fff);
  3100. // .rounded(4px, black);
  3101. // .button;
  3102. //
  3103. // The `while` loop is there because mixins can be
  3104. // namespaced, but we only support the child and descendant
  3105. // selector for now.
  3106. //
  3107. call: function () {
  3108. var s = parserInput.currentChar(), important = false, index = parserInput.i, elemIndex,
  3109. elements, elem, e, c, args;
  3110. if (s !== '.' && s !== '#') { return; }
  3111. parserInput.save(); // stop us absorbing part of an invalid selector
  3112. while (true) {
  3113. elemIndex = parserInput.i;
  3114. e = parserInput.$re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/);
  3115. if (!e) {
  3116. break;
  3117. }
  3118. elem = new(tree.Element)(c, e, elemIndex, fileInfo);
  3119. if (elements) {
  3120. elements.push(elem);
  3121. } else {
  3122. elements = [ elem ];
  3123. }
  3124. c = parserInput.$char('>');
  3125. }
  3126. if (elements) {
  3127. if (parserInput.$char('(')) {
  3128. args = this.args(true).args;
  3129. expectChar(')');
  3130. }
  3131. if (parsers.important()) {
  3132. important = true;
  3133. }
  3134. if (parsers.end()) {
  3135. parserInput.forget();
  3136. return new(tree.mixin.Call)(elements, args, index, fileInfo, important);
  3137. }
  3138. }
  3139. parserInput.restore();
  3140. },
  3141. args: function (isCall) {
  3142. var entities = parsers.entities,
  3143. returner = { args:null, variadic: false },
  3144. expressions = [], argsSemiColon = [], argsComma = [],
  3145. isSemiColonSeparated, expressionContainsNamed, name, nameLoop, value, arg;
  3146. parserInput.save();
  3147. while (true) {
  3148. if (isCall) {
  3149. arg = parsers.detachedRuleset() || parsers.expression();
  3150. } else {
  3151. parserInput.commentStore.length = 0;
  3152. if (parserInput.currentChar() === '.' && parserInput.$re(/^\.{3}/)) {
  3153. returner.variadic = true;
  3154. if (parserInput.$char(";") && !isSemiColonSeparated) {
  3155. isSemiColonSeparated = true;
  3156. }
  3157. (isSemiColonSeparated ? argsSemiColon : argsComma)
  3158. .push({ variadic: true });
  3159. break;
  3160. }
  3161. arg = entities.variable() || entities.literal() || entities.keyword();
  3162. }
  3163. if (!arg) {
  3164. break;
  3165. }
  3166. nameLoop = null;
  3167. if (arg.throwAwayComments) {
  3168. arg.throwAwayComments();
  3169. }
  3170. value = arg;
  3171. var val = null;
  3172. if (isCall) {
  3173. // Variable
  3174. if (arg.value && arg.value.length == 1) {
  3175. val = arg.value[0];
  3176. }
  3177. } else {
  3178. val = arg;
  3179. }
  3180. if (val && val instanceof tree.Variable) {
  3181. if (parserInput.$char(':')) {
  3182. if (expressions.length > 0) {
  3183. if (isSemiColonSeparated) {
  3184. error("Cannot mix ; and , as delimiter types");
  3185. }
  3186. expressionContainsNamed = true;
  3187. }
  3188. // we do not support setting a ruleset as a default variable - it doesn't make sense
  3189. // However if we do want to add it, there is nothing blocking it, just don't error
  3190. // and remove isCall dependency below
  3191. value = (isCall && parsers.detachedRuleset()) || parsers.expression();
  3192. if (!value) {
  3193. if (isCall) {
  3194. error("could not understand value for named argument");
  3195. } else {
  3196. parserInput.restore();
  3197. returner.args = [];
  3198. return returner;
  3199. }
  3200. }
  3201. nameLoop = (name = val.name);
  3202. } else if (!isCall && parserInput.$re(/^\.{3}/)) {
  3203. returner.variadic = true;
  3204. if (parserInput.$char(";") && !isSemiColonSeparated) {
  3205. isSemiColonSeparated = true;
  3206. }
  3207. (isSemiColonSeparated ? argsSemiColon : argsComma)
  3208. .push({ name: arg.name, variadic: true });
  3209. break;
  3210. } else if (!isCall) {
  3211. name = nameLoop = val.name;
  3212. value = null;
  3213. }
  3214. }
  3215. if (value) {
  3216. expressions.push(value);
  3217. }
  3218. argsComma.push({ name:nameLoop, value:value });
  3219. if (parserInput.$char(',')) {
  3220. continue;
  3221. }
  3222. if (parserInput.$char(';') || isSemiColonSeparated) {
  3223. if (expressionContainsNamed) {
  3224. error("Cannot mix ; and , as delimiter types");
  3225. }
  3226. isSemiColonSeparated = true;
  3227. if (expressions.length > 1) {
  3228. value = new(tree.Value)(expressions);
  3229. }
  3230. argsSemiColon.push({ name:name, value:value });
  3231. name = null;
  3232. expressions = [];
  3233. expressionContainsNamed = false;
  3234. }
  3235. }
  3236. parserInput.forget();
  3237. returner.args = isSemiColonSeparated ? argsSemiColon : argsComma;
  3238. return returner;
  3239. },
  3240. //
  3241. // A Mixin definition, with a list of parameters
  3242. //
  3243. // .rounded (@radius: 2px, @color) {
  3244. // ...
  3245. // }
  3246. //
  3247. // Until we have a finer grained state-machine, we have to
  3248. // do a look-ahead, to make sure we don't have a mixin call.
  3249. // See the `rule` function for more information.
  3250. //
  3251. // We start by matching `.rounded (`, and then proceed on to
  3252. // the argument list, which has optional default values.
  3253. // We store the parameters in `params`, with a `value` key,
  3254. // if there is a value, such as in the case of `@radius`.
  3255. //
  3256. // Once we've got our params list, and a closing `)`, we parse
  3257. // the `{...}` block.
  3258. //
  3259. definition: function () {
  3260. var name, params = [], match, ruleset, cond, variadic = false;
  3261. if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
  3262. parserInput.peek(/^[^{]*\}/)) {
  3263. return;
  3264. }
  3265. parserInput.save();
  3266. match = parserInput.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
  3267. if (match) {
  3268. name = match[1];
  3269. var argInfo = this.args(false);
  3270. params = argInfo.args;
  3271. variadic = argInfo.variadic;
  3272. // .mixincall("@{a}");
  3273. // looks a bit like a mixin definition..
  3274. // also
  3275. // .mixincall(@a: {rule: set;});
  3276. // so we have to be nice and restore
  3277. if (!parserInput.$char(')')) {
  3278. parserInput.restore("Missing closing ')'");
  3279. return;
  3280. }
  3281. parserInput.commentStore.length = 0;
  3282. if (parserInput.$re(/^when/)) { // Guard
  3283. cond = expect(parsers.conditions, 'expected condition');
  3284. }
  3285. ruleset = parsers.block();
  3286. if (ruleset) {
  3287. parserInput.forget();
  3288. return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
  3289. } else {
  3290. parserInput.restore();
  3291. }
  3292. } else {
  3293. parserInput.forget();
  3294. }
  3295. }
  3296. },
  3297. //
  3298. // Entities are the smallest recognized token,
  3299. // and can be found inside a rule's value.
  3300. //
  3301. entity: function () {
  3302. var entities = this.entities;
  3303. return this.comment() || entities.literal() || entities.variable() || entities.url() ||
  3304. entities.call() || entities.keyword() || entities.javascript();
  3305. },
  3306. //
  3307. // A Rule terminator. Note that we use `peek()` to check for '}',
  3308. // because the `block` rule will be expecting it, but we still need to make sure
  3309. // it's there, if ';' was ommitted.
  3310. //
  3311. end: function () {
  3312. return parserInput.$char(';') || parserInput.peek('}');
  3313. },
  3314. //
  3315. // IE's alpha function
  3316. //
  3317. // alpha(opacity=88)
  3318. //
  3319. alpha: function () {
  3320. var value;
  3321. if (! parserInput.$re(/^opacity=/i)) { return; }
  3322. value = parserInput.$re(/^\d+/);
  3323. if (!value) {
  3324. value = expect(this.entities.variable, "Could not parse alpha");
  3325. }
  3326. expectChar(')');
  3327. return new(tree.Alpha)(value);
  3328. },
  3329. //
  3330. // A Selector Element
  3331. //
  3332. // div
  3333. // + h1
  3334. // #socks
  3335. // input[type="text"]
  3336. //
  3337. // Elements are the building blocks for Selectors,
  3338. // they are made out of a `Combinator` (see combinator rule),
  3339. // and an element name, such as a tag a class, or `*`.
  3340. //
  3341. element: function () {
  3342. var e, c, v, index = parserInput.i;
  3343. c = this.combinator();
  3344. e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
  3345. parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
  3346. parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
  3347. parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
  3348. this.entities.variableCurly();
  3349. if (! e) {
  3350. parserInput.save();
  3351. if (parserInput.$char('(')) {
  3352. if ((v = this.selector()) && parserInput.$char(')')) {
  3353. e = new(tree.Paren)(v);
  3354. parserInput.forget();
  3355. } else {
  3356. parserInput.restore("Missing closing ')'");
  3357. }
  3358. } else {
  3359. parserInput.forget();
  3360. }
  3361. }
  3362. if (e) { return new(tree.Element)(c, e, index, fileInfo); }
  3363. },
  3364. //
  3365. // Combinators combine elements together, in a Selector.
  3366. //
  3367. // Because our parser isn't white-space sensitive, special care
  3368. // has to be taken, when parsing the descendant combinator, ` `,
  3369. // as it's an empty space. We have to check the previous character
  3370. // in the input, to see if it's a ` ` character. More info on how
  3371. // we deal with this in *combinator.js*.
  3372. //
  3373. combinator: function () {
  3374. var c = parserInput.currentChar();
  3375. if (c === '/') {
  3376. parserInput.save();
  3377. var slashedCombinator = parserInput.$re(/^\/[a-z]+\//i);
  3378. if (slashedCombinator) {
  3379. parserInput.forget();
  3380. return new(tree.Combinator)(slashedCombinator);
  3381. }
  3382. parserInput.restore();
  3383. }
  3384. if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') {
  3385. parserInput.i++;
  3386. if (c === '^' && parserInput.currentChar() === '^') {
  3387. c = '^^';
  3388. parserInput.i++;
  3389. }
  3390. while (parserInput.isWhitespace()) { parserInput.i++; }
  3391. return new(tree.Combinator)(c);
  3392. } else if (parserInput.isWhitespace(-1)) {
  3393. return new(tree.Combinator)(" ");
  3394. } else {
  3395. return new(tree.Combinator)(null);
  3396. }
  3397. },
  3398. //
  3399. // A CSS selector (see selector below)
  3400. // with less extensions e.g. the ability to extend and guard
  3401. //
  3402. lessSelector: function () {
  3403. return this.selector(true);
  3404. },
  3405. //
  3406. // A CSS Selector
  3407. //
  3408. // .class > div + h1
  3409. // li a:hover
  3410. //
  3411. // Selectors are made out of one or more Elements, see above.
  3412. //
  3413. selector: function (isLess) {
  3414. var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition;
  3415. while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$re(/^when/))) || (e = this.element())) {
  3416. if (when) {
  3417. condition = expect(this.conditions, 'expected condition');
  3418. } else if (condition) {
  3419. error("CSS guard can only be used at the end of selector");
  3420. } else if (extendList) {
  3421. if (allExtends) {
  3422. allExtends = allExtends.concat(extendList);
  3423. } else {
  3424. allExtends = extendList;
  3425. }
  3426. } else {
  3427. if (allExtends) { error("Extend can only be used at the end of selector"); }
  3428. c = parserInput.currentChar();
  3429. if (elements) {
  3430. elements.push(e);
  3431. } else {
  3432. elements = [ e ];
  3433. }
  3434. e = null;
  3435. }
  3436. if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') {
  3437. break;
  3438. }
  3439. }
  3440. if (elements) { return new(tree.Selector)(elements, allExtends, condition, index, fileInfo); }
  3441. if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); }
  3442. },
  3443. attribute: function () {
  3444. if (! parserInput.$char('[')) { return; }
  3445. var entities = this.entities,
  3446. key, val, op;
  3447. if (!(key = entities.variableCurly())) {
  3448. key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/);
  3449. }
  3450. op = parserInput.$re(/^[|~*$^]?=/);
  3451. if (op) {
  3452. val = entities.quoted() || parserInput.$re(/^[0-9]+%/) || parserInput.$re(/^[\w-]+/) || entities.variableCurly();
  3453. }
  3454. expectChar(']');
  3455. return new(tree.Attribute)(key, op, val);
  3456. },
  3457. //
  3458. // The `block` rule is used by `ruleset` and `mixin.definition`.
  3459. // It's a wrapper around the `primary` rule, with added `{}`.
  3460. //
  3461. block: function () {
  3462. var content;
  3463. if (parserInput.$char('{') && (content = this.primary()) && parserInput.$char('}')) {
  3464. return content;
  3465. }
  3466. },
  3467. blockRuleset: function() {
  3468. var block = this.block();
  3469. if (block) {
  3470. block = new tree.Ruleset(null, block);
  3471. }
  3472. return block;
  3473. },
  3474. detachedRuleset: function() {
  3475. var blockRuleset = this.blockRuleset();
  3476. if (blockRuleset) {
  3477. return new tree.DetachedRuleset(blockRuleset);
  3478. }
  3479. },
  3480. //
  3481. // div, .class, body > p {...}
  3482. //
  3483. ruleset: function () {
  3484. var selectors, s, rules, debugInfo;
  3485. parserInput.save();
  3486. if (context.dumpLineNumbers) {
  3487. debugInfo = getDebugInfo(parserInput.i);
  3488. }
  3489. while (true) {
  3490. s = this.lessSelector();
  3491. if (!s) {
  3492. break;
  3493. }
  3494. if (selectors) {
  3495. selectors.push(s);
  3496. } else {
  3497. selectors = [ s ];
  3498. }
  3499. parserInput.commentStore.length = 0;
  3500. if (s.condition && selectors.length > 1) {
  3501. error("Guards are only currently allowed on a single selector.");
  3502. }
  3503. if (! parserInput.$char(',')) { break; }
  3504. if (s.condition) {
  3505. error("Guards are only currently allowed on a single selector.");
  3506. }
  3507. parserInput.commentStore.length = 0;
  3508. }
  3509. if (selectors && (rules = this.block())) {
  3510. parserInput.forget();
  3511. var ruleset = new(tree.Ruleset)(selectors, rules, context.strictImports);
  3512. if (context.dumpLineNumbers) {
  3513. ruleset.debugInfo = debugInfo;
  3514. }
  3515. return ruleset;
  3516. } else {
  3517. parserInput.restore();
  3518. }
  3519. },
  3520. rule: function (tryAnonymous) {
  3521. var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable;
  3522. if (c === '.' || c === '#' || c === '&') { return; }
  3523. parserInput.save();
  3524. name = this.variable() || this.ruleProperty();
  3525. if (name) {
  3526. isVariable = typeof name === "string";
  3527. if (isVariable) {
  3528. value = this.detachedRuleset();
  3529. }
  3530. parserInput.commentStore.length = 0;
  3531. if (!value) {
  3532. // a name returned by this.ruleProperty() is always an array of the form:
  3533. // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
  3534. // where each item is a tree.Keyword or tree.Variable
  3535. merge = !isVariable && name.pop().value;
  3536. // prefer to try to parse first if its a variable or we are compressing
  3537. // but always fallback on the other one
  3538. var tryValueFirst = !tryAnonymous && (context.compress || isVariable);
  3539. if (tryValueFirst) {
  3540. value = this.value();
  3541. }
  3542. if (!value) {
  3543. value = this.anonymousValue();
  3544. if (value) {
  3545. parserInput.forget();
  3546. // anonymous values absorb the end ';' which is reequired for them to work
  3547. return new (tree.Rule)(name, value, false, merge, startOfRule, fileInfo);
  3548. }
  3549. }
  3550. if (!tryValueFirst && !value) {
  3551. value = this.value();
  3552. }
  3553. important = this.important();
  3554. }
  3555. if (value && this.end()) {
  3556. parserInput.forget();
  3557. return new (tree.Rule)(name, value, important, merge, startOfRule, fileInfo);
  3558. } else {
  3559. parserInput.restore();
  3560. if (value && !tryAnonymous) {
  3561. return this.rule(true);
  3562. }
  3563. }
  3564. } else {
  3565. parserInput.forget();
  3566. }
  3567. },
  3568. anonymousValue: function () {
  3569. var match = parserInput.$re(/^([^@+\/'"*`(;{}-]*);/);
  3570. if (match) {
  3571. return new(tree.Anonymous)(match[1]);
  3572. }
  3573. },
  3574. //
  3575. // An @import directive
  3576. //
  3577. // @import "lib";
  3578. //
  3579. // Depending on our environment, importing is done differently:
  3580. // In the browser, it's an XHR request, in Node, it would be a
  3581. // file-system operation. The function used for importing is
  3582. // stored in `import`, which we pass to the Import constructor.
  3583. //
  3584. "import": function () {
  3585. var path, features, index = parserInput.i;
  3586. var dir = parserInput.$re(/^@import?\s+/);
  3587. if (dir) {
  3588. var options = (dir ? this.importOptions() : null) || {};
  3589. if ((path = this.entities.quoted() || this.entities.url())) {
  3590. features = this.mediaFeatures();
  3591. if (!parserInput.$(';')) {
  3592. parserInput.i = index;
  3593. error("missing semi-colon or unrecognised media features on import");
  3594. }
  3595. features = features && new(tree.Value)(features);
  3596. return new(tree.Import)(path, features, options, index, fileInfo);
  3597. }
  3598. else
  3599. {
  3600. parserInput.i = index;
  3601. error("malformed import statement");
  3602. }
  3603. }
  3604. },
  3605. importOptions: function() {
  3606. var o, options = {}, optionName, value;
  3607. // list of options, surrounded by parens
  3608. if (! parserInput.$char('(')) { return null; }
  3609. do {
  3610. o = this.importOption();
  3611. if (o) {
  3612. optionName = o;
  3613. value = true;
  3614. switch(optionName) {
  3615. case "css":
  3616. optionName = "less";
  3617. value = false;
  3618. break;
  3619. case "once":
  3620. optionName = "multiple";
  3621. value = false;
  3622. break;
  3623. }
  3624. options[optionName] = value;
  3625. if (! parserInput.$char(',')) { break; }
  3626. }
  3627. } while (o);
  3628. expectChar(')');
  3629. return options;
  3630. },
  3631. importOption: function() {
  3632. var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
  3633. if (opt) {
  3634. return opt[1];
  3635. }
  3636. },
  3637. mediaFeature: function () {
  3638. var entities = this.entities, nodes = [], e, p;
  3639. parserInput.save();
  3640. do {
  3641. e = entities.keyword() || entities.variable();
  3642. if (e) {
  3643. nodes.push(e);
  3644. } else if (parserInput.$char('(')) {
  3645. p = this.property();
  3646. e = this.value();
  3647. if (parserInput.$char(')')) {
  3648. if (p && e) {
  3649. nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, parserInput.i, fileInfo, true)));
  3650. } else if (e) {
  3651. nodes.push(new(tree.Paren)(e));
  3652. } else {
  3653. parserInput.restore("badly formed media feature definition");
  3654. return null;
  3655. }
  3656. } else {
  3657. parserInput.restore("Missing closing ')'");
  3658. return null;
  3659. }
  3660. }
  3661. } while (e);
  3662. parserInput.forget();
  3663. if (nodes.length > 0) {
  3664. return new(tree.Expression)(nodes);
  3665. }
  3666. },
  3667. mediaFeatures: function () {
  3668. var entities = this.entities, features = [], e;
  3669. do {
  3670. e = this.mediaFeature();
  3671. if (e) {
  3672. features.push(e);
  3673. if (! parserInput.$char(',')) { break; }
  3674. } else {
  3675. e = entities.variable();
  3676. if (e) {
  3677. features.push(e);
  3678. if (! parserInput.$char(',')) { break; }
  3679. }
  3680. }
  3681. } while (e);
  3682. return features.length > 0 ? features : null;
  3683. },
  3684. media: function () {
  3685. var features, rules, media, debugInfo;
  3686. if (context.dumpLineNumbers) {
  3687. debugInfo = getDebugInfo(parserInput.i);
  3688. }
  3689. if (parserInput.$re(/^@media/)) {
  3690. features = this.mediaFeatures();
  3691. rules = this.block();
  3692. if (rules) {
  3693. media = new(tree.Media)(rules, features, parserInput.i, fileInfo);
  3694. if (context.dumpLineNumbers) {
  3695. media.debugInfo = debugInfo;
  3696. }
  3697. return media;
  3698. }
  3699. }
  3700. },
  3701. //
  3702. // A CSS Directive
  3703. //
  3704. // @charset "utf-8";
  3705. //
  3706. directive: function () {
  3707. var index = parserInput.i, name, value, rules, nonVendorSpecificName,
  3708. hasIdentifier, hasExpression, hasUnknown, hasBlock = true;
  3709. if (parserInput.currentChar() !== '@') { return; }
  3710. value = this['import']() || this.media();
  3711. if (value) {
  3712. return value;
  3713. }
  3714. parserInput.save();
  3715. name = parserInput.$re(/^@[a-z-]+/);
  3716. if (!name) { return; }
  3717. nonVendorSpecificName = name;
  3718. if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
  3719. nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1);
  3720. }
  3721. switch(nonVendorSpecificName) {
  3722. /*
  3723. case "@font-face":
  3724. case "@viewport":
  3725. case "@top-left":
  3726. case "@top-left-corner":
  3727. case "@top-center":
  3728. case "@top-right":
  3729. case "@top-right-corner":
  3730. case "@bottom-left":
  3731. case "@bottom-left-corner":
  3732. case "@bottom-center":
  3733. case "@bottom-right":
  3734. case "@bottom-right-corner":
  3735. case "@left-top":
  3736. case "@left-middle":
  3737. case "@left-bottom":
  3738. case "@right-top":
  3739. case "@right-middle":
  3740. case "@right-bottom":
  3741. hasBlock = true;
  3742. break;
  3743. */
  3744. case "@counter-style":
  3745. hasIdentifier = true;
  3746. hasBlock = true;
  3747. break;
  3748. case "@charset":
  3749. hasIdentifier = true;
  3750. hasBlock = false;
  3751. break;
  3752. case "@namespace":
  3753. hasExpression = true;
  3754. hasBlock = false;
  3755. break;
  3756. case "@keyframes":
  3757. hasIdentifier = true;
  3758. break;
  3759. case "@host":
  3760. case "@page":
  3761. case "@document":
  3762. case "@supports":
  3763. hasUnknown = true;
  3764. break;
  3765. }
  3766. parserInput.commentStore.length = 0;
  3767. if (hasIdentifier) {
  3768. value = this.entity();
  3769. if (!value) {
  3770. error("expected " + name + " identifier");
  3771. }
  3772. } else if (hasExpression) {
  3773. value = this.expression();
  3774. if (!value) {
  3775. error("expected " + name + " expression");
  3776. }
  3777. } else if (hasUnknown) {
  3778. value = (parserInput.$re(/^[^{;]+/) || '').trim();
  3779. if (value) {
  3780. value = new(tree.Anonymous)(value);
  3781. }
  3782. }
  3783. if (hasBlock) {
  3784. rules = this.blockRuleset();
  3785. }
  3786. if (rules || (!hasBlock && value && parserInput.$char(';'))) {
  3787. parserInput.forget();
  3788. return new(tree.Directive)(name, value, rules, index, fileInfo,
  3789. context.dumpLineNumbers ? getDebugInfo(index) : null);
  3790. }
  3791. parserInput.restore("directive options not recognised");
  3792. },
  3793. //
  3794. // A Value is a comma-delimited list of Expressions
  3795. //
  3796. // font-family: Baskerville, Georgia, serif;
  3797. //
  3798. // In a Rule, a Value represents everything after the `:`,
  3799. // and before the `;`.
  3800. //
  3801. value: function () {
  3802. var e, expressions = [];
  3803. do {
  3804. e = this.expression();
  3805. if (e) {
  3806. expressions.push(e);
  3807. if (! parserInput.$char(',')) { break; }
  3808. }
  3809. } while (e);
  3810. if (expressions.length > 0) {
  3811. return new(tree.Value)(expressions);
  3812. }
  3813. },
  3814. important: function () {
  3815. if (parserInput.currentChar() === '!') {
  3816. return parserInput.$re(/^! *important/);
  3817. }
  3818. },
  3819. sub: function () {
  3820. var a, e;
  3821. parserInput.save();
  3822. if (parserInput.$char('(')) {
  3823. a = this.addition();
  3824. if (a && parserInput.$char(')')) {
  3825. parserInput.forget();
  3826. e = new(tree.Expression)([a]);
  3827. e.parens = true;
  3828. return e;
  3829. }
  3830. parserInput.restore("Expected ')'");
  3831. return;
  3832. }
  3833. parserInput.restore();
  3834. },
  3835. multiplication: function () {
  3836. var m, a, op, operation, isSpaced;
  3837. m = this.operand();
  3838. if (m) {
  3839. isSpaced = parserInput.isWhitespace(-1);
  3840. while (true) {
  3841. if (parserInput.peek(/^\/[*\/]/)) {
  3842. break;
  3843. }
  3844. parserInput.save();
  3845. op = parserInput.$char('/') || parserInput.$char('*');
  3846. if (!op) { parserInput.forget(); break; }
  3847. a = this.operand();
  3848. if (!a) { parserInput.restore(); break; }
  3849. parserInput.forget();
  3850. m.parensInOp = true;
  3851. a.parensInOp = true;
  3852. operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
  3853. isSpaced = parserInput.isWhitespace(-1);
  3854. }
  3855. return operation || m;
  3856. }
  3857. },
  3858. addition: function () {
  3859. var m, a, op, operation, isSpaced;
  3860. m = this.multiplication();
  3861. if (m) {
  3862. isSpaced = parserInput.isWhitespace(-1);
  3863. while (true) {
  3864. op = parserInput.$re(/^[-+]\s+/) || (!isSpaced && (parserInput.$char('+') || parserInput.$char('-')));
  3865. if (!op) {
  3866. break;
  3867. }
  3868. a = this.multiplication();
  3869. if (!a) {
  3870. break;
  3871. }
  3872. m.parensInOp = true;
  3873. a.parensInOp = true;
  3874. operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
  3875. isSpaced = parserInput.isWhitespace(-1);
  3876. }
  3877. return operation || m;
  3878. }
  3879. },
  3880. conditions: function () {
  3881. var a, b, index = parserInput.i, condition;
  3882. a = this.condition();
  3883. if (a) {
  3884. while (true) {
  3885. if (!parserInput.peek(/^,\s*(not\s*)?\(/) || !parserInput.$char(',')) {
  3886. break;
  3887. }
  3888. b = this.condition();
  3889. if (!b) {
  3890. break;
  3891. }
  3892. condition = new(tree.Condition)('or', condition || a, b, index);
  3893. }
  3894. return condition || a;
  3895. }
  3896. },
  3897. condition: function () {
  3898. var entities = this.entities, index = parserInput.i, negate = false,
  3899. a, b, c, op;
  3900. if (parserInput.$re(/^not/)) { negate = true; }
  3901. expectChar('(');
  3902. a = this.addition() || entities.keyword() || entities.quoted();
  3903. if (a) {
  3904. op = parserInput.$re(/^(?:>=|<=|=<|[<=>])/);
  3905. if (op) {
  3906. b = this.addition() || entities.keyword() || entities.quoted();
  3907. if (b) {
  3908. c = new(tree.Condition)(op, a, b, index, negate);
  3909. } else {
  3910. error('expected expression');
  3911. }
  3912. } else {
  3913. c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate);
  3914. }
  3915. expectChar(')');
  3916. return parserInput.$re(/^and/) ? new(tree.Condition)('and', c, this.condition()) : c;
  3917. }
  3918. },
  3919. //
  3920. // An operand is anything that can be part of an operation,
  3921. // such as a Color, or a Variable
  3922. //
  3923. operand: function () {
  3924. var entities = this.entities, negate;
  3925. if (parserInput.peek(/^-[@\(]/)) {
  3926. negate = parserInput.$char('-');
  3927. }
  3928. var o = this.sub() || entities.dimension() ||
  3929. entities.color() || entities.variable() ||
  3930. entities.call();
  3931. if (negate) {
  3932. o.parensInOp = true;
  3933. o = new(tree.Negative)(o);
  3934. }
  3935. return o;
  3936. },
  3937. //
  3938. // Expressions either represent mathematical operations,
  3939. // or white-space delimited Entities.
  3940. //
  3941. // 1px solid black
  3942. // @var * 2
  3943. //
  3944. expression: function () {
  3945. var entities = [], e, delim;
  3946. do {
  3947. e = this.comment();
  3948. if (e) {
  3949. entities.push(e);
  3950. continue;
  3951. }
  3952. e = this.addition() || this.entity();
  3953. if (e) {
  3954. entities.push(e);
  3955. // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here
  3956. if (!parserInput.peek(/^\/[\/*]/)) {
  3957. delim = parserInput.$char('/');
  3958. if (delim) {
  3959. entities.push(new(tree.Anonymous)(delim));
  3960. }
  3961. }
  3962. }
  3963. } while (e);
  3964. if (entities.length > 0) {
  3965. return new(tree.Expression)(entities);
  3966. }
  3967. },
  3968. property: function () {
  3969. var name = parserInput.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);
  3970. if (name) {
  3971. return name[1];
  3972. }
  3973. },
  3974. ruleProperty: function () {
  3975. var name = [], index = [], s, k;
  3976. parserInput.save();
  3977. function match(re) {
  3978. var i = parserInput.i,
  3979. chunk = parserInput.$re(re);
  3980. if (chunk) {
  3981. index.push(i);
  3982. return name.push(chunk[1]);
  3983. }
  3984. }
  3985. match(/^(\*?)/);
  3986. while (true) {
  3987. if (!match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)) {
  3988. break;
  3989. }
  3990. }
  3991. if ((name.length > 1) && match(/^((?:\+_|\+)?)\s*:/)) {
  3992. parserInput.forget();
  3993. // at last, we have the complete match now. move forward,
  3994. // convert name particles to tree objects and return:
  3995. if (name[0] === '') {
  3996. name.shift();
  3997. index.shift();
  3998. }
  3999. for (k = 0; k < name.length; k++) {
  4000. s = name[k];
  4001. name[k] = (s.charAt(0) !== '@') ?
  4002. new(tree.Keyword)(s) :
  4003. new(tree.Variable)('@' + s.slice(2, -1),
  4004. index[k], fileInfo);
  4005. }
  4006. return name;
  4007. }
  4008. parserInput.restore();
  4009. }
  4010. }
  4011. };
  4012. };
  4013. Parser.serializeVars = function(vars) {
  4014. var s = '';
  4015. for (var name in vars) {
  4016. if (Object.hasOwnProperty.call(vars, name)) {
  4017. var value = vars[name];
  4018. s += ((name[0] === '@') ? '' : '@') + name + ': ' + value +
  4019. ((String(value).slice(-1) === ';') ? '' : ';');
  4020. }
  4021. }
  4022. return s;
  4023. };
  4024. module.exports = Parser;
  4025. },{"../less-error":30,"../tree":59,"../utils":80,"../visitors":84,"./parser-input":35}],37:[function(require,module,exports){
  4026. /**
  4027. * Plugin Manager
  4028. */
  4029. var PluginManager = function(less) {
  4030. this.less = less;
  4031. this.visitors = [];
  4032. this.preProcessors = [];
  4033. this.postProcessors = [];
  4034. this.installedPlugins = [];
  4035. this.fileManagers = [];
  4036. };
  4037. /**
  4038. * Adds all the plugins in the array
  4039. * @param {Array} plugins
  4040. */
  4041. PluginManager.prototype.addPlugins = function(plugins) {
  4042. if (plugins) {
  4043. for (var i = 0; i < plugins.length; i++) {
  4044. this.addPlugin(plugins[i]);
  4045. }
  4046. }
  4047. };
  4048. /**
  4049. *
  4050. * @param plugin
  4051. */
  4052. PluginManager.prototype.addPlugin = function(plugin) {
  4053. this.installedPlugins.push(plugin);
  4054. plugin.install(this.less, this);
  4055. };
  4056. /**
  4057. * Adds a visitor. The visitor object has options on itself to determine
  4058. * when it should run.
  4059. * @param visitor
  4060. */
  4061. PluginManager.prototype.addVisitor = function(visitor) {
  4062. this.visitors.push(visitor);
  4063. };
  4064. /**
  4065. * Adds a pre processor object
  4066. * @param {object} preProcessor
  4067. * @param {number} priority - guidelines 1 = before import, 1000 = import, 2000 = after import
  4068. */
  4069. PluginManager.prototype.addPreProcessor = function(preProcessor, priority) {
  4070. var indexToInsertAt;
  4071. for (indexToInsertAt = 0; indexToInsertAt < this.preProcessors.length; indexToInsertAt++) {
  4072. if (this.preProcessors[indexToInsertAt].priority >= priority) {
  4073. break;
  4074. }
  4075. }
  4076. this.preProcessors.splice(indexToInsertAt, 0, {preProcessor: preProcessor, priority: priority});
  4077. };
  4078. /**
  4079. * Adds a post processor object
  4080. * @param {object} postProcessor
  4081. * @param {number} priority - guidelines 1 = before compression, 1000 = compression, 2000 = after compression
  4082. */
  4083. PluginManager.prototype.addPostProcessor = function(postProcessor, priority) {
  4084. var indexToInsertAt;
  4085. for (indexToInsertAt = 0; indexToInsertAt < this.postProcessors.length; indexToInsertAt++) {
  4086. if (this.postProcessors[indexToInsertAt].priority >= priority) {
  4087. break;
  4088. }
  4089. }
  4090. this.postProcessors.splice(indexToInsertAt, 0, {postProcessor: postProcessor, priority: priority});
  4091. };
  4092. /**
  4093. *
  4094. * @param manager
  4095. */
  4096. PluginManager.prototype.addFileManager = function(manager) {
  4097. this.fileManagers.push(manager);
  4098. };
  4099. /**
  4100. *
  4101. * @returns {Array}
  4102. * @private
  4103. */
  4104. PluginManager.prototype.getPreProcessors = function() {
  4105. var preProcessors = [];
  4106. for (var i = 0; i < this.preProcessors.length; i++) {
  4107. preProcessors.push(this.preProcessors[i].preProcessor);
  4108. }
  4109. return preProcessors;
  4110. };
  4111. /**
  4112. *
  4113. * @returns {Array}
  4114. * @private
  4115. */
  4116. PluginManager.prototype.getPostProcessors = function() {
  4117. var postProcessors = [];
  4118. for (var i = 0; i < this.postProcessors.length; i++) {
  4119. postProcessors.push(this.postProcessors[i].postProcessor);
  4120. }
  4121. return postProcessors;
  4122. };
  4123. /**
  4124. *
  4125. * @returns {Array}
  4126. * @private
  4127. */
  4128. PluginManager.prototype.getVisitors = function() {
  4129. return this.visitors;
  4130. };
  4131. /**
  4132. *
  4133. * @returns {Array}
  4134. * @private
  4135. */
  4136. PluginManager.prototype.getFileManagers = function() {
  4137. return this.fileManagers;
  4138. };
  4139. module.exports = PluginManager;
  4140. },{}],38:[function(require,module,exports){
  4141. var PromiseConstructor;
  4142. module.exports = function(environment, ParseTree, ImportManager) {
  4143. var render = function (input, options, callback) {
  4144. if (typeof options === 'function') {
  4145. callback = options;
  4146. options = {};
  4147. }
  4148. if (!callback) {
  4149. if (!PromiseConstructor) {
  4150. PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
  4151. }
  4152. var self = this;
  4153. return new PromiseConstructor(function (resolve, reject) {
  4154. render.call(self, input, options, function(err, output) {
  4155. if (err) {
  4156. reject(err);
  4157. } else {
  4158. resolve(output);
  4159. }
  4160. });
  4161. });
  4162. } else {
  4163. this.parse(input, options, function(err, root, imports, options) {
  4164. if (err) { return callback(err); }
  4165. var result;
  4166. try {
  4167. var parseTree = new ParseTree(root, imports);
  4168. result = parseTree.toCSS(options);
  4169. }
  4170. catch (err) { return callback(err); }
  4171. callback(null, result);
  4172. });
  4173. }
  4174. };
  4175. return render;
  4176. };
  4177. },{"promise":undefined}],39:[function(require,module,exports){
  4178. module.exports = function (SourceMapOutput, environment) {
  4179. var SourceMapBuilder = function (options) {
  4180. this.options = options;
  4181. };
  4182. SourceMapBuilder.prototype.toCSS = function(rootNode, options, imports) {
  4183. var sourceMapOutput = new SourceMapOutput(
  4184. {
  4185. contentsIgnoredCharsMap: imports.contentsIgnoredChars,
  4186. rootNode: rootNode,
  4187. contentsMap: imports.contents,
  4188. sourceMapFilename: this.options.sourceMapFilename,
  4189. sourceMapURL: this.options.sourceMapURL,
  4190. outputFilename: this.options.sourceMapOutputFilename,
  4191. sourceMapBasepath: this.options.sourceMapBasepath,
  4192. sourceMapRootpath: this.options.sourceMapRootpath,
  4193. outputSourceFiles: this.options.outputSourceFiles,
  4194. sourceMapGenerator: this.options.sourceMapGenerator,
  4195. sourceMapFileInline: this.options.sourceMapFileInline
  4196. });
  4197. var css = sourceMapOutput.toCSS(options);
  4198. this.sourceMap = sourceMapOutput.sourceMap;
  4199. this.sourceMapURL = sourceMapOutput.sourceMapURL;
  4200. if (this.options.sourceMapInputFilename) {
  4201. this.sourceMapInputFilename = sourceMapOutput.normalizeFilename(this.options.sourceMapInputFilename);
  4202. }
  4203. return css + this.getCSSAppendage();
  4204. };
  4205. SourceMapBuilder.prototype.getCSSAppendage = function() {
  4206. var sourceMapURL = this.sourceMapURL;
  4207. if (this.options.sourceMapFileInline) {
  4208. if (this.sourceMap === undefined) {
  4209. return "";
  4210. }
  4211. sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap);
  4212. }
  4213. if (sourceMapURL) {
  4214. return "/*# sourceMappingURL=" + sourceMapURL + " */";
  4215. }
  4216. return "";
  4217. };
  4218. SourceMapBuilder.prototype.getExternalSourceMap = function() {
  4219. return this.sourceMap;
  4220. };
  4221. SourceMapBuilder.prototype.setExternalSourceMap = function(sourceMap) {
  4222. this.sourceMap = sourceMap;
  4223. };
  4224. SourceMapBuilder.prototype.isInline = function() {
  4225. return this.options.sourceMapFileInline;
  4226. };
  4227. SourceMapBuilder.prototype.getSourceMapURL = function() {
  4228. return this.sourceMapURL;
  4229. };
  4230. SourceMapBuilder.prototype.getOutputFilename = function() {
  4231. return this.options.sourceMapOutputFilename;
  4232. };
  4233. SourceMapBuilder.prototype.getInputFilename = function() {
  4234. return this.sourceMapInputFilename;
  4235. };
  4236. return SourceMapBuilder;
  4237. };
  4238. },{}],40:[function(require,module,exports){
  4239. module.exports = function (environment) {
  4240. var SourceMapOutput = function (options) {
  4241. this._css = [];
  4242. this._rootNode = options.rootNode;
  4243. this._contentsMap = options.contentsMap;
  4244. this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap;
  4245. if (options.sourceMapFilename) {
  4246. this._sourceMapFilename = options.sourceMapFilename.replace(/\\/g, '/');
  4247. }
  4248. this._outputFilename = options.outputFilename;
  4249. this.sourceMapURL = options.sourceMapURL;
  4250. if (options.sourceMapBasepath) {
  4251. this._sourceMapBasepath = options.sourceMapBasepath.replace(/\\/g, '/');
  4252. }
  4253. if (options.sourceMapRootpath) {
  4254. this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
  4255. if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
  4256. this._sourceMapRootpath += '/';
  4257. }
  4258. } else {
  4259. this._sourceMapRootpath = "";
  4260. }
  4261. this._outputSourceFiles = options.outputSourceFiles;
  4262. this._sourceMapGeneratorConstructor = environment.getSourceMapGenerator();
  4263. this._lineNumber = 0;
  4264. this._column = 0;
  4265. };
  4266. SourceMapOutput.prototype.normalizeFilename = function(filename) {
  4267. filename = filename.replace(/\\/g, '/');
  4268. if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
  4269. filename = filename.substring(this._sourceMapBasepath.length);
  4270. if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
  4271. filename = filename.substring(1);
  4272. }
  4273. }
  4274. return (this._sourceMapRootpath || "") + filename;
  4275. };
  4276. SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) {
  4277. //ignore adding empty strings
  4278. if (!chunk) {
  4279. return;
  4280. }
  4281. var lines,
  4282. sourceLines,
  4283. columns,
  4284. sourceColumns,
  4285. i;
  4286. if (fileInfo) {
  4287. var inputSource = this._contentsMap[fileInfo.filename];
  4288. // remove vars/banner added to the top of the file
  4289. if (this._contentsIgnoredCharsMap[fileInfo.filename]) {
  4290. // adjust the index
  4291. index -= this._contentsIgnoredCharsMap[fileInfo.filename];
  4292. if (index < 0) { index = 0; }
  4293. // adjust the source
  4294. inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]);
  4295. }
  4296. inputSource = inputSource.substring(0, index);
  4297. sourceLines = inputSource.split("\n");
  4298. sourceColumns = sourceLines[sourceLines.length - 1];
  4299. }
  4300. lines = chunk.split("\n");
  4301. columns = lines[lines.length - 1];
  4302. if (fileInfo) {
  4303. if (!mapLines) {
  4304. this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
  4305. original: { line: sourceLines.length, column: sourceColumns.length},
  4306. source: this.normalizeFilename(fileInfo.filename)});
  4307. } else {
  4308. for (i = 0; i < lines.length; i++) {
  4309. this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
  4310. original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
  4311. source: this.normalizeFilename(fileInfo.filename)});
  4312. }
  4313. }
  4314. }
  4315. if (lines.length === 1) {
  4316. this._column += columns.length;
  4317. } else {
  4318. this._lineNumber += lines.length - 1;
  4319. this._column = columns.length;
  4320. }
  4321. this._css.push(chunk);
  4322. };
  4323. SourceMapOutput.prototype.isEmpty = function() {
  4324. return this._css.length === 0;
  4325. };
  4326. SourceMapOutput.prototype.toCSS = function(context) {
  4327. this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
  4328. if (this._outputSourceFiles) {
  4329. for (var filename in this._contentsMap) {
  4330. if (this._contentsMap.hasOwnProperty(filename))
  4331. {
  4332. var source = this._contentsMap[filename];
  4333. if (this._contentsIgnoredCharsMap[filename]) {
  4334. source = source.slice(this._contentsIgnoredCharsMap[filename]);
  4335. }
  4336. this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source);
  4337. }
  4338. }
  4339. }
  4340. this._rootNode.genCSS(context, this);
  4341. if (this._css.length > 0) {
  4342. var sourceMapURL,
  4343. sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON());
  4344. if (this.sourceMapURL) {
  4345. sourceMapURL = this.sourceMapURL;
  4346. } else if (this._sourceMapFilename) {
  4347. sourceMapURL = this._sourceMapFilename;
  4348. }
  4349. this.sourceMapURL = sourceMapURL;
  4350. this.sourceMap = sourceMapContent;
  4351. }
  4352. return this._css.join('');
  4353. };
  4354. return SourceMapOutput;
  4355. };
  4356. },{}],41:[function(require,module,exports){
  4357. var contexts = require("./contexts"),
  4358. visitor = require("./visitors"),
  4359. tree = require("./tree");
  4360. module.exports = function(root, options) {
  4361. options = options || {};
  4362. var evaldRoot,
  4363. variables = options.variables,
  4364. evalEnv = new contexts.Eval(options);
  4365. //
  4366. // Allows setting variables with a hash, so:
  4367. //
  4368. // `{ color: new tree.Color('#f01') }` will become:
  4369. //
  4370. // new tree.Rule('@color',
  4371. // new tree.Value([
  4372. // new tree.Expression([
  4373. // new tree.Color('#f01')
  4374. // ])
  4375. // ])
  4376. // )
  4377. //
  4378. if (typeof variables === 'object' && !Array.isArray(variables)) {
  4379. variables = Object.keys(variables).map(function (k) {
  4380. var value = variables[k];
  4381. if (! (value instanceof tree.Value)) {
  4382. if (! (value instanceof tree.Expression)) {
  4383. value = new tree.Expression([value]);
  4384. }
  4385. value = new tree.Value([value]);
  4386. }
  4387. return new tree.Rule('@' + k, value, false, null, 0);
  4388. });
  4389. evalEnv.frames = [new tree.Ruleset(null, variables)];
  4390. }
  4391. var preEvalVisitors = [],
  4392. visitors = [
  4393. new visitor.JoinSelectorVisitor(),
  4394. new visitor.ExtendVisitor(),
  4395. new visitor.ToCSSVisitor({compress: Boolean(options.compress)})
  4396. ], i;
  4397. if (options.pluginManager) {
  4398. var pluginVisitors = options.pluginManager.getVisitors();
  4399. for (i = 0; i < pluginVisitors.length; i++) {
  4400. var pluginVisitor = pluginVisitors[i];
  4401. if (pluginVisitor.isPreEvalVisitor) {
  4402. preEvalVisitors.push(pluginVisitor);
  4403. } else {
  4404. if (pluginVisitor.isPreVisitor) {
  4405. visitors.splice(0, 0, pluginVisitor);
  4406. } else {
  4407. visitors.push(pluginVisitor);
  4408. }
  4409. }
  4410. }
  4411. }
  4412. for (i = 0; i < preEvalVisitors.length; i++) {
  4413. preEvalVisitors[i].run(root);
  4414. }
  4415. evaldRoot = root.eval(evalEnv);
  4416. for (i = 0; i < visitors.length; i++) {
  4417. visitors[i].run(evaldRoot);
  4418. }
  4419. return evaldRoot;
  4420. };
  4421. },{"./contexts":10,"./tree":59,"./visitors":84}],42:[function(require,module,exports){
  4422. var Node = require("./node");
  4423. var Alpha = function (val) {
  4424. this.value = val;
  4425. };
  4426. Alpha.prototype = new Node();
  4427. Alpha.prototype.type = "Alpha";
  4428. Alpha.prototype.accept = function (visitor) {
  4429. this.value = visitor.visit(this.value);
  4430. };
  4431. Alpha.prototype.eval = function (context) {
  4432. if (this.value.eval) { return new Alpha(this.value.eval(context)); }
  4433. return this;
  4434. };
  4435. Alpha.prototype.genCSS = function (context, output) {
  4436. output.add("alpha(opacity=");
  4437. if (this.value.genCSS) {
  4438. this.value.genCSS(context, output);
  4439. } else {
  4440. output.add(this.value);
  4441. }
  4442. output.add(")");
  4443. };
  4444. module.exports = Alpha;
  4445. },{"./node":67}],43:[function(require,module,exports){
  4446. var Node = require("./node");
  4447. var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike) {
  4448. this.value = value;
  4449. this.index = index;
  4450. this.mapLines = mapLines;
  4451. this.currentFileInfo = currentFileInfo;
  4452. this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
  4453. };
  4454. Anonymous.prototype = new Node();
  4455. Anonymous.prototype.type = "Anonymous";
  4456. Anonymous.prototype.eval = function () {
  4457. return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike);
  4458. };
  4459. Anonymous.prototype.compare = function (other) {
  4460. return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
  4461. };
  4462. Anonymous.prototype.isRulesetLike = function() {
  4463. return this.rulesetLike;
  4464. };
  4465. Anonymous.prototype.genCSS = function (context, output) {
  4466. output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
  4467. };
  4468. module.exports = Anonymous;
  4469. },{"./node":67}],44:[function(require,module,exports){
  4470. var Node = require("./node");
  4471. var Assignment = function (key, val) {
  4472. this.key = key;
  4473. this.value = val;
  4474. };
  4475. Assignment.prototype = new Node();
  4476. Assignment.prototype.type = "Assignment";
  4477. Assignment.prototype.accept = function (visitor) {
  4478. this.value = visitor.visit(this.value);
  4479. };
  4480. Assignment.prototype.eval = function (context) {
  4481. if (this.value.eval) {
  4482. return new Assignment(this.key, this.value.eval(context));
  4483. }
  4484. return this;
  4485. };
  4486. Assignment.prototype.genCSS = function (context, output) {
  4487. output.add(this.key + '=');
  4488. if (this.value.genCSS) {
  4489. this.value.genCSS(context, output);
  4490. } else {
  4491. output.add(this.value);
  4492. }
  4493. };
  4494. module.exports = Assignment;
  4495. },{"./node":67}],45:[function(require,module,exports){
  4496. var Node = require("./node");
  4497. var Attribute = function (key, op, value) {
  4498. this.key = key;
  4499. this.op = op;
  4500. this.value = value;
  4501. };
  4502. Attribute.prototype = new Node();
  4503. Attribute.prototype.type = "Attribute";
  4504. Attribute.prototype.eval = function (context) {
  4505. return new Attribute(this.key.eval ? this.key.eval(context) : this.key,
  4506. this.op, (this.value && this.value.eval) ? this.value.eval(context) : this.value);
  4507. };
  4508. Attribute.prototype.genCSS = function (context, output) {
  4509. output.add(this.toCSS(context));
  4510. };
  4511. Attribute.prototype.toCSS = function (context) {
  4512. var value = this.key.toCSS ? this.key.toCSS(context) : this.key;
  4513. if (this.op) {
  4514. value += this.op;
  4515. value += (this.value.toCSS ? this.value.toCSS(context) : this.value);
  4516. }
  4517. return '[' + value + ']';
  4518. };
  4519. module.exports = Attribute;
  4520. },{"./node":67}],46:[function(require,module,exports){
  4521. var Node = require("./node"),
  4522. FunctionCaller = require("../functions/function-caller");
  4523. //
  4524. // A function call node.
  4525. //
  4526. var Call = function (name, args, index, currentFileInfo) {
  4527. this.name = name;
  4528. this.args = args;
  4529. this.index = index;
  4530. this.currentFileInfo = currentFileInfo;
  4531. };
  4532. Call.prototype = new Node();
  4533. Call.prototype.type = "Call";
  4534. Call.prototype.accept = function (visitor) {
  4535. if (this.args) {
  4536. this.args = visitor.visitArray(this.args);
  4537. }
  4538. };
  4539. //
  4540. // When evaluating a function call,
  4541. // we either find the function in the functionRegistry,
  4542. // in which case we call it, passing the evaluated arguments,
  4543. // if this returns null or we cannot find the function, we
  4544. // simply print it out as it appeared originally [2].
  4545. //
  4546. // The reason why we evaluate the arguments, is in the case where
  4547. // we try to pass a variable to a function, like: `saturate(@color)`.
  4548. // The function should receive the value, not the variable.
  4549. //
  4550. Call.prototype.eval = function (context) {
  4551. var args = this.args.map(function (a) { return a.eval(context); }),
  4552. result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo);
  4553. if (funcCaller.isValid()) { // 1.
  4554. try {
  4555. result = funcCaller.call(args);
  4556. if (result != null) {
  4557. return result;
  4558. }
  4559. } catch (e) {
  4560. throw { type: e.type || "Runtime",
  4561. message: "error evaluating function `" + this.name + "`" +
  4562. (e.message ? ': ' + e.message : ''),
  4563. index: this.index, filename: this.currentFileInfo.filename };
  4564. }
  4565. }
  4566. return new Call(this.name, args, this.index, this.currentFileInfo);
  4567. };
  4568. Call.prototype.genCSS = function (context, output) {
  4569. output.add(this.name + "(", this.currentFileInfo, this.index);
  4570. for (var i = 0; i < this.args.length; i++) {
  4571. this.args[i].genCSS(context, output);
  4572. if (i + 1 < this.args.length) {
  4573. output.add(", ");
  4574. }
  4575. }
  4576. output.add(")");
  4577. };
  4578. module.exports = Call;
  4579. },{"../functions/function-caller":20,"./node":67}],47:[function(require,module,exports){
  4580. var Node = require("./node"),
  4581. colors = require("../data/colors");
  4582. //
  4583. // RGB Colors - #ff0014, #eee
  4584. //
  4585. var Color = function (rgb, a) {
  4586. //
  4587. // The end goal here, is to parse the arguments
  4588. // into an integer triplet, such as `128, 255, 0`
  4589. //
  4590. // This facilitates operations and conversions.
  4591. //
  4592. if (Array.isArray(rgb)) {
  4593. this.rgb = rgb;
  4594. } else if (rgb.length == 6) {
  4595. this.rgb = rgb.match(/.{2}/g).map(function (c) {
  4596. return parseInt(c, 16);
  4597. });
  4598. } else {
  4599. this.rgb = rgb.split('').map(function (c) {
  4600. return parseInt(c + c, 16);
  4601. });
  4602. }
  4603. this.alpha = typeof a === 'number' ? a : 1;
  4604. };
  4605. Color.prototype = new Node();
  4606. Color.prototype.type = "Color";
  4607. function clamp(v, max) {
  4608. return Math.min(Math.max(v, 0), max);
  4609. }
  4610. function toHex(v) {
  4611. return '#' + v.map(function (c) {
  4612. c = clamp(Math.round(c), 255);
  4613. return (c < 16 ? '0' : '') + c.toString(16);
  4614. }).join('');
  4615. }
  4616. Color.prototype.luma = function () {
  4617. var r = this.rgb[0] / 255,
  4618. g = this.rgb[1] / 255,
  4619. b = this.rgb[2] / 255;
  4620. r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
  4621. g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
  4622. b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
  4623. return 0.2126 * r + 0.7152 * g + 0.0722 * b;
  4624. };
  4625. Color.prototype.genCSS = function (context, output) {
  4626. output.add(this.toCSS(context));
  4627. };
  4628. Color.prototype.toCSS = function (context, doNotCompress) {
  4629. var compress = context && context.compress && !doNotCompress, color, alpha;
  4630. // `value` is set if this color was originally
  4631. // converted from a named color string so we need
  4632. // to respect this and try to output named color too.
  4633. if (this.value) {
  4634. return this.value;
  4635. }
  4636. // If we have some transparency, the only way to represent it
  4637. // is via `rgba`. Otherwise, we use the hex representation,
  4638. // which has better compatibility with older browsers.
  4639. // Values are capped between `0` and `255`, rounded and zero-padded.
  4640. alpha = this.fround(context, this.alpha);
  4641. if (alpha < 1) {
  4642. return "rgba(" + this.rgb.map(function (c) {
  4643. return clamp(Math.round(c), 255);
  4644. }).concat(clamp(alpha, 1))
  4645. .join(',' + (compress ? '' : ' ')) + ")";
  4646. }
  4647. color = this.toRGB();
  4648. if (compress) {
  4649. var splitcolor = color.split('');
  4650. // Convert color to short format
  4651. if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
  4652. color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5];
  4653. }
  4654. }
  4655. return color;
  4656. };
  4657. //
  4658. // Operations have to be done per-channel, if not,
  4659. // channels will spill onto each other. Once we have
  4660. // our result, in the form of an integer triplet,
  4661. // we create a new Color node to hold the result.
  4662. //
  4663. Color.prototype.operate = function (context, op, other) {
  4664. var rgb = [];
  4665. var alpha = this.alpha * (1 - other.alpha) + other.alpha;
  4666. for (var c = 0; c < 3; c++) {
  4667. rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]);
  4668. }
  4669. return new Color(rgb, alpha);
  4670. };
  4671. Color.prototype.toRGB = function () {
  4672. return toHex(this.rgb);
  4673. };
  4674. Color.prototype.toHSL = function () {
  4675. var r = this.rgb[0] / 255,
  4676. g = this.rgb[1] / 255,
  4677. b = this.rgb[2] / 255,
  4678. a = this.alpha;
  4679. var max = Math.max(r, g, b), min = Math.min(r, g, b);
  4680. var h, s, l = (max + min) / 2, d = max - min;
  4681. if (max === min) {
  4682. h = s = 0;
  4683. } else {
  4684. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  4685. switch (max) {
  4686. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  4687. case g: h = (b - r) / d + 2; break;
  4688. case b: h = (r - g) / d + 4; break;
  4689. }
  4690. h /= 6;
  4691. }
  4692. return { h: h * 360, s: s, l: l, a: a };
  4693. };
  4694. //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
  4695. Color.prototype.toHSV = function () {
  4696. var r = this.rgb[0] / 255,
  4697. g = this.rgb[1] / 255,
  4698. b = this.rgb[2] / 255,
  4699. a = this.alpha;
  4700. var max = Math.max(r, g, b), min = Math.min(r, g, b);
  4701. var h, s, v = max;
  4702. var d = max - min;
  4703. if (max === 0) {
  4704. s = 0;
  4705. } else {
  4706. s = d / max;
  4707. }
  4708. if (max === min) {
  4709. h = 0;
  4710. } else {
  4711. switch(max) {
  4712. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  4713. case g: h = (b - r) / d + 2; break;
  4714. case b: h = (r - g) / d + 4; break;
  4715. }
  4716. h /= 6;
  4717. }
  4718. return { h: h * 360, s: s, v: v, a: a };
  4719. };
  4720. Color.prototype.toARGB = function () {
  4721. return toHex([this.alpha * 255].concat(this.rgb));
  4722. };
  4723. Color.prototype.compare = function (x) {
  4724. return (x.rgb &&
  4725. x.rgb[0] === this.rgb[0] &&
  4726. x.rgb[1] === this.rgb[1] &&
  4727. x.rgb[2] === this.rgb[2] &&
  4728. x.alpha === this.alpha) ? 0 : undefined;
  4729. };
  4730. Color.fromKeyword = function(keyword) {
  4731. var c, key = keyword.toLowerCase();
  4732. if (colors.hasOwnProperty(key)) {
  4733. c = new Color(colors[key].slice(1));
  4734. }
  4735. else if (key === "transparent") {
  4736. c = new Color([0, 0, 0], 0);
  4737. }
  4738. if (c) {
  4739. c.value = keyword;
  4740. return c;
  4741. }
  4742. };
  4743. module.exports = Color;
  4744. },{"../data/colors":11,"./node":67}],48:[function(require,module,exports){
  4745. var Node = require("./node");
  4746. var Combinator = function (value) {
  4747. if (value === ' ') {
  4748. this.value = ' ';
  4749. this.emptyOrWhitespace = true;
  4750. } else {
  4751. this.value = value ? value.trim() : "";
  4752. this.emptyOrWhitespace = this.value === "";
  4753. }
  4754. };
  4755. Combinator.prototype = new Node();
  4756. Combinator.prototype.type = "Combinator";
  4757. var _noSpaceCombinators = {
  4758. '': true,
  4759. ' ': true,
  4760. '|': true
  4761. };
  4762. Combinator.prototype.genCSS = function (context, output) {
  4763. var spaceOrEmpty = (context.compress || _noSpaceCombinators[this.value]) ? '' : ' ';
  4764. output.add(spaceOrEmpty + this.value + spaceOrEmpty);
  4765. };
  4766. module.exports = Combinator;
  4767. },{"./node":67}],49:[function(require,module,exports){
  4768. var Node = require("./node"),
  4769. getDebugInfo = require("./debug-info");
  4770. var Comment = function (value, isLineComment, index, currentFileInfo) {
  4771. this.value = value;
  4772. this.isLineComment = isLineComment;
  4773. this.currentFileInfo = currentFileInfo;
  4774. };
  4775. Comment.prototype = new Node();
  4776. Comment.prototype.type = "Comment";
  4777. Comment.prototype.genCSS = function (context, output) {
  4778. if (this.debugInfo) {
  4779. output.add(getDebugInfo(context, this), this.currentFileInfo, this.index);
  4780. }
  4781. output.add(this.value);
  4782. };
  4783. Comment.prototype.isSilent = function(context) {
  4784. var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced),
  4785. isCompressed = context.compress && this.value[2] !== "!";
  4786. return this.isLineComment || isReference || isCompressed;
  4787. };
  4788. Comment.prototype.markReferenced = function () {
  4789. this.isReferenced = true;
  4790. };
  4791. Comment.prototype.isRulesetLike = function(root) {
  4792. return Boolean(root);
  4793. };
  4794. module.exports = Comment;
  4795. },{"./debug-info":51,"./node":67}],50:[function(require,module,exports){
  4796. var Node = require("./node");
  4797. var Condition = function (op, l, r, i, negate) {
  4798. this.op = op.trim();
  4799. this.lvalue = l;
  4800. this.rvalue = r;
  4801. this.index = i;
  4802. this.negate = negate;
  4803. };
  4804. Condition.prototype = new Node();
  4805. Condition.prototype.type = "Condition";
  4806. Condition.prototype.accept = function (visitor) {
  4807. this.lvalue = visitor.visit(this.lvalue);
  4808. this.rvalue = visitor.visit(this.rvalue);
  4809. };
  4810. Condition.prototype.eval = function (context) {
  4811. var result = (function (op, a, b) {
  4812. switch (op) {
  4813. case 'and': return a && b;
  4814. case 'or': return a || b;
  4815. default:
  4816. switch (Node.compare(a, b)) {
  4817. case -1:
  4818. return op === '<' || op === '=<' || op === '<=';
  4819. case 0:
  4820. return op === '=' || op === '>=' || op === '=<' || op === '<=';
  4821. case 1:
  4822. return op === '>' || op === '>=';
  4823. default:
  4824. return false;
  4825. }
  4826. }
  4827. })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
  4828. return this.negate ? !result : result;
  4829. };
  4830. module.exports = Condition;
  4831. },{"./node":67}],51:[function(require,module,exports){
  4832. var debugInfo = function(context, ctx, lineSeparator) {
  4833. var result = "";
  4834. if (context.dumpLineNumbers && !context.compress) {
  4835. switch(context.dumpLineNumbers) {
  4836. case 'comments':
  4837. result = debugInfo.asComment(ctx);
  4838. break;
  4839. case 'mediaquery':
  4840. result = debugInfo.asMediaQuery(ctx);
  4841. break;
  4842. case 'all':
  4843. result = debugInfo.asComment(ctx) + (lineSeparator || "") + debugInfo.asMediaQuery(ctx);
  4844. break;
  4845. }
  4846. }
  4847. return result;
  4848. };
  4849. debugInfo.asComment = function(ctx) {
  4850. return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n';
  4851. };
  4852. debugInfo.asMediaQuery = function(ctx) {
  4853. var filenameWithProtocol = ctx.debugInfo.fileName;
  4854. if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
  4855. filenameWithProtocol = 'file://' + filenameWithProtocol;
  4856. }
  4857. return '@media -sass-debug-info{filename{font-family:' +
  4858. filenameWithProtocol.replace(/([.:\/\\])/g, function (a) {
  4859. if (a == '\\') {
  4860. a = '\/';
  4861. }
  4862. return '\\' + a;
  4863. }) +
  4864. '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n';
  4865. };
  4866. module.exports = debugInfo;
  4867. },{}],52:[function(require,module,exports){
  4868. var Node = require("./node"),
  4869. contexts = require("../contexts");
  4870. var DetachedRuleset = function (ruleset, frames) {
  4871. this.ruleset = ruleset;
  4872. this.frames = frames;
  4873. };
  4874. DetachedRuleset.prototype = new Node();
  4875. DetachedRuleset.prototype.type = "DetachedRuleset";
  4876. DetachedRuleset.prototype.evalFirst = true;
  4877. DetachedRuleset.prototype.accept = function (visitor) {
  4878. this.ruleset = visitor.visit(this.ruleset);
  4879. };
  4880. DetachedRuleset.prototype.eval = function (context) {
  4881. var frames = this.frames || context.frames.slice(0);
  4882. return new DetachedRuleset(this.ruleset, frames);
  4883. };
  4884. DetachedRuleset.prototype.callEval = function (context) {
  4885. return this.ruleset.eval(this.frames ? new contexts.Eval(context, this.frames.concat(context.frames)) : context);
  4886. };
  4887. module.exports = DetachedRuleset;
  4888. },{"../contexts":10,"./node":67}],53:[function(require,module,exports){
  4889. var Node = require("./node"),
  4890. unitConversions = require("../data/unit-conversions"),
  4891. Unit = require("./unit"),
  4892. Color = require("./color");
  4893. //
  4894. // A number with a unit
  4895. //
  4896. var Dimension = function (value, unit) {
  4897. this.value = parseFloat(value);
  4898. this.unit = (unit && unit instanceof Unit) ? unit :
  4899. new Unit(unit ? [unit] : undefined);
  4900. };
  4901. Dimension.prototype = new Node();
  4902. Dimension.prototype.type = "Dimension";
  4903. Dimension.prototype.accept = function (visitor) {
  4904. this.unit = visitor.visit(this.unit);
  4905. };
  4906. Dimension.prototype.eval = function (context) {
  4907. return this;
  4908. };
  4909. Dimension.prototype.toColor = function () {
  4910. return new Color([this.value, this.value, this.value]);
  4911. };
  4912. Dimension.prototype.genCSS = function (context, output) {
  4913. if ((context && context.strictUnits) && !this.unit.isSingular()) {
  4914. throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString());
  4915. }
  4916. var value = this.fround(context, this.value),
  4917. strValue = String(value);
  4918. if (value !== 0 && value < 0.000001 && value > -0.000001) {
  4919. // would be output 1e-6 etc.
  4920. strValue = value.toFixed(20).replace(/0+$/, "");
  4921. }
  4922. if (context && context.compress) {
  4923. // Zero values doesn't need a unit
  4924. if (value === 0 && this.unit.isLength()) {
  4925. output.add(strValue);
  4926. return;
  4927. }
  4928. // Float values doesn't need a leading zero
  4929. if (value > 0 && value < 1) {
  4930. strValue = (strValue).substr(1);
  4931. }
  4932. }
  4933. output.add(strValue);
  4934. this.unit.genCSS(context, output);
  4935. };
  4936. // In an operation between two Dimensions,
  4937. // we default to the first Dimension's unit,
  4938. // so `1px + 2` will yield `3px`.
  4939. Dimension.prototype.operate = function (context, op, other) {
  4940. /*jshint noempty:false */
  4941. var value = this._operate(context, op, this.value, other.value),
  4942. unit = this.unit.clone();
  4943. if (op === '+' || op === '-') {
  4944. if (unit.numerator.length === 0 && unit.denominator.length === 0) {
  4945. unit.numerator = other.unit.numerator.slice(0);
  4946. unit.denominator = other.unit.denominator.slice(0);
  4947. } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
  4948. // do nothing
  4949. } else {
  4950. other = other.convertTo(this.unit.usedUnits());
  4951. if (context.strictUnits && other.unit.toString() !== unit.toString()) {
  4952. throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
  4953. "' and '" + other.unit.toString() + "'.");
  4954. }
  4955. value = this._operate(context, op, this.value, other.value);
  4956. }
  4957. } else if (op === '*') {
  4958. unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
  4959. unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
  4960. unit.cancel();
  4961. } else if (op === '/') {
  4962. unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
  4963. unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
  4964. unit.cancel();
  4965. }
  4966. return new Dimension(value, unit);
  4967. };
  4968. Dimension.prototype.compare = function (other) {
  4969. var a, b;
  4970. if (!(other instanceof Dimension)) {
  4971. return undefined;
  4972. }
  4973. if (this.unit.isEmpty() || other.unit.isEmpty()) {
  4974. a = this;
  4975. b = other;
  4976. } else {
  4977. a = this.unify();
  4978. b = other.unify();
  4979. if (a.unit.compare(b.unit) !== 0) {
  4980. return undefined;
  4981. }
  4982. }
  4983. return Node.numericCompare(a.value, b.value);
  4984. };
  4985. Dimension.prototype.unify = function () {
  4986. return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
  4987. };
  4988. Dimension.prototype.convertTo = function (conversions) {
  4989. var value = this.value, unit = this.unit.clone(),
  4990. i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
  4991. if (typeof conversions === 'string') {
  4992. for (i in unitConversions) {
  4993. if (unitConversions[i].hasOwnProperty(conversions)) {
  4994. derivedConversions = {};
  4995. derivedConversions[i] = conversions;
  4996. }
  4997. }
  4998. conversions = derivedConversions;
  4999. }
  5000. applyUnit = function (atomicUnit, denominator) {
  5001. /*jshint loopfunc:true */
  5002. if (group.hasOwnProperty(atomicUnit)) {
  5003. if (denominator) {
  5004. value = value / (group[atomicUnit] / group[targetUnit]);
  5005. } else {
  5006. value = value * (group[atomicUnit] / group[targetUnit]);
  5007. }
  5008. return targetUnit;
  5009. }
  5010. return atomicUnit;
  5011. };
  5012. for (groupName in conversions) {
  5013. if (conversions.hasOwnProperty(groupName)) {
  5014. targetUnit = conversions[groupName];
  5015. group = unitConversions[groupName];
  5016. unit.map(applyUnit);
  5017. }
  5018. }
  5019. unit.cancel();
  5020. return new Dimension(value, unit);
  5021. };
  5022. module.exports = Dimension;
  5023. },{"../data/unit-conversions":13,"./color":47,"./node":67,"./unit":76}],54:[function(require,module,exports){
  5024. var Node = require("./node"),
  5025. Ruleset = require("./ruleset");
  5026. var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isReferenced) {
  5027. this.name = name;
  5028. this.value = value;
  5029. if (rules) {
  5030. this.rules = rules;
  5031. this.rules.allowImports = true;
  5032. }
  5033. this.index = index;
  5034. this.currentFileInfo = currentFileInfo;
  5035. this.debugInfo = debugInfo;
  5036. this.isReferenced = isReferenced;
  5037. };
  5038. Directive.prototype = new Node();
  5039. Directive.prototype.type = "Directive";
  5040. Directive.prototype.accept = function (visitor) {
  5041. var value = this.value, rules = this.rules;
  5042. if (rules) {
  5043. this.rules = visitor.visit(rules);
  5044. }
  5045. if (value) {
  5046. this.value = visitor.visit(value);
  5047. }
  5048. };
  5049. Directive.prototype.isRulesetLike = function() {
  5050. return this.rules || !this.isCharset();
  5051. };
  5052. Directive.prototype.isCharset = function() {
  5053. return "@charset" === this.name;
  5054. };
  5055. Directive.prototype.genCSS = function (context, output) {
  5056. var value = this.value, rules = this.rules;
  5057. output.add(this.name, this.currentFileInfo, this.index);
  5058. if (value) {
  5059. output.add(' ');
  5060. value.genCSS(context, output);
  5061. }
  5062. if (rules) {
  5063. if (rules.type === "Ruleset") {
  5064. rules = [rules];
  5065. }
  5066. this.outputRuleset(context, output, rules);
  5067. } else {
  5068. output.add(';');
  5069. }
  5070. };
  5071. Directive.prototype.eval = function (context) {
  5072. var value = this.value, rules = this.rules;
  5073. if (value) {
  5074. value = value.eval(context);
  5075. }
  5076. if (rules) {
  5077. rules = rules.eval(context);
  5078. rules.root = true;
  5079. }
  5080. return new Directive(this.name, value, rules,
  5081. this.index, this.currentFileInfo, this.debugInfo, this.isReferenced);
  5082. };
  5083. Directive.prototype.variable = function (name) {
  5084. if (this.rules) {
  5085. return Ruleset.prototype.variable.call(this.rules, name);
  5086. }
  5087. };
  5088. Directive.prototype.find = function () {
  5089. if (this.rules) {
  5090. return Ruleset.prototype.find.apply(this.rules, arguments);
  5091. }
  5092. };
  5093. Directive.prototype.rulesets = function () {
  5094. if (this.rules) {
  5095. return Ruleset.prototype.rulesets.apply(this.rules);
  5096. }
  5097. };
  5098. Directive.prototype.markReferenced = function () {
  5099. var i, rules;
  5100. this.isReferenced = true;
  5101. if (this.rules) {
  5102. rules = this.rules.rules;
  5103. for (i = 0; i < rules.length; i++) {
  5104. if (rules[i].markReferenced) {
  5105. rules[i].markReferenced();
  5106. }
  5107. }
  5108. }
  5109. };
  5110. Directive.prototype.getIsReferenced = function () {
  5111. return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
  5112. };
  5113. Directive.prototype.outputRuleset = function (context, output, rules) {
  5114. var ruleCnt = rules.length, i;
  5115. context.tabLevel = (context.tabLevel | 0) + 1;
  5116. // Compressed
  5117. if (context.compress) {
  5118. output.add('{');
  5119. for (i = 0; i < ruleCnt; i++) {
  5120. rules[i].genCSS(context, output);
  5121. }
  5122. output.add('}');
  5123. context.tabLevel--;
  5124. return;
  5125. }
  5126. // Non-compressed
  5127. var tabSetStr = '\n' + Array(context.tabLevel).join(" "), tabRuleStr = tabSetStr + " ";
  5128. if (!ruleCnt) {
  5129. output.add(" {" + tabSetStr + '}');
  5130. } else {
  5131. output.add(" {" + tabRuleStr);
  5132. rules[0].genCSS(context, output);
  5133. for (i = 1; i < ruleCnt; i++) {
  5134. output.add(tabRuleStr);
  5135. rules[i].genCSS(context, output);
  5136. }
  5137. output.add(tabSetStr + '}');
  5138. }
  5139. context.tabLevel--;
  5140. };
  5141. module.exports = Directive;
  5142. },{"./node":67,"./ruleset":73}],55:[function(require,module,exports){
  5143. var Node = require("./node"),
  5144. Paren = require("./paren"),
  5145. Combinator = require("./combinator");
  5146. var Element = function (combinator, value, index, currentFileInfo) {
  5147. this.combinator = combinator instanceof Combinator ?
  5148. combinator : new Combinator(combinator);
  5149. if (typeof value === 'string') {
  5150. this.value = value.trim();
  5151. } else if (value) {
  5152. this.value = value;
  5153. } else {
  5154. this.value = "";
  5155. }
  5156. this.index = index;
  5157. this.currentFileInfo = currentFileInfo;
  5158. };
  5159. Element.prototype = new Node();
  5160. Element.prototype.type = "Element";
  5161. Element.prototype.accept = function (visitor) {
  5162. var value = this.value;
  5163. this.combinator = visitor.visit(this.combinator);
  5164. if (typeof value === "object") {
  5165. this.value = visitor.visit(value);
  5166. }
  5167. };
  5168. Element.prototype.eval = function (context) {
  5169. return new Element(this.combinator,
  5170. this.value.eval ? this.value.eval(context) : this.value,
  5171. this.index,
  5172. this.currentFileInfo);
  5173. };
  5174. Element.prototype.genCSS = function (context, output) {
  5175. output.add(this.toCSS(context), this.currentFileInfo, this.index);
  5176. };
  5177. Element.prototype.toCSS = function (context) {
  5178. context = context || {};
  5179. var value = this.value, firstSelector = context.firstSelector;
  5180. if (value instanceof Paren) {
  5181. // selector in parens should not be affected by outer selector
  5182. // flags (breaks only interpolated selectors - see #1973)
  5183. context.firstSelector = true;
  5184. }
  5185. value = value.toCSS ? value.toCSS(context) : value;
  5186. context.firstSelector = firstSelector;
  5187. if (value === '' && this.combinator.value.charAt(0) === '&') {
  5188. return '';
  5189. } else {
  5190. return this.combinator.toCSS(context) + value;
  5191. }
  5192. };
  5193. module.exports = Element;
  5194. },{"./combinator":48,"./node":67,"./paren":69}],56:[function(require,module,exports){
  5195. var Node = require("./node"),
  5196. Paren = require("./paren"),
  5197. Comment = require("./comment");
  5198. var Expression = function (value) {
  5199. this.value = value;
  5200. if (!value) {
  5201. throw new Error("Expression requires an array parameter");
  5202. }
  5203. };
  5204. Expression.prototype = new Node();
  5205. Expression.prototype.type = "Expression";
  5206. Expression.prototype.accept = function (visitor) {
  5207. this.value = visitor.visitArray(this.value);
  5208. };
  5209. Expression.prototype.eval = function (context) {
  5210. var returnValue,
  5211. inParenthesis = this.parens && !this.parensInOp,
  5212. doubleParen = false;
  5213. if (inParenthesis) {
  5214. context.inParenthesis();
  5215. }
  5216. if (this.value.length > 1) {
  5217. returnValue = new Expression(this.value.map(function (e) {
  5218. return e.eval(context);
  5219. }));
  5220. } else if (this.value.length === 1) {
  5221. if (this.value[0].parens && !this.value[0].parensInOp) {
  5222. doubleParen = true;
  5223. }
  5224. returnValue = this.value[0].eval(context);
  5225. } else {
  5226. returnValue = this;
  5227. }
  5228. if (inParenthesis) {
  5229. context.outOfParenthesis();
  5230. }
  5231. if (this.parens && this.parensInOp && !(context.isMathOn()) && !doubleParen) {
  5232. returnValue = new Paren(returnValue);
  5233. }
  5234. return returnValue;
  5235. };
  5236. Expression.prototype.genCSS = function (context, output) {
  5237. for (var i = 0; i < this.value.length; i++) {
  5238. this.value[i].genCSS(context, output);
  5239. if (i + 1 < this.value.length) {
  5240. output.add(" ");
  5241. }
  5242. }
  5243. };
  5244. Expression.prototype.throwAwayComments = function () {
  5245. this.value = this.value.filter(function(v) {
  5246. return !(v instanceof Comment);
  5247. });
  5248. };
  5249. module.exports = Expression;
  5250. },{"./comment":49,"./node":67,"./paren":69}],57:[function(require,module,exports){
  5251. var Node = require("./node");
  5252. var Extend = function Extend(selector, option, index) {
  5253. this.selector = selector;
  5254. this.option = option;
  5255. this.index = index;
  5256. this.object_id = Extend.next_id++;
  5257. this.parent_ids = [this.object_id];
  5258. switch(option) {
  5259. case "all":
  5260. this.allowBefore = true;
  5261. this.allowAfter = true;
  5262. break;
  5263. default:
  5264. this.allowBefore = false;
  5265. this.allowAfter = false;
  5266. break;
  5267. }
  5268. };
  5269. Extend.next_id = 0;
  5270. Extend.prototype = new Node();
  5271. Extend.prototype.type = "Extend";
  5272. Extend.prototype.accept = function (visitor) {
  5273. this.selector = visitor.visit(this.selector);
  5274. };
  5275. Extend.prototype.eval = function (context) {
  5276. return new Extend(this.selector.eval(context), this.option, this.index);
  5277. };
  5278. Extend.prototype.clone = function (context) {
  5279. return new Extend(this.selector, this.option, this.index);
  5280. };
  5281. Extend.prototype.findSelfSelectors = function (selectors) {
  5282. var selfElements = [],
  5283. i,
  5284. selectorElements;
  5285. for (i = 0; i < selectors.length; i++) {
  5286. selectorElements = selectors[i].elements;
  5287. // duplicate the logic in genCSS function inside the selector node.
  5288. // future TODO - move both logics into the selector joiner visitor
  5289. if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") {
  5290. selectorElements[0].combinator.value = ' ';
  5291. }
  5292. selfElements = selfElements.concat(selectors[i].elements);
  5293. }
  5294. this.selfSelectors = [{ elements: selfElements }];
  5295. };
  5296. module.exports = Extend;
  5297. },{"./node":67}],58:[function(require,module,exports){
  5298. var Node = require("./node"),
  5299. Media = require("./media"),
  5300. URL = require("./url"),
  5301. Quoted = require("./quoted"),
  5302. Ruleset = require("./ruleset"),
  5303. Anonymous = require("./anonymous");
  5304. //
  5305. // CSS @import node
  5306. //
  5307. // The general strategy here is that we don't want to wait
  5308. // for the parsing to be completed, before we start importing
  5309. // the file. That's because in the context of a browser,
  5310. // most of the time will be spent waiting for the server to respond.
  5311. //
  5312. // On creation, we push the import path to our import queue, though
  5313. // `import,push`, we also pass it a callback, which it'll call once
  5314. // the file has been fetched, and parsed.
  5315. //
  5316. var Import = function (path, features, options, index, currentFileInfo) {
  5317. this.options = options;
  5318. this.index = index;
  5319. this.path = path;
  5320. this.features = features;
  5321. this.currentFileInfo = currentFileInfo;
  5322. if (this.options.less !== undefined || this.options.inline) {
  5323. this.css = !this.options.less || this.options.inline;
  5324. } else {
  5325. var pathValue = this.getPath();
  5326. if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
  5327. this.css = true;
  5328. }
  5329. }
  5330. };
  5331. //
  5332. // The actual import node doesn't return anything, when converted to CSS.
  5333. // The reason is that it's used at the evaluation stage, so that the rules
  5334. // it imports can be treated like any other rules.
  5335. //
  5336. // In `eval`, we make sure all Import nodes get evaluated, recursively, so
  5337. // we end up with a flat structure, which can easily be imported in the parent
  5338. // ruleset.
  5339. //
  5340. Import.prototype = new Node();
  5341. Import.prototype.type = "Import";
  5342. Import.prototype.accept = function (visitor) {
  5343. if (this.features) {
  5344. this.features = visitor.visit(this.features);
  5345. }
  5346. this.path = visitor.visit(this.path);
  5347. if (!this.options.inline && this.root) {
  5348. this.root = visitor.visit(this.root);
  5349. }
  5350. };
  5351. Import.prototype.genCSS = function (context, output) {
  5352. if (this.css) {
  5353. output.add("@import ", this.currentFileInfo, this.index);
  5354. this.path.genCSS(context, output);
  5355. if (this.features) {
  5356. output.add(" ");
  5357. this.features.genCSS(context, output);
  5358. }
  5359. output.add(';');
  5360. }
  5361. };
  5362. Import.prototype.getPath = function () {
  5363. if (this.path instanceof Quoted) {
  5364. return this.path.value;
  5365. } else if (this.path instanceof URL) {
  5366. return this.path.value.value;
  5367. }
  5368. return null;
  5369. };
  5370. Import.prototype.isVariableImport = function () {
  5371. var path = this.path;
  5372. if (path instanceof URL) {
  5373. path = path.value;
  5374. }
  5375. if (path instanceof Quoted) {
  5376. return path.containsVariables();
  5377. }
  5378. return true;
  5379. };
  5380. Import.prototype.evalForImport = function (context) {
  5381. var path = this.path;
  5382. if (path instanceof URL) {
  5383. path = path.value;
  5384. }
  5385. return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo);
  5386. };
  5387. Import.prototype.evalPath = function (context) {
  5388. var path = this.path.eval(context);
  5389. var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
  5390. if (!(path instanceof URL)) {
  5391. if (rootpath) {
  5392. var pathValue = path.value;
  5393. // Add the base path if the import is relative
  5394. if (pathValue && context.isPathRelative(pathValue)) {
  5395. path.value = rootpath + pathValue;
  5396. }
  5397. }
  5398. path.value = context.normalizePath(path.value);
  5399. }
  5400. return path;
  5401. };
  5402. Import.prototype.eval = function (context) {
  5403. var ruleset, features = this.features && this.features.eval(context);
  5404. if (this.skip) {
  5405. if (typeof this.skip === "function") {
  5406. this.skip = this.skip();
  5407. }
  5408. if (this.skip) {
  5409. return [];
  5410. }
  5411. }
  5412. if (this.options.inline) {
  5413. var contents = new Anonymous(this.root, 0, {filename: this.importedFilename}, true, true);
  5414. return this.features ? new Media([contents], this.features.value) : [contents];
  5415. } else if (this.css) {
  5416. var newImport = new Import(this.evalPath(context), features, this.options, this.index);
  5417. if (!newImport.css && this.error) {
  5418. throw this.error;
  5419. }
  5420. return newImport;
  5421. } else {
  5422. ruleset = new Ruleset(null, this.root.rules.slice(0));
  5423. ruleset.evalImports(context);
  5424. return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules;
  5425. }
  5426. };
  5427. module.exports = Import;
  5428. },{"./anonymous":43,"./media":63,"./node":67,"./quoted":70,"./ruleset":73,"./url":77}],59:[function(require,module,exports){
  5429. var tree = {};
  5430. tree.Node = require('./node');
  5431. tree.Alpha = require('./alpha');
  5432. tree.Color = require('./color');
  5433. tree.Directive = require('./directive');
  5434. tree.DetachedRuleset = require('./detached-ruleset');
  5435. tree.Operation = require('./operation');
  5436. tree.Dimension = require('./dimension');
  5437. tree.Unit = require('./unit');
  5438. tree.Keyword = require('./keyword');
  5439. tree.Variable = require('./variable');
  5440. tree.Ruleset = require('./ruleset');
  5441. tree.Element = require('./element');
  5442. tree.Attribute = require('./attribute');
  5443. tree.Combinator = require('./combinator');
  5444. tree.Selector = require('./selector');
  5445. tree.Quoted = require('./quoted');
  5446. tree.Expression = require('./expression');
  5447. tree.Rule = require('./rule');
  5448. tree.Call = require('./call');
  5449. tree.URL = require('./url');
  5450. tree.Import = require('./import');
  5451. tree.mixin = {
  5452. Call: require('./mixin-call'),
  5453. Definition: require('./mixin-definition')
  5454. };
  5455. tree.Comment = require('./comment');
  5456. tree.Anonymous = require('./anonymous');
  5457. tree.Value = require('./value');
  5458. tree.JavaScript = require('./javascript');
  5459. tree.Assignment = require('./assignment');
  5460. tree.Condition = require('./condition');
  5461. tree.Paren = require('./paren');
  5462. tree.Media = require('./media');
  5463. tree.UnicodeDescriptor = require('./unicode-descriptor');
  5464. tree.Negative = require('./negative');
  5465. tree.Extend = require('./extend');
  5466. tree.RulesetCall = require('./ruleset-call');
  5467. module.exports = tree;
  5468. },{"./alpha":42,"./anonymous":43,"./assignment":44,"./attribute":45,"./call":46,"./color":47,"./combinator":48,"./comment":49,"./condition":50,"./detached-ruleset":52,"./dimension":53,"./directive":54,"./element":55,"./expression":56,"./extend":57,"./import":58,"./javascript":60,"./keyword":62,"./media":63,"./mixin-call":64,"./mixin-definition":65,"./negative":66,"./node":67,"./operation":68,"./paren":69,"./quoted":70,"./rule":71,"./ruleset":73,"./ruleset-call":72,"./selector":74,"./unicode-descriptor":75,"./unit":76,"./url":77,"./value":78,"./variable":79}],60:[function(require,module,exports){
  5469. var JsEvalNode = require("./js-eval-node"),
  5470. Dimension = require("./dimension"),
  5471. Quoted = require("./quoted"),
  5472. Anonymous = require("./anonymous");
  5473. var JavaScript = function (string, escaped, index, currentFileInfo) {
  5474. this.escaped = escaped;
  5475. this.expression = string;
  5476. this.index = index;
  5477. this.currentFileInfo = currentFileInfo;
  5478. };
  5479. JavaScript.prototype = new JsEvalNode();
  5480. JavaScript.prototype.type = "JavaScript";
  5481. JavaScript.prototype.eval = function(context) {
  5482. var result = this.evaluateJavaScript(this.expression, context);
  5483. if (typeof result === 'number') {
  5484. return new Dimension(result);
  5485. } else if (typeof result === 'string') {
  5486. return new Quoted('"' + result + '"', result, this.escaped, this.index);
  5487. } else if (Array.isArray(result)) {
  5488. return new Anonymous(result.join(', '));
  5489. } else {
  5490. return new Anonymous(result);
  5491. }
  5492. };
  5493. module.exports = JavaScript;
  5494. },{"./anonymous":43,"./dimension":53,"./js-eval-node":61,"./quoted":70}],61:[function(require,module,exports){
  5495. var Node = require("./node"),
  5496. Variable = require("./variable");
  5497. var JsEvalNode = function() {
  5498. };
  5499. JsEvalNode.prototype = new Node();
  5500. JsEvalNode.prototype.evaluateJavaScript = function (expression, context) {
  5501. var result,
  5502. that = this,
  5503. evalContext = {};
  5504. if (context.javascriptEnabled !== undefined && !context.javascriptEnabled) {
  5505. throw { message: "You are using JavaScript, which has been disabled.",
  5506. filename: this.currentFileInfo.filename,
  5507. index: this.index };
  5508. }
  5509. expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
  5510. return that.jsify(new Variable('@' + name, that.index, that.currentFileInfo).eval(context));
  5511. });
  5512. try {
  5513. expression = new Function('return (' + expression + ')');
  5514. } catch (e) {
  5515. throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" ,
  5516. filename: this.currentFileInfo.filename,
  5517. index: this.index };
  5518. }
  5519. var variables = context.frames[0].variables();
  5520. for (var k in variables) {
  5521. if (variables.hasOwnProperty(k)) {
  5522. /*jshint loopfunc:true */
  5523. evalContext[k.slice(1)] = {
  5524. value: variables[k].value,
  5525. toJS: function () {
  5526. return this.value.eval(context).toCSS();
  5527. }
  5528. };
  5529. }
  5530. }
  5531. try {
  5532. result = expression.call(evalContext);
  5533. } catch (e) {
  5534. throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
  5535. filename: this.currentFileInfo.filename,
  5536. index: this.index };
  5537. }
  5538. return result;
  5539. };
  5540. JsEvalNode.prototype.jsify = function (obj) {
  5541. if (Array.isArray(obj.value) && (obj.value.length > 1)) {
  5542. return '[' + obj.value.map(function (v) { return v.toCSS(); }).join(', ') + ']';
  5543. } else {
  5544. return obj.toCSS();
  5545. }
  5546. };
  5547. module.exports = JsEvalNode;
  5548. },{"./node":67,"./variable":79}],62:[function(require,module,exports){
  5549. var Node = require("./node");
  5550. var Keyword = function (value) { this.value = value; };
  5551. Keyword.prototype = new Node();
  5552. Keyword.prototype.type = "Keyword";
  5553. Keyword.prototype.genCSS = function (context, output) {
  5554. if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
  5555. output.add(this.value);
  5556. };
  5557. Keyword.True = new Keyword('true');
  5558. Keyword.False = new Keyword('false');
  5559. module.exports = Keyword;
  5560. },{"./node":67}],63:[function(require,module,exports){
  5561. var Ruleset = require("./ruleset"),
  5562. Value = require("./value"),
  5563. Element = require("./element"),
  5564. Selector = require("./selector"),
  5565. Anonymous = require("./anonymous"),
  5566. Expression = require("./expression"),
  5567. Directive = require("./directive");
  5568. var Media = function (value, features, index, currentFileInfo) {
  5569. this.index = index;
  5570. this.currentFileInfo = currentFileInfo;
  5571. var selectors = this.emptySelectors();
  5572. this.features = new Value(features);
  5573. this.rules = [new Ruleset(selectors, value)];
  5574. this.rules[0].allowImports = true;
  5575. };
  5576. Media.prototype = new Directive();
  5577. Media.prototype.type = "Media";
  5578. Media.prototype.isRulesetLike = true;
  5579. Media.prototype.accept = function (visitor) {
  5580. if (this.features) {
  5581. this.features = visitor.visit(this.features);
  5582. }
  5583. if (this.rules) {
  5584. this.rules = visitor.visitArray(this.rules);
  5585. }
  5586. };
  5587. Media.prototype.genCSS = function (context, output) {
  5588. output.add('@media ', this.currentFileInfo, this.index);
  5589. this.features.genCSS(context, output);
  5590. this.outputRuleset(context, output, this.rules);
  5591. };
  5592. Media.prototype.eval = function (context) {
  5593. if (!context.mediaBlocks) {
  5594. context.mediaBlocks = [];
  5595. context.mediaPath = [];
  5596. }
  5597. var media = new Media(null, [], this.index, this.currentFileInfo);
  5598. if (this.debugInfo) {
  5599. this.rules[0].debugInfo = this.debugInfo;
  5600. media.debugInfo = this.debugInfo;
  5601. }
  5602. var strictMathBypass = false;
  5603. if (!context.strictMath) {
  5604. strictMathBypass = true;
  5605. context.strictMath = true;
  5606. }
  5607. try {
  5608. media.features = this.features.eval(context);
  5609. }
  5610. finally {
  5611. if (strictMathBypass) {
  5612. context.strictMath = false;
  5613. }
  5614. }
  5615. context.mediaPath.push(media);
  5616. context.mediaBlocks.push(media);
  5617. context.frames.unshift(this.rules[0]);
  5618. media.rules = [this.rules[0].eval(context)];
  5619. context.frames.shift();
  5620. context.mediaPath.pop();
  5621. return context.mediaPath.length === 0 ? media.evalTop(context) :
  5622. media.evalNested(context);
  5623. };
  5624. //TODO merge with directive
  5625. Media.prototype.variable = function (name) { return Ruleset.prototype.variable.call(this.rules[0], name); };
  5626. Media.prototype.find = function () { return Ruleset.prototype.find.apply(this.rules[0], arguments); };
  5627. Media.prototype.rulesets = function () { return Ruleset.prototype.rulesets.apply(this.rules[0]); };
  5628. Media.prototype.emptySelectors = function() {
  5629. var el = new Element('', '&', this.index, this.currentFileInfo),
  5630. sels = [new Selector([el], null, null, this.index, this.currentFileInfo)];
  5631. sels[0].mediaEmpty = true;
  5632. return sels;
  5633. };
  5634. Media.prototype.markReferenced = function () {
  5635. var i, rules = this.rules[0].rules;
  5636. this.rules[0].markReferenced();
  5637. this.isReferenced = true;
  5638. for (i = 0; i < rules.length; i++) {
  5639. if (rules[i].markReferenced) {
  5640. rules[i].markReferenced();
  5641. }
  5642. }
  5643. };
  5644. Media.prototype.evalTop = function (context) {
  5645. var result = this;
  5646. // Render all dependent Media blocks.
  5647. if (context.mediaBlocks.length > 1) {
  5648. var selectors = this.emptySelectors();
  5649. result = new Ruleset(selectors, context.mediaBlocks);
  5650. result.multiMedia = true;
  5651. }
  5652. delete context.mediaBlocks;
  5653. delete context.mediaPath;
  5654. return result;
  5655. };
  5656. Media.prototype.evalNested = function (context) {
  5657. var i, value,
  5658. path = context.mediaPath.concat([this]);
  5659. // Extract the media-query conditions separated with `,` (OR).
  5660. for (i = 0; i < path.length; i++) {
  5661. value = path[i].features instanceof Value ?
  5662. path[i].features.value : path[i].features;
  5663. path[i] = Array.isArray(value) ? value : [value];
  5664. }
  5665. // Trace all permutations to generate the resulting media-query.
  5666. //
  5667. // (a, b and c) with nested (d, e) ->
  5668. // a and d
  5669. // a and e
  5670. // b and c and d
  5671. // b and c and e
  5672. this.features = new Value(this.permute(path).map(function (path) {
  5673. path = path.map(function (fragment) {
  5674. return fragment.toCSS ? fragment : new Anonymous(fragment);
  5675. });
  5676. for (i = path.length - 1; i > 0; i--) {
  5677. path.splice(i, 0, new Anonymous("and"));
  5678. }
  5679. return new Expression(path);
  5680. }));
  5681. // Fake a tree-node that doesn't output anything.
  5682. return new Ruleset([], []);
  5683. };
  5684. Media.prototype.permute = function (arr) {
  5685. if (arr.length === 0) {
  5686. return [];
  5687. } else if (arr.length === 1) {
  5688. return arr[0];
  5689. } else {
  5690. var result = [];
  5691. var rest = this.permute(arr.slice(1));
  5692. for (var i = 0; i < rest.length; i++) {
  5693. for (var j = 0; j < arr[0].length; j++) {
  5694. result.push([arr[0][j]].concat(rest[i]));
  5695. }
  5696. }
  5697. return result;
  5698. }
  5699. };
  5700. Media.prototype.bubbleSelectors = function (selectors) {
  5701. if (!selectors) {
  5702. return;
  5703. }
  5704. this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
  5705. };
  5706. module.exports = Media;
  5707. },{"./anonymous":43,"./directive":54,"./element":55,"./expression":56,"./ruleset":73,"./selector":74,"./value":78}],64:[function(require,module,exports){
  5708. var Node = require("./node"),
  5709. Selector = require("./selector"),
  5710. MixinDefinition = require("./mixin-definition"),
  5711. defaultFunc = require("../functions/default");
  5712. var MixinCall = function (elements, args, index, currentFileInfo, important) {
  5713. this.selector = new Selector(elements);
  5714. this.arguments = (args && args.length) ? args : null;
  5715. this.index = index;
  5716. this.currentFileInfo = currentFileInfo;
  5717. this.important = important;
  5718. };
  5719. MixinCall.prototype = new Node();
  5720. MixinCall.prototype.type = "MixinCall";
  5721. MixinCall.prototype.accept = function (visitor) {
  5722. if (this.selector) {
  5723. this.selector = visitor.visit(this.selector);
  5724. }
  5725. if (this.arguments) {
  5726. this.arguments = visitor.visitArray(this.arguments);
  5727. }
  5728. };
  5729. MixinCall.prototype.eval = function (context) {
  5730. var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
  5731. candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
  5732. defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
  5733. function calcDefGroup(mixin, mixinPath) {
  5734. var p, namespace;
  5735. for (f = 0; f < 2; f++) {
  5736. conditionResult[f] = true;
  5737. defaultFunc.value(f);
  5738. for (p = 0; p < mixinPath.length && conditionResult[f]; p++) {
  5739. namespace = mixinPath[p];
  5740. if (namespace.matchCondition) {
  5741. conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, context);
  5742. }
  5743. }
  5744. if (mixin.matchCondition) {
  5745. conditionResult[f] = conditionResult[f] && mixin.matchCondition(args, context);
  5746. }
  5747. }
  5748. if (conditionResult[0] || conditionResult[1]) {
  5749. if (conditionResult[0] != conditionResult[1]) {
  5750. return conditionResult[1] ?
  5751. defTrue : defFalse;
  5752. }
  5753. return defNone;
  5754. }
  5755. return defFalseEitherCase;
  5756. }
  5757. args = this.arguments && this.arguments.map(function (a) {
  5758. return { name: a.name, value: a.value.eval(context) };
  5759. });
  5760. noArgumentsFilter = function(rule) {return rule.matchArgs(null, context);};
  5761. for (i = 0; i < context.frames.length; i++) {
  5762. if ((mixins = context.frames[i].find(this.selector, null, noArgumentsFilter)).length > 0) {
  5763. isOneFound = true;
  5764. // To make `default()` function independent of definition order we have two "subpasses" here.
  5765. // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
  5766. // and build candidate list with corresponding flags. Then, when we know all possible matches,
  5767. // we make a final decision.
  5768. for (m = 0; m < mixins.length; m++) {
  5769. mixin = mixins[m].rule;
  5770. mixinPath = mixins[m].path;
  5771. isRecursive = false;
  5772. for (f = 0; f < context.frames.length; f++) {
  5773. if ((!(mixin instanceof MixinDefinition)) && mixin === (context.frames[f].originalRuleset || context.frames[f])) {
  5774. isRecursive = true;
  5775. break;
  5776. }
  5777. }
  5778. if (isRecursive) {
  5779. continue;
  5780. }
  5781. if (mixin.matchArgs(args, context)) {
  5782. candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
  5783. if (candidate.group !== defFalseEitherCase) {
  5784. candidates.push(candidate);
  5785. }
  5786. match = true;
  5787. }
  5788. }
  5789. defaultFunc.reset();
  5790. count = [0, 0, 0];
  5791. for (m = 0; m < candidates.length; m++) {
  5792. count[candidates[m].group]++;
  5793. }
  5794. if (count[defNone] > 0) {
  5795. defaultResult = defFalse;
  5796. } else {
  5797. defaultResult = defTrue;
  5798. if ((count[defTrue] + count[defFalse]) > 1) {
  5799. throw { type: 'Runtime',
  5800. message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`',
  5801. index: this.index, filename: this.currentFileInfo.filename };
  5802. }
  5803. }
  5804. for (m = 0; m < candidates.length; m++) {
  5805. candidate = candidates[m].group;
  5806. if ((candidate === defNone) || (candidate === defaultResult)) {
  5807. try {
  5808. mixin = candidates[m].mixin;
  5809. if (!(mixin instanceof MixinDefinition)) {
  5810. originalRuleset = mixin.originalRuleset || mixin;
  5811. mixin = new MixinDefinition("", [], mixin.rules, null, false);
  5812. mixin.originalRuleset = originalRuleset;
  5813. }
  5814. Array.prototype.push.apply(
  5815. rules, mixin.evalCall(context, args, this.important).rules);
  5816. } catch (e) {
  5817. throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
  5818. }
  5819. }
  5820. }
  5821. if (match) {
  5822. if (!this.currentFileInfo || !this.currentFileInfo.reference) {
  5823. for (i = 0; i < rules.length; i++) {
  5824. rule = rules[i];
  5825. if (rule.markReferenced) {
  5826. rule.markReferenced();
  5827. }
  5828. }
  5829. }
  5830. return rules;
  5831. }
  5832. }
  5833. }
  5834. if (isOneFound) {
  5835. throw { type: 'Runtime',
  5836. message: 'No matching definition was found for `' + this.format(args) + '`',
  5837. index: this.index, filename: this.currentFileInfo.filename };
  5838. } else {
  5839. throw { type: 'Name',
  5840. message: this.selector.toCSS().trim() + " is undefined",
  5841. index: this.index, filename: this.currentFileInfo.filename };
  5842. }
  5843. };
  5844. MixinCall.prototype.format = function (args) {
  5845. return this.selector.toCSS().trim() + '(' +
  5846. (args ? args.map(function (a) {
  5847. var argValue = "";
  5848. if (a.name) {
  5849. argValue += a.name + ":";
  5850. }
  5851. if (a.value.toCSS) {
  5852. argValue += a.value.toCSS();
  5853. } else {
  5854. argValue += "???";
  5855. }
  5856. return argValue;
  5857. }).join(', ') : "") + ")";
  5858. };
  5859. module.exports = MixinCall;
  5860. },{"../functions/default":19,"./mixin-definition":65,"./node":67,"./selector":74}],65:[function(require,module,exports){
  5861. var Selector = require("./selector"),
  5862. Element = require("./element"),
  5863. Ruleset = require("./ruleset"),
  5864. Rule = require("./rule"),
  5865. Expression = require("./expression"),
  5866. contexts = require("../contexts");
  5867. var Definition = function (name, params, rules, condition, variadic, frames) {
  5868. this.name = name;
  5869. this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])];
  5870. this.params = params;
  5871. this.condition = condition;
  5872. this.variadic = variadic;
  5873. this.arity = params.length;
  5874. this.rules = rules;
  5875. this._lookups = {};
  5876. this.required = params.reduce(function (count, p) {
  5877. if (!p.name || (p.name && !p.value)) {
  5878. return count + 1;
  5879. }
  5880. else {
  5881. return count;
  5882. }
  5883. }, 0);
  5884. this.frames = frames;
  5885. };
  5886. Definition.prototype = new Ruleset();
  5887. Definition.prototype.type = "MixinDefinition";
  5888. Definition.prototype.evalFirst = true;
  5889. Definition.prototype.accept = function (visitor) {
  5890. if (this.params && this.params.length) {
  5891. this.params = visitor.visitArray(this.params);
  5892. }
  5893. this.rules = visitor.visitArray(this.rules);
  5894. if (this.condition) {
  5895. this.condition = visitor.visit(this.condition);
  5896. }
  5897. };
  5898. Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArguments) {
  5899. /*jshint boss:true */
  5900. var frame = new Ruleset(null, null),
  5901. varargs, arg,
  5902. params = this.params.slice(0),
  5903. i, j, val, name, isNamedFound, argIndex, argsLength = 0;
  5904. mixinEnv = new contexts.Eval(mixinEnv, [frame].concat(mixinEnv.frames));
  5905. if (args) {
  5906. args = args.slice(0);
  5907. argsLength = args.length;
  5908. for (i = 0; i < argsLength; i++) {
  5909. arg = args[i];
  5910. if (name = (arg && arg.name)) {
  5911. isNamedFound = false;
  5912. for (j = 0; j < params.length; j++) {
  5913. if (!evaldArguments[j] && name === params[j].name) {
  5914. evaldArguments[j] = arg.value.eval(context);
  5915. frame.prependRule(new Rule(name, arg.value.eval(context)));
  5916. isNamedFound = true;
  5917. break;
  5918. }
  5919. }
  5920. if (isNamedFound) {
  5921. args.splice(i, 1);
  5922. i--;
  5923. continue;
  5924. } else {
  5925. throw { type: 'Runtime', message: "Named argument for " + this.name +
  5926. ' ' + args[i].name + ' not found' };
  5927. }
  5928. }
  5929. }
  5930. }
  5931. argIndex = 0;
  5932. for (i = 0; i < params.length; i++) {
  5933. if (evaldArguments[i]) { continue; }
  5934. arg = args && args[argIndex];
  5935. if (name = params[i].name) {
  5936. if (params[i].variadic) {
  5937. varargs = [];
  5938. for (j = argIndex; j < argsLength; j++) {
  5939. varargs.push(args[j].value.eval(context));
  5940. }
  5941. frame.prependRule(new Rule(name, new Expression(varargs).eval(context)));
  5942. } else {
  5943. val = arg && arg.value;
  5944. if (val) {
  5945. val = val.eval(context);
  5946. } else if (params[i].value) {
  5947. val = params[i].value.eval(mixinEnv);
  5948. frame.resetCache();
  5949. } else {
  5950. throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
  5951. ' (' + argsLength + ' for ' + this.arity + ')' };
  5952. }
  5953. frame.prependRule(new Rule(name, val));
  5954. evaldArguments[i] = val;
  5955. }
  5956. }
  5957. if (params[i].variadic && args) {
  5958. for (j = argIndex; j < argsLength; j++) {
  5959. evaldArguments[j] = args[j].value.eval(context);
  5960. }
  5961. }
  5962. argIndex++;
  5963. }
  5964. return frame;
  5965. };
  5966. Definition.prototype.makeImportant = function() {
  5967. var rules = !this.rules ? this.rules : this.rules.map(function (r) {
  5968. if (r.makeImportant) {
  5969. return r.makeImportant(true);
  5970. } else {
  5971. return r;
  5972. }
  5973. });
  5974. var result = new Definition (this.name, this.params, rules, this.condition, this.variadic, this.frames);
  5975. return result;
  5976. };
  5977. Definition.prototype.eval = function (context) {
  5978. return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0));
  5979. };
  5980. Definition.prototype.evalCall = function (context, args, important) {
  5981. var _arguments = [],
  5982. mixinFrames = this.frames ? this.frames.concat(context.frames) : context.frames,
  5983. frame = this.evalParams(context, new contexts.Eval(context, mixinFrames), args, _arguments),
  5984. rules, ruleset;
  5985. frame.prependRule(new Rule('@arguments', new Expression(_arguments).eval(context)));
  5986. rules = this.rules.slice(0);
  5987. ruleset = new Ruleset(null, rules);
  5988. ruleset.originalRuleset = this;
  5989. ruleset = ruleset.eval(new contexts.Eval(context, [this, frame].concat(mixinFrames)));
  5990. if (important) {
  5991. ruleset = ruleset.makeImportant();
  5992. }
  5993. return ruleset;
  5994. };
  5995. Definition.prototype.matchCondition = function (args, context) {
  5996. if (this.condition && !this.condition.eval(
  5997. new contexts.Eval(context,
  5998. [this.evalParams(context, /* the parameter variables*/
  5999. new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
  6000. .concat(this.frames) // the parent namespace/mixin frames
  6001. .concat(context.frames)))) { // the current environment frames
  6002. return false;
  6003. }
  6004. return true;
  6005. };
  6006. Definition.prototype.matchArgs = function (args, context) {
  6007. var argsLength = (args && args.length) || 0, len;
  6008. if (! this.variadic) {
  6009. if (argsLength < this.required) {
  6010. return false;
  6011. }
  6012. if (argsLength > this.params.length) {
  6013. return false;
  6014. }
  6015. } else {
  6016. if (argsLength < (this.required - 1)) {
  6017. return false;
  6018. }
  6019. }
  6020. len = Math.min(argsLength, this.arity);
  6021. for (var i = 0; i < len; i++) {
  6022. if (!this.params[i].name && !this.params[i].variadic) {
  6023. if (args[i].value.eval(context).toCSS() != this.params[i].value.eval(context).toCSS()) {
  6024. return false;
  6025. }
  6026. }
  6027. }
  6028. return true;
  6029. };
  6030. module.exports = Definition;
  6031. },{"../contexts":10,"./element":55,"./expression":56,"./rule":71,"./ruleset":73,"./selector":74}],66:[function(require,module,exports){
  6032. var Node = require("./node"),
  6033. Operation = require("./operation"),
  6034. Dimension = require("./dimension");
  6035. var Negative = function (node) {
  6036. this.value = node;
  6037. };
  6038. Negative.prototype = new Node();
  6039. Negative.prototype.type = "Negative";
  6040. Negative.prototype.genCSS = function (context, output) {
  6041. output.add('-');
  6042. this.value.genCSS(context, output);
  6043. };
  6044. Negative.prototype.eval = function (context) {
  6045. if (context.isMathOn()) {
  6046. return (new Operation('*', [new Dimension(-1), this.value])).eval(context);
  6047. }
  6048. return new Negative(this.value.eval(context));
  6049. };
  6050. module.exports = Negative;
  6051. },{"./dimension":53,"./node":67,"./operation":68}],67:[function(require,module,exports){
  6052. var Node = function() {
  6053. };
  6054. Node.prototype.toCSS = function (context) {
  6055. var strs = [];
  6056. this.genCSS(context, {
  6057. add: function(chunk, fileInfo, index) {
  6058. strs.push(chunk);
  6059. },
  6060. isEmpty: function () {
  6061. return strs.length === 0;
  6062. }
  6063. });
  6064. return strs.join('');
  6065. };
  6066. Node.prototype.genCSS = function (context, output) {
  6067. output.add(this.value);
  6068. };
  6069. Node.prototype.accept = function (visitor) {
  6070. this.value = visitor.visit(this.value);
  6071. };
  6072. Node.prototype.eval = function () { return this; };
  6073. Node.prototype._operate = function (context, op, a, b) {
  6074. switch (op) {
  6075. case '+': return a + b;
  6076. case '-': return a - b;
  6077. case '*': return a * b;
  6078. case '/': return a / b;
  6079. }
  6080. };
  6081. Node.prototype.fround = function(context, value) {
  6082. var precision = context && context.numPrecision;
  6083. //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
  6084. return (precision == null) ? value : Number((value + 2e-16).toFixed(precision));
  6085. };
  6086. Node.compare = function (a, b) {
  6087. /* returns:
  6088. -1: a < b
  6089. 0: a = b
  6090. 1: a > b
  6091. and *any* other value for a != b (e.g. undefined, NaN, -2 etc.) */
  6092. if ((a.compare) &&
  6093. // for "symmetric results" force toCSS-based comparison
  6094. // of Quoted or Anonymous if either value is one of those
  6095. !(b.type === "Quoted" || b.type === "Anonymous")) {
  6096. return a.compare(b);
  6097. } else if (b.compare) {
  6098. return -b.compare(a);
  6099. } else if (a.type !== b.type) {
  6100. return undefined;
  6101. }
  6102. a = a.value;
  6103. b = b.value;
  6104. if (!Array.isArray(a)) {
  6105. return a === b ? 0 : undefined;
  6106. }
  6107. if (a.length !== b.length) {
  6108. return undefined;
  6109. }
  6110. for (var i = 0; i < a.length; i++) {
  6111. if (Node.compare(a[i], b[i]) !== 0) {
  6112. return undefined;
  6113. }
  6114. }
  6115. return 0;
  6116. };
  6117. Node.numericCompare = function (a, b) {
  6118. return a < b ? -1
  6119. : a === b ? 0
  6120. : a > b ? 1 : undefined;
  6121. };
  6122. module.exports = Node;
  6123. },{}],68:[function(require,module,exports){
  6124. var Node = require("./node"),
  6125. Color = require("./color"),
  6126. Dimension = require("./dimension");
  6127. var Operation = function (op, operands, isSpaced) {
  6128. this.op = op.trim();
  6129. this.operands = operands;
  6130. this.isSpaced = isSpaced;
  6131. };
  6132. Operation.prototype = new Node();
  6133. Operation.prototype.type = "Operation";
  6134. Operation.prototype.accept = function (visitor) {
  6135. this.operands = visitor.visit(this.operands);
  6136. };
  6137. Operation.prototype.eval = function (context) {
  6138. var a = this.operands[0].eval(context),
  6139. b = this.operands[1].eval(context);
  6140. if (context.isMathOn()) {
  6141. if (a instanceof Dimension && b instanceof Color) {
  6142. a = a.toColor();
  6143. }
  6144. if (b instanceof Dimension && a instanceof Color) {
  6145. b = b.toColor();
  6146. }
  6147. if (!a.operate) {
  6148. throw { type: "Operation",
  6149. message: "Operation on an invalid type" };
  6150. }
  6151. return a.operate(context, this.op, b);
  6152. } else {
  6153. return new Operation(this.op, [a, b], this.isSpaced);
  6154. }
  6155. };
  6156. Operation.prototype.genCSS = function (context, output) {
  6157. this.operands[0].genCSS(context, output);
  6158. if (this.isSpaced) {
  6159. output.add(" ");
  6160. }
  6161. output.add(this.op);
  6162. if (this.isSpaced) {
  6163. output.add(" ");
  6164. }
  6165. this.operands[1].genCSS(context, output);
  6166. };
  6167. module.exports = Operation;
  6168. },{"./color":47,"./dimension":53,"./node":67}],69:[function(require,module,exports){
  6169. var Node = require("./node");
  6170. var Paren = function (node) {
  6171. this.value = node;
  6172. };
  6173. Paren.prototype = new Node();
  6174. Paren.prototype.type = "Paren";
  6175. Paren.prototype.genCSS = function (context, output) {
  6176. output.add('(');
  6177. this.value.genCSS(context, output);
  6178. output.add(')');
  6179. };
  6180. Paren.prototype.eval = function (context) {
  6181. return new Paren(this.value.eval(context));
  6182. };
  6183. module.exports = Paren;
  6184. },{"./node":67}],70:[function(require,module,exports){
  6185. var Node = require("./node"),
  6186. JsEvalNode = require("./js-eval-node"),
  6187. Variable = require("./variable");
  6188. var Quoted = function (str, content, escaped, index, currentFileInfo) {
  6189. this.escaped = (escaped == null) ? true : escaped;
  6190. this.value = content || '';
  6191. this.quote = str.charAt(0);
  6192. this.index = index;
  6193. this.currentFileInfo = currentFileInfo;
  6194. };
  6195. Quoted.prototype = new JsEvalNode();
  6196. Quoted.prototype.type = "Quoted";
  6197. Quoted.prototype.genCSS = function (context, output) {
  6198. if (!this.escaped) {
  6199. output.add(this.quote, this.currentFileInfo, this.index);
  6200. }
  6201. output.add(this.value);
  6202. if (!this.escaped) {
  6203. output.add(this.quote);
  6204. }
  6205. };
  6206. Quoted.prototype.containsVariables = function() {
  6207. return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/);
  6208. };
  6209. Quoted.prototype.eval = function (context) {
  6210. var that = this, value = this.value;
  6211. var javascriptReplacement = function (_, exp) {
  6212. return String(that.evaluateJavaScript(exp, context));
  6213. };
  6214. var interpolationReplacement = function (_, name) {
  6215. var v = new Variable('@' + name, that.index, that.currentFileInfo).eval(context, true);
  6216. return (v instanceof Quoted) ? v.value : v.toCSS();
  6217. };
  6218. function iterativeReplace(value, regexp, replacementFnc) {
  6219. var evaluatedValue = value;
  6220. do {
  6221. value = evaluatedValue;
  6222. evaluatedValue = value.replace(regexp, replacementFnc);
  6223. } while (value !== evaluatedValue);
  6224. return evaluatedValue;
  6225. }
  6226. value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
  6227. value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement);
  6228. return new Quoted(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
  6229. };
  6230. Quoted.prototype.compare = function (other) {
  6231. // when comparing quoted strings allow the quote to differ
  6232. if (other.type === "Quoted" && !this.escaped && !other.escaped) {
  6233. return Node.numericCompare(this.value, other.value);
  6234. } else {
  6235. return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
  6236. }
  6237. };
  6238. module.exports = Quoted;
  6239. },{"./js-eval-node":61,"./node":67,"./variable":79}],71:[function(require,module,exports){
  6240. var Node = require("./node"),
  6241. Value = require("./value"),
  6242. Keyword = require("./keyword");
  6243. var Rule = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
  6244. this.name = name;
  6245. this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ??
  6246. this.important = important ? ' ' + important.trim() : '';
  6247. this.merge = merge;
  6248. this.index = index;
  6249. this.currentFileInfo = currentFileInfo;
  6250. this.inline = inline || false;
  6251. this.variable = (variable !== undefined) ? variable
  6252. : (name.charAt && (name.charAt(0) === '@'));
  6253. };
  6254. function evalName(context, name) {
  6255. var value = "", i, n = name.length,
  6256. output = {add: function (s) {value += s;}};
  6257. for (i = 0; i < n; i++) {
  6258. name[i].eval(context).genCSS(context, output);
  6259. }
  6260. return value;
  6261. }
  6262. Rule.prototype = new Node();
  6263. Rule.prototype.type = "Rule";
  6264. Rule.prototype.genCSS = function (context, output) {
  6265. output.add(this.name + (context.compress ? ':' : ': '), this.currentFileInfo, this.index);
  6266. try {
  6267. this.value.genCSS(context, output);
  6268. }
  6269. catch(e) {
  6270. e.index = this.index;
  6271. e.filename = this.currentFileInfo.filename;
  6272. throw e;
  6273. }
  6274. output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this.currentFileInfo, this.index);
  6275. };
  6276. Rule.prototype.eval = function (context) {
  6277. var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable;
  6278. if (typeof name !== "string") {
  6279. // expand 'primitive' name directly to get
  6280. // things faster (~10% for benchmark.less):
  6281. name = (name.length === 1) && (name[0] instanceof Keyword) ?
  6282. name[0].value : evalName(context, name);
  6283. variable = false; // never treat expanded interpolation as new variable name
  6284. }
  6285. if (name === "font" && !context.strictMath) {
  6286. strictMathBypass = true;
  6287. context.strictMath = true;
  6288. }
  6289. try {
  6290. context.importantScope.push({});
  6291. evaldValue = this.value.eval(context);
  6292. if (!this.variable && evaldValue.type === "DetachedRuleset") {
  6293. throw { message: "Rulesets cannot be evaluated on a property.",
  6294. index: this.index, filename: this.currentFileInfo.filename };
  6295. }
  6296. var important = this.important,
  6297. importantResult = context.importantScope.pop();
  6298. if (!important && importantResult.important) {
  6299. important = importantResult.important;
  6300. }
  6301. return new Rule(name,
  6302. evaldValue,
  6303. important,
  6304. this.merge,
  6305. this.index, this.currentFileInfo, this.inline,
  6306. variable);
  6307. }
  6308. catch(e) {
  6309. if (typeof e.index !== 'number') {
  6310. e.index = this.index;
  6311. e.filename = this.currentFileInfo.filename;
  6312. }
  6313. throw e;
  6314. }
  6315. finally {
  6316. if (strictMathBypass) {
  6317. context.strictMath = false;
  6318. }
  6319. }
  6320. };
  6321. Rule.prototype.makeImportant = function () {
  6322. return new Rule(this.name,
  6323. this.value,
  6324. "!important",
  6325. this.merge,
  6326. this.index, this.currentFileInfo, this.inline);
  6327. };
  6328. module.exports = Rule;
  6329. },{"./keyword":62,"./node":67,"./value":78}],72:[function(require,module,exports){
  6330. var Node = require("./node"),
  6331. Variable = require("./variable");
  6332. var RulesetCall = function (variable) {
  6333. this.variable = variable;
  6334. };
  6335. RulesetCall.prototype = new Node();
  6336. RulesetCall.prototype.type = "RulesetCall";
  6337. RulesetCall.prototype.eval = function (context) {
  6338. var detachedRuleset = new Variable(this.variable).eval(context);
  6339. return detachedRuleset.callEval(context);
  6340. };
  6341. module.exports = RulesetCall;
  6342. },{"./node":67,"./variable":79}],73:[function(require,module,exports){
  6343. var Node = require("./node"),
  6344. Rule = require("./rule"),
  6345. Selector = require("./selector"),
  6346. Element = require("./element"),
  6347. Paren = require("./paren"),
  6348. contexts = require("../contexts"),
  6349. defaultFunc = require("../functions/default"),
  6350. getDebugInfo = require("./debug-info");
  6351. var Ruleset = function (selectors, rules, strictImports) {
  6352. this.selectors = selectors;
  6353. this.rules = rules;
  6354. this._lookups = {};
  6355. this.strictImports = strictImports;
  6356. };
  6357. Ruleset.prototype = new Node();
  6358. Ruleset.prototype.type = "Ruleset";
  6359. Ruleset.prototype.isRuleset = true;
  6360. Ruleset.prototype.isRulesetLike = true;
  6361. Ruleset.prototype.accept = function (visitor) {
  6362. if (this.paths) {
  6363. visitor.visitArray(this.paths, true);
  6364. } else if (this.selectors) {
  6365. this.selectors = visitor.visitArray(this.selectors);
  6366. }
  6367. if (this.rules && this.rules.length) {
  6368. this.rules = visitor.visitArray(this.rules);
  6369. }
  6370. };
  6371. Ruleset.prototype.eval = function (context) {
  6372. var thisSelectors = this.selectors, selectors,
  6373. selCnt, selector, i, hasOnePassingSelector = false;
  6374. if (thisSelectors && (selCnt = thisSelectors.length)) {
  6375. selectors = [];
  6376. defaultFunc.error({
  6377. type: "Syntax",
  6378. message: "it is currently only allowed in parametric mixin guards,"
  6379. });
  6380. for (i = 0; i < selCnt; i++) {
  6381. selector = thisSelectors[i].eval(context);
  6382. selectors.push(selector);
  6383. if (selector.evaldCondition) {
  6384. hasOnePassingSelector = true;
  6385. }
  6386. }
  6387. defaultFunc.reset();
  6388. } else {
  6389. hasOnePassingSelector = true;
  6390. }
  6391. var rules = this.rules ? this.rules.slice(0) : null,
  6392. ruleset = new Ruleset(selectors, rules, this.strictImports),
  6393. rule, subRule;
  6394. ruleset.originalRuleset = this;
  6395. ruleset.root = this.root;
  6396. ruleset.firstRoot = this.firstRoot;
  6397. ruleset.allowImports = this.allowImports;
  6398. if (this.debugInfo) {
  6399. ruleset.debugInfo = this.debugInfo;
  6400. }
  6401. if (!hasOnePassingSelector) {
  6402. rules.length = 0;
  6403. }
  6404. // push the current ruleset to the frames stack
  6405. var ctxFrames = context.frames;
  6406. ctxFrames.unshift(ruleset);
  6407. // currrent selectors
  6408. var ctxSelectors = context.selectors;
  6409. if (!ctxSelectors) {
  6410. context.selectors = ctxSelectors = [];
  6411. }
  6412. ctxSelectors.unshift(this.selectors);
  6413. // Evaluate imports
  6414. if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
  6415. ruleset.evalImports(context);
  6416. }
  6417. // Store the frames around mixin definitions,
  6418. // so they can be evaluated like closures when the time comes.
  6419. var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0;
  6420. for (i = 0; i < rsRuleCnt; i++) {
  6421. if (rsRules[i].evalFirst) {
  6422. rsRules[i] = rsRules[i].eval(context);
  6423. }
  6424. }
  6425. var mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0;
  6426. // Evaluate mixin calls.
  6427. for (i = 0; i < rsRuleCnt; i++) {
  6428. if (rsRules[i].type === "MixinCall") {
  6429. /*jshint loopfunc:true */
  6430. rules = rsRules[i].eval(context).filter(function(r) {
  6431. if ((r instanceof Rule) && r.variable) {
  6432. // do not pollute the scope if the variable is
  6433. // already there. consider returning false here
  6434. // but we need a way to "return" variable from mixins
  6435. return !(ruleset.variable(r.name));
  6436. }
  6437. return true;
  6438. });
  6439. rsRules.splice.apply(rsRules, [i, 1].concat(rules));
  6440. rsRuleCnt += rules.length - 1;
  6441. i += rules.length - 1;
  6442. ruleset.resetCache();
  6443. } else if (rsRules[i].type === "RulesetCall") {
  6444. /*jshint loopfunc:true */
  6445. rules = rsRules[i].eval(context).rules.filter(function(r) {
  6446. if ((r instanceof Rule) && r.variable) {
  6447. // do not pollute the scope at all
  6448. return false;
  6449. }
  6450. return true;
  6451. });
  6452. rsRules.splice.apply(rsRules, [i, 1].concat(rules));
  6453. rsRuleCnt += rules.length - 1;
  6454. i += rules.length - 1;
  6455. ruleset.resetCache();
  6456. }
  6457. }
  6458. // Evaluate everything else
  6459. for (i = 0; i < rsRules.length; i++) {
  6460. rule = rsRules[i];
  6461. if (!rule.evalFirst) {
  6462. rsRules[i] = rule = rule.eval ? rule.eval(context) : rule;
  6463. }
  6464. }
  6465. // Evaluate everything else
  6466. for (i = 0; i < rsRules.length; i++) {
  6467. rule = rsRules[i];
  6468. // for rulesets, check if it is a css guard and can be removed
  6469. if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) {
  6470. // check if it can be folded in (e.g. & where)
  6471. if (rule.selectors[0].isJustParentSelector()) {
  6472. rsRules.splice(i--, 1);
  6473. for (var j = 0; j < rule.rules.length; j++) {
  6474. subRule = rule.rules[j];
  6475. if (!(subRule instanceof Rule) || !subRule.variable) {
  6476. rsRules.splice(++i, 0, subRule);
  6477. }
  6478. }
  6479. }
  6480. }
  6481. }
  6482. // Pop the stack
  6483. ctxFrames.shift();
  6484. ctxSelectors.shift();
  6485. if (context.mediaBlocks) {
  6486. for (i = mediaBlockCount; i < context.mediaBlocks.length; i++) {
  6487. context.mediaBlocks[i].bubbleSelectors(selectors);
  6488. }
  6489. }
  6490. return ruleset;
  6491. };
  6492. Ruleset.prototype.evalImports = function(context) {
  6493. var rules = this.rules, i, importRules;
  6494. if (!rules) { return; }
  6495. for (i = 0; i < rules.length; i++) {
  6496. if (rules[i].type === "Import") {
  6497. importRules = rules[i].eval(context);
  6498. if (importRules && importRules.length) {
  6499. rules.splice.apply(rules, [i, 1].concat(importRules));
  6500. i+= importRules.length - 1;
  6501. } else {
  6502. rules.splice(i, 1, importRules);
  6503. }
  6504. this.resetCache();
  6505. }
  6506. }
  6507. };
  6508. Ruleset.prototype.makeImportant = function() {
  6509. var result = new Ruleset(this.selectors, this.rules.map(function (r) {
  6510. if (r.makeImportant) {
  6511. return r.makeImportant();
  6512. } else {
  6513. return r;
  6514. }
  6515. }), this.strictImports);
  6516. return result;
  6517. };
  6518. Ruleset.prototype.matchArgs = function (args) {
  6519. return !args || args.length === 0;
  6520. };
  6521. // lets you call a css selector with a guard
  6522. Ruleset.prototype.matchCondition = function (args, context) {
  6523. var lastSelector = this.selectors[this.selectors.length - 1];
  6524. if (!lastSelector.evaldCondition) {
  6525. return false;
  6526. }
  6527. if (lastSelector.condition &&
  6528. !lastSelector.condition.eval(
  6529. new contexts.Eval(context,
  6530. context.frames))) {
  6531. return false;
  6532. }
  6533. return true;
  6534. };
  6535. Ruleset.prototype.resetCache = function () {
  6536. this._rulesets = null;
  6537. this._variables = null;
  6538. this._lookups = {};
  6539. };
  6540. Ruleset.prototype.variables = function () {
  6541. if (!this._variables) {
  6542. this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
  6543. if (r instanceof Rule && r.variable === true) {
  6544. hash[r.name] = r;
  6545. }
  6546. // when evaluating variables in an import statement, imports have not been eval'd
  6547. // so we need to go inside import statements.
  6548. // guard against root being a string (in the case of inlined less)
  6549. if (r.type === "Import" && r.root && r.root.variables) {
  6550. var vars = r.root.variables();
  6551. for (var name in vars) {
  6552. if (vars.hasOwnProperty(name)) {
  6553. hash[name] = vars[name];
  6554. }
  6555. }
  6556. }
  6557. return hash;
  6558. }, {});
  6559. }
  6560. return this._variables;
  6561. };
  6562. Ruleset.prototype.variable = function (name) {
  6563. return this.variables()[name];
  6564. };
  6565. Ruleset.prototype.rulesets = function () {
  6566. if (!this.rules) { return null; }
  6567. var filtRules = [], rules = this.rules, cnt = rules.length,
  6568. i, rule;
  6569. for (i = 0; i < cnt; i++) {
  6570. rule = rules[i];
  6571. if (rule.isRuleset) {
  6572. filtRules.push(rule);
  6573. }
  6574. }
  6575. return filtRules;
  6576. };
  6577. Ruleset.prototype.prependRule = function (rule) {
  6578. var rules = this.rules;
  6579. if (rules) {
  6580. rules.unshift(rule);
  6581. } else {
  6582. this.rules = [ rule ];
  6583. }
  6584. };
  6585. Ruleset.prototype.find = function (selector, self, filter) {
  6586. self = self || this;
  6587. var rules = [], match, foundMixins,
  6588. key = selector.toCSS();
  6589. if (key in this._lookups) { return this._lookups[key]; }
  6590. this.rulesets().forEach(function (rule) {
  6591. if (rule !== self) {
  6592. for (var j = 0; j < rule.selectors.length; j++) {
  6593. match = selector.match(rule.selectors[j]);
  6594. if (match) {
  6595. if (selector.elements.length > match) {
  6596. if (!filter || filter(rule)) {
  6597. foundMixins = rule.find(new Selector(selector.elements.slice(match)), self, filter);
  6598. for (var i = 0; i < foundMixins.length; ++i) {
  6599. foundMixins[i].path.push(rule);
  6600. }
  6601. Array.prototype.push.apply(rules, foundMixins);
  6602. }
  6603. } else {
  6604. rules.push({ rule: rule, path: []});
  6605. }
  6606. break;
  6607. }
  6608. }
  6609. }
  6610. });
  6611. this._lookups[key] = rules;
  6612. return rules;
  6613. };
  6614. Ruleset.prototype.genCSS = function (context, output) {
  6615. var i, j,
  6616. charsetRuleNodes = [],
  6617. ruleNodes = [],
  6618. rulesetNodes = [],
  6619. rulesetNodeCnt,
  6620. debugInfo, // Line number debugging
  6621. rule,
  6622. path;
  6623. context.tabLevel = (context.tabLevel || 0);
  6624. if (!this.root) {
  6625. context.tabLevel++;
  6626. }
  6627. var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(" "),
  6628. tabSetStr = context.compress ? '' : Array(context.tabLevel).join(" "),
  6629. sep;
  6630. function isRulesetLikeNode(rule, root) {
  6631. // if it has nested rules, then it should be treated like a ruleset
  6632. // medias and comments do not have nested rules, but should be treated like rulesets anyway
  6633. // some directives and anonymous nodes are ruleset like, others are not
  6634. if (typeof rule.isRulesetLike === "boolean") {
  6635. return rule.isRulesetLike;
  6636. } else if (typeof rule.isRulesetLike === "function") {
  6637. return rule.isRulesetLike(root);
  6638. }
  6639. //anything else is assumed to be a rule
  6640. return false;
  6641. }
  6642. for (i = 0; i < this.rules.length; i++) {
  6643. rule = this.rules[i];
  6644. if (isRulesetLikeNode(rule, this.root)) {
  6645. rulesetNodes.push(rule);
  6646. } else {
  6647. //charsets should float on top of everything
  6648. if (rule.isCharset && rule.isCharset()) {
  6649. charsetRuleNodes.push(rule);
  6650. } else {
  6651. ruleNodes.push(rule);
  6652. }
  6653. }
  6654. }
  6655. ruleNodes = charsetRuleNodes.concat(ruleNodes);
  6656. // If this is the root node, we don't render
  6657. // a selector, or {}.
  6658. if (!this.root) {
  6659. debugInfo = getDebugInfo(context, this, tabSetStr);
  6660. if (debugInfo) {
  6661. output.add(debugInfo);
  6662. output.add(tabSetStr);
  6663. }
  6664. var paths = this.paths, pathCnt = paths.length,
  6665. pathSubCnt;
  6666. sep = context.compress ? ',' : (',\n' + tabSetStr);
  6667. for (i = 0; i < pathCnt; i++) {
  6668. path = paths[i];
  6669. if (!(pathSubCnt = path.length)) { continue; }
  6670. if (i > 0) { output.add(sep); }
  6671. context.firstSelector = true;
  6672. path[0].genCSS(context, output);
  6673. context.firstSelector = false;
  6674. for (j = 1; j < pathSubCnt; j++) {
  6675. path[j].genCSS(context, output);
  6676. }
  6677. }
  6678. output.add((context.compress ? '{' : ' {\n') + tabRuleStr);
  6679. }
  6680. // Compile rules and rulesets
  6681. for (i = 0; i < ruleNodes.length; i++) {
  6682. rule = ruleNodes[i];
  6683. // @page{ directive ends up with root elements inside it, a mix of rules and rulesets
  6684. // In this instance we do not know whether it is the last property
  6685. if (i + 1 === ruleNodes.length && (!this.root || rulesetNodes.length === 0 || this.firstRoot)) {
  6686. context.lastRule = true;
  6687. }
  6688. if (rule.genCSS) {
  6689. rule.genCSS(context, output);
  6690. } else if (rule.value) {
  6691. output.add(rule.value.toString());
  6692. }
  6693. if (!context.lastRule) {
  6694. output.add(context.compress ? '' : ('\n' + tabRuleStr));
  6695. } else {
  6696. context.lastRule = false;
  6697. }
  6698. }
  6699. if (!this.root) {
  6700. output.add((context.compress ? '}' : '\n' + tabSetStr + '}'));
  6701. context.tabLevel--;
  6702. }
  6703. sep = (context.compress ? "" : "\n") + (this.root ? tabRuleStr : tabSetStr);
  6704. rulesetNodeCnt = rulesetNodes.length;
  6705. if (rulesetNodeCnt) {
  6706. if (ruleNodes.length && sep) { output.add(sep); }
  6707. rulesetNodes[0].genCSS(context, output);
  6708. for (i = 1; i < rulesetNodeCnt; i++) {
  6709. if (sep) { output.add(sep); }
  6710. rulesetNodes[i].genCSS(context, output);
  6711. }
  6712. }
  6713. if (!output.isEmpty() && !context.compress && this.firstRoot) {
  6714. output.add('\n');
  6715. }
  6716. };
  6717. Ruleset.prototype.markReferenced = function () {
  6718. var s;
  6719. if (this.selectors) {
  6720. for (s = 0; s < this.selectors.length; s++) {
  6721. this.selectors[s].markReferenced();
  6722. }
  6723. }
  6724. if (this.rules) {
  6725. for (s = 0; s < this.rules.length; s++) {
  6726. if (this.rules[s].markReferenced) {
  6727. this.rules[s].markReferenced();
  6728. }
  6729. }
  6730. }
  6731. };
  6732. Ruleset.prototype.getIsReferenced = function() {
  6733. var i, j, path, selector;
  6734. if (this.paths) {
  6735. for (i = 0; i < this.paths.length; i++) {
  6736. path = this.paths[i];
  6737. for (j = 0; j < path.length; j++) {
  6738. if (path[j].getIsReferenced && path[j].getIsReferenced()) {
  6739. return true;
  6740. }
  6741. }
  6742. }
  6743. }
  6744. if (this.selectors) {
  6745. for (i = 0; i < this.selectors.length; i++) {
  6746. selector = this.selectors[i];
  6747. if (selector.getIsReferenced && selector.getIsReferenced()) {
  6748. return true;
  6749. }
  6750. }
  6751. }
  6752. return false;
  6753. };
  6754. Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
  6755. for (var s = 0; s < selectors.length; s++) {
  6756. this.joinSelector(paths, context, selectors[s]);
  6757. }
  6758. };
  6759. Ruleset.prototype.joinSelector = function (paths, context, selector) {
  6760. function createParenthesis(elementsToPak, originalElement) {
  6761. var replacementParen, j;
  6762. if (elementsToPak.length === 0) {
  6763. replacementParen = new Paren(elementsToPak[0]);
  6764. } else {
  6765. var insideParent = [];
  6766. for (j = 0; j < elementsToPak.length; j++) {
  6767. insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
  6768. }
  6769. replacementParen = new Paren(new Selector(insideParent));
  6770. }
  6771. return replacementParen;
  6772. }
  6773. function createSelector(containedElement, originalElement) {
  6774. var element, selector;
  6775. element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
  6776. selector = new Selector([element]);
  6777. return selector;
  6778. }
  6779. // replace all parent selectors inside `inSelector` by content of `context` array
  6780. // resulting selectors are returned inside `paths` array
  6781. // returns true if `inSelector` contained at least one parent selector
  6782. function replaceParentSelector(paths, context, inSelector) {
  6783. // The paths are [[Selector]]
  6784. // The first list is a list of comma separated selectors
  6785. // The inner list is a list of inheritance separated selectors
  6786. // e.g.
  6787. // .a, .b {
  6788. // .c {
  6789. // }
  6790. // }
  6791. // == [[.a] [.c]] [[.b] [.c]]
  6792. //
  6793. var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector;
  6794. function findNestedSelector(element) {
  6795. var maybeSelector;
  6796. if (element.value.type !== 'Paren') {
  6797. return null;
  6798. }
  6799. maybeSelector = element.value.value;
  6800. if (maybeSelector.type !== 'Selector') {
  6801. return null;
  6802. }
  6803. return maybeSelector;
  6804. }
  6805. // the elements from the current selector so far
  6806. currentElements = [];
  6807. // the current list of new selectors to add to the path.
  6808. // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
  6809. // by the parents
  6810. newSelectors = [
  6811. []
  6812. ];
  6813. for (i = 0; i < inSelector.elements.length; i++) {
  6814. el = inSelector.elements[i];
  6815. // non parent reference elements just get added
  6816. if (el.value !== "&") {
  6817. var nestedSelector = findNestedSelector(el);
  6818. if (nestedSelector != null) {
  6819. // merge the current list of non parent selector elements
  6820. // on to the current list of selectors to add
  6821. mergeElementsOnToSelectors(currentElements, newSelectors);
  6822. var nestedPaths = [], replaced, replacedNewSelectors = [];
  6823. replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
  6824. hadParentSelector = hadParentSelector || replaced;
  6825. //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
  6826. for (k = 0; k < nestedPaths.length; k++) {
  6827. var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
  6828. addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
  6829. }
  6830. newSelectors = replacedNewSelectors;
  6831. currentElements = [];
  6832. } else {
  6833. currentElements.push(el);
  6834. }
  6835. } else {
  6836. hadParentSelector = true;
  6837. // the new list of selectors to add
  6838. selectorsMultiplied = [];
  6839. // merge the current list of non parent selector elements
  6840. // on to the current list of selectors to add
  6841. mergeElementsOnToSelectors(currentElements, newSelectors);
  6842. // loop through our current selectors
  6843. for (j = 0; j < newSelectors.length; j++) {
  6844. sel = newSelectors[j];
  6845. // if we don't have any parent paths, the & might be in a mixin so that it can be used
  6846. // whether there are parents or not
  6847. if (context.length === 0) {
  6848. // the combinator used on el should now be applied to the next element instead so that
  6849. // it is not lost
  6850. if (sel.length > 0) {
  6851. sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
  6852. }
  6853. selectorsMultiplied.push(sel);
  6854. }
  6855. else {
  6856. // and the parent selectors
  6857. for (k = 0; k < context.length; k++) {
  6858. // We need to put the current selectors
  6859. // then join the last selector's elements on to the parents selectors
  6860. var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
  6861. // add that to our new set of selectors
  6862. selectorsMultiplied.push(newSelectorPath);
  6863. }
  6864. }
  6865. }
  6866. // our new selectors has been multiplied, so reset the state
  6867. newSelectors = selectorsMultiplied;
  6868. currentElements = [];
  6869. }
  6870. }
  6871. // if we have any elements left over (e.g. .a& .b == .b)
  6872. // add them on to all the current selectors
  6873. mergeElementsOnToSelectors(currentElements, newSelectors);
  6874. for (i = 0; i < newSelectors.length; i++) {
  6875. length = newSelectors[i].length;
  6876. if (length > 0) {
  6877. paths.push(newSelectors[i]);
  6878. lastSelector = newSelectors[i][length - 1];
  6879. newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
  6880. }
  6881. }
  6882. return hadParentSelector;
  6883. }
  6884. // joins selector path from `beginningPath` with selector path in `addPath`
  6885. // `replacedElement` contains element that is being replaced by `addPath`
  6886. // returns concatenated path
  6887. function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
  6888. var newSelectorPath, lastSelector, newJoinedSelector;
  6889. // our new selector path
  6890. newSelectorPath = [];
  6891. //construct the joined selector - if & is the first thing this will be empty,
  6892. // if not newJoinedSelector will be the last set of elements in the selector
  6893. if (beginningPath.length > 0) {
  6894. newSelectorPath = beginningPath.slice(0);
  6895. lastSelector = newSelectorPath.pop();
  6896. newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
  6897. }
  6898. else {
  6899. newJoinedSelector = originalSelector.createDerived([]);
  6900. }
  6901. if (addPath.length > 0) {
  6902. // /deep/ is a combinator that is valid without anything in front of it
  6903. // so if the & does not have a combinator that is "" or " " then
  6904. // and there is a combinator on the parent, then grab that.
  6905. // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
  6906. var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
  6907. if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
  6908. combinator = parentEl.combinator;
  6909. }
  6910. // join the elements so far with the first part of the parent
  6911. newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
  6912. newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
  6913. }
  6914. // now add the joined selector - but only if it is not empty
  6915. if (newJoinedSelector.elements.length !== 0) {
  6916. newSelectorPath.push(newJoinedSelector);
  6917. }
  6918. //put together the parent selectors after the join (e.g. the rest of the parent)
  6919. if (addPath.length > 1) {
  6920. newSelectorPath = newSelectorPath.concat(addPath.slice(1));
  6921. }
  6922. return newSelectorPath;
  6923. }
  6924. // joins selector path from `beginningPath` with every selector path in `addPaths` array
  6925. // `replacedElement` contains element that is being replaced by `addPath`
  6926. // returns array with all concatenated paths
  6927. function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
  6928. var j;
  6929. for (j = 0; j < beginningPath.length; j++) {
  6930. var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
  6931. result.push(newSelectorPath);
  6932. }
  6933. return result;
  6934. }
  6935. function mergeElementsOnToSelectors(elements, selectors) {
  6936. var i, sel;
  6937. if (elements.length === 0) {
  6938. return ;
  6939. }
  6940. if (selectors.length === 0) {
  6941. selectors.push([ new Selector(elements) ]);
  6942. return;
  6943. }
  6944. for (i = 0; i < selectors.length; i++) {
  6945. sel = selectors[i];
  6946. // if the previous thing in sel is a parent this needs to join on to it
  6947. if (sel.length > 0) {
  6948. sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
  6949. }
  6950. else {
  6951. sel.push(new Selector(elements));
  6952. }
  6953. }
  6954. }
  6955. // joinSelector code follows
  6956. var i, newPaths, hadParentSelector;
  6957. newPaths = [];
  6958. hadParentSelector = replaceParentSelector(newPaths, context, selector);
  6959. if (!hadParentSelector) {
  6960. if (context.length > 0) {
  6961. newPaths = [];
  6962. for (i = 0; i < context.length; i++) {
  6963. newPaths.push(context[i].concat(selector));
  6964. }
  6965. }
  6966. else {
  6967. newPaths = [[selector]];
  6968. }
  6969. }
  6970. for (i = 0; i < newPaths.length; i++) {
  6971. paths.push(newPaths[i]);
  6972. }
  6973. };
  6974. module.exports = Ruleset;
  6975. },{"../contexts":10,"../functions/default":19,"./debug-info":51,"./element":55,"./node":67,"./paren":69,"./rule":71,"./selector":74}],74:[function(require,module,exports){
  6976. var Node = require("./node");
  6977. var Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
  6978. this.elements = elements;
  6979. this.extendList = extendList;
  6980. this.condition = condition;
  6981. this.currentFileInfo = currentFileInfo || {};
  6982. this.isReferenced = isReferenced;
  6983. if (!condition) {
  6984. this.evaldCondition = true;
  6985. }
  6986. };
  6987. Selector.prototype = new Node();
  6988. Selector.prototype.type = "Selector";
  6989. Selector.prototype.accept = function (visitor) {
  6990. if (this.elements) {
  6991. this.elements = visitor.visitArray(this.elements);
  6992. }
  6993. if (this.extendList) {
  6994. this.extendList = visitor.visitArray(this.extendList);
  6995. }
  6996. if (this.condition) {
  6997. this.condition = visitor.visit(this.condition);
  6998. }
  6999. };
  7000. Selector.prototype.createDerived = function(elements, extendList, evaldCondition) {
  7001. evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
  7002. var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced);
  7003. newSelector.evaldCondition = evaldCondition;
  7004. newSelector.mediaEmpty = this.mediaEmpty;
  7005. return newSelector;
  7006. };
  7007. Selector.prototype.match = function (other) {
  7008. var elements = this.elements,
  7009. len = elements.length,
  7010. olen, i;
  7011. other.CacheElements();
  7012. olen = other._elements.length;
  7013. if (olen === 0 || len < olen) {
  7014. return 0;
  7015. } else {
  7016. for (i = 0; i < olen; i++) {
  7017. if (elements[i].value !== other._elements[i]) {
  7018. return 0;
  7019. }
  7020. }
  7021. }
  7022. return olen; // return number of matched elements
  7023. };
  7024. Selector.prototype.CacheElements = function() {
  7025. if (this._elements) {
  7026. return;
  7027. }
  7028. var elements = this.elements.map( function(v) {
  7029. return v.combinator.value + (v.value.value || v.value);
  7030. }).join("").match(/[,&#\*\.\w-]([\w-]|(\\.))*/g);
  7031. if (elements) {
  7032. if (elements[0] === "&") {
  7033. elements.shift();
  7034. }
  7035. } else {
  7036. elements = [];
  7037. }
  7038. this._elements = elements;
  7039. };
  7040. Selector.prototype.isJustParentSelector = function() {
  7041. return !this.mediaEmpty &&
  7042. this.elements.length === 1 &&
  7043. this.elements[0].value === '&' &&
  7044. (this.elements[0].combinator.value === ' ' || this.elements[0].combinator.value === '');
  7045. };
  7046. Selector.prototype.eval = function (context) {
  7047. var evaldCondition = this.condition && this.condition.eval(context),
  7048. elements = this.elements, extendList = this.extendList;
  7049. elements = elements && elements.map(function (e) { return e.eval(context); });
  7050. extendList = extendList && extendList.map(function(extend) { return extend.eval(context); });
  7051. return this.createDerived(elements, extendList, evaldCondition);
  7052. };
  7053. Selector.prototype.genCSS = function (context, output) {
  7054. var i, element;
  7055. if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") {
  7056. output.add(' ', this.currentFileInfo, this.index);
  7057. }
  7058. if (!this._css) {
  7059. //TODO caching? speed comparison?
  7060. for (i = 0; i < this.elements.length; i++) {
  7061. element = this.elements[i];
  7062. element.genCSS(context, output);
  7063. }
  7064. }
  7065. };
  7066. Selector.prototype.markReferenced = function () {
  7067. this.isReferenced = true;
  7068. };
  7069. Selector.prototype.getIsReferenced = function() {
  7070. return !this.currentFileInfo.reference || this.isReferenced;
  7071. };
  7072. Selector.prototype.getIsOutput = function() {
  7073. return this.evaldCondition;
  7074. };
  7075. module.exports = Selector;
  7076. },{"./node":67}],75:[function(require,module,exports){
  7077. var Node = require("./node");
  7078. var UnicodeDescriptor = function (value) {
  7079. this.value = value;
  7080. };
  7081. UnicodeDescriptor.prototype = new Node();
  7082. UnicodeDescriptor.prototype.type = "UnicodeDescriptor";
  7083. module.exports = UnicodeDescriptor;
  7084. },{"./node":67}],76:[function(require,module,exports){
  7085. var Node = require("./node"),
  7086. unitConversions = require("../data/unit-conversions");
  7087. var Unit = function (numerator, denominator, backupUnit) {
  7088. this.numerator = numerator ? numerator.slice(0).sort() : [];
  7089. this.denominator = denominator ? denominator.slice(0).sort() : [];
  7090. if (backupUnit) {
  7091. this.backupUnit = backupUnit;
  7092. } else if (numerator && numerator.length) {
  7093. this.backupUnit = numerator[0];
  7094. }
  7095. };
  7096. Unit.prototype = new Node();
  7097. Unit.prototype.type = "Unit";
  7098. Unit.prototype.clone = function () {
  7099. return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
  7100. };
  7101. Unit.prototype.genCSS = function (context, output) {
  7102. // Dimension checks the unit is singular and throws an error if in strict math mode.
  7103. var strictUnits = context && context.strictUnits;
  7104. if (this.numerator.length === 1) {
  7105. output.add(this.numerator[0]); // the ideal situation
  7106. } else if (!strictUnits && this.backupUnit) {
  7107. output.add(this.backupUnit);
  7108. } else if (!strictUnits && this.denominator.length) {
  7109. output.add(this.denominator[0]);
  7110. }
  7111. };
  7112. Unit.prototype.toString = function () {
  7113. var i, returnStr = this.numerator.join("*");
  7114. for (i = 0; i < this.denominator.length; i++) {
  7115. returnStr += "/" + this.denominator[i];
  7116. }
  7117. return returnStr;
  7118. };
  7119. Unit.prototype.compare = function (other) {
  7120. return this.is(other.toString()) ? 0 : undefined;
  7121. };
  7122. Unit.prototype.is = function (unitString) {
  7123. return this.toString().toUpperCase() === unitString.toUpperCase();
  7124. };
  7125. Unit.prototype.isLength = function () {
  7126. return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
  7127. };
  7128. Unit.prototype.isEmpty = function () {
  7129. return this.numerator.length === 0 && this.denominator.length === 0;
  7130. };
  7131. Unit.prototype.isSingular = function() {
  7132. return this.numerator.length <= 1 && this.denominator.length === 0;
  7133. };
  7134. Unit.prototype.map = function(callback) {
  7135. var i;
  7136. for (i = 0; i < this.numerator.length; i++) {
  7137. this.numerator[i] = callback(this.numerator[i], false);
  7138. }
  7139. for (i = 0; i < this.denominator.length; i++) {
  7140. this.denominator[i] = callback(this.denominator[i], true);
  7141. }
  7142. };
  7143. Unit.prototype.usedUnits = function() {
  7144. var group, result = {}, mapUnit;
  7145. mapUnit = function (atomicUnit) {
  7146. /*jshint loopfunc:true */
  7147. if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
  7148. result[groupName] = atomicUnit;
  7149. }
  7150. return atomicUnit;
  7151. };
  7152. for (var groupName in unitConversions) {
  7153. if (unitConversions.hasOwnProperty(groupName)) {
  7154. group = unitConversions[groupName];
  7155. this.map(mapUnit);
  7156. }
  7157. }
  7158. return result;
  7159. };
  7160. Unit.prototype.cancel = function () {
  7161. var counter = {}, atomicUnit, i;
  7162. for (i = 0; i < this.numerator.length; i++) {
  7163. atomicUnit = this.numerator[i];
  7164. counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
  7165. }
  7166. for (i = 0; i < this.denominator.length; i++) {
  7167. atomicUnit = this.denominator[i];
  7168. counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
  7169. }
  7170. this.numerator = [];
  7171. this.denominator = [];
  7172. for (atomicUnit in counter) {
  7173. if (counter.hasOwnProperty(atomicUnit)) {
  7174. var count = counter[atomicUnit];
  7175. if (count > 0) {
  7176. for (i = 0; i < count; i++) {
  7177. this.numerator.push(atomicUnit);
  7178. }
  7179. } else if (count < 0) {
  7180. for (i = 0; i < -count; i++) {
  7181. this.denominator.push(atomicUnit);
  7182. }
  7183. }
  7184. }
  7185. }
  7186. this.numerator.sort();
  7187. this.denominator.sort();
  7188. };
  7189. module.exports = Unit;
  7190. },{"../data/unit-conversions":13,"./node":67}],77:[function(require,module,exports){
  7191. var Node = require("./node");
  7192. var URL = function (val, index, currentFileInfo, isEvald) {
  7193. this.value = val;
  7194. this.currentFileInfo = currentFileInfo;
  7195. this.index = index;
  7196. this.isEvald = isEvald;
  7197. };
  7198. URL.prototype = new Node();
  7199. URL.prototype.type = "Url";
  7200. URL.prototype.accept = function (visitor) {
  7201. this.value = visitor.visit(this.value);
  7202. };
  7203. URL.prototype.genCSS = function (context, output) {
  7204. output.add("url(");
  7205. this.value.genCSS(context, output);
  7206. output.add(")");
  7207. };
  7208. URL.prototype.eval = function (context) {
  7209. var val = this.value.eval(context),
  7210. rootpath;
  7211. if (!this.isEvald) {
  7212. // Add the base path if the URL is relative
  7213. rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
  7214. if (rootpath &&
  7215. typeof val.value === "string" &&
  7216. context.isPathRelative(val.value)) {
  7217. if (!val.quote) {
  7218. rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; });
  7219. }
  7220. val.value = rootpath + val.value;
  7221. }
  7222. val.value = context.normalizePath(val.value);
  7223. // Add url args if enabled
  7224. if (context.urlArgs) {
  7225. if (!val.value.match(/^\s*data:/)) {
  7226. var delimiter = val.value.indexOf('?') === -1 ? '?' : '&';
  7227. var urlArgs = delimiter + context.urlArgs;
  7228. if (val.value.indexOf('#') !== -1) {
  7229. val.value = val.value.replace('#', urlArgs + '#');
  7230. } else {
  7231. val.value += urlArgs;
  7232. }
  7233. }
  7234. }
  7235. }
  7236. return new URL(val, this.index, this.currentFileInfo, true);
  7237. };
  7238. module.exports = URL;
  7239. },{"./node":67}],78:[function(require,module,exports){
  7240. var Node = require("./node");
  7241. var Value = function (value) {
  7242. this.value = value;
  7243. if (!value) {
  7244. throw new Error("Value requires an array argument");
  7245. }
  7246. };
  7247. Value.prototype = new Node();
  7248. Value.prototype.type = "Value";
  7249. Value.prototype.accept = function (visitor) {
  7250. if (this.value) {
  7251. this.value = visitor.visitArray(this.value);
  7252. }
  7253. };
  7254. Value.prototype.eval = function (context) {
  7255. if (this.value.length === 1) {
  7256. return this.value[0].eval(context);
  7257. } else {
  7258. return new Value(this.value.map(function (v) {
  7259. return v.eval(context);
  7260. }));
  7261. }
  7262. };
  7263. Value.prototype.genCSS = function (context, output) {
  7264. var i;
  7265. for (i = 0; i < this.value.length; i++) {
  7266. this.value[i].genCSS(context, output);
  7267. if (i + 1 < this.value.length) {
  7268. output.add((context && context.compress) ? ',' : ', ');
  7269. }
  7270. }
  7271. };
  7272. module.exports = Value;
  7273. },{"./node":67}],79:[function(require,module,exports){
  7274. var Node = require("./node");
  7275. var Variable = function (name, index, currentFileInfo) {
  7276. this.name = name;
  7277. this.index = index;
  7278. this.currentFileInfo = currentFileInfo || {};
  7279. };
  7280. Variable.prototype = new Node();
  7281. Variable.prototype.type = "Variable";
  7282. Variable.prototype.eval = function (context) {
  7283. var variable, name = this.name;
  7284. if (name.indexOf('@@') === 0) {
  7285. name = '@' + new Variable(name.slice(1), this.index, this.currentFileInfo).eval(context).value;
  7286. }
  7287. if (this.evaluating) {
  7288. throw { type: 'Name',
  7289. message: "Recursive variable definition for " + name,
  7290. filename: this.currentFileInfo.filename,
  7291. index: this.index };
  7292. }
  7293. this.evaluating = true;
  7294. variable = this.find(context.frames, function (frame) {
  7295. var v = frame.variable(name);
  7296. if (v) {
  7297. if (v.important) {
  7298. var importantScope = context.importantScope[context.importantScope.length - 1];
  7299. importantScope.important = v.important;
  7300. }
  7301. return v.value.eval(context);
  7302. }
  7303. });
  7304. if (variable) {
  7305. this.evaluating = false;
  7306. return variable;
  7307. } else {
  7308. throw { type: 'Name',
  7309. message: "variable " + name + " is undefined",
  7310. filename: this.currentFileInfo.filename,
  7311. index: this.index };
  7312. }
  7313. };
  7314. Variable.prototype.find = function (obj, fun) {
  7315. for (var i = 0, r; i < obj.length; i++) {
  7316. r = fun.call(obj, obj[i]);
  7317. if (r) { return r; }
  7318. }
  7319. return null;
  7320. };
  7321. module.exports = Variable;
  7322. },{"./node":67}],80:[function(require,module,exports){
  7323. module.exports = {
  7324. getLocation: function(index, inputStream) {
  7325. var n = index + 1,
  7326. line = null,
  7327. column = -1;
  7328. while (--n >= 0 && inputStream.charAt(n) !== '\n') {
  7329. column++;
  7330. }
  7331. if (typeof index === 'number') {
  7332. line = (inputStream.slice(0, index).match(/\n/g) || "").length;
  7333. }
  7334. return {
  7335. line: line,
  7336. column: column
  7337. };
  7338. }
  7339. };
  7340. },{}],81:[function(require,module,exports){
  7341. var tree = require("../tree"),
  7342. Visitor = require("./visitor"),
  7343. logger = require("../logger");
  7344. /*jshint loopfunc:true */
  7345. var ExtendFinderVisitor = function() {
  7346. this._visitor = new Visitor(this);
  7347. this.contexts = [];
  7348. this.allExtendsStack = [[]];
  7349. };
  7350. ExtendFinderVisitor.prototype = {
  7351. run: function (root) {
  7352. root = this._visitor.visit(root);
  7353. root.allExtends = this.allExtendsStack[0];
  7354. return root;
  7355. },
  7356. visitRule: function (ruleNode, visitArgs) {
  7357. visitArgs.visitDeeper = false;
  7358. },
  7359. visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
  7360. visitArgs.visitDeeper = false;
  7361. },
  7362. visitRuleset: function (rulesetNode, visitArgs) {
  7363. if (rulesetNode.root) {
  7364. return;
  7365. }
  7366. var i, j, extend, allSelectorsExtendList = [], extendList;
  7367. // get &:extend(.a); rules which apply to all selectors in this ruleset
  7368. var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
  7369. for (i = 0; i < ruleCnt; i++) {
  7370. if (rulesetNode.rules[i] instanceof tree.Extend) {
  7371. allSelectorsExtendList.push(rules[i]);
  7372. rulesetNode.extendOnEveryPath = true;
  7373. }
  7374. }
  7375. // now find every selector and apply the extends that apply to all extends
  7376. // and the ones which apply to an individual extend
  7377. var paths = rulesetNode.paths;
  7378. for (i = 0; i < paths.length; i++) {
  7379. var selectorPath = paths[i],
  7380. selector = selectorPath[selectorPath.length - 1],
  7381. selExtendList = selector.extendList;
  7382. extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
  7383. : allSelectorsExtendList;
  7384. if (extendList) {
  7385. extendList = extendList.map(function(allSelectorsExtend) {
  7386. return allSelectorsExtend.clone();
  7387. });
  7388. }
  7389. for (j = 0; j < extendList.length; j++) {
  7390. this.foundExtends = true;
  7391. extend = extendList[j];
  7392. extend.findSelfSelectors(selectorPath);
  7393. extend.ruleset = rulesetNode;
  7394. if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
  7395. this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
  7396. }
  7397. }
  7398. this.contexts.push(rulesetNode.selectors);
  7399. },
  7400. visitRulesetOut: function (rulesetNode) {
  7401. if (!rulesetNode.root) {
  7402. this.contexts.length = this.contexts.length - 1;
  7403. }
  7404. },
  7405. visitMedia: function (mediaNode, visitArgs) {
  7406. mediaNode.allExtends = [];
  7407. this.allExtendsStack.push(mediaNode.allExtends);
  7408. },
  7409. visitMediaOut: function (mediaNode) {
  7410. this.allExtendsStack.length = this.allExtendsStack.length - 1;
  7411. },
  7412. visitDirective: function (directiveNode, visitArgs) {
  7413. directiveNode.allExtends = [];
  7414. this.allExtendsStack.push(directiveNode.allExtends);
  7415. },
  7416. visitDirectiveOut: function (directiveNode) {
  7417. this.allExtendsStack.length = this.allExtendsStack.length - 1;
  7418. }
  7419. };
  7420. var ProcessExtendsVisitor = function() {
  7421. this._visitor = new Visitor(this);
  7422. };
  7423. ProcessExtendsVisitor.prototype = {
  7424. run: function(root) {
  7425. var extendFinder = new ExtendFinderVisitor();
  7426. this.extendIndicies = {};
  7427. extendFinder.run(root);
  7428. if (!extendFinder.foundExtends) { return root; }
  7429. root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
  7430. this.allExtendsStack = [root.allExtends];
  7431. var newRoot = this._visitor.visit(root);
  7432. this.checkExtendsForNonMatched(root.allExtends);
  7433. return newRoot;
  7434. },
  7435. checkExtendsForNonMatched: function(extendList) {
  7436. var indicies = this.extendIndicies;
  7437. extendList.filter(function(extend) {
  7438. return !extend.hasFoundMatches && extend.parent_ids.length == 1;
  7439. }).forEach(function(extend) {
  7440. var selector = "_unknown_";
  7441. try {
  7442. selector = extend.selector.toCSS({});
  7443. }
  7444. catch(_) {}
  7445. if (!indicies[extend.index + ' ' + selector]) {
  7446. indicies[extend.index + ' ' + selector] = true;
  7447. logger.warn("extend '" + selector + "' has no matches");
  7448. }
  7449. });
  7450. },
  7451. doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
  7452. //
  7453. // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
  7454. // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
  7455. // this means this new extend can then go and alter other extends
  7456. //
  7457. // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
  7458. // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
  7459. // processed if we look at each selector at a time, as is done in visitRuleset
  7460. var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath,
  7461. extend, targetExtend, newExtend;
  7462. iterationCount = iterationCount || 0;
  7463. //loop through comparing every extend with every target extend.
  7464. // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
  7465. // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
  7466. // and the second is the target.
  7467. // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
  7468. // case when processing media queries
  7469. for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) {
  7470. for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) {
  7471. extend = extendsList[extendIndex];
  7472. targetExtend = extendsListTarget[targetExtendIndex];
  7473. // look for circular references
  7474. if ( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ) { continue; }
  7475. // find a match in the target extends self selector (the bit before :extend)
  7476. selectorPath = [targetExtend.selfSelectors[0]];
  7477. matches = extendVisitor.findMatch(extend, selectorPath);
  7478. if (matches.length) {
  7479. extend.hasFoundMatches = true;
  7480. // we found a match, so for each self selector..
  7481. extend.selfSelectors.forEach(function(selfSelector) {
  7482. // process the extend as usual
  7483. newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector);
  7484. // but now we create a new extend from it
  7485. newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0);
  7486. newExtend.selfSelectors = newSelector;
  7487. // add the extend onto the list of extends for that selector
  7488. newSelector[newSelector.length - 1].extendList = [newExtend];
  7489. // record that we need to add it.
  7490. extendsToAdd.push(newExtend);
  7491. newExtend.ruleset = targetExtend.ruleset;
  7492. //remember its parents for circular references
  7493. newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
  7494. // only process the selector once.. if we have :extend(.a,.b) then multiple
  7495. // extends will look at the same selector path, so when extending
  7496. // we know that any others will be duplicates in terms of what is added to the css
  7497. if (targetExtend.firstExtendOnThisSelectorPath) {
  7498. newExtend.firstExtendOnThisSelectorPath = true;
  7499. targetExtend.ruleset.paths.push(newSelector);
  7500. }
  7501. });
  7502. }
  7503. }
  7504. }
  7505. if (extendsToAdd.length) {
  7506. // try to detect circular references to stop a stack overflow.
  7507. // may no longer be needed.
  7508. this.extendChainCount++;
  7509. if (iterationCount > 100) {
  7510. var selectorOne = "{unable to calculate}";
  7511. var selectorTwo = "{unable to calculate}";
  7512. try
  7513. {
  7514. selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
  7515. selectorTwo = extendsToAdd[0].selector.toCSS();
  7516. }
  7517. catch(e) {}
  7518. throw { message: "extend circular reference detected. One of the circular extends is currently:" +
  7519. selectorOne + ":extend(" + selectorTwo + ")"};
  7520. }
  7521. // now process the new extends on the existing rules so that we can handle a extending b extending c extending
  7522. // d extending e...
  7523. return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
  7524. } else {
  7525. return extendsToAdd;
  7526. }
  7527. },
  7528. visitRule: function (ruleNode, visitArgs) {
  7529. visitArgs.visitDeeper = false;
  7530. },
  7531. visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
  7532. visitArgs.visitDeeper = false;
  7533. },
  7534. visitSelector: function (selectorNode, visitArgs) {
  7535. visitArgs.visitDeeper = false;
  7536. },
  7537. visitRuleset: function (rulesetNode, visitArgs) {
  7538. if (rulesetNode.root) {
  7539. return;
  7540. }
  7541. var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length - 1],
  7542. selectorsToAdd = [], extendVisitor = this, selectorPath;
  7543. // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
  7544. for (extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
  7545. for (pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
  7546. selectorPath = rulesetNode.paths[pathIndex];
  7547. // extending extends happens initially, before the main pass
  7548. if (rulesetNode.extendOnEveryPath) { continue; }
  7549. var extendList = selectorPath[selectorPath.length - 1].extendList;
  7550. if (extendList && extendList.length) { continue; }
  7551. matches = this.findMatch(allExtends[extendIndex], selectorPath);
  7552. if (matches.length) {
  7553. allExtends[extendIndex].hasFoundMatches = true;
  7554. allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
  7555. selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
  7556. });
  7557. }
  7558. }
  7559. }
  7560. rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
  7561. },
  7562. findMatch: function (extend, haystackSelectorPath) {
  7563. //
  7564. // look through the haystack selector path to try and find the needle - extend.selector
  7565. // returns an array of selector matches that can then be replaced
  7566. //
  7567. var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement,
  7568. targetCombinator, i,
  7569. extendVisitor = this,
  7570. needleElements = extend.selector.elements,
  7571. potentialMatches = [], potentialMatch, matches = [];
  7572. // loop through the haystack elements
  7573. for (haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
  7574. hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
  7575. for (hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
  7576. haystackElement = hackstackSelector.elements[hackstackElementIndex];
  7577. // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
  7578. if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
  7579. potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
  7580. initialCombinator: haystackElement.combinator});
  7581. }
  7582. for (i = 0; i < potentialMatches.length; i++) {
  7583. potentialMatch = potentialMatches[i];
  7584. // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
  7585. // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
  7586. // work out what the resulting combinator will be
  7587. targetCombinator = haystackElement.combinator.value;
  7588. if (targetCombinator === '' && hackstackElementIndex === 0) {
  7589. targetCombinator = ' ';
  7590. }
  7591. // if we don't match, null our match to indicate failure
  7592. if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
  7593. (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
  7594. potentialMatch = null;
  7595. } else {
  7596. potentialMatch.matched++;
  7597. }
  7598. // if we are still valid and have finished, test whether we have elements after and whether these are allowed
  7599. if (potentialMatch) {
  7600. potentialMatch.finished = potentialMatch.matched === needleElements.length;
  7601. if (potentialMatch.finished &&
  7602. (!extend.allowAfter &&
  7603. (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
  7604. potentialMatch = null;
  7605. }
  7606. }
  7607. // if null we remove, if not, we are still valid, so either push as a valid match or continue
  7608. if (potentialMatch) {
  7609. if (potentialMatch.finished) {
  7610. potentialMatch.length = needleElements.length;
  7611. potentialMatch.endPathIndex = haystackSelectorIndex;
  7612. potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
  7613. potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
  7614. matches.push(potentialMatch);
  7615. }
  7616. } else {
  7617. potentialMatches.splice(i, 1);
  7618. i--;
  7619. }
  7620. }
  7621. }
  7622. }
  7623. return matches;
  7624. },
  7625. isElementValuesEqual: function(elementValue1, elementValue2) {
  7626. if (typeof elementValue1 === "string" || typeof elementValue2 === "string") {
  7627. return elementValue1 === elementValue2;
  7628. }
  7629. if (elementValue1 instanceof tree.Attribute) {
  7630. if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
  7631. return false;
  7632. }
  7633. if (!elementValue1.value || !elementValue2.value) {
  7634. if (elementValue1.value || elementValue2.value) {
  7635. return false;
  7636. }
  7637. return true;
  7638. }
  7639. elementValue1 = elementValue1.value.value || elementValue1.value;
  7640. elementValue2 = elementValue2.value.value || elementValue2.value;
  7641. return elementValue1 === elementValue2;
  7642. }
  7643. elementValue1 = elementValue1.value;
  7644. elementValue2 = elementValue2.value;
  7645. if (elementValue1 instanceof tree.Selector) {
  7646. if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
  7647. return false;
  7648. }
  7649. for (var i = 0; i < elementValue1.elements.length; i++) {
  7650. if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
  7651. if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
  7652. return false;
  7653. }
  7654. }
  7655. if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
  7656. return false;
  7657. }
  7658. }
  7659. return true;
  7660. }
  7661. return false;
  7662. },
  7663. extendSelector:function (matches, selectorPath, replacementSelector) {
  7664. //for a set of matches, replace each match with the replacement selector
  7665. var currentSelectorPathIndex = 0,
  7666. currentSelectorPathElementIndex = 0,
  7667. path = [],
  7668. matchIndex,
  7669. selector,
  7670. firstElement,
  7671. match,
  7672. newElements;
  7673. for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
  7674. match = matches[matchIndex];
  7675. selector = selectorPath[match.pathIndex];
  7676. firstElement = new tree.Element(
  7677. match.initialCombinator,
  7678. replacementSelector.elements[0].value,
  7679. replacementSelector.elements[0].index,
  7680. replacementSelector.elements[0].currentFileInfo
  7681. );
  7682. if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
  7683. path[path.length - 1].elements = path[path.length - 1]
  7684. .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
  7685. currentSelectorPathElementIndex = 0;
  7686. currentSelectorPathIndex++;
  7687. }
  7688. newElements = selector.elements
  7689. .slice(currentSelectorPathElementIndex, match.index)
  7690. .concat([firstElement])
  7691. .concat(replacementSelector.elements.slice(1));
  7692. if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
  7693. path[path.length - 1].elements =
  7694. path[path.length - 1].elements.concat(newElements);
  7695. } else {
  7696. path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
  7697. path.push(new tree.Selector(
  7698. newElements
  7699. ));
  7700. }
  7701. currentSelectorPathIndex = match.endPathIndex;
  7702. currentSelectorPathElementIndex = match.endPathElementIndex;
  7703. if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
  7704. currentSelectorPathElementIndex = 0;
  7705. currentSelectorPathIndex++;
  7706. }
  7707. }
  7708. if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
  7709. path[path.length - 1].elements = path[path.length - 1]
  7710. .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
  7711. currentSelectorPathIndex++;
  7712. }
  7713. path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
  7714. return path;
  7715. },
  7716. visitRulesetOut: function (rulesetNode) {
  7717. },
  7718. visitMedia: function (mediaNode, visitArgs) {
  7719. var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
  7720. newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
  7721. this.allExtendsStack.push(newAllExtends);
  7722. },
  7723. visitMediaOut: function (mediaNode) {
  7724. var lastIndex = this.allExtendsStack.length - 1;
  7725. this.checkExtendsForNonMatched(this.allExtendsStack[lastIndex]);
  7726. this.allExtendsStack.length = lastIndex;
  7727. },
  7728. visitDirective: function (directiveNode, visitArgs) {
  7729. var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
  7730. newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
  7731. this.allExtendsStack.push(newAllExtends);
  7732. },
  7733. visitDirectiveOut: function (directiveNode) {
  7734. var lastIndex = this.allExtendsStack.length - 1;
  7735. this.checkExtendsForNonMatched(this.allExtendsStack[lastIndex]);
  7736. this.allExtendsStack.length = lastIndex;
  7737. }
  7738. };
  7739. module.exports = ProcessExtendsVisitor;
  7740. },{"../logger":31,"../tree":59,"./visitor":87}],82:[function(require,module,exports){
  7741. function ImportSequencer(onSequencerEmpty) {
  7742. this.imports = [];
  7743. this.variableImports = [];
  7744. this._onSequencerEmpty = onSequencerEmpty;
  7745. this._currentDepth = 0;
  7746. }
  7747. ImportSequencer.prototype.addImport = function(callback) {
  7748. var importSequencer = this,
  7749. importItem = {
  7750. callback: callback,
  7751. args: null,
  7752. isReady: false
  7753. };
  7754. this.imports.push(importItem);
  7755. return function() {
  7756. importItem.args = Array.prototype.slice.call(arguments, 0);
  7757. importItem.isReady = true;
  7758. importSequencer.tryRun();
  7759. };
  7760. };
  7761. ImportSequencer.prototype.addVariableImport = function(callback) {
  7762. this.variableImports.push(callback);
  7763. };
  7764. ImportSequencer.prototype.tryRun = function() {
  7765. this._currentDepth++;
  7766. try {
  7767. while (true) {
  7768. while (this.imports.length > 0) {
  7769. var importItem = this.imports[0];
  7770. if (!importItem.isReady) {
  7771. return;
  7772. }
  7773. this.imports = this.imports.slice(1);
  7774. importItem.callback.apply(null, importItem.args);
  7775. }
  7776. if (this.variableImports.length === 0) {
  7777. break;
  7778. }
  7779. var variableImport = this.variableImports[0];
  7780. this.variableImports = this.variableImports.slice(1);
  7781. variableImport();
  7782. }
  7783. } finally {
  7784. this._currentDepth--;
  7785. }
  7786. if (this._currentDepth === 0 && this._onSequencerEmpty) {
  7787. this._onSequencerEmpty();
  7788. }
  7789. };
  7790. module.exports = ImportSequencer;
  7791. },{}],83:[function(require,module,exports){
  7792. var contexts = require("../contexts"),
  7793. Visitor = require("./visitor"),
  7794. ImportSequencer = require("./import-sequencer");
  7795. var ImportVisitor = function(importer, finish) {
  7796. this._visitor = new Visitor(this);
  7797. this._importer = importer;
  7798. this._finish = finish;
  7799. this.context = new contexts.Eval();
  7800. this.importCount = 0;
  7801. this.onceFileDetectionMap = {};
  7802. this.recursionDetector = {};
  7803. this._sequencer = new ImportSequencer(this._onSequencerEmpty.bind(this));
  7804. };
  7805. ImportVisitor.prototype = {
  7806. isReplacing: false,
  7807. run: function (root) {
  7808. try {
  7809. // process the contents
  7810. this._visitor.visit(root);
  7811. }
  7812. catch(e) {
  7813. this.error = e;
  7814. }
  7815. this.isFinished = true;
  7816. this._sequencer.tryRun();
  7817. },
  7818. _onSequencerEmpty: function() {
  7819. if (!this.isFinished) {
  7820. return;
  7821. }
  7822. this._finish(this.error);
  7823. },
  7824. visitImport: function (importNode, visitArgs) {
  7825. var inlineCSS = importNode.options.inline;
  7826. if (!importNode.css || inlineCSS) {
  7827. var context = new contexts.Eval(this.context, this.context.frames.slice(0));
  7828. var importParent = context.frames[0];
  7829. this.importCount++;
  7830. if (importNode.isVariableImport()) {
  7831. this._sequencer.addVariableImport(this.processImportNode.bind(this, importNode, context, importParent));
  7832. } else {
  7833. this.processImportNode(importNode, context, importParent);
  7834. }
  7835. }
  7836. visitArgs.visitDeeper = false;
  7837. },
  7838. processImportNode: function(importNode, context, importParent) {
  7839. var evaldImportNode,
  7840. inlineCSS = importNode.options.inline;
  7841. try {
  7842. evaldImportNode = importNode.evalForImport(context);
  7843. } catch(e) {
  7844. if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
  7845. // attempt to eval properly and treat as css
  7846. importNode.css = true;
  7847. // if that fails, this error will be thrown
  7848. importNode.error = e;
  7849. }
  7850. if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
  7851. if (evaldImportNode.options.multiple) {
  7852. context.importMultiple = true;
  7853. }
  7854. // try appending if we haven't determined if it is css or not
  7855. var tryAppendLessExtension = evaldImportNode.css === undefined;
  7856. for (var i = 0; i < importParent.rules.length; i++) {
  7857. if (importParent.rules[i] === importNode) {
  7858. importParent.rules[i] = evaldImportNode;
  7859. break;
  7860. }
  7861. }
  7862. var onImported = this.onImported.bind(this, evaldImportNode, context),
  7863. sequencedOnImported = this._sequencer.addImport(onImported);
  7864. this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo,
  7865. evaldImportNode.options, sequencedOnImported);
  7866. } else {
  7867. this.importCount--;
  7868. if (this.isFinished) {
  7869. this._sequencer.tryRun();
  7870. }
  7871. }
  7872. },
  7873. onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
  7874. if (e) {
  7875. if (!e.filename) {
  7876. e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
  7877. }
  7878. this.error = e;
  7879. }
  7880. var importVisitor = this,
  7881. inlineCSS = importNode.options.inline,
  7882. duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
  7883. if (!context.importMultiple) {
  7884. if (duplicateImport) {
  7885. importNode.skip = true;
  7886. } else {
  7887. importNode.skip = function() {
  7888. if (fullPath in importVisitor.onceFileDetectionMap) {
  7889. return true;
  7890. }
  7891. importVisitor.onceFileDetectionMap[fullPath] = true;
  7892. return false;
  7893. };
  7894. }
  7895. }
  7896. if (root) {
  7897. importNode.root = root;
  7898. importNode.importedFilename = fullPath;
  7899. if (!inlineCSS && (context.importMultiple || !duplicateImport)) {
  7900. importVisitor.recursionDetector[fullPath] = true;
  7901. var oldContext = this.context;
  7902. this.context = context;
  7903. try {
  7904. this._visitor.visit(root);
  7905. } catch (e) {
  7906. this.error = e;
  7907. }
  7908. this.context = oldContext;
  7909. }
  7910. }
  7911. importVisitor.importCount--;
  7912. if (importVisitor.isFinished) {
  7913. importVisitor._sequencer.tryRun();
  7914. }
  7915. },
  7916. visitRule: function (ruleNode, visitArgs) {
  7917. visitArgs.visitDeeper = false;
  7918. },
  7919. visitDirective: function (directiveNode, visitArgs) {
  7920. this.context.frames.unshift(directiveNode);
  7921. },
  7922. visitDirectiveOut: function (directiveNode) {
  7923. this.context.frames.shift();
  7924. },
  7925. visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
  7926. this.context.frames.unshift(mixinDefinitionNode);
  7927. },
  7928. visitMixinDefinitionOut: function (mixinDefinitionNode) {
  7929. this.context.frames.shift();
  7930. },
  7931. visitRuleset: function (rulesetNode, visitArgs) {
  7932. this.context.frames.unshift(rulesetNode);
  7933. },
  7934. visitRulesetOut: function (rulesetNode) {
  7935. this.context.frames.shift();
  7936. },
  7937. visitMedia: function (mediaNode, visitArgs) {
  7938. this.context.frames.unshift(mediaNode.rules[0]);
  7939. },
  7940. visitMediaOut: function (mediaNode) {
  7941. this.context.frames.shift();
  7942. }
  7943. };
  7944. module.exports = ImportVisitor;
  7945. },{"../contexts":10,"./import-sequencer":82,"./visitor":87}],84:[function(require,module,exports){
  7946. var visitors = {
  7947. Visitor: require("./visitor"),
  7948. ImportVisitor: require('./import-visitor'),
  7949. ExtendVisitor: require('./extend-visitor'),
  7950. JoinSelectorVisitor: require('./join-selector-visitor'),
  7951. ToCSSVisitor: require('./to-css-visitor')
  7952. };
  7953. module.exports = visitors;
  7954. },{"./extend-visitor":81,"./import-visitor":83,"./join-selector-visitor":85,"./to-css-visitor":86,"./visitor":87}],85:[function(require,module,exports){
  7955. var Visitor = require("./visitor");
  7956. var JoinSelectorVisitor = function() {
  7957. this.contexts = [[]];
  7958. this._visitor = new Visitor(this);
  7959. };
  7960. JoinSelectorVisitor.prototype = {
  7961. run: function (root) {
  7962. return this._visitor.visit(root);
  7963. },
  7964. visitRule: function (ruleNode, visitArgs) {
  7965. visitArgs.visitDeeper = false;
  7966. },
  7967. visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
  7968. visitArgs.visitDeeper = false;
  7969. },
  7970. visitRuleset: function (rulesetNode, visitArgs) {
  7971. var context = this.contexts[this.contexts.length - 1],
  7972. paths = [], selectors;
  7973. this.contexts.push(paths);
  7974. if (! rulesetNode.root) {
  7975. selectors = rulesetNode.selectors;
  7976. if (selectors) {
  7977. selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
  7978. rulesetNode.selectors = selectors.length ? selectors : (selectors = null);
  7979. if (selectors) { rulesetNode.joinSelectors(paths, context, selectors); }
  7980. }
  7981. if (!selectors) { rulesetNode.rules = null; }
  7982. rulesetNode.paths = paths;
  7983. }
  7984. },
  7985. visitRulesetOut: function (rulesetNode) {
  7986. this.contexts.length = this.contexts.length - 1;
  7987. },
  7988. visitMedia: function (mediaNode, visitArgs) {
  7989. var context = this.contexts[this.contexts.length - 1];
  7990. mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
  7991. }
  7992. };
  7993. module.exports = JoinSelectorVisitor;
  7994. },{"./visitor":87}],86:[function(require,module,exports){
  7995. var tree = require("../tree"),
  7996. Visitor = require("./visitor");
  7997. var ToCSSVisitor = function(context) {
  7998. this._visitor = new Visitor(this);
  7999. this._context = context;
  8000. };
  8001. ToCSSVisitor.prototype = {
  8002. isReplacing: true,
  8003. run: function (root) {
  8004. return this._visitor.visit(root);
  8005. },
  8006. visitRule: function (ruleNode, visitArgs) {
  8007. if (ruleNode.variable) {
  8008. return;
  8009. }
  8010. return ruleNode;
  8011. },
  8012. visitMixinDefinition: function (mixinNode, visitArgs) {
  8013. // mixin definitions do not get eval'd - this means they keep state
  8014. // so we have to clear that state here so it isn't used if toCSS is called twice
  8015. mixinNode.frames = [];
  8016. },
  8017. visitExtend: function (extendNode, visitArgs) {
  8018. },
  8019. visitComment: function (commentNode, visitArgs) {
  8020. if (commentNode.isSilent(this._context)) {
  8021. return;
  8022. }
  8023. return commentNode;
  8024. },
  8025. visitMedia: function(mediaNode, visitArgs) {
  8026. mediaNode.accept(this._visitor);
  8027. visitArgs.visitDeeper = false;
  8028. if (!mediaNode.rules.length) {
  8029. return;
  8030. }
  8031. return mediaNode;
  8032. },
  8033. visitDirective: function(directiveNode, visitArgs) {
  8034. if (directiveNode.name === "@charset") {
  8035. if (!directiveNode.getIsReferenced()) {
  8036. return;
  8037. }
  8038. // Only output the debug info together with subsequent @charset definitions
  8039. // a comment (or @media statement) before the actual @charset directive would
  8040. // be considered illegal css as it has to be on the first line
  8041. if (this.charset) {
  8042. if (directiveNode.debugInfo) {
  8043. var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
  8044. comment.debugInfo = directiveNode.debugInfo;
  8045. return this._visitor.visit(comment);
  8046. }
  8047. return;
  8048. }
  8049. this.charset = true;
  8050. }
  8051. if (directiveNode.rules && directiveNode.rules.rules) {
  8052. this._mergeRules(directiveNode.rules.rules);
  8053. //process childs
  8054. directiveNode.accept(this._visitor);
  8055. visitArgs.visitDeeper = false;
  8056. // the directive was directly referenced and therefore needs to be shown in the output
  8057. if (directiveNode.getIsReferenced()) {
  8058. return directiveNode;
  8059. }
  8060. if (!directiveNode.rules.rules) {
  8061. return ;
  8062. }
  8063. //the directive was not directly referenced
  8064. for (var r = 0; r < directiveNode.rules.rules.length; r++) {
  8065. var rule = directiveNode.rules.rules[r];
  8066. if (rule.getIsReferenced && rule.getIsReferenced()) {
  8067. //the directive contains something that was referenced (likely by extend)
  8068. //therefore it needs to be shown in output too
  8069. //marking as referenced in case the directive is stored inside another directive
  8070. directiveNode.markReferenced();
  8071. return directiveNode;
  8072. }
  8073. }
  8074. //The directive was not directly referenced and does not contain anything that
  8075. //was referenced. Therefore it must not be shown in output.
  8076. return ;
  8077. } else {
  8078. if (!directiveNode.getIsReferenced()) {
  8079. return;
  8080. }
  8081. }
  8082. return directiveNode;
  8083. },
  8084. checkPropertiesInRoot: function(rules) {
  8085. var ruleNode;
  8086. for (var i = 0; i < rules.length; i++) {
  8087. ruleNode = rules[i];
  8088. if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
  8089. throw { message: "properties must be inside selector blocks, they cannot be in the root.",
  8090. index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
  8091. }
  8092. }
  8093. },
  8094. visitRuleset: function (rulesetNode, visitArgs) {
  8095. var rule, rulesets = [];
  8096. if (rulesetNode.firstRoot) {
  8097. this.checkPropertiesInRoot(rulesetNode.rules);
  8098. }
  8099. if (! rulesetNode.root) {
  8100. if (rulesetNode.paths) {
  8101. rulesetNode.paths = rulesetNode.paths
  8102. .filter(function(p) {
  8103. var i;
  8104. if (p[0].elements[0].combinator.value === ' ') {
  8105. p[0].elements[0].combinator = new(tree.Combinator)('');
  8106. }
  8107. for (i = 0; i < p.length; i++) {
  8108. if (p[i].getIsReferenced() && p[i].getIsOutput()) {
  8109. return true;
  8110. }
  8111. }
  8112. return false;
  8113. });
  8114. }
  8115. // Compile rules and rulesets
  8116. var nodeRules = rulesetNode.rules, nodeRuleCnt = nodeRules ? nodeRules.length : 0;
  8117. for (var i = 0; i < nodeRuleCnt; ) {
  8118. rule = nodeRules[i];
  8119. if (rule && rule.rules) {
  8120. // visit because we are moving them out from being a child
  8121. rulesets.push(this._visitor.visit(rule));
  8122. nodeRules.splice(i, 1);
  8123. nodeRuleCnt--;
  8124. continue;
  8125. }
  8126. i++;
  8127. }
  8128. // accept the visitor to remove rules and refactor itself
  8129. // then we can decide now whether we want it or not
  8130. if (nodeRuleCnt > 0) {
  8131. rulesetNode.accept(this._visitor);
  8132. } else {
  8133. rulesetNode.rules = null;
  8134. }
  8135. visitArgs.visitDeeper = false;
  8136. nodeRules = rulesetNode.rules;
  8137. if (nodeRules) {
  8138. this._mergeRules(nodeRules);
  8139. nodeRules = rulesetNode.rules;
  8140. }
  8141. if (nodeRules) {
  8142. this._removeDuplicateRules(nodeRules);
  8143. nodeRules = rulesetNode.rules;
  8144. }
  8145. // now decide whether we keep the ruleset
  8146. if (nodeRules && nodeRules.length > 0 && rulesetNode.paths.length > 0) {
  8147. rulesets.splice(0, 0, rulesetNode);
  8148. }
  8149. } else {
  8150. rulesetNode.accept(this._visitor);
  8151. visitArgs.visitDeeper = false;
  8152. if (rulesetNode.firstRoot || (rulesetNode.rules && rulesetNode.rules.length > 0)) {
  8153. rulesets.splice(0, 0, rulesetNode);
  8154. }
  8155. }
  8156. if (rulesets.length === 1) {
  8157. return rulesets[0];
  8158. }
  8159. return rulesets;
  8160. },
  8161. _removeDuplicateRules: function(rules) {
  8162. if (!rules) { return; }
  8163. // remove duplicates
  8164. var ruleCache = {},
  8165. ruleList, rule, i;
  8166. for (i = rules.length - 1; i >= 0 ; i--) {
  8167. rule = rules[i];
  8168. if (rule instanceof tree.Rule) {
  8169. if (!ruleCache[rule.name]) {
  8170. ruleCache[rule.name] = rule;
  8171. } else {
  8172. ruleList = ruleCache[rule.name];
  8173. if (ruleList instanceof tree.Rule) {
  8174. ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._context)];
  8175. }
  8176. var ruleCSS = rule.toCSS(this._context);
  8177. if (ruleList.indexOf(ruleCSS) !== -1) {
  8178. rules.splice(i, 1);
  8179. } else {
  8180. ruleList.push(ruleCSS);
  8181. }
  8182. }
  8183. }
  8184. }
  8185. },
  8186. _mergeRules: function (rules) {
  8187. if (!rules) { return; }
  8188. var groups = {},
  8189. parts,
  8190. rule,
  8191. key;
  8192. for (var i = 0; i < rules.length; i++) {
  8193. rule = rules[i];
  8194. if ((rule instanceof tree.Rule) && rule.merge) {
  8195. key = [rule.name,
  8196. rule.important ? "!" : ""].join(",");
  8197. if (!groups[key]) {
  8198. groups[key] = [];
  8199. } else {
  8200. rules.splice(i--, 1);
  8201. }
  8202. groups[key].push(rule);
  8203. }
  8204. }
  8205. Object.keys(groups).map(function (k) {
  8206. function toExpression(values) {
  8207. return new (tree.Expression)(values.map(function (p) {
  8208. return p.value;
  8209. }));
  8210. }
  8211. function toValue(values) {
  8212. return new (tree.Value)(values.map(function (p) {
  8213. return p;
  8214. }));
  8215. }
  8216. parts = groups[k];
  8217. if (parts.length > 1) {
  8218. rule = parts[0];
  8219. var spacedGroups = [];
  8220. var lastSpacedGroup = [];
  8221. parts.map(function (p) {
  8222. if (p.merge === "+") {
  8223. if (lastSpacedGroup.length > 0) {
  8224. spacedGroups.push(toExpression(lastSpacedGroup));
  8225. }
  8226. lastSpacedGroup = [];
  8227. }
  8228. lastSpacedGroup.push(p);
  8229. });
  8230. spacedGroups.push(toExpression(lastSpacedGroup));
  8231. rule.value = toValue(spacedGroups);
  8232. }
  8233. });
  8234. }
  8235. };
  8236. module.exports = ToCSSVisitor;
  8237. },{"../tree":59,"./visitor":87}],87:[function(require,module,exports){
  8238. var tree = require("../tree");
  8239. var _visitArgs = { visitDeeper: true },
  8240. _hasIndexed = false;
  8241. function _noop(node) {
  8242. return node;
  8243. }
  8244. function indexNodeTypes(parent, ticker) {
  8245. // add .typeIndex to tree node types for lookup table
  8246. var key, child;
  8247. for (key in parent) {
  8248. if (parent.hasOwnProperty(key)) {
  8249. child = parent[key];
  8250. switch (typeof child) {
  8251. case "function":
  8252. // ignore bound functions directly on tree which do not have a prototype
  8253. // or aren't nodes
  8254. if (child.prototype && child.prototype.type) {
  8255. child.prototype.typeIndex = ticker++;
  8256. }
  8257. break;
  8258. case "object":
  8259. ticker = indexNodeTypes(child, ticker);
  8260. break;
  8261. }
  8262. }
  8263. }
  8264. return ticker;
  8265. }
  8266. var Visitor = function(implementation) {
  8267. this._implementation = implementation;
  8268. this._visitFnCache = [];
  8269. if (!_hasIndexed) {
  8270. indexNodeTypes(tree, 1);
  8271. _hasIndexed = true;
  8272. }
  8273. };
  8274. Visitor.prototype = {
  8275. visit: function(node) {
  8276. if (!node) {
  8277. return node;
  8278. }
  8279. var nodeTypeIndex = node.typeIndex;
  8280. if (!nodeTypeIndex) {
  8281. return node;
  8282. }
  8283. var visitFnCache = this._visitFnCache,
  8284. impl = this._implementation,
  8285. aryIndx = nodeTypeIndex << 1,
  8286. outAryIndex = aryIndx | 1,
  8287. func = visitFnCache[aryIndx],
  8288. funcOut = visitFnCache[outAryIndex],
  8289. visitArgs = _visitArgs,
  8290. fnName;
  8291. visitArgs.visitDeeper = true;
  8292. if (!func) {
  8293. fnName = "visit" + node.type;
  8294. func = impl[fnName] || _noop;
  8295. funcOut = impl[fnName + "Out"] || _noop;
  8296. visitFnCache[aryIndx] = func;
  8297. visitFnCache[outAryIndex] = funcOut;
  8298. }
  8299. if (func !== _noop) {
  8300. var newNode = func.call(impl, node, visitArgs);
  8301. if (impl.isReplacing) {
  8302. node = newNode;
  8303. }
  8304. }
  8305. if (visitArgs.visitDeeper && node && node.accept) {
  8306. node.accept(this);
  8307. }
  8308. if (funcOut != _noop) {
  8309. funcOut.call(impl, node);
  8310. }
  8311. return node;
  8312. },
  8313. visitArray: function(nodes, nonReplacing) {
  8314. if (!nodes) {
  8315. return nodes;
  8316. }
  8317. var cnt = nodes.length, i;
  8318. // Non-replacing
  8319. if (nonReplacing || !this._implementation.isReplacing) {
  8320. for (i = 0; i < cnt; i++) {
  8321. this.visit(nodes[i]);
  8322. }
  8323. return nodes;
  8324. }
  8325. // Replacing
  8326. var out = [];
  8327. for (i = 0; i < cnt; i++) {
  8328. var evald = this.visit(nodes[i]);
  8329. if (evald === undefined) { continue; }
  8330. if (!evald.splice) {
  8331. out.push(evald);
  8332. } else if (evald.length) {
  8333. this.flatten(evald, out);
  8334. }
  8335. }
  8336. return out;
  8337. },
  8338. flatten: function(arr, out) {
  8339. if (!out) {
  8340. out = [];
  8341. }
  8342. var cnt, i, item,
  8343. nestedCnt, j, nestedItem;
  8344. for (i = 0, cnt = arr.length; i < cnt; i++) {
  8345. item = arr[i];
  8346. if (item === undefined) {
  8347. continue;
  8348. }
  8349. if (!item.splice) {
  8350. out.push(item);
  8351. continue;
  8352. }
  8353. for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
  8354. nestedItem = item[j];
  8355. if (nestedItem === undefined) {
  8356. continue;
  8357. }
  8358. if (!nestedItem.splice) {
  8359. out.push(nestedItem);
  8360. } else if (nestedItem.length) {
  8361. this.flatten(nestedItem, out);
  8362. }
  8363. }
  8364. }
  8365. return out;
  8366. }
  8367. };
  8368. module.exports = Visitor;
  8369. },{"../tree":59}],88:[function(require,module,exports){
  8370. // shim for using process in browser
  8371. var process = module.exports = {};
  8372. var queue = [];
  8373. var draining = false;
  8374. function drainQueue() {
  8375. if (draining) {
  8376. return;
  8377. }
  8378. draining = true;
  8379. var currentQueue;
  8380. var len = queue.length;
  8381. while(len) {
  8382. currentQueue = queue;
  8383. queue = [];
  8384. var i = -1;
  8385. while (++i < len) {
  8386. currentQueue[i]();
  8387. }
  8388. len = queue.length;
  8389. }
  8390. draining = false;
  8391. }
  8392. process.nextTick = function (fun) {
  8393. queue.push(fun);
  8394. if (!draining) {
  8395. setTimeout(drainQueue, 0);
  8396. }
  8397. };
  8398. process.title = 'browser';
  8399. process.browser = true;
  8400. process.env = {};
  8401. process.argv = [];
  8402. process.version = ''; // empty string to avoid regexp issues
  8403. function noop() {}
  8404. process.on = noop;
  8405. process.addListener = noop;
  8406. process.once = noop;
  8407. process.off = noop;
  8408. process.removeListener = noop;
  8409. process.removeAllListeners = noop;
  8410. process.emit = noop;
  8411. process.binding = function (name) {
  8412. throw new Error('process.binding is not supported');
  8413. };
  8414. // TODO(shtylman)
  8415. process.cwd = function () { return '/' };
  8416. process.chdir = function (dir) {
  8417. throw new Error('process.chdir is not supported');
  8418. };
  8419. process.umask = function() { return 0; };
  8420. },{}],89:[function(require,module,exports){
  8421. 'use strict';
  8422. var asap = require('asap')
  8423. module.exports = Promise;
  8424. function Promise(fn) {
  8425. if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
  8426. if (typeof fn !== 'function') throw new TypeError('not a function')
  8427. var state = null
  8428. var value = null
  8429. var deferreds = []
  8430. var self = this
  8431. this.then = function(onFulfilled, onRejected) {
  8432. return new self.constructor(function(resolve, reject) {
  8433. handle(new Handler(onFulfilled, onRejected, resolve, reject))
  8434. })
  8435. }
  8436. function handle(deferred) {
  8437. if (state === null) {
  8438. deferreds.push(deferred)
  8439. return
  8440. }
  8441. asap(function() {
  8442. var cb = state ? deferred.onFulfilled : deferred.onRejected
  8443. if (cb === null) {
  8444. (state ? deferred.resolve : deferred.reject)(value)
  8445. return
  8446. }
  8447. var ret
  8448. try {
  8449. ret = cb(value)
  8450. }
  8451. catch (e) {
  8452. deferred.reject(e)
  8453. return
  8454. }
  8455. deferred.resolve(ret)
  8456. })
  8457. }
  8458. function resolve(newValue) {
  8459. try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
  8460. if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
  8461. if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
  8462. var then = newValue.then
  8463. if (typeof then === 'function') {
  8464. doResolve(then.bind(newValue), resolve, reject)
  8465. return
  8466. }
  8467. }
  8468. state = true
  8469. value = newValue
  8470. finale()
  8471. } catch (e) { reject(e) }
  8472. }
  8473. function reject(newValue) {
  8474. state = false
  8475. value = newValue
  8476. finale()
  8477. }
  8478. function finale() {
  8479. for (var i = 0, len = deferreds.length; i < len; i++)
  8480. handle(deferreds[i])
  8481. deferreds = null
  8482. }
  8483. doResolve(fn, resolve, reject)
  8484. }
  8485. function Handler(onFulfilled, onRejected, resolve, reject){
  8486. this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
  8487. this.onRejected = typeof onRejected === 'function' ? onRejected : null
  8488. this.resolve = resolve
  8489. this.reject = reject
  8490. }
  8491. /**
  8492. * Take a potentially misbehaving resolver function and make sure
  8493. * onFulfilled and onRejected are only called once.
  8494. *
  8495. * Makes no guarantees about asynchrony.
  8496. */
  8497. function doResolve(fn, onFulfilled, onRejected) {
  8498. var done = false;
  8499. try {
  8500. fn(function (value) {
  8501. if (done) return
  8502. done = true
  8503. onFulfilled(value)
  8504. }, function (reason) {
  8505. if (done) return
  8506. done = true
  8507. onRejected(reason)
  8508. })
  8509. } catch (ex) {
  8510. if (done) return
  8511. done = true
  8512. onRejected(ex)
  8513. }
  8514. }
  8515. },{"asap":91}],90:[function(require,module,exports){
  8516. 'use strict';
  8517. //This file contains the ES6 extensions to the core Promises/A+ API
  8518. var Promise = require('./core.js')
  8519. var asap = require('asap')
  8520. module.exports = Promise
  8521. /* Static Functions */
  8522. function ValuePromise(value) {
  8523. this.then = function (onFulfilled) {
  8524. if (typeof onFulfilled !== 'function') return this
  8525. return new Promise(function (resolve, reject) {
  8526. asap(function () {
  8527. try {
  8528. resolve(onFulfilled(value))
  8529. } catch (ex) {
  8530. reject(ex);
  8531. }
  8532. })
  8533. })
  8534. }
  8535. }
  8536. ValuePromise.prototype = Promise.prototype
  8537. var TRUE = new ValuePromise(true)
  8538. var FALSE = new ValuePromise(false)
  8539. var NULL = new ValuePromise(null)
  8540. var UNDEFINED = new ValuePromise(undefined)
  8541. var ZERO = new ValuePromise(0)
  8542. var EMPTYSTRING = new ValuePromise('')
  8543. Promise.resolve = function (value) {
  8544. if (value instanceof Promise) return value
  8545. if (value === null) return NULL
  8546. if (value === undefined) return UNDEFINED
  8547. if (value === true) return TRUE
  8548. if (value === false) return FALSE
  8549. if (value === 0) return ZERO
  8550. if (value === '') return EMPTYSTRING
  8551. if (typeof value === 'object' || typeof value === 'function') {
  8552. try {
  8553. var then = value.then
  8554. if (typeof then === 'function') {
  8555. return new Promise(then.bind(value))
  8556. }
  8557. } catch (ex) {
  8558. return new Promise(function (resolve, reject) {
  8559. reject(ex)
  8560. })
  8561. }
  8562. }
  8563. return new ValuePromise(value)
  8564. }
  8565. Promise.all = function (arr) {
  8566. var args = Array.prototype.slice.call(arr)
  8567. return new Promise(function (resolve, reject) {
  8568. if (args.length === 0) return resolve([])
  8569. var remaining = args.length
  8570. function res(i, val) {
  8571. try {
  8572. if (val && (typeof val === 'object' || typeof val === 'function')) {
  8573. var then = val.then
  8574. if (typeof then === 'function') {
  8575. then.call(val, function (val) { res(i, val) }, reject)
  8576. return
  8577. }
  8578. }
  8579. args[i] = val
  8580. if (--remaining === 0) {
  8581. resolve(args);
  8582. }
  8583. } catch (ex) {
  8584. reject(ex)
  8585. }
  8586. }
  8587. for (var i = 0; i < args.length; i++) {
  8588. res(i, args[i])
  8589. }
  8590. })
  8591. }
  8592. Promise.reject = function (value) {
  8593. return new Promise(function (resolve, reject) {
  8594. reject(value);
  8595. });
  8596. }
  8597. Promise.race = function (values) {
  8598. return new Promise(function (resolve, reject) {
  8599. values.forEach(function(value){
  8600. Promise.resolve(value).then(resolve, reject);
  8601. })
  8602. });
  8603. }
  8604. /* Prototype Methods */
  8605. Promise.prototype['catch'] = function (onRejected) {
  8606. return this.then(null, onRejected);
  8607. }
  8608. },{"./core.js":89,"asap":91}],91:[function(require,module,exports){
  8609. (function (process){
  8610. // Use the fastest possible means to execute a task in a future turn
  8611. // of the event loop.
  8612. // linked list of tasks (single, with head node)
  8613. var head = {task: void 0, next: null};
  8614. var tail = head;
  8615. var flushing = false;
  8616. var requestFlush = void 0;
  8617. var isNodeJS = false;
  8618. function flush() {
  8619. /* jshint loopfunc: true */
  8620. while (head.next) {
  8621. head = head.next;
  8622. var task = head.task;
  8623. head.task = void 0;
  8624. var domain = head.domain;
  8625. if (domain) {
  8626. head.domain = void 0;
  8627. domain.enter();
  8628. }
  8629. try {
  8630. task();
  8631. } catch (e) {
  8632. if (isNodeJS) {
  8633. // In node, uncaught exceptions are considered fatal errors.
  8634. // Re-throw them synchronously to interrupt flushing!
  8635. // Ensure continuation if the uncaught exception is suppressed
  8636. // listening "uncaughtException" events (as domains does).
  8637. // Continue in next event to avoid tick recursion.
  8638. if (domain) {
  8639. domain.exit();
  8640. }
  8641. setTimeout(flush, 0);
  8642. if (domain) {
  8643. domain.enter();
  8644. }
  8645. throw e;
  8646. } else {
  8647. // In browsers, uncaught exceptions are not fatal.
  8648. // Re-throw them asynchronously to avoid slow-downs.
  8649. setTimeout(function() {
  8650. throw e;
  8651. }, 0);
  8652. }
  8653. }
  8654. if (domain) {
  8655. domain.exit();
  8656. }
  8657. }
  8658. flushing = false;
  8659. }
  8660. if (typeof process !== "undefined" && process.nextTick) {
  8661. // Node.js before 0.9. Note that some fake-Node environments, like the
  8662. // Mocha test runner, introduce a `process` global without a `nextTick`.
  8663. isNodeJS = true;
  8664. requestFlush = function () {
  8665. process.nextTick(flush);
  8666. };
  8667. } else if (typeof setImmediate === "function") {
  8668. // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate
  8669. if (typeof window !== "undefined") {
  8670. requestFlush = setImmediate.bind(window, flush);
  8671. } else {
  8672. requestFlush = function () {
  8673. setImmediate(flush);
  8674. };
  8675. }
  8676. } else if (typeof MessageChannel !== "undefined") {
  8677. // modern browsers
  8678. // http://www.nonblocking.io/2011/06/windownexttick.html
  8679. var channel = new MessageChannel();
  8680. channel.port1.onmessage = flush;
  8681. requestFlush = function () {
  8682. channel.port2.postMessage(0);
  8683. };
  8684. } else {
  8685. // old browsers
  8686. requestFlush = function () {
  8687. setTimeout(flush, 0);
  8688. };
  8689. }
  8690. function asap(task) {
  8691. tail = tail.next = {
  8692. task: task,
  8693. domain: isNodeJS && process.domain,
  8694. next: null
  8695. };
  8696. if (!flushing) {
  8697. flushing = true;
  8698. requestFlush();
  8699. }
  8700. };
  8701. module.exports = asap;
  8702. }).call(this,require('_process'))
  8703. },{"_process":88}],92:[function(require,module,exports){
  8704. // should work in any browser without browserify
  8705. if (typeof Promise.prototype.done !== 'function') {
  8706. Promise.prototype.done = function (onFulfilled, onRejected) {
  8707. var self = arguments.length ? this.then.apply(this, arguments) : this
  8708. self.then(null, function (err) {
  8709. setTimeout(function () {
  8710. throw err
  8711. }, 0)
  8712. })
  8713. }
  8714. }
  8715. },{}],"promise/polyfill.js":[function(require,module,exports){
  8716. // not "use strict" so we can declare global "Promise"
  8717. var asap = require('asap');
  8718. if (typeof Promise === 'undefined') {
  8719. Promise = require('./lib/core.js')
  8720. require('./lib/es6-extensions.js')
  8721. }
  8722. require('./polyfill-done.js');
  8723. },{"./lib/core.js":89,"./lib/es6-extensions.js":90,"./polyfill-done.js":92,"asap":91}]},{},[2])(2)
  8724. });