less.cjs.js 412 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867
  1. 'use strict';
  2. var tslib = require('tslib');
  3. var path = require('path');
  4. var url = require('url');
  5. var CloneHelper = require('clone');
  6. var environment = {
  7. encodeBase64: function encodeBase64(str) {
  8. // Avoid Buffer constructor on newer versions of Node.js.
  9. var buffer = (Buffer.from ? Buffer.from(str) : (new Buffer(str)));
  10. return buffer.toString('base64');
  11. },
  12. mimeLookup: function (filename) {
  13. return require('mime').lookup(filename);
  14. },
  15. charsetLookup: function (mime) {
  16. return require('mime').charsets.lookup(mime);
  17. },
  18. getSourceMapGenerator: function getSourceMapGenerator() {
  19. return require('source-map').SourceMapGenerator;
  20. }
  21. };
  22. var fs;
  23. try {
  24. fs = require('graceful-fs');
  25. }
  26. catch (e) {
  27. fs = require('fs');
  28. }
  29. var fs$1 = fs;
  30. var AbstractFileManager = /** @class */ (function () {
  31. function AbstractFileManager() {
  32. }
  33. AbstractFileManager.prototype.getPath = function (filename) {
  34. var j = filename.lastIndexOf('?');
  35. if (j > 0) {
  36. filename = filename.slice(0, j);
  37. }
  38. j = filename.lastIndexOf('/');
  39. if (j < 0) {
  40. j = filename.lastIndexOf('\\');
  41. }
  42. if (j < 0) {
  43. return '';
  44. }
  45. return filename.slice(0, j + 1);
  46. };
  47. AbstractFileManager.prototype.tryAppendExtension = function (path, ext) {
  48. return /(\.[a-z]*$)|([\?;].*)$/.test(path) ? path : path + ext;
  49. };
  50. AbstractFileManager.prototype.tryAppendLessExtension = function (path) {
  51. return this.tryAppendExtension(path, '.less');
  52. };
  53. AbstractFileManager.prototype.supportsSync = function () { return false; };
  54. AbstractFileManager.prototype.alwaysMakePathsAbsolute = function () { return false; };
  55. AbstractFileManager.prototype.isPathAbsolute = function (filename) {
  56. return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename);
  57. };
  58. // TODO: pull out / replace?
  59. AbstractFileManager.prototype.join = function (basePath, laterPath) {
  60. if (!basePath) {
  61. return laterPath;
  62. }
  63. return basePath + laterPath;
  64. };
  65. AbstractFileManager.prototype.pathDiff = function (url, baseUrl) {
  66. // diff between two paths to create a relative path
  67. var urlParts = this.extractUrlParts(url);
  68. var baseUrlParts = this.extractUrlParts(baseUrl);
  69. var i;
  70. var max;
  71. var urlDirectories;
  72. var baseUrlDirectories;
  73. var diff = '';
  74. if (urlParts.hostPart !== baseUrlParts.hostPart) {
  75. return '';
  76. }
  77. max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
  78. for (i = 0; i < max; i++) {
  79. if (baseUrlParts.directories[i] !== urlParts.directories[i]) {
  80. break;
  81. }
  82. }
  83. baseUrlDirectories = baseUrlParts.directories.slice(i);
  84. urlDirectories = urlParts.directories.slice(i);
  85. for (i = 0; i < baseUrlDirectories.length - 1; i++) {
  86. diff += '../';
  87. }
  88. for (i = 0; i < urlDirectories.length - 1; i++) {
  89. diff += urlDirectories[i] + "/";
  90. }
  91. return diff;
  92. };
  93. // helper function, not part of API
  94. AbstractFileManager.prototype.extractUrlParts = function (url, baseUrl) {
  95. // urlParts[1] = protocol://hostname/ OR /
  96. // urlParts[2] = / if path relative to host base
  97. // urlParts[3] = directories
  98. // urlParts[4] = filename
  99. // urlParts[5] = parameters
  100. var urlPartsRegex = /^((?:[a-z-]+:)?\/{2}(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i;
  101. var urlParts = url.match(urlPartsRegex);
  102. var returner = {};
  103. var rawDirectories = [];
  104. var directories = [];
  105. var i;
  106. var baseUrlParts;
  107. if (!urlParts) {
  108. throw new Error("Could not parse sheet href - '" + url + "'");
  109. }
  110. // Stylesheets in IE don't always return the full path
  111. if (baseUrl && (!urlParts[1] || urlParts[2])) {
  112. baseUrlParts = baseUrl.match(urlPartsRegex);
  113. if (!baseUrlParts) {
  114. throw new Error("Could not parse page url - '" + baseUrl + "'");
  115. }
  116. urlParts[1] = urlParts[1] || baseUrlParts[1] || '';
  117. if (!urlParts[2]) {
  118. urlParts[3] = baseUrlParts[3] + urlParts[3];
  119. }
  120. }
  121. if (urlParts[3]) {
  122. rawDirectories = urlParts[3].replace(/\\/g, '/').split('/');
  123. // collapse '..' and skip '.'
  124. for (i = 0; i < rawDirectories.length; i++) {
  125. if (rawDirectories[i] === '..') {
  126. directories.pop();
  127. }
  128. else if (rawDirectories[i] !== '.') {
  129. directories.push(rawDirectories[i]);
  130. }
  131. }
  132. }
  133. returner.hostPart = urlParts[1];
  134. returner.directories = directories;
  135. returner.rawPath = (urlParts[1] || '') + rawDirectories.join('/');
  136. returner.path = (urlParts[1] || '') + directories.join('/');
  137. returner.filename = urlParts[4];
  138. returner.fileUrl = returner.path + (urlParts[4] || '');
  139. returner.url = returner.fileUrl + (urlParts[5] || '');
  140. return returner;
  141. };
  142. return AbstractFileManager;
  143. }());
  144. var FileManager = /** @class */ (function (_super) {
  145. tslib.__extends(FileManager, _super);
  146. function FileManager() {
  147. return _super !== null && _super.apply(this, arguments) || this;
  148. }
  149. FileManager.prototype.supports = function () {
  150. return true;
  151. };
  152. FileManager.prototype.supportsSync = function () {
  153. return true;
  154. };
  155. FileManager.prototype.loadFile = function (filename, currentDirectory, options, environment, callback) {
  156. var fullFilename;
  157. var isAbsoluteFilename = this.isPathAbsolute(filename);
  158. var filenamesTried = [];
  159. var self = this;
  160. var prefix = filename.slice(0, 1);
  161. var explicit = prefix === '.' || prefix === '/';
  162. var result = null;
  163. var isNodeModule = false;
  164. var npmPrefix = 'npm://';
  165. options = options || {};
  166. var paths = isAbsoluteFilename ? [''] : [currentDirectory];
  167. if (options.paths) {
  168. paths.push.apply(paths, options.paths);
  169. }
  170. if (!isAbsoluteFilename && paths.indexOf('.') === -1) {
  171. paths.push('.');
  172. }
  173. var prefixes = options.prefixes || [''];
  174. var fileParts = this.extractUrlParts(filename);
  175. if (options.syncImport) {
  176. getFileData(returnData, returnData);
  177. if (callback) {
  178. callback(result.error, result);
  179. }
  180. else {
  181. return result;
  182. }
  183. }
  184. else {
  185. // promise is guaranteed to be asyncronous
  186. // which helps as it allows the file handle
  187. // to be closed before it continues with the next file
  188. return new Promise(getFileData);
  189. }
  190. function returnData(data) {
  191. if (!data.filename) {
  192. result = { error: data };
  193. }
  194. else {
  195. result = data;
  196. }
  197. }
  198. function getFileData(fulfill, reject) {
  199. (function tryPathIndex(i) {
  200. if (i < paths.length) {
  201. (function tryPrefix(j) {
  202. if (j < prefixes.length) {
  203. isNodeModule = false;
  204. fullFilename = fileParts.rawPath + prefixes[j] + fileParts.filename;
  205. if (paths[i]) {
  206. fullFilename = path.join(paths[i], fullFilename);
  207. }
  208. if (!explicit && paths[i] === '.') {
  209. try {
  210. fullFilename = require.resolve(fullFilename);
  211. isNodeModule = true;
  212. }
  213. catch (e) {
  214. filenamesTried.push(npmPrefix + fullFilename);
  215. tryWithExtension();
  216. }
  217. }
  218. else {
  219. tryWithExtension();
  220. }
  221. function tryWithExtension() {
  222. var extFilename = options.ext ? self.tryAppendExtension(fullFilename, options.ext) : fullFilename;
  223. if (extFilename !== fullFilename && !explicit && paths[i] === '.') {
  224. try {
  225. fullFilename = require.resolve(extFilename);
  226. isNodeModule = true;
  227. }
  228. catch (e) {
  229. filenamesTried.push(npmPrefix + extFilename);
  230. fullFilename = extFilename;
  231. }
  232. }
  233. else {
  234. fullFilename = extFilename;
  235. }
  236. }
  237. var readFileArgs = [fullFilename];
  238. if (!options.rawBuffer) {
  239. readFileArgs.push('utf-8');
  240. }
  241. if (options.syncImport) {
  242. try {
  243. var data = fs$1.readFileSync.apply(this, readFileArgs);
  244. fulfill({ contents: data, filename: fullFilename });
  245. }
  246. catch (e) {
  247. filenamesTried.push(isNodeModule ? npmPrefix + fullFilename : fullFilename);
  248. return tryPrefix(j + 1);
  249. }
  250. }
  251. else {
  252. readFileArgs.push(function (e, data) {
  253. if (e) {
  254. filenamesTried.push(isNodeModule ? npmPrefix + fullFilename : fullFilename);
  255. return tryPrefix(j + 1);
  256. }
  257. fulfill({ contents: data, filename: fullFilename });
  258. });
  259. fs$1.readFile.apply(this, readFileArgs);
  260. }
  261. }
  262. else {
  263. tryPathIndex(i + 1);
  264. }
  265. })(0);
  266. }
  267. else {
  268. reject({ type: 'File', message: "'" + filename + "' wasn't found. Tried - " + filenamesTried.join(',') });
  269. }
  270. }(0));
  271. }
  272. };
  273. FileManager.prototype.loadFileSync = function (filename, currentDirectory, options, environment) {
  274. options.syncImport = true;
  275. return this.loadFile(filename, currentDirectory, options, environment);
  276. };
  277. return FileManager;
  278. }(AbstractFileManager));
  279. var logger = {
  280. error: function (msg) {
  281. this._fireEvent('error', msg);
  282. },
  283. warn: function (msg) {
  284. this._fireEvent('warn', msg);
  285. },
  286. info: function (msg) {
  287. this._fireEvent('info', msg);
  288. },
  289. debug: function (msg) {
  290. this._fireEvent('debug', msg);
  291. },
  292. addListener: function (listener) {
  293. this._listeners.push(listener);
  294. },
  295. removeListener: function (listener) {
  296. for (var i_1 = 0; i_1 < this._listeners.length; i_1++) {
  297. if (this._listeners[i_1] === listener) {
  298. this._listeners.splice(i_1, 1);
  299. return;
  300. }
  301. }
  302. },
  303. _fireEvent: function (type, msg) {
  304. for (var i_2 = 0; i_2 < this._listeners.length; i_2++) {
  305. var logFunction = this._listeners[i_2][type];
  306. if (logFunction) {
  307. logFunction(msg);
  308. }
  309. }
  310. },
  311. _listeners: []
  312. };
  313. var isUrlRe = /^(?:https?:)?\/\//i;
  314. var request;
  315. var UrlFileManager = /** @class */ (function (_super) {
  316. tslib.__extends(UrlFileManager, _super);
  317. function UrlFileManager() {
  318. return _super !== null && _super.apply(this, arguments) || this;
  319. }
  320. UrlFileManager.prototype.supports = function (filename, currentDirectory, options, environment) {
  321. return isUrlRe.test(filename) || isUrlRe.test(currentDirectory);
  322. };
  323. UrlFileManager.prototype.loadFile = function (filename, currentDirectory, options, environment) {
  324. return new Promise(function (fulfill, reject) {
  325. if (request === undefined) {
  326. try {
  327. request = require('request');
  328. }
  329. catch (e) {
  330. request = null;
  331. }
  332. }
  333. if (!request) {
  334. reject({ type: 'File', message: 'optional dependency \'request\' required to import over http(s)\n' });
  335. return;
  336. }
  337. var urlStr = isUrlRe.test(filename) ? filename : url.resolve(currentDirectory, filename);
  338. var urlObj = url.parse(urlStr);
  339. if (!urlObj.protocol) {
  340. urlObj.protocol = 'http';
  341. urlStr = urlObj.format();
  342. }
  343. request.get({ uri: urlStr, strictSSL: !options.insecure }, function (error, res, body) {
  344. if (error) {
  345. reject({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n " + error + "\n" });
  346. return;
  347. }
  348. if (res && res.statusCode === 404) {
  349. reject({ type: 'File', message: "resource '" + urlStr + "' was not found\n" });
  350. return;
  351. }
  352. if (!body) {
  353. logger.warn("Warning: Empty body (HTTP " + res.statusCode + ") returned by \"" + urlStr + "\"");
  354. }
  355. fulfill({ contents: body, filename: urlStr });
  356. });
  357. });
  358. };
  359. return UrlFileManager;
  360. }(AbstractFileManager));
  361. var colors = {
  362. 'aliceblue': '#f0f8ff',
  363. 'antiquewhite': '#faebd7',
  364. 'aqua': '#00ffff',
  365. 'aquamarine': '#7fffd4',
  366. 'azure': '#f0ffff',
  367. 'beige': '#f5f5dc',
  368. 'bisque': '#ffe4c4',
  369. 'black': '#000000',
  370. 'blanchedalmond': '#ffebcd',
  371. 'blue': '#0000ff',
  372. 'blueviolet': '#8a2be2',
  373. 'brown': '#a52a2a',
  374. 'burlywood': '#deb887',
  375. 'cadetblue': '#5f9ea0',
  376. 'chartreuse': '#7fff00',
  377. 'chocolate': '#d2691e',
  378. 'coral': '#ff7f50',
  379. 'cornflowerblue': '#6495ed',
  380. 'cornsilk': '#fff8dc',
  381. 'crimson': '#dc143c',
  382. 'cyan': '#00ffff',
  383. 'darkblue': '#00008b',
  384. 'darkcyan': '#008b8b',
  385. 'darkgoldenrod': '#b8860b',
  386. 'darkgray': '#a9a9a9',
  387. 'darkgrey': '#a9a9a9',
  388. 'darkgreen': '#006400',
  389. 'darkkhaki': '#bdb76b',
  390. 'darkmagenta': '#8b008b',
  391. 'darkolivegreen': '#556b2f',
  392. 'darkorange': '#ff8c00',
  393. 'darkorchid': '#9932cc',
  394. 'darkred': '#8b0000',
  395. 'darksalmon': '#e9967a',
  396. 'darkseagreen': '#8fbc8f',
  397. 'darkslateblue': '#483d8b',
  398. 'darkslategray': '#2f4f4f',
  399. 'darkslategrey': '#2f4f4f',
  400. 'darkturquoise': '#00ced1',
  401. 'darkviolet': '#9400d3',
  402. 'deeppink': '#ff1493',
  403. 'deepskyblue': '#00bfff',
  404. 'dimgray': '#696969',
  405. 'dimgrey': '#696969',
  406. 'dodgerblue': '#1e90ff',
  407. 'firebrick': '#b22222',
  408. 'floralwhite': '#fffaf0',
  409. 'forestgreen': '#228b22',
  410. 'fuchsia': '#ff00ff',
  411. 'gainsboro': '#dcdcdc',
  412. 'ghostwhite': '#f8f8ff',
  413. 'gold': '#ffd700',
  414. 'goldenrod': '#daa520',
  415. 'gray': '#808080',
  416. 'grey': '#808080',
  417. 'green': '#008000',
  418. 'greenyellow': '#adff2f',
  419. 'honeydew': '#f0fff0',
  420. 'hotpink': '#ff69b4',
  421. 'indianred': '#cd5c5c',
  422. 'indigo': '#4b0082',
  423. 'ivory': '#fffff0',
  424. 'khaki': '#f0e68c',
  425. 'lavender': '#e6e6fa',
  426. 'lavenderblush': '#fff0f5',
  427. 'lawngreen': '#7cfc00',
  428. 'lemonchiffon': '#fffacd',
  429. 'lightblue': '#add8e6',
  430. 'lightcoral': '#f08080',
  431. 'lightcyan': '#e0ffff',
  432. 'lightgoldenrodyellow': '#fafad2',
  433. 'lightgray': '#d3d3d3',
  434. 'lightgrey': '#d3d3d3',
  435. 'lightgreen': '#90ee90',
  436. 'lightpink': '#ffb6c1',
  437. 'lightsalmon': '#ffa07a',
  438. 'lightseagreen': '#20b2aa',
  439. 'lightskyblue': '#87cefa',
  440. 'lightslategray': '#778899',
  441. 'lightslategrey': '#778899',
  442. 'lightsteelblue': '#b0c4de',
  443. 'lightyellow': '#ffffe0',
  444. 'lime': '#00ff00',
  445. 'limegreen': '#32cd32',
  446. 'linen': '#faf0e6',
  447. 'magenta': '#ff00ff',
  448. 'maroon': '#800000',
  449. 'mediumaquamarine': '#66cdaa',
  450. 'mediumblue': '#0000cd',
  451. 'mediumorchid': '#ba55d3',
  452. 'mediumpurple': '#9370d8',
  453. 'mediumseagreen': '#3cb371',
  454. 'mediumslateblue': '#7b68ee',
  455. 'mediumspringgreen': '#00fa9a',
  456. 'mediumturquoise': '#48d1cc',
  457. 'mediumvioletred': '#c71585',
  458. 'midnightblue': '#191970',
  459. 'mintcream': '#f5fffa',
  460. 'mistyrose': '#ffe4e1',
  461. 'moccasin': '#ffe4b5',
  462. 'navajowhite': '#ffdead',
  463. 'navy': '#000080',
  464. 'oldlace': '#fdf5e6',
  465. 'olive': '#808000',
  466. 'olivedrab': '#6b8e23',
  467. 'orange': '#ffa500',
  468. 'orangered': '#ff4500',
  469. 'orchid': '#da70d6',
  470. 'palegoldenrod': '#eee8aa',
  471. 'palegreen': '#98fb98',
  472. 'paleturquoise': '#afeeee',
  473. 'palevioletred': '#d87093',
  474. 'papayawhip': '#ffefd5',
  475. 'peachpuff': '#ffdab9',
  476. 'peru': '#cd853f',
  477. 'pink': '#ffc0cb',
  478. 'plum': '#dda0dd',
  479. 'powderblue': '#b0e0e6',
  480. 'purple': '#800080',
  481. 'rebeccapurple': '#663399',
  482. 'red': '#ff0000',
  483. 'rosybrown': '#bc8f8f',
  484. 'royalblue': '#4169e1',
  485. 'saddlebrown': '#8b4513',
  486. 'salmon': '#fa8072',
  487. 'sandybrown': '#f4a460',
  488. 'seagreen': '#2e8b57',
  489. 'seashell': '#fff5ee',
  490. 'sienna': '#a0522d',
  491. 'silver': '#c0c0c0',
  492. 'skyblue': '#87ceeb',
  493. 'slateblue': '#6a5acd',
  494. 'slategray': '#708090',
  495. 'slategrey': '#708090',
  496. 'snow': '#fffafa',
  497. 'springgreen': '#00ff7f',
  498. 'steelblue': '#4682b4',
  499. 'tan': '#d2b48c',
  500. 'teal': '#008080',
  501. 'thistle': '#d8bfd8',
  502. 'tomato': '#ff6347',
  503. 'turquoise': '#40e0d0',
  504. 'violet': '#ee82ee',
  505. 'wheat': '#f5deb3',
  506. 'white': '#ffffff',
  507. 'whitesmoke': '#f5f5f5',
  508. 'yellow': '#ffff00',
  509. 'yellowgreen': '#9acd32'
  510. };
  511. var unitConversions = {
  512. length: {
  513. 'm': 1,
  514. 'cm': 0.01,
  515. 'mm': 0.001,
  516. 'in': 0.0254,
  517. 'px': 0.0254 / 96,
  518. 'pt': 0.0254 / 72,
  519. 'pc': 0.0254 / 72 * 12
  520. },
  521. duration: {
  522. 's': 1,
  523. 'ms': 0.001
  524. },
  525. angle: {
  526. 'rad': 1 / (2 * Math.PI),
  527. 'deg': 1 / 360,
  528. 'grad': 1 / 400,
  529. 'turn': 1
  530. }
  531. };
  532. var data = { colors: colors, unitConversions: unitConversions };
  533. var Node = /** @class */ (function () {
  534. function Node() {
  535. this.parent = null;
  536. this.visibilityBlocks = undefined;
  537. this.nodeVisible = undefined;
  538. this.rootNode = null;
  539. this.parsed = null;
  540. var self = this;
  541. Object.defineProperty(this, 'currentFileInfo', {
  542. get: function () { return self.fileInfo(); }
  543. });
  544. Object.defineProperty(this, 'index', {
  545. get: function () { return self.getIndex(); }
  546. });
  547. }
  548. Node.prototype.setParent = function (nodes, parent) {
  549. function set(node) {
  550. if (node && node instanceof Node) {
  551. node.parent = parent;
  552. }
  553. }
  554. if (Array.isArray(nodes)) {
  555. nodes.forEach(set);
  556. }
  557. else {
  558. set(nodes);
  559. }
  560. };
  561. Node.prototype.getIndex = function () {
  562. return this._index || (this.parent && this.parent.getIndex()) || 0;
  563. };
  564. Node.prototype.fileInfo = function () {
  565. return this._fileInfo || (this.parent && this.parent.fileInfo()) || {};
  566. };
  567. Node.prototype.isRulesetLike = function () {
  568. return false;
  569. };
  570. Node.prototype.toCSS = function (context) {
  571. var strs = [];
  572. this.genCSS(context, {
  573. add: function (chunk, fileInfo, index) {
  574. strs.push(chunk);
  575. },
  576. isEmpty: function () {
  577. return strs.length === 0;
  578. }
  579. });
  580. return strs.join('');
  581. };
  582. Node.prototype.genCSS = function (context, output) {
  583. output.add(this.value);
  584. };
  585. Node.prototype.accept = function (visitor) {
  586. this.value = visitor.visit(this.value);
  587. };
  588. Node.prototype.eval = function () { return this; };
  589. Node.prototype._operate = function (context, op, a, b) {
  590. switch (op) {
  591. case '+': return a + b;
  592. case '-': return a - b;
  593. case '*': return a * b;
  594. case '/': return a / b;
  595. }
  596. };
  597. Node.prototype.fround = function (context, value) {
  598. var precision = context && context.numPrecision;
  599. // add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999...) are properly rounded:
  600. return (precision) ? Number((value + 2e-16).toFixed(precision)) : value;
  601. };
  602. // Returns true if this node represents root of ast imported by reference
  603. Node.prototype.blocksVisibility = function () {
  604. if (this.visibilityBlocks == null) {
  605. this.visibilityBlocks = 0;
  606. }
  607. return this.visibilityBlocks !== 0;
  608. };
  609. Node.prototype.addVisibilityBlock = function () {
  610. if (this.visibilityBlocks == null) {
  611. this.visibilityBlocks = 0;
  612. }
  613. this.visibilityBlocks = this.visibilityBlocks + 1;
  614. };
  615. Node.prototype.removeVisibilityBlock = function () {
  616. if (this.visibilityBlocks == null) {
  617. this.visibilityBlocks = 0;
  618. }
  619. this.visibilityBlocks = this.visibilityBlocks - 1;
  620. };
  621. // Turns on node visibility - if called node will be shown in output regardless
  622. // of whether it comes from import by reference or not
  623. Node.prototype.ensureVisibility = function () {
  624. this.nodeVisible = true;
  625. };
  626. // Turns off node visibility - if called node will NOT be shown in output regardless
  627. // of whether it comes from import by reference or not
  628. Node.prototype.ensureInvisibility = function () {
  629. this.nodeVisible = false;
  630. };
  631. // return values:
  632. // false - the node must not be visible
  633. // true - the node must be visible
  634. // undefined or null - the node has the same visibility as its parent
  635. Node.prototype.isVisible = function () {
  636. return this.nodeVisible;
  637. };
  638. Node.prototype.visibilityInfo = function () {
  639. return {
  640. visibilityBlocks: this.visibilityBlocks,
  641. nodeVisible: this.nodeVisible
  642. };
  643. };
  644. Node.prototype.copyVisibilityInfo = function (info) {
  645. if (!info) {
  646. return;
  647. }
  648. this.visibilityBlocks = info.visibilityBlocks;
  649. this.nodeVisible = info.nodeVisible;
  650. };
  651. return Node;
  652. }());
  653. Node.compare = function (a, b) {
  654. /* returns:
  655. -1: a < b
  656. 0: a = b
  657. 1: a > b
  658. and *any* other value for a != b (e.g. undefined, NaN, -2 etc.) */
  659. if ((a.compare) &&
  660. // for "symmetric results" force toCSS-based comparison
  661. // of Quoted or Anonymous if either value is one of those
  662. !(b.type === 'Quoted' || b.type === 'Anonymous')) {
  663. return a.compare(b);
  664. }
  665. else if (b.compare) {
  666. return -b.compare(a);
  667. }
  668. else if (a.type !== b.type) {
  669. return undefined;
  670. }
  671. a = a.value;
  672. b = b.value;
  673. if (!Array.isArray(a)) {
  674. return a === b ? 0 : undefined;
  675. }
  676. if (a.length !== b.length) {
  677. return undefined;
  678. }
  679. for (var i_1 = 0; i_1 < a.length; i_1++) {
  680. if (Node.compare(a[i_1], b[i_1]) !== 0) {
  681. return undefined;
  682. }
  683. }
  684. return 0;
  685. };
  686. Node.numericCompare = function (a, b) { return a < b ? -1
  687. : a === b ? 0
  688. : a > b ? 1 : undefined; };
  689. //
  690. // RGB Colors - #ff0014, #eee
  691. //
  692. var Color = /** @class */ (function (_super) {
  693. tslib.__extends(Color, _super);
  694. function Color(rgb, a, originalForm) {
  695. var _this = _super.call(this) || this;
  696. var self = _this;
  697. //
  698. // The end goal here, is to parse the arguments
  699. // into an integer triplet, such as `128, 255, 0`
  700. //
  701. // This facilitates operations and conversions.
  702. //
  703. if (Array.isArray(rgb)) {
  704. _this.rgb = rgb;
  705. }
  706. else if (rgb.length >= 6) {
  707. _this.rgb = [];
  708. rgb.match(/.{2}/g).map(function (c, i) {
  709. if (i < 3) {
  710. self.rgb.push(parseInt(c, 16));
  711. }
  712. else {
  713. self.alpha = (parseInt(c, 16)) / 255;
  714. }
  715. });
  716. }
  717. else {
  718. _this.rgb = [];
  719. rgb.split('').map(function (c, i) {
  720. if (i < 3) {
  721. self.rgb.push(parseInt(c + c, 16));
  722. }
  723. else {
  724. self.alpha = (parseInt(c + c, 16)) / 255;
  725. }
  726. });
  727. }
  728. _this.alpha = _this.alpha || (typeof a === 'number' ? a : 1);
  729. if (typeof originalForm !== 'undefined') {
  730. _this.value = originalForm;
  731. }
  732. return _this;
  733. }
  734. Color.prototype.luma = function () {
  735. var r = this.rgb[0] / 255;
  736. var g = this.rgb[1] / 255;
  737. var b = this.rgb[2] / 255;
  738. r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
  739. g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
  740. b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
  741. return 0.2126 * r + 0.7152 * g + 0.0722 * b;
  742. };
  743. Color.prototype.genCSS = function (context, output) {
  744. output.add(this.toCSS(context));
  745. };
  746. Color.prototype.toCSS = function (context, doNotCompress) {
  747. var compress = context && context.compress && !doNotCompress;
  748. var color;
  749. var alpha;
  750. var colorFunction;
  751. var args = [];
  752. // `value` is set if this color was originally
  753. // converted from a named color string so we need
  754. // to respect this and try to output named color too.
  755. alpha = this.fround(context, this.alpha);
  756. if (this.value) {
  757. if (this.value.indexOf('rgb') === 0) {
  758. if (alpha < 1) {
  759. colorFunction = 'rgba';
  760. }
  761. }
  762. else if (this.value.indexOf('hsl') === 0) {
  763. if (alpha < 1) {
  764. colorFunction = 'hsla';
  765. }
  766. else {
  767. colorFunction = 'hsl';
  768. }
  769. }
  770. else {
  771. return this.value;
  772. }
  773. }
  774. else {
  775. if (alpha < 1) {
  776. colorFunction = 'rgba';
  777. }
  778. }
  779. switch (colorFunction) {
  780. case 'rgba':
  781. args = this.rgb.map(function (c) { return clamp(Math.round(c), 255); }).concat(clamp(alpha, 1));
  782. break;
  783. case 'hsla':
  784. args.push(clamp(alpha, 1));
  785. case 'hsl':
  786. color = this.toHSL();
  787. args = [
  788. this.fround(context, color.h),
  789. this.fround(context, color.s * 100) + "%",
  790. this.fround(context, color.l * 100) + "%"
  791. ].concat(args);
  792. }
  793. if (colorFunction) {
  794. // Values are capped between `0` and `255`, rounded and zero-padded.
  795. return colorFunction + "(" + args.join("," + (compress ? '' : ' ')) + ")";
  796. }
  797. color = this.toRGB();
  798. if (compress) {
  799. var splitcolor = color.split('');
  800. // Convert color to short format
  801. if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
  802. color = "#" + splitcolor[1] + splitcolor[3] + splitcolor[5];
  803. }
  804. }
  805. return color;
  806. };
  807. //
  808. // Operations have to be done per-channel, if not,
  809. // channels will spill onto each other. Once we have
  810. // our result, in the form of an integer triplet,
  811. // we create a new Color node to hold the result.
  812. //
  813. Color.prototype.operate = function (context, op, other) {
  814. var rgb = new Array(3);
  815. var alpha = this.alpha * (1 - other.alpha) + other.alpha;
  816. for (var c = 0; c < 3; c++) {
  817. rgb[c] = this._operate(context, op, this.rgb[c], other.rgb[c]);
  818. }
  819. return new Color(rgb, alpha);
  820. };
  821. Color.prototype.toRGB = function () {
  822. return toHex(this.rgb);
  823. };
  824. Color.prototype.toHSL = function () {
  825. var r = this.rgb[0] / 255;
  826. var g = this.rgb[1] / 255;
  827. var b = this.rgb[2] / 255;
  828. var a = this.alpha;
  829. var max = Math.max(r, g, b);
  830. var min = Math.min(r, g, b);
  831. var h;
  832. var s;
  833. var l = (max + min) / 2;
  834. var d = max - min;
  835. if (max === min) {
  836. h = s = 0;
  837. }
  838. else {
  839. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  840. switch (max) {
  841. case r:
  842. h = (g - b) / d + (g < b ? 6 : 0);
  843. break;
  844. case g:
  845. h = (b - r) / d + 2;
  846. break;
  847. case b:
  848. h = (r - g) / d + 4;
  849. break;
  850. }
  851. h /= 6;
  852. }
  853. return { h: h * 360, s: s, l: l, a: a };
  854. };
  855. // Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
  856. Color.prototype.toHSV = function () {
  857. var r = this.rgb[0] / 255;
  858. var g = this.rgb[1] / 255;
  859. var b = this.rgb[2] / 255;
  860. var a = this.alpha;
  861. var max = Math.max(r, g, b);
  862. var min = Math.min(r, g, b);
  863. var h;
  864. var s;
  865. var v = max;
  866. var d = max - min;
  867. if (max === 0) {
  868. s = 0;
  869. }
  870. else {
  871. s = d / max;
  872. }
  873. if (max === min) {
  874. h = 0;
  875. }
  876. else {
  877. switch (max) {
  878. case r:
  879. h = (g - b) / d + (g < b ? 6 : 0);
  880. break;
  881. case g:
  882. h = (b - r) / d + 2;
  883. break;
  884. case b:
  885. h = (r - g) / d + 4;
  886. break;
  887. }
  888. h /= 6;
  889. }
  890. return { h: h * 360, s: s, v: v, a: a };
  891. };
  892. Color.prototype.toARGB = function () {
  893. return toHex([this.alpha * 255].concat(this.rgb));
  894. };
  895. Color.prototype.compare = function (x) {
  896. return (x.rgb &&
  897. x.rgb[0] === this.rgb[0] &&
  898. x.rgb[1] === this.rgb[1] &&
  899. x.rgb[2] === this.rgb[2] &&
  900. x.alpha === this.alpha) ? 0 : undefined;
  901. };
  902. return Color;
  903. }(Node));
  904. Color.prototype.type = 'Color';
  905. function clamp(v, max) {
  906. return Math.min(Math.max(v, 0), max);
  907. }
  908. function toHex(v) {
  909. return "#" + v.map(function (c) {
  910. c = clamp(Math.round(c), 255);
  911. return (c < 16 ? '0' : '') + c.toString(16);
  912. }).join('');
  913. }
  914. Color.fromKeyword = function (keyword) {
  915. var c;
  916. var key = keyword.toLowerCase();
  917. if (colors.hasOwnProperty(key)) {
  918. c = new Color(colors[key].slice(1));
  919. }
  920. else if (key === 'transparent') {
  921. c = new Color([0, 0, 0], 0);
  922. }
  923. if (c) {
  924. c.value = keyword;
  925. return c;
  926. }
  927. };
  928. var Paren = /** @class */ (function (_super) {
  929. tslib.__extends(Paren, _super);
  930. function Paren(node) {
  931. var _this = _super.call(this) || this;
  932. _this.value = node;
  933. return _this;
  934. }
  935. Paren.prototype.genCSS = function (context, output) {
  936. output.add('(');
  937. this.value.genCSS(context, output);
  938. output.add(')');
  939. };
  940. Paren.prototype.eval = function (context) {
  941. return new Paren(this.value.eval(context));
  942. };
  943. return Paren;
  944. }(Node));
  945. Paren.prototype.type = 'Paren';
  946. var _noSpaceCombinators = {
  947. '': true,
  948. ' ': true,
  949. '|': true
  950. };
  951. var Combinator = /** @class */ (function (_super) {
  952. tslib.__extends(Combinator, _super);
  953. function Combinator(value) {
  954. var _this = _super.call(this) || this;
  955. if (value === ' ') {
  956. _this.value = ' ';
  957. _this.emptyOrWhitespace = true;
  958. }
  959. else {
  960. _this.value = value ? value.trim() : '';
  961. _this.emptyOrWhitespace = _this.value === '';
  962. }
  963. return _this;
  964. }
  965. Combinator.prototype.genCSS = function (context, output) {
  966. var spaceOrEmpty = (context.compress || _noSpaceCombinators[this.value]) ? '' : ' ';
  967. output.add(spaceOrEmpty + this.value + spaceOrEmpty);
  968. };
  969. return Combinator;
  970. }(Node));
  971. Combinator.prototype.type = 'Combinator';
  972. var Element = /** @class */ (function (_super) {
  973. tslib.__extends(Element, _super);
  974. function Element(combinator, value, isVariable, index, currentFileInfo, visibilityInfo) {
  975. var _this = _super.call(this) || this;
  976. _this.combinator = combinator instanceof Combinator ?
  977. combinator : new Combinator(combinator);
  978. if (typeof value === 'string') {
  979. _this.value = value.trim();
  980. }
  981. else if (value) {
  982. _this.value = value;
  983. }
  984. else {
  985. _this.value = '';
  986. }
  987. _this.isVariable = isVariable;
  988. _this._index = index;
  989. _this._fileInfo = currentFileInfo;
  990. _this.copyVisibilityInfo(visibilityInfo);
  991. _this.setParent(_this.combinator, _this);
  992. return _this;
  993. }
  994. Element.prototype.accept = function (visitor) {
  995. var value = this.value;
  996. this.combinator = visitor.visit(this.combinator);
  997. if (typeof value === 'object') {
  998. this.value = visitor.visit(value);
  999. }
  1000. };
  1001. Element.prototype.eval = function (context) {
  1002. return new Element(this.combinator, this.value.eval ? this.value.eval(context) : this.value, this.isVariable, this.getIndex(), this.fileInfo(), this.visibilityInfo());
  1003. };
  1004. Element.prototype.clone = function () {
  1005. return new Element(this.combinator, this.value, this.isVariable, this.getIndex(), this.fileInfo(), this.visibilityInfo());
  1006. };
  1007. Element.prototype.genCSS = function (context, output) {
  1008. output.add(this.toCSS(context), this.fileInfo(), this.getIndex());
  1009. };
  1010. Element.prototype.toCSS = function (context) {
  1011. if (context === void 0) { context = {}; }
  1012. var value = this.value;
  1013. var firstSelector = context.firstSelector;
  1014. if (value instanceof Paren) {
  1015. // selector in parens should not be affected by outer selector
  1016. // flags (breaks only interpolated selectors - see #1973)
  1017. context.firstSelector = true;
  1018. }
  1019. value = value.toCSS ? value.toCSS(context) : value;
  1020. context.firstSelector = firstSelector;
  1021. if (value === '' && this.combinator.value.charAt(0) === '&') {
  1022. return '';
  1023. }
  1024. else {
  1025. return this.combinator.toCSS(context) + value;
  1026. }
  1027. };
  1028. return Element;
  1029. }(Node));
  1030. Element.prototype.type = 'Element';
  1031. var Math$1 = {
  1032. ALWAYS: 0,
  1033. PARENS_DIVISION: 1,
  1034. PARENS: 2,
  1035. STRICT_LEGACY: 3
  1036. };
  1037. var RewriteUrls = {
  1038. OFF: 0,
  1039. LOCAL: 1,
  1040. ALL: 2
  1041. };
  1042. /* jshint proto: true */
  1043. function getLocation(index, inputStream) {
  1044. var n = index + 1;
  1045. var line = null;
  1046. var column = -1;
  1047. while (--n >= 0 && inputStream.charAt(n) !== '\n') {
  1048. column++;
  1049. }
  1050. if (typeof index === 'number') {
  1051. line = (inputStream.slice(0, index).match(/\n/g) || '').length;
  1052. }
  1053. return {
  1054. line: line,
  1055. column: column
  1056. };
  1057. }
  1058. function copyArray(arr) {
  1059. var i;
  1060. var length = arr.length;
  1061. var copy = new Array(length);
  1062. for (i = 0; i < length; i++) {
  1063. copy[i] = arr[i];
  1064. }
  1065. return copy;
  1066. }
  1067. function clone(obj) {
  1068. var cloned = {};
  1069. for (var prop in obj) {
  1070. if (obj.hasOwnProperty(prop)) {
  1071. cloned[prop] = obj[prop];
  1072. }
  1073. }
  1074. return cloned;
  1075. }
  1076. function defaults(obj1, obj2) {
  1077. var newObj = obj2 || {};
  1078. if (!obj2._defaults) {
  1079. newObj = {};
  1080. var defaults_1 = CloneHelper(obj1);
  1081. newObj._defaults = defaults_1;
  1082. var cloned = obj2 ? CloneHelper(obj2) : {};
  1083. Object.assign(newObj, defaults_1, cloned);
  1084. }
  1085. return newObj;
  1086. }
  1087. function copyOptions(obj1, obj2) {
  1088. if (obj2 && obj2._defaults) {
  1089. return obj2;
  1090. }
  1091. var opts = defaults(obj1, obj2);
  1092. if (opts.strictMath) {
  1093. opts.math = Math$1.STRICT_LEGACY;
  1094. }
  1095. // Back compat with changed relativeUrls option
  1096. if (opts.relativeUrls) {
  1097. opts.rewriteUrls = RewriteUrls.ALL;
  1098. }
  1099. if (typeof opts.math === 'string') {
  1100. switch (opts.math.toLowerCase()) {
  1101. case 'always':
  1102. opts.math = Math$1.ALWAYS;
  1103. break;
  1104. case 'parens-division':
  1105. opts.math = Math$1.PARENS_DIVISION;
  1106. break;
  1107. case 'strict':
  1108. case 'parens':
  1109. opts.math = Math$1.PARENS;
  1110. break;
  1111. case 'strict-legacy':
  1112. opts.math = Math$1.STRICT_LEGACY;
  1113. }
  1114. }
  1115. if (typeof opts.rewriteUrls === 'string') {
  1116. switch (opts.rewriteUrls.toLowerCase()) {
  1117. case 'off':
  1118. opts.rewriteUrls = RewriteUrls.OFF;
  1119. break;
  1120. case 'local':
  1121. opts.rewriteUrls = RewriteUrls.LOCAL;
  1122. break;
  1123. case 'all':
  1124. opts.rewriteUrls = RewriteUrls.ALL;
  1125. break;
  1126. }
  1127. }
  1128. return opts;
  1129. }
  1130. function merge(obj1, obj2) {
  1131. for (var prop in obj2) {
  1132. if (obj2.hasOwnProperty(prop)) {
  1133. obj1[prop] = obj2[prop];
  1134. }
  1135. }
  1136. return obj1;
  1137. }
  1138. function flattenArray(arr, result) {
  1139. if (result === void 0) { result = []; }
  1140. for (var i_1 = 0, length_1 = arr.length; i_1 < length_1; i_1++) {
  1141. var value = arr[i_1];
  1142. if (Array.isArray(value)) {
  1143. flattenArray(value, result);
  1144. }
  1145. else {
  1146. if (value !== undefined) {
  1147. result.push(value);
  1148. }
  1149. }
  1150. }
  1151. return result;
  1152. }
  1153. var utils = /*#__PURE__*/Object.freeze({
  1154. __proto__: null,
  1155. getLocation: getLocation,
  1156. copyArray: copyArray,
  1157. clone: clone,
  1158. defaults: defaults,
  1159. copyOptions: copyOptions,
  1160. merge: merge,
  1161. flattenArray: flattenArray
  1162. });
  1163. var anonymousFunc = /(<anonymous>|Function):(\d+):(\d+)/;
  1164. /**
  1165. * This is a centralized class of any error that could be thrown internally (mostly by the parser).
  1166. * Besides standard .message it keeps some additional data like a path to the file where the error
  1167. * occurred along with line and column numbers.
  1168. *
  1169. * @class
  1170. * @extends Error
  1171. * @type {module.LessError}
  1172. *
  1173. * @prop {string} type
  1174. * @prop {string} filename
  1175. * @prop {number} index
  1176. * @prop {number} line
  1177. * @prop {number} column
  1178. * @prop {number} callLine
  1179. * @prop {number} callExtract
  1180. * @prop {string[]} extract
  1181. *
  1182. * @param {Object} e - An error object to wrap around or just a descriptive object
  1183. * @param {Object} fileContentMap - An object with file contents in 'contents' property (like importManager) @todo - move to fileManager?
  1184. * @param {string} [currentFilename]
  1185. */
  1186. var LessError = function LessError(e, fileContentMap, currentFilename) {
  1187. Error.call(this);
  1188. var filename = e.filename || currentFilename;
  1189. this.message = e.message;
  1190. this.stack = e.stack;
  1191. if (fileContentMap && filename) {
  1192. var input = fileContentMap.contents[filename];
  1193. var loc = getLocation(e.index, input);
  1194. var line = loc.line;
  1195. var col = loc.column;
  1196. var callLine = e.call && getLocation(e.call, input).line;
  1197. var lines = input ? input.split('\n') : '';
  1198. this.type = e.type || 'Syntax';
  1199. this.filename = filename;
  1200. this.index = e.index;
  1201. this.line = typeof line === 'number' ? line + 1 : null;
  1202. this.column = col;
  1203. if (!this.line && this.stack) {
  1204. var found = this.stack.match(anonymousFunc);
  1205. /**
  1206. * We have to figure out how this environment stringifies anonymous functions
  1207. * so we can correctly map plugin errors.
  1208. *
  1209. * Note, in Node 8, the output of anonymous funcs varied based on parameters
  1210. * being present or not, so we inject dummy params.
  1211. */
  1212. var func = new Function('a', 'throw new Error()');
  1213. var lineAdjust = 0;
  1214. try {
  1215. func();
  1216. }
  1217. catch (e) {
  1218. var match = e.stack.match(anonymousFunc);
  1219. var line_1 = parseInt(match[2]);
  1220. lineAdjust = 1 - line_1;
  1221. }
  1222. if (found) {
  1223. if (found[2]) {
  1224. this.line = parseInt(found[2]) + lineAdjust;
  1225. }
  1226. if (found[3]) {
  1227. this.column = parseInt(found[3]);
  1228. }
  1229. }
  1230. }
  1231. this.callLine = callLine + 1;
  1232. this.callExtract = lines[callLine];
  1233. this.extract = [
  1234. lines[this.line - 2],
  1235. lines[this.line - 1],
  1236. lines[this.line]
  1237. ];
  1238. }
  1239. };
  1240. if (typeof Object.create === 'undefined') {
  1241. var F = function () { };
  1242. F.prototype = Error.prototype;
  1243. LessError.prototype = new F();
  1244. }
  1245. else {
  1246. LessError.prototype = Object.create(Error.prototype);
  1247. }
  1248. LessError.prototype.constructor = LessError;
  1249. /**
  1250. * An overridden version of the default Object.prototype.toString
  1251. * which uses additional information to create a helpful message.
  1252. *
  1253. * @param {Object} options
  1254. * @returns {string}
  1255. */
  1256. LessError.prototype.toString = function (options) {
  1257. if (options === void 0) { options = {}; }
  1258. var message = '';
  1259. var extract = this.extract || [];
  1260. var error = [];
  1261. var stylize = function (str) { return str; };
  1262. if (options.stylize) {
  1263. var type = typeof options.stylize;
  1264. if (type !== 'function') {
  1265. throw Error("options.stylize should be a function, got a " + type + "!");
  1266. }
  1267. stylize = options.stylize;
  1268. }
  1269. if (this.line !== null) {
  1270. if (typeof extract[0] === 'string') {
  1271. error.push(stylize(this.line - 1 + " " + extract[0], 'grey'));
  1272. }
  1273. if (typeof extract[1] === 'string') {
  1274. var errorTxt = this.line + " ";
  1275. if (extract[1]) {
  1276. errorTxt += extract[1].slice(0, this.column) +
  1277. stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') +
  1278. extract[1].slice(this.column + 1), 'red'), 'inverse');
  1279. }
  1280. error.push(errorTxt);
  1281. }
  1282. if (typeof extract[2] === 'string') {
  1283. error.push(stylize(this.line + 1 + " " + extract[2], 'grey'));
  1284. }
  1285. error = error.join('\n') + stylize('', 'reset') + "\n";
  1286. }
  1287. message += stylize(this.type + "Error: " + this.message, 'red');
  1288. if (this.filename) {
  1289. message += stylize(' in ', 'red') + this.filename;
  1290. }
  1291. if (this.line) {
  1292. message += stylize(" on line " + this.line + ", column " + (this.column + 1) + ":", 'grey');
  1293. }
  1294. message += "\n" + error;
  1295. if (this.callLine) {
  1296. message += stylize('from ', 'red') + (this.filename || '') + "/n";
  1297. message += stylize(this.callLine, 'grey') + " " + this.callExtract + "/n";
  1298. }
  1299. return message;
  1300. };
  1301. var Selector = /** @class */ (function (_super) {
  1302. tslib.__extends(Selector, _super);
  1303. function Selector(elements, extendList, condition, index, currentFileInfo, visibilityInfo) {
  1304. var _this = _super.call(this) || this;
  1305. _this.extendList = extendList;
  1306. _this.condition = condition;
  1307. _this.evaldCondition = !condition;
  1308. _this._index = index;
  1309. _this._fileInfo = currentFileInfo;
  1310. _this.elements = _this.getElements(elements);
  1311. _this.mixinElements_ = undefined;
  1312. _this.copyVisibilityInfo(visibilityInfo);
  1313. _this.setParent(_this.elements, _this);
  1314. return _this;
  1315. }
  1316. Selector.prototype.accept = function (visitor) {
  1317. if (this.elements) {
  1318. this.elements = visitor.visitArray(this.elements);
  1319. }
  1320. if (this.extendList) {
  1321. this.extendList = visitor.visitArray(this.extendList);
  1322. }
  1323. if (this.condition) {
  1324. this.condition = visitor.visit(this.condition);
  1325. }
  1326. };
  1327. Selector.prototype.createDerived = function (elements, extendList, evaldCondition) {
  1328. elements = this.getElements(elements);
  1329. var newSelector = new Selector(elements, extendList || this.extendList, null, this.getIndex(), this.fileInfo(), this.visibilityInfo());
  1330. newSelector.evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
  1331. newSelector.mediaEmpty = this.mediaEmpty;
  1332. return newSelector;
  1333. };
  1334. Selector.prototype.getElements = function (els) {
  1335. if (!els) {
  1336. return [new Element('', '&', false, this._index, this._fileInfo)];
  1337. }
  1338. if (typeof els === 'string') {
  1339. this.parse.parseNode(els, ['selector'], this._index, this._fileInfo, function (err, result) {
  1340. if (err) {
  1341. throw new LessError({
  1342. index: err.index,
  1343. message: err.message
  1344. }, this.parse.imports, this._fileInfo.filename);
  1345. }
  1346. els = result[0].elements;
  1347. });
  1348. }
  1349. return els;
  1350. };
  1351. Selector.prototype.createEmptySelectors = function () {
  1352. var el = new Element('', '&', false, this._index, this._fileInfo);
  1353. var sels = [new Selector([el], null, null, this._index, this._fileInfo)];
  1354. sels[0].mediaEmpty = true;
  1355. return sels;
  1356. };
  1357. Selector.prototype.match = function (other) {
  1358. var elements = this.elements;
  1359. var len = elements.length;
  1360. var olen;
  1361. var i;
  1362. other = other.mixinElements();
  1363. olen = other.length;
  1364. if (olen === 0 || len < olen) {
  1365. return 0;
  1366. }
  1367. else {
  1368. for (i = 0; i < olen; i++) {
  1369. if (elements[i].value !== other[i]) {
  1370. return 0;
  1371. }
  1372. }
  1373. }
  1374. return olen; // return number of matched elements
  1375. };
  1376. Selector.prototype.mixinElements = function () {
  1377. if (this.mixinElements_) {
  1378. return this.mixinElements_;
  1379. }
  1380. var elements = this.elements.map(function (v) { return v.combinator.value + (v.value.value || v.value); }).join('').match(/[,&#\*\.\w-]([\w-]|(\\.))*/g);
  1381. if (elements) {
  1382. if (elements[0] === '&') {
  1383. elements.shift();
  1384. }
  1385. }
  1386. else {
  1387. elements = [];
  1388. }
  1389. return (this.mixinElements_ = elements);
  1390. };
  1391. Selector.prototype.isJustParentSelector = function () {
  1392. return !this.mediaEmpty &&
  1393. this.elements.length === 1 &&
  1394. this.elements[0].value === '&' &&
  1395. (this.elements[0].combinator.value === ' ' || this.elements[0].combinator.value === '');
  1396. };
  1397. Selector.prototype.eval = function (context) {
  1398. var evaldCondition = this.condition && this.condition.eval(context);
  1399. var elements = this.elements;
  1400. var extendList = this.extendList;
  1401. elements = elements && elements.map(function (e) { return e.eval(context); });
  1402. extendList = extendList && extendList.map(function (extend) { return extend.eval(context); });
  1403. return this.createDerived(elements, extendList, evaldCondition);
  1404. };
  1405. Selector.prototype.genCSS = function (context, output) {
  1406. var i;
  1407. var element;
  1408. if ((!context || !context.firstSelector) && this.elements[0].combinator.value === '') {
  1409. output.add(' ', this.fileInfo(), this.getIndex());
  1410. }
  1411. for (i = 0; i < this.elements.length; i++) {
  1412. element = this.elements[i];
  1413. element.genCSS(context, output);
  1414. }
  1415. };
  1416. Selector.prototype.getIsOutput = function () {
  1417. return this.evaldCondition;
  1418. };
  1419. return Selector;
  1420. }(Node));
  1421. Selector.prototype.type = 'Selector';
  1422. var Value = /** @class */ (function (_super) {
  1423. tslib.__extends(Value, _super);
  1424. function Value(value) {
  1425. var _this = _super.call(this) || this;
  1426. if (!value) {
  1427. throw new Error('Value requires an array argument');
  1428. }
  1429. if (!Array.isArray(value)) {
  1430. _this.value = [value];
  1431. }
  1432. else {
  1433. _this.value = value;
  1434. }
  1435. return _this;
  1436. }
  1437. Value.prototype.accept = function (visitor) {
  1438. if (this.value) {
  1439. this.value = visitor.visitArray(this.value);
  1440. }
  1441. };
  1442. Value.prototype.eval = function (context) {
  1443. if (this.value.length === 1) {
  1444. return this.value[0].eval(context);
  1445. }
  1446. else {
  1447. return new Value(this.value.map(function (v) { return v.eval(context); }));
  1448. }
  1449. };
  1450. Value.prototype.genCSS = function (context, output) {
  1451. var i;
  1452. for (i = 0; i < this.value.length; i++) {
  1453. this.value[i].genCSS(context, output);
  1454. if (i + 1 < this.value.length) {
  1455. output.add((context && context.compress) ? ',' : ', ');
  1456. }
  1457. }
  1458. };
  1459. return Value;
  1460. }(Node));
  1461. Value.prototype.type = 'Value';
  1462. var Keyword = /** @class */ (function (_super) {
  1463. tslib.__extends(Keyword, _super);
  1464. function Keyword(value) {
  1465. var _this = _super.call(this) || this;
  1466. _this.value = value;
  1467. return _this;
  1468. }
  1469. Keyword.prototype.genCSS = function (context, output) {
  1470. if (this.value === '%') {
  1471. throw { type: 'Syntax', message: 'Invalid % without number' };
  1472. }
  1473. output.add(this.value);
  1474. };
  1475. return Keyword;
  1476. }(Node));
  1477. Keyword.prototype.type = 'Keyword';
  1478. Keyword.True = new Keyword('true');
  1479. Keyword.False = new Keyword('false');
  1480. var Anonymous = /** @class */ (function (_super) {
  1481. tslib.__extends(Anonymous, _super);
  1482. function Anonymous(value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) {
  1483. var _this = _super.call(this) || this;
  1484. _this.value = value;
  1485. _this._index = index;
  1486. _this._fileInfo = currentFileInfo;
  1487. _this.mapLines = mapLines;
  1488. _this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
  1489. _this.allowRoot = true;
  1490. _this.copyVisibilityInfo(visibilityInfo);
  1491. return _this;
  1492. }
  1493. Anonymous.prototype.eval = function () {
  1494. return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo());
  1495. };
  1496. Anonymous.prototype.compare = function (other) {
  1497. return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
  1498. };
  1499. Anonymous.prototype.isRulesetLike = function () {
  1500. return this.rulesetLike;
  1501. };
  1502. Anonymous.prototype.genCSS = function (context, output) {
  1503. this.nodeVisible = Boolean(this.value);
  1504. if (this.nodeVisible) {
  1505. output.add(this.value, this._fileInfo, this._index, this.mapLines);
  1506. }
  1507. };
  1508. return Anonymous;
  1509. }(Node));
  1510. Anonymous.prototype.type = 'Anonymous';
  1511. var MATH = Math$1;
  1512. var Declaration = /** @class */ (function (_super) {
  1513. tslib.__extends(Declaration, _super);
  1514. function Declaration(name, value, important, merge, index, currentFileInfo, inline, variable) {
  1515. var _this = _super.call(this) || this;
  1516. _this.name = name;
  1517. _this.value = (value instanceof Node) ? value : new Value([value ? new Anonymous(value) : null]);
  1518. _this.important = important ? " " + important.trim() : '';
  1519. _this.merge = merge;
  1520. _this._index = index;
  1521. _this._fileInfo = currentFileInfo;
  1522. _this.inline = inline || false;
  1523. _this.variable = (variable !== undefined) ? variable
  1524. : (name.charAt && (name.charAt(0) === '@'));
  1525. _this.allowRoot = true;
  1526. _this.setParent(_this.value, _this);
  1527. return _this;
  1528. }
  1529. Declaration.prototype.genCSS = function (context, output) {
  1530. output.add(this.name + (context.compress ? ':' : ': '), this.fileInfo(), this.getIndex());
  1531. try {
  1532. this.value.genCSS(context, output);
  1533. }
  1534. catch (e) {
  1535. e.index = this._index;
  1536. e.filename = this._fileInfo.filename;
  1537. throw e;
  1538. }
  1539. output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? '' : ';'), this._fileInfo, this._index);
  1540. };
  1541. Declaration.prototype.eval = function (context) {
  1542. var mathBypass = false;
  1543. var prevMath;
  1544. var name = this.name;
  1545. var evaldValue;
  1546. var variable = this.variable;
  1547. if (typeof name !== 'string') {
  1548. // expand 'primitive' name directly to get
  1549. // things faster (~10% for benchmark.less):
  1550. name = (name.length === 1) && (name[0] instanceof Keyword) ?
  1551. name[0].value : evalName(context, name);
  1552. variable = false; // never treat expanded interpolation as new variable name
  1553. }
  1554. // @todo remove when parens-division is default
  1555. if (name === 'font' && context.math === MATH.ALWAYS) {
  1556. mathBypass = true;
  1557. prevMath = context.math;
  1558. context.math = MATH.PARENS_DIVISION;
  1559. }
  1560. try {
  1561. context.importantScope.push({});
  1562. evaldValue = this.value.eval(context);
  1563. if (!this.variable && evaldValue.type === 'DetachedRuleset') {
  1564. throw { message: 'Rulesets cannot be evaluated on a property.',
  1565. index: this.getIndex(), filename: this.fileInfo().filename };
  1566. }
  1567. var important = this.important;
  1568. var importantResult = context.importantScope.pop();
  1569. if (!important && importantResult.important) {
  1570. important = importantResult.important;
  1571. }
  1572. return new Declaration(name, evaldValue, important, this.merge, this.getIndex(), this.fileInfo(), this.inline, variable);
  1573. }
  1574. catch (e) {
  1575. if (typeof e.index !== 'number') {
  1576. e.index = this.getIndex();
  1577. e.filename = this.fileInfo().filename;
  1578. }
  1579. throw e;
  1580. }
  1581. finally {
  1582. if (mathBypass) {
  1583. context.math = prevMath;
  1584. }
  1585. }
  1586. };
  1587. Declaration.prototype.makeImportant = function () {
  1588. return new Declaration(this.name, this.value, '!important', this.merge, this.getIndex(), this.fileInfo(), this.inline);
  1589. };
  1590. return Declaration;
  1591. }(Node));
  1592. function evalName(context, name) {
  1593. var value = '';
  1594. var i;
  1595. var n = name.length;
  1596. var output = { add: function (s) { value += s; } };
  1597. for (i = 0; i < n; i++) {
  1598. name[i].eval(context).genCSS(context, output);
  1599. }
  1600. return value;
  1601. }
  1602. Declaration.prototype.type = 'Declaration';
  1603. var debugInfo = function (context, ctx, lineSeparator) {
  1604. var result = '';
  1605. if (context.dumpLineNumbers && !context.compress) {
  1606. switch (context.dumpLineNumbers) {
  1607. case 'comments':
  1608. result = debugInfo.asComment(ctx);
  1609. break;
  1610. case 'mediaquery':
  1611. result = debugInfo.asMediaQuery(ctx);
  1612. break;
  1613. case 'all':
  1614. result = debugInfo.asComment(ctx) + (lineSeparator || '') + debugInfo.asMediaQuery(ctx);
  1615. break;
  1616. }
  1617. }
  1618. return result;
  1619. };
  1620. debugInfo.asComment = function (ctx) { return "/* line " + ctx.debugInfo.lineNumber + ", " + ctx.debugInfo.fileName + " */\n"; };
  1621. debugInfo.asMediaQuery = function (ctx) {
  1622. var filenameWithProtocol = ctx.debugInfo.fileName;
  1623. if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
  1624. filenameWithProtocol = "file://" + filenameWithProtocol;
  1625. }
  1626. return "@media -sass-debug-info{filename{font-family:" + filenameWithProtocol.replace(/([.:\/\\])/g, function (a) {
  1627. if (a == '\\') {
  1628. a = '\/';
  1629. }
  1630. return "\\" + a;
  1631. }) + "}line{font-family:\\00003" + ctx.debugInfo.lineNumber + "}}\n";
  1632. };
  1633. var Comment = /** @class */ (function (_super) {
  1634. tslib.__extends(Comment, _super);
  1635. function Comment(value, isLineComment, index, currentFileInfo) {
  1636. var _this = _super.call(this) || this;
  1637. _this.value = value;
  1638. _this.isLineComment = isLineComment;
  1639. _this._index = index;
  1640. _this._fileInfo = currentFileInfo;
  1641. _this.allowRoot = true;
  1642. return _this;
  1643. }
  1644. Comment.prototype.genCSS = function (context, output) {
  1645. if (this.debugInfo) {
  1646. output.add(debugInfo(context, this), this.fileInfo(), this.getIndex());
  1647. }
  1648. output.add(this.value);
  1649. };
  1650. Comment.prototype.isSilent = function (context) {
  1651. var isCompressed = context.compress && this.value[2] !== '!';
  1652. return this.isLineComment || isCompressed;
  1653. };
  1654. return Comment;
  1655. }(Node));
  1656. Comment.prototype.type = 'Comment';
  1657. var contexts = {};
  1658. var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
  1659. if (!original) {
  1660. return;
  1661. }
  1662. for (var i_1 = 0; i_1 < propertiesToCopy.length; i_1++) {
  1663. if (original.hasOwnProperty(propertiesToCopy[i_1])) {
  1664. destination[propertiesToCopy[i_1]] = original[propertiesToCopy[i_1]];
  1665. }
  1666. }
  1667. };
  1668. /*
  1669. parse is used whilst parsing
  1670. */
  1671. var parseCopyProperties = [
  1672. // options
  1673. 'paths',
  1674. 'rewriteUrls',
  1675. 'rootpath',
  1676. 'strictImports',
  1677. 'insecure',
  1678. 'dumpLineNumbers',
  1679. 'compress',
  1680. 'syncImport',
  1681. 'chunkInput',
  1682. 'mime',
  1683. 'useFileCache',
  1684. // context
  1685. 'processImports',
  1686. // Used by the import manager to stop multiple import visitors being created.
  1687. 'pluginManager' // Used as the plugin manager for the session
  1688. ];
  1689. contexts.Parse = function (options) {
  1690. copyFromOriginal(options, this, parseCopyProperties);
  1691. if (typeof this.paths === 'string') {
  1692. this.paths = [this.paths];
  1693. }
  1694. };
  1695. var evalCopyProperties = [
  1696. 'paths',
  1697. 'compress',
  1698. 'math',
  1699. 'strictUnits',
  1700. 'sourceMap',
  1701. 'importMultiple',
  1702. 'urlArgs',
  1703. 'javascriptEnabled',
  1704. 'pluginManager',
  1705. 'importantScope',
  1706. 'rewriteUrls' // option - whether to adjust URL's to be relative
  1707. ];
  1708. function isPathRelative(path) {
  1709. return !/^(?:[a-z-]+:|\/|#)/i.test(path);
  1710. }
  1711. function isPathLocalRelative(path) {
  1712. return path.charAt(0) === '.';
  1713. }
  1714. contexts.Eval = /** @class */ (function () {
  1715. function Eval(options, frames) {
  1716. copyFromOriginal(options, this, evalCopyProperties);
  1717. if (typeof this.paths === 'string') {
  1718. this.paths = [this.paths];
  1719. }
  1720. this.frames = frames || [];
  1721. this.importantScope = this.importantScope || [];
  1722. this.inCalc = false;
  1723. this.mathOn = true;
  1724. }
  1725. Eval.prototype.enterCalc = function () {
  1726. if (!this.calcStack) {
  1727. this.calcStack = [];
  1728. }
  1729. this.calcStack.push(true);
  1730. this.inCalc = true;
  1731. };
  1732. Eval.prototype.exitCalc = function () {
  1733. this.calcStack.pop();
  1734. if (!this.calcStack) {
  1735. this.inCalc = false;
  1736. }
  1737. };
  1738. Eval.prototype.inParenthesis = function () {
  1739. if (!this.parensStack) {
  1740. this.parensStack = [];
  1741. }
  1742. this.parensStack.push(true);
  1743. };
  1744. Eval.prototype.outOfParenthesis = function () {
  1745. this.parensStack.pop();
  1746. };
  1747. Eval.prototype.isMathOn = function (op) {
  1748. if (!this.mathOn) {
  1749. return false;
  1750. }
  1751. if (op === '/' && this.math !== Math$1.ALWAYS && (!this.parensStack || !this.parensStack.length)) {
  1752. return false;
  1753. }
  1754. if (this.math > Math$1.PARENS_DIVISION) {
  1755. return this.parensStack && this.parensStack.length;
  1756. }
  1757. return true;
  1758. };
  1759. Eval.prototype.pathRequiresRewrite = function (path) {
  1760. var isRelative = this.rewriteUrls === RewriteUrls.LOCAL ? isPathLocalRelative : isPathRelative;
  1761. return isRelative(path);
  1762. };
  1763. Eval.prototype.rewritePath = function (path, rootpath) {
  1764. var newPath;
  1765. rootpath = rootpath || '';
  1766. newPath = this.normalizePath(rootpath + path);
  1767. // If a path was explicit relative and the rootpath was not an absolute path
  1768. // we must ensure that the new path is also explicit relative.
  1769. if (isPathLocalRelative(path) &&
  1770. isPathRelative(rootpath) &&
  1771. isPathLocalRelative(newPath) === false) {
  1772. newPath = "./" + newPath;
  1773. }
  1774. return newPath;
  1775. };
  1776. Eval.prototype.normalizePath = function (path) {
  1777. var segments = path.split('/').reverse();
  1778. var segment;
  1779. path = [];
  1780. while (segments.length !== 0) {
  1781. segment = segments.pop();
  1782. switch (segment) {
  1783. case '.':
  1784. break;
  1785. case '..':
  1786. if ((path.length === 0) || (path[path.length - 1] === '..')) {
  1787. path.push(segment);
  1788. }
  1789. else {
  1790. path.pop();
  1791. }
  1792. break;
  1793. default:
  1794. path.push(segment);
  1795. break;
  1796. }
  1797. }
  1798. return path.join('/');
  1799. };
  1800. return Eval;
  1801. }());
  1802. function makeRegistry(base) {
  1803. return {
  1804. _data: {},
  1805. add: function (name, func) {
  1806. // precautionary case conversion, as later querying of
  1807. // the registry by function-caller uses lower case as well.
  1808. name = name.toLowerCase();
  1809. if (this._data.hasOwnProperty(name)) ;
  1810. this._data[name] = func;
  1811. },
  1812. addMultiple: function (functions) {
  1813. var _this = this;
  1814. Object.keys(functions).forEach(function (name) {
  1815. _this.add(name, functions[name]);
  1816. });
  1817. },
  1818. get: function (name) {
  1819. return this._data[name] || (base && base.get(name));
  1820. },
  1821. getLocalFunctions: function () {
  1822. return this._data;
  1823. },
  1824. inherit: function () {
  1825. return makeRegistry(this);
  1826. },
  1827. create: function (base) {
  1828. return makeRegistry(base);
  1829. }
  1830. };
  1831. }
  1832. var functionRegistry = makeRegistry(null);
  1833. var defaultFunc = {
  1834. eval: function () {
  1835. var v = this.value_;
  1836. var e = this.error_;
  1837. if (e) {
  1838. throw e;
  1839. }
  1840. if (v != null) {
  1841. return v ? Keyword.True : Keyword.False;
  1842. }
  1843. },
  1844. value: function (v) {
  1845. this.value_ = v;
  1846. },
  1847. error: function (e) {
  1848. this.error_ = e;
  1849. },
  1850. reset: function () {
  1851. this.value_ = this.error_ = null;
  1852. }
  1853. };
  1854. var Ruleset = /** @class */ (function (_super) {
  1855. tslib.__extends(Ruleset, _super);
  1856. function Ruleset(selectors, rules, strictImports, visibilityInfo) {
  1857. var _this = _super.call(this) || this;
  1858. _this.selectors = selectors;
  1859. _this.rules = rules;
  1860. _this._lookups = {};
  1861. _this._variables = null;
  1862. _this._properties = null;
  1863. _this.strictImports = strictImports;
  1864. _this.copyVisibilityInfo(visibilityInfo);
  1865. _this.allowRoot = true;
  1866. _this.setParent(_this.selectors, _this);
  1867. _this.setParent(_this.rules, _this);
  1868. return _this;
  1869. }
  1870. Ruleset.prototype.isRulesetLike = function () {
  1871. return true;
  1872. };
  1873. Ruleset.prototype.accept = function (visitor) {
  1874. if (this.paths) {
  1875. this.paths = visitor.visitArray(this.paths, true);
  1876. }
  1877. else if (this.selectors) {
  1878. this.selectors = visitor.visitArray(this.selectors);
  1879. }
  1880. if (this.rules && this.rules.length) {
  1881. this.rules = visitor.visitArray(this.rules);
  1882. }
  1883. };
  1884. Ruleset.prototype.eval = function (context) {
  1885. var selectors;
  1886. var selCnt;
  1887. var selector;
  1888. var i;
  1889. var hasVariable;
  1890. var hasOnePassingSelector = false;
  1891. if (this.selectors && (selCnt = this.selectors.length)) {
  1892. selectors = new Array(selCnt);
  1893. defaultFunc.error({
  1894. type: 'Syntax',
  1895. message: 'it is currently only allowed in parametric mixin guards,'
  1896. });
  1897. for (i = 0; i < selCnt; i++) {
  1898. selector = this.selectors[i].eval(context);
  1899. for (var j = 0; j < selector.elements.length; j++) {
  1900. if (selector.elements[j].isVariable) {
  1901. hasVariable = true;
  1902. break;
  1903. }
  1904. }
  1905. selectors[i] = selector;
  1906. if (selector.evaldCondition) {
  1907. hasOnePassingSelector = true;
  1908. }
  1909. }
  1910. if (hasVariable) {
  1911. var toParseSelectors = new Array(selCnt);
  1912. for (i = 0; i < selCnt; i++) {
  1913. selector = selectors[i];
  1914. toParseSelectors[i] = selector.toCSS(context);
  1915. }
  1916. this.parse.parseNode(toParseSelectors.join(','), ["selectors"], selectors[0].getIndex(), selectors[0].fileInfo(), function (err, result) {
  1917. if (result) {
  1918. selectors = flattenArray(result);
  1919. }
  1920. });
  1921. }
  1922. defaultFunc.reset();
  1923. }
  1924. else {
  1925. hasOnePassingSelector = true;
  1926. }
  1927. var rules = this.rules ? copyArray(this.rules) : null;
  1928. var ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo());
  1929. var rule;
  1930. var subRule;
  1931. ruleset.originalRuleset = this;
  1932. ruleset.root = this.root;
  1933. ruleset.firstRoot = this.firstRoot;
  1934. ruleset.allowImports = this.allowImports;
  1935. if (this.debugInfo) {
  1936. ruleset.debugInfo = this.debugInfo;
  1937. }
  1938. if (!hasOnePassingSelector) {
  1939. rules.length = 0;
  1940. }
  1941. // inherit a function registry from the frames stack when possible;
  1942. // otherwise from the global registry
  1943. ruleset.functionRegistry = (function (frames) {
  1944. var i = 0;
  1945. var n = frames.length;
  1946. var found;
  1947. for (; i !== n; ++i) {
  1948. found = frames[i].functionRegistry;
  1949. if (found) {
  1950. return found;
  1951. }
  1952. }
  1953. return functionRegistry;
  1954. })(context.frames).inherit();
  1955. // push the current ruleset to the frames stack
  1956. var ctxFrames = context.frames;
  1957. ctxFrames.unshift(ruleset);
  1958. // currrent selectors
  1959. var ctxSelectors = context.selectors;
  1960. if (!ctxSelectors) {
  1961. context.selectors = ctxSelectors = [];
  1962. }
  1963. ctxSelectors.unshift(this.selectors);
  1964. // Evaluate imports
  1965. if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
  1966. ruleset.evalImports(context);
  1967. }
  1968. // Store the frames around mixin definitions,
  1969. // so they can be evaluated like closures when the time comes.
  1970. var rsRules = ruleset.rules;
  1971. for (i = 0; (rule = rsRules[i]); i++) {
  1972. if (rule.evalFirst) {
  1973. rsRules[i] = rule.eval(context);
  1974. }
  1975. }
  1976. var mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0;
  1977. // Evaluate mixin calls.
  1978. for (i = 0; (rule = rsRules[i]); i++) {
  1979. if (rule.type === 'MixinCall') {
  1980. /* jshint loopfunc:true */
  1981. rules = rule.eval(context).filter(function (r) {
  1982. if ((r instanceof Declaration) && r.variable) {
  1983. // do not pollute the scope if the variable is
  1984. // already there. consider returning false here
  1985. // but we need a way to "return" variable from mixins
  1986. return !(ruleset.variable(r.name));
  1987. }
  1988. return true;
  1989. });
  1990. rsRules.splice.apply(rsRules, [i, 1].concat(rules));
  1991. i += rules.length - 1;
  1992. ruleset.resetCache();
  1993. }
  1994. else if (rule.type === 'VariableCall') {
  1995. /* jshint loopfunc:true */
  1996. rules = rule.eval(context).rules.filter(function (r) {
  1997. if ((r instanceof Declaration) && r.variable) {
  1998. // do not pollute the scope at all
  1999. return false;
  2000. }
  2001. return true;
  2002. });
  2003. rsRules.splice.apply(rsRules, [i, 1].concat(rules));
  2004. i += rules.length - 1;
  2005. ruleset.resetCache();
  2006. }
  2007. }
  2008. // Evaluate everything else
  2009. for (i = 0; (rule = rsRules[i]); i++) {
  2010. if (!rule.evalFirst) {
  2011. rsRules[i] = rule = rule.eval ? rule.eval(context) : rule;
  2012. }
  2013. }
  2014. // Evaluate everything else
  2015. for (i = 0; (rule = rsRules[i]); i++) {
  2016. // for rulesets, check if it is a css guard and can be removed
  2017. if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) {
  2018. // check if it can be folded in (e.g. & where)
  2019. if (rule.selectors[0] && rule.selectors[0].isJustParentSelector()) {
  2020. rsRules.splice(i--, 1);
  2021. for (var j = 0; (subRule = rule.rules[j]); j++) {
  2022. if (subRule instanceof Node) {
  2023. subRule.copyVisibilityInfo(rule.visibilityInfo());
  2024. if (!(subRule instanceof Declaration) || !subRule.variable) {
  2025. rsRules.splice(++i, 0, subRule);
  2026. }
  2027. }
  2028. }
  2029. }
  2030. }
  2031. }
  2032. // Pop the stack
  2033. ctxFrames.shift();
  2034. ctxSelectors.shift();
  2035. if (context.mediaBlocks) {
  2036. for (i = mediaBlockCount; i < context.mediaBlocks.length; i++) {
  2037. context.mediaBlocks[i].bubbleSelectors(selectors);
  2038. }
  2039. }
  2040. return ruleset;
  2041. };
  2042. Ruleset.prototype.evalImports = function (context) {
  2043. var rules = this.rules;
  2044. var i;
  2045. var importRules;
  2046. if (!rules) {
  2047. return;
  2048. }
  2049. for (i = 0; i < rules.length; i++) {
  2050. if (rules[i].type === 'Import') {
  2051. importRules = rules[i].eval(context);
  2052. if (importRules && (importRules.length || importRules.length === 0)) {
  2053. rules.splice.apply(rules, [i, 1].concat(importRules));
  2054. i += importRules.length - 1;
  2055. }
  2056. else {
  2057. rules.splice(i, 1, importRules);
  2058. }
  2059. this.resetCache();
  2060. }
  2061. }
  2062. };
  2063. Ruleset.prototype.makeImportant = function () {
  2064. var result = new Ruleset(this.selectors, this.rules.map(function (r) {
  2065. if (r.makeImportant) {
  2066. return r.makeImportant();
  2067. }
  2068. else {
  2069. return r;
  2070. }
  2071. }), this.strictImports, this.visibilityInfo());
  2072. return result;
  2073. };
  2074. Ruleset.prototype.matchArgs = function (args) {
  2075. return !args || args.length === 0;
  2076. };
  2077. // lets you call a css selector with a guard
  2078. Ruleset.prototype.matchCondition = function (args, context) {
  2079. var lastSelector = this.selectors[this.selectors.length - 1];
  2080. if (!lastSelector.evaldCondition) {
  2081. return false;
  2082. }
  2083. if (lastSelector.condition &&
  2084. !lastSelector.condition.eval(new contexts.Eval(context, context.frames))) {
  2085. return false;
  2086. }
  2087. return true;
  2088. };
  2089. Ruleset.prototype.resetCache = function () {
  2090. this._rulesets = null;
  2091. this._variables = null;
  2092. this._properties = null;
  2093. this._lookups = {};
  2094. };
  2095. Ruleset.prototype.variables = function () {
  2096. if (!this._variables) {
  2097. this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
  2098. if (r instanceof Declaration && r.variable === true) {
  2099. hash[r.name] = r;
  2100. }
  2101. // when evaluating variables in an import statement, imports have not been eval'd
  2102. // so we need to go inside import statements.
  2103. // guard against root being a string (in the case of inlined less)
  2104. if (r.type === 'Import' && r.root && r.root.variables) {
  2105. var vars = r.root.variables();
  2106. for (var name_1 in vars) {
  2107. if (vars.hasOwnProperty(name_1)) {
  2108. hash[name_1] = r.root.variable(name_1);
  2109. }
  2110. }
  2111. }
  2112. return hash;
  2113. }, {});
  2114. }
  2115. return this._variables;
  2116. };
  2117. Ruleset.prototype.properties = function () {
  2118. if (!this._properties) {
  2119. this._properties = !this.rules ? {} : this.rules.reduce(function (hash, r) {
  2120. if (r instanceof Declaration && r.variable !== true) {
  2121. var name_2 = (r.name.length === 1) && (r.name[0] instanceof Keyword) ?
  2122. r.name[0].value : r.name;
  2123. // Properties don't overwrite as they can merge
  2124. if (!hash["$" + name_2]) {
  2125. hash["$" + name_2] = [r];
  2126. }
  2127. else {
  2128. hash["$" + name_2].push(r);
  2129. }
  2130. }
  2131. return hash;
  2132. }, {});
  2133. }
  2134. return this._properties;
  2135. };
  2136. Ruleset.prototype.variable = function (name) {
  2137. var decl = this.variables()[name];
  2138. if (decl) {
  2139. return this.parseValue(decl);
  2140. }
  2141. };
  2142. Ruleset.prototype.property = function (name) {
  2143. var decl = this.properties()[name];
  2144. if (decl) {
  2145. return this.parseValue(decl);
  2146. }
  2147. };
  2148. Ruleset.prototype.lastDeclaration = function () {
  2149. for (var i_1 = this.rules.length; i_1 > 0; i_1--) {
  2150. var decl = this.rules[i_1 - 1];
  2151. if (decl instanceof Declaration) {
  2152. return this.parseValue(decl);
  2153. }
  2154. }
  2155. };
  2156. Ruleset.prototype.parseValue = function (toParse) {
  2157. var self = this;
  2158. function transformDeclaration(decl) {
  2159. if (decl.value instanceof Anonymous && !decl.parsed) {
  2160. if (typeof decl.value.value === 'string') {
  2161. this.parse.parseNode(decl.value.value, ['value', 'important'], decl.value.getIndex(), decl.fileInfo(), function (err, result) {
  2162. if (err) {
  2163. decl.parsed = true;
  2164. }
  2165. if (result) {
  2166. decl.value = result[0];
  2167. decl.important = result[1] || '';
  2168. decl.parsed = true;
  2169. }
  2170. });
  2171. }
  2172. else {
  2173. decl.parsed = true;
  2174. }
  2175. return decl;
  2176. }
  2177. else {
  2178. return decl;
  2179. }
  2180. }
  2181. if (!Array.isArray(toParse)) {
  2182. return transformDeclaration.call(self, toParse);
  2183. }
  2184. else {
  2185. var nodes_1 = [];
  2186. toParse.forEach(function (n) {
  2187. nodes_1.push(transformDeclaration.call(self, n));
  2188. });
  2189. return nodes_1;
  2190. }
  2191. };
  2192. Ruleset.prototype.rulesets = function () {
  2193. if (!this.rules) {
  2194. return [];
  2195. }
  2196. var filtRules = [];
  2197. var rules = this.rules;
  2198. var i;
  2199. var rule;
  2200. for (i = 0; (rule = rules[i]); i++) {
  2201. if (rule.isRuleset) {
  2202. filtRules.push(rule);
  2203. }
  2204. }
  2205. return filtRules;
  2206. };
  2207. Ruleset.prototype.prependRule = function (rule) {
  2208. var rules = this.rules;
  2209. if (rules) {
  2210. rules.unshift(rule);
  2211. }
  2212. else {
  2213. this.rules = [rule];
  2214. }
  2215. this.setParent(rule, this);
  2216. };
  2217. Ruleset.prototype.find = function (selector, self, filter) {
  2218. if (self === void 0) { self = this; }
  2219. var rules = [];
  2220. var match;
  2221. var foundMixins;
  2222. var key = selector.toCSS();
  2223. if (key in this._lookups) {
  2224. return this._lookups[key];
  2225. }
  2226. this.rulesets().forEach(function (rule) {
  2227. if (rule !== self) {
  2228. for (var j = 0; j < rule.selectors.length; j++) {
  2229. match = selector.match(rule.selectors[j]);
  2230. if (match) {
  2231. if (selector.elements.length > match) {
  2232. if (!filter || filter(rule)) {
  2233. foundMixins = rule.find(new Selector(selector.elements.slice(match)), self, filter);
  2234. for (var i_2 = 0; i_2 < foundMixins.length; ++i_2) {
  2235. foundMixins[i_2].path.push(rule);
  2236. }
  2237. Array.prototype.push.apply(rules, foundMixins);
  2238. }
  2239. }
  2240. else {
  2241. rules.push({ rule: rule, path: [] });
  2242. }
  2243. break;
  2244. }
  2245. }
  2246. }
  2247. });
  2248. this._lookups[key] = rules;
  2249. return rules;
  2250. };
  2251. Ruleset.prototype.genCSS = function (context, output) {
  2252. var i;
  2253. var j;
  2254. var charsetRuleNodes = [];
  2255. var ruleNodes = [];
  2256. var // Line number debugging
  2257. debugInfo$1;
  2258. var rule;
  2259. var path;
  2260. context.tabLevel = (context.tabLevel || 0);
  2261. if (!this.root) {
  2262. context.tabLevel++;
  2263. }
  2264. var tabRuleStr = context.compress ? '' : Array(context.tabLevel + 1).join(' ');
  2265. var tabSetStr = context.compress ? '' : Array(context.tabLevel).join(' ');
  2266. var sep;
  2267. var charsetNodeIndex = 0;
  2268. var importNodeIndex = 0;
  2269. for (i = 0; (rule = this.rules[i]); i++) {
  2270. if (rule instanceof Comment) {
  2271. if (importNodeIndex === i) {
  2272. importNodeIndex++;
  2273. }
  2274. ruleNodes.push(rule);
  2275. }
  2276. else if (rule.isCharset && rule.isCharset()) {
  2277. ruleNodes.splice(charsetNodeIndex, 0, rule);
  2278. charsetNodeIndex++;
  2279. importNodeIndex++;
  2280. }
  2281. else if (rule.type === 'Import') {
  2282. ruleNodes.splice(importNodeIndex, 0, rule);
  2283. importNodeIndex++;
  2284. }
  2285. else {
  2286. ruleNodes.push(rule);
  2287. }
  2288. }
  2289. ruleNodes = charsetRuleNodes.concat(ruleNodes);
  2290. // If this is the root node, we don't render
  2291. // a selector, or {}.
  2292. if (!this.root) {
  2293. debugInfo$1 = debugInfo(context, this, tabSetStr);
  2294. if (debugInfo$1) {
  2295. output.add(debugInfo$1);
  2296. output.add(tabSetStr);
  2297. }
  2298. var paths = this.paths;
  2299. var pathCnt = paths.length;
  2300. var pathSubCnt = void 0;
  2301. sep = context.compress ? ',' : (",\n" + tabSetStr);
  2302. for (i = 0; i < pathCnt; i++) {
  2303. path = paths[i];
  2304. if (!(pathSubCnt = path.length)) {
  2305. continue;
  2306. }
  2307. if (i > 0) {
  2308. output.add(sep);
  2309. }
  2310. context.firstSelector = true;
  2311. path[0].genCSS(context, output);
  2312. context.firstSelector = false;
  2313. for (j = 1; j < pathSubCnt; j++) {
  2314. path[j].genCSS(context, output);
  2315. }
  2316. }
  2317. output.add((context.compress ? '{' : ' {\n') + tabRuleStr);
  2318. }
  2319. // Compile rules and rulesets
  2320. for (i = 0; (rule = ruleNodes[i]); i++) {
  2321. if (i + 1 === ruleNodes.length) {
  2322. context.lastRule = true;
  2323. }
  2324. var currentLastRule = context.lastRule;
  2325. if (rule.isRulesetLike(rule)) {
  2326. context.lastRule = false;
  2327. }
  2328. if (rule.genCSS) {
  2329. rule.genCSS(context, output);
  2330. }
  2331. else if (rule.value) {
  2332. output.add(rule.value.toString());
  2333. }
  2334. context.lastRule = currentLastRule;
  2335. if (!context.lastRule && rule.isVisible()) {
  2336. output.add(context.compress ? '' : ("\n" + tabRuleStr));
  2337. }
  2338. else {
  2339. context.lastRule = false;
  2340. }
  2341. }
  2342. if (!this.root) {
  2343. output.add((context.compress ? '}' : "\n" + tabSetStr + "}"));
  2344. context.tabLevel--;
  2345. }
  2346. if (!output.isEmpty() && !context.compress && this.firstRoot) {
  2347. output.add('\n');
  2348. }
  2349. };
  2350. Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
  2351. for (var s = 0; s < selectors.length; s++) {
  2352. this.joinSelector(paths, context, selectors[s]);
  2353. }
  2354. };
  2355. Ruleset.prototype.joinSelector = function (paths, context, selector) {
  2356. function createParenthesis(elementsToPak, originalElement) {
  2357. var replacementParen;
  2358. var j;
  2359. if (elementsToPak.length === 0) {
  2360. replacementParen = new Paren(elementsToPak[0]);
  2361. }
  2362. else {
  2363. var insideParent = new Array(elementsToPak.length);
  2364. for (j = 0; j < elementsToPak.length; j++) {
  2365. insideParent[j] = new Element(null, elementsToPak[j], originalElement.isVariable, originalElement._index, originalElement._fileInfo);
  2366. }
  2367. replacementParen = new Paren(new Selector(insideParent));
  2368. }
  2369. return replacementParen;
  2370. }
  2371. function createSelector(containedElement, originalElement) {
  2372. var element;
  2373. var selector;
  2374. element = new Element(null, containedElement, originalElement.isVariable, originalElement._index, originalElement._fileInfo);
  2375. selector = new Selector([element]);
  2376. return selector;
  2377. }
  2378. // joins selector path from `beginningPath` with selector path in `addPath`
  2379. // `replacedElement` contains element that is being replaced by `addPath`
  2380. // returns concatenated path
  2381. function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
  2382. var newSelectorPath;
  2383. var lastSelector;
  2384. var newJoinedSelector;
  2385. // our new selector path
  2386. newSelectorPath = [];
  2387. // construct the joined selector - if & is the first thing this will be empty,
  2388. // if not newJoinedSelector will be the last set of elements in the selector
  2389. if (beginningPath.length > 0) {
  2390. newSelectorPath = copyArray(beginningPath);
  2391. lastSelector = newSelectorPath.pop();
  2392. newJoinedSelector = originalSelector.createDerived(copyArray(lastSelector.elements));
  2393. }
  2394. else {
  2395. newJoinedSelector = originalSelector.createDerived([]);
  2396. }
  2397. if (addPath.length > 0) {
  2398. // /deep/ is a CSS4 selector - (removed, so should deprecate)
  2399. // that is valid without anything in front of it
  2400. // so if the & does not have a combinator that is "" or " " then
  2401. // and there is a combinator on the parent, then grab that.
  2402. // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
  2403. var combinator = replacedElement.combinator;
  2404. var parentEl = addPath[0].elements[0];
  2405. if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
  2406. combinator = parentEl.combinator;
  2407. }
  2408. // join the elements so far with the first part of the parent
  2409. newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.isVariable, replacedElement._index, replacedElement._fileInfo));
  2410. newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
  2411. }
  2412. // now add the joined selector - but only if it is not empty
  2413. if (newJoinedSelector.elements.length !== 0) {
  2414. newSelectorPath.push(newJoinedSelector);
  2415. }
  2416. // put together the parent selectors after the join (e.g. the rest of the parent)
  2417. if (addPath.length > 1) {
  2418. var restOfPath = addPath.slice(1);
  2419. restOfPath = restOfPath.map(function (selector) { return selector.createDerived(selector.elements, []); });
  2420. newSelectorPath = newSelectorPath.concat(restOfPath);
  2421. }
  2422. return newSelectorPath;
  2423. }
  2424. // joins selector path from `beginningPath` with every selector path in `addPaths` array
  2425. // `replacedElement` contains element that is being replaced by `addPath`
  2426. // returns array with all concatenated paths
  2427. function addAllReplacementsIntoPath(beginningPath, addPaths, replacedElement, originalSelector, result) {
  2428. var j;
  2429. for (j = 0; j < beginningPath.length; j++) {
  2430. var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
  2431. result.push(newSelectorPath);
  2432. }
  2433. return result;
  2434. }
  2435. function mergeElementsOnToSelectors(elements, selectors) {
  2436. var i;
  2437. var sel;
  2438. if (elements.length === 0) {
  2439. return;
  2440. }
  2441. if (selectors.length === 0) {
  2442. selectors.push([new Selector(elements)]);
  2443. return;
  2444. }
  2445. for (i = 0; (sel = selectors[i]); i++) {
  2446. // if the previous thing in sel is a parent this needs to join on to it
  2447. if (sel.length > 0) {
  2448. sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
  2449. }
  2450. else {
  2451. sel.push(new Selector(elements));
  2452. }
  2453. }
  2454. }
  2455. // replace all parent selectors inside `inSelector` by content of `context` array
  2456. // resulting selectors are returned inside `paths` array
  2457. // returns true if `inSelector` contained at least one parent selector
  2458. function replaceParentSelector(paths, context, inSelector) {
  2459. // The paths are [[Selector]]
  2460. // The first list is a list of comma separated selectors
  2461. // The inner list is a list of inheritance separated selectors
  2462. // e.g.
  2463. // .a, .b {
  2464. // .c {
  2465. // }
  2466. // }
  2467. // == [[.a] [.c]] [[.b] [.c]]
  2468. //
  2469. var i;
  2470. var j;
  2471. var k;
  2472. var currentElements;
  2473. var newSelectors;
  2474. var selectorsMultiplied;
  2475. var sel;
  2476. var el;
  2477. var hadParentSelector = false;
  2478. var length;
  2479. var lastSelector;
  2480. function findNestedSelector(element) {
  2481. var maybeSelector;
  2482. if (!(element.value instanceof Paren)) {
  2483. return null;
  2484. }
  2485. maybeSelector = element.value.value;
  2486. if (!(maybeSelector instanceof Selector)) {
  2487. return null;
  2488. }
  2489. return maybeSelector;
  2490. }
  2491. // the elements from the current selector so far
  2492. currentElements = [];
  2493. // the current list of new selectors to add to the path.
  2494. // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
  2495. // by the parents
  2496. newSelectors = [
  2497. []
  2498. ];
  2499. for (i = 0; (el = inSelector.elements[i]); i++) {
  2500. // non parent reference elements just get added
  2501. if (el.value !== '&') {
  2502. var nestedSelector = findNestedSelector(el);
  2503. if (nestedSelector != null) {
  2504. // merge the current list of non parent selector elements
  2505. // on to the current list of selectors to add
  2506. mergeElementsOnToSelectors(currentElements, newSelectors);
  2507. var nestedPaths = [];
  2508. var replaced = void 0;
  2509. var replacedNewSelectors = [];
  2510. replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
  2511. hadParentSelector = hadParentSelector || replaced;
  2512. // the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
  2513. for (k = 0; k < nestedPaths.length; k++) {
  2514. var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
  2515. addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
  2516. }
  2517. newSelectors = replacedNewSelectors;
  2518. currentElements = [];
  2519. }
  2520. else {
  2521. currentElements.push(el);
  2522. }
  2523. }
  2524. else {
  2525. hadParentSelector = true;
  2526. // the new list of selectors to add
  2527. selectorsMultiplied = [];
  2528. // merge the current list of non parent selector elements
  2529. // on to the current list of selectors to add
  2530. mergeElementsOnToSelectors(currentElements, newSelectors);
  2531. // loop through our current selectors
  2532. for (j = 0; j < newSelectors.length; j++) {
  2533. sel = newSelectors[j];
  2534. // if we don't have any parent paths, the & might be in a mixin so that it can be used
  2535. // whether there are parents or not
  2536. if (context.length === 0) {
  2537. // the combinator used on el should now be applied to the next element instead so that
  2538. // it is not lost
  2539. if (sel.length > 0) {
  2540. sel[0].elements.push(new Element(el.combinator, '', el.isVariable, el._index, el._fileInfo));
  2541. }
  2542. selectorsMultiplied.push(sel);
  2543. }
  2544. else {
  2545. // and the parent selectors
  2546. for (k = 0; k < context.length; k++) {
  2547. // We need to put the current selectors
  2548. // then join the last selector's elements on to the parents selectors
  2549. var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
  2550. // add that to our new set of selectors
  2551. selectorsMultiplied.push(newSelectorPath);
  2552. }
  2553. }
  2554. }
  2555. // our new selectors has been multiplied, so reset the state
  2556. newSelectors = selectorsMultiplied;
  2557. currentElements = [];
  2558. }
  2559. }
  2560. // if we have any elements left over (e.g. .a& .b == .b)
  2561. // add them on to all the current selectors
  2562. mergeElementsOnToSelectors(currentElements, newSelectors);
  2563. for (i = 0; i < newSelectors.length; i++) {
  2564. length = newSelectors[i].length;
  2565. if (length > 0) {
  2566. paths.push(newSelectors[i]);
  2567. lastSelector = newSelectors[i][length - 1];
  2568. newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
  2569. }
  2570. }
  2571. return hadParentSelector;
  2572. }
  2573. function deriveSelector(visibilityInfo, deriveFrom) {
  2574. var newSelector = deriveFrom.createDerived(deriveFrom.elements, deriveFrom.extendList, deriveFrom.evaldCondition);
  2575. newSelector.copyVisibilityInfo(visibilityInfo);
  2576. return newSelector;
  2577. }
  2578. // joinSelector code follows
  2579. var i;
  2580. var newPaths;
  2581. var hadParentSelector;
  2582. newPaths = [];
  2583. hadParentSelector = replaceParentSelector(newPaths, context, selector);
  2584. if (!hadParentSelector) {
  2585. if (context.length > 0) {
  2586. newPaths = [];
  2587. for (i = 0; i < context.length; i++) {
  2588. var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo()));
  2589. concatenated.push(selector);
  2590. newPaths.push(concatenated);
  2591. }
  2592. }
  2593. else {
  2594. newPaths = [[selector]];
  2595. }
  2596. }
  2597. for (i = 0; i < newPaths.length; i++) {
  2598. paths.push(newPaths[i]);
  2599. }
  2600. };
  2601. return Ruleset;
  2602. }(Node));
  2603. Ruleset.prototype.type = 'Ruleset';
  2604. Ruleset.prototype.isRuleset = true;
  2605. var AtRule = /** @class */ (function (_super) {
  2606. tslib.__extends(AtRule, _super);
  2607. function AtRule(name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) {
  2608. var _this = _super.call(this) || this;
  2609. var i;
  2610. _this.name = name;
  2611. _this.value = (value instanceof Node) ? value : (value ? new Anonymous(value) : value);
  2612. if (rules) {
  2613. if (Array.isArray(rules)) {
  2614. _this.rules = rules;
  2615. }
  2616. else {
  2617. _this.rules = [rules];
  2618. _this.rules[0].selectors = (new Selector([], null, null, index, currentFileInfo)).createEmptySelectors();
  2619. }
  2620. for (i = 0; i < _this.rules.length; i++) {
  2621. _this.rules[i].allowImports = true;
  2622. }
  2623. _this.setParent(_this.rules, _this);
  2624. }
  2625. _this._index = index;
  2626. _this._fileInfo = currentFileInfo;
  2627. _this.debugInfo = debugInfo;
  2628. _this.isRooted = isRooted || false;
  2629. _this.copyVisibilityInfo(visibilityInfo);
  2630. _this.allowRoot = true;
  2631. return _this;
  2632. }
  2633. AtRule.prototype.accept = function (visitor) {
  2634. var value = this.value;
  2635. var rules = this.rules;
  2636. if (rules) {
  2637. this.rules = visitor.visitArray(rules);
  2638. }
  2639. if (value) {
  2640. this.value = visitor.visit(value);
  2641. }
  2642. };
  2643. AtRule.prototype.isRulesetLike = function () {
  2644. return this.rules || !this.isCharset();
  2645. };
  2646. AtRule.prototype.isCharset = function () {
  2647. return '@charset' === this.name;
  2648. };
  2649. AtRule.prototype.genCSS = function (context, output) {
  2650. var value = this.value;
  2651. var rules = this.rules;
  2652. output.add(this.name, this.fileInfo(), this.getIndex());
  2653. if (value) {
  2654. output.add(' ');
  2655. value.genCSS(context, output);
  2656. }
  2657. if (rules) {
  2658. this.outputRuleset(context, output, rules);
  2659. }
  2660. else {
  2661. output.add(';');
  2662. }
  2663. };
  2664. AtRule.prototype.eval = function (context) {
  2665. var mediaPathBackup;
  2666. var mediaBlocksBackup;
  2667. var value = this.value;
  2668. var rules = this.rules;
  2669. // media stored inside other atrule should not bubble over it
  2670. // backpup media bubbling information
  2671. mediaPathBackup = context.mediaPath;
  2672. mediaBlocksBackup = context.mediaBlocks;
  2673. // deleted media bubbling information
  2674. context.mediaPath = [];
  2675. context.mediaBlocks = [];
  2676. if (value) {
  2677. value = value.eval(context);
  2678. }
  2679. if (rules) {
  2680. // assuming that there is only one rule at this point - that is how parser constructs the rule
  2681. rules = [rules[0].eval(context)];
  2682. rules[0].root = true;
  2683. }
  2684. // restore media bubbling information
  2685. context.mediaPath = mediaPathBackup;
  2686. context.mediaBlocks = mediaBlocksBackup;
  2687. return new AtRule(this.name, value, rules, this.getIndex(), this.fileInfo(), this.debugInfo, this.isRooted, this.visibilityInfo());
  2688. };
  2689. AtRule.prototype.variable = function (name) {
  2690. if (this.rules) {
  2691. // assuming that there is only one rule at this point - that is how parser constructs the rule
  2692. return Ruleset.prototype.variable.call(this.rules[0], name);
  2693. }
  2694. };
  2695. AtRule.prototype.find = function () {
  2696. var args = [];
  2697. for (var _i = 0; _i < arguments.length; _i++) {
  2698. args[_i] = arguments[_i];
  2699. }
  2700. if (this.rules) {
  2701. // assuming that there is only one rule at this point - that is how parser constructs the rule
  2702. return Ruleset.prototype.find.apply(this.rules[0], args);
  2703. }
  2704. };
  2705. AtRule.prototype.rulesets = function () {
  2706. if (this.rules) {
  2707. // assuming that there is only one rule at this point - that is how parser constructs the rule
  2708. return Ruleset.prototype.rulesets.apply(this.rules[0]);
  2709. }
  2710. };
  2711. AtRule.prototype.outputRuleset = function (context, output, rules) {
  2712. var ruleCnt = rules.length;
  2713. var i;
  2714. context.tabLevel = (context.tabLevel | 0) + 1;
  2715. // Compressed
  2716. if (context.compress) {
  2717. output.add('{');
  2718. for (i = 0; i < ruleCnt; i++) {
  2719. rules[i].genCSS(context, output);
  2720. }
  2721. output.add('}');
  2722. context.tabLevel--;
  2723. return;
  2724. }
  2725. // Non-compressed
  2726. var tabSetStr = "\n" + Array(context.tabLevel).join(' ');
  2727. var tabRuleStr = tabSetStr + " ";
  2728. if (!ruleCnt) {
  2729. output.add(" {" + tabSetStr + "}");
  2730. }
  2731. else {
  2732. output.add(" {" + tabRuleStr);
  2733. rules[0].genCSS(context, output);
  2734. for (i = 1; i < ruleCnt; i++) {
  2735. output.add(tabRuleStr);
  2736. rules[i].genCSS(context, output);
  2737. }
  2738. output.add(tabSetStr + "}");
  2739. }
  2740. context.tabLevel--;
  2741. };
  2742. return AtRule;
  2743. }(Node));
  2744. AtRule.prototype.type = 'AtRule';
  2745. var DetachedRuleset = /** @class */ (function (_super) {
  2746. tslib.__extends(DetachedRuleset, _super);
  2747. function DetachedRuleset(ruleset, frames) {
  2748. var _this = _super.call(this) || this;
  2749. _this.ruleset = ruleset;
  2750. _this.frames = frames;
  2751. _this.setParent(_this.ruleset, _this);
  2752. return _this;
  2753. }
  2754. DetachedRuleset.prototype.accept = function (visitor) {
  2755. this.ruleset = visitor.visit(this.ruleset);
  2756. };
  2757. DetachedRuleset.prototype.eval = function (context) {
  2758. var frames = this.frames || copyArray(context.frames);
  2759. return new DetachedRuleset(this.ruleset, frames);
  2760. };
  2761. DetachedRuleset.prototype.callEval = function (context) {
  2762. return this.ruleset.eval(this.frames ? new contexts.Eval(context, this.frames.concat(context.frames)) : context);
  2763. };
  2764. return DetachedRuleset;
  2765. }(Node));
  2766. DetachedRuleset.prototype.type = 'DetachedRuleset';
  2767. DetachedRuleset.prototype.evalFirst = true;
  2768. var Unit = /** @class */ (function (_super) {
  2769. tslib.__extends(Unit, _super);
  2770. function Unit(numerator, denominator, backupUnit) {
  2771. var _this = _super.call(this) || this;
  2772. _this.numerator = numerator ? copyArray(numerator).sort() : [];
  2773. _this.denominator = denominator ? copyArray(denominator).sort() : [];
  2774. if (backupUnit) {
  2775. _this.backupUnit = backupUnit;
  2776. }
  2777. else if (numerator && numerator.length) {
  2778. _this.backupUnit = numerator[0];
  2779. }
  2780. return _this;
  2781. }
  2782. Unit.prototype.clone = function () {
  2783. return new Unit(copyArray(this.numerator), copyArray(this.denominator), this.backupUnit);
  2784. };
  2785. Unit.prototype.genCSS = function (context, output) {
  2786. // Dimension checks the unit is singular and throws an error if in strict math mode.
  2787. var strictUnits = context && context.strictUnits;
  2788. if (this.numerator.length === 1) {
  2789. output.add(this.numerator[0]); // the ideal situation
  2790. }
  2791. else if (!strictUnits && this.backupUnit) {
  2792. output.add(this.backupUnit);
  2793. }
  2794. else if (!strictUnits && this.denominator.length) {
  2795. output.add(this.denominator[0]);
  2796. }
  2797. };
  2798. Unit.prototype.toString = function () {
  2799. var i;
  2800. var returnStr = this.numerator.join('*');
  2801. for (i = 0; i < this.denominator.length; i++) {
  2802. returnStr += "/" + this.denominator[i];
  2803. }
  2804. return returnStr;
  2805. };
  2806. Unit.prototype.compare = function (other) {
  2807. return this.is(other.toString()) ? 0 : undefined;
  2808. };
  2809. Unit.prototype.is = function (unitString) {
  2810. return this.toString().toUpperCase() === unitString.toUpperCase();
  2811. };
  2812. Unit.prototype.isLength = function () {
  2813. return RegExp('^(px|em|ex|ch|rem|in|cm|mm|pc|pt|ex|vw|vh|vmin|vmax)$', 'gi').test(this.toCSS());
  2814. };
  2815. Unit.prototype.isEmpty = function () {
  2816. return this.numerator.length === 0 && this.denominator.length === 0;
  2817. };
  2818. Unit.prototype.isSingular = function () {
  2819. return this.numerator.length <= 1 && this.denominator.length === 0;
  2820. };
  2821. Unit.prototype.map = function (callback) {
  2822. var i;
  2823. for (i = 0; i < this.numerator.length; i++) {
  2824. this.numerator[i] = callback(this.numerator[i], false);
  2825. }
  2826. for (i = 0; i < this.denominator.length; i++) {
  2827. this.denominator[i] = callback(this.denominator[i], true);
  2828. }
  2829. };
  2830. Unit.prototype.usedUnits = function () {
  2831. var group;
  2832. var result = {};
  2833. var mapUnit;
  2834. var groupName;
  2835. mapUnit = function (atomicUnit) {
  2836. /* jshint loopfunc:true */
  2837. if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
  2838. result[groupName] = atomicUnit;
  2839. }
  2840. return atomicUnit;
  2841. };
  2842. for (groupName in unitConversions) {
  2843. if (unitConversions.hasOwnProperty(groupName)) {
  2844. group = unitConversions[groupName];
  2845. this.map(mapUnit);
  2846. }
  2847. }
  2848. return result;
  2849. };
  2850. Unit.prototype.cancel = function () {
  2851. var counter = {};
  2852. var atomicUnit;
  2853. var i;
  2854. for (i = 0; i < this.numerator.length; i++) {
  2855. atomicUnit = this.numerator[i];
  2856. counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
  2857. }
  2858. for (i = 0; i < this.denominator.length; i++) {
  2859. atomicUnit = this.denominator[i];
  2860. counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
  2861. }
  2862. this.numerator = [];
  2863. this.denominator = [];
  2864. for (atomicUnit in counter) {
  2865. if (counter.hasOwnProperty(atomicUnit)) {
  2866. var count = counter[atomicUnit];
  2867. if (count > 0) {
  2868. for (i = 0; i < count; i++) {
  2869. this.numerator.push(atomicUnit);
  2870. }
  2871. }
  2872. else if (count < 0) {
  2873. for (i = 0; i < -count; i++) {
  2874. this.denominator.push(atomicUnit);
  2875. }
  2876. }
  2877. }
  2878. }
  2879. this.numerator.sort();
  2880. this.denominator.sort();
  2881. };
  2882. return Unit;
  2883. }(Node));
  2884. Unit.prototype.type = 'Unit';
  2885. //
  2886. // A number with a unit
  2887. //
  2888. var Dimension = /** @class */ (function (_super) {
  2889. tslib.__extends(Dimension, _super);
  2890. function Dimension(value, unit) {
  2891. var _this = _super.call(this) || this;
  2892. _this.value = parseFloat(value);
  2893. if (isNaN(_this.value)) {
  2894. throw new Error('Dimension is not a number.');
  2895. }
  2896. _this.unit = (unit && unit instanceof Unit) ? unit :
  2897. new Unit(unit ? [unit] : undefined);
  2898. _this.setParent(_this.unit, _this);
  2899. return _this;
  2900. }
  2901. Dimension.prototype.accept = function (visitor) {
  2902. this.unit = visitor.visit(this.unit);
  2903. };
  2904. Dimension.prototype.eval = function (context) {
  2905. return this;
  2906. };
  2907. Dimension.prototype.toColor = function () {
  2908. return new Color([this.value, this.value, this.value]);
  2909. };
  2910. Dimension.prototype.genCSS = function (context, output) {
  2911. if ((context && context.strictUnits) && !this.unit.isSingular()) {
  2912. throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString());
  2913. }
  2914. var value = this.fround(context, this.value);
  2915. var strValue = String(value);
  2916. if (value !== 0 && value < 0.000001 && value > -0.000001) {
  2917. // would be output 1e-6 etc.
  2918. strValue = value.toFixed(20).replace(/0+$/, '');
  2919. }
  2920. if (context && context.compress) {
  2921. // Zero values doesn't need a unit
  2922. if (value === 0 && this.unit.isLength()) {
  2923. output.add(strValue);
  2924. return;
  2925. }
  2926. // Float values doesn't need a leading zero
  2927. if (value > 0 && value < 1) {
  2928. strValue = (strValue).substr(1);
  2929. }
  2930. }
  2931. output.add(strValue);
  2932. this.unit.genCSS(context, output);
  2933. };
  2934. // In an operation between two Dimensions,
  2935. // we default to the first Dimension's unit,
  2936. // so `1px + 2` will yield `3px`.
  2937. Dimension.prototype.operate = function (context, op, other) {
  2938. /* jshint noempty:false */
  2939. var value = this._operate(context, op, this.value, other.value);
  2940. var unit = this.unit.clone();
  2941. if (op === '+' || op === '-') {
  2942. if (unit.numerator.length === 0 && unit.denominator.length === 0) {
  2943. unit = other.unit.clone();
  2944. if (this.unit.backupUnit) {
  2945. unit.backupUnit = this.unit.backupUnit;
  2946. }
  2947. }
  2948. else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) ;
  2949. else {
  2950. other = other.convertTo(this.unit.usedUnits());
  2951. if (context.strictUnits && other.unit.toString() !== unit.toString()) {
  2952. throw new Error("Incompatible units. Change the units or use the unit function. " +
  2953. ("Bad units: '" + unit.toString() + "' and '" + other.unit.toString() + "'."));
  2954. }
  2955. value = this._operate(context, op, this.value, other.value);
  2956. }
  2957. }
  2958. else if (op === '*') {
  2959. unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
  2960. unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
  2961. unit.cancel();
  2962. }
  2963. else if (op === '/') {
  2964. unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
  2965. unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
  2966. unit.cancel();
  2967. }
  2968. return new Dimension(value, unit);
  2969. };
  2970. Dimension.prototype.compare = function (other) {
  2971. var a;
  2972. var b;
  2973. if (!(other instanceof Dimension)) {
  2974. return undefined;
  2975. }
  2976. if (this.unit.isEmpty() || other.unit.isEmpty()) {
  2977. a = this;
  2978. b = other;
  2979. }
  2980. else {
  2981. a = this.unify();
  2982. b = other.unify();
  2983. if (a.unit.compare(b.unit) !== 0) {
  2984. return undefined;
  2985. }
  2986. }
  2987. return Node.numericCompare(a.value, b.value);
  2988. };
  2989. Dimension.prototype.unify = function () {
  2990. return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
  2991. };
  2992. Dimension.prototype.convertTo = function (conversions) {
  2993. var value = this.value;
  2994. var unit = this.unit.clone();
  2995. var i;
  2996. var groupName;
  2997. var group;
  2998. var targetUnit;
  2999. var derivedConversions = {};
  3000. var applyUnit;
  3001. if (typeof conversions === 'string') {
  3002. for (i in unitConversions) {
  3003. if (unitConversions[i].hasOwnProperty(conversions)) {
  3004. derivedConversions = {};
  3005. derivedConversions[i] = conversions;
  3006. }
  3007. }
  3008. conversions = derivedConversions;
  3009. }
  3010. applyUnit = function (atomicUnit, denominator) {
  3011. /* jshint loopfunc:true */
  3012. if (group.hasOwnProperty(atomicUnit)) {
  3013. if (denominator) {
  3014. value = value / (group[atomicUnit] / group[targetUnit]);
  3015. }
  3016. else {
  3017. value = value * (group[atomicUnit] / group[targetUnit]);
  3018. }
  3019. return targetUnit;
  3020. }
  3021. return atomicUnit;
  3022. };
  3023. for (groupName in conversions) {
  3024. if (conversions.hasOwnProperty(groupName)) {
  3025. targetUnit = conversions[groupName];
  3026. group = unitConversions[groupName];
  3027. unit.map(applyUnit);
  3028. }
  3029. }
  3030. unit.cancel();
  3031. return new Dimension(value, unit);
  3032. };
  3033. return Dimension;
  3034. }(Node));
  3035. Dimension.prototype.type = 'Dimension';
  3036. var MATH$1 = Math$1;
  3037. var Operation = /** @class */ (function (_super) {
  3038. tslib.__extends(Operation, _super);
  3039. function Operation(op, operands, isSpaced) {
  3040. var _this = _super.call(this) || this;
  3041. _this.op = op.trim();
  3042. _this.operands = operands;
  3043. _this.isSpaced = isSpaced;
  3044. return _this;
  3045. }
  3046. Operation.prototype.accept = function (visitor) {
  3047. this.operands = visitor.visitArray(this.operands);
  3048. };
  3049. Operation.prototype.eval = function (context) {
  3050. var a = this.operands[0].eval(context);
  3051. var b = this.operands[1].eval(context);
  3052. var op;
  3053. if (context.isMathOn(this.op)) {
  3054. op = this.op === './' ? '/' : this.op;
  3055. if (a instanceof Dimension && b instanceof Color) {
  3056. a = a.toColor();
  3057. }
  3058. if (b instanceof Dimension && a instanceof Color) {
  3059. b = b.toColor();
  3060. }
  3061. if (!a.operate) {
  3062. if (a instanceof Operation && a.op === '/' && context.math === MATH$1.PARENS_DIVISION) {
  3063. return new Operation(this.op, [a, b], this.isSpaced);
  3064. }
  3065. throw { type: 'Operation',
  3066. message: 'Operation on an invalid type' };
  3067. }
  3068. return a.operate(context, op, b);
  3069. }
  3070. else {
  3071. return new Operation(this.op, [a, b], this.isSpaced);
  3072. }
  3073. };
  3074. Operation.prototype.genCSS = function (context, output) {
  3075. this.operands[0].genCSS(context, output);
  3076. if (this.isSpaced) {
  3077. output.add(' ');
  3078. }
  3079. output.add(this.op);
  3080. if (this.isSpaced) {
  3081. output.add(' ');
  3082. }
  3083. this.operands[1].genCSS(context, output);
  3084. };
  3085. return Operation;
  3086. }(Node));
  3087. Operation.prototype.type = 'Operation';
  3088. var MATH$2 = Math$1;
  3089. var Expression = /** @class */ (function (_super) {
  3090. tslib.__extends(Expression, _super);
  3091. function Expression(value, noSpacing) {
  3092. var _this = _super.call(this) || this;
  3093. _this.value = value;
  3094. _this.noSpacing = noSpacing;
  3095. if (!value) {
  3096. throw new Error('Expression requires an array parameter');
  3097. }
  3098. return _this;
  3099. }
  3100. Expression.prototype.accept = function (visitor) {
  3101. this.value = visitor.visitArray(this.value);
  3102. };
  3103. Expression.prototype.eval = function (context) {
  3104. var returnValue;
  3105. var mathOn = context.isMathOn();
  3106. var inParenthesis = this.parens &&
  3107. (context.math !== MATH$2.STRICT_LEGACY || !this.parensInOp);
  3108. var doubleParen = false;
  3109. if (inParenthesis) {
  3110. context.inParenthesis();
  3111. }
  3112. if (this.value.length > 1) {
  3113. returnValue = new Expression(this.value.map(function (e) {
  3114. if (!e.eval) {
  3115. return e;
  3116. }
  3117. return e.eval(context);
  3118. }), this.noSpacing);
  3119. }
  3120. else if (this.value.length === 1) {
  3121. if (this.value[0].parens && !this.value[0].parensInOp && !context.inCalc) {
  3122. doubleParen = true;
  3123. }
  3124. returnValue = this.value[0].eval(context);
  3125. }
  3126. else {
  3127. returnValue = this;
  3128. }
  3129. if (inParenthesis) {
  3130. context.outOfParenthesis();
  3131. }
  3132. if (this.parens && this.parensInOp && !mathOn && !doubleParen
  3133. && (!(returnValue instanceof Dimension))) {
  3134. returnValue = new Paren(returnValue);
  3135. }
  3136. return returnValue;
  3137. };
  3138. Expression.prototype.genCSS = function (context, output) {
  3139. for (var i_1 = 0; i_1 < this.value.length; i_1++) {
  3140. this.value[i_1].genCSS(context, output);
  3141. if (!this.noSpacing && i_1 + 1 < this.value.length) {
  3142. output.add(' ');
  3143. }
  3144. }
  3145. };
  3146. Expression.prototype.throwAwayComments = function () {
  3147. this.value = this.value.filter(function (v) { return !(v instanceof Comment); });
  3148. };
  3149. return Expression;
  3150. }(Node));
  3151. Expression.prototype.type = 'Expression';
  3152. var functionCaller = /** @class */ (function () {
  3153. function functionCaller(name, context, index, currentFileInfo) {
  3154. this.name = name.toLowerCase();
  3155. this.index = index;
  3156. this.context = context;
  3157. this.currentFileInfo = currentFileInfo;
  3158. this.func = context.frames[0].functionRegistry.get(this.name);
  3159. }
  3160. functionCaller.prototype.isValid = function () {
  3161. return Boolean(this.func);
  3162. };
  3163. functionCaller.prototype.call = function (args) {
  3164. // This code is terrible and should be replaced as per this issue...
  3165. // https://github.com/less/less.js/issues/2477
  3166. if (Array.isArray(args)) {
  3167. args = args.filter(function (item) {
  3168. if (item.type === 'Comment') {
  3169. return false;
  3170. }
  3171. return true;
  3172. })
  3173. .map(function (item) {
  3174. if (item.type === 'Expression') {
  3175. var subNodes = item.value.filter(function (item) {
  3176. if (item.type === 'Comment') {
  3177. return false;
  3178. }
  3179. return true;
  3180. });
  3181. if (subNodes.length === 1) {
  3182. return subNodes[0];
  3183. }
  3184. else {
  3185. return new Expression(subNodes);
  3186. }
  3187. }
  3188. return item;
  3189. });
  3190. }
  3191. return this.func.apply(this, args);
  3192. };
  3193. return functionCaller;
  3194. }());
  3195. //
  3196. // A function call node.
  3197. //
  3198. var Call = /** @class */ (function (_super) {
  3199. tslib.__extends(Call, _super);
  3200. function Call(name, args, index, currentFileInfo) {
  3201. var _this = _super.call(this) || this;
  3202. _this.name = name;
  3203. _this.args = args;
  3204. _this.calc = name === 'calc';
  3205. _this._index = index;
  3206. _this._fileInfo = currentFileInfo;
  3207. return _this;
  3208. }
  3209. Call.prototype.accept = function (visitor) {
  3210. if (this.args) {
  3211. this.args = visitor.visitArray(this.args);
  3212. }
  3213. };
  3214. //
  3215. // When evaluating a function call,
  3216. // we either find the function in the functionRegistry,
  3217. // in which case we call it, passing the evaluated arguments,
  3218. // if this returns null or we cannot find the function, we
  3219. // simply print it out as it appeared originally [2].
  3220. //
  3221. // The reason why we evaluate the arguments, is in the case where
  3222. // we try to pass a variable to a function, like: `saturate(@color)`.
  3223. // The function should receive the value, not the variable.
  3224. //
  3225. Call.prototype.eval = function (context) {
  3226. /**
  3227. * Turn off math for calc(), and switch back on for evaluating nested functions
  3228. */
  3229. var currentMathContext = context.mathOn;
  3230. context.mathOn = !this.calc;
  3231. if (this.calc || context.inCalc) {
  3232. context.enterCalc();
  3233. }
  3234. var args = this.args.map(function (a) { return a.eval(context); });
  3235. if (this.calc || context.inCalc) {
  3236. context.exitCalc();
  3237. }
  3238. context.mathOn = currentMathContext;
  3239. var result;
  3240. var funcCaller = new functionCaller(this.name, context, this.getIndex(), this.fileInfo());
  3241. if (funcCaller.isValid()) {
  3242. try {
  3243. result = funcCaller.call(args);
  3244. }
  3245. catch (e) {
  3246. throw {
  3247. type: e.type || 'Runtime',
  3248. message: "error evaluating function `" + this.name + "`" + (e.message ? ": " + e.message : ''),
  3249. index: this.getIndex(),
  3250. filename: this.fileInfo().filename,
  3251. line: e.lineNumber,
  3252. column: e.columnNumber
  3253. };
  3254. }
  3255. if (result !== null && result !== undefined) {
  3256. // Results that that are not nodes are cast as Anonymous nodes
  3257. // Falsy values or booleans are returned as empty nodes
  3258. if (!(result instanceof Node)) {
  3259. if (!result || result === true) {
  3260. result = new Anonymous(null);
  3261. }
  3262. else {
  3263. result = new Anonymous(result.toString());
  3264. }
  3265. }
  3266. result._index = this._index;
  3267. result._fileInfo = this._fileInfo;
  3268. return result;
  3269. }
  3270. }
  3271. return new Call(this.name, args, this.getIndex(), this.fileInfo());
  3272. };
  3273. Call.prototype.genCSS = function (context, output) {
  3274. output.add(this.name + "(", this.fileInfo(), this.getIndex());
  3275. for (var i_1 = 0; i_1 < this.args.length; i_1++) {
  3276. this.args[i_1].genCSS(context, output);
  3277. if (i_1 + 1 < this.args.length) {
  3278. output.add(', ');
  3279. }
  3280. }
  3281. output.add(')');
  3282. };
  3283. return Call;
  3284. }(Node));
  3285. Call.prototype.type = 'Call';
  3286. var Variable = /** @class */ (function (_super) {
  3287. tslib.__extends(Variable, _super);
  3288. function Variable(name, index, currentFileInfo) {
  3289. var _this = _super.call(this) || this;
  3290. _this.name = name;
  3291. _this._index = index;
  3292. _this._fileInfo = currentFileInfo;
  3293. return _this;
  3294. }
  3295. Variable.prototype.eval = function (context) {
  3296. var variable;
  3297. var name = this.name;
  3298. if (name.indexOf('@@') === 0) {
  3299. name = "@" + new Variable(name.slice(1), this.getIndex(), this.fileInfo()).eval(context).value;
  3300. }
  3301. if (this.evaluating) {
  3302. throw { type: 'Name',
  3303. message: "Recursive variable definition for " + name,
  3304. filename: this.fileInfo().filename,
  3305. index: this.getIndex() };
  3306. }
  3307. this.evaluating = true;
  3308. variable = this.find(context.frames, function (frame) {
  3309. var v = frame.variable(name);
  3310. if (v) {
  3311. if (v.important) {
  3312. var importantScope = context.importantScope[context.importantScope.length - 1];
  3313. importantScope.important = v.important;
  3314. }
  3315. // If in calc, wrap vars in a function call to cascade evaluate args first
  3316. if (context.inCalc) {
  3317. return (new Call('_SELF', [v.value])).eval(context);
  3318. }
  3319. else {
  3320. return v.value.eval(context);
  3321. }
  3322. }
  3323. });
  3324. if (variable) {
  3325. this.evaluating = false;
  3326. return variable;
  3327. }
  3328. else {
  3329. throw { type: 'Name',
  3330. message: "variable " + name + " is undefined",
  3331. filename: this.fileInfo().filename,
  3332. index: this.getIndex() };
  3333. }
  3334. };
  3335. Variable.prototype.find = function (obj, fun) {
  3336. for (var i_1 = 0, r = void 0; i_1 < obj.length; i_1++) {
  3337. r = fun.call(obj, obj[i_1]);
  3338. if (r) {
  3339. return r;
  3340. }
  3341. }
  3342. return null;
  3343. };
  3344. return Variable;
  3345. }(Node));
  3346. Variable.prototype.type = 'Variable';
  3347. var Property = /** @class */ (function (_super) {
  3348. tslib.__extends(Property, _super);
  3349. function Property(name, index, currentFileInfo) {
  3350. var _this = _super.call(this) || this;
  3351. _this.name = name;
  3352. _this._index = index;
  3353. _this._fileInfo = currentFileInfo;
  3354. return _this;
  3355. }
  3356. Property.prototype.eval = function (context) {
  3357. var property;
  3358. var name = this.name;
  3359. // TODO: shorten this reference
  3360. var mergeRules = context.pluginManager.less.visitors.ToCSSVisitor.prototype._mergeRules;
  3361. if (this.evaluating) {
  3362. throw { type: 'Name',
  3363. message: "Recursive property reference for " + name,
  3364. filename: this.fileInfo().filename,
  3365. index: this.getIndex() };
  3366. }
  3367. this.evaluating = true;
  3368. property = this.find(context.frames, function (frame) {
  3369. var v;
  3370. var vArr = frame.property(name);
  3371. if (vArr) {
  3372. for (var i_1 = 0; i_1 < vArr.length; i_1++) {
  3373. v = vArr[i_1];
  3374. vArr[i_1] = new Declaration(v.name, v.value, v.important, v.merge, v.index, v.currentFileInfo, v.inline, v.variable);
  3375. }
  3376. mergeRules(vArr);
  3377. v = vArr[vArr.length - 1];
  3378. if (v.important) {
  3379. var importantScope = context.importantScope[context.importantScope.length - 1];
  3380. importantScope.important = v.important;
  3381. }
  3382. v = v.value.eval(context);
  3383. return v;
  3384. }
  3385. });
  3386. if (property) {
  3387. this.evaluating = false;
  3388. return property;
  3389. }
  3390. else {
  3391. throw { type: 'Name',
  3392. message: "Property '" + name + "' is undefined",
  3393. filename: this.currentFileInfo.filename,
  3394. index: this.index };
  3395. }
  3396. };
  3397. Property.prototype.find = function (obj, fun) {
  3398. for (var i_2 = 0, r = void 0; i_2 < obj.length; i_2++) {
  3399. r = fun.call(obj, obj[i_2]);
  3400. if (r) {
  3401. return r;
  3402. }
  3403. }
  3404. return null;
  3405. };
  3406. return Property;
  3407. }(Node));
  3408. Property.prototype.type = 'Property';
  3409. var Attribute = /** @class */ (function (_super) {
  3410. tslib.__extends(Attribute, _super);
  3411. function Attribute(key, op, value) {
  3412. var _this = _super.call(this) || this;
  3413. _this.key = key;
  3414. _this.op = op;
  3415. _this.value = value;
  3416. return _this;
  3417. }
  3418. Attribute.prototype.eval = function (context) {
  3419. return new Attribute(this.key.eval ? this.key.eval(context) : this.key, this.op, (this.value && this.value.eval) ? this.value.eval(context) : this.value);
  3420. };
  3421. Attribute.prototype.genCSS = function (context, output) {
  3422. output.add(this.toCSS(context));
  3423. };
  3424. Attribute.prototype.toCSS = function (context) {
  3425. var value = this.key.toCSS ? this.key.toCSS(context) : this.key;
  3426. if (this.op) {
  3427. value += this.op;
  3428. value += (this.value.toCSS ? this.value.toCSS(context) : this.value);
  3429. }
  3430. return "[" + value + "]";
  3431. };
  3432. return Attribute;
  3433. }(Node));
  3434. Attribute.prototype.type = 'Attribute';
  3435. var Quoted = /** @class */ (function (_super) {
  3436. tslib.__extends(Quoted, _super);
  3437. function Quoted(str, content, escaped, index, currentFileInfo) {
  3438. var _this = _super.call(this) || this;
  3439. _this.escaped = (escaped == null) ? true : escaped;
  3440. _this.value = content || '';
  3441. _this.quote = str.charAt(0);
  3442. _this._index = index;
  3443. _this._fileInfo = currentFileInfo;
  3444. _this.variableRegex = /@\{([\w-]+)\}/g;
  3445. _this.propRegex = /\$\{([\w-]+)\}/g;
  3446. _this.allowRoot = escaped;
  3447. return _this;
  3448. }
  3449. Quoted.prototype.genCSS = function (context, output) {
  3450. if (!this.escaped) {
  3451. output.add(this.quote, this.fileInfo(), this.getIndex());
  3452. }
  3453. output.add(this.value);
  3454. if (!this.escaped) {
  3455. output.add(this.quote);
  3456. }
  3457. };
  3458. Quoted.prototype.containsVariables = function () {
  3459. return this.value.match(this.variableRegex);
  3460. };
  3461. Quoted.prototype.eval = function (context) {
  3462. var that = this;
  3463. var value = this.value;
  3464. var variableReplacement = function (_, name) {
  3465. var v = new Variable("@" + name, that.getIndex(), that.fileInfo()).eval(context, true);
  3466. return (v instanceof Quoted) ? v.value : v.toCSS();
  3467. };
  3468. var propertyReplacement = function (_, name) {
  3469. var v = new Property("$" + name, that.getIndex(), that.fileInfo()).eval(context, true);
  3470. return (v instanceof Quoted) ? v.value : v.toCSS();
  3471. };
  3472. function iterativeReplace(value, regexp, replacementFnc) {
  3473. var evaluatedValue = value;
  3474. do {
  3475. value = evaluatedValue.toString();
  3476. evaluatedValue = value.replace(regexp, replacementFnc);
  3477. } while (value !== evaluatedValue);
  3478. return evaluatedValue;
  3479. }
  3480. value = iterativeReplace(value, this.variableRegex, variableReplacement);
  3481. value = iterativeReplace(value, this.propRegex, propertyReplacement);
  3482. return new Quoted(this.quote + value + this.quote, value, this.escaped, this.getIndex(), this.fileInfo());
  3483. };
  3484. Quoted.prototype.compare = function (other) {
  3485. // when comparing quoted strings allow the quote to differ
  3486. if (other.type === 'Quoted' && !this.escaped && !other.escaped) {
  3487. return Node.numericCompare(this.value, other.value);
  3488. }
  3489. else {
  3490. return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
  3491. }
  3492. };
  3493. return Quoted;
  3494. }(Node));
  3495. Quoted.prototype.type = 'Quoted';
  3496. var URL = /** @class */ (function (_super) {
  3497. tslib.__extends(URL, _super);
  3498. function URL(val, index, currentFileInfo, isEvald) {
  3499. var _this = _super.call(this) || this;
  3500. _this.value = val;
  3501. _this._index = index;
  3502. _this._fileInfo = currentFileInfo;
  3503. _this.isEvald = isEvald;
  3504. return _this;
  3505. }
  3506. URL.prototype.accept = function (visitor) {
  3507. this.value = visitor.visit(this.value);
  3508. };
  3509. URL.prototype.genCSS = function (context, output) {
  3510. output.add('url(');
  3511. this.value.genCSS(context, output);
  3512. output.add(')');
  3513. };
  3514. URL.prototype.eval = function (context) {
  3515. var val = this.value.eval(context);
  3516. var rootpath;
  3517. if (!this.isEvald) {
  3518. // Add the rootpath if the URL requires a rewrite
  3519. rootpath = this.fileInfo() && this.fileInfo().rootpath;
  3520. if (typeof rootpath === 'string' &&
  3521. typeof val.value === 'string' &&
  3522. context.pathRequiresRewrite(val.value)) {
  3523. if (!val.quote) {
  3524. rootpath = escapePath(rootpath);
  3525. }
  3526. val.value = context.rewritePath(val.value, rootpath);
  3527. }
  3528. else {
  3529. val.value = context.normalizePath(val.value);
  3530. }
  3531. // Add url args if enabled
  3532. if (context.urlArgs) {
  3533. if (!val.value.match(/^\s*data:/)) {
  3534. var delimiter = val.value.indexOf('?') === -1 ? '?' : '&';
  3535. var urlArgs = delimiter + context.urlArgs;
  3536. if (val.value.indexOf('#') !== -1) {
  3537. val.value = val.value.replace('#', urlArgs + "#");
  3538. }
  3539. else {
  3540. val.value += urlArgs;
  3541. }
  3542. }
  3543. }
  3544. }
  3545. return new URL(val, this.getIndex(), this.fileInfo(), true);
  3546. };
  3547. return URL;
  3548. }(Node));
  3549. URL.prototype.type = 'Url';
  3550. function escapePath(path) {
  3551. return path.replace(/[\(\)'"\s]/g, function (match) { return "\\" + match; });
  3552. }
  3553. var Media = /** @class */ (function (_super) {
  3554. tslib.__extends(Media, _super);
  3555. function Media(value, features, index, currentFileInfo, visibilityInfo) {
  3556. var _this = _super.call(this) || this;
  3557. _this._index = index;
  3558. _this._fileInfo = currentFileInfo;
  3559. var selectors = (new Selector([], null, null, _this._index, _this._fileInfo)).createEmptySelectors();
  3560. _this.features = new Value(features);
  3561. _this.rules = [new Ruleset(selectors, value)];
  3562. _this.rules[0].allowImports = true;
  3563. _this.copyVisibilityInfo(visibilityInfo);
  3564. _this.allowRoot = true;
  3565. _this.setParent(selectors, _this);
  3566. _this.setParent(_this.features, _this);
  3567. _this.setParent(_this.rules, _this);
  3568. return _this;
  3569. }
  3570. Media.prototype.isRulesetLike = function () {
  3571. return true;
  3572. };
  3573. Media.prototype.accept = function (visitor) {
  3574. if (this.features) {
  3575. this.features = visitor.visit(this.features);
  3576. }
  3577. if (this.rules) {
  3578. this.rules = visitor.visitArray(this.rules);
  3579. }
  3580. };
  3581. Media.prototype.genCSS = function (context, output) {
  3582. output.add('@media ', this._fileInfo, this._index);
  3583. this.features.genCSS(context, output);
  3584. this.outputRuleset(context, output, this.rules);
  3585. };
  3586. Media.prototype.eval = function (context) {
  3587. if (!context.mediaBlocks) {
  3588. context.mediaBlocks = [];
  3589. context.mediaPath = [];
  3590. }
  3591. var media = new Media(null, [], this._index, this._fileInfo, this.visibilityInfo());
  3592. if (this.debugInfo) {
  3593. this.rules[0].debugInfo = this.debugInfo;
  3594. media.debugInfo = this.debugInfo;
  3595. }
  3596. media.features = this.features.eval(context);
  3597. context.mediaPath.push(media);
  3598. context.mediaBlocks.push(media);
  3599. this.rules[0].functionRegistry = context.frames[0].functionRegistry.inherit();
  3600. context.frames.unshift(this.rules[0]);
  3601. media.rules = [this.rules[0].eval(context)];
  3602. context.frames.shift();
  3603. context.mediaPath.pop();
  3604. return context.mediaPath.length === 0 ? media.evalTop(context) :
  3605. media.evalNested(context);
  3606. };
  3607. Media.prototype.evalTop = function (context) {
  3608. var result = this;
  3609. // Render all dependent Media blocks.
  3610. if (context.mediaBlocks.length > 1) {
  3611. var selectors = (new Selector([], null, null, this.getIndex(), this.fileInfo())).createEmptySelectors();
  3612. result = new Ruleset(selectors, context.mediaBlocks);
  3613. result.multiMedia = true;
  3614. result.copyVisibilityInfo(this.visibilityInfo());
  3615. this.setParent(result, this);
  3616. }
  3617. delete context.mediaBlocks;
  3618. delete context.mediaPath;
  3619. return result;
  3620. };
  3621. Media.prototype.evalNested = function (context) {
  3622. var i;
  3623. var value;
  3624. var path = context.mediaPath.concat([this]);
  3625. // Extract the media-query conditions separated with `,` (OR).
  3626. for (i = 0; i < path.length; i++) {
  3627. value = path[i].features instanceof Value ?
  3628. path[i].features.value : path[i].features;
  3629. path[i] = Array.isArray(value) ? value : [value];
  3630. }
  3631. // Trace all permutations to generate the resulting media-query.
  3632. //
  3633. // (a, b and c) with nested (d, e) ->
  3634. // a and d
  3635. // a and e
  3636. // b and c and d
  3637. // b and c and e
  3638. this.features = new Value(this.permute(path).map(function (path) {
  3639. path = path.map(function (fragment) { return fragment.toCSS ? fragment : new Anonymous(fragment); });
  3640. for (i = path.length - 1; i > 0; i--) {
  3641. path.splice(i, 0, new Anonymous('and'));
  3642. }
  3643. return new Expression(path);
  3644. }));
  3645. this.setParent(this.features, this);
  3646. // Fake a tree-node that doesn't output anything.
  3647. return new Ruleset([], []);
  3648. };
  3649. Media.prototype.permute = function (arr) {
  3650. if (arr.length === 0) {
  3651. return [];
  3652. }
  3653. else if (arr.length === 1) {
  3654. return arr[0];
  3655. }
  3656. else {
  3657. var result = [];
  3658. var rest = this.permute(arr.slice(1));
  3659. for (var i_1 = 0; i_1 < rest.length; i_1++) {
  3660. for (var j = 0; j < arr[0].length; j++) {
  3661. result.push([arr[0][j]].concat(rest[i_1]));
  3662. }
  3663. }
  3664. return result;
  3665. }
  3666. };
  3667. Media.prototype.bubbleSelectors = function (selectors) {
  3668. if (!selectors) {
  3669. return;
  3670. }
  3671. this.rules = [new Ruleset(copyArray(selectors), [this.rules[0]])];
  3672. this.setParent(this.rules, this);
  3673. };
  3674. return Media;
  3675. }(AtRule));
  3676. Media.prototype.type = 'Media';
  3677. //
  3678. // CSS @import node
  3679. //
  3680. // The general strategy here is that we don't want to wait
  3681. // for the parsing to be completed, before we start importing
  3682. // the file. That's because in the context of a browser,
  3683. // most of the time will be spent waiting for the server to respond.
  3684. //
  3685. // On creation, we push the import path to our import queue, though
  3686. // `import,push`, we also pass it a callback, which it'll call once
  3687. // the file has been fetched, and parsed.
  3688. //
  3689. var Import = /** @class */ (function (_super) {
  3690. tslib.__extends(Import, _super);
  3691. function Import(path, features, options, index, currentFileInfo, visibilityInfo) {
  3692. var _this = _super.call(this) || this;
  3693. _this.options = options;
  3694. _this._index = index;
  3695. _this._fileInfo = currentFileInfo;
  3696. _this.path = path;
  3697. _this.features = features;
  3698. _this.allowRoot = true;
  3699. if (_this.options.less !== undefined || _this.options.inline) {
  3700. _this.css = !_this.options.less || _this.options.inline;
  3701. }
  3702. else {
  3703. var pathValue = _this.getPath();
  3704. if (pathValue && /[#\.\&\?]css([\?;].*)?$/.test(pathValue)) {
  3705. _this.css = true;
  3706. }
  3707. }
  3708. _this.copyVisibilityInfo(visibilityInfo);
  3709. _this.setParent(_this.features, _this);
  3710. _this.setParent(_this.path, _this);
  3711. return _this;
  3712. }
  3713. Import.prototype.accept = function (visitor) {
  3714. if (this.features) {
  3715. this.features = visitor.visit(this.features);
  3716. }
  3717. this.path = visitor.visit(this.path);
  3718. if (!this.options.isPlugin && !this.options.inline && this.root) {
  3719. this.root = visitor.visit(this.root);
  3720. }
  3721. };
  3722. Import.prototype.genCSS = function (context, output) {
  3723. if (this.css && this.path._fileInfo.reference === undefined) {
  3724. output.add('@import ', this._fileInfo, this._index);
  3725. this.path.genCSS(context, output);
  3726. if (this.features) {
  3727. output.add(' ');
  3728. this.features.genCSS(context, output);
  3729. }
  3730. output.add(';');
  3731. }
  3732. };
  3733. Import.prototype.getPath = function () {
  3734. return (this.path instanceof URL) ?
  3735. this.path.value.value : this.path.value;
  3736. };
  3737. Import.prototype.isVariableImport = function () {
  3738. var path = this.path;
  3739. if (path instanceof URL) {
  3740. path = path.value;
  3741. }
  3742. if (path instanceof Quoted) {
  3743. return path.containsVariables();
  3744. }
  3745. return true;
  3746. };
  3747. Import.prototype.evalForImport = function (context) {
  3748. var path = this.path;
  3749. if (path instanceof URL) {
  3750. path = path.value;
  3751. }
  3752. return new Import(path.eval(context), this.features, this.options, this._index, this._fileInfo, this.visibilityInfo());
  3753. };
  3754. Import.prototype.evalPath = function (context) {
  3755. var path = this.path.eval(context);
  3756. var fileInfo = this._fileInfo;
  3757. if (!(path instanceof URL)) {
  3758. // Add the rootpath if the URL requires a rewrite
  3759. var pathValue = path.value;
  3760. if (fileInfo &&
  3761. pathValue &&
  3762. context.pathRequiresRewrite(pathValue)) {
  3763. path.value = context.rewritePath(pathValue, fileInfo.rootpath);
  3764. }
  3765. else {
  3766. path.value = context.normalizePath(path.value);
  3767. }
  3768. }
  3769. return path;
  3770. };
  3771. Import.prototype.eval = function (context) {
  3772. var result = this.doEval(context);
  3773. if (this.options.reference || this.blocksVisibility()) {
  3774. if (result.length || result.length === 0) {
  3775. result.forEach(function (node) {
  3776. node.addVisibilityBlock();
  3777. });
  3778. }
  3779. else {
  3780. result.addVisibilityBlock();
  3781. }
  3782. }
  3783. return result;
  3784. };
  3785. Import.prototype.doEval = function (context) {
  3786. var ruleset;
  3787. var registry;
  3788. var features = this.features && this.features.eval(context);
  3789. if (this.options.isPlugin) {
  3790. if (this.root && this.root.eval) {
  3791. try {
  3792. this.root.eval(context);
  3793. }
  3794. catch (e) {
  3795. e.message = 'Plugin error during evaluation';
  3796. throw new LessError(e, this.root.imports, this.root.filename);
  3797. }
  3798. }
  3799. registry = context.frames[0] && context.frames[0].functionRegistry;
  3800. if (registry && this.root && this.root.functions) {
  3801. registry.addMultiple(this.root.functions);
  3802. }
  3803. return [];
  3804. }
  3805. if (this.skip) {
  3806. if (typeof this.skip === 'function') {
  3807. this.skip = this.skip();
  3808. }
  3809. if (this.skip) {
  3810. return [];
  3811. }
  3812. }
  3813. if (this.options.inline) {
  3814. var contents = new Anonymous(this.root, 0, {
  3815. filename: this.importedFilename,
  3816. reference: this.path._fileInfo && this.path._fileInfo.reference
  3817. }, true, true);
  3818. return this.features ? new Media([contents], this.features.value) : [contents];
  3819. }
  3820. else if (this.css) {
  3821. var newImport = new Import(this.evalPath(context), features, this.options, this._index);
  3822. if (!newImport.css && this.error) {
  3823. throw this.error;
  3824. }
  3825. return newImport;
  3826. }
  3827. else {
  3828. ruleset = new Ruleset(null, copyArray(this.root.rules));
  3829. ruleset.evalImports(context);
  3830. return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules;
  3831. }
  3832. };
  3833. return Import;
  3834. }(Node));
  3835. Import.prototype.type = 'Import';
  3836. var JsEvalNode = /** @class */ (function (_super) {
  3837. tslib.__extends(JsEvalNode, _super);
  3838. function JsEvalNode() {
  3839. return _super !== null && _super.apply(this, arguments) || this;
  3840. }
  3841. JsEvalNode.prototype.evaluateJavaScript = function (expression, context) {
  3842. var result;
  3843. var that = this;
  3844. var evalContext = {};
  3845. if (!context.javascriptEnabled) {
  3846. throw { message: 'Inline JavaScript is not enabled. Is it set in your options?',
  3847. filename: this.fileInfo().filename,
  3848. index: this.getIndex() };
  3849. }
  3850. expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) { return that.jsify(new Variable("@" + name, that.getIndex(), that.fileInfo()).eval(context)); });
  3851. try {
  3852. expression = new Function("return (" + expression + ")");
  3853. }
  3854. catch (e) {
  3855. throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`",
  3856. filename: this.fileInfo().filename,
  3857. index: this.getIndex() };
  3858. }
  3859. var variables = context.frames[0].variables();
  3860. for (var k in variables) {
  3861. if (variables.hasOwnProperty(k)) {
  3862. /* jshint loopfunc:true */
  3863. evalContext[k.slice(1)] = {
  3864. value: variables[k].value,
  3865. toJS: function () {
  3866. return this.value.eval(context).toCSS();
  3867. }
  3868. };
  3869. }
  3870. }
  3871. try {
  3872. result = expression.call(evalContext);
  3873. }
  3874. catch (e) {
  3875. throw { message: "JavaScript evaluation error: '" + e.name + ": " + e.message.replace(/["]/g, '\'') + "'",
  3876. filename: this.fileInfo().filename,
  3877. index: this.getIndex() };
  3878. }
  3879. return result;
  3880. };
  3881. JsEvalNode.prototype.jsify = function (obj) {
  3882. if (Array.isArray(obj.value) && (obj.value.length > 1)) {
  3883. return "[" + obj.value.map(function (v) { return v.toCSS(); }).join(', ') + "]";
  3884. }
  3885. else {
  3886. return obj.toCSS();
  3887. }
  3888. };
  3889. return JsEvalNode;
  3890. }(Node));
  3891. var JavaScript = /** @class */ (function (_super) {
  3892. tslib.__extends(JavaScript, _super);
  3893. function JavaScript(string, escaped, index, currentFileInfo) {
  3894. var _this = _super.call(this) || this;
  3895. _this.escaped = escaped;
  3896. _this.expression = string;
  3897. _this._index = index;
  3898. _this._fileInfo = currentFileInfo;
  3899. return _this;
  3900. }
  3901. JavaScript.prototype.eval = function (context) {
  3902. var result = this.evaluateJavaScript(this.expression, context);
  3903. var type = typeof result;
  3904. if (type === 'number' && !isNaN(result)) {
  3905. return new Dimension(result);
  3906. }
  3907. else if (type === 'string') {
  3908. return new Quoted("\"" + result + "\"", result, this.escaped, this._index);
  3909. }
  3910. else if (Array.isArray(result)) {
  3911. return new Anonymous(result.join(', '));
  3912. }
  3913. else {
  3914. return new Anonymous(result);
  3915. }
  3916. };
  3917. return JavaScript;
  3918. }(JsEvalNode));
  3919. JavaScript.prototype.type = 'JavaScript';
  3920. var Assignment = /** @class */ (function (_super) {
  3921. tslib.__extends(Assignment, _super);
  3922. function Assignment(key, val) {
  3923. var _this = _super.call(this) || this;
  3924. _this.key = key;
  3925. _this.value = val;
  3926. return _this;
  3927. }
  3928. Assignment.prototype.accept = function (visitor) {
  3929. this.value = visitor.visit(this.value);
  3930. };
  3931. Assignment.prototype.eval = function (context) {
  3932. if (this.value.eval) {
  3933. return new Assignment(this.key, this.value.eval(context));
  3934. }
  3935. return this;
  3936. };
  3937. Assignment.prototype.genCSS = function (context, output) {
  3938. output.add(this.key + "=");
  3939. if (this.value.genCSS) {
  3940. this.value.genCSS(context, output);
  3941. }
  3942. else {
  3943. output.add(this.value);
  3944. }
  3945. };
  3946. return Assignment;
  3947. }(Node));
  3948. Assignment.prototype.type = 'Assignment';
  3949. var Condition = /** @class */ (function (_super) {
  3950. tslib.__extends(Condition, _super);
  3951. function Condition(op, l, r, i, negate) {
  3952. var _this = _super.call(this) || this;
  3953. _this.op = op.trim();
  3954. _this.lvalue = l;
  3955. _this.rvalue = r;
  3956. _this._index = i;
  3957. _this.negate = negate;
  3958. return _this;
  3959. }
  3960. Condition.prototype.accept = function (visitor) {
  3961. this.lvalue = visitor.visit(this.lvalue);
  3962. this.rvalue = visitor.visit(this.rvalue);
  3963. };
  3964. Condition.prototype.eval = function (context) {
  3965. var result = (function (op, a, b) {
  3966. switch (op) {
  3967. case 'and': return a && b;
  3968. case 'or': return a || b;
  3969. default:
  3970. switch (Node.compare(a, b)) {
  3971. case -1:
  3972. return op === '<' || op === '=<' || op === '<=';
  3973. case 0:
  3974. return op === '=' || op === '>=' || op === '=<' || op === '<=';
  3975. case 1:
  3976. return op === '>' || op === '>=';
  3977. default:
  3978. return false;
  3979. }
  3980. }
  3981. })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
  3982. return this.negate ? !result : result;
  3983. };
  3984. return Condition;
  3985. }(Node));
  3986. Condition.prototype.type = 'Condition';
  3987. var UnicodeDescriptor = /** @class */ (function (_super) {
  3988. tslib.__extends(UnicodeDescriptor, _super);
  3989. function UnicodeDescriptor(value) {
  3990. var _this = _super.call(this) || this;
  3991. _this.value = value;
  3992. return _this;
  3993. }
  3994. return UnicodeDescriptor;
  3995. }(Node));
  3996. UnicodeDescriptor.prototype.type = 'UnicodeDescriptor';
  3997. var Negative = /** @class */ (function (_super) {
  3998. tslib.__extends(Negative, _super);
  3999. function Negative(node) {
  4000. var _this = _super.call(this) || this;
  4001. _this.value = node;
  4002. return _this;
  4003. }
  4004. Negative.prototype.genCSS = function (context, output) {
  4005. output.add('-');
  4006. this.value.genCSS(context, output);
  4007. };
  4008. Negative.prototype.eval = function (context) {
  4009. if (context.isMathOn()) {
  4010. return (new Operation('*', [new Dimension(-1), this.value])).eval(context);
  4011. }
  4012. return new Negative(this.value.eval(context));
  4013. };
  4014. return Negative;
  4015. }(Node));
  4016. Negative.prototype.type = 'Negative';
  4017. var Extend = /** @class */ (function (_super) {
  4018. tslib.__extends(Extend, _super);
  4019. function Extend(selector, option, index, currentFileInfo, visibilityInfo) {
  4020. var _this = _super.call(this) || this;
  4021. _this.selector = selector;
  4022. _this.option = option;
  4023. _this.object_id = Extend.next_id++;
  4024. _this.parent_ids = [_this.object_id];
  4025. _this._index = index;
  4026. _this._fileInfo = currentFileInfo;
  4027. _this.copyVisibilityInfo(visibilityInfo);
  4028. _this.allowRoot = true;
  4029. switch (option) {
  4030. case 'all':
  4031. _this.allowBefore = true;
  4032. _this.allowAfter = true;
  4033. break;
  4034. default:
  4035. _this.allowBefore = false;
  4036. _this.allowAfter = false;
  4037. break;
  4038. }
  4039. _this.setParent(_this.selector, _this);
  4040. return _this;
  4041. }
  4042. Extend.prototype.accept = function (visitor) {
  4043. this.selector = visitor.visit(this.selector);
  4044. };
  4045. Extend.prototype.eval = function (context) {
  4046. return new Extend(this.selector.eval(context), this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo());
  4047. };
  4048. Extend.prototype.clone = function (context) {
  4049. return new Extend(this.selector, this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo());
  4050. };
  4051. // it concatenates (joins) all selectors in selector array
  4052. Extend.prototype.findSelfSelectors = function (selectors) {
  4053. var selfElements = [];
  4054. var i;
  4055. var selectorElements;
  4056. for (i = 0; i < selectors.length; i++) {
  4057. selectorElements = selectors[i].elements;
  4058. // duplicate the logic in genCSS function inside the selector node.
  4059. // future TODO - move both logics into the selector joiner visitor
  4060. if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === '') {
  4061. selectorElements[0].combinator.value = ' ';
  4062. }
  4063. selfElements = selfElements.concat(selectors[i].elements);
  4064. }
  4065. this.selfSelectors = [new Selector(selfElements)];
  4066. this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo());
  4067. };
  4068. return Extend;
  4069. }(Node));
  4070. Extend.next_id = 0;
  4071. Extend.prototype.type = 'Extend';
  4072. var VariableCall = /** @class */ (function (_super) {
  4073. tslib.__extends(VariableCall, _super);
  4074. function VariableCall(variable, index, currentFileInfo) {
  4075. var _this = _super.call(this) || this;
  4076. _this.variable = variable;
  4077. _this._index = index;
  4078. _this._fileInfo = currentFileInfo;
  4079. _this.allowRoot = true;
  4080. return _this;
  4081. }
  4082. VariableCall.prototype.eval = function (context) {
  4083. var rules;
  4084. var detachedRuleset = new Variable(this.variable, this.getIndex(), this.fileInfo()).eval(context);
  4085. var error = new LessError({ message: "Could not evaluate variable call " + this.variable });
  4086. if (!detachedRuleset.ruleset) {
  4087. if (detachedRuleset.rules) {
  4088. rules = detachedRuleset;
  4089. }
  4090. else if (Array.isArray(detachedRuleset)) {
  4091. rules = new Ruleset('', detachedRuleset);
  4092. }
  4093. else if (Array.isArray(detachedRuleset.value)) {
  4094. rules = new Ruleset('', detachedRuleset.value);
  4095. }
  4096. else {
  4097. throw error;
  4098. }
  4099. detachedRuleset = new DetachedRuleset(rules);
  4100. }
  4101. if (detachedRuleset.ruleset) {
  4102. return detachedRuleset.callEval(context);
  4103. }
  4104. throw error;
  4105. };
  4106. return VariableCall;
  4107. }(Node));
  4108. VariableCall.prototype.type = 'VariableCall';
  4109. var NamespaceValue = /** @class */ (function (_super) {
  4110. tslib.__extends(NamespaceValue, _super);
  4111. function NamespaceValue(ruleCall, lookups, index, fileInfo) {
  4112. var _this = _super.call(this) || this;
  4113. _this.value = ruleCall;
  4114. _this.lookups = lookups;
  4115. _this._index = index;
  4116. _this._fileInfo = fileInfo;
  4117. return _this;
  4118. }
  4119. NamespaceValue.prototype.eval = function (context) {
  4120. var i;
  4121. var name;
  4122. var rules = this.value.eval(context);
  4123. for (i = 0; i < this.lookups.length; i++) {
  4124. name = this.lookups[i];
  4125. /**
  4126. * Eval'd DRs return rulesets.
  4127. * Eval'd mixins return rules, so let's make a ruleset if we need it.
  4128. * We need to do this because of late parsing of values
  4129. */
  4130. if (Array.isArray(rules)) {
  4131. rules = new Ruleset([new Selector()], rules);
  4132. }
  4133. if (name === '') {
  4134. rules = rules.lastDeclaration();
  4135. }
  4136. else if (name.charAt(0) === '@') {
  4137. if (name.charAt(1) === '@') {
  4138. name = "@" + new Variable(name.substr(1)).eval(context).value;
  4139. }
  4140. if (rules.variables) {
  4141. rules = rules.variable(name);
  4142. }
  4143. if (!rules) {
  4144. throw { type: 'Name',
  4145. message: "variable " + name + " not found",
  4146. filename: this.fileInfo().filename,
  4147. index: this.getIndex() };
  4148. }
  4149. }
  4150. else {
  4151. if (name.substring(0, 2) === '$@') {
  4152. name = "$" + new Variable(name.substr(1)).eval(context).value;
  4153. }
  4154. else {
  4155. name = name.charAt(0) === '$' ? name : "$" + name;
  4156. }
  4157. if (rules.properties) {
  4158. rules = rules.property(name);
  4159. }
  4160. if (!rules) {
  4161. throw { type: 'Name',
  4162. message: "property \"" + name.substr(1) + "\" not found",
  4163. filename: this.fileInfo().filename,
  4164. index: this.getIndex() };
  4165. }
  4166. // Properties are an array of values, since a ruleset can have multiple props.
  4167. // We pick the last one (the "cascaded" value)
  4168. rules = rules[rules.length - 1];
  4169. }
  4170. if (rules.value) {
  4171. rules = rules.eval(context).value;
  4172. }
  4173. if (rules.ruleset) {
  4174. rules = rules.ruleset.eval(context);
  4175. }
  4176. }
  4177. return rules;
  4178. };
  4179. return NamespaceValue;
  4180. }(Node));
  4181. NamespaceValue.prototype.type = 'NamespaceValue';
  4182. var Definition = /** @class */ (function (_super) {
  4183. tslib.__extends(Definition, _super);
  4184. function Definition(name, params, rules, condition, variadic, frames, visibilityInfo) {
  4185. var _this = _super.call(this) || this;
  4186. _this.name = name || 'anonymous mixin';
  4187. _this.selectors = [new Selector([new Element(null, name, false, _this._index, _this._fileInfo)])];
  4188. _this.params = params;
  4189. _this.condition = condition;
  4190. _this.variadic = variadic;
  4191. _this.arity = params.length;
  4192. _this.rules = rules;
  4193. _this._lookups = {};
  4194. var optionalParameters = [];
  4195. _this.required = params.reduce(function (count, p) {
  4196. if (!p.name || (p.name && !p.value)) {
  4197. return count + 1;
  4198. }
  4199. else {
  4200. optionalParameters.push(p.name);
  4201. return count;
  4202. }
  4203. }, 0);
  4204. _this.optionalParameters = optionalParameters;
  4205. _this.frames = frames;
  4206. _this.copyVisibilityInfo(visibilityInfo);
  4207. _this.allowRoot = true;
  4208. return _this;
  4209. }
  4210. Definition.prototype.accept = function (visitor) {
  4211. if (this.params && this.params.length) {
  4212. this.params = visitor.visitArray(this.params);
  4213. }
  4214. this.rules = visitor.visitArray(this.rules);
  4215. if (this.condition) {
  4216. this.condition = visitor.visit(this.condition);
  4217. }
  4218. };
  4219. Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArguments) {
  4220. /* jshint boss:true */
  4221. var frame = new Ruleset(null, null);
  4222. var varargs;
  4223. var arg;
  4224. var params = copyArray(this.params);
  4225. var i;
  4226. var j;
  4227. var val;
  4228. var name;
  4229. var isNamedFound;
  4230. var argIndex;
  4231. var argsLength = 0;
  4232. if (mixinEnv.frames && mixinEnv.frames[0] && mixinEnv.frames[0].functionRegistry) {
  4233. frame.functionRegistry = mixinEnv.frames[0].functionRegistry.inherit();
  4234. }
  4235. mixinEnv = new contexts.Eval(mixinEnv, [frame].concat(mixinEnv.frames));
  4236. if (args) {
  4237. args = copyArray(args);
  4238. argsLength = args.length;
  4239. for (i = 0; i < argsLength; i++) {
  4240. arg = args[i];
  4241. if (name = (arg && arg.name)) {
  4242. isNamedFound = false;
  4243. for (j = 0; j < params.length; j++) {
  4244. if (!evaldArguments[j] && name === params[j].name) {
  4245. evaldArguments[j] = arg.value.eval(context);
  4246. frame.prependRule(new Declaration(name, arg.value.eval(context)));
  4247. isNamedFound = true;
  4248. break;
  4249. }
  4250. }
  4251. if (isNamedFound) {
  4252. args.splice(i, 1);
  4253. i--;
  4254. continue;
  4255. }
  4256. else {
  4257. throw { type: 'Runtime', message: "Named argument for " + this.name + " " + args[i].name + " not found" };
  4258. }
  4259. }
  4260. }
  4261. }
  4262. argIndex = 0;
  4263. for (i = 0; i < params.length; i++) {
  4264. if (evaldArguments[i]) {
  4265. continue;
  4266. }
  4267. arg = args && args[argIndex];
  4268. if (name = params[i].name) {
  4269. if (params[i].variadic) {
  4270. varargs = [];
  4271. for (j = argIndex; j < argsLength; j++) {
  4272. varargs.push(args[j].value.eval(context));
  4273. }
  4274. frame.prependRule(new Declaration(name, new Expression(varargs).eval(context)));
  4275. }
  4276. else {
  4277. val = arg && arg.value;
  4278. if (val) {
  4279. // This was a mixin call, pass in a detached ruleset of it's eval'd rules
  4280. if (Array.isArray(val)) {
  4281. val = new DetachedRuleset(new Ruleset('', val));
  4282. }
  4283. else {
  4284. val = val.eval(context);
  4285. }
  4286. }
  4287. else if (params[i].value) {
  4288. val = params[i].value.eval(mixinEnv);
  4289. frame.resetCache();
  4290. }
  4291. else {
  4292. throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + " (" + argsLength + " for " + this.arity + ")" };
  4293. }
  4294. frame.prependRule(new Declaration(name, val));
  4295. evaldArguments[i] = val;
  4296. }
  4297. }
  4298. if (params[i].variadic && args) {
  4299. for (j = argIndex; j < argsLength; j++) {
  4300. evaldArguments[j] = args[j].value.eval(context);
  4301. }
  4302. }
  4303. argIndex++;
  4304. }
  4305. return frame;
  4306. };
  4307. Definition.prototype.makeImportant = function () {
  4308. var rules = !this.rules ? this.rules : this.rules.map(function (r) {
  4309. if (r.makeImportant) {
  4310. return r.makeImportant(true);
  4311. }
  4312. else {
  4313. return r;
  4314. }
  4315. });
  4316. var result = new Definition(this.name, this.params, rules, this.condition, this.variadic, this.frames);
  4317. return result;
  4318. };
  4319. Definition.prototype.eval = function (context) {
  4320. return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || copyArray(context.frames));
  4321. };
  4322. Definition.prototype.evalCall = function (context, args, important) {
  4323. var _arguments = [];
  4324. var mixinFrames = this.frames ? this.frames.concat(context.frames) : context.frames;
  4325. var frame = this.evalParams(context, new contexts.Eval(context, mixinFrames), args, _arguments);
  4326. var rules;
  4327. var ruleset;
  4328. frame.prependRule(new Declaration('@arguments', new Expression(_arguments).eval(context)));
  4329. rules = copyArray(this.rules);
  4330. ruleset = new Ruleset(null, rules);
  4331. ruleset.originalRuleset = this;
  4332. ruleset = ruleset.eval(new contexts.Eval(context, [this, frame].concat(mixinFrames)));
  4333. if (important) {
  4334. ruleset = ruleset.makeImportant();
  4335. }
  4336. return ruleset;
  4337. };
  4338. Definition.prototype.matchCondition = function (args, context) {
  4339. if (this.condition && !this.condition.eval(new contexts.Eval(context, [this.evalParams(context, /* the parameter variables */ new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
  4340. .concat(this.frames || []) // the parent namespace/mixin frames
  4341. .concat(context.frames)))) { // the current environment frames
  4342. return false;
  4343. }
  4344. return true;
  4345. };
  4346. Definition.prototype.matchArgs = function (args, context) {
  4347. var allArgsCnt = (args && args.length) || 0;
  4348. var len;
  4349. var optionalParameters = this.optionalParameters;
  4350. var requiredArgsCnt = !args ? 0 : args.reduce(function (count, p) {
  4351. if (optionalParameters.indexOf(p.name) < 0) {
  4352. return count + 1;
  4353. }
  4354. else {
  4355. return count;
  4356. }
  4357. }, 0);
  4358. if (!this.variadic) {
  4359. if (requiredArgsCnt < this.required) {
  4360. return false;
  4361. }
  4362. if (allArgsCnt > this.params.length) {
  4363. return false;
  4364. }
  4365. }
  4366. else {
  4367. if (requiredArgsCnt < (this.required - 1)) {
  4368. return false;
  4369. }
  4370. }
  4371. // check patterns
  4372. len = Math.min(requiredArgsCnt, this.arity);
  4373. for (var i_1 = 0; i_1 < len; i_1++) {
  4374. if (!this.params[i_1].name && !this.params[i_1].variadic) {
  4375. if (args[i_1].value.eval(context).toCSS() != this.params[i_1].value.eval(context).toCSS()) {
  4376. return false;
  4377. }
  4378. }
  4379. }
  4380. return true;
  4381. };
  4382. return Definition;
  4383. }(Ruleset));
  4384. Definition.prototype.type = 'MixinDefinition';
  4385. Definition.prototype.evalFirst = true;
  4386. var MixinCall = /** @class */ (function (_super) {
  4387. tslib.__extends(MixinCall, _super);
  4388. function MixinCall(elements, args, index, currentFileInfo, important) {
  4389. var _this = _super.call(this) || this;
  4390. _this.selector = new Selector(elements);
  4391. _this.arguments = args || [];
  4392. _this._index = index;
  4393. _this._fileInfo = currentFileInfo;
  4394. _this.important = important;
  4395. _this.allowRoot = true;
  4396. _this.setParent(_this.selector, _this);
  4397. return _this;
  4398. }
  4399. MixinCall.prototype.accept = function (visitor) {
  4400. if (this.selector) {
  4401. this.selector = visitor.visit(this.selector);
  4402. }
  4403. if (this.arguments.length) {
  4404. this.arguments = visitor.visitArray(this.arguments);
  4405. }
  4406. };
  4407. MixinCall.prototype.eval = function (context) {
  4408. var mixins;
  4409. var mixin;
  4410. var mixinPath;
  4411. var args = [];
  4412. var arg;
  4413. var argValue;
  4414. var rules = [];
  4415. var match = false;
  4416. var i;
  4417. var m;
  4418. var f;
  4419. var isRecursive;
  4420. var isOneFound;
  4421. var candidates = [];
  4422. var candidate;
  4423. var conditionResult = [];
  4424. var defaultResult;
  4425. var defFalseEitherCase = -1;
  4426. var defNone = 0;
  4427. var defTrue = 1;
  4428. var defFalse = 2;
  4429. var count;
  4430. var originalRuleset;
  4431. var noArgumentsFilter;
  4432. this.selector = this.selector.eval(context);
  4433. function calcDefGroup(mixin, mixinPath) {
  4434. var f;
  4435. var p;
  4436. var namespace;
  4437. for (f = 0; f < 2; f++) {
  4438. conditionResult[f] = true;
  4439. defaultFunc.value(f);
  4440. for (p = 0; p < mixinPath.length && conditionResult[f]; p++) {
  4441. namespace = mixinPath[p];
  4442. if (namespace.matchCondition) {
  4443. conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, context);
  4444. }
  4445. }
  4446. if (mixin.matchCondition) {
  4447. conditionResult[f] = conditionResult[f] && mixin.matchCondition(args, context);
  4448. }
  4449. }
  4450. if (conditionResult[0] || conditionResult[1]) {
  4451. if (conditionResult[0] != conditionResult[1]) {
  4452. return conditionResult[1] ?
  4453. defTrue : defFalse;
  4454. }
  4455. return defNone;
  4456. }
  4457. return defFalseEitherCase;
  4458. }
  4459. for (i = 0; i < this.arguments.length; i++) {
  4460. arg = this.arguments[i];
  4461. argValue = arg.value.eval(context);
  4462. if (arg.expand && Array.isArray(argValue.value)) {
  4463. argValue = argValue.value;
  4464. for (m = 0; m < argValue.length; m++) {
  4465. args.push({ value: argValue[m] });
  4466. }
  4467. }
  4468. else {
  4469. args.push({ name: arg.name, value: argValue });
  4470. }
  4471. }
  4472. noArgumentsFilter = function (rule) { return rule.matchArgs(null, context); };
  4473. for (i = 0; i < context.frames.length; i++) {
  4474. if ((mixins = context.frames[i].find(this.selector, null, noArgumentsFilter)).length > 0) {
  4475. isOneFound = true;
  4476. // To make `default()` function independent of definition order we have two "subpasses" here.
  4477. // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
  4478. // and build candidate list with corresponding flags. Then, when we know all possible matches,
  4479. // we make a final decision.
  4480. for (m = 0; m < mixins.length; m++) {
  4481. mixin = mixins[m].rule;
  4482. mixinPath = mixins[m].path;
  4483. isRecursive = false;
  4484. for (f = 0; f < context.frames.length; f++) {
  4485. if ((!(mixin instanceof Definition)) && mixin === (context.frames[f].originalRuleset || context.frames[f])) {
  4486. isRecursive = true;
  4487. break;
  4488. }
  4489. }
  4490. if (isRecursive) {
  4491. continue;
  4492. }
  4493. if (mixin.matchArgs(args, context)) {
  4494. candidate = { mixin: mixin, group: calcDefGroup(mixin, mixinPath) };
  4495. if (candidate.group !== defFalseEitherCase) {
  4496. candidates.push(candidate);
  4497. }
  4498. match = true;
  4499. }
  4500. }
  4501. defaultFunc.reset();
  4502. count = [0, 0, 0];
  4503. for (m = 0; m < candidates.length; m++) {
  4504. count[candidates[m].group]++;
  4505. }
  4506. if (count[defNone] > 0) {
  4507. defaultResult = defFalse;
  4508. }
  4509. else {
  4510. defaultResult = defTrue;
  4511. if ((count[defTrue] + count[defFalse]) > 1) {
  4512. throw { type: 'Runtime',
  4513. message: "Ambiguous use of `default()` found when matching for `" + this.format(args) + "`",
  4514. index: this.getIndex(), filename: this.fileInfo().filename };
  4515. }
  4516. }
  4517. for (m = 0; m < candidates.length; m++) {
  4518. candidate = candidates[m].group;
  4519. if ((candidate === defNone) || (candidate === defaultResult)) {
  4520. try {
  4521. mixin = candidates[m].mixin;
  4522. if (!(mixin instanceof Definition)) {
  4523. originalRuleset = mixin.originalRuleset || mixin;
  4524. mixin = new Definition('', [], mixin.rules, null, false, null, originalRuleset.visibilityInfo());
  4525. mixin.originalRuleset = originalRuleset;
  4526. }
  4527. var newRules = mixin.evalCall(context, args, this.important).rules;
  4528. this._setVisibilityToReplacement(newRules);
  4529. Array.prototype.push.apply(rules, newRules);
  4530. }
  4531. catch (e) {
  4532. throw { message: e.message, index: this.getIndex(), filename: this.fileInfo().filename, stack: e.stack };
  4533. }
  4534. }
  4535. }
  4536. if (match) {
  4537. return rules;
  4538. }
  4539. }
  4540. }
  4541. if (isOneFound) {
  4542. throw { type: 'Runtime',
  4543. message: "No matching definition was found for `" + this.format(args) + "`",
  4544. index: this.getIndex(), filename: this.fileInfo().filename };
  4545. }
  4546. else {
  4547. throw { type: 'Name',
  4548. message: this.selector.toCSS().trim() + " is undefined",
  4549. index: this.getIndex(), filename: this.fileInfo().filename };
  4550. }
  4551. };
  4552. MixinCall.prototype._setVisibilityToReplacement = function (replacement) {
  4553. var i;
  4554. var rule;
  4555. if (this.blocksVisibility()) {
  4556. for (i = 0; i < replacement.length; i++) {
  4557. rule = replacement[i];
  4558. rule.addVisibilityBlock();
  4559. }
  4560. }
  4561. };
  4562. MixinCall.prototype.format = function (args) {
  4563. return this.selector.toCSS().trim() + "(" + (args ? args.map(function (a) {
  4564. var argValue = '';
  4565. if (a.name) {
  4566. argValue += a.name + ":";
  4567. }
  4568. if (a.value.toCSS) {
  4569. argValue += a.value.toCSS();
  4570. }
  4571. else {
  4572. argValue += '???';
  4573. }
  4574. return argValue;
  4575. }).join(', ') : '') + ")";
  4576. };
  4577. return MixinCall;
  4578. }(Node));
  4579. MixinCall.prototype.type = 'MixinCall';
  4580. var tree = {
  4581. Node: Node, Color: Color, AtRule: AtRule, DetachedRuleset: DetachedRuleset, Operation: Operation,
  4582. Dimension: Dimension, Unit: Unit, Keyword: Keyword, Variable: Variable, Property: Property,
  4583. Ruleset: Ruleset, Element: Element, Attribute: Attribute, Combinator: Combinator, Selector: Selector,
  4584. Quoted: Quoted, Expression: Expression, Declaration: Declaration, Call: Call, URL: URL, Import: Import,
  4585. Comment: Comment, Anonymous: Anonymous, Value: Value, JavaScript: JavaScript, Assignment: Assignment,
  4586. Condition: Condition, Paren: Paren, Media: Media, UnicodeDescriptor: UnicodeDescriptor, Negative: Negative,
  4587. Extend: Extend, VariableCall: VariableCall, NamespaceValue: NamespaceValue,
  4588. mixin: {
  4589. Call: MixinCall,
  4590. Definition: Definition
  4591. }
  4592. };
  4593. /**
  4594. * @todo Document why this abstraction exists, and the relationship between
  4595. * environment, file managers, and plugin manager
  4596. */
  4597. var environment$1 = /** @class */ (function () {
  4598. function environment(externalEnvironment, fileManagers) {
  4599. this.fileManagers = fileManagers || [];
  4600. externalEnvironment = externalEnvironment || {};
  4601. var optionalFunctions = ['encodeBase64', 'mimeLookup', 'charsetLookup', 'getSourceMapGenerator'];
  4602. var requiredFunctions = [];
  4603. var functions = requiredFunctions.concat(optionalFunctions);
  4604. for (var i_1 = 0; i_1 < functions.length; i_1++) {
  4605. var propName = functions[i_1];
  4606. var environmentFunc = externalEnvironment[propName];
  4607. if (environmentFunc) {
  4608. this[propName] = environmentFunc.bind(externalEnvironment);
  4609. }
  4610. else if (i_1 < requiredFunctions.length) {
  4611. this.warn("missing required function in environment - " + propName);
  4612. }
  4613. }
  4614. }
  4615. environment.prototype.getFileManager = function (filename, currentDirectory, options, environment, isSync) {
  4616. if (!filename) {
  4617. logger.warn('getFileManager called with no filename.. Please report this issue. continuing.');
  4618. }
  4619. if (currentDirectory == null) {
  4620. logger.warn('getFileManager called with null directory.. Please report this issue. continuing.');
  4621. }
  4622. var fileManagers = this.fileManagers;
  4623. if (options.pluginManager) {
  4624. fileManagers = [].concat(fileManagers).concat(options.pluginManager.getFileManagers());
  4625. }
  4626. for (var i_2 = fileManagers.length - 1; i_2 >= 0; i_2--) {
  4627. var fileManager = fileManagers[i_2];
  4628. if (fileManager[isSync ? 'supportsSync' : 'supports'](filename, currentDirectory, options, environment)) {
  4629. return fileManager;
  4630. }
  4631. }
  4632. return null;
  4633. };
  4634. environment.prototype.addFileManager = function (fileManager) {
  4635. this.fileManagers.push(fileManager);
  4636. };
  4637. environment.prototype.clearFileManagers = function () {
  4638. this.fileManagers = [];
  4639. };
  4640. return environment;
  4641. }());
  4642. var AbstractPluginLoader = /** @class */ (function () {
  4643. function AbstractPluginLoader() {
  4644. // Implemented by Node.js plugin loader
  4645. this.require = function () { return null; };
  4646. }
  4647. AbstractPluginLoader.prototype.evalPlugin = function (contents, context, imports, pluginOptions, fileInfo) {
  4648. var loader;
  4649. var registry;
  4650. var pluginObj;
  4651. var localModule;
  4652. var pluginManager;
  4653. var filename;
  4654. var result;
  4655. pluginManager = context.pluginManager;
  4656. if (fileInfo) {
  4657. if (typeof fileInfo === 'string') {
  4658. filename = fileInfo;
  4659. }
  4660. else {
  4661. filename = fileInfo.filename;
  4662. }
  4663. }
  4664. var shortname = (new this.less.FileManager()).extractUrlParts(filename).filename;
  4665. if (filename) {
  4666. pluginObj = pluginManager.get(filename);
  4667. if (pluginObj) {
  4668. result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
  4669. if (result) {
  4670. return result;
  4671. }
  4672. try {
  4673. if (pluginObj.use) {
  4674. pluginObj.use.call(this.context, pluginObj);
  4675. }
  4676. }
  4677. catch (e) {
  4678. e.message = e.message || 'Error during @plugin call';
  4679. return new LessError(e, imports, filename);
  4680. }
  4681. return pluginObj;
  4682. }
  4683. }
  4684. localModule = {
  4685. exports: {},
  4686. pluginManager: pluginManager,
  4687. fileInfo: fileInfo
  4688. };
  4689. registry = functionRegistry.create();
  4690. var registerPlugin = function (obj) {
  4691. pluginObj = obj;
  4692. };
  4693. try {
  4694. loader = new Function('module', 'require', 'registerPlugin', 'functions', 'tree', 'less', 'fileInfo', contents);
  4695. loader(localModule, this.require(filename), registerPlugin, registry, this.less.tree, this.less, fileInfo);
  4696. }
  4697. catch (e) {
  4698. return new LessError(e, imports, filename);
  4699. }
  4700. if (!pluginObj) {
  4701. pluginObj = localModule.exports;
  4702. }
  4703. pluginObj = this.validatePlugin(pluginObj, filename, shortname);
  4704. if (pluginObj instanceof LessError) {
  4705. return pluginObj;
  4706. }
  4707. if (pluginObj) {
  4708. pluginObj.imports = imports;
  4709. pluginObj.filename = filename;
  4710. // For < 3.x (or unspecified minVersion) - setOptions() before install()
  4711. if (!pluginObj.minVersion || this.compareVersion('3.0.0', pluginObj.minVersion) < 0) {
  4712. result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
  4713. if (result) {
  4714. return result;
  4715. }
  4716. }
  4717. // Run on first load
  4718. pluginManager.addPlugin(pluginObj, fileInfo.filename, registry);
  4719. pluginObj.functions = registry.getLocalFunctions();
  4720. // Need to call setOptions again because the pluginObj might have functions
  4721. result = this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
  4722. if (result) {
  4723. return result;
  4724. }
  4725. // Run every @plugin call
  4726. try {
  4727. if (pluginObj.use) {
  4728. pluginObj.use.call(this.context, pluginObj);
  4729. }
  4730. }
  4731. catch (e) {
  4732. e.message = e.message || 'Error during @plugin call';
  4733. return new LessError(e, imports, filename);
  4734. }
  4735. }
  4736. else {
  4737. return new LessError({ message: 'Not a valid plugin' }, imports, filename);
  4738. }
  4739. return pluginObj;
  4740. };
  4741. AbstractPluginLoader.prototype.trySetOptions = function (plugin, filename, name, options) {
  4742. if (options && !plugin.setOptions) {
  4743. return new LessError({
  4744. message: "Options have been provided but the plugin " + name + " does not support any options."
  4745. });
  4746. }
  4747. try {
  4748. plugin.setOptions && plugin.setOptions(options);
  4749. }
  4750. catch (e) {
  4751. return new LessError(e);
  4752. }
  4753. };
  4754. AbstractPluginLoader.prototype.validatePlugin = function (plugin, filename, name) {
  4755. if (plugin) {
  4756. // support plugins being a function
  4757. // so that the plugin can be more usable programmatically
  4758. if (typeof plugin === 'function') {
  4759. plugin = new plugin();
  4760. }
  4761. if (plugin.minVersion) {
  4762. if (this.compareVersion(plugin.minVersion, this.less.version) < 0) {
  4763. return new LessError({
  4764. message: "Plugin " + name + " requires version " + this.versionToString(plugin.minVersion)
  4765. });
  4766. }
  4767. }
  4768. return plugin;
  4769. }
  4770. return null;
  4771. };
  4772. AbstractPluginLoader.prototype.compareVersion = function (aVersion, bVersion) {
  4773. if (typeof aVersion === 'string') {
  4774. aVersion = aVersion.match(/^(\d+)\.?(\d+)?\.?(\d+)?/);
  4775. aVersion.shift();
  4776. }
  4777. for (var i_1 = 0; i_1 < aVersion.length; i_1++) {
  4778. if (aVersion[i_1] !== bVersion[i_1]) {
  4779. return parseInt(aVersion[i_1]) > parseInt(bVersion[i_1]) ? -1 : 1;
  4780. }
  4781. }
  4782. return 0;
  4783. };
  4784. AbstractPluginLoader.prototype.versionToString = function (version) {
  4785. var versionString = '';
  4786. for (var i_2 = 0; i_2 < version.length; i_2++) {
  4787. versionString += (versionString ? '.' : '') + version[i_2];
  4788. }
  4789. return versionString;
  4790. };
  4791. AbstractPluginLoader.prototype.printUsage = function (plugins) {
  4792. for (var i_3 = 0; i_3 < plugins.length; i_3++) {
  4793. var plugin = plugins[i_3];
  4794. if (plugin.printUsage) {
  4795. plugin.printUsage();
  4796. }
  4797. }
  4798. };
  4799. return AbstractPluginLoader;
  4800. }());
  4801. var _visitArgs = { visitDeeper: true };
  4802. var _hasIndexed = false;
  4803. function _noop(node) {
  4804. return node;
  4805. }
  4806. function indexNodeTypes(parent, ticker) {
  4807. // add .typeIndex to tree node types for lookup table
  4808. var key;
  4809. var child;
  4810. for (key in parent) {
  4811. /* eslint guard-for-in: 0 */
  4812. child = parent[key];
  4813. switch (typeof child) {
  4814. case 'function':
  4815. // ignore bound functions directly on tree which do not have a prototype
  4816. // or aren't nodes
  4817. if (child.prototype && child.prototype.type) {
  4818. child.prototype.typeIndex = ticker++;
  4819. }
  4820. break;
  4821. case 'object':
  4822. ticker = indexNodeTypes(child, ticker);
  4823. break;
  4824. }
  4825. }
  4826. return ticker;
  4827. }
  4828. var Visitor = /** @class */ (function () {
  4829. function Visitor(implementation) {
  4830. this._implementation = implementation;
  4831. this._visitInCache = {};
  4832. this._visitOutCache = {};
  4833. if (!_hasIndexed) {
  4834. indexNodeTypes(tree, 1);
  4835. _hasIndexed = true;
  4836. }
  4837. }
  4838. Visitor.prototype.visit = function (node) {
  4839. if (!node) {
  4840. return node;
  4841. }
  4842. var nodeTypeIndex = node.typeIndex;
  4843. if (!nodeTypeIndex) {
  4844. // MixinCall args aren't a node type?
  4845. if (node.value && node.value.typeIndex) {
  4846. this.visit(node.value);
  4847. }
  4848. return node;
  4849. }
  4850. var impl = this._implementation;
  4851. var func = this._visitInCache[nodeTypeIndex];
  4852. var funcOut = this._visitOutCache[nodeTypeIndex];
  4853. var visitArgs = _visitArgs;
  4854. var fnName;
  4855. visitArgs.visitDeeper = true;
  4856. if (!func) {
  4857. fnName = "visit" + node.type;
  4858. func = impl[fnName] || _noop;
  4859. funcOut = impl[fnName + "Out"] || _noop;
  4860. this._visitInCache[nodeTypeIndex] = func;
  4861. this._visitOutCache[nodeTypeIndex] = funcOut;
  4862. }
  4863. if (func !== _noop) {
  4864. var newNode = func.call(impl, node, visitArgs);
  4865. if (node && impl.isReplacing) {
  4866. node = newNode;
  4867. }
  4868. }
  4869. if (visitArgs.visitDeeper && node) {
  4870. if (node.length) {
  4871. for (var i = 0, cnt = node.length; i < cnt; i++) {
  4872. if (node[i].accept) {
  4873. node[i].accept(this);
  4874. }
  4875. }
  4876. }
  4877. else if (node.accept) {
  4878. node.accept(this);
  4879. }
  4880. }
  4881. if (funcOut != _noop) {
  4882. funcOut.call(impl, node);
  4883. }
  4884. return node;
  4885. };
  4886. Visitor.prototype.visitArray = function (nodes, nonReplacing) {
  4887. if (!nodes) {
  4888. return nodes;
  4889. }
  4890. var cnt = nodes.length;
  4891. var i;
  4892. // Non-replacing
  4893. if (nonReplacing || !this._implementation.isReplacing) {
  4894. for (i = 0; i < cnt; i++) {
  4895. this.visit(nodes[i]);
  4896. }
  4897. return nodes;
  4898. }
  4899. // Replacing
  4900. var out = [];
  4901. for (i = 0; i < cnt; i++) {
  4902. var evald = this.visit(nodes[i]);
  4903. if (evald === undefined) {
  4904. continue;
  4905. }
  4906. if (!evald.splice) {
  4907. out.push(evald);
  4908. }
  4909. else if (evald.length) {
  4910. this.flatten(evald, out);
  4911. }
  4912. }
  4913. return out;
  4914. };
  4915. Visitor.prototype.flatten = function (arr, out) {
  4916. if (!out) {
  4917. out = [];
  4918. }
  4919. var cnt;
  4920. var i;
  4921. var item;
  4922. var nestedCnt;
  4923. var j;
  4924. var nestedItem;
  4925. for (i = 0, cnt = arr.length; i < cnt; i++) {
  4926. item = arr[i];
  4927. if (item === undefined) {
  4928. continue;
  4929. }
  4930. if (!item.splice) {
  4931. out.push(item);
  4932. continue;
  4933. }
  4934. for (j = 0, nestedCnt = item.length; j < nestedCnt; j++) {
  4935. nestedItem = item[j];
  4936. if (nestedItem === undefined) {
  4937. continue;
  4938. }
  4939. if (!nestedItem.splice) {
  4940. out.push(nestedItem);
  4941. }
  4942. else if (nestedItem.length) {
  4943. this.flatten(nestedItem, out);
  4944. }
  4945. }
  4946. }
  4947. return out;
  4948. };
  4949. return Visitor;
  4950. }());
  4951. var ImportSequencer = /** @class */ (function () {
  4952. function ImportSequencer(onSequencerEmpty) {
  4953. this.imports = [];
  4954. this.variableImports = [];
  4955. this._onSequencerEmpty = onSequencerEmpty;
  4956. this._currentDepth = 0;
  4957. }
  4958. ImportSequencer.prototype.addImport = function (callback) {
  4959. var importSequencer = this;
  4960. var importItem = {
  4961. callback: callback,
  4962. args: null,
  4963. isReady: false
  4964. };
  4965. this.imports.push(importItem);
  4966. return function () {
  4967. var args = [];
  4968. for (var _i = 0; _i < arguments.length; _i++) {
  4969. args[_i] = arguments[_i];
  4970. }
  4971. importItem.args = Array.prototype.slice.call(args, 0);
  4972. importItem.isReady = true;
  4973. importSequencer.tryRun();
  4974. };
  4975. };
  4976. ImportSequencer.prototype.addVariableImport = function (callback) {
  4977. this.variableImports.push(callback);
  4978. };
  4979. ImportSequencer.prototype.tryRun = function () {
  4980. this._currentDepth++;
  4981. try {
  4982. while (true) {
  4983. while (this.imports.length > 0) {
  4984. var importItem = this.imports[0];
  4985. if (!importItem.isReady) {
  4986. return;
  4987. }
  4988. this.imports = this.imports.slice(1);
  4989. importItem.callback.apply(null, importItem.args);
  4990. }
  4991. if (this.variableImports.length === 0) {
  4992. break;
  4993. }
  4994. var variableImport = this.variableImports[0];
  4995. this.variableImports = this.variableImports.slice(1);
  4996. variableImport();
  4997. }
  4998. }
  4999. finally {
  5000. this._currentDepth--;
  5001. }
  5002. if (this._currentDepth === 0 && this._onSequencerEmpty) {
  5003. this._onSequencerEmpty();
  5004. }
  5005. };
  5006. return ImportSequencer;
  5007. }());
  5008. var ImportVisitor = function (importer, finish) {
  5009. this._visitor = new Visitor(this);
  5010. this._importer = importer;
  5011. this._finish = finish;
  5012. this.context = new contexts.Eval();
  5013. this.importCount = 0;
  5014. this.onceFileDetectionMap = {};
  5015. this.recursionDetector = {};
  5016. this._sequencer = new ImportSequencer(this._onSequencerEmpty.bind(this));
  5017. };
  5018. ImportVisitor.prototype = {
  5019. isReplacing: false,
  5020. run: function (root) {
  5021. try {
  5022. // process the contents
  5023. this._visitor.visit(root);
  5024. }
  5025. catch (e) {
  5026. this.error = e;
  5027. }
  5028. this.isFinished = true;
  5029. this._sequencer.tryRun();
  5030. },
  5031. _onSequencerEmpty: function () {
  5032. if (!this.isFinished) {
  5033. return;
  5034. }
  5035. this._finish(this.error);
  5036. },
  5037. visitImport: function (importNode, visitArgs) {
  5038. var inlineCSS = importNode.options.inline;
  5039. if (!importNode.css || inlineCSS) {
  5040. var context = new contexts.Eval(this.context, copyArray(this.context.frames));
  5041. var importParent = context.frames[0];
  5042. this.importCount++;
  5043. if (importNode.isVariableImport()) {
  5044. this._sequencer.addVariableImport(this.processImportNode.bind(this, importNode, context, importParent));
  5045. }
  5046. else {
  5047. this.processImportNode(importNode, context, importParent);
  5048. }
  5049. }
  5050. visitArgs.visitDeeper = false;
  5051. },
  5052. processImportNode: function (importNode, context, importParent) {
  5053. var evaldImportNode;
  5054. var inlineCSS = importNode.options.inline;
  5055. try {
  5056. evaldImportNode = importNode.evalForImport(context);
  5057. }
  5058. catch (e) {
  5059. if (!e.filename) {
  5060. e.index = importNode.getIndex();
  5061. e.filename = importNode.fileInfo().filename;
  5062. }
  5063. // attempt to eval properly and treat as css
  5064. importNode.css = true;
  5065. // if that fails, this error will be thrown
  5066. importNode.error = e;
  5067. }
  5068. if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
  5069. if (evaldImportNode.options.multiple) {
  5070. context.importMultiple = true;
  5071. }
  5072. // try appending if we haven't determined if it is css or not
  5073. var tryAppendLessExtension = evaldImportNode.css === undefined;
  5074. for (var i_1 = 0; i_1 < importParent.rules.length; i_1++) {
  5075. if (importParent.rules[i_1] === importNode) {
  5076. importParent.rules[i_1] = evaldImportNode;
  5077. break;
  5078. }
  5079. }
  5080. var onImported = this.onImported.bind(this, evaldImportNode, context);
  5081. var sequencedOnImported = this._sequencer.addImport(onImported);
  5082. this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.fileInfo(), evaldImportNode.options, sequencedOnImported);
  5083. }
  5084. else {
  5085. this.importCount--;
  5086. if (this.isFinished) {
  5087. this._sequencer.tryRun();
  5088. }
  5089. }
  5090. },
  5091. onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
  5092. if (e) {
  5093. if (!e.filename) {
  5094. e.index = importNode.getIndex();
  5095. e.filename = importNode.fileInfo().filename;
  5096. }
  5097. this.error = e;
  5098. }
  5099. var importVisitor = this;
  5100. var inlineCSS = importNode.options.inline;
  5101. var isPlugin = importNode.options.isPlugin;
  5102. var isOptional = importNode.options.optional;
  5103. var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
  5104. if (!context.importMultiple) {
  5105. if (duplicateImport) {
  5106. importNode.skip = true;
  5107. }
  5108. else {
  5109. importNode.skip = function () {
  5110. if (fullPath in importVisitor.onceFileDetectionMap) {
  5111. return true;
  5112. }
  5113. importVisitor.onceFileDetectionMap[fullPath] = true;
  5114. return false;
  5115. };
  5116. }
  5117. }
  5118. if (!fullPath && isOptional) {
  5119. importNode.skip = true;
  5120. }
  5121. if (root) {
  5122. importNode.root = root;
  5123. importNode.importedFilename = fullPath;
  5124. if (!inlineCSS && !isPlugin && (context.importMultiple || !duplicateImport)) {
  5125. importVisitor.recursionDetector[fullPath] = true;
  5126. var oldContext = this.context;
  5127. this.context = context;
  5128. try {
  5129. this._visitor.visit(root);
  5130. }
  5131. catch (e) {
  5132. this.error = e;
  5133. }
  5134. this.context = oldContext;
  5135. }
  5136. }
  5137. importVisitor.importCount--;
  5138. if (importVisitor.isFinished) {
  5139. importVisitor._sequencer.tryRun();
  5140. }
  5141. },
  5142. visitDeclaration: function (declNode, visitArgs) {
  5143. if (declNode.value.type === 'DetachedRuleset') {
  5144. this.context.frames.unshift(declNode);
  5145. }
  5146. else {
  5147. visitArgs.visitDeeper = false;
  5148. }
  5149. },
  5150. visitDeclarationOut: function (declNode) {
  5151. if (declNode.value.type === 'DetachedRuleset') {
  5152. this.context.frames.shift();
  5153. }
  5154. },
  5155. visitAtRule: function (atRuleNode, visitArgs) {
  5156. this.context.frames.unshift(atRuleNode);
  5157. },
  5158. visitAtRuleOut: function (atRuleNode) {
  5159. this.context.frames.shift();
  5160. },
  5161. visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
  5162. this.context.frames.unshift(mixinDefinitionNode);
  5163. },
  5164. visitMixinDefinitionOut: function (mixinDefinitionNode) {
  5165. this.context.frames.shift();
  5166. },
  5167. visitRuleset: function (rulesetNode, visitArgs) {
  5168. this.context.frames.unshift(rulesetNode);
  5169. },
  5170. visitRulesetOut: function (rulesetNode) {
  5171. this.context.frames.shift();
  5172. },
  5173. visitMedia: function (mediaNode, visitArgs) {
  5174. this.context.frames.unshift(mediaNode.rules[0]);
  5175. },
  5176. visitMediaOut: function (mediaNode) {
  5177. this.context.frames.shift();
  5178. }
  5179. };
  5180. var SetTreeVisibilityVisitor = /** @class */ (function () {
  5181. function SetTreeVisibilityVisitor(visible) {
  5182. this.visible = visible;
  5183. }
  5184. SetTreeVisibilityVisitor.prototype.run = function (root) {
  5185. this.visit(root);
  5186. };
  5187. SetTreeVisibilityVisitor.prototype.visitArray = function (nodes) {
  5188. if (!nodes) {
  5189. return nodes;
  5190. }
  5191. var cnt = nodes.length;
  5192. var i;
  5193. for (i = 0; i < cnt; i++) {
  5194. this.visit(nodes[i]);
  5195. }
  5196. return nodes;
  5197. };
  5198. SetTreeVisibilityVisitor.prototype.visit = function (node) {
  5199. if (!node) {
  5200. return node;
  5201. }
  5202. if (node.constructor === Array) {
  5203. return this.visitArray(node);
  5204. }
  5205. if (!node.blocksVisibility || node.blocksVisibility()) {
  5206. return node;
  5207. }
  5208. if (this.visible) {
  5209. node.ensureVisibility();
  5210. }
  5211. else {
  5212. node.ensureInvisibility();
  5213. }
  5214. node.accept(this);
  5215. return node;
  5216. };
  5217. return SetTreeVisibilityVisitor;
  5218. }());
  5219. /* jshint loopfunc:true */
  5220. var ExtendFinderVisitor = /** @class */ (function () {
  5221. function ExtendFinderVisitor() {
  5222. this._visitor = new Visitor(this);
  5223. this.contexts = [];
  5224. this.allExtendsStack = [[]];
  5225. }
  5226. ExtendFinderVisitor.prototype.run = function (root) {
  5227. root = this._visitor.visit(root);
  5228. root.allExtends = this.allExtendsStack[0];
  5229. return root;
  5230. };
  5231. ExtendFinderVisitor.prototype.visitDeclaration = function (declNode, visitArgs) {
  5232. visitArgs.visitDeeper = false;
  5233. };
  5234. ExtendFinderVisitor.prototype.visitMixinDefinition = function (mixinDefinitionNode, visitArgs) {
  5235. visitArgs.visitDeeper = false;
  5236. };
  5237. ExtendFinderVisitor.prototype.visitRuleset = function (rulesetNode, visitArgs) {
  5238. if (rulesetNode.root) {
  5239. return;
  5240. }
  5241. var i;
  5242. var j;
  5243. var extend;
  5244. var allSelectorsExtendList = [];
  5245. var extendList;
  5246. // get &:extend(.a); rules which apply to all selectors in this ruleset
  5247. var rules = rulesetNode.rules;
  5248. var ruleCnt = rules ? rules.length : 0;
  5249. for (i = 0; i < ruleCnt; i++) {
  5250. if (rulesetNode.rules[i] instanceof tree.Extend) {
  5251. allSelectorsExtendList.push(rules[i]);
  5252. rulesetNode.extendOnEveryPath = true;
  5253. }
  5254. }
  5255. // now find every selector and apply the extends that apply to all extends
  5256. // and the ones which apply to an individual extend
  5257. var paths = rulesetNode.paths;
  5258. for (i = 0; i < paths.length; i++) {
  5259. var selectorPath = paths[i];
  5260. var selector = selectorPath[selectorPath.length - 1];
  5261. var selExtendList = selector.extendList;
  5262. extendList = selExtendList ? copyArray(selExtendList).concat(allSelectorsExtendList)
  5263. : allSelectorsExtendList;
  5264. if (extendList) {
  5265. extendList = extendList.map(function (allSelectorsExtend) { return allSelectorsExtend.clone(); });
  5266. }
  5267. for (j = 0; j < extendList.length; j++) {
  5268. this.foundExtends = true;
  5269. extend = extendList[j];
  5270. extend.findSelfSelectors(selectorPath);
  5271. extend.ruleset = rulesetNode;
  5272. if (j === 0) {
  5273. extend.firstExtendOnThisSelectorPath = true;
  5274. }
  5275. this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
  5276. }
  5277. }
  5278. this.contexts.push(rulesetNode.selectors);
  5279. };
  5280. ExtendFinderVisitor.prototype.visitRulesetOut = function (rulesetNode) {
  5281. if (!rulesetNode.root) {
  5282. this.contexts.length = this.contexts.length - 1;
  5283. }
  5284. };
  5285. ExtendFinderVisitor.prototype.visitMedia = function (mediaNode, visitArgs) {
  5286. mediaNode.allExtends = [];
  5287. this.allExtendsStack.push(mediaNode.allExtends);
  5288. };
  5289. ExtendFinderVisitor.prototype.visitMediaOut = function (mediaNode) {
  5290. this.allExtendsStack.length = this.allExtendsStack.length - 1;
  5291. };
  5292. ExtendFinderVisitor.prototype.visitAtRule = function (atRuleNode, visitArgs) {
  5293. atRuleNode.allExtends = [];
  5294. this.allExtendsStack.push(atRuleNode.allExtends);
  5295. };
  5296. ExtendFinderVisitor.prototype.visitAtRuleOut = function (atRuleNode) {
  5297. this.allExtendsStack.length = this.allExtendsStack.length - 1;
  5298. };
  5299. return ExtendFinderVisitor;
  5300. }());
  5301. var ProcessExtendsVisitor = /** @class */ (function () {
  5302. function ProcessExtendsVisitor() {
  5303. this._visitor = new Visitor(this);
  5304. }
  5305. ProcessExtendsVisitor.prototype.run = function (root) {
  5306. var extendFinder = new ExtendFinderVisitor();
  5307. this.extendIndices = {};
  5308. extendFinder.run(root);
  5309. if (!extendFinder.foundExtends) {
  5310. return root;
  5311. }
  5312. root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
  5313. this.allExtendsStack = [root.allExtends];
  5314. var newRoot = this._visitor.visit(root);
  5315. this.checkExtendsForNonMatched(root.allExtends);
  5316. return newRoot;
  5317. };
  5318. ProcessExtendsVisitor.prototype.checkExtendsForNonMatched = function (extendList) {
  5319. var indices = this.extendIndices;
  5320. extendList.filter(function (extend) { return !extend.hasFoundMatches && extend.parent_ids.length == 1; }).forEach(function (extend) {
  5321. var selector = '_unknown_';
  5322. try {
  5323. selector = extend.selector.toCSS({});
  5324. }
  5325. catch (_) { }
  5326. if (!indices[extend.index + " " + selector]) {
  5327. indices[extend.index + " " + selector] = true;
  5328. logger.warn("extend '" + selector + "' has no matches");
  5329. }
  5330. });
  5331. };
  5332. ProcessExtendsVisitor.prototype.doExtendChaining = function (extendsList, extendsListTarget, iterationCount) {
  5333. //
  5334. // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
  5335. // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
  5336. // this means this new extend can then go and alter other extends
  5337. //
  5338. // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
  5339. // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
  5340. // processed if we look at each selector at a time, as is done in visitRuleset
  5341. var extendIndex;
  5342. var targetExtendIndex;
  5343. var matches;
  5344. var extendsToAdd = [];
  5345. var newSelector;
  5346. var extendVisitor = this;
  5347. var selectorPath;
  5348. var extend;
  5349. var targetExtend;
  5350. var newExtend;
  5351. iterationCount = iterationCount || 0;
  5352. // loop through comparing every extend with every target extend.
  5353. // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
  5354. // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
  5355. // and the second is the target.
  5356. // the separation into two lists allows us to process a subset of chains with a bigger set, as is the
  5357. // case when processing media queries
  5358. for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) {
  5359. for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) {
  5360. extend = extendsList[extendIndex];
  5361. targetExtend = extendsListTarget[targetExtendIndex];
  5362. // look for circular references
  5363. if (extend.parent_ids.indexOf(targetExtend.object_id) >= 0) {
  5364. continue;
  5365. }
  5366. // find a match in the target extends self selector (the bit before :extend)
  5367. selectorPath = [targetExtend.selfSelectors[0]];
  5368. matches = extendVisitor.findMatch(extend, selectorPath);
  5369. if (matches.length) {
  5370. extend.hasFoundMatches = true;
  5371. // we found a match, so for each self selector..
  5372. extend.selfSelectors.forEach(function (selfSelector) {
  5373. var info = targetExtend.visibilityInfo();
  5374. // process the extend as usual
  5375. newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible());
  5376. // but now we create a new extend from it
  5377. newExtend = new (tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.fileInfo(), info);
  5378. newExtend.selfSelectors = newSelector;
  5379. // add the extend onto the list of extends for that selector
  5380. newSelector[newSelector.length - 1].extendList = [newExtend];
  5381. // record that we need to add it.
  5382. extendsToAdd.push(newExtend);
  5383. newExtend.ruleset = targetExtend.ruleset;
  5384. // remember its parents for circular references
  5385. newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
  5386. // only process the selector once.. if we have :extend(.a,.b) then multiple
  5387. // extends will look at the same selector path, so when extending
  5388. // we know that any others will be duplicates in terms of what is added to the css
  5389. if (targetExtend.firstExtendOnThisSelectorPath) {
  5390. newExtend.firstExtendOnThisSelectorPath = true;
  5391. targetExtend.ruleset.paths.push(newSelector);
  5392. }
  5393. });
  5394. }
  5395. }
  5396. }
  5397. if (extendsToAdd.length) {
  5398. // try to detect circular references to stop a stack overflow.
  5399. // may no longer be needed.
  5400. this.extendChainCount++;
  5401. if (iterationCount > 100) {
  5402. var selectorOne = '{unable to calculate}';
  5403. var selectorTwo = '{unable to calculate}';
  5404. try {
  5405. selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
  5406. selectorTwo = extendsToAdd[0].selector.toCSS();
  5407. }
  5408. catch (e) { }
  5409. throw { message: "extend circular reference detected. One of the circular extends is currently:" + selectorOne + ":extend(" + selectorTwo + ")" };
  5410. }
  5411. // now process the new extends on the existing rules so that we can handle a extending b extending c extending
  5412. // d extending e...
  5413. return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
  5414. }
  5415. else {
  5416. return extendsToAdd;
  5417. }
  5418. };
  5419. ProcessExtendsVisitor.prototype.visitDeclaration = function (ruleNode, visitArgs) {
  5420. visitArgs.visitDeeper = false;
  5421. };
  5422. ProcessExtendsVisitor.prototype.visitMixinDefinition = function (mixinDefinitionNode, visitArgs) {
  5423. visitArgs.visitDeeper = false;
  5424. };
  5425. ProcessExtendsVisitor.prototype.visitSelector = function (selectorNode, visitArgs) {
  5426. visitArgs.visitDeeper = false;
  5427. };
  5428. ProcessExtendsVisitor.prototype.visitRuleset = function (rulesetNode, visitArgs) {
  5429. if (rulesetNode.root) {
  5430. return;
  5431. }
  5432. var matches;
  5433. var pathIndex;
  5434. var extendIndex;
  5435. var allExtends = this.allExtendsStack[this.allExtendsStack.length - 1];
  5436. var selectorsToAdd = [];
  5437. var extendVisitor = this;
  5438. var selectorPath;
  5439. // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
  5440. for (extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
  5441. for (pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
  5442. selectorPath = rulesetNode.paths[pathIndex];
  5443. // extending extends happens initially, before the main pass
  5444. if (rulesetNode.extendOnEveryPath) {
  5445. continue;
  5446. }
  5447. var extendList = selectorPath[selectorPath.length - 1].extendList;
  5448. if (extendList && extendList.length) {
  5449. continue;
  5450. }
  5451. matches = this.findMatch(allExtends[extendIndex], selectorPath);
  5452. if (matches.length) {
  5453. allExtends[extendIndex].hasFoundMatches = true;
  5454. allExtends[extendIndex].selfSelectors.forEach(function (selfSelector) {
  5455. var extendedSelectors;
  5456. extendedSelectors = extendVisitor.extendSelector(matches, selectorPath, selfSelector, allExtends[extendIndex].isVisible());
  5457. selectorsToAdd.push(extendedSelectors);
  5458. });
  5459. }
  5460. }
  5461. }
  5462. rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
  5463. };
  5464. ProcessExtendsVisitor.prototype.findMatch = function (extend, haystackSelectorPath) {
  5465. //
  5466. // look through the haystack selector path to try and find the needle - extend.selector
  5467. // returns an array of selector matches that can then be replaced
  5468. //
  5469. var haystackSelectorIndex;
  5470. var hackstackSelector;
  5471. var hackstackElementIndex;
  5472. var haystackElement;
  5473. var targetCombinator;
  5474. var i;
  5475. var extendVisitor = this;
  5476. var needleElements = extend.selector.elements;
  5477. var potentialMatches = [];
  5478. var potentialMatch;
  5479. var matches = [];
  5480. // loop through the haystack elements
  5481. for (haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
  5482. hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
  5483. for (hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
  5484. haystackElement = hackstackSelector.elements[hackstackElementIndex];
  5485. // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
  5486. if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
  5487. potentialMatches.push({ pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
  5488. initialCombinator: haystackElement.combinator });
  5489. }
  5490. for (i = 0; i < potentialMatches.length; i++) {
  5491. potentialMatch = potentialMatches[i];
  5492. // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
  5493. // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
  5494. // work out what the resulting combinator will be
  5495. targetCombinator = haystackElement.combinator.value;
  5496. if (targetCombinator === '' && hackstackElementIndex === 0) {
  5497. targetCombinator = ' ';
  5498. }
  5499. // if we don't match, null our match to indicate failure
  5500. if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
  5501. (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
  5502. potentialMatch = null;
  5503. }
  5504. else {
  5505. potentialMatch.matched++;
  5506. }
  5507. // if we are still valid and have finished, test whether we have elements after and whether these are allowed
  5508. if (potentialMatch) {
  5509. potentialMatch.finished = potentialMatch.matched === needleElements.length;
  5510. if (potentialMatch.finished &&
  5511. (!extend.allowAfter &&
  5512. (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
  5513. potentialMatch = null;
  5514. }
  5515. }
  5516. // if null we remove, if not, we are still valid, so either push as a valid match or continue
  5517. if (potentialMatch) {
  5518. if (potentialMatch.finished) {
  5519. potentialMatch.length = needleElements.length;
  5520. potentialMatch.endPathIndex = haystackSelectorIndex;
  5521. potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
  5522. potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
  5523. matches.push(potentialMatch);
  5524. }
  5525. }
  5526. else {
  5527. potentialMatches.splice(i, 1);
  5528. i--;
  5529. }
  5530. }
  5531. }
  5532. }
  5533. return matches;
  5534. };
  5535. ProcessExtendsVisitor.prototype.isElementValuesEqual = function (elementValue1, elementValue2) {
  5536. if (typeof elementValue1 === 'string' || typeof elementValue2 === 'string') {
  5537. return elementValue1 === elementValue2;
  5538. }
  5539. if (elementValue1 instanceof tree.Attribute) {
  5540. if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
  5541. return false;
  5542. }
  5543. if (!elementValue1.value || !elementValue2.value) {
  5544. if (elementValue1.value || elementValue2.value) {
  5545. return false;
  5546. }
  5547. return true;
  5548. }
  5549. elementValue1 = elementValue1.value.value || elementValue1.value;
  5550. elementValue2 = elementValue2.value.value || elementValue2.value;
  5551. return elementValue1 === elementValue2;
  5552. }
  5553. elementValue1 = elementValue1.value;
  5554. elementValue2 = elementValue2.value;
  5555. if (elementValue1 instanceof tree.Selector) {
  5556. if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
  5557. return false;
  5558. }
  5559. for (var i_1 = 0; i_1 < elementValue1.elements.length; i_1++) {
  5560. if (elementValue1.elements[i_1].combinator.value !== elementValue2.elements[i_1].combinator.value) {
  5561. if (i_1 !== 0 || (elementValue1.elements[i_1].combinator.value || ' ') !== (elementValue2.elements[i_1].combinator.value || ' ')) {
  5562. return false;
  5563. }
  5564. }
  5565. if (!this.isElementValuesEqual(elementValue1.elements[i_1].value, elementValue2.elements[i_1].value)) {
  5566. return false;
  5567. }
  5568. }
  5569. return true;
  5570. }
  5571. return false;
  5572. };
  5573. ProcessExtendsVisitor.prototype.extendSelector = function (matches, selectorPath, replacementSelector, isVisible) {
  5574. // for a set of matches, replace each match with the replacement selector
  5575. var currentSelectorPathIndex = 0;
  5576. var currentSelectorPathElementIndex = 0;
  5577. var path = [];
  5578. var matchIndex;
  5579. var selector;
  5580. var firstElement;
  5581. var match;
  5582. var newElements;
  5583. for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
  5584. match = matches[matchIndex];
  5585. selector = selectorPath[match.pathIndex];
  5586. firstElement = new tree.Element(match.initialCombinator, replacementSelector.elements[0].value, replacementSelector.elements[0].isVariable, replacementSelector.elements[0].getIndex(), replacementSelector.elements[0].fileInfo());
  5587. if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
  5588. path[path.length - 1].elements = path[path.length - 1]
  5589. .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
  5590. currentSelectorPathElementIndex = 0;
  5591. currentSelectorPathIndex++;
  5592. }
  5593. newElements = selector.elements
  5594. .slice(currentSelectorPathElementIndex, match.index)
  5595. .concat([firstElement])
  5596. .concat(replacementSelector.elements.slice(1));
  5597. if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
  5598. path[path.length - 1].elements =
  5599. path[path.length - 1].elements.concat(newElements);
  5600. }
  5601. else {
  5602. path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
  5603. path.push(new tree.Selector(newElements));
  5604. }
  5605. currentSelectorPathIndex = match.endPathIndex;
  5606. currentSelectorPathElementIndex = match.endPathElementIndex;
  5607. if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
  5608. currentSelectorPathElementIndex = 0;
  5609. currentSelectorPathIndex++;
  5610. }
  5611. }
  5612. if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
  5613. path[path.length - 1].elements = path[path.length - 1]
  5614. .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
  5615. currentSelectorPathIndex++;
  5616. }
  5617. path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
  5618. path = path.map(function (currentValue) {
  5619. // we can re-use elements here, because the visibility property matters only for selectors
  5620. var derived = currentValue.createDerived(currentValue.elements);
  5621. if (isVisible) {
  5622. derived.ensureVisibility();
  5623. }
  5624. else {
  5625. derived.ensureInvisibility();
  5626. }
  5627. return derived;
  5628. });
  5629. return path;
  5630. };
  5631. ProcessExtendsVisitor.prototype.visitMedia = function (mediaNode, visitArgs) {
  5632. var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
  5633. newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
  5634. this.allExtendsStack.push(newAllExtends);
  5635. };
  5636. ProcessExtendsVisitor.prototype.visitMediaOut = function (mediaNode) {
  5637. var lastIndex = this.allExtendsStack.length - 1;
  5638. this.allExtendsStack.length = lastIndex;
  5639. };
  5640. ProcessExtendsVisitor.prototype.visitAtRule = function (atRuleNode, visitArgs) {
  5641. var newAllExtends = atRuleNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
  5642. newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, atRuleNode.allExtends));
  5643. this.allExtendsStack.push(newAllExtends);
  5644. };
  5645. ProcessExtendsVisitor.prototype.visitAtRuleOut = function (atRuleNode) {
  5646. var lastIndex = this.allExtendsStack.length - 1;
  5647. this.allExtendsStack.length = lastIndex;
  5648. };
  5649. return ProcessExtendsVisitor;
  5650. }());
  5651. var JoinSelectorVisitor = /** @class */ (function () {
  5652. function JoinSelectorVisitor() {
  5653. this.contexts = [[]];
  5654. this._visitor = new Visitor(this);
  5655. }
  5656. JoinSelectorVisitor.prototype.run = function (root) {
  5657. return this._visitor.visit(root);
  5658. };
  5659. JoinSelectorVisitor.prototype.visitDeclaration = function (declNode, visitArgs) {
  5660. visitArgs.visitDeeper = false;
  5661. };
  5662. JoinSelectorVisitor.prototype.visitMixinDefinition = function (mixinDefinitionNode, visitArgs) {
  5663. visitArgs.visitDeeper = false;
  5664. };
  5665. JoinSelectorVisitor.prototype.visitRuleset = function (rulesetNode, visitArgs) {
  5666. var context = this.contexts[this.contexts.length - 1];
  5667. var paths = [];
  5668. var selectors;
  5669. this.contexts.push(paths);
  5670. if (!rulesetNode.root) {
  5671. selectors = rulesetNode.selectors;
  5672. if (selectors) {
  5673. selectors = selectors.filter(function (selector) { return selector.getIsOutput(); });
  5674. rulesetNode.selectors = selectors.length ? selectors : (selectors = null);
  5675. if (selectors) {
  5676. rulesetNode.joinSelectors(paths, context, selectors);
  5677. }
  5678. }
  5679. if (!selectors) {
  5680. rulesetNode.rules = null;
  5681. }
  5682. rulesetNode.paths = paths;
  5683. }
  5684. };
  5685. JoinSelectorVisitor.prototype.visitRulesetOut = function (rulesetNode) {
  5686. this.contexts.length = this.contexts.length - 1;
  5687. };
  5688. JoinSelectorVisitor.prototype.visitMedia = function (mediaNode, visitArgs) {
  5689. var context = this.contexts[this.contexts.length - 1];
  5690. mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
  5691. };
  5692. JoinSelectorVisitor.prototype.visitAtRule = function (atRuleNode, visitArgs) {
  5693. var context = this.contexts[this.contexts.length - 1];
  5694. if (atRuleNode.rules && atRuleNode.rules.length) {
  5695. atRuleNode.rules[0].root = (atRuleNode.isRooted || context.length === 0 || null);
  5696. }
  5697. };
  5698. return JoinSelectorVisitor;
  5699. }());
  5700. var CSSVisitorUtils = /** @class */ (function () {
  5701. function CSSVisitorUtils(context) {
  5702. this._visitor = new Visitor(this);
  5703. this._context = context;
  5704. }
  5705. CSSVisitorUtils.prototype.containsSilentNonBlockedChild = function (bodyRules) {
  5706. var rule;
  5707. if (!bodyRules) {
  5708. return false;
  5709. }
  5710. for (var r = 0; r < bodyRules.length; r++) {
  5711. rule = bodyRules[r];
  5712. if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) {
  5713. // the atrule contains something that was referenced (likely by extend)
  5714. // therefore it needs to be shown in output too
  5715. return true;
  5716. }
  5717. }
  5718. return false;
  5719. };
  5720. CSSVisitorUtils.prototype.keepOnlyVisibleChilds = function (owner) {
  5721. if (owner && owner.rules) {
  5722. owner.rules = owner.rules.filter(function (thing) { return thing.isVisible(); });
  5723. }
  5724. };
  5725. CSSVisitorUtils.prototype.isEmpty = function (owner) {
  5726. return (owner && owner.rules)
  5727. ? (owner.rules.length === 0) : true;
  5728. };
  5729. CSSVisitorUtils.prototype.hasVisibleSelector = function (rulesetNode) {
  5730. return (rulesetNode && rulesetNode.paths)
  5731. ? (rulesetNode.paths.length > 0) : false;
  5732. };
  5733. CSSVisitorUtils.prototype.resolveVisibility = function (node, originalRules) {
  5734. if (!node.blocksVisibility()) {
  5735. if (this.isEmpty(node) && !this.containsSilentNonBlockedChild(originalRules)) {
  5736. return;
  5737. }
  5738. return node;
  5739. }
  5740. var compiledRulesBody = node.rules[0];
  5741. this.keepOnlyVisibleChilds(compiledRulesBody);
  5742. if (this.isEmpty(compiledRulesBody)) {
  5743. return;
  5744. }
  5745. node.ensureVisibility();
  5746. node.removeVisibilityBlock();
  5747. return node;
  5748. };
  5749. CSSVisitorUtils.prototype.isVisibleRuleset = function (rulesetNode) {
  5750. if (rulesetNode.firstRoot) {
  5751. return true;
  5752. }
  5753. if (this.isEmpty(rulesetNode)) {
  5754. return false;
  5755. }
  5756. if (!rulesetNode.root && !this.hasVisibleSelector(rulesetNode)) {
  5757. return false;
  5758. }
  5759. return true;
  5760. };
  5761. return CSSVisitorUtils;
  5762. }());
  5763. var ToCSSVisitor = function (context) {
  5764. this._visitor = new Visitor(this);
  5765. this._context = context;
  5766. this.utils = new CSSVisitorUtils(context);
  5767. };
  5768. ToCSSVisitor.prototype = {
  5769. isReplacing: true,
  5770. run: function (root) {
  5771. return this._visitor.visit(root);
  5772. },
  5773. visitDeclaration: function (declNode, visitArgs) {
  5774. if (declNode.blocksVisibility() || declNode.variable) {
  5775. return;
  5776. }
  5777. return declNode;
  5778. },
  5779. visitMixinDefinition: function (mixinNode, visitArgs) {
  5780. // mixin definitions do not get eval'd - this means they keep state
  5781. // so we have to clear that state here so it isn't used if toCSS is called twice
  5782. mixinNode.frames = [];
  5783. },
  5784. visitExtend: function (extendNode, visitArgs) {
  5785. },
  5786. visitComment: function (commentNode, visitArgs) {
  5787. if (commentNode.blocksVisibility() || commentNode.isSilent(this._context)) {
  5788. return;
  5789. }
  5790. return commentNode;
  5791. },
  5792. visitMedia: function (mediaNode, visitArgs) {
  5793. var originalRules = mediaNode.rules[0].rules;
  5794. mediaNode.accept(this._visitor);
  5795. visitArgs.visitDeeper = false;
  5796. return this.utils.resolveVisibility(mediaNode, originalRules);
  5797. },
  5798. visitImport: function (importNode, visitArgs) {
  5799. if (importNode.blocksVisibility()) {
  5800. return;
  5801. }
  5802. return importNode;
  5803. },
  5804. visitAtRule: function (atRuleNode, visitArgs) {
  5805. if (atRuleNode.rules && atRuleNode.rules.length) {
  5806. return this.visitAtRuleWithBody(atRuleNode, visitArgs);
  5807. }
  5808. else {
  5809. return this.visitAtRuleWithoutBody(atRuleNode, visitArgs);
  5810. }
  5811. },
  5812. visitAnonymous: function (anonymousNode, visitArgs) {
  5813. if (!anonymousNode.blocksVisibility()) {
  5814. anonymousNode.accept(this._visitor);
  5815. return anonymousNode;
  5816. }
  5817. },
  5818. visitAtRuleWithBody: function (atRuleNode, visitArgs) {
  5819. // if there is only one nested ruleset and that one has no path, then it is
  5820. // just fake ruleset
  5821. function hasFakeRuleset(atRuleNode) {
  5822. var bodyRules = atRuleNode.rules;
  5823. return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0);
  5824. }
  5825. function getBodyRules(atRuleNode) {
  5826. var nodeRules = atRuleNode.rules;
  5827. if (hasFakeRuleset(atRuleNode)) {
  5828. return nodeRules[0].rules;
  5829. }
  5830. return nodeRules;
  5831. }
  5832. // it is still true that it is only one ruleset in array
  5833. // this is last such moment
  5834. // process childs
  5835. var originalRules = getBodyRules(atRuleNode);
  5836. atRuleNode.accept(this._visitor);
  5837. visitArgs.visitDeeper = false;
  5838. if (!this.utils.isEmpty(atRuleNode)) {
  5839. this._mergeRules(atRuleNode.rules[0].rules);
  5840. }
  5841. return this.utils.resolveVisibility(atRuleNode, originalRules);
  5842. },
  5843. visitAtRuleWithoutBody: function (atRuleNode, visitArgs) {
  5844. if (atRuleNode.blocksVisibility()) {
  5845. return;
  5846. }
  5847. if (atRuleNode.name === '@charset') {
  5848. // Only output the debug info together with subsequent @charset definitions
  5849. // a comment (or @media statement) before the actual @charset atrule would
  5850. // be considered illegal css as it has to be on the first line
  5851. if (this.charset) {
  5852. if (atRuleNode.debugInfo) {
  5853. var comment = new tree.Comment("/* " + atRuleNode.toCSS(this._context).replace(/\n/g, '') + " */\n");
  5854. comment.debugInfo = atRuleNode.debugInfo;
  5855. return this._visitor.visit(comment);
  5856. }
  5857. return;
  5858. }
  5859. this.charset = true;
  5860. }
  5861. return atRuleNode;
  5862. },
  5863. checkValidNodes: function (rules, isRoot) {
  5864. if (!rules) {
  5865. return;
  5866. }
  5867. for (var i_1 = 0; i_1 < rules.length; i_1++) {
  5868. var ruleNode = rules[i_1];
  5869. if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) {
  5870. throw { message: 'Properties must be inside selector blocks. They cannot be in the root',
  5871. index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename };
  5872. }
  5873. if (ruleNode instanceof tree.Call) {
  5874. throw { message: "Function '" + ruleNode.name + "' is undefined",
  5875. index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename };
  5876. }
  5877. if (ruleNode.type && !ruleNode.allowRoot) {
  5878. throw { message: ruleNode.type + " node returned by a function is not valid here",
  5879. index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename };
  5880. }
  5881. }
  5882. },
  5883. visitRuleset: function (rulesetNode, visitArgs) {
  5884. // at this point rulesets are nested into each other
  5885. var rule;
  5886. var rulesets = [];
  5887. this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot);
  5888. if (!rulesetNode.root) {
  5889. // remove invisible paths
  5890. this._compileRulesetPaths(rulesetNode);
  5891. // remove rulesets from this ruleset body and compile them separately
  5892. var nodeRules = rulesetNode.rules;
  5893. var nodeRuleCnt = nodeRules ? nodeRules.length : 0;
  5894. for (var i_2 = 0; i_2 < nodeRuleCnt;) {
  5895. rule = nodeRules[i_2];
  5896. if (rule && rule.rules) {
  5897. // visit because we are moving them out from being a child
  5898. rulesets.push(this._visitor.visit(rule));
  5899. nodeRules.splice(i_2, 1);
  5900. nodeRuleCnt--;
  5901. continue;
  5902. }
  5903. i_2++;
  5904. }
  5905. // accept the visitor to remove rules and refactor itself
  5906. // then we can decide nogw whether we want it or not
  5907. // compile body
  5908. if (nodeRuleCnt > 0) {
  5909. rulesetNode.accept(this._visitor);
  5910. }
  5911. else {
  5912. rulesetNode.rules = null;
  5913. }
  5914. visitArgs.visitDeeper = false;
  5915. }
  5916. else { // if (! rulesetNode.root) {
  5917. rulesetNode.accept(this._visitor);
  5918. visitArgs.visitDeeper = false;
  5919. }
  5920. if (rulesetNode.rules) {
  5921. this._mergeRules(rulesetNode.rules);
  5922. this._removeDuplicateRules(rulesetNode.rules);
  5923. }
  5924. // now decide whether we keep the ruleset
  5925. if (this.utils.isVisibleRuleset(rulesetNode)) {
  5926. rulesetNode.ensureVisibility();
  5927. rulesets.splice(0, 0, rulesetNode);
  5928. }
  5929. if (rulesets.length === 1) {
  5930. return rulesets[0];
  5931. }
  5932. return rulesets;
  5933. },
  5934. _compileRulesetPaths: function (rulesetNode) {
  5935. if (rulesetNode.paths) {
  5936. rulesetNode.paths = rulesetNode.paths
  5937. .filter(function (p) {
  5938. var i;
  5939. if (p[0].elements[0].combinator.value === ' ') {
  5940. p[0].elements[0].combinator = new (tree.Combinator)('');
  5941. }
  5942. for (i = 0; i < p.length; i++) {
  5943. if (p[i].isVisible() && p[i].getIsOutput()) {
  5944. return true;
  5945. }
  5946. }
  5947. return false;
  5948. });
  5949. }
  5950. },
  5951. _removeDuplicateRules: function (rules) {
  5952. if (!rules) {
  5953. return;
  5954. }
  5955. // remove duplicates
  5956. var ruleCache = {};
  5957. var ruleList;
  5958. var rule;
  5959. var i;
  5960. for (i = rules.length - 1; i >= 0; i--) {
  5961. rule = rules[i];
  5962. if (rule instanceof tree.Declaration) {
  5963. if (!ruleCache[rule.name]) {
  5964. ruleCache[rule.name] = rule;
  5965. }
  5966. else {
  5967. ruleList = ruleCache[rule.name];
  5968. if (ruleList instanceof tree.Declaration) {
  5969. ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._context)];
  5970. }
  5971. var ruleCSS = rule.toCSS(this._context);
  5972. if (ruleList.indexOf(ruleCSS) !== -1) {
  5973. rules.splice(i, 1);
  5974. }
  5975. else {
  5976. ruleList.push(ruleCSS);
  5977. }
  5978. }
  5979. }
  5980. }
  5981. },
  5982. _mergeRules: function (rules) {
  5983. if (!rules) {
  5984. return;
  5985. }
  5986. var groups = {};
  5987. var groupsArr = [];
  5988. for (var i_3 = 0; i_3 < rules.length; i_3++) {
  5989. var rule = rules[i_3];
  5990. if (rule.merge) {
  5991. var key = rule.name;
  5992. groups[key] ? rules.splice(i_3--, 1) :
  5993. groupsArr.push(groups[key] = []);
  5994. groups[key].push(rule);
  5995. }
  5996. }
  5997. groupsArr.forEach(function (group) {
  5998. if (group.length > 0) {
  5999. var result_1 = group[0];
  6000. var space_1 = [];
  6001. var comma_1 = [new tree.Expression(space_1)];
  6002. group.forEach(function (rule) {
  6003. if ((rule.merge === '+') && (space_1.length > 0)) {
  6004. comma_1.push(new tree.Expression(space_1 = []));
  6005. }
  6006. space_1.push(rule.value);
  6007. result_1.important = result_1.important || rule.important;
  6008. });
  6009. result_1.value = new tree.Value(comma_1);
  6010. }
  6011. });
  6012. }
  6013. };
  6014. var visitors = {
  6015. Visitor: Visitor,
  6016. ImportVisitor: ImportVisitor,
  6017. MarkVisibleSelectorsVisitor: SetTreeVisibilityVisitor,
  6018. ExtendVisitor: ProcessExtendsVisitor,
  6019. JoinSelectorVisitor: JoinSelectorVisitor,
  6020. ToCSSVisitor: ToCSSVisitor
  6021. };
  6022. // Split the input into chunks.
  6023. var chunker = (function (input, fail) {
  6024. var len = input.length;
  6025. var level = 0;
  6026. var parenLevel = 0;
  6027. var lastOpening;
  6028. var lastOpeningParen;
  6029. var lastMultiComment;
  6030. var lastMultiCommentEndBrace;
  6031. var chunks = [];
  6032. var emitFrom = 0;
  6033. var chunkerCurrentIndex;
  6034. var currentChunkStartIndex;
  6035. var cc;
  6036. var cc2;
  6037. var matched;
  6038. function emitChunk(force) {
  6039. var len = chunkerCurrentIndex - emitFrom;
  6040. if (((len < 512) && !force) || !len) {
  6041. return;
  6042. }
  6043. chunks.push(input.slice(emitFrom, chunkerCurrentIndex + 1));
  6044. emitFrom = chunkerCurrentIndex + 1;
  6045. }
  6046. for (chunkerCurrentIndex = 0; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
  6047. cc = input.charCodeAt(chunkerCurrentIndex);
  6048. if (((cc >= 97) && (cc <= 122)) || (cc < 34)) {
  6049. // a-z or whitespace
  6050. continue;
  6051. }
  6052. switch (cc) {
  6053. case 40: // (
  6054. parenLevel++;
  6055. lastOpeningParen = chunkerCurrentIndex;
  6056. continue;
  6057. case 41: // )
  6058. if (--parenLevel < 0) {
  6059. return fail('missing opening `(`', chunkerCurrentIndex);
  6060. }
  6061. continue;
  6062. case 59: // ;
  6063. if (!parenLevel) {
  6064. emitChunk();
  6065. }
  6066. continue;
  6067. case 123: // {
  6068. level++;
  6069. lastOpening = chunkerCurrentIndex;
  6070. continue;
  6071. case 125: // }
  6072. if (--level < 0) {
  6073. return fail('missing opening `{`', chunkerCurrentIndex);
  6074. }
  6075. if (!level && !parenLevel) {
  6076. emitChunk();
  6077. }
  6078. continue;
  6079. case 92: // \
  6080. if (chunkerCurrentIndex < len - 1) {
  6081. chunkerCurrentIndex++;
  6082. continue;
  6083. }
  6084. return fail('unescaped `\\`', chunkerCurrentIndex);
  6085. case 34:
  6086. case 39:
  6087. case 96: // ", ' and `
  6088. matched = 0;
  6089. currentChunkStartIndex = chunkerCurrentIndex;
  6090. for (chunkerCurrentIndex = chunkerCurrentIndex + 1; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
  6091. cc2 = input.charCodeAt(chunkerCurrentIndex);
  6092. if (cc2 > 96) {
  6093. continue;
  6094. }
  6095. if (cc2 == cc) {
  6096. matched = 1;
  6097. break;
  6098. }
  6099. if (cc2 == 92) { // \
  6100. if (chunkerCurrentIndex == len - 1) {
  6101. return fail('unescaped `\\`', chunkerCurrentIndex);
  6102. }
  6103. chunkerCurrentIndex++;
  6104. }
  6105. }
  6106. if (matched) {
  6107. continue;
  6108. }
  6109. return fail("unmatched `" + String.fromCharCode(cc) + "`", currentChunkStartIndex);
  6110. case 47: // /, check for comment
  6111. if (parenLevel || (chunkerCurrentIndex == len - 1)) {
  6112. continue;
  6113. }
  6114. cc2 = input.charCodeAt(chunkerCurrentIndex + 1);
  6115. if (cc2 == 47) {
  6116. // //, find lnfeed
  6117. for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
  6118. cc2 = input.charCodeAt(chunkerCurrentIndex);
  6119. if ((cc2 <= 13) && ((cc2 == 10) || (cc2 == 13))) {
  6120. break;
  6121. }
  6122. }
  6123. }
  6124. else if (cc2 == 42) {
  6125. // /*, find */
  6126. lastMultiComment = currentChunkStartIndex = chunkerCurrentIndex;
  6127. for (chunkerCurrentIndex = chunkerCurrentIndex + 2; chunkerCurrentIndex < len - 1; chunkerCurrentIndex++) {
  6128. cc2 = input.charCodeAt(chunkerCurrentIndex);
  6129. if (cc2 == 125) {
  6130. lastMultiCommentEndBrace = chunkerCurrentIndex;
  6131. }
  6132. if (cc2 != 42) {
  6133. continue;
  6134. }
  6135. if (input.charCodeAt(chunkerCurrentIndex + 1) == 47) {
  6136. break;
  6137. }
  6138. }
  6139. if (chunkerCurrentIndex == len - 1) {
  6140. return fail('missing closing `*/`', currentChunkStartIndex);
  6141. }
  6142. chunkerCurrentIndex++;
  6143. }
  6144. continue;
  6145. case 42: // *, check for unmatched */
  6146. if ((chunkerCurrentIndex < len - 1) && (input.charCodeAt(chunkerCurrentIndex + 1) == 47)) {
  6147. return fail('unmatched `/*`', chunkerCurrentIndex);
  6148. }
  6149. continue;
  6150. }
  6151. }
  6152. if (level !== 0) {
  6153. if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) {
  6154. return fail('missing closing `}` or `*/`', lastOpening);
  6155. }
  6156. else {
  6157. return fail('missing closing `}`', lastOpening);
  6158. }
  6159. }
  6160. else if (parenLevel !== 0) {
  6161. return fail('missing closing `)`', lastOpeningParen);
  6162. }
  6163. emitChunk(true);
  6164. return chunks;
  6165. });
  6166. var getParserInput = (function () {
  6167. var // Less input string
  6168. input;
  6169. var // current chunk
  6170. j;
  6171. var // holds state for backtracking
  6172. saveStack = [];
  6173. var // furthest index the parser has gone to
  6174. furthest;
  6175. var // if this is furthest we got to, this is the probably cause
  6176. furthestPossibleErrorMessage;
  6177. var // chunkified input
  6178. chunks;
  6179. var // current chunk
  6180. current;
  6181. var // index of current chunk, in `input`
  6182. currentPos;
  6183. var parserInput = {};
  6184. var CHARCODE_SPACE = 32;
  6185. var CHARCODE_TAB = 9;
  6186. var CHARCODE_LF = 10;
  6187. var CHARCODE_CR = 13;
  6188. var CHARCODE_PLUS = 43;
  6189. var CHARCODE_COMMA = 44;
  6190. var CHARCODE_FORWARD_SLASH = 47;
  6191. var CHARCODE_9 = 57;
  6192. function skipWhitespace(length) {
  6193. var oldi = parserInput.i;
  6194. var oldj = j;
  6195. var curr = parserInput.i - currentPos;
  6196. var endIndex = parserInput.i + current.length - curr;
  6197. var mem = (parserInput.i += length);
  6198. var inp = input;
  6199. var c;
  6200. var nextChar;
  6201. var comment;
  6202. for (; parserInput.i < endIndex; parserInput.i++) {
  6203. c = inp.charCodeAt(parserInput.i);
  6204. if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
  6205. nextChar = inp.charAt(parserInput.i + 1);
  6206. if (nextChar === '/') {
  6207. comment = { index: parserInput.i, isLineComment: true };
  6208. var nextNewLine = inp.indexOf('\n', parserInput.i + 2);
  6209. if (nextNewLine < 0) {
  6210. nextNewLine = endIndex;
  6211. }
  6212. parserInput.i = nextNewLine;
  6213. comment.text = inp.substr(comment.index, parserInput.i - comment.index);
  6214. parserInput.commentStore.push(comment);
  6215. continue;
  6216. }
  6217. else if (nextChar === '*') {
  6218. var nextStarSlash = inp.indexOf('*/', parserInput.i + 2);
  6219. if (nextStarSlash >= 0) {
  6220. comment = {
  6221. index: parserInput.i,
  6222. text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
  6223. isLineComment: false
  6224. };
  6225. parserInput.i += comment.text.length - 1;
  6226. parserInput.commentStore.push(comment);
  6227. continue;
  6228. }
  6229. }
  6230. break;
  6231. }
  6232. if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
  6233. break;
  6234. }
  6235. }
  6236. current = current.slice(length + parserInput.i - mem + curr);
  6237. currentPos = parserInput.i;
  6238. if (!current.length) {
  6239. if (j < chunks.length - 1) {
  6240. current = chunks[++j];
  6241. skipWhitespace(0); // skip space at the beginning of a chunk
  6242. return true; // things changed
  6243. }
  6244. parserInput.finished = true;
  6245. }
  6246. return oldi !== parserInput.i || oldj !== j;
  6247. }
  6248. parserInput.save = function () {
  6249. currentPos = parserInput.i;
  6250. saveStack.push({ current: current, i: parserInput.i, j: j });
  6251. };
  6252. parserInput.restore = function (possibleErrorMessage) {
  6253. if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
  6254. furthest = parserInput.i;
  6255. furthestPossibleErrorMessage = possibleErrorMessage;
  6256. }
  6257. var state = saveStack.pop();
  6258. current = state.current;
  6259. currentPos = parserInput.i = state.i;
  6260. j = state.j;
  6261. };
  6262. parserInput.forget = function () {
  6263. saveStack.pop();
  6264. };
  6265. parserInput.isWhitespace = function (offset) {
  6266. var pos = parserInput.i + (offset || 0);
  6267. var code = input.charCodeAt(pos);
  6268. return (code === CHARCODE_SPACE || code === CHARCODE_CR || code === CHARCODE_TAB || code === CHARCODE_LF);
  6269. };
  6270. // Specialization of $(tok)
  6271. parserInput.$re = function (tok) {
  6272. if (parserInput.i > currentPos) {
  6273. current = current.slice(parserInput.i - currentPos);
  6274. currentPos = parserInput.i;
  6275. }
  6276. var m = tok.exec(current);
  6277. if (!m) {
  6278. return null;
  6279. }
  6280. skipWhitespace(m[0].length);
  6281. if (typeof m === 'string') {
  6282. return m;
  6283. }
  6284. return m.length === 1 ? m[0] : m;
  6285. };
  6286. parserInput.$char = function (tok) {
  6287. if (input.charAt(parserInput.i) !== tok) {
  6288. return null;
  6289. }
  6290. skipWhitespace(1);
  6291. return tok;
  6292. };
  6293. parserInput.$str = function (tok) {
  6294. var tokLength = tok.length;
  6295. // https://jsperf.com/string-startswith/21
  6296. for (var i_1 = 0; i_1 < tokLength; i_1++) {
  6297. if (input.charAt(parserInput.i + i_1) !== tok.charAt(i_1)) {
  6298. return null;
  6299. }
  6300. }
  6301. skipWhitespace(tokLength);
  6302. return tok;
  6303. };
  6304. parserInput.$quoted = function (loc) {
  6305. var pos = loc || parserInput.i;
  6306. var startChar = input.charAt(pos);
  6307. if (startChar !== '\'' && startChar !== '"') {
  6308. return;
  6309. }
  6310. var length = input.length;
  6311. var currentPosition = pos;
  6312. for (var i_2 = 1; i_2 + currentPosition < length; i_2++) {
  6313. var nextChar = input.charAt(i_2 + currentPosition);
  6314. switch (nextChar) {
  6315. case '\\':
  6316. i_2++;
  6317. continue;
  6318. case '\r':
  6319. case '\n':
  6320. break;
  6321. case startChar:
  6322. var str = input.substr(currentPosition, i_2 + 1);
  6323. if (!loc && loc !== 0) {
  6324. skipWhitespace(i_2 + 1);
  6325. return str;
  6326. }
  6327. return [startChar, str];
  6328. }
  6329. }
  6330. return null;
  6331. };
  6332. /**
  6333. * Permissive parsing. Ignores everything except matching {} [] () and quotes
  6334. * until matching token (outside of blocks)
  6335. */
  6336. parserInput.$parseUntil = function (tok) {
  6337. var quote = '';
  6338. var returnVal = null;
  6339. var inComment = false;
  6340. var blockDepth = 0;
  6341. var blockStack = [];
  6342. var parseGroups = [];
  6343. var length = input.length;
  6344. var startPos = parserInput.i;
  6345. var lastPos = parserInput.i;
  6346. var i = parserInput.i;
  6347. var loop = true;
  6348. var testChar;
  6349. if (typeof tok === 'string') {
  6350. testChar = function (char) { return char === tok; };
  6351. }
  6352. else {
  6353. testChar = function (char) { return tok.test(char); };
  6354. }
  6355. do {
  6356. var nextChar = input.charAt(i);
  6357. if (blockDepth === 0 && testChar(nextChar)) {
  6358. returnVal = input.substr(lastPos, i - lastPos);
  6359. if (returnVal) {
  6360. parseGroups.push(returnVal);
  6361. }
  6362. else {
  6363. parseGroups.push(' ');
  6364. }
  6365. returnVal = parseGroups;
  6366. skipWhitespace(i - startPos);
  6367. loop = false;
  6368. }
  6369. else {
  6370. if (inComment) {
  6371. if (nextChar === '*' &&
  6372. input.charAt(i + 1) === '/') {
  6373. i++;
  6374. blockDepth--;
  6375. inComment = false;
  6376. }
  6377. i++;
  6378. continue;
  6379. }
  6380. switch (nextChar) {
  6381. case '\\':
  6382. i++;
  6383. nextChar = input.charAt(i);
  6384. parseGroups.push(input.substr(lastPos, i - lastPos + 1));
  6385. lastPos = i + 1;
  6386. break;
  6387. case '/':
  6388. if (input.charAt(i + 1) === '*') {
  6389. i++;
  6390. inComment = true;
  6391. blockDepth++;
  6392. }
  6393. break;
  6394. case '\'':
  6395. case '"':
  6396. quote = parserInput.$quoted(i);
  6397. if (quote) {
  6398. parseGroups.push(input.substr(lastPos, i - lastPos), quote);
  6399. i += quote[1].length - 1;
  6400. lastPos = i + 1;
  6401. }
  6402. else {
  6403. skipWhitespace(i - startPos);
  6404. returnVal = nextChar;
  6405. loop = false;
  6406. }
  6407. break;
  6408. case '{':
  6409. blockStack.push('}');
  6410. blockDepth++;
  6411. break;
  6412. case '(':
  6413. blockStack.push(')');
  6414. blockDepth++;
  6415. break;
  6416. case '[':
  6417. blockStack.push(']');
  6418. blockDepth++;
  6419. break;
  6420. case '}':
  6421. case ')':
  6422. case ']':
  6423. var expected = blockStack.pop();
  6424. if (nextChar === expected) {
  6425. blockDepth--;
  6426. }
  6427. else {
  6428. // move the parser to the error and return expected
  6429. skipWhitespace(i - startPos);
  6430. returnVal = expected;
  6431. loop = false;
  6432. }
  6433. }
  6434. i++;
  6435. if (i > length) {
  6436. loop = false;
  6437. }
  6438. }
  6439. } while (loop);
  6440. return returnVal ? returnVal : null;
  6441. };
  6442. parserInput.autoCommentAbsorb = true;
  6443. parserInput.commentStore = [];
  6444. parserInput.finished = false;
  6445. // Same as $(), but don't change the state of the parser,
  6446. // just return the match.
  6447. parserInput.peek = function (tok) {
  6448. if (typeof tok === 'string') {
  6449. // https://jsperf.com/string-startswith/21
  6450. for (var i_3 = 0; i_3 < tok.length; i_3++) {
  6451. if (input.charAt(parserInput.i + i_3) !== tok.charAt(i_3)) {
  6452. return false;
  6453. }
  6454. }
  6455. return true;
  6456. }
  6457. else {
  6458. return tok.test(current);
  6459. }
  6460. };
  6461. // Specialization of peek()
  6462. // TODO remove or change some currentChar calls to peekChar
  6463. parserInput.peekChar = function (tok) { return input.charAt(parserInput.i) === tok; };
  6464. parserInput.currentChar = function () { return input.charAt(parserInput.i); };
  6465. parserInput.prevChar = function () { return input.charAt(parserInput.i - 1); };
  6466. parserInput.getInput = function () { return input; };
  6467. parserInput.peekNotNumeric = function () {
  6468. var c = input.charCodeAt(parserInput.i);
  6469. // Is the first char of the dimension 0-9, '.', '+' or '-'
  6470. return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA;
  6471. };
  6472. parserInput.start = function (str, chunkInput, failFunction) {
  6473. input = str;
  6474. parserInput.i = j = currentPos = furthest = 0;
  6475. // chunking apparently makes things quicker (but my tests indicate
  6476. // it might actually make things slower in node at least)
  6477. // and it is a non-perfect parse - it can't recognise
  6478. // unquoted urls, meaning it can't distinguish comments
  6479. // meaning comments with quotes or {}() in them get 'counted'
  6480. // and then lead to parse errors.
  6481. // In addition if the chunking chunks in the wrong place we might
  6482. // not be able to parse a parser statement in one go
  6483. // this is officially deprecated but can be switched on via an option
  6484. // in the case it causes too much performance issues.
  6485. if (chunkInput) {
  6486. chunks = chunker(str, failFunction);
  6487. }
  6488. else {
  6489. chunks = [str];
  6490. }
  6491. current = chunks[0];
  6492. skipWhitespace(0);
  6493. };
  6494. parserInput.end = function () {
  6495. var message;
  6496. var isFinished = parserInput.i >= input.length;
  6497. if (parserInput.i < furthest) {
  6498. message = furthestPossibleErrorMessage;
  6499. parserInput.i = furthest;
  6500. }
  6501. return {
  6502. isFinished: isFinished,
  6503. furthest: parserInput.i,
  6504. furthestPossibleErrorMessage: message,
  6505. furthestReachedEnd: parserInput.i >= input.length - 1,
  6506. furthestChar: input[parserInput.i]
  6507. };
  6508. };
  6509. return parserInput;
  6510. });
  6511. //
  6512. // less.js - parser
  6513. //
  6514. // A relatively straight-forward predictive parser.
  6515. // There is no tokenization/lexing stage, the input is parsed
  6516. // in one sweep.
  6517. //
  6518. // To make the parser fast enough to run in the browser, several
  6519. // optimization had to be made:
  6520. //
  6521. // - Matching and slicing on a huge input is often cause of slowdowns.
  6522. // The solution is to chunkify the input into smaller strings.
  6523. // The chunks are stored in the `chunks` var,
  6524. // `j` holds the current chunk index, and `currentPos` holds
  6525. // the index of the current chunk in relation to `input`.
  6526. // This gives us an almost 4x speed-up.
  6527. //
  6528. // - In many cases, we don't need to match individual tokens;
  6529. // for example, if a value doesn't hold any variables, operations
  6530. // or dynamic references, the parser can effectively 'skip' it,
  6531. // treating it as a literal.
  6532. // An example would be '1px solid #000' - which evaluates to itself,
  6533. // we don't need to know what the individual components are.
  6534. // The drawback, of course is that you don't get the benefits of
  6535. // syntax-checking on the CSS. This gives us a 50% speed-up in the parser,
  6536. // and a smaller speed-up in the code-gen.
  6537. //
  6538. //
  6539. // Token matching is done with the `$` function, which either takes
  6540. // a terminal string or regexp, or a non-terminal function to call.
  6541. // It also takes care of moving all the indices forwards.
  6542. //
  6543. var Parser = function Parser(context, imports, fileInfo) {
  6544. var parsers;
  6545. var parserInput = getParserInput();
  6546. function error(msg, type) {
  6547. throw new LessError({
  6548. index: parserInput.i,
  6549. filename: fileInfo.filename,
  6550. type: type || 'Syntax',
  6551. message: msg
  6552. }, imports);
  6553. }
  6554. function expect(arg, msg) {
  6555. // some older browsers return typeof 'function' for RegExp
  6556. var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
  6557. if (result) {
  6558. return result;
  6559. }
  6560. error(msg || (typeof arg === 'string'
  6561. ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'"
  6562. : 'unexpected token'));
  6563. }
  6564. // Specialization of expect()
  6565. function expectChar(arg, msg) {
  6566. if (parserInput.$char(arg)) {
  6567. return arg;
  6568. }
  6569. error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'");
  6570. }
  6571. function getDebugInfo(index) {
  6572. var filename = fileInfo.filename;
  6573. return {
  6574. lineNumber: getLocation(index, parserInput.getInput()).line + 1,
  6575. fileName: filename
  6576. };
  6577. }
  6578. /**
  6579. * Used after initial parsing to create nodes on the fly
  6580. *
  6581. * @param {String} str - string to parse
  6582. * @param {Array} parseList - array of parsers to run input through e.g. ["value", "important"]
  6583. * @param {Number} currentIndex - start number to begin indexing
  6584. * @param {Object} fileInfo - fileInfo to attach to created nodes
  6585. */
  6586. function parseNode(str, parseList, currentIndex, fileInfo, callback) {
  6587. var result;
  6588. var returnNodes = [];
  6589. var parser = parserInput;
  6590. try {
  6591. parser.start(str, false, function fail(msg, index) {
  6592. callback({
  6593. message: msg,
  6594. index: index + currentIndex
  6595. });
  6596. });
  6597. for (var x = 0, p = void 0, i_1; (p = parseList[x]); x++) {
  6598. i_1 = parser.i;
  6599. result = parsers[p]();
  6600. if (result) {
  6601. try {
  6602. result._index = i_1 + currentIndex;
  6603. result._fileInfo = fileInfo;
  6604. }
  6605. catch (e) { }
  6606. returnNodes.push(result);
  6607. }
  6608. else {
  6609. returnNodes.push(null);
  6610. }
  6611. }
  6612. var endInfo = parser.end();
  6613. if (endInfo.isFinished) {
  6614. callback(null, returnNodes);
  6615. }
  6616. else {
  6617. callback(true, null);
  6618. }
  6619. }
  6620. catch (e) {
  6621. throw new LessError({
  6622. index: e.index + currentIndex,
  6623. message: e.message
  6624. }, imports, fileInfo.filename);
  6625. }
  6626. }
  6627. //
  6628. // The Parser
  6629. //
  6630. return {
  6631. parserInput: parserInput,
  6632. imports: imports,
  6633. fileInfo: fileInfo,
  6634. parseNode: parseNode,
  6635. //
  6636. // Parse an input string into an abstract syntax tree,
  6637. // @param str A string containing 'less' markup
  6638. // @param callback call `callback` when done.
  6639. // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
  6640. //
  6641. parse: function (str, callback, additionalData) {
  6642. var root;
  6643. var error = null;
  6644. var globalVars;
  6645. var modifyVars;
  6646. var ignored;
  6647. var preText = '';
  6648. globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + "\n" : '';
  6649. modifyVars = (additionalData && additionalData.modifyVars) ? "\n" + Parser.serializeVars(additionalData.modifyVars) : '';
  6650. if (context.pluginManager) {
  6651. var preProcessors = context.pluginManager.getPreProcessors();
  6652. for (var i_2 = 0; i_2 < preProcessors.length; i_2++) {
  6653. str = preProcessors[i_2].process(str, { context: context, imports: imports, fileInfo: fileInfo });
  6654. }
  6655. }
  6656. if (globalVars || (additionalData && additionalData.banner)) {
  6657. preText = ((additionalData && additionalData.banner) ? additionalData.banner : '') + globalVars;
  6658. ignored = imports.contentsIgnoredChars;
  6659. ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0;
  6660. ignored[fileInfo.filename] += preText.length;
  6661. }
  6662. str = str.replace(/\r\n?/g, '\n');
  6663. // Remove potential UTF Byte Order Mark
  6664. str = preText + str.replace(/^\uFEFF/, '') + modifyVars;
  6665. imports.contents[fileInfo.filename] = str;
  6666. // Start with the primary rule.
  6667. // The whole syntax tree is held under a Ruleset node,
  6668. // with the `root` property set to true, so no `{}` are
  6669. // output. The callback is called when the input is parsed.
  6670. try {
  6671. parserInput.start(str, context.chunkInput, function fail(msg, index) {
  6672. throw new LessError({
  6673. index: index,
  6674. type: 'Parse',
  6675. message: msg,
  6676. filename: fileInfo.filename
  6677. }, imports);
  6678. });
  6679. tree.Node.prototype.parse = this;
  6680. root = new tree.Ruleset(null, this.parsers.primary());
  6681. tree.Node.prototype.rootNode = root;
  6682. root.root = true;
  6683. root.firstRoot = true;
  6684. root.functionRegistry = functionRegistry.inherit();
  6685. }
  6686. catch (e) {
  6687. return callback(new LessError(e, imports, fileInfo.filename));
  6688. }
  6689. // If `i` is smaller than the `input.length - 1`,
  6690. // it means the parser wasn't able to parse the whole
  6691. // string, so we've got a parsing error.
  6692. //
  6693. // We try to extract a \n delimited string,
  6694. // showing the line where the parse error occurred.
  6695. // We split it up into two parts (the part which parsed,
  6696. // and the part which didn't), so we can color them differently.
  6697. var endInfo = parserInput.end();
  6698. if (!endInfo.isFinished) {
  6699. var message = endInfo.furthestPossibleErrorMessage;
  6700. if (!message) {
  6701. message = 'Unrecognised input';
  6702. if (endInfo.furthestChar === '}') {
  6703. message += '. Possibly missing opening \'{\'';
  6704. }
  6705. else if (endInfo.furthestChar === ')') {
  6706. message += '. Possibly missing opening \'(\'';
  6707. }
  6708. else if (endInfo.furthestReachedEnd) {
  6709. message += '. Possibly missing something';
  6710. }
  6711. }
  6712. error = new LessError({
  6713. type: 'Parse',
  6714. message: message,
  6715. index: endInfo.furthest,
  6716. filename: fileInfo.filename
  6717. }, imports);
  6718. }
  6719. var finish = function (e) {
  6720. e = error || e || imports.error;
  6721. if (e) {
  6722. if (!(e instanceof LessError)) {
  6723. e = new LessError(e, imports, fileInfo.filename);
  6724. }
  6725. return callback(e);
  6726. }
  6727. else {
  6728. return callback(null, root);
  6729. }
  6730. };
  6731. if (context.processImports !== false) {
  6732. new visitors.ImportVisitor(imports, finish)
  6733. .run(root);
  6734. }
  6735. else {
  6736. return finish();
  6737. }
  6738. },
  6739. //
  6740. // Here in, the parsing rules/functions
  6741. //
  6742. // The basic structure of the syntax tree generated is as follows:
  6743. //
  6744. // Ruleset -> Declaration -> Value -> Expression -> Entity
  6745. //
  6746. // Here's some Less code:
  6747. //
  6748. // .class {
  6749. // color: #fff;
  6750. // border: 1px solid #000;
  6751. // width: @w + 4px;
  6752. // > .child {...}
  6753. // }
  6754. //
  6755. // And here's what the parse tree might look like:
  6756. //
  6757. // Ruleset (Selector '.class', [
  6758. // Declaration ("color", Value ([Expression [Color #fff]]))
  6759. // Declaration ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
  6760. // Declaration ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]]))
  6761. // Ruleset (Selector [Element '>', '.child'], [...])
  6762. // ])
  6763. //
  6764. // In general, most rules will try to parse a token with the `$re()` function, and if the return
  6765. // value is truly, will return a new node, of the relevant type. Sometimes, we need to check
  6766. // first, before parsing, that's when we use `peek()`.
  6767. //
  6768. parsers: parsers = {
  6769. //
  6770. // The `primary` rule is the *entry* and *exit* point of the parser.
  6771. // The rules here can appear at any level of the parse tree.
  6772. //
  6773. // The recursive nature of the grammar is an interplay between the `block`
  6774. // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule,
  6775. // as represented by this simplified grammar:
  6776. //
  6777. // primary → (ruleset | declaration)+
  6778. // ruleset → selector+ block
  6779. // block → '{' primary '}'
  6780. //
  6781. // Only at one point is the primary rule not called from the
  6782. // block rule: at the root level.
  6783. //
  6784. primary: function () {
  6785. var mixin = this.mixin;
  6786. var root = [];
  6787. var node;
  6788. while (true) {
  6789. while (true) {
  6790. node = this.comment();
  6791. if (!node) {
  6792. break;
  6793. }
  6794. root.push(node);
  6795. }
  6796. // always process comments before deciding if finished
  6797. if (parserInput.finished) {
  6798. break;
  6799. }
  6800. if (parserInput.peek('}')) {
  6801. break;
  6802. }
  6803. node = this.extendRule();
  6804. if (node) {
  6805. root = root.concat(node);
  6806. continue;
  6807. }
  6808. node = mixin.definition() || this.declaration() || mixin.call(false, false) ||
  6809. this.ruleset() || this.variableCall() || this.entities.call() || this.atrule();
  6810. if (node) {
  6811. root.push(node);
  6812. }
  6813. else {
  6814. var foundSemiColon = false;
  6815. while (parserInput.$char(';')) {
  6816. foundSemiColon = true;
  6817. }
  6818. if (!foundSemiColon) {
  6819. break;
  6820. }
  6821. }
  6822. }
  6823. return root;
  6824. },
  6825. // comments are collected by the main parsing mechanism and then assigned to nodes
  6826. // where the current structure allows it
  6827. comment: function () {
  6828. if (parserInput.commentStore.length) {
  6829. var comment = parserInput.commentStore.shift();
  6830. return new (tree.Comment)(comment.text, comment.isLineComment, comment.index, fileInfo);
  6831. }
  6832. },
  6833. //
  6834. // Entities are tokens which can be found inside an Expression
  6835. //
  6836. entities: {
  6837. mixinLookup: function () {
  6838. return parsers.mixin.call(true, true);
  6839. },
  6840. //
  6841. // A string, which supports escaping " and '
  6842. //
  6843. // "milky way" 'he\'s the one!'
  6844. //
  6845. quoted: function (forceEscaped) {
  6846. var str;
  6847. var index = parserInput.i;
  6848. var isEscaped = false;
  6849. parserInput.save();
  6850. if (parserInput.$char('~')) {
  6851. isEscaped = true;
  6852. }
  6853. else if (forceEscaped) {
  6854. parserInput.restore();
  6855. return;
  6856. }
  6857. str = parserInput.$quoted();
  6858. if (!str) {
  6859. parserInput.restore();
  6860. return;
  6861. }
  6862. parserInput.forget();
  6863. return new (tree.Quoted)(str.charAt(0), str.substr(1, str.length - 2), isEscaped, index, fileInfo);
  6864. },
  6865. //
  6866. // A catch-all word, such as:
  6867. //
  6868. // black border-collapse
  6869. //
  6870. keyword: function () {
  6871. var k = parserInput.$char('%') || parserInput.$re(/^\[?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+\]?/);
  6872. if (k) {
  6873. return tree.Color.fromKeyword(k) || new (tree.Keyword)(k);
  6874. }
  6875. },
  6876. //
  6877. // A function call
  6878. //
  6879. // rgb(255, 0, 255)
  6880. //
  6881. // The arguments are parsed with the `entities.arguments` parser.
  6882. //
  6883. call: function () {
  6884. var name;
  6885. var args;
  6886. var func;
  6887. var index = parserInput.i;
  6888. // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
  6889. if (parserInput.peek(/^url\(/i)) {
  6890. return;
  6891. }
  6892. parserInput.save();
  6893. name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/);
  6894. if (!name) {
  6895. parserInput.forget();
  6896. return;
  6897. }
  6898. name = name[1];
  6899. func = this.customFuncCall(name);
  6900. if (func) {
  6901. args = func.parse();
  6902. if (args && func.stop) {
  6903. parserInput.forget();
  6904. return args;
  6905. }
  6906. }
  6907. args = this.arguments(args);
  6908. if (!parserInput.$char(')')) {
  6909. parserInput.restore('Could not parse call arguments or missing \')\'');
  6910. return;
  6911. }
  6912. parserInput.forget();
  6913. return new (tree.Call)(name, args, index, fileInfo);
  6914. },
  6915. //
  6916. // Parsing rules for functions with non-standard args, e.g.:
  6917. //
  6918. // boolean(not(2 > 1))
  6919. //
  6920. // This is a quick prototype, to be modified/improved when
  6921. // more custom-parsed funcs come (e.g. `selector(...)`)
  6922. //
  6923. customFuncCall: function (name) {
  6924. /* Ideally the table is to be moved out of here for faster perf.,
  6925. but it's quite tricky since it relies on all these `parsers`
  6926. and `expect` available only here */
  6927. return {
  6928. alpha: f(parsers.ieAlpha, true),
  6929. boolean: f(condition),
  6930. 'if': f(condition)
  6931. }[name.toLowerCase()];
  6932. function f(parse, stop) {
  6933. return {
  6934. parse: parse,
  6935. stop: stop // when true - stop after parse() and return its result,
  6936. // otherwise continue for plain args
  6937. };
  6938. }
  6939. function condition() {
  6940. return [expect(parsers.condition, 'expected condition')];
  6941. }
  6942. },
  6943. arguments: function (prevArgs) {
  6944. var argsComma = prevArgs || [];
  6945. var argsSemiColon = [];
  6946. var isSemiColonSeparated;
  6947. var value;
  6948. parserInput.save();
  6949. while (true) {
  6950. if (prevArgs) {
  6951. prevArgs = false;
  6952. }
  6953. else {
  6954. value = parsers.detachedRuleset() || this.assignment() || parsers.expression();
  6955. if (!value) {
  6956. break;
  6957. }
  6958. if (value.value && value.value.length == 1) {
  6959. value = value.value[0];
  6960. }
  6961. argsComma.push(value);
  6962. }
  6963. if (parserInput.$char(',')) {
  6964. continue;
  6965. }
  6966. if (parserInput.$char(';') || isSemiColonSeparated) {
  6967. isSemiColonSeparated = true;
  6968. value = (argsComma.length < 1) ? argsComma[0]
  6969. : new tree.Value(argsComma);
  6970. argsSemiColon.push(value);
  6971. argsComma = [];
  6972. }
  6973. }
  6974. parserInput.forget();
  6975. return isSemiColonSeparated ? argsSemiColon : argsComma;
  6976. },
  6977. literal: function () {
  6978. return this.dimension() ||
  6979. this.color() ||
  6980. this.quoted() ||
  6981. this.unicodeDescriptor();
  6982. },
  6983. // Assignments are argument entities for calls.
  6984. // They are present in ie filter properties as shown below.
  6985. //
  6986. // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* )
  6987. //
  6988. assignment: function () {
  6989. var key;
  6990. var value;
  6991. parserInput.save();
  6992. key = parserInput.$re(/^\w+(?=\s?=)/i);
  6993. if (!key) {
  6994. parserInput.restore();
  6995. return;
  6996. }
  6997. if (!parserInput.$char('=')) {
  6998. parserInput.restore();
  6999. return;
  7000. }
  7001. value = parsers.entity();
  7002. if (value) {
  7003. parserInput.forget();
  7004. return new (tree.Assignment)(key, value);
  7005. }
  7006. else {
  7007. parserInput.restore();
  7008. }
  7009. },
  7010. //
  7011. // Parse url() tokens
  7012. //
  7013. // We use a specific rule for urls, because they don't really behave like
  7014. // standard function calls. The difference is that the argument doesn't have
  7015. // to be enclosed within a string, so it can't be parsed as an Expression.
  7016. //
  7017. url: function () {
  7018. var value;
  7019. var index = parserInput.i;
  7020. parserInput.autoCommentAbsorb = false;
  7021. if (!parserInput.$str('url(')) {
  7022. parserInput.autoCommentAbsorb = true;
  7023. return;
  7024. }
  7025. value = this.quoted() || this.variable() || this.property() ||
  7026. parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || '';
  7027. parserInput.autoCommentAbsorb = true;
  7028. expectChar(')');
  7029. return new (tree.URL)((value.value != null ||
  7030. value instanceof tree.Variable ||
  7031. value instanceof tree.Property) ?
  7032. value : new (tree.Anonymous)(value, index), index, fileInfo);
  7033. },
  7034. //
  7035. // A Variable entity, such as `@fink`, in
  7036. //
  7037. // width: @fink + 2px
  7038. //
  7039. // We use a different parser for variable definitions,
  7040. // see `parsers.variable`.
  7041. //
  7042. variable: function () {
  7043. var ch;
  7044. var name;
  7045. var index = parserInput.i;
  7046. parserInput.save();
  7047. if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) {
  7048. ch = parserInput.currentChar();
  7049. if (ch === '(' || ch === '[' && !parserInput.prevChar().match(/^\s/)) {
  7050. // this may be a VariableCall lookup
  7051. var result = parsers.variableCall(name);
  7052. if (result) {
  7053. parserInput.forget();
  7054. return result;
  7055. }
  7056. }
  7057. parserInput.forget();
  7058. return new (tree.Variable)(name, index, fileInfo);
  7059. }
  7060. parserInput.restore();
  7061. },
  7062. // A variable entity using the protective {} e.g. @{var}
  7063. variableCurly: function () {
  7064. var curly;
  7065. var index = parserInput.i;
  7066. if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) {
  7067. return new (tree.Variable)("@" + curly[1], index, fileInfo);
  7068. }
  7069. },
  7070. //
  7071. // A Property accessor, such as `$color`, in
  7072. //
  7073. // background-color: $color
  7074. //
  7075. property: function () {
  7076. var name;
  7077. var index = parserInput.i;
  7078. if (parserInput.currentChar() === '$' && (name = parserInput.$re(/^\$[\w-]+/))) {
  7079. return new (tree.Property)(name, index, fileInfo);
  7080. }
  7081. },
  7082. // A property entity useing the protective {} e.g. ${prop}
  7083. propertyCurly: function () {
  7084. var curly;
  7085. var index = parserInput.i;
  7086. if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) {
  7087. return new (tree.Property)("$" + curly[1], index, fileInfo);
  7088. }
  7089. },
  7090. //
  7091. // A Hexadecimal color
  7092. //
  7093. // #4F3C2F
  7094. //
  7095. // `rgb` and `hsl` colors are parsed through the `entities.call` parser.
  7096. //
  7097. color: function () {
  7098. var rgb;
  7099. parserInput.save();
  7100. if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3,4})([\w.#\[])?/))) {
  7101. if (!rgb[2]) {
  7102. parserInput.forget();
  7103. return new (tree.Color)(rgb[1], undefined, rgb[0]);
  7104. }
  7105. }
  7106. parserInput.restore();
  7107. },
  7108. colorKeyword: function () {
  7109. parserInput.save();
  7110. var autoCommentAbsorb = parserInput.autoCommentAbsorb;
  7111. parserInput.autoCommentAbsorb = false;
  7112. var k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);
  7113. parserInput.autoCommentAbsorb = autoCommentAbsorb;
  7114. if (!k) {
  7115. parserInput.forget();
  7116. return;
  7117. }
  7118. parserInput.restore();
  7119. var color = tree.Color.fromKeyword(k);
  7120. if (color) {
  7121. parserInput.$str(k);
  7122. return color;
  7123. }
  7124. },
  7125. //
  7126. // A Dimension, that is, a number and a unit
  7127. //
  7128. // 0.5em 95%
  7129. //
  7130. dimension: function () {
  7131. if (parserInput.peekNotNumeric()) {
  7132. return;
  7133. }
  7134. var value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);
  7135. if (value) {
  7136. return new (tree.Dimension)(value[1], value[2]);
  7137. }
  7138. },
  7139. //
  7140. // A unicode descriptor, as is used in unicode-range
  7141. //
  7142. // U+0?? or U+00A1-00A9
  7143. //
  7144. unicodeDescriptor: function () {
  7145. var ud;
  7146. ud = parserInput.$re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/);
  7147. if (ud) {
  7148. return new (tree.UnicodeDescriptor)(ud[0]);
  7149. }
  7150. },
  7151. //
  7152. // JavaScript code to be evaluated
  7153. //
  7154. // `window.location.href`
  7155. //
  7156. javascript: function () {
  7157. var js;
  7158. var index = parserInput.i;
  7159. parserInput.save();
  7160. var escape = parserInput.$char('~');
  7161. var jsQuote = parserInput.$char('`');
  7162. if (!jsQuote) {
  7163. parserInput.restore();
  7164. return;
  7165. }
  7166. js = parserInput.$re(/^[^`]*`/);
  7167. if (js) {
  7168. parserInput.forget();
  7169. return new (tree.JavaScript)(js.substr(0, js.length - 1), Boolean(escape), index, fileInfo);
  7170. }
  7171. parserInput.restore('invalid javascript definition');
  7172. }
  7173. },
  7174. //
  7175. // The variable part of a variable definition. Used in the `rule` parser
  7176. //
  7177. // @fink:
  7178. //
  7179. variable: function () {
  7180. var name;
  7181. if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) {
  7182. return name[1];
  7183. }
  7184. },
  7185. //
  7186. // Call a variable value to retrieve a detached ruleset
  7187. // or a value from a detached ruleset's rules.
  7188. //
  7189. // @fink();
  7190. // @fink;
  7191. // color: @fink[@color];
  7192. //
  7193. variableCall: function (parsedName) {
  7194. var lookups;
  7195. var i = parserInput.i;
  7196. var inValue = !!parsedName;
  7197. var name = parsedName;
  7198. parserInput.save();
  7199. if (name || (parserInput.currentChar() === '@'
  7200. && (name = parserInput.$re(/^(@[\w-]+)(\(\s*\))?/)))) {
  7201. lookups = this.mixin.ruleLookups();
  7202. if (!lookups && ((inValue && parserInput.$str('()') !== '()') || (name[2] !== '()'))) {
  7203. parserInput.restore('Missing \'[...]\' lookup in variable call');
  7204. return;
  7205. }
  7206. if (!inValue) {
  7207. name = name[1];
  7208. }
  7209. var call = new tree.VariableCall(name, i, fileInfo);
  7210. if (!inValue && parsers.end()) {
  7211. parserInput.forget();
  7212. return call;
  7213. }
  7214. else {
  7215. parserInput.forget();
  7216. return new tree.NamespaceValue(call, lookups, i, fileInfo);
  7217. }
  7218. }
  7219. parserInput.restore();
  7220. },
  7221. //
  7222. // extend syntax - used to extend selectors
  7223. //
  7224. extend: function (isRule) {
  7225. var elements;
  7226. var e;
  7227. var index = parserInput.i;
  7228. var option;
  7229. var extendList;
  7230. var extend;
  7231. if (!parserInput.$str(isRule ? '&:extend(' : ':extend(')) {
  7232. return;
  7233. }
  7234. do {
  7235. option = null;
  7236. elements = null;
  7237. while (!(option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
  7238. e = this.element();
  7239. if (!e) {
  7240. break;
  7241. }
  7242. if (elements) {
  7243. elements.push(e);
  7244. }
  7245. else {
  7246. elements = [e];
  7247. }
  7248. }
  7249. option = option && option[1];
  7250. if (!elements) {
  7251. error('Missing target selector for :extend().');
  7252. }
  7253. extend = new (tree.Extend)(new (tree.Selector)(elements), option, index, fileInfo);
  7254. if (extendList) {
  7255. extendList.push(extend);
  7256. }
  7257. else {
  7258. extendList = [extend];
  7259. }
  7260. } while (parserInput.$char(','));
  7261. expect(/^\)/);
  7262. if (isRule) {
  7263. expect(/^;/);
  7264. }
  7265. return extendList;
  7266. },
  7267. //
  7268. // extendRule - used in a rule to extend all the parent selectors
  7269. //
  7270. extendRule: function () {
  7271. return this.extend(true);
  7272. },
  7273. //
  7274. // Mixins
  7275. //
  7276. mixin: {
  7277. //
  7278. // A Mixin call, with an optional argument list
  7279. //
  7280. // #mixins > .square(#fff);
  7281. // #mixins.square(#fff);
  7282. // .rounded(4px, black);
  7283. // .button;
  7284. //
  7285. // We can lookup / return a value using the lookup syntax:
  7286. //
  7287. // color: #mixin.square(#fff)[@color];
  7288. //
  7289. // The `while` loop is there because mixins can be
  7290. // namespaced, but we only support the child and descendant
  7291. // selector for now.
  7292. //
  7293. call: function (inValue, getLookup) {
  7294. var s = parserInput.currentChar();
  7295. var important = false;
  7296. var lookups;
  7297. var index = parserInput.i;
  7298. var elements;
  7299. var args;
  7300. var hasParens;
  7301. if (s !== '.' && s !== '#') {
  7302. return;
  7303. }
  7304. parserInput.save(); // stop us absorbing part of an invalid selector
  7305. elements = this.elements();
  7306. if (elements) {
  7307. if (parserInput.$char('(')) {
  7308. args = this.args(true).args;
  7309. expectChar(')');
  7310. hasParens = true;
  7311. }
  7312. if (getLookup !== false) {
  7313. lookups = this.ruleLookups();
  7314. }
  7315. if (getLookup === true && !lookups) {
  7316. parserInput.restore();
  7317. return;
  7318. }
  7319. if (inValue && !lookups && !hasParens) {
  7320. // This isn't a valid in-value mixin call
  7321. parserInput.restore();
  7322. return;
  7323. }
  7324. if (!inValue && parsers.important()) {
  7325. important = true;
  7326. }
  7327. if (inValue || parsers.end()) {
  7328. parserInput.forget();
  7329. var mixin = new (tree.mixin.Call)(elements, args, index, fileInfo, !lookups && important);
  7330. if (lookups) {
  7331. return new tree.NamespaceValue(mixin, lookups);
  7332. }
  7333. else {
  7334. return mixin;
  7335. }
  7336. }
  7337. }
  7338. parserInput.restore();
  7339. },
  7340. /**
  7341. * Matching elements for mixins
  7342. * (Start with . or # and can have > )
  7343. */
  7344. elements: function () {
  7345. var elements;
  7346. var e;
  7347. var c;
  7348. var elem;
  7349. var elemIndex;
  7350. var re = /^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/;
  7351. while (true) {
  7352. elemIndex = parserInput.i;
  7353. e = parserInput.$re(re);
  7354. if (!e) {
  7355. break;
  7356. }
  7357. elem = new (tree.Element)(c, e, false, elemIndex, fileInfo);
  7358. if (elements) {
  7359. elements.push(elem);
  7360. }
  7361. else {
  7362. elements = [elem];
  7363. }
  7364. c = parserInput.$char('>');
  7365. }
  7366. return elements;
  7367. },
  7368. args: function (isCall) {
  7369. var entities = parsers.entities;
  7370. var returner = { args: null, variadic: false };
  7371. var expressions = [];
  7372. var argsSemiColon = [];
  7373. var argsComma = [];
  7374. var isSemiColonSeparated;
  7375. var expressionContainsNamed;
  7376. var name;
  7377. var nameLoop;
  7378. var value;
  7379. var arg;
  7380. var expand;
  7381. var hasSep = true;
  7382. parserInput.save();
  7383. while (true) {
  7384. if (isCall) {
  7385. arg = parsers.detachedRuleset() || parsers.expression();
  7386. }
  7387. else {
  7388. parserInput.commentStore.length = 0;
  7389. if (parserInput.$str('...')) {
  7390. returner.variadic = true;
  7391. if (parserInput.$char(';') && !isSemiColonSeparated) {
  7392. isSemiColonSeparated = true;
  7393. }
  7394. (isSemiColonSeparated ? argsSemiColon : argsComma)
  7395. .push({ variadic: true });
  7396. break;
  7397. }
  7398. arg = entities.variable() || entities.property() || entities.literal() || entities.keyword() || this.call(true);
  7399. }
  7400. if (!arg || !hasSep) {
  7401. break;
  7402. }
  7403. nameLoop = null;
  7404. if (arg.throwAwayComments) {
  7405. arg.throwAwayComments();
  7406. }
  7407. value = arg;
  7408. var val = null;
  7409. if (isCall) {
  7410. // Variable
  7411. if (arg.value && arg.value.length == 1) {
  7412. val = arg.value[0];
  7413. }
  7414. }
  7415. else {
  7416. val = arg;
  7417. }
  7418. if (val && (val instanceof tree.Variable || val instanceof tree.Property)) {
  7419. if (parserInput.$char(':')) {
  7420. if (expressions.length > 0) {
  7421. if (isSemiColonSeparated) {
  7422. error('Cannot mix ; and , as delimiter types');
  7423. }
  7424. expressionContainsNamed = true;
  7425. }
  7426. value = parsers.detachedRuleset() || parsers.expression();
  7427. if (!value) {
  7428. if (isCall) {
  7429. error('could not understand value for named argument');
  7430. }
  7431. else {
  7432. parserInput.restore();
  7433. returner.args = [];
  7434. return returner;
  7435. }
  7436. }
  7437. nameLoop = (name = val.name);
  7438. }
  7439. else if (parserInput.$str('...')) {
  7440. if (!isCall) {
  7441. returner.variadic = true;
  7442. if (parserInput.$char(';') && !isSemiColonSeparated) {
  7443. isSemiColonSeparated = true;
  7444. }
  7445. (isSemiColonSeparated ? argsSemiColon : argsComma)
  7446. .push({ name: arg.name, variadic: true });
  7447. break;
  7448. }
  7449. else {
  7450. expand = true;
  7451. }
  7452. }
  7453. else if (!isCall) {
  7454. name = nameLoop = val.name;
  7455. value = null;
  7456. }
  7457. }
  7458. if (value) {
  7459. expressions.push(value);
  7460. }
  7461. argsComma.push({ name: nameLoop, value: value, expand: expand });
  7462. if (parserInput.$char(',')) {
  7463. hasSep = true;
  7464. continue;
  7465. }
  7466. hasSep = parserInput.$char(';') === ';';
  7467. if (hasSep || isSemiColonSeparated) {
  7468. if (expressionContainsNamed) {
  7469. error('Cannot mix ; and , as delimiter types');
  7470. }
  7471. isSemiColonSeparated = true;
  7472. if (expressions.length > 1) {
  7473. value = new (tree.Value)(expressions);
  7474. }
  7475. argsSemiColon.push({ name: name, value: value, expand: expand });
  7476. name = null;
  7477. expressions = [];
  7478. expressionContainsNamed = false;
  7479. }
  7480. }
  7481. parserInput.forget();
  7482. returner.args = isSemiColonSeparated ? argsSemiColon : argsComma;
  7483. return returner;
  7484. },
  7485. //
  7486. // A Mixin definition, with a list of parameters
  7487. //
  7488. // .rounded (@radius: 2px, @color) {
  7489. // ...
  7490. // }
  7491. //
  7492. // Until we have a finer grained state-machine, we have to
  7493. // do a look-ahead, to make sure we don't have a mixin call.
  7494. // See the `rule` function for more information.
  7495. //
  7496. // We start by matching `.rounded (`, and then proceed on to
  7497. // the argument list, which has optional default values.
  7498. // We store the parameters in `params`, with a `value` key,
  7499. // if there is a value, such as in the case of `@radius`.
  7500. //
  7501. // Once we've got our params list, and a closing `)`, we parse
  7502. // the `{...}` block.
  7503. //
  7504. definition: function () {
  7505. var name;
  7506. var params = [];
  7507. var match;
  7508. var ruleset;
  7509. var cond;
  7510. var variadic = false;
  7511. if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
  7512. parserInput.peek(/^[^{]*\}/)) {
  7513. return;
  7514. }
  7515. parserInput.save();
  7516. match = parserInput.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
  7517. if (match) {
  7518. name = match[1];
  7519. var argInfo = this.args(false);
  7520. params = argInfo.args;
  7521. variadic = argInfo.variadic;
  7522. // .mixincall("@{a}");
  7523. // looks a bit like a mixin definition..
  7524. // also
  7525. // .mixincall(@a: {rule: set;});
  7526. // so we have to be nice and restore
  7527. if (!parserInput.$char(')')) {
  7528. parserInput.restore('Missing closing \')\'');
  7529. return;
  7530. }
  7531. parserInput.commentStore.length = 0;
  7532. if (parserInput.$str('when')) { // Guard
  7533. cond = expect(parsers.conditions, 'expected condition');
  7534. }
  7535. ruleset = parsers.block();
  7536. if (ruleset) {
  7537. parserInput.forget();
  7538. return new (tree.mixin.Definition)(name, params, ruleset, cond, variadic);
  7539. }
  7540. else {
  7541. parserInput.restore();
  7542. }
  7543. }
  7544. else {
  7545. parserInput.restore();
  7546. }
  7547. },
  7548. ruleLookups: function () {
  7549. var rule;
  7550. var lookups = [];
  7551. if (parserInput.currentChar() !== '[') {
  7552. return;
  7553. }
  7554. while (true) {
  7555. parserInput.save();
  7556. rule = this.lookupValue();
  7557. if (!rule && rule !== '') {
  7558. parserInput.restore();
  7559. break;
  7560. }
  7561. lookups.push(rule);
  7562. parserInput.forget();
  7563. }
  7564. if (lookups.length > 0) {
  7565. return lookups;
  7566. }
  7567. },
  7568. lookupValue: function () {
  7569. parserInput.save();
  7570. if (!parserInput.$char('[')) {
  7571. parserInput.restore();
  7572. return;
  7573. }
  7574. var name = parserInput.$re(/^(?:[@$]{0,2})[_a-zA-Z0-9-]*/);
  7575. if (!parserInput.$char(']')) {
  7576. parserInput.restore();
  7577. return;
  7578. }
  7579. if (name || name === '') {
  7580. parserInput.forget();
  7581. return name;
  7582. }
  7583. parserInput.restore();
  7584. }
  7585. },
  7586. //
  7587. // Entities are the smallest recognized token,
  7588. // and can be found inside a rule's value.
  7589. //
  7590. entity: function () {
  7591. var entities = this.entities;
  7592. return this.comment() || entities.literal() || entities.variable() || entities.url() ||
  7593. entities.property() || entities.call() || entities.keyword() || this.mixin.call(true) ||
  7594. entities.javascript();
  7595. },
  7596. //
  7597. // A Declaration terminator. Note that we use `peek()` to check for '}',
  7598. // because the `block` rule will be expecting it, but we still need to make sure
  7599. // it's there, if ';' was omitted.
  7600. //
  7601. end: function () {
  7602. return parserInput.$char(';') || parserInput.peek('}');
  7603. },
  7604. //
  7605. // IE's alpha function
  7606. //
  7607. // alpha(opacity=88)
  7608. //
  7609. ieAlpha: function () {
  7610. var value;
  7611. // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
  7612. if (!parserInput.$re(/^opacity=/i)) {
  7613. return;
  7614. }
  7615. value = parserInput.$re(/^\d+/);
  7616. if (!value) {
  7617. value = expect(parsers.entities.variable, 'Could not parse alpha');
  7618. value = "@{" + value.name.slice(1) + "}";
  7619. }
  7620. expectChar(')');
  7621. return new tree.Quoted('', "alpha(opacity=" + value + ")");
  7622. },
  7623. //
  7624. // A Selector Element
  7625. //
  7626. // div
  7627. // + h1
  7628. // #socks
  7629. // input[type="text"]
  7630. //
  7631. // Elements are the building blocks for Selectors,
  7632. // they are made out of a `Combinator` (see combinator rule),
  7633. // and an element name, such as a tag a class, or `*`.
  7634. //
  7635. element: function () {
  7636. var e;
  7637. var c;
  7638. var v;
  7639. var index = parserInput.i;
  7640. c = this.combinator();
  7641. e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
  7642. parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
  7643. parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
  7644. parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
  7645. this.entities.variableCurly();
  7646. if (!e) {
  7647. parserInput.save();
  7648. if (parserInput.$char('(')) {
  7649. if ((v = this.selector(false)) && parserInput.$char(')')) {
  7650. e = new (tree.Paren)(v);
  7651. parserInput.forget();
  7652. }
  7653. else {
  7654. parserInput.restore('Missing closing \')\'');
  7655. }
  7656. }
  7657. else {
  7658. parserInput.forget();
  7659. }
  7660. }
  7661. if (e) {
  7662. return new (tree.Element)(c, e, e instanceof tree.Variable, index, fileInfo);
  7663. }
  7664. },
  7665. //
  7666. // Combinators combine elements together, in a Selector.
  7667. //
  7668. // Because our parser isn't white-space sensitive, special care
  7669. // has to be taken, when parsing the descendant combinator, ` `,
  7670. // as it's an empty space. We have to check the previous character
  7671. // in the input, to see if it's a ` ` character. More info on how
  7672. // we deal with this in *combinator.js*.
  7673. //
  7674. combinator: function () {
  7675. var c = parserInput.currentChar();
  7676. if (c === '/') {
  7677. parserInput.save();
  7678. var slashedCombinator = parserInput.$re(/^\/[a-z]+\//i);
  7679. if (slashedCombinator) {
  7680. parserInput.forget();
  7681. return new (tree.Combinator)(slashedCombinator);
  7682. }
  7683. parserInput.restore();
  7684. }
  7685. if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') {
  7686. parserInput.i++;
  7687. if (c === '^' && parserInput.currentChar() === '^') {
  7688. c = '^^';
  7689. parserInput.i++;
  7690. }
  7691. while (parserInput.isWhitespace()) {
  7692. parserInput.i++;
  7693. }
  7694. return new (tree.Combinator)(c);
  7695. }
  7696. else if (parserInput.isWhitespace(-1)) {
  7697. return new (tree.Combinator)(' ');
  7698. }
  7699. else {
  7700. return new (tree.Combinator)(null);
  7701. }
  7702. },
  7703. //
  7704. // A CSS Selector
  7705. // with less extensions e.g. the ability to extend and guard
  7706. //
  7707. // .class > div + h1
  7708. // li a:hover
  7709. //
  7710. // Selectors are made out of one or more Elements, see above.
  7711. //
  7712. selector: function (isLess) {
  7713. var index = parserInput.i;
  7714. var elements;
  7715. var extendList;
  7716. var c;
  7717. var e;
  7718. var allExtends;
  7719. var when;
  7720. var condition;
  7721. isLess = isLess !== false;
  7722. while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str('when'))) || (e = this.element())) {
  7723. if (when) {
  7724. condition = expect(this.conditions, 'expected condition');
  7725. }
  7726. else if (condition) {
  7727. error('CSS guard can only be used at the end of selector');
  7728. }
  7729. else if (extendList) {
  7730. if (allExtends) {
  7731. allExtends = allExtends.concat(extendList);
  7732. }
  7733. else {
  7734. allExtends = extendList;
  7735. }
  7736. }
  7737. else {
  7738. if (allExtends) {
  7739. error('Extend can only be used at the end of selector');
  7740. }
  7741. c = parserInput.currentChar();
  7742. if (elements) {
  7743. elements.push(e);
  7744. }
  7745. else {
  7746. elements = [e];
  7747. }
  7748. e = null;
  7749. }
  7750. if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') {
  7751. break;
  7752. }
  7753. }
  7754. if (elements) {
  7755. return new (tree.Selector)(elements, allExtends, condition, index, fileInfo);
  7756. }
  7757. if (allExtends) {
  7758. error('Extend must be used to extend a selector, it cannot be used on its own');
  7759. }
  7760. },
  7761. selectors: function () {
  7762. var s;
  7763. var selectors;
  7764. while (true) {
  7765. s = this.selector();
  7766. if (!s) {
  7767. break;
  7768. }
  7769. if (selectors) {
  7770. selectors.push(s);
  7771. }
  7772. else {
  7773. selectors = [s];
  7774. }
  7775. parserInput.commentStore.length = 0;
  7776. if (s.condition && selectors.length > 1) {
  7777. error("Guards are only currently allowed on a single selector.");
  7778. }
  7779. if (!parserInput.$char(',')) {
  7780. break;
  7781. }
  7782. if (s.condition) {
  7783. error("Guards are only currently allowed on a single selector.");
  7784. }
  7785. parserInput.commentStore.length = 0;
  7786. }
  7787. return selectors;
  7788. },
  7789. attribute: function () {
  7790. if (!parserInput.$char('[')) {
  7791. return;
  7792. }
  7793. var entities = this.entities;
  7794. var key;
  7795. var val;
  7796. var op;
  7797. if (!(key = entities.variableCurly())) {
  7798. key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/);
  7799. }
  7800. op = parserInput.$re(/^[|~*$^]?=/);
  7801. if (op) {
  7802. val = entities.quoted() || parserInput.$re(/^[0-9]+%/) || parserInput.$re(/^[\w-]+/) || entities.variableCurly();
  7803. }
  7804. expectChar(']');
  7805. return new (tree.Attribute)(key, op, val);
  7806. },
  7807. //
  7808. // The `block` rule is used by `ruleset` and `mixin.definition`.
  7809. // It's a wrapper around the `primary` rule, with added `{}`.
  7810. //
  7811. block: function () {
  7812. var content;
  7813. if (parserInput.$char('{') && (content = this.primary()) && parserInput.$char('}')) {
  7814. return content;
  7815. }
  7816. },
  7817. blockRuleset: function () {
  7818. var block = this.block();
  7819. if (block) {
  7820. block = new tree.Ruleset(null, block);
  7821. }
  7822. return block;
  7823. },
  7824. detachedRuleset: function () {
  7825. var argInfo;
  7826. var params;
  7827. var variadic;
  7828. parserInput.save();
  7829. if (parserInput.$re(/^[.#]\(/)) {
  7830. /**
  7831. * DR args currently only implemented for each() function, and not
  7832. * yet settable as `@dr: #(@arg) {}`
  7833. * This should be done when DRs are merged with mixins.
  7834. * See: https://github.com/less/less-meta/issues/16
  7835. */
  7836. argInfo = this.mixin.args(false);
  7837. params = argInfo.args;
  7838. variadic = argInfo.variadic;
  7839. if (!parserInput.$char(')')) {
  7840. parserInput.restore();
  7841. return;
  7842. }
  7843. }
  7844. var blockRuleset = this.blockRuleset();
  7845. if (blockRuleset) {
  7846. parserInput.forget();
  7847. if (params) {
  7848. return new tree.mixin.Definition(null, params, blockRuleset, null, variadic);
  7849. }
  7850. return new tree.DetachedRuleset(blockRuleset);
  7851. }
  7852. parserInput.restore();
  7853. },
  7854. //
  7855. // div, .class, body > p {...}
  7856. //
  7857. ruleset: function () {
  7858. var selectors;
  7859. var rules;
  7860. var debugInfo;
  7861. parserInput.save();
  7862. if (context.dumpLineNumbers) {
  7863. debugInfo = getDebugInfo(parserInput.i);
  7864. }
  7865. selectors = this.selectors();
  7866. if (selectors && (rules = this.block())) {
  7867. parserInput.forget();
  7868. var ruleset = new (tree.Ruleset)(selectors, rules, context.strictImports);
  7869. if (context.dumpLineNumbers) {
  7870. ruleset.debugInfo = debugInfo;
  7871. }
  7872. return ruleset;
  7873. }
  7874. else {
  7875. parserInput.restore();
  7876. }
  7877. },
  7878. declaration: function () {
  7879. var name;
  7880. var value;
  7881. var index = parserInput.i;
  7882. var hasDR;
  7883. var c = parserInput.currentChar();
  7884. var important;
  7885. var merge;
  7886. var isVariable;
  7887. if (c === '.' || c === '#' || c === '&' || c === ':') {
  7888. return;
  7889. }
  7890. parserInput.save();
  7891. name = this.variable() || this.ruleProperty();
  7892. if (name) {
  7893. isVariable = typeof name === 'string';
  7894. if (isVariable) {
  7895. value = this.detachedRuleset();
  7896. if (value) {
  7897. hasDR = true;
  7898. }
  7899. }
  7900. parserInput.commentStore.length = 0;
  7901. if (!value) {
  7902. // a name returned by this.ruleProperty() is always an array of the form:
  7903. // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
  7904. // where each item is a tree.Keyword or tree.Variable
  7905. merge = !isVariable && name.length > 1 && name.pop().value;
  7906. // Custom property values get permissive parsing
  7907. if (name[0].value && name[0].value.slice(0, 2) === '--') {
  7908. value = this.permissiveValue();
  7909. }
  7910. // Try to store values as anonymous
  7911. // If we need the value later we'll re-parse it in ruleset.parseValue
  7912. else {
  7913. value = this.anonymousValue();
  7914. }
  7915. if (value) {
  7916. parserInput.forget();
  7917. // anonymous values absorb the end ';' which is required for them to work
  7918. return new (tree.Declaration)(name, value, false, merge, index, fileInfo);
  7919. }
  7920. if (!value) {
  7921. value = this.value();
  7922. }
  7923. if (value) {
  7924. important = this.important();
  7925. }
  7926. else if (isVariable) {
  7927. // As a last resort, try permissiveValue
  7928. value = this.permissiveValue();
  7929. }
  7930. }
  7931. if (value && (this.end() || hasDR)) {
  7932. parserInput.forget();
  7933. return new (tree.Declaration)(name, value, important, merge, index, fileInfo);
  7934. }
  7935. else {
  7936. parserInput.restore();
  7937. }
  7938. }
  7939. else {
  7940. parserInput.restore();
  7941. }
  7942. },
  7943. anonymousValue: function () {
  7944. var index = parserInput.i;
  7945. var match = parserInput.$re(/^([^.#@\$+\/'"*`(;{}-]*);/);
  7946. if (match) {
  7947. return new (tree.Anonymous)(match[1], index);
  7948. }
  7949. },
  7950. /**
  7951. * Used for custom properties, at-rules, and variables (as fallback)
  7952. * Parses almost anything inside of {} [] () "" blocks
  7953. * until it reaches outer-most tokens.
  7954. *
  7955. * First, it will try to parse comments and entities to reach
  7956. * the end. This is mostly like the Expression parser except no
  7957. * math is allowed.
  7958. */
  7959. permissiveValue: function (untilTokens) {
  7960. var i;
  7961. var e;
  7962. var done;
  7963. var value;
  7964. var tok = untilTokens || ';';
  7965. var index = parserInput.i;
  7966. var result = [];
  7967. function testCurrentChar() {
  7968. var char = parserInput.currentChar();
  7969. if (typeof tok === 'string') {
  7970. return char === tok;
  7971. }
  7972. else {
  7973. return tok.test(char);
  7974. }
  7975. }
  7976. if (testCurrentChar()) {
  7977. return;
  7978. }
  7979. value = [];
  7980. do {
  7981. e = this.comment();
  7982. if (e) {
  7983. value.push(e);
  7984. continue;
  7985. }
  7986. e = this.entity();
  7987. if (e) {
  7988. value.push(e);
  7989. }
  7990. } while (e);
  7991. done = testCurrentChar();
  7992. if (value.length > 0) {
  7993. value = new (tree.Expression)(value);
  7994. if (done) {
  7995. return value;
  7996. }
  7997. else {
  7998. result.push(value);
  7999. }
  8000. // Preserve space before $parseUntil as it will not
  8001. if (parserInput.prevChar() === ' ') {
  8002. result.push(new tree.Anonymous(' ', index));
  8003. }
  8004. }
  8005. parserInput.save();
  8006. value = parserInput.$parseUntil(tok);
  8007. if (value) {
  8008. if (typeof value === 'string') {
  8009. error("Expected '" + value + "'", 'Parse');
  8010. }
  8011. if (value.length === 1 && value[0] === ' ') {
  8012. parserInput.forget();
  8013. return new tree.Anonymous('', index);
  8014. }
  8015. var item = void 0;
  8016. for (i = 0; i < value.length; i++) {
  8017. item = value[i];
  8018. if (Array.isArray(item)) {
  8019. // Treat actual quotes as normal quoted values
  8020. result.push(new tree.Quoted(item[0], item[1], true, index, fileInfo));
  8021. }
  8022. else {
  8023. if (i === value.length - 1) {
  8024. item = item.trim();
  8025. }
  8026. // Treat like quoted values, but replace vars like unquoted expressions
  8027. var quote = new tree.Quoted('\'', item, true, index, fileInfo);
  8028. quote.variableRegex = /@([\w-]+)/g;
  8029. quote.propRegex = /\$([\w-]+)/g;
  8030. result.push(quote);
  8031. }
  8032. }
  8033. parserInput.forget();
  8034. return new tree.Expression(result, true);
  8035. }
  8036. parserInput.restore();
  8037. },
  8038. //
  8039. // An @import atrule
  8040. //
  8041. // @import "lib";
  8042. //
  8043. // Depending on our environment, importing is done differently:
  8044. // In the browser, it's an XHR request, in Node, it would be a
  8045. // file-system operation. The function used for importing is
  8046. // stored in `import`, which we pass to the Import constructor.
  8047. //
  8048. 'import': function () {
  8049. var path;
  8050. var features;
  8051. var index = parserInput.i;
  8052. var dir = parserInput.$re(/^@import?\s+/);
  8053. if (dir) {
  8054. var options_1 = (dir ? this.importOptions() : null) || {};
  8055. if ((path = this.entities.quoted() || this.entities.url())) {
  8056. features = this.mediaFeatures();
  8057. if (!parserInput.$char(';')) {
  8058. parserInput.i = index;
  8059. error('missing semi-colon or unrecognised media features on import');
  8060. }
  8061. features = features && new (tree.Value)(features);
  8062. return new (tree.Import)(path, features, options_1, index, fileInfo);
  8063. }
  8064. else {
  8065. parserInput.i = index;
  8066. error('malformed import statement');
  8067. }
  8068. }
  8069. },
  8070. importOptions: function () {
  8071. var o;
  8072. var options = {};
  8073. var optionName;
  8074. var value;
  8075. // list of options, surrounded by parens
  8076. if (!parserInput.$char('(')) {
  8077. return null;
  8078. }
  8079. do {
  8080. o = this.importOption();
  8081. if (o) {
  8082. optionName = o;
  8083. value = true;
  8084. switch (optionName) {
  8085. case 'css':
  8086. optionName = 'less';
  8087. value = false;
  8088. break;
  8089. case 'once':
  8090. optionName = 'multiple';
  8091. value = false;
  8092. break;
  8093. }
  8094. options[optionName] = value;
  8095. if (!parserInput.$char(',')) {
  8096. break;
  8097. }
  8098. }
  8099. } while (o);
  8100. expectChar(')');
  8101. return options;
  8102. },
  8103. importOption: function () {
  8104. var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
  8105. if (opt) {
  8106. return opt[1];
  8107. }
  8108. },
  8109. mediaFeature: function () {
  8110. var entities = this.entities;
  8111. var nodes = [];
  8112. var e;
  8113. var p;
  8114. parserInput.save();
  8115. do {
  8116. e = entities.keyword() || entities.variable() || entities.mixinLookup();
  8117. if (e) {
  8118. nodes.push(e);
  8119. }
  8120. else if (parserInput.$char('(')) {
  8121. p = this.property();
  8122. e = this.value();
  8123. if (parserInput.$char(')')) {
  8124. if (p && e) {
  8125. nodes.push(new (tree.Paren)(new (tree.Declaration)(p, e, null, null, parserInput.i, fileInfo, true)));
  8126. }
  8127. else if (e) {
  8128. nodes.push(new (tree.Paren)(e));
  8129. }
  8130. else {
  8131. error('badly formed media feature definition');
  8132. }
  8133. }
  8134. else {
  8135. error('Missing closing \')\'', 'Parse');
  8136. }
  8137. }
  8138. } while (e);
  8139. parserInput.forget();
  8140. if (nodes.length > 0) {
  8141. return new (tree.Expression)(nodes);
  8142. }
  8143. },
  8144. mediaFeatures: function () {
  8145. var entities = this.entities;
  8146. var features = [];
  8147. var e;
  8148. do {
  8149. e = this.mediaFeature();
  8150. if (e) {
  8151. features.push(e);
  8152. if (!parserInput.$char(',')) {
  8153. break;
  8154. }
  8155. }
  8156. else {
  8157. e = entities.variable() || entities.mixinLookup();
  8158. if (e) {
  8159. features.push(e);
  8160. if (!parserInput.$char(',')) {
  8161. break;
  8162. }
  8163. }
  8164. }
  8165. } while (e);
  8166. return features.length > 0 ? features : null;
  8167. },
  8168. media: function () {
  8169. var features;
  8170. var rules;
  8171. var media;
  8172. var debugInfo;
  8173. var index = parserInput.i;
  8174. if (context.dumpLineNumbers) {
  8175. debugInfo = getDebugInfo(index);
  8176. }
  8177. parserInput.save();
  8178. if (parserInput.$str('@media')) {
  8179. features = this.mediaFeatures();
  8180. rules = this.block();
  8181. if (!rules) {
  8182. error('media definitions require block statements after any features');
  8183. }
  8184. parserInput.forget();
  8185. media = new (tree.Media)(rules, features, index, fileInfo);
  8186. if (context.dumpLineNumbers) {
  8187. media.debugInfo = debugInfo;
  8188. }
  8189. return media;
  8190. }
  8191. parserInput.restore();
  8192. },
  8193. //
  8194. // A @plugin directive, used to import plugins dynamically.
  8195. //
  8196. // @plugin (args) "lib";
  8197. //
  8198. plugin: function () {
  8199. var path;
  8200. var args;
  8201. var options;
  8202. var index = parserInput.i;
  8203. var dir = parserInput.$re(/^@plugin?\s+/);
  8204. if (dir) {
  8205. args = this.pluginArgs();
  8206. if (args) {
  8207. options = {
  8208. pluginArgs: args,
  8209. isPlugin: true
  8210. };
  8211. }
  8212. else {
  8213. options = { isPlugin: true };
  8214. }
  8215. if ((path = this.entities.quoted() || this.entities.url())) {
  8216. if (!parserInput.$char(';')) {
  8217. parserInput.i = index;
  8218. error('missing semi-colon on @plugin');
  8219. }
  8220. return new (tree.Import)(path, null, options, index, fileInfo);
  8221. }
  8222. else {
  8223. parserInput.i = index;
  8224. error('malformed @plugin statement');
  8225. }
  8226. }
  8227. },
  8228. pluginArgs: function () {
  8229. // list of options, surrounded by parens
  8230. parserInput.save();
  8231. if (!parserInput.$char('(')) {
  8232. parserInput.restore();
  8233. return null;
  8234. }
  8235. var args = parserInput.$re(/^\s*([^\);]+)\)\s*/);
  8236. if (args[1]) {
  8237. parserInput.forget();
  8238. return args[1].trim();
  8239. }
  8240. else {
  8241. parserInput.restore();
  8242. return null;
  8243. }
  8244. },
  8245. //
  8246. // A CSS AtRule
  8247. //
  8248. // @charset "utf-8";
  8249. //
  8250. atrule: function () {
  8251. var index = parserInput.i;
  8252. var name;
  8253. var value;
  8254. var rules;
  8255. var nonVendorSpecificName;
  8256. var hasIdentifier;
  8257. var hasExpression;
  8258. var hasUnknown;
  8259. var hasBlock = true;
  8260. var isRooted = true;
  8261. if (parserInput.currentChar() !== '@') {
  8262. return;
  8263. }
  8264. value = this['import']() || this.plugin() || this.media();
  8265. if (value) {
  8266. return value;
  8267. }
  8268. parserInput.save();
  8269. name = parserInput.$re(/^@[a-z-]+/);
  8270. if (!name) {
  8271. return;
  8272. }
  8273. nonVendorSpecificName = name;
  8274. if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
  8275. nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1);
  8276. }
  8277. switch (nonVendorSpecificName) {
  8278. case '@charset':
  8279. hasIdentifier = true;
  8280. hasBlock = false;
  8281. break;
  8282. case '@namespace':
  8283. hasExpression = true;
  8284. hasBlock = false;
  8285. break;
  8286. case '@keyframes':
  8287. case '@counter-style':
  8288. hasIdentifier = true;
  8289. break;
  8290. case '@document':
  8291. case '@supports':
  8292. hasUnknown = true;
  8293. isRooted = false;
  8294. break;
  8295. default:
  8296. hasUnknown = true;
  8297. break;
  8298. }
  8299. parserInput.commentStore.length = 0;
  8300. if (hasIdentifier) {
  8301. value = this.entity();
  8302. if (!value) {
  8303. error("expected " + name + " identifier");
  8304. }
  8305. }
  8306. else if (hasExpression) {
  8307. value = this.expression();
  8308. if (!value) {
  8309. error("expected " + name + " expression");
  8310. }
  8311. }
  8312. else if (hasUnknown) {
  8313. value = this.permissiveValue(/^[{;]/);
  8314. hasBlock = (parserInput.currentChar() === '{');
  8315. if (!value) {
  8316. if (!hasBlock && parserInput.currentChar() !== ';') {
  8317. error(name + " rule is missing block or ending semi-colon");
  8318. }
  8319. }
  8320. else if (!value.value) {
  8321. value = null;
  8322. }
  8323. }
  8324. if (hasBlock) {
  8325. rules = this.blockRuleset();
  8326. }
  8327. if (rules || (!hasBlock && value && parserInput.$char(';'))) {
  8328. parserInput.forget();
  8329. return new (tree.AtRule)(name, value, rules, index, fileInfo, context.dumpLineNumbers ? getDebugInfo(index) : null, isRooted);
  8330. }
  8331. parserInput.restore('at-rule options not recognised');
  8332. },
  8333. //
  8334. // A Value is a comma-delimited list of Expressions
  8335. //
  8336. // font-family: Baskerville, Georgia, serif;
  8337. //
  8338. // In a Rule, a Value represents everything after the `:`,
  8339. // and before the `;`.
  8340. //
  8341. value: function () {
  8342. var e;
  8343. var expressions = [];
  8344. var index = parserInput.i;
  8345. do {
  8346. e = this.expression();
  8347. if (e) {
  8348. expressions.push(e);
  8349. if (!parserInput.$char(',')) {
  8350. break;
  8351. }
  8352. }
  8353. } while (e);
  8354. if (expressions.length > 0) {
  8355. return new (tree.Value)(expressions, index);
  8356. }
  8357. },
  8358. important: function () {
  8359. if (parserInput.currentChar() === '!') {
  8360. return parserInput.$re(/^! *important/);
  8361. }
  8362. },
  8363. sub: function () {
  8364. var a;
  8365. var e;
  8366. parserInput.save();
  8367. if (parserInput.$char('(')) {
  8368. a = this.addition();
  8369. if (a && parserInput.$char(')')) {
  8370. parserInput.forget();
  8371. e = new (tree.Expression)([a]);
  8372. e.parens = true;
  8373. return e;
  8374. }
  8375. parserInput.restore('Expected \')\'');
  8376. return;
  8377. }
  8378. parserInput.restore();
  8379. },
  8380. multiplication: function () {
  8381. var m;
  8382. var a;
  8383. var op;
  8384. var operation;
  8385. var isSpaced;
  8386. m = this.operand();
  8387. if (m) {
  8388. isSpaced = parserInput.isWhitespace(-1);
  8389. while (true) {
  8390. if (parserInput.peek(/^\/[*\/]/)) {
  8391. break;
  8392. }
  8393. parserInput.save();
  8394. op = parserInput.$char('/') || parserInput.$char('*') || parserInput.$str('./');
  8395. if (!op) {
  8396. parserInput.forget();
  8397. break;
  8398. }
  8399. a = this.operand();
  8400. if (!a) {
  8401. parserInput.restore();
  8402. break;
  8403. }
  8404. parserInput.forget();
  8405. m.parensInOp = true;
  8406. a.parensInOp = true;
  8407. operation = new (tree.Operation)(op, [operation || m, a], isSpaced);
  8408. isSpaced = parserInput.isWhitespace(-1);
  8409. }
  8410. return operation || m;
  8411. }
  8412. },
  8413. addition: function () {
  8414. var m;
  8415. var a;
  8416. var op;
  8417. var operation;
  8418. var isSpaced;
  8419. m = this.multiplication();
  8420. if (m) {
  8421. isSpaced = parserInput.isWhitespace(-1);
  8422. while (true) {
  8423. op = parserInput.$re(/^[-+]\s+/) || (!isSpaced && (parserInput.$char('+') || parserInput.$char('-')));
  8424. if (!op) {
  8425. break;
  8426. }
  8427. a = this.multiplication();
  8428. if (!a) {
  8429. break;
  8430. }
  8431. m.parensInOp = true;
  8432. a.parensInOp = true;
  8433. operation = new (tree.Operation)(op, [operation || m, a], isSpaced);
  8434. isSpaced = parserInput.isWhitespace(-1);
  8435. }
  8436. return operation || m;
  8437. }
  8438. },
  8439. conditions: function () {
  8440. var a;
  8441. var b;
  8442. var index = parserInput.i;
  8443. var condition;
  8444. a = this.condition(true);
  8445. if (a) {
  8446. while (true) {
  8447. if (!parserInput.peek(/^,\s*(not\s*)?\(/) || !parserInput.$char(',')) {
  8448. break;
  8449. }
  8450. b = this.condition(true);
  8451. if (!b) {
  8452. break;
  8453. }
  8454. condition = new (tree.Condition)('or', condition || a, b, index);
  8455. }
  8456. return condition || a;
  8457. }
  8458. },
  8459. condition: function (needsParens) {
  8460. var result;
  8461. var logical;
  8462. var next;
  8463. function or() {
  8464. return parserInput.$str('or');
  8465. }
  8466. result = this.conditionAnd(needsParens);
  8467. if (!result) {
  8468. return;
  8469. }
  8470. logical = or();
  8471. if (logical) {
  8472. next = this.condition(needsParens);
  8473. if (next) {
  8474. result = new (tree.Condition)(logical, result, next);
  8475. }
  8476. else {
  8477. return;
  8478. }
  8479. }
  8480. return result;
  8481. },
  8482. conditionAnd: function (needsParens) {
  8483. var result;
  8484. var logical;
  8485. var next;
  8486. var self = this;
  8487. function insideCondition() {
  8488. var cond = self.negatedCondition(needsParens) || self.parenthesisCondition(needsParens);
  8489. if (!cond && !needsParens) {
  8490. return self.atomicCondition(needsParens);
  8491. }
  8492. return cond;
  8493. }
  8494. function and() {
  8495. return parserInput.$str('and');
  8496. }
  8497. result = insideCondition();
  8498. if (!result) {
  8499. return;
  8500. }
  8501. logical = and();
  8502. if (logical) {
  8503. next = this.conditionAnd(needsParens);
  8504. if (next) {
  8505. result = new (tree.Condition)(logical, result, next);
  8506. }
  8507. else {
  8508. return;
  8509. }
  8510. }
  8511. return result;
  8512. },
  8513. negatedCondition: function (needsParens) {
  8514. if (parserInput.$str('not')) {
  8515. var result = this.parenthesisCondition(needsParens);
  8516. if (result) {
  8517. result.negate = !result.negate;
  8518. }
  8519. return result;
  8520. }
  8521. },
  8522. parenthesisCondition: function (needsParens) {
  8523. function tryConditionFollowedByParenthesis(me) {
  8524. var body;
  8525. parserInput.save();
  8526. body = me.condition(needsParens);
  8527. if (!body) {
  8528. parserInput.restore();
  8529. return;
  8530. }
  8531. if (!parserInput.$char(')')) {
  8532. parserInput.restore();
  8533. return;
  8534. }
  8535. parserInput.forget();
  8536. return body;
  8537. }
  8538. var body;
  8539. parserInput.save();
  8540. if (!parserInput.$str('(')) {
  8541. parserInput.restore();
  8542. return;
  8543. }
  8544. body = tryConditionFollowedByParenthesis(this);
  8545. if (body) {
  8546. parserInput.forget();
  8547. return body;
  8548. }
  8549. body = this.atomicCondition(needsParens);
  8550. if (!body) {
  8551. parserInput.restore();
  8552. return;
  8553. }
  8554. if (!parserInput.$char(')')) {
  8555. parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'");
  8556. return;
  8557. }
  8558. parserInput.forget();
  8559. return body;
  8560. },
  8561. atomicCondition: function (needsParens) {
  8562. var entities = this.entities;
  8563. var index = parserInput.i;
  8564. var a;
  8565. var b;
  8566. var c;
  8567. var op;
  8568. function cond() {
  8569. return this.addition() || entities.keyword() || entities.quoted() || entities.mixinLookup();
  8570. }
  8571. cond = cond.bind(this);
  8572. a = cond();
  8573. if (a) {
  8574. if (parserInput.$char('>')) {
  8575. if (parserInput.$char('=')) {
  8576. op = '>=';
  8577. }
  8578. else {
  8579. op = '>';
  8580. }
  8581. }
  8582. else if (parserInput.$char('<')) {
  8583. if (parserInput.$char('=')) {
  8584. op = '<=';
  8585. }
  8586. else {
  8587. op = '<';
  8588. }
  8589. }
  8590. else if (parserInput.$char('=')) {
  8591. if (parserInput.$char('>')) {
  8592. op = '=>';
  8593. }
  8594. else if (parserInput.$char('<')) {
  8595. op = '=<';
  8596. }
  8597. else {
  8598. op = '=';
  8599. }
  8600. }
  8601. if (op) {
  8602. b = cond();
  8603. if (b) {
  8604. c = new (tree.Condition)(op, a, b, index, false);
  8605. }
  8606. else {
  8607. error('expected expression');
  8608. }
  8609. }
  8610. else {
  8611. c = new (tree.Condition)('=', a, new (tree.Keyword)('true'), index, false);
  8612. }
  8613. return c;
  8614. }
  8615. },
  8616. //
  8617. // An operand is anything that can be part of an operation,
  8618. // such as a Color, or a Variable
  8619. //
  8620. operand: function () {
  8621. var entities = this.entities;
  8622. var negate;
  8623. if (parserInput.peek(/^-[@\$\(]/)) {
  8624. negate = parserInput.$char('-');
  8625. }
  8626. var o = this.sub() || entities.dimension() ||
  8627. entities.color() || entities.variable() ||
  8628. entities.property() || entities.call() ||
  8629. entities.quoted(true) || entities.colorKeyword() ||
  8630. entities.mixinLookup();
  8631. if (negate) {
  8632. o.parensInOp = true;
  8633. o = new (tree.Negative)(o);
  8634. }
  8635. return o;
  8636. },
  8637. //
  8638. // Expressions either represent mathematical operations,
  8639. // or white-space delimited Entities.
  8640. //
  8641. // 1px solid black
  8642. // @var * 2
  8643. //
  8644. expression: function () {
  8645. var entities = [];
  8646. var e;
  8647. var delim;
  8648. var index = parserInput.i;
  8649. do {
  8650. e = this.comment();
  8651. if (e) {
  8652. entities.push(e);
  8653. continue;
  8654. }
  8655. e = this.addition() || this.entity();
  8656. if (e) {
  8657. entities.push(e);
  8658. // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here
  8659. if (!parserInput.peek(/^\/[\/*]/)) {
  8660. delim = parserInput.$char('/');
  8661. if (delim) {
  8662. entities.push(new (tree.Anonymous)(delim, index));
  8663. }
  8664. }
  8665. }
  8666. } while (e);
  8667. if (entities.length > 0) {
  8668. return new (tree.Expression)(entities);
  8669. }
  8670. },
  8671. property: function () {
  8672. var name = parserInput.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);
  8673. if (name) {
  8674. return name[1];
  8675. }
  8676. },
  8677. ruleProperty: function () {
  8678. var name = [];
  8679. var index = [];
  8680. var s;
  8681. var k;
  8682. parserInput.save();
  8683. var simpleProperty = parserInput.$re(/^([_a-zA-Z0-9-]+)\s*:/);
  8684. if (simpleProperty) {
  8685. name = [new (tree.Keyword)(simpleProperty[1])];
  8686. parserInput.forget();
  8687. return name;
  8688. }
  8689. function match(re) {
  8690. var i = parserInput.i;
  8691. var chunk = parserInput.$re(re);
  8692. if (chunk) {
  8693. index.push(i);
  8694. return name.push(chunk[1]);
  8695. }
  8696. }
  8697. match(/^(\*?)/);
  8698. while (true) {
  8699. if (!match(/^((?:[\w-]+)|(?:[@\$]\{[\w-]+\}))/)) {
  8700. break;
  8701. }
  8702. }
  8703. if ((name.length > 1) && match(/^((?:\+_|\+)?)\s*:/)) {
  8704. parserInput.forget();
  8705. // at last, we have the complete match now. move forward,
  8706. // convert name particles to tree objects and return:
  8707. if (name[0] === '') {
  8708. name.shift();
  8709. index.shift();
  8710. }
  8711. for (k = 0; k < name.length; k++) {
  8712. s = name[k];
  8713. name[k] = (s.charAt(0) !== '@' && s.charAt(0) !== '$') ?
  8714. new (tree.Keyword)(s) :
  8715. (s.charAt(0) === '@' ?
  8716. new (tree.Variable)("@" + s.slice(2, -1), index[k], fileInfo) :
  8717. new (tree.Property)("$" + s.slice(2, -1), index[k], fileInfo));
  8718. }
  8719. return name;
  8720. }
  8721. parserInput.restore();
  8722. }
  8723. }
  8724. };
  8725. };
  8726. Parser.serializeVars = function (vars) {
  8727. var s = '';
  8728. for (var name_1 in vars) {
  8729. if (Object.hasOwnProperty.call(vars, name_1)) {
  8730. var value = vars[name_1];
  8731. s += ((name_1[0] === '@') ? '' : '@') + name_1 + ": " + value + ((String(value).slice(-1) === ';') ? '' : ';');
  8732. }
  8733. }
  8734. return s;
  8735. };
  8736. function boolean(condition) {
  8737. return condition ? Keyword.True : Keyword.False;
  8738. }
  8739. function If(condition, trueValue, falseValue) {
  8740. return condition ? trueValue
  8741. : (falseValue || new Anonymous);
  8742. }
  8743. var boolean$1 = { boolean: boolean, 'if': If };
  8744. var colorFunctions;
  8745. function clamp$1(val) {
  8746. return Math.min(1, Math.max(0, val));
  8747. }
  8748. function hsla(origColor, hsl) {
  8749. var color = colorFunctions.hsla(hsl.h, hsl.s, hsl.l, hsl.a);
  8750. if (color) {
  8751. if (origColor.value &&
  8752. /^(rgb|hsl)/.test(origColor.value)) {
  8753. color.value = origColor.value;
  8754. }
  8755. else {
  8756. color.value = 'rgb';
  8757. }
  8758. return color;
  8759. }
  8760. }
  8761. function toHSL(color) {
  8762. if (color.toHSL) {
  8763. return color.toHSL();
  8764. }
  8765. else {
  8766. throw new Error('Argument cannot be evaluated to a color');
  8767. }
  8768. }
  8769. function toHSV(color) {
  8770. if (color.toHSV) {
  8771. return color.toHSV();
  8772. }
  8773. else {
  8774. throw new Error('Argument cannot be evaluated to a color');
  8775. }
  8776. }
  8777. function number(n) {
  8778. if (n instanceof Dimension) {
  8779. return parseFloat(n.unit.is('%') ? n.value / 100 : n.value);
  8780. }
  8781. else if (typeof n === 'number') {
  8782. return n;
  8783. }
  8784. else {
  8785. throw {
  8786. type: 'Argument',
  8787. message: 'color functions take numbers as parameters'
  8788. };
  8789. }
  8790. }
  8791. function scaled(n, size) {
  8792. if (n instanceof Dimension && n.unit.is('%')) {
  8793. return parseFloat(n.value * size / 100);
  8794. }
  8795. else {
  8796. return number(n);
  8797. }
  8798. }
  8799. colorFunctions = {
  8800. rgb: function (r, g, b) {
  8801. var color = colorFunctions.rgba(r, g, b, 1.0);
  8802. if (color) {
  8803. color.value = 'rgb';
  8804. return color;
  8805. }
  8806. },
  8807. rgba: function (r, g, b, a) {
  8808. try {
  8809. if (r instanceof Color) {
  8810. if (g) {
  8811. a = number(g);
  8812. }
  8813. else {
  8814. a = r.alpha;
  8815. }
  8816. return new Color(r.rgb, a, 'rgba');
  8817. }
  8818. var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
  8819. a = number(a);
  8820. return new Color(rgb, a, 'rgba');
  8821. }
  8822. catch (e) { }
  8823. },
  8824. hsl: function (h, s, l) {
  8825. var color = colorFunctions.hsla(h, s, l, 1.0);
  8826. if (color) {
  8827. color.value = 'hsl';
  8828. return color;
  8829. }
  8830. },
  8831. hsla: function (h, s, l, a) {
  8832. try {
  8833. if (h instanceof Color) {
  8834. if (s) {
  8835. a = number(s);
  8836. }
  8837. else {
  8838. a = h.alpha;
  8839. }
  8840. return new Color(h.rgb, a, 'hsla');
  8841. }
  8842. var m1_1;
  8843. var m2_1;
  8844. function hue(h) {
  8845. h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
  8846. if (h * 6 < 1) {
  8847. return m1_1 + (m2_1 - m1_1) * h * 6;
  8848. }
  8849. else if (h * 2 < 1) {
  8850. return m2_1;
  8851. }
  8852. else if (h * 3 < 2) {
  8853. return m1_1 + (m2_1 - m1_1) * (2 / 3 - h) * 6;
  8854. }
  8855. else {
  8856. return m1_1;
  8857. }
  8858. }
  8859. h = (number(h) % 360) / 360;
  8860. s = clamp$1(number(s));
  8861. l = clamp$1(number(l));
  8862. a = clamp$1(number(a));
  8863. m2_1 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
  8864. m1_1 = l * 2 - m2_1;
  8865. var rgb = [
  8866. hue(h + 1 / 3) * 255,
  8867. hue(h) * 255,
  8868. hue(h - 1 / 3) * 255
  8869. ];
  8870. a = number(a);
  8871. return new Color(rgb, a, 'hsla');
  8872. }
  8873. catch (e) { }
  8874. },
  8875. hsv: function (h, s, v) {
  8876. return colorFunctions.hsva(h, s, v, 1.0);
  8877. },
  8878. hsva: function (h, s, v, a) {
  8879. h = ((number(h) % 360) / 360) * 360;
  8880. s = number(s);
  8881. v = number(v);
  8882. a = number(a);
  8883. var i;
  8884. var f;
  8885. i = Math.floor((h / 60) % 6);
  8886. f = (h / 60) - i;
  8887. var vs = [v,
  8888. v * (1 - s),
  8889. v * (1 - f * s),
  8890. v * (1 - (1 - f) * s)];
  8891. var perm = [[0, 3, 1],
  8892. [2, 0, 1],
  8893. [1, 0, 3],
  8894. [1, 2, 0],
  8895. [3, 1, 0],
  8896. [0, 1, 2]];
  8897. return colorFunctions.rgba(vs[perm[i][0]] * 255, vs[perm[i][1]] * 255, vs[perm[i][2]] * 255, a);
  8898. },
  8899. hue: function (color) {
  8900. return new Dimension(toHSL(color).h);
  8901. },
  8902. saturation: function (color) {
  8903. return new Dimension(toHSL(color).s * 100, '%');
  8904. },
  8905. lightness: function (color) {
  8906. return new Dimension(toHSL(color).l * 100, '%');
  8907. },
  8908. hsvhue: function (color) {
  8909. return new Dimension(toHSV(color).h);
  8910. },
  8911. hsvsaturation: function (color) {
  8912. return new Dimension(toHSV(color).s * 100, '%');
  8913. },
  8914. hsvvalue: function (color) {
  8915. return new Dimension(toHSV(color).v * 100, '%');
  8916. },
  8917. red: function (color) {
  8918. return new Dimension(color.rgb[0]);
  8919. },
  8920. green: function (color) {
  8921. return new Dimension(color.rgb[1]);
  8922. },
  8923. blue: function (color) {
  8924. return new Dimension(color.rgb[2]);
  8925. },
  8926. alpha: function (color) {
  8927. return new Dimension(toHSL(color).a);
  8928. },
  8929. luma: function (color) {
  8930. return new Dimension(color.luma() * color.alpha * 100, '%');
  8931. },
  8932. luminance: function (color) {
  8933. var luminance = (0.2126 * color.rgb[0] / 255) +
  8934. (0.7152 * color.rgb[1] / 255) +
  8935. (0.0722 * color.rgb[2] / 255);
  8936. return new Dimension(luminance * color.alpha * 100, '%');
  8937. },
  8938. saturate: function (color, amount, method) {
  8939. // filter: saturate(3.2);
  8940. // should be kept as is, so check for color
  8941. if (!color.rgb) {
  8942. return null;
  8943. }
  8944. var hsl = toHSL(color);
  8945. if (typeof method !== 'undefined' && method.value === 'relative') {
  8946. hsl.s += hsl.s * amount.value / 100;
  8947. }
  8948. else {
  8949. hsl.s += amount.value / 100;
  8950. }
  8951. hsl.s = clamp$1(hsl.s);
  8952. return hsla(color, hsl);
  8953. },
  8954. desaturate: function (color, amount, method) {
  8955. var hsl = toHSL(color);
  8956. if (typeof method !== 'undefined' && method.value === 'relative') {
  8957. hsl.s -= hsl.s * amount.value / 100;
  8958. }
  8959. else {
  8960. hsl.s -= amount.value / 100;
  8961. }
  8962. hsl.s = clamp$1(hsl.s);
  8963. return hsla(color, hsl);
  8964. },
  8965. lighten: function (color, amount, method) {
  8966. var hsl = toHSL(color);
  8967. if (typeof method !== 'undefined' && method.value === 'relative') {
  8968. hsl.l += hsl.l * amount.value / 100;
  8969. }
  8970. else {
  8971. hsl.l += amount.value / 100;
  8972. }
  8973. hsl.l = clamp$1(hsl.l);
  8974. return hsla(color, hsl);
  8975. },
  8976. darken: function (color, amount, method) {
  8977. var hsl = toHSL(color);
  8978. if (typeof method !== 'undefined' && method.value === 'relative') {
  8979. hsl.l -= hsl.l * amount.value / 100;
  8980. }
  8981. else {
  8982. hsl.l -= amount.value / 100;
  8983. }
  8984. hsl.l = clamp$1(hsl.l);
  8985. return hsla(color, hsl);
  8986. },
  8987. fadein: function (color, amount, method) {
  8988. var hsl = toHSL(color);
  8989. if (typeof method !== 'undefined' && method.value === 'relative') {
  8990. hsl.a += hsl.a * amount.value / 100;
  8991. }
  8992. else {
  8993. hsl.a += amount.value / 100;
  8994. }
  8995. hsl.a = clamp$1(hsl.a);
  8996. return hsla(color, hsl);
  8997. },
  8998. fadeout: function (color, amount, method) {
  8999. var hsl = toHSL(color);
  9000. if (typeof method !== 'undefined' && method.value === 'relative') {
  9001. hsl.a -= hsl.a * amount.value / 100;
  9002. }
  9003. else {
  9004. hsl.a -= amount.value / 100;
  9005. }
  9006. hsl.a = clamp$1(hsl.a);
  9007. return hsla(color, hsl);
  9008. },
  9009. fade: function (color, amount) {
  9010. var hsl = toHSL(color);
  9011. hsl.a = amount.value / 100;
  9012. hsl.a = clamp$1(hsl.a);
  9013. return hsla(color, hsl);
  9014. },
  9015. spin: function (color, amount) {
  9016. var hsl = toHSL(color);
  9017. var hue = (hsl.h + amount.value) % 360;
  9018. hsl.h = hue < 0 ? 360 + hue : hue;
  9019. return hsla(color, hsl);
  9020. },
  9021. //
  9022. // Copyright (c) 2006-2009 Hampton Catlin, Natalie Weizenbaum, and Chris Eppstein
  9023. // http://sass-lang.com
  9024. //
  9025. mix: function (color1, color2, weight) {
  9026. if (!weight) {
  9027. weight = new Dimension(50);
  9028. }
  9029. var p = weight.value / 100.0;
  9030. var w = p * 2 - 1;
  9031. var a = toHSL(color1).a - toHSL(color2).a;
  9032. var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
  9033. var w2 = 1 - w1;
  9034. var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2,
  9035. color1.rgb[1] * w1 + color2.rgb[1] * w2,
  9036. color1.rgb[2] * w1 + color2.rgb[2] * w2];
  9037. var alpha = color1.alpha * p + color2.alpha * (1 - p);
  9038. return new Color(rgb, alpha);
  9039. },
  9040. greyscale: function (color) {
  9041. return colorFunctions.desaturate(color, new Dimension(100));
  9042. },
  9043. contrast: function (color, dark, light, threshold) {
  9044. // filter: contrast(3.2);
  9045. // should be kept as is, so check for color
  9046. if (!color.rgb) {
  9047. return null;
  9048. }
  9049. if (typeof light === 'undefined') {
  9050. light = colorFunctions.rgba(255, 255, 255, 1.0);
  9051. }
  9052. if (typeof dark === 'undefined') {
  9053. dark = colorFunctions.rgba(0, 0, 0, 1.0);
  9054. }
  9055. // Figure out which is actually light and dark:
  9056. if (dark.luma() > light.luma()) {
  9057. var t = light;
  9058. light = dark;
  9059. dark = t;
  9060. }
  9061. if (typeof threshold === 'undefined') {
  9062. threshold = 0.43;
  9063. }
  9064. else {
  9065. threshold = number(threshold);
  9066. }
  9067. if (color.luma() < threshold) {
  9068. return light;
  9069. }
  9070. else {
  9071. return dark;
  9072. }
  9073. },
  9074. // Changes made in 2.7.0 - Reverted in 3.0.0
  9075. // contrast: function (color, color1, color2, threshold) {
  9076. // // Return which of `color1` and `color2` has the greatest contrast with `color`
  9077. // // according to the standard WCAG contrast ratio calculation.
  9078. // // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
  9079. // // The threshold param is no longer used, in line with SASS.
  9080. // // filter: contrast(3.2);
  9081. // // should be kept as is, so check for color
  9082. // if (!color.rgb) {
  9083. // return null;
  9084. // }
  9085. // if (typeof color1 === 'undefined') {
  9086. // color1 = colorFunctions.rgba(0, 0, 0, 1.0);
  9087. // }
  9088. // if (typeof color2 === 'undefined') {
  9089. // color2 = colorFunctions.rgba(255, 255, 255, 1.0);
  9090. // }
  9091. // var contrast1, contrast2;
  9092. // var luma = color.luma();
  9093. // var luma1 = color1.luma();
  9094. // var luma2 = color2.luma();
  9095. // // Calculate contrast ratios for each color
  9096. // if (luma > luma1) {
  9097. // contrast1 = (luma + 0.05) / (luma1 + 0.05);
  9098. // } else {
  9099. // contrast1 = (luma1 + 0.05) / (luma + 0.05);
  9100. // }
  9101. // if (luma > luma2) {
  9102. // contrast2 = (luma + 0.05) / (luma2 + 0.05);
  9103. // } else {
  9104. // contrast2 = (luma2 + 0.05) / (luma + 0.05);
  9105. // }
  9106. // if (contrast1 > contrast2) {
  9107. // return color1;
  9108. // } else {
  9109. // return color2;
  9110. // }
  9111. // },
  9112. argb: function (color) {
  9113. return new Anonymous(color.toARGB());
  9114. },
  9115. color: function (c) {
  9116. if ((c instanceof Quoted) &&
  9117. (/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3,4})$/i.test(c.value))) {
  9118. var val = c.value.slice(1);
  9119. return new Color(val, undefined, "#" + val);
  9120. }
  9121. if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
  9122. c.value = undefined;
  9123. return c;
  9124. }
  9125. throw {
  9126. type: 'Argument',
  9127. message: 'argument must be a color keyword or 3|4|6|8 digit hex e.g. #FFF'
  9128. };
  9129. },
  9130. tint: function (color, amount) {
  9131. return colorFunctions.mix(colorFunctions.rgb(255, 255, 255), color, amount);
  9132. },
  9133. shade: function (color, amount) {
  9134. return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
  9135. }
  9136. };
  9137. var color = colorFunctions;
  9138. // Color Blending
  9139. // ref: http://www.w3.org/TR/compositing-1
  9140. function colorBlend(mode, color1, color2) {
  9141. var ab = color1.alpha; // result
  9142. var // backdrop
  9143. cb;
  9144. var as = color2.alpha;
  9145. var // source
  9146. cs;
  9147. var ar;
  9148. var cr;
  9149. var r = [];
  9150. ar = as + ab * (1 - as);
  9151. for (var i_1 = 0; i_1 < 3; i_1++) {
  9152. cb = color1.rgb[i_1] / 255;
  9153. cs = color2.rgb[i_1] / 255;
  9154. cr = mode(cb, cs);
  9155. if (ar) {
  9156. cr = (as * cs + ab * (cb -
  9157. as * (cb + cs - cr))) / ar;
  9158. }
  9159. r[i_1] = cr * 255;
  9160. }
  9161. return new Color(r, ar);
  9162. }
  9163. var colorBlendModeFunctions = {
  9164. multiply: function (cb, cs) {
  9165. return cb * cs;
  9166. },
  9167. screen: function (cb, cs) {
  9168. return cb + cs - cb * cs;
  9169. },
  9170. overlay: function (cb, cs) {
  9171. cb *= 2;
  9172. return (cb <= 1) ?
  9173. colorBlendModeFunctions.multiply(cb, cs) :
  9174. colorBlendModeFunctions.screen(cb - 1, cs);
  9175. },
  9176. softlight: function (cb, cs) {
  9177. var d = 1;
  9178. var e = cb;
  9179. if (cs > 0.5) {
  9180. e = 1;
  9181. d = (cb > 0.25) ? Math.sqrt(cb)
  9182. : ((16 * cb - 12) * cb + 4) * cb;
  9183. }
  9184. return cb - (1 - 2 * cs) * e * (d - cb);
  9185. },
  9186. hardlight: function (cb, cs) {
  9187. return colorBlendModeFunctions.overlay(cs, cb);
  9188. },
  9189. difference: function (cb, cs) {
  9190. return Math.abs(cb - cs);
  9191. },
  9192. exclusion: function (cb, cs) {
  9193. return cb + cs - 2 * cb * cs;
  9194. },
  9195. // non-w3c functions:
  9196. average: function (cb, cs) {
  9197. return (cb + cs) / 2;
  9198. },
  9199. negation: function (cb, cs) {
  9200. return 1 - Math.abs(cb + cs - 1);
  9201. }
  9202. };
  9203. for (var f in colorBlendModeFunctions) {
  9204. if (colorBlendModeFunctions.hasOwnProperty(f)) {
  9205. colorBlend[f] = colorBlend.bind(null, colorBlendModeFunctions[f]);
  9206. }
  9207. }
  9208. var dataUri = (function (environment) {
  9209. var fallback = function (functionThis, node) { return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context); };
  9210. return { 'data-uri': function (mimetypeNode, filePathNode) {
  9211. if (!filePathNode) {
  9212. filePathNode = mimetypeNode;
  9213. mimetypeNode = null;
  9214. }
  9215. var mimetype = mimetypeNode && mimetypeNode.value;
  9216. var filePath = filePathNode.value;
  9217. var currentFileInfo = this.currentFileInfo;
  9218. var currentDirectory = currentFileInfo.rewriteUrls ?
  9219. currentFileInfo.currentDirectory : currentFileInfo.entryPath;
  9220. var fragmentStart = filePath.indexOf('#');
  9221. var fragment = '';
  9222. if (fragmentStart !== -1) {
  9223. fragment = filePath.slice(fragmentStart);
  9224. filePath = filePath.slice(0, fragmentStart);
  9225. }
  9226. var context = clone(this.context);
  9227. context.rawBuffer = true;
  9228. var fileManager = environment.getFileManager(filePath, currentDirectory, context, environment, true);
  9229. if (!fileManager) {
  9230. return fallback(this, filePathNode);
  9231. }
  9232. var useBase64 = false;
  9233. // detect the mimetype if not given
  9234. if (!mimetypeNode) {
  9235. mimetype = environment.mimeLookup(filePath);
  9236. if (mimetype === 'image/svg+xml') {
  9237. useBase64 = false;
  9238. }
  9239. else {
  9240. // use base 64 unless it's an ASCII or UTF-8 format
  9241. var charset = environment.charsetLookup(mimetype);
  9242. useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
  9243. }
  9244. if (useBase64) {
  9245. mimetype += ';base64';
  9246. }
  9247. }
  9248. else {
  9249. useBase64 = /;base64$/.test(mimetype);
  9250. }
  9251. var fileSync = fileManager.loadFileSync(filePath, currentDirectory, context, environment);
  9252. if (!fileSync.contents) {
  9253. logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
  9254. return fallback(this, filePathNode || mimetypeNode);
  9255. }
  9256. var buf = fileSync.contents;
  9257. if (useBase64 && !environment.encodeBase64) {
  9258. return fallback(this, filePathNode);
  9259. }
  9260. buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf);
  9261. var uri = "data:" + mimetype + "," + buf + fragment;
  9262. return new URL(new Quoted("\"" + uri + "\"", uri, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
  9263. } };
  9264. });
  9265. var getItemsFromNode = function (node) {
  9266. // handle non-array values as an array of length 1
  9267. // return 'undefined' if index is invalid
  9268. var items = Array.isArray(node.value) ?
  9269. node.value : Array(node);
  9270. return items;
  9271. };
  9272. var list = {
  9273. _SELF: function (n) {
  9274. return n;
  9275. },
  9276. extract: function (values, index) {
  9277. // (1-based index)
  9278. index = index.value - 1;
  9279. return getItemsFromNode(values)[index];
  9280. },
  9281. length: function (values) {
  9282. return new Dimension(getItemsFromNode(values).length);
  9283. },
  9284. /**
  9285. * Creates a Less list of incremental values.
  9286. * Modeled after Lodash's range function, also exists natively in PHP
  9287. *
  9288. * @param {Dimension} [start=1]
  9289. * @param {Dimension} end - e.g. 10 or 10px - unit is added to output
  9290. * @param {Dimension} [step=1]
  9291. */
  9292. range: function (start, end, step) {
  9293. var from;
  9294. var to;
  9295. var stepValue = 1;
  9296. var list = [];
  9297. if (end) {
  9298. to = end;
  9299. from = start.value;
  9300. if (step) {
  9301. stepValue = step.value;
  9302. }
  9303. }
  9304. else {
  9305. from = 1;
  9306. to = start;
  9307. }
  9308. for (var i_1 = from; i_1 <= to.value; i_1 += stepValue) {
  9309. list.push(new Dimension(i_1, to.unit));
  9310. }
  9311. return new Expression(list);
  9312. },
  9313. each: function (list, rs) {
  9314. var rules = [];
  9315. var newRules;
  9316. var iterator;
  9317. if (list.value && !(list instanceof Quoted)) {
  9318. if (Array.isArray(list.value)) {
  9319. iterator = list.value;
  9320. }
  9321. else {
  9322. iterator = [list.value];
  9323. }
  9324. }
  9325. else if (list.ruleset) {
  9326. iterator = list.ruleset.rules;
  9327. }
  9328. else if (list.rules) {
  9329. iterator = list.rules;
  9330. }
  9331. else if (Array.isArray(list)) {
  9332. iterator = list;
  9333. }
  9334. else {
  9335. iterator = [list];
  9336. }
  9337. var valueName = '@value';
  9338. var keyName = '@key';
  9339. var indexName = '@index';
  9340. if (rs.params) {
  9341. valueName = rs.params[0] && rs.params[0].name;
  9342. keyName = rs.params[1] && rs.params[1].name;
  9343. indexName = rs.params[2] && rs.params[2].name;
  9344. rs = rs.rules;
  9345. }
  9346. else {
  9347. rs = rs.ruleset;
  9348. }
  9349. for (var i_2 = 0; i_2 < iterator.length; i_2++) {
  9350. var key = void 0;
  9351. var value = void 0;
  9352. var item = iterator[i_2];
  9353. if (item instanceof Declaration) {
  9354. key = typeof item.name === 'string' ? item.name : item.name[0].value;
  9355. value = item.value;
  9356. }
  9357. else {
  9358. key = new Dimension(i_2 + 1);
  9359. value = item;
  9360. }
  9361. if (item instanceof Comment) {
  9362. continue;
  9363. }
  9364. newRules = rs.rules.slice(0);
  9365. if (valueName) {
  9366. newRules.push(new Declaration(valueName, value, false, false, this.index, this.currentFileInfo));
  9367. }
  9368. if (indexName) {
  9369. newRules.push(new Declaration(indexName, new Dimension(i_2 + 1), false, false, this.index, this.currentFileInfo));
  9370. }
  9371. if (keyName) {
  9372. newRules.push(new Declaration(keyName, key, false, false, this.index, this.currentFileInfo));
  9373. }
  9374. rules.push(new Ruleset([new (Selector)([new Element("", '&')])], newRules, rs.strictImports, rs.visibilityInfo()));
  9375. }
  9376. return new Ruleset([new (Selector)([new Element("", '&')])], rules, rs.strictImports, rs.visibilityInfo()).eval(this.context);
  9377. }
  9378. };
  9379. var MathHelper = function (fn, unit, n) {
  9380. if (!(n instanceof Dimension)) {
  9381. throw { type: 'Argument', message: 'argument must be a number' };
  9382. }
  9383. if (unit == null) {
  9384. unit = n.unit;
  9385. }
  9386. else {
  9387. n = n.unify();
  9388. }
  9389. return new Dimension(fn(parseFloat(n.value)), unit);
  9390. };
  9391. var mathFunctions = {
  9392. // name, unit
  9393. ceil: null,
  9394. floor: null,
  9395. sqrt: null,
  9396. abs: null,
  9397. tan: '',
  9398. sin: '',
  9399. cos: '',
  9400. atan: 'rad',
  9401. asin: 'rad',
  9402. acos: 'rad'
  9403. };
  9404. for (var f$1 in mathFunctions) {
  9405. if (mathFunctions.hasOwnProperty(f$1)) {
  9406. mathFunctions[f$1] = MathHelper.bind(null, Math[f$1], mathFunctions[f$1]);
  9407. }
  9408. }
  9409. mathFunctions.round = function (n, f) {
  9410. var fraction = typeof f === 'undefined' ? 0 : f.value;
  9411. return MathHelper(function (num) { return num.toFixed(fraction); }, null, n);
  9412. };
  9413. var minMax = function (isMin, args) {
  9414. args = Array.prototype.slice.call(args);
  9415. switch (args.length) {
  9416. case 0: throw { type: 'Argument', message: 'one or more arguments required' };
  9417. }
  9418. var i; // key is the unit.toString() for unified Dimension values,
  9419. var j;
  9420. var current;
  9421. var currentUnified;
  9422. var referenceUnified;
  9423. var unit;
  9424. var unitStatic;
  9425. var unitClone;
  9426. var // elems only contains original argument values.
  9427. order = [];
  9428. var values = {};
  9429. // value is the index into the order array.
  9430. for (i = 0; i < args.length; i++) {
  9431. current = args[i];
  9432. if (!(current instanceof Dimension)) {
  9433. if (Array.isArray(args[i].value)) {
  9434. Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value));
  9435. }
  9436. continue;
  9437. }
  9438. currentUnified = current.unit.toString() === '' && unitClone !== undefined ? new Dimension(current.value, unitClone).unify() : current.unify();
  9439. unit = currentUnified.unit.toString() === '' && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString();
  9440. unitStatic = unit !== '' && unitStatic === undefined || unit !== '' && order[0].unify().unit.toString() === '' ? unit : unitStatic;
  9441. unitClone = unit !== '' && unitClone === undefined ? current.unit.toString() : unitClone;
  9442. j = values[''] !== undefined && unit !== '' && unit === unitStatic ? values[''] : values[unit];
  9443. if (j === undefined) {
  9444. if (unitStatic !== undefined && unit !== unitStatic) {
  9445. throw { type: 'Argument', message: 'incompatible types' };
  9446. }
  9447. values[unit] = order.length;
  9448. order.push(current);
  9449. continue;
  9450. }
  9451. referenceUnified = order[j].unit.toString() === '' && unitClone !== undefined ? new Dimension(order[j].value, unitClone).unify() : order[j].unify();
  9452. if (isMin && currentUnified.value < referenceUnified.value ||
  9453. !isMin && currentUnified.value > referenceUnified.value) {
  9454. order[j] = current;
  9455. }
  9456. }
  9457. if (order.length == 1) {
  9458. return order[0];
  9459. }
  9460. args = order.map(function (a) { return a.toCSS(this.context); }).join(this.context.compress ? ',' : ', ');
  9461. return new Anonymous((isMin ? 'min' : 'max') + "(" + args + ")");
  9462. };
  9463. var number$1 = {
  9464. min: function () {
  9465. var args = [];
  9466. for (var _i = 0; _i < arguments.length; _i++) {
  9467. args[_i] = arguments[_i];
  9468. }
  9469. return minMax(true, args);
  9470. },
  9471. max: function () {
  9472. var args = [];
  9473. for (var _i = 0; _i < arguments.length; _i++) {
  9474. args[_i] = arguments[_i];
  9475. }
  9476. return minMax(false, args);
  9477. },
  9478. convert: function (val, unit) {
  9479. return val.convertTo(unit.value);
  9480. },
  9481. pi: function () {
  9482. return new Dimension(Math.PI);
  9483. },
  9484. mod: function (a, b) {
  9485. return new Dimension(a.value % b.value, a.unit);
  9486. },
  9487. pow: function (x, y) {
  9488. if (typeof x === 'number' && typeof y === 'number') {
  9489. x = new Dimension(x);
  9490. y = new Dimension(y);
  9491. }
  9492. else if (!(x instanceof Dimension) || !(y instanceof Dimension)) {
  9493. throw { type: 'Argument', message: 'arguments must be numbers' };
  9494. }
  9495. return new Dimension(Math.pow(x.value, y.value), x.unit);
  9496. },
  9497. percentage: function (n) {
  9498. var result = MathHelper(function (num) { return num * 100; }, '%', n);
  9499. return result;
  9500. }
  9501. };
  9502. var string = {
  9503. e: function (str) {
  9504. return new Quoted('"', str instanceof JavaScript ? str.evaluated : str.value, true);
  9505. },
  9506. escape: function (str) {
  9507. return new Anonymous(encodeURI(str.value).replace(/=/g, '%3D').replace(/:/g, '%3A').replace(/#/g, '%23').replace(/;/g, '%3B')
  9508. .replace(/\(/g, '%28').replace(/\)/g, '%29'));
  9509. },
  9510. replace: function (string, pattern, replacement, flags) {
  9511. var result = string.value;
  9512. replacement = (replacement.type === 'Quoted') ?
  9513. replacement.value : replacement.toCSS();
  9514. result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement);
  9515. return new Quoted(string.quote || '', result, string.escaped);
  9516. },
  9517. '%': function (string /* arg, arg, ... */) {
  9518. var args = Array.prototype.slice.call(arguments, 1);
  9519. var result = string.value;
  9520. var _loop_1 = function (i_1) {
  9521. /* jshint loopfunc:true */
  9522. result = result.replace(/%[sda]/i, function (token) {
  9523. var value = ((args[i_1].type === 'Quoted') &&
  9524. token.match(/s/i)) ? args[i_1].value : args[i_1].toCSS();
  9525. return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value;
  9526. });
  9527. };
  9528. for (var i_1 = 0; i_1 < args.length; i_1++) {
  9529. _loop_1(i_1);
  9530. }
  9531. result = result.replace(/%%/g, '%');
  9532. return new Quoted(string.quote || '', result, string.escaped);
  9533. }
  9534. };
  9535. var svg = (function (environment) {
  9536. return { 'svg-gradient': function (direction) {
  9537. var stops;
  9538. var gradientDirectionSvg;
  9539. var gradientType = 'linear';
  9540. var rectangleDimension = 'x="0" y="0" width="1" height="1"';
  9541. var renderEnv = { compress: false };
  9542. var returner;
  9543. var directionValue = direction.toCSS(renderEnv);
  9544. var i;
  9545. var color;
  9546. var position;
  9547. var positionValue;
  9548. var alpha;
  9549. function throwArgumentDescriptor() {
  9550. throw { type: 'Argument',
  9551. message: 'svg-gradient expects direction, start_color [start_position], [color position,]...,' +
  9552. ' end_color [end_position] or direction, color list' };
  9553. }
  9554. if (arguments.length == 2) {
  9555. if (arguments[1].value.length < 2) {
  9556. throwArgumentDescriptor();
  9557. }
  9558. stops = arguments[1].value;
  9559. }
  9560. else if (arguments.length < 3) {
  9561. throwArgumentDescriptor();
  9562. }
  9563. else {
  9564. stops = Array.prototype.slice.call(arguments, 1);
  9565. }
  9566. switch (directionValue) {
  9567. case 'to bottom':
  9568. gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"';
  9569. break;
  9570. case 'to right':
  9571. gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"';
  9572. break;
  9573. case 'to bottom right':
  9574. gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"';
  9575. break;
  9576. case 'to top right':
  9577. gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"';
  9578. break;
  9579. case 'ellipse':
  9580. case 'ellipse at center':
  9581. gradientType = 'radial';
  9582. gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"';
  9583. rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
  9584. break;
  9585. default:
  9586. throw { type: 'Argument', message: 'svg-gradient direction must be \'to bottom\', \'to right\',' +
  9587. ' \'to bottom right\', \'to top right\' or \'ellipse at center\'' };
  9588. }
  9589. returner = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1 1\"><" + gradientType + "Gradient id=\"g\" " + gradientDirectionSvg + ">";
  9590. for (i = 0; i < stops.length; i += 1) {
  9591. if (stops[i] instanceof Expression) {
  9592. color = stops[i].value[0];
  9593. position = stops[i].value[1];
  9594. }
  9595. else {
  9596. color = stops[i];
  9597. position = undefined;
  9598. }
  9599. if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
  9600. throwArgumentDescriptor();
  9601. }
  9602. positionValue = position ? position.toCSS(renderEnv) : i === 0 ? '0%' : '100%';
  9603. alpha = color.alpha;
  9604. returner += "<stop offset=\"" + positionValue + "\" stop-color=\"" + color.toRGB() + "\"" + (alpha < 1 ? " stop-opacity=\"" + alpha + "\"" : '') + "/>";
  9605. }
  9606. returner += "</" + gradientType + "Gradient><rect " + rectangleDimension + " fill=\"url(#g)\" /></svg>";
  9607. returner = encodeURIComponent(returner);
  9608. returner = "data:image/svg+xml," + returner;
  9609. return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
  9610. } };
  9611. });
  9612. var isa = function (n, Type) { return (n instanceof Type) ? Keyword.True : Keyword.False; };
  9613. var isunit = function (n, unit) {
  9614. if (unit === undefined) {
  9615. throw { type: 'Argument', message: 'missing the required second argument to isunit.' };
  9616. }
  9617. unit = typeof unit.value === 'string' ? unit.value : unit;
  9618. if (typeof unit !== 'string') {
  9619. throw { type: 'Argument', message: 'Second argument to isunit should be a unit or a string.' };
  9620. }
  9621. return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
  9622. };
  9623. var types = {
  9624. isruleset: function (n) {
  9625. return isa(n, DetachedRuleset);
  9626. },
  9627. iscolor: function (n) {
  9628. return isa(n, Color);
  9629. },
  9630. isnumber: function (n) {
  9631. return isa(n, Dimension);
  9632. },
  9633. isstring: function (n) {
  9634. return isa(n, Quoted);
  9635. },
  9636. iskeyword: function (n) {
  9637. return isa(n, Keyword);
  9638. },
  9639. isurl: function (n) {
  9640. return isa(n, URL);
  9641. },
  9642. ispixel: function (n) {
  9643. return isunit(n, 'px');
  9644. },
  9645. ispercentage: function (n) {
  9646. return isunit(n, '%');
  9647. },
  9648. isem: function (n) {
  9649. return isunit(n, 'em');
  9650. },
  9651. isunit: isunit,
  9652. unit: function (val, unit) {
  9653. if (!(val instanceof Dimension)) {
  9654. throw { type: 'Argument',
  9655. message: "the first argument to unit must be a number" + (val instanceof Operation ? '. Have you forgotten parenthesis?' : '') };
  9656. }
  9657. if (unit) {
  9658. if (unit instanceof Keyword) {
  9659. unit = unit.value;
  9660. }
  9661. else {
  9662. unit = unit.toCSS();
  9663. }
  9664. }
  9665. else {
  9666. unit = '';
  9667. }
  9668. return new Dimension(val.value, unit);
  9669. },
  9670. 'get-unit': function (n) {
  9671. return new Anonymous(n.unit);
  9672. }
  9673. };
  9674. var Functions = (function (environment) {
  9675. var functions = { functionRegistry: functionRegistry, functionCaller: functionCaller };
  9676. // register functions
  9677. functionRegistry.addMultiple(boolean$1);
  9678. functionRegistry.add('default', defaultFunc.eval.bind(defaultFunc));
  9679. functionRegistry.addMultiple(color);
  9680. functionRegistry.addMultiple(colorBlend);
  9681. functionRegistry.addMultiple(dataUri(environment));
  9682. functionRegistry.addMultiple(list);
  9683. functionRegistry.addMultiple(mathFunctions);
  9684. functionRegistry.addMultiple(number$1);
  9685. functionRegistry.addMultiple(string);
  9686. functionRegistry.addMultiple(svg());
  9687. functionRegistry.addMultiple(types);
  9688. return functions;
  9689. });
  9690. var sourceMapOutput = (function (environment) {
  9691. var SourceMapOutput = /** @class */ (function () {
  9692. function SourceMapOutput(options) {
  9693. this._css = [];
  9694. this._rootNode = options.rootNode;
  9695. this._contentsMap = options.contentsMap;
  9696. this._contentsIgnoredCharsMap = options.contentsIgnoredCharsMap;
  9697. if (options.sourceMapFilename) {
  9698. this._sourceMapFilename = options.sourceMapFilename.replace(/\\/g, '/');
  9699. }
  9700. this._outputFilename = options.outputFilename;
  9701. this.sourceMapURL = options.sourceMapURL;
  9702. if (options.sourceMapBasepath) {
  9703. this._sourceMapBasepath = options.sourceMapBasepath.replace(/\\/g, '/');
  9704. }
  9705. if (options.sourceMapRootpath) {
  9706. this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
  9707. if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
  9708. this._sourceMapRootpath += '/';
  9709. }
  9710. }
  9711. else {
  9712. this._sourceMapRootpath = '';
  9713. }
  9714. this._outputSourceFiles = options.outputSourceFiles;
  9715. this._sourceMapGeneratorConstructor = environment.getSourceMapGenerator();
  9716. this._lineNumber = 0;
  9717. this._column = 0;
  9718. }
  9719. SourceMapOutput.prototype.removeBasepath = function (path) {
  9720. if (this._sourceMapBasepath && path.indexOf(this._sourceMapBasepath) === 0) {
  9721. path = path.substring(this._sourceMapBasepath.length);
  9722. if (path.charAt(0) === '\\' || path.charAt(0) === '/') {
  9723. path = path.substring(1);
  9724. }
  9725. }
  9726. return path;
  9727. };
  9728. SourceMapOutput.prototype.normalizeFilename = function (filename) {
  9729. filename = filename.replace(/\\/g, '/');
  9730. filename = this.removeBasepath(filename);
  9731. return (this._sourceMapRootpath || '') + filename;
  9732. };
  9733. SourceMapOutput.prototype.add = function (chunk, fileInfo, index, mapLines) {
  9734. // ignore adding empty strings
  9735. if (!chunk) {
  9736. return;
  9737. }
  9738. var lines;
  9739. var sourceLines;
  9740. var columns;
  9741. var sourceColumns;
  9742. var i;
  9743. if (fileInfo && fileInfo.filename) {
  9744. var inputSource = this._contentsMap[fileInfo.filename];
  9745. // remove vars/banner added to the top of the file
  9746. if (this._contentsIgnoredCharsMap[fileInfo.filename]) {
  9747. // adjust the index
  9748. index -= this._contentsIgnoredCharsMap[fileInfo.filename];
  9749. if (index < 0) {
  9750. index = 0;
  9751. }
  9752. // adjust the source
  9753. inputSource = inputSource.slice(this._contentsIgnoredCharsMap[fileInfo.filename]);
  9754. }
  9755. // ignore empty content
  9756. if (inputSource === undefined) {
  9757. return;
  9758. }
  9759. inputSource = inputSource.substring(0, index);
  9760. sourceLines = inputSource.split('\n');
  9761. sourceColumns = sourceLines[sourceLines.length - 1];
  9762. }
  9763. lines = chunk.split('\n');
  9764. columns = lines[lines.length - 1];
  9765. if (fileInfo && fileInfo.filename) {
  9766. if (!mapLines) {
  9767. this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column },
  9768. original: { line: sourceLines.length, column: sourceColumns.length },
  9769. source: this.normalizeFilename(fileInfo.filename) });
  9770. }
  9771. else {
  9772. for (i = 0; i < lines.length; i++) {
  9773. this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0 },
  9774. original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0 },
  9775. source: this.normalizeFilename(fileInfo.filename) });
  9776. }
  9777. }
  9778. }
  9779. if (lines.length === 1) {
  9780. this._column += columns.length;
  9781. }
  9782. else {
  9783. this._lineNumber += lines.length - 1;
  9784. this._column = columns.length;
  9785. }
  9786. this._css.push(chunk);
  9787. };
  9788. SourceMapOutput.prototype.isEmpty = function () {
  9789. return this._css.length === 0;
  9790. };
  9791. SourceMapOutput.prototype.toCSS = function (context) {
  9792. this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
  9793. if (this._outputSourceFiles) {
  9794. for (var filename in this._contentsMap) {
  9795. if (this._contentsMap.hasOwnProperty(filename)) {
  9796. var source = this._contentsMap[filename];
  9797. if (this._contentsIgnoredCharsMap[filename]) {
  9798. source = source.slice(this._contentsIgnoredCharsMap[filename]);
  9799. }
  9800. this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), source);
  9801. }
  9802. }
  9803. }
  9804. this._rootNode.genCSS(context, this);
  9805. if (this._css.length > 0) {
  9806. var sourceMapURL = void 0;
  9807. var sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON());
  9808. if (this.sourceMapURL) {
  9809. sourceMapURL = this.sourceMapURL;
  9810. }
  9811. else if (this._sourceMapFilename) {
  9812. sourceMapURL = this._sourceMapFilename;
  9813. }
  9814. this.sourceMapURL = sourceMapURL;
  9815. this.sourceMap = sourceMapContent;
  9816. }
  9817. return this._css.join('');
  9818. };
  9819. return SourceMapOutput;
  9820. }());
  9821. return SourceMapOutput;
  9822. });
  9823. var sourceMapBuilder = (function (SourceMapOutput, environment) {
  9824. var SourceMapBuilder = /** @class */ (function () {
  9825. function SourceMapBuilder(options) {
  9826. this.options = options;
  9827. }
  9828. SourceMapBuilder.prototype.toCSS = function (rootNode, options, imports) {
  9829. var sourceMapOutput = new SourceMapOutput({
  9830. contentsIgnoredCharsMap: imports.contentsIgnoredChars,
  9831. rootNode: rootNode,
  9832. contentsMap: imports.contents,
  9833. sourceMapFilename: this.options.sourceMapFilename,
  9834. sourceMapURL: this.options.sourceMapURL,
  9835. outputFilename: this.options.sourceMapOutputFilename,
  9836. sourceMapBasepath: this.options.sourceMapBasepath,
  9837. sourceMapRootpath: this.options.sourceMapRootpath,
  9838. outputSourceFiles: this.options.outputSourceFiles,
  9839. sourceMapGenerator: this.options.sourceMapGenerator,
  9840. sourceMapFileInline: this.options.sourceMapFileInline
  9841. });
  9842. var css = sourceMapOutput.toCSS(options);
  9843. this.sourceMap = sourceMapOutput.sourceMap;
  9844. this.sourceMapURL = sourceMapOutput.sourceMapURL;
  9845. if (this.options.sourceMapInputFilename) {
  9846. this.sourceMapInputFilename = sourceMapOutput.normalizeFilename(this.options.sourceMapInputFilename);
  9847. }
  9848. if (this.options.sourceMapBasepath !== undefined && this.sourceMapURL !== undefined) {
  9849. this.sourceMapURL = sourceMapOutput.removeBasepath(this.sourceMapURL);
  9850. }
  9851. return css + this.getCSSAppendage();
  9852. };
  9853. SourceMapBuilder.prototype.getCSSAppendage = function () {
  9854. var sourceMapURL = this.sourceMapURL;
  9855. if (this.options.sourceMapFileInline) {
  9856. if (this.sourceMap === undefined) {
  9857. return '';
  9858. }
  9859. sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap);
  9860. }
  9861. if (sourceMapURL) {
  9862. return "/*# sourceMappingURL=" + sourceMapURL + " */";
  9863. }
  9864. return '';
  9865. };
  9866. SourceMapBuilder.prototype.getExternalSourceMap = function () {
  9867. return this.sourceMap;
  9868. };
  9869. SourceMapBuilder.prototype.setExternalSourceMap = function (sourceMap) {
  9870. this.sourceMap = sourceMap;
  9871. };
  9872. SourceMapBuilder.prototype.isInline = function () {
  9873. return this.options.sourceMapFileInline;
  9874. };
  9875. SourceMapBuilder.prototype.getSourceMapURL = function () {
  9876. return this.sourceMapURL;
  9877. };
  9878. SourceMapBuilder.prototype.getOutputFilename = function () {
  9879. return this.options.sourceMapOutputFilename;
  9880. };
  9881. SourceMapBuilder.prototype.getInputFilename = function () {
  9882. return this.sourceMapInputFilename;
  9883. };
  9884. return SourceMapBuilder;
  9885. }());
  9886. return SourceMapBuilder;
  9887. });
  9888. var transformTree = (function (root, options) {
  9889. if (options === void 0) { options = {}; }
  9890. var evaldRoot;
  9891. var variables = options.variables;
  9892. var evalEnv = new contexts.Eval(options);
  9893. //
  9894. // Allows setting variables with a hash, so:
  9895. //
  9896. // `{ color: new tree.Color('#f01') }` will become:
  9897. //
  9898. // new tree.Declaration('@color',
  9899. // new tree.Value([
  9900. // new tree.Expression([
  9901. // new tree.Color('#f01')
  9902. // ])
  9903. // ])
  9904. // )
  9905. //
  9906. if (typeof variables === 'object' && !Array.isArray(variables)) {
  9907. variables = Object.keys(variables).map(function (k) {
  9908. var value = variables[k];
  9909. if (!(value instanceof tree.Value)) {
  9910. if (!(value instanceof tree.Expression)) {
  9911. value = new tree.Expression([value]);
  9912. }
  9913. value = new tree.Value([value]);
  9914. }
  9915. return new tree.Declaration("@" + k, value, false, null, 0);
  9916. });
  9917. evalEnv.frames = [new tree.Ruleset(null, variables)];
  9918. }
  9919. var visitors$1 = [
  9920. new visitors.JoinSelectorVisitor(),
  9921. new visitors.MarkVisibleSelectorsVisitor(true),
  9922. new visitors.ExtendVisitor(),
  9923. new visitors.ToCSSVisitor({ compress: Boolean(options.compress) })
  9924. ];
  9925. var preEvalVisitors = [];
  9926. var v;
  9927. var visitorIterator;
  9928. /**
  9929. * first() / get() allows visitors to be added while visiting
  9930. *
  9931. * @todo Add scoping for visitors just like functions for @plugin; right now they're global
  9932. */
  9933. if (options.pluginManager) {
  9934. visitorIterator = options.pluginManager.visitor();
  9935. for (var i = 0; i < 2; i++) {
  9936. visitorIterator.first();
  9937. while ((v = visitorIterator.get())) {
  9938. if (v.isPreEvalVisitor) {
  9939. if (i === 0 || preEvalVisitors.indexOf(v) === -1) {
  9940. preEvalVisitors.push(v);
  9941. v.run(root);
  9942. }
  9943. }
  9944. else {
  9945. if (i === 0 || visitors$1.indexOf(v) === -1) {
  9946. if (v.isPreVisitor) {
  9947. visitors$1.unshift(v);
  9948. }
  9949. else {
  9950. visitors$1.push(v);
  9951. }
  9952. }
  9953. }
  9954. }
  9955. }
  9956. }
  9957. evaldRoot = root.eval(evalEnv);
  9958. for (var i = 0; i < visitors$1.length; i++) {
  9959. visitors$1[i].run(evaldRoot);
  9960. }
  9961. // Run any remaining visitors added after eval pass
  9962. if (options.pluginManager) {
  9963. visitorIterator.first();
  9964. while ((v = visitorIterator.get())) {
  9965. if (visitors$1.indexOf(v) === -1 && preEvalVisitors.indexOf(v) === -1) {
  9966. v.run(evaldRoot);
  9967. }
  9968. }
  9969. }
  9970. return evaldRoot;
  9971. });
  9972. var parseTree = (function (SourceMapBuilder) {
  9973. var ParseTree = /** @class */ (function () {
  9974. function ParseTree(root, imports) {
  9975. this.root = root;
  9976. this.imports = imports;
  9977. }
  9978. ParseTree.prototype.toCSS = function (options) {
  9979. var evaldRoot;
  9980. var result = {};
  9981. var sourceMapBuilder;
  9982. try {
  9983. evaldRoot = transformTree(this.root, options);
  9984. }
  9985. catch (e) {
  9986. throw new LessError(e, this.imports);
  9987. }
  9988. try {
  9989. var compress = Boolean(options.compress);
  9990. if (compress) {
  9991. logger.warn('The compress option has been deprecated. ' +
  9992. 'We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.');
  9993. }
  9994. var toCSSOptions = {
  9995. compress: compress,
  9996. dumpLineNumbers: options.dumpLineNumbers,
  9997. strictUnits: Boolean(options.strictUnits),
  9998. numPrecision: 8
  9999. };
  10000. if (options.sourceMap) {
  10001. sourceMapBuilder = new SourceMapBuilder(options.sourceMap);
  10002. result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
  10003. }
  10004. else {
  10005. result.css = evaldRoot.toCSS(toCSSOptions);
  10006. }
  10007. }
  10008. catch (e) {
  10009. throw new LessError(e, this.imports);
  10010. }
  10011. if (options.pluginManager) {
  10012. var postProcessors = options.pluginManager.getPostProcessors();
  10013. for (var i_1 = 0; i_1 < postProcessors.length; i_1++) {
  10014. result.css = postProcessors[i_1].process(result.css, { sourceMap: sourceMapBuilder, options: options, imports: this.imports });
  10015. }
  10016. }
  10017. if (options.sourceMap) {
  10018. result.map = sourceMapBuilder.getExternalSourceMap();
  10019. }
  10020. result.imports = [];
  10021. for (var file_1 in this.imports.files) {
  10022. if (this.imports.files.hasOwnProperty(file_1) && file_1 !== this.imports.rootFilename) {
  10023. result.imports.push(file_1);
  10024. }
  10025. }
  10026. return result;
  10027. };
  10028. return ParseTree;
  10029. }());
  10030. return ParseTree;
  10031. });
  10032. var importManager = (function (environment) {
  10033. // FileInfo = {
  10034. // 'rewriteUrls' - option - whether to adjust URL's to be relative
  10035. // 'filename' - full resolved filename of current file
  10036. // 'rootpath' - path to append to normal URLs for this node
  10037. // 'currentDirectory' - path to the current file, absolute
  10038. // 'rootFilename' - filename of the base file
  10039. // 'entryPath' - absolute path to the entry file
  10040. // 'reference' - whether the file should not be output and only output parts that are referenced
  10041. var ImportManager = /** @class */ (function () {
  10042. function ImportManager(less, context, rootFileInfo) {
  10043. this.less = less;
  10044. this.rootFilename = rootFileInfo.filename;
  10045. this.paths = context.paths || []; // Search paths, when importing
  10046. this.contents = {}; // map - filename to contents of all the files
  10047. this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
  10048. this.mime = context.mime;
  10049. this.error = null;
  10050. this.context = context;
  10051. // Deprecated? Unused outside of here, could be useful.
  10052. this.queue = []; // Files which haven't been imported yet
  10053. this.files = {}; // Holds the imported parse trees.
  10054. }
  10055. /**
  10056. * Add an import to be imported
  10057. * @param path - the raw path
  10058. * @param tryAppendExtension - whether to try appending a file extension (.less or .js if the path has no extension)
  10059. * @param currentFileInfo - the current file info (used for instance to work out relative paths)
  10060. * @param importOptions - import options
  10061. * @param callback - callback for when it is imported
  10062. */
  10063. ImportManager.prototype.push = function (path, tryAppendExtension, currentFileInfo, importOptions, callback) {
  10064. var importManager = this;
  10065. var pluginLoader = this.context.pluginManager.Loader;
  10066. this.queue.push(path);
  10067. var fileParsedFunc = function (e, root, fullPath) {
  10068. importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
  10069. var importedEqualsRoot = fullPath === importManager.rootFilename;
  10070. if (importOptions.optional && e) {
  10071. callback(null, { rules: [] }, false, null);
  10072. logger.info("The file " + fullPath + " was skipped because it was not found and the import was marked optional.");
  10073. }
  10074. else {
  10075. // Inline imports aren't cached here.
  10076. // If we start to cache them, please make sure they won't conflict with non-inline imports of the
  10077. // same name as they used to do before this comment and the condition below have been added.
  10078. if (!importManager.files[fullPath] && !importOptions.inline) {
  10079. importManager.files[fullPath] = { root: root, options: importOptions };
  10080. }
  10081. if (e && !importManager.error) {
  10082. importManager.error = e;
  10083. }
  10084. callback(e, root, importedEqualsRoot, fullPath);
  10085. }
  10086. };
  10087. var newFileInfo = {
  10088. rewriteUrls: this.context.rewriteUrls,
  10089. entryPath: currentFileInfo.entryPath,
  10090. rootpath: currentFileInfo.rootpath,
  10091. rootFilename: currentFileInfo.rootFilename
  10092. };
  10093. var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);
  10094. if (!fileManager) {
  10095. fileParsedFunc({ message: "Could not find a file-manager for " + path });
  10096. return;
  10097. }
  10098. var loadFileCallback = function (loadedFile) {
  10099. var plugin;
  10100. var resolvedFilename = loadedFile.filename;
  10101. var contents = loadedFile.contents.replace(/^\uFEFF/, '');
  10102. // Pass on an updated rootpath if path of imported file is relative and file
  10103. // is in a (sub|sup) directory
  10104. //
  10105. // Examples:
  10106. // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
  10107. // then rootpath should become 'less/module/nav/'
  10108. // - If path of imported file is '../mixins.less' and rootpath is 'less/',
  10109. // then rootpath should become 'less/../'
  10110. newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
  10111. if (newFileInfo.rewriteUrls) {
  10112. newFileInfo.rootpath = fileManager.join((importManager.context.rootpath || ''), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
  10113. if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
  10114. newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
  10115. }
  10116. }
  10117. newFileInfo.filename = resolvedFilename;
  10118. var newEnv = new contexts.Parse(importManager.context);
  10119. newEnv.processImports = false;
  10120. importManager.contents[resolvedFilename] = contents;
  10121. if (currentFileInfo.reference || importOptions.reference) {
  10122. newFileInfo.reference = true;
  10123. }
  10124. if (importOptions.isPlugin) {
  10125. plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo);
  10126. if (plugin instanceof LessError) {
  10127. fileParsedFunc(plugin, null, resolvedFilename);
  10128. }
  10129. else {
  10130. fileParsedFunc(null, plugin, resolvedFilename);
  10131. }
  10132. }
  10133. else if (importOptions.inline) {
  10134. fileParsedFunc(null, contents, resolvedFilename);
  10135. }
  10136. else {
  10137. // import (multiple) parse trees apparently get altered and can't be cached.
  10138. // TODO: investigate why this is
  10139. if (importManager.files[resolvedFilename]
  10140. && !importManager.files[resolvedFilename].options.multiple
  10141. && !importOptions.multiple) {
  10142. fileParsedFunc(null, importManager.files[resolvedFilename].root, resolvedFilename);
  10143. }
  10144. else {
  10145. new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
  10146. fileParsedFunc(e, root, resolvedFilename);
  10147. });
  10148. }
  10149. }
  10150. };
  10151. var promise;
  10152. var context = clone(this.context);
  10153. if (tryAppendExtension) {
  10154. context.ext = importOptions.isPlugin ? '.js' : '.less';
  10155. }
  10156. if (importOptions.isPlugin) {
  10157. context.mime = 'application/javascript';
  10158. promise = pluginLoader.loadPlugin(path, currentFileInfo.currentDirectory, context, environment, fileManager);
  10159. }
  10160. else {
  10161. promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment, function (err, loadedFile) {
  10162. if (err) {
  10163. fileParsedFunc(err);
  10164. }
  10165. else {
  10166. loadFileCallback(loadedFile);
  10167. }
  10168. });
  10169. }
  10170. if (promise) {
  10171. promise.then(loadFileCallback, fileParsedFunc);
  10172. }
  10173. };
  10174. return ImportManager;
  10175. }());
  10176. return ImportManager;
  10177. });
  10178. var Render = (function (environment, ParseTree, ImportManager) {
  10179. var render = function (input, options, callback) {
  10180. if (typeof options === 'function') {
  10181. callback = options;
  10182. options = copyOptions(this.options, {});
  10183. }
  10184. else {
  10185. options = copyOptions(this.options, options || {});
  10186. }
  10187. if (!callback) {
  10188. var self_1 = this;
  10189. return new Promise(function (resolve, reject) {
  10190. render.call(self_1, input, options, function (err, output) {
  10191. if (err) {
  10192. reject(err);
  10193. }
  10194. else {
  10195. resolve(output);
  10196. }
  10197. });
  10198. });
  10199. }
  10200. else {
  10201. this.parse(input, options, function (err, root, imports, options) {
  10202. if (err) {
  10203. return callback(err);
  10204. }
  10205. var result;
  10206. try {
  10207. var parseTree = new ParseTree(root, imports);
  10208. result = parseTree.toCSS(options);
  10209. }
  10210. catch (err) {
  10211. return callback(err);
  10212. }
  10213. callback(null, result);
  10214. });
  10215. }
  10216. };
  10217. return render;
  10218. });
  10219. /**
  10220. * Plugin Manager
  10221. */
  10222. var PluginManager = /** @class */ (function () {
  10223. function PluginManager(less) {
  10224. this.less = less;
  10225. this.visitors = [];
  10226. this.preProcessors = [];
  10227. this.postProcessors = [];
  10228. this.installedPlugins = [];
  10229. this.fileManagers = [];
  10230. this.iterator = -1;
  10231. this.pluginCache = {};
  10232. this.Loader = new less.PluginLoader(less);
  10233. }
  10234. /**
  10235. * Adds all the plugins in the array
  10236. * @param {Array} plugins
  10237. */
  10238. PluginManager.prototype.addPlugins = function (plugins) {
  10239. if (plugins) {
  10240. for (var i_1 = 0; i_1 < plugins.length; i_1++) {
  10241. this.addPlugin(plugins[i_1]);
  10242. }
  10243. }
  10244. };
  10245. /**
  10246. *
  10247. * @param plugin
  10248. * @param {String} filename
  10249. */
  10250. PluginManager.prototype.addPlugin = function (plugin, filename, functionRegistry) {
  10251. this.installedPlugins.push(plugin);
  10252. if (filename) {
  10253. this.pluginCache[filename] = plugin;
  10254. }
  10255. if (plugin.install) {
  10256. plugin.install(this.less, this, functionRegistry || this.less.functions.functionRegistry);
  10257. }
  10258. };
  10259. /**
  10260. *
  10261. * @param filename
  10262. */
  10263. PluginManager.prototype.get = function (filename) {
  10264. return this.pluginCache[filename];
  10265. };
  10266. /**
  10267. * Adds a visitor. The visitor object has options on itself to determine
  10268. * when it should run.
  10269. * @param visitor
  10270. */
  10271. PluginManager.prototype.addVisitor = function (visitor) {
  10272. this.visitors.push(visitor);
  10273. };
  10274. /**
  10275. * Adds a pre processor object
  10276. * @param {object} preProcessor
  10277. * @param {number} priority - guidelines 1 = before import, 1000 = import, 2000 = after import
  10278. */
  10279. PluginManager.prototype.addPreProcessor = function (preProcessor, priority) {
  10280. var indexToInsertAt;
  10281. for (indexToInsertAt = 0; indexToInsertAt < this.preProcessors.length; indexToInsertAt++) {
  10282. if (this.preProcessors[indexToInsertAt].priority >= priority) {
  10283. break;
  10284. }
  10285. }
  10286. this.preProcessors.splice(indexToInsertAt, 0, { preProcessor: preProcessor, priority: priority });
  10287. };
  10288. /**
  10289. * Adds a post processor object
  10290. * @param {object} postProcessor
  10291. * @param {number} priority - guidelines 1 = before compression, 1000 = compression, 2000 = after compression
  10292. */
  10293. PluginManager.prototype.addPostProcessor = function (postProcessor, priority) {
  10294. var indexToInsertAt;
  10295. for (indexToInsertAt = 0; indexToInsertAt < this.postProcessors.length; indexToInsertAt++) {
  10296. if (this.postProcessors[indexToInsertAt].priority >= priority) {
  10297. break;
  10298. }
  10299. }
  10300. this.postProcessors.splice(indexToInsertAt, 0, { postProcessor: postProcessor, priority: priority });
  10301. };
  10302. /**
  10303. *
  10304. * @param manager
  10305. */
  10306. PluginManager.prototype.addFileManager = function (manager) {
  10307. this.fileManagers.push(manager);
  10308. };
  10309. /**
  10310. *
  10311. * @returns {Array}
  10312. * @private
  10313. */
  10314. PluginManager.prototype.getPreProcessors = function () {
  10315. var preProcessors = [];
  10316. for (var i_2 = 0; i_2 < this.preProcessors.length; i_2++) {
  10317. preProcessors.push(this.preProcessors[i_2].preProcessor);
  10318. }
  10319. return preProcessors;
  10320. };
  10321. /**
  10322. *
  10323. * @returns {Array}
  10324. * @private
  10325. */
  10326. PluginManager.prototype.getPostProcessors = function () {
  10327. var postProcessors = [];
  10328. for (var i_3 = 0; i_3 < this.postProcessors.length; i_3++) {
  10329. postProcessors.push(this.postProcessors[i_3].postProcessor);
  10330. }
  10331. return postProcessors;
  10332. };
  10333. /**
  10334. *
  10335. * @returns {Array}
  10336. * @private
  10337. */
  10338. PluginManager.prototype.getVisitors = function () {
  10339. return this.visitors;
  10340. };
  10341. PluginManager.prototype.visitor = function () {
  10342. var self = this;
  10343. return {
  10344. first: function () {
  10345. self.iterator = -1;
  10346. return self.visitors[self.iterator];
  10347. },
  10348. get: function () {
  10349. self.iterator += 1;
  10350. return self.visitors[self.iterator];
  10351. }
  10352. };
  10353. };
  10354. /**
  10355. *
  10356. * @returns {Array}
  10357. * @private
  10358. */
  10359. PluginManager.prototype.getFileManagers = function () {
  10360. return this.fileManagers;
  10361. };
  10362. return PluginManager;
  10363. }());
  10364. var pm;
  10365. function PluginManagerFactory(less, newFactory) {
  10366. if (newFactory || !pm) {
  10367. pm = new PluginManager(less);
  10368. }
  10369. return pm;
  10370. }
  10371. var Parse = (function (environment, ParseTree, ImportManager) {
  10372. var parse = function (input, options, callback) {
  10373. if (typeof options === 'function') {
  10374. callback = options;
  10375. options = copyOptions(this.options, {});
  10376. }
  10377. else {
  10378. options = copyOptions(this.options, options || {});
  10379. }
  10380. if (!callback) {
  10381. var self_1 = this;
  10382. return new Promise(function (resolve, reject) {
  10383. parse.call(self_1, input, options, function (err, output) {
  10384. if (err) {
  10385. reject(err);
  10386. }
  10387. else {
  10388. resolve(output);
  10389. }
  10390. });
  10391. });
  10392. }
  10393. else {
  10394. var context_1;
  10395. var rootFileInfo = void 0;
  10396. var pluginManager_1 = new PluginManagerFactory(this, !options.reUsePluginManager);
  10397. options.pluginManager = pluginManager_1;
  10398. context_1 = new contexts.Parse(options);
  10399. if (options.rootFileInfo) {
  10400. rootFileInfo = options.rootFileInfo;
  10401. }
  10402. else {
  10403. var filename = options.filename || 'input';
  10404. var entryPath = filename.replace(/[^\/\\]*$/, '');
  10405. rootFileInfo = {
  10406. filename: filename,
  10407. rewriteUrls: context_1.rewriteUrls,
  10408. rootpath: context_1.rootpath || '',
  10409. currentDirectory: entryPath,
  10410. entryPath: entryPath,
  10411. rootFilename: filename
  10412. };
  10413. // add in a missing trailing slash
  10414. if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== '/') {
  10415. rootFileInfo.rootpath += '/';
  10416. }
  10417. }
  10418. var imports_1 = new ImportManager(this, context_1, rootFileInfo);
  10419. this.importManager = imports_1;
  10420. // TODO: allow the plugins to be just a list of paths or names
  10421. // Do an async plugin queue like lessc
  10422. if (options.plugins) {
  10423. options.plugins.forEach(function (plugin) {
  10424. var evalResult;
  10425. var contents;
  10426. if (plugin.fileContent) {
  10427. contents = plugin.fileContent.replace(/^\uFEFF/, '');
  10428. evalResult = pluginManager_1.Loader.evalPlugin(contents, context_1, imports_1, plugin.options, plugin.filename);
  10429. if (evalResult instanceof LessError) {
  10430. return callback(evalResult);
  10431. }
  10432. }
  10433. else {
  10434. pluginManager_1.addPlugin(plugin);
  10435. }
  10436. });
  10437. }
  10438. new Parser(context_1, imports_1, rootFileInfo)
  10439. .parse(input, function (e, root) {
  10440. if (e) {
  10441. return callback(e);
  10442. }
  10443. callback(null, root, imports_1, options);
  10444. }, options);
  10445. }
  10446. };
  10447. return parse;
  10448. });
  10449. var createFromEnvironment = (function (environment, fileManagers) {
  10450. /**
  10451. * @todo
  10452. * This original code could be improved quite a bit.
  10453. * Many classes / modules currently add side-effects / mutations to passed in objects,
  10454. * which makes it hard to refactor and reason about.
  10455. */
  10456. environment = new environment$1(environment, fileManagers);
  10457. var SourceMapOutput = sourceMapOutput(environment);
  10458. var SourceMapBuilder = sourceMapBuilder(SourceMapOutput, environment);
  10459. var ParseTree = parseTree(SourceMapBuilder);
  10460. var ImportManager = importManager(environment);
  10461. var render = Render(environment, ParseTree);
  10462. var parse = Parse(environment, ParseTree, ImportManager);
  10463. var functions = Functions(environment);
  10464. /**
  10465. * @todo
  10466. * This root properties / methods need to be organized.
  10467. * It's not clear what should / must be public and why.
  10468. */
  10469. var initial = {
  10470. version: [3, 11, 1],
  10471. data: data,
  10472. tree: tree,
  10473. Environment: environment$1,
  10474. AbstractFileManager: AbstractFileManager,
  10475. AbstractPluginLoader: AbstractPluginLoader,
  10476. environment: environment,
  10477. visitors: visitors,
  10478. Parser: Parser,
  10479. functions: functions,
  10480. contexts: contexts,
  10481. SourceMapOutput: SourceMapOutput,
  10482. SourceMapBuilder: SourceMapBuilder,
  10483. ParseTree: ParseTree,
  10484. ImportManager: ImportManager,
  10485. render: render,
  10486. parse: parse,
  10487. LessError: LessError,
  10488. transformTree: transformTree,
  10489. utils: utils,
  10490. PluginManager: PluginManagerFactory,
  10491. logger: logger
  10492. };
  10493. // Create a public API
  10494. var ctor = function (t) { return function () {
  10495. var args = [];
  10496. for (var _i = 0; _i < arguments.length; _i++) {
  10497. args[_i] = arguments[_i];
  10498. }
  10499. return new (t.bind.apply(t, tslib.__spreadArrays([void 0], args)))();
  10500. }; };
  10501. var t;
  10502. var api = Object.create(initial);
  10503. for (var n in initial.tree) {
  10504. /* eslint guard-for-in: 0 */
  10505. t = initial.tree[n];
  10506. if (typeof t === 'function') {
  10507. api[n.toLowerCase()] = ctor(t);
  10508. }
  10509. else {
  10510. api[n] = Object.create(null);
  10511. for (var o in t) {
  10512. /* eslint guard-for-in: 0 */
  10513. api[n][o.toLowerCase()] = ctor(t[o]);
  10514. }
  10515. }
  10516. }
  10517. return api;
  10518. });
  10519. function createCommonjsModule(fn, module) {
  10520. return module = { exports: {} }, fn(module, module.exports), module.exports;
  10521. }
  10522. var lesscHelper = createCommonjsModule(function (module, exports) {
  10523. // lessc_helper.js
  10524. //
  10525. // helper functions for lessc
  10526. var lessc_helper = {
  10527. // Stylize a string
  10528. stylize: function (str, style) {
  10529. var styles = {
  10530. 'reset': [0, 0],
  10531. 'bold': [1, 22],
  10532. 'inverse': [7, 27],
  10533. 'underline': [4, 24],
  10534. 'yellow': [33, 39],
  10535. 'green': [32, 39],
  10536. 'red': [31, 39],
  10537. 'grey': [90, 39]
  10538. };
  10539. return "\u001B[" + styles[style][0] + "m" + str + "\u001B[" + styles[style][1] + "m";
  10540. },
  10541. // Print command line options
  10542. printUsage: function () {
  10543. console.log('usage: lessc [option option=parameter ...] <source> [destination]');
  10544. console.log('');
  10545. console.log('If source is set to `-\' (dash or hyphen-minus), input is read from stdin.');
  10546. console.log('');
  10547. console.log('options:');
  10548. console.log(' -h, --help Prints help (this message) and exit.');
  10549. console.log(' --include-path=PATHS Sets include paths. Separated by `:\'. `;\' also supported on windows.');
  10550. console.log(' -M, --depends Outputs a makefile import dependency list to stdout.');
  10551. console.log(' --no-color Disables colorized output.');
  10552. console.log(' --ie-compat Enables IE8 compatibility checks.');
  10553. console.log(' --js Enables inline JavaScript in less files');
  10554. console.log(' -l, --lint Syntax check only (lint).');
  10555. console.log(' -s, --silent Suppresses output of error messages.');
  10556. console.log(' --strict-imports Forces evaluation of imports.');
  10557. console.log(' --insecure Allows imports from insecure https hosts.');
  10558. console.log(' -v, --version Prints version number and exit.');
  10559. console.log(' --verbose Be verbose.');
  10560. console.log(' --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map).');
  10561. console.log(' --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths.');
  10562. console.log(' --source-map-basepath=X Sets sourcemap base path, defaults to current working directory.');
  10563. console.log(' --source-map-include-source Puts the less files into the map instead of referencing them.');
  10564. console.log(' --source-map-inline Puts the map (and any less files) as a base64 data uri into the output css file.');
  10565. console.log(' --source-map-url=URL Sets a custom URL to map file, for sourceMappingURL comment');
  10566. console.log(' in generated CSS file.');
  10567. console.log(' -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls');
  10568. console.log(' Works with or without the relative-urls option.');
  10569. console.log(' -ru=, --rewrite-urls= Rewrites URLs to make them relative to the base less file.');
  10570. console.log(' all|local|off \'all\' rewrites all URLs, \'local\' just those starting with a \'.\'');
  10571. console.log('');
  10572. console.log(' -m=, --math=');
  10573. console.log(' always Less will eagerly perform math operations always.');
  10574. console.log(' parens-division Math performed except for division (/) operator');
  10575. console.log(' parens | strict Math only performed inside parentheses');
  10576. console.log(' strict-legacy Parens required in very strict terms (legacy --strict-math)');
  10577. console.log('');
  10578. console.log(' -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units');
  10579. console.log(' --strict-units=on|off that cannot be represented.');
  10580. console.log(' --global-var=\'VAR=VALUE\' Defines a variable that can be referenced by the file.');
  10581. console.log(' --modify-var=\'VAR=VALUE\' Modifies a variable already declared in the file.');
  10582. console.log(' --url-args=\'QUERYSTRING\' Adds params into url tokens (e.g. 42, cb=42 or \'a=1&b=2\')');
  10583. console.log(' --plugin=PLUGIN=OPTIONS Loads a plugin. You can also omit the --plugin= if the plugin begins');
  10584. console.log(' less-plugin. E.g. the clean css plugin is called less-plugin-clean-css');
  10585. console.log(' once installed (npm install less-plugin-clean-css), use either with');
  10586. console.log(' --plugin=less-plugin-clean-css or just --clean-css');
  10587. console.log(' specify options afterwards e.g. --plugin=less-plugin-clean-css="advanced"');
  10588. console.log(' or --clean-css="advanced"');
  10589. console.log('');
  10590. console.log('-------------------------- Deprecated ----------------');
  10591. console.log(' -sm=on|off Legacy parens-only math. Use --math');
  10592. console.log(' --strict-math=on|off ');
  10593. console.log('');
  10594. console.log(' --line-numbers=TYPE Outputs filename and line numbers.');
  10595. console.log(' TYPE can be either \'comments\', which will output');
  10596. console.log(' the debug info within comments, \'mediaquery\'');
  10597. console.log(' that will output the information within a fake');
  10598. console.log(' media query which is compatible with the SASS');
  10599. console.log(' format, and \'all\' which will do both.');
  10600. console.log(' -x, --compress Compresses output by removing some whitespaces.');
  10601. console.log(' We recommend you use a dedicated minifer like less-plugin-clean-css');
  10602. console.log('');
  10603. console.log('Report bugs to: http://github.com/less/less.js/issues');
  10604. console.log('Home page: <http://lesscss.org/>');
  10605. }
  10606. };
  10607. // Exports helper functions
  10608. for (var h in lessc_helper) {
  10609. if (lessc_helper.hasOwnProperty(h)) {
  10610. exports[h] = lessc_helper[h];
  10611. }
  10612. }
  10613. });
  10614. /**
  10615. * Node Plugin Loader
  10616. */
  10617. var PluginLoader = /** @class */ (function (_super) {
  10618. tslib.__extends(PluginLoader, _super);
  10619. function PluginLoader(less) {
  10620. var _this = _super.call(this) || this;
  10621. _this.less = less;
  10622. _this.require = function (prefix) {
  10623. prefix = path.dirname(prefix);
  10624. return function (id) {
  10625. var str = id.substr(0, 2);
  10626. if (str === '..' || str === './') {
  10627. return require(path.join(prefix, id));
  10628. }
  10629. else {
  10630. return require(id);
  10631. }
  10632. };
  10633. };
  10634. return _this;
  10635. }
  10636. PluginLoader.prototype.loadPlugin = function (filename, basePath, context, environment, fileManager) {
  10637. var prefix = filename.slice(0, 1);
  10638. var explicit = prefix === '.' || prefix === '/' || filename.slice(-3).toLowerCase() === '.js';
  10639. if (!explicit) {
  10640. context.prefixes = ['less-plugin-', ''];
  10641. }
  10642. return new Promise(function (fulfill, reject) {
  10643. fileManager.loadFile(filename, basePath, context, environment).then(function (data) {
  10644. try {
  10645. fulfill(data);
  10646. }
  10647. catch (e) {
  10648. console.log(e);
  10649. reject(e);
  10650. }
  10651. }).catch(function (err) {
  10652. reject(err);
  10653. });
  10654. });
  10655. };
  10656. return PluginLoader;
  10657. }(AbstractPluginLoader));
  10658. // Export a new default each time
  10659. var defaultOptions = (function () { return ({
  10660. /* Inline Javascript - @plugin still allowed */
  10661. javascriptEnabled: false,
  10662. /* Outputs a makefile import dependency list to stdout. */
  10663. depends: false,
  10664. /* (DEPRECATED) Compress using less built-in compression.
  10665. * This does an okay job but does not utilise all the tricks of
  10666. * dedicated css compression. */
  10667. compress: false,
  10668. /* Runs the less parser and just reports errors without any output. */
  10669. lint: false,
  10670. /* Sets available include paths.
  10671. * If the file in an @import rule does not exist at that exact location,
  10672. * less will look for it at the location(s) passed to this option.
  10673. * You might use this for instance to specify a path to a library which
  10674. * you want to be referenced simply and relatively in the less files. */
  10675. paths: [],
  10676. /* color output in the terminal */
  10677. color: true,
  10678. /* The strictImports controls whether the compiler will allow an @import inside of either
  10679. * @media blocks or (a later addition) other selector blocks.
  10680. * See: https://github.com/less/less.js/issues/656 */
  10681. strictImports: false,
  10682. /* Allow Imports from Insecure HTTPS Hosts */
  10683. insecure: false,
  10684. /* Allows you to add a path to every generated import and url in your css.
  10685. * This does not affect less import statements that are processed, just ones
  10686. * that are left in the output css. */
  10687. rootpath: '',
  10688. /* By default URLs are kept as-is, so if you import a file in a sub-directory
  10689. * that references an image, exactly the same URL will be output in the css.
  10690. * This option allows you to re-write URL's in imported files so that the
  10691. * URL is always relative to the base imported file */
  10692. rewriteUrls: false,
  10693. /* How to process math
  10694. * 0 always - eagerly try to solve all operations
  10695. * 1 parens-division - require parens for division "/"
  10696. * 2 parens | strict - require parens for all operations
  10697. * 3 strict-legacy - legacy strict behavior (super-strict)
  10698. */
  10699. math: 0,
  10700. /* Without this option, less attempts to guess at the output unit when it does maths. */
  10701. strictUnits: false,
  10702. /* Effectively the declaration is put at the top of your base Less file,
  10703. * meaning it can be used but it also can be overridden if this variable
  10704. * is defined in the file. */
  10705. globalVars: null,
  10706. /* As opposed to the global variable option, this puts the declaration at the
  10707. * end of your base file, meaning it will override anything defined in your Less file. */
  10708. modifyVars: null,
  10709. /* This option allows you to specify a argument to go on to every URL. */
  10710. urlArgs: ''
  10711. }); });
  10712. var imageSize = (function (environment) {
  10713. function imageSize(functionContext, filePathNode) {
  10714. var filePath = filePathNode.value;
  10715. var currentFileInfo = functionContext.currentFileInfo;
  10716. var currentDirectory = currentFileInfo.rewriteUrls ?
  10717. currentFileInfo.currentDirectory : currentFileInfo.entryPath;
  10718. var fragmentStart = filePath.indexOf('#');
  10719. var fragment = '';
  10720. if (fragmentStart !== -1) {
  10721. fragment = filePath.slice(fragmentStart);
  10722. filePath = filePath.slice(0, fragmentStart);
  10723. }
  10724. var fileManager = environment.getFileManager(filePath, currentDirectory, functionContext.context, environment, true);
  10725. if (!fileManager) {
  10726. throw {
  10727. type: 'File',
  10728. message: "Can not set up FileManager for " + filePathNode
  10729. };
  10730. }
  10731. var fileSync = fileManager.loadFileSync(filePath, currentDirectory, functionContext.context, environment);
  10732. if (fileSync.error) {
  10733. throw fileSync.error;
  10734. }
  10735. var sizeOf = require('image-size');
  10736. return sizeOf(fileSync.filename);
  10737. }
  10738. var imageFunctions = {
  10739. 'image-size': function (filePathNode) {
  10740. var size = imageSize(this, filePathNode);
  10741. return new Expression([
  10742. new Dimension(size.width, 'px'),
  10743. new Dimension(size.height, 'px')
  10744. ]);
  10745. },
  10746. 'image-width': function (filePathNode) {
  10747. var size = imageSize(this, filePathNode);
  10748. return new Dimension(size.width, 'px');
  10749. },
  10750. 'image-height': function (filePathNode) {
  10751. var size = imageSize(this, filePathNode);
  10752. return new Dimension(size.height, 'px');
  10753. }
  10754. };
  10755. functionRegistry.addMultiple(imageFunctions);
  10756. });
  10757. var less = createFromEnvironment(environment, [new FileManager(), new UrlFileManager()]);
  10758. // allow people to create less with their own environment
  10759. less.createFromEnvironment = createFromEnvironment;
  10760. less.lesscHelper = lesscHelper;
  10761. less.PluginLoader = PluginLoader;
  10762. less.fs = fs$1;
  10763. less.FileManager = FileManager;
  10764. less.UrlFileManager = UrlFileManager;
  10765. // Set up options
  10766. less.options = defaultOptions();
  10767. // provide image-size functionality
  10768. imageSize(less.environment);
  10769. module.exports = less;