123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168 |
- var Node = require('../node');
- var NodeType = require('../node-types');
- var TokenType = require('../token-types');
- module.exports = (function() {
- var tokens, tokensLength, pos, needInfo;
- var rules = {
- 'arguments': function() { return checkArguments(pos) && getArguments(); },
- 'atkeyword': function() { return checkAtkeyword(pos) && getAtkeyword(); },
- 'atruleb': function() { return checkAtruleb(pos) && getAtruleb(); },
- 'atruler': function() { return checkAtruler(pos) && getAtruler(); },
- 'atrulerq': function() { return checkAtrulerq(pos) && getAtrulerq(); },
- 'atrulers': function() { return checkAtrulers(pos) && getAtrulers(); },
- 'atrules': function() { return checkAtrules(pos) && getAtrules(); },
- 'attrib': function() { return checkAttrib(pos) && getAttrib(); },
- 'attrselector': function() { return checkAttrselector(pos) && getAttrselector(); },
- 'block': function() { return checkBlock(pos) && getBlock(); },
- 'braces': function() { return checkBraces(pos) && getBraces(); },
- 'class': function() { return checkClass(pos) && getClass(); },
- 'combinator': function() { return checkCombinator(pos) && getCombinator(); },
- 'commentML': function() { return checkCommentML(pos) && getCommentML(); },
- 'commentSL': function() { return checkCommentSL(pos) && getCommentSL(); },
- 'condition': function() { return checkCondition(pos) && getCondition(); },
- 'declaration': function() { return checkDeclaration(pos) && getDeclaration(); },
- 'declDelim': function() { return checkDeclDelim(pos) && getDeclDelim(); },
- 'delim': function() { return checkDelim(pos) && getDelim(); },
- 'dimension': function() { return checkDimension(pos) && getDimension(); },
- 'escapedString': function() { return checkEscapedString(pos) && getEscapedString(); },
- 'filter': function() { return checkFilter(pos) && getFilter(); },
- 'filterv': function() { return checkFilterv(pos) && getFilterv(); },
- 'functionExpression': function() { return checkFunctionExpression(pos) && getFunctionExpression(); },
- 'function': function() { return checkFunction(pos) && getFunction(); },
- 'ident': function() { return checkIdent(pos) && getIdent(); },
- 'important': function() { return checkImportant(pos) && getImportant(); },
- 'include': function() { return checkInclude(pos) && getInclude(); },
- 'interpolatedVariable': function() { return checkInterpolatedVariable(pos) && getInterpolatedVariable(); },
- 'mixin': function() { return checkMixin(pos) && getMixin(); },
- 'namespace': function() { return checkNamespace(pos) && getNamespace(); },
- 'nth': function() { return checkNth(pos) && getNth(); },
- 'nthselector': function() { return checkNthselector(pos) && getNthselector(); },
- 'number': function() { return checkNumber(pos) && getNumber(); },
- 'operator': function() { return checkOperator(pos) && getOperator(); },
- 'parentselector': function() { return checkParentSelector(pos) && getParentSelector(); },
- 'percentage': function() { return checkPercentage(pos) && getPercentage(); },
- 'progid': function() { return checkProgid(pos) && getProgid(); },
- 'property': function() { return checkProperty(pos) && getProperty(); },
- 'propertyDelim': function() { return checkPropertyDelim(pos) && getPropertyDelim(); },
- 'pseudoc': function() { return checkPseudoc(pos) && getPseudoc(); },
- 'pseudoe': function() { return checkPseudoe(pos) && getPseudoe(); },
- 'ruleset': function() { return checkRuleset(pos) && getRuleset(); },
- 's': function() { return checkS(pos) && getS(); },
- 'selector': function() { return checkSelector(pos) && getSelector(); },
- 'shash': function() { return checkShash(pos) && getShash(); },
- 'simpleselector': function() { return checkSimpleSelector(pos) && getSimpleSelector(); },
- 'string': function() { return checkString(pos) && getString(); },
- 'stylesheet': function() { return checkStylesheet(pos) && getStylesheet(); },
- 'unary': function() { return checkUnary(pos) && getUnary(); },
- 'uri': function() { return checkUri(pos) && getUri(); },
- 'value': function() { return checkValue(pos) && getValue(); },
- 'variable': function () { return checkVariable(pos) && getVariable(); },
- 'variableslist': function () { return checkVariablesList(pos) && getVariablesList(); },
- 'vhash': function() { return checkVhash(pos) && getVhash(); }
- };
- /**
- * Stop parsing and display error
- * @param {Number=} i Token's index number
- */
- function throwError(i) {
- var ln = tokens[i].ln;
- throw {line: ln, syntax: 'less'};
- }
- /**
- * @param {Object} exclude
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkExcluding(exclude, i) {
- var start = i;
- while(i < tokensLength) {
- if (exclude[tokens[i++].type]) break;
- }
- return i - start - 2;
- }
- /**
- * @param {Number} start
- * @param {Number} finish
- * @returns {String}
- */
- function joinValues(start, finish) {
- var s = '';
- for (var i = start; i < finish + 1; i++) {
- s += tokens[i].value;
- }
- return s;
- }
- /**
- * @param {Number} start
- * @param {Number} num
- * @returns {String}
- */
- function joinValues2(start, num) {
- if (start + num - 1 >= tokensLength) return;
- var s = '';
- for (var i = 0; i < num; i++) {
- s += tokens[start + i].value;
- }
- return s;
- }
- /////////////////////////////////////
- /////////////////////////////////////
- /////////////////////////////////////
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAny(i) {
- var l;
- if (l = checkBraces(i)) tokens[i].any_child = 1;
- else if (l = checkString(i)) tokens[i].any_child = 2;
- else if (l = checkVariablesList(i)) tokens[i].any_child = 3;
- else if (l = checkVariable(i)) tokens[i].any_child = 4;
- else if (l = checkPercentage(i)) tokens[i].any_child = 5;
- else if (l = checkDimension(i)) tokens[i].any_child = 6;
- else if (l = checkNumber(i)) tokens[i].any_child = 7;
- else if (l = checkUri(i)) tokens[i].any_child = 8;
- else if (l = checkFunctionExpression(i)) tokens[i].any_child = 9;
- else if (l = checkFunction(i)) tokens[i].any_child = 10;
- else if (l = checkIdent(i)) tokens[i].any_child = 11;
- else if (l = checkClass(i)) tokens[i].any_child = 12;
- else if (l = checkUnary(i)) tokens[i].any_child = 13;
- return l;
- }
- /**
- * @returns {Array}
- */
- function getAny() {
- var childType = tokens[pos].any_child;
- if (childType === 1) return getBraces();
- if (childType === 2) return getString();
- if (childType === 3) return getVariablesList();
- if (childType === 4) return getVariable();
- if (childType === 5) return getPercentage();
- if (childType === 6) return getDimension();
- if (childType === 7) return getNumber();
- if (childType === 8) return getUri();
- if (childType === 9) return getFunctionExpression();
- if (childType === 10) return getFunction();
- if (childType === 11) return getIdent();
- if (childType === 12) return getClass();
- if (childType === 13) return getUnary();
- }
- /**
- * Check if token is part of mixin's arguments.
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkArguments(i) {
- var start = i,
- l;
- if (i >= tokensLength ||
- tokens[i++].type !== TokenType.LeftParenthesis) return 0;
- while (i < tokens[start].right) {
- if (l = checkArgument(i)) i +=l;
- else return 0;
- }
- return tokens[start].right - start + 1;
- }
- /**
- * Check if token is valid to be part of arguments list.
- * @param i Token's index number
- * @returns {Number}
- */
- function checkArgument(i) {
- var l;
- if (l = checkEscapedString(i)) tokens[i].argument_child = 1;
- else if (l = checkDeclaration(i)) tokens[i].argument_child = 2;
- else if (l = checkVariablesList(i)) tokens[i].argument_child = 3;
- else if (l = checkVariable(i)) tokens[i].argument_child = 4;
- else if (l = checkSC(i)) tokens[i].argument_child = 5;
- else if (l = checkUnary(i)) tokens[i].argument_child = 6;
- else if (l = checkOperator(i)) tokens[i].argument_child = 7;
- else if (l = checkDelim(i)) tokens[i].argument_child = 8;
- else if (l = checkDeclDelim(i)) tokens[i].argument_child = 9;
- else if (l = checkString(i)) tokens[i].argument_child = 10;
- else if (l = checkPercentage(i)) tokens[i].argument_child = 11;
- else if (l = checkDimension(i)) tokens[i].argument_child = 12;
- else if (l = checkNumber(i)) tokens[i].argument_child = 13;
- else if (l = checkUri(i)) tokens[i].argument_child = 14;
- else if (l = checkFunction(i)) tokens[i].argument_child = 15;
- else if (l = checkIdent(i)) tokens[i].argument_child = 16;
- else if (l = checkVhash(i)) tokens[i].argument_child = 17;
- return l;
- }
- /**
- * @returns {Array} Node that is part of arguments list.
- */
- function getArgument() {
- var childType = tokens[pos].argument_child;
- if (childType === 1) return getEscapedString();
- if (childType === 2) return getDeclaration();
- if (childType === 3) return getVariablesList();
- if (childType === 4) return getVariable();
- if (childType === 5) return getSC();
- if (childType === 6) return getUnary();
- if (childType === 7) return getOperator();
- if (childType === 8) return getDelim();
- if (childType === 9) return getDeclDelim();
- if (childType === 10) return getString();
- if (childType === 11) return getPercentage();
- if (childType === 12) return getDimension();
- if (childType === 13) return getNumber();
- if (childType === 14) return getUri();
- if (childType === 15) return getFunction();
- if (childType === 16) return getIdent();
- if (childType === 17) return getVhash();
- }
- /**
- * Check if token is part of an @-word (e.g. `@import`, `@include`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAtkeyword(i) {
- var l;
- // Check that token is `@`:
- if (i >= tokensLength ||
- tokens[i++].type !== TokenType.CommercialAt) return 0;
- return (l = checkIdent(i)) ? l + 1 : 0;
- }
- /**
- * Get node with @-word
- * @returns {Array} `['atkeyword', ['ident', x]]` where `x` is
- * an identifier without
- * `@` (e.g. `import`, `include`)
- */
- function getAtkeyword() {
- var startPos = pos,
- token = tokens[pos++],
- content = [getIdent()];
- return new Node(NodeType.AtkeywordType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of an attribute selector (e.g. `[attr]`,
- * `[attr='panda']`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAttrib(i) {
- if (i >= tokensLength ||
- tokens[i].type !== TokenType.LeftSquareBracket ||
- !tokens[i].right) return 0;
- return tokens[i].right - i + 1;
- }
- /**
- * Get node with an attribute selector
- * @returns {Array} `['attrib', ['ident', x], ['attrselector', y]*, [z]*]`
- * where `x` is attribute's name, `y` is operator (if there is any)
- * and `z` is attribute's value (if there is any)
- */
- function getAttrib() {
- if (checkAttrib1(pos)) return getAttrib1();
- if (checkAttrib2(pos)) return getAttrib2();
- }
- /**
- * Check if token is part of an attribute selector of the form `[attr='value']`
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAttrib1(i) {
- var start = i,
- l;
- if (i++ >= tokensLength) return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkIdent(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkAttrselector(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkIdent(i) || checkString(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- return tokens[i].type === TokenType.RightSquareBracket ? i - start : 0;
- }
- /**
- * Get node with an attribute selector of the form `[attr='value']`
- * @returns {Array} `['attrib', ['ident', x], ['attrselector', y], [z]]`
- * where `x` is attribute's name, `y` is operator and `z` is attribute's
- * value
- */
- function getAttrib1() {
- var startPos = pos++;
- var content = []
- .concat(getSC())
- .concat([getIdent()])
- .concat(getSC())
- .concat([getAttrselector()])
- .concat(getSC())
- .concat([checkString(pos)? getString() : getIdent()])
- .concat(getSC());
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.AttribType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of an attribute selector of the form `[attr]`
- * Attribute can not be empty, e.g. `[]`.
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAttrib2(i) {
- var start = i,
- l;
- if (i++ >= tokensLength) return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkIdent(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- return tokens[i].type === TokenType.RightSquareBracket ? i - start : 0;
- }
- /**
- * Get node with an attribute selector of the form `[attr]`
- * @returns {Array} `['attrib', ['ident', x]]` where `x` is attribute's name
- */
- function getAttrib2() {
- var startPos = pos++;
- var content = []
- .concat(getSC())
- .concat([getIdent()])
- .concat(getSC());
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.AttribType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of an attribute selector operator (`=`, `~=`,
- * `^=`, `$=`, `*=` or `|=`)
- * @param {Number} i Token's index number
- * @returns {Number} Length of operator (`0` if token is not part of an
- * operator, `1` or `2` if it is).
- */
- function checkAttrselector(i) {
- if (i >= tokensLength) return 0;
- if (tokens[i].type === TokenType.EqualsSign) return 1;
- // TODO: Add example or remove
- if (tokens[i].type === TokenType.VerticalLine &&
- (!tokens[i + 1] || tokens[i + 1].type !== TokenType.EqualsSign))
- return 1;
- if (!tokens[i + 1] || tokens[i + 1].type !== TokenType.EqualsSign) return 0;
- switch(tokens[i].type) {
- case TokenType.Tilde:
- case TokenType.CircumflexAccent:
- case TokenType.DollarSign:
- case TokenType.Asterisk:
- case TokenType.VerticalLine:
- return 2;
- }
- return 0;
- }
- /**
- * Get node with an attribute selector operator (`=`, `~=`, `^=`, `$=`,
- * `*=` or `|=`)
- * @returns {Array} `['attrselector', x]` where `x` is an operator.
- */
- function getAttrselector() {
- var startPos = pos,
- content = tokens[pos++].value;
- if (tokens[pos] && tokens[pos].type === TokenType.EqualsSign)
- content += tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.AttrselectorType, content, token.ln, token.col);
- }
- /**
- * Check if token is a part of an @-rule
- * @param {Number} i Token's index number
- * @returns {Number} Length of @-rule
- */
- function checkAtrule(i) {
- var l;
- if (i >= tokensLength) return 0;
- // If token already has a record of being part of an @-rule,
- // return the @-rule's length:
- if (tokens[i].atrule_l !== undefined) return tokens[i].atrule_l;
- // If token is part of an @-rule, save the rule's type to token:
- if (l = checkAtruler(i)) tokens[i].atrule_type = 1; // @-rule with ruleset
- else if (l = checkAtruleb(i)) tokens[i].atrule_type = 2; // block @-rule
- else if (l = checkAtrules(i)) tokens[i].atrule_type = 3; // single-line @-rule
- else return 0;
- // If token is part of an @-rule, save the rule's length to token:
- tokens[i].atrule_l = l;
- return l;
- }
- /**
- * Get node with @-rule
- * @returns {Array}
- */
- function getAtrule() {
- switch (tokens[pos].atrule_type) {
- case 1: return getAtruler(); // @-rule with ruleset
- case 2: return getAtruleb(); // block @-rule
- case 3: return getAtrules(); // single-line @-rule
- }
- }
- /**
- * Check if token is part of a block @-rule
- * @param {Number} i Token's index number
- * @returns {Number} Length of the @-rule
- */
- function checkAtruleb(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkAtkeyword(i)) i += l;
- else return 0;
- if (l = checkTsets(i)) i += l;
- if (l = checkBlock(i)) i += l;
- else return 0;
- return i - start;
- }
- /**
- * Get node with a block @-rule
- * @returns {Array} `['atruleb', ['atkeyword', x], y, ['block', z]]`
- */
- function getAtruleb() {
- var startPos = pos;
- var content = [getAtkeyword()]
- .concat(getTsets())
- .concat([getBlock()]);
- var token = tokens[startPos];
- return new Node(NodeType.AtrulebType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of an @-rule with ruleset
- * @param {Number} i Token's index number
- * @returns {Number} Length of the @-rule
- */
- function checkAtruler(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkAtkeyword(i)) i += l;
- else return 0;
- if (l = checkAtrulerq(i)) i += l;
- if (i < tokensLength && tokens[i].type === TokenType.LeftCurlyBracket) i++;
- else return 0;
- if (l = checkAtrulers(i)) i += l;
- if (i < tokensLength && tokens[i].type === TokenType.RightCurlyBracket) i++;
- else return 0;
- return i - start;
- }
- /**
- * Get node with an @-rule with ruleset
- * @returns {Array} ['atruler', ['atkeyword', x], y, z]
- */
- function getAtruler() {
- var startPos = pos;
- var content = [getAtkeyword(), getAtrulerq()];
- pos++;
- content.push(getAtrulers());
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.AtrulerType, content, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAtrulerq(i) {
- return checkTsets(i);
- }
- /**
- * @returns {Array} `['atrulerq', x]`
- */
- function getAtrulerq() {
- var startPos = pos,
- content = getTsets();
- var token = tokens[startPos];
- return new Node(NodeType.AtrulerqType, content, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAtrulers(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkSC(i)) i += l;
- while (i < tokensLength) {
- if (l = checkSC(i)) tokens[i].atrulers_child = 1;
- else if (l = checkAtrule(i)) tokens[i].atrulers_child = 2;
- else if (l = checkRuleset(i)) tokens[i].atrulers_child = 3;
- else break;
- i += l;
- }
- tokens[i].atrulers_end = 1;
- if (l = checkSC(i)) i += l;
- return i - start;
- }
- /**
- * @returns {Array} `['atrulers', x]`
- */
- function getAtrulers() {
- var startPos = pos,
- content = getSC();
- while (!tokens[pos].atrulers_end) {
- var childType = tokens[pos].atrulers_child;
- if (childType === 1) content = content.concat(getSC());
- else if (childType === 2) content.push(getAtrule());
- else if (childType === 3) content.push(getRuleset());
- }
- content = content.concat(getSC());
- var token = tokens[startPos];
- return new Node(NodeType.AtrulersType, content, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkAtrules(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkAtkeyword(i)) i += l;
- else return 0;
- if (l = checkTsets(i)) i += l;
- return i - start;
- }
- /**
- * @returns {Array} `['atrules', ['atkeyword', x], y]`
- */
- function getAtrules() {
- var startPos = pos,
- content = [getAtkeyword()].concat(getTsets());
- var token = tokens[startPos];
- return new Node(NodeType.AtrulesType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of a block (e.g. `{...}`).
- * @param {Number} i Token's index number
- * @returns {Number} Length of the block
- */
- function checkBlock(i) {
- return i < tokensLength && tokens[i].type === TokenType.LeftCurlyBracket ?
- tokens[i].right - i + 1 : 0;
- }
- /**
- * Get node with a block
- * @returns {Array} `['block', x]`
- */
- function getBlock() {
- var startPos = pos,
- end = tokens[pos++].right,
- content = [];
- while (pos < end) {
- if (checkBlockdecl(pos)) content = content.concat(getBlockdecl());
- else throwError(pos);
- }
- pos = end + 1;
- var token = tokens[startPos];
- return new Node(NodeType.BlockType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of a declaration (property-value pair)
- * @param {Number} i Token's index number
- * @returns {Number} Length of the declaration
- */
- function checkBlockdecl(i) {
- var l;
- if (i >= tokensLength) return 0;
- if (l = checkBlockdecl1(i)) tokens[i].bd_type = 1;
- else if (l = checkBlockdecl2(i)) tokens[i].bd_type = 2;
- else if (l = checkBlockdecl3(i)) tokens[i].bd_type = 3;
- else if (l = checkBlockdecl4(i)) tokens[i].bd_type = 4;
- else return 0;
- return l;
- }
- /**
- * @returns {Array}
- */
- function getBlockdecl() {
- switch (tokens[pos].bd_type) {
- case 1: return getBlockdecl1();
- case 2: return getBlockdecl2();
- case 3: return getBlockdecl3();
- case 4: return getBlockdecl4();
- }
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkBlockdecl1(i) {
- var start = i,
- l;
- if (l = checkSC(i)) i += l;
- if (l = checkCondition(i)) tokens[i].bd_kind = 1;
- else if (l = checkFilter(i)) tokens[i].bd_kind = 3;
- else if (l = checkDeclaration(i)) tokens[i].bd_kind = 4;
- else if (l = checkAtrule(i)) tokens[i].bd_kind = 5;
- else if (l = checkRuleset(i)) tokens[i].bd_kind = 6;
- else if (l = checkInclude(i)) tokens[i].bd_kind = 2;
- else return 0;
- i += l;
- if (i < tokensLength && (l = checkDeclDelim(i))) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- else return 0;
- return i - start;
- }
- /**
- * sc*:s0 (atrule | ruleset | filter | declaration):x declDelim:y sc*:s1 -> concat(s0, [x], [y], s1)
- * @returns {Array}
- */
- function getBlockdecl1() {
- var sc = getSC(),
- x;
- switch (tokens[pos].bd_kind) {
- case 1:
- x = getCondition();
- break;
- case 2:
- x = getInclude();
- break;
- case 3:
- x = getFilter();
- break;
- case 4:
- x = getDeclaration();
- break;
- case 5:
- x = getAtrule();
- break;
- case 6:
- x = getRuleset();
- break;
- }
- return sc
- .concat([x])
- .concat([getDeclDelim()])
- .concat(getSC());
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkBlockdecl2(i) {
- var start = i,
- l;
- if (l = checkSC(i)) i += l;
- if (l = checkCondition(i)) tokens[i].bd_kind = 1;
- else if (l = checkFilter(i)) tokens[i].bd_kind = 3;
- else if (l = checkDeclaration(i)) tokens[i].bd_kind = 4;
- else if (l = checkAtrule(i)) tokens[i].bd_kind = 5;
- else if (l = checkRuleset(i)) tokens[i].bd_kind = 6;
- else if (l = checkInclude(i)) tokens[i].bd_kind = 2;
- else return 0;
- i += l;
- if (l = checkSC(i)) i += l;
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getBlockdecl2() {
- var sc = getSC(),
- x;
- switch (tokens[pos].bd_kind) {
- case 1:
- x = getCondition();
- break;
- case 2:
- x = getInclude();
- break;
- case 3:
- x = getFilter();
- break;
- case 4:
- x = getDeclaration();
- break;
- case 5:
- x = getAtrule();
- break;
- case 6:
- x = getRuleset();
- break;
- }
- return sc
- .concat([x])
- .concat(getSC());
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkBlockdecl3(i) {
- var start = i,
- l;
- if (l = checkSC(i)) i += l;
- if (l = checkDeclDelim(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- return i - start;
- }
- /**
- * @returns {Array} `[s0, ['declDelim'], s1]` where `s0` and `s1` are
- * are optional whitespaces.
- */
- function getBlockdecl3() {
- return getSC()
- .concat([getDeclDelim()])
- .concat(getSC());
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkBlockdecl4(i) {
- return checkSC(i);
- }
- /**
- * @returns {Array}
- */
- function getBlockdecl4() {
- return getSC();
- }
- /**
- * Check if token is part of text inside parentheses or square brackets
- * (e.g. `(1)`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkBraces(i) {
- if (i >= tokensLength ||
- (tokens[i].type !== TokenType.LeftParenthesis &&
- tokens[i].type !== TokenType.LeftSquareBracket)) return 0;
- return tokens[i].right - i + 1;
- }
- /**
- * Get node with text inside parentheses or square brackets (e.g. `(1)`)
- * @returns {Array} `['braces', l, r, x*]` where `l` is a left bracket
- * (e.g. `'('`), `r` is a right bracket (e.g. `')'`) and `x` is
- * parsed text inside those brackets (if there is any)
- * (e.g. `['number', '1']`)
- */
- function getBraces() {
- var startPos = pos,
- left = pos,
- right = tokens[pos++].right;
- var content = [tokens[left].value, tokens[right].value]
- .concat(getTsets());
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.BracesType, content, token.ln, token.col);
- }
- /**
- * Check if token is part of a class selector (e.g. `.abc`)
- * @param {Number} i Token's index number
- * @returns {Number} Length of the class selector
- */
- function checkClass(i) {
- var l;
- if (i >= tokensLength) return 0;
- if (tokens[i].class_l) return tokens[i].class_l;
- if (tokens[i++].type === TokenType.FullStop) {
- if (l = checkInterpolatedVariable(i)) tokens[i].class_child = 1;
- else if (l = checkIdent(i)) tokens[i].class_child = 2;
- else return 0;
- tokens[i].class_l = l + 1;
- return l + 1;
- }
- return 0;
- }
- /**
- * Get node with a class selector
- * @returns {Array} `['class', ['ident', x]]` where x is a class's
- * identifier (without `.`, e.g. `abc`).
- */
- function getClass() {
- var startPos = pos++;
- var content = [];
- var childType = tokens[pos].class_child;
- if (childType === 1) content.push(getInterpolatedVariable());
- else content.push(getIdent());
- var token = tokens[startPos];
- return new Node(NodeType.ClassType, content, token.ln, token.col);
- }
- /**
- * Check if token is a combinator (`+`, `>` or `~`)
- * @param {Number} i Token's index number
- * @returns {Number} Length of the combinator
- */
- function checkCombinator(i) {
- if (i >= tokensLength) return 0;
- switch (tokens[i].type) {
- case TokenType.PlusSign:
- case TokenType.GreaterThanSign:
- case TokenType.Tilde:
- return 1;
- }
- return 0;
- }
- /**
- * Get node with a combinator (`+`, `>` or `~`)
- * @returns {Array} `['combinator', x]` where `x` is a combinator
- * converted to string.
- */
- function getCombinator() {
- var startPos = pos,
- content = tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.CombinatorType, content, token.ln, token.col);
- }
- /**
- * Check if token is a multiline comment.
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is a multiline comment, otherwise `0`
- */
- function checkCommentML(i) {
- return i < tokensLength && tokens[i].type === TokenType.CommentML ? 1 : 0;
- }
- /**
- * Get node with a multiline comment
- * @returns {Array} `['commentML', x]` where `x`
- * is the comment's text (without `/*` and `* /`).
- */
- function getCommentML() {
- var startPos = pos,
- s = tokens[pos].value.substring(2),
- l = s.length;
- if (s.charAt(l - 2) === '*' && s.charAt(l - 1) === '/')
- s = s.substring(0, l - 2);
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.CommentMLType, s, token.ln, token.col);
- }
- /**
- * Check if token is part of a single-line comment.
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is a single-line comment, otherwise `0`
- */
- function checkCommentSL(i) {
- return i < tokensLength && tokens[i].type === TokenType.CommentSL ? 1 : 0;
- }
- /**
- * Get node with a single-line comment.
- * @returns {Array}
- */
- function getCommentSL() {
- var startPos = pos,
- x = tokens[pos++].value.substring(2);
- var token = tokens[startPos];
- return new Node(NodeType.CommentSLType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a condition.
- * @param {Number} i Token's index number
- * @return {Number} Length of the condition
- */
- function checkCondition(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if ((l = checkIdent(i)) && tokens[i].value === 'when') i += l;
- else return 0;
- while (i < tokensLength) {
- if (l = checkBlock(i)) {
- tokens[i].condition_child = 0;
- break;
- } else if (l = checkFunction(i)) tokens[i].condition_child = 1;
- else if (l = checkBraces(i)) tokens[i].condition_child = 2;
- else if (l = checkVariable(i)) tokens[i].condition_child = 3;
- else if (l = checkIdent(i)) tokens[i].condition_child = 4;
- else if (l = checkNumber(i)) tokens[i].condition_child = 5;
- else if (l = checkDelim(i)) tokens[i].condition_child = 6;
- else if (l = checkOperator(i)) tokens[i].condition_child = 7;
- else if (l = checkCombinator(i)) tokens[i].condition_child = 8;
- else if (l = checkSC(i)) tokens[i].condition_child = 9;
- else if (l = checkString(i)) tokens[i].condition_child = 10;
- else return 0;
- i += l;
- }
- return i - start;
- }
- /**
- * Get node with a condition.
- * @returns {Array} `['condition', x]`
- */
- function getCondition() {
- var startPos = pos,
- x = [];
- x.push(getIdent());
- while (pos < tokensLength) {
- var childType = tokens[pos].condition_child;
- if (childType === 0) break;
- else if (childType === 1) x.push(getFunction());
- else if (childType === 2) x.push(getBraces());
- else if (childType === 3) x.push(getVariable());
- else if (childType === 4) x.push(getIdent());
- else if (childType === 5) x.push(getNumber());
- else if (childType === 6) x.push(getDelim());
- else if (childType === 7) x.push(getOperator());
- else if (childType === 8) x.push(getCombinator());
- else if (childType === 9) x = x.concat(getSC());
- else if (childType === 10) x.push(getString());
- }
- var token = tokens[startPos];
- return new Node(NodeType.ConditionType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a declaration (property-value pair)
- * @param {Number} i Token's index number
- * @returns {Number} Length of the declaration
- */
- function checkDeclaration(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkProperty(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkPropertyDelim(i)) i++;
- else return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkValue(i)) i += l;
- else return 0;
- return i - start;
- }
- /**
- * Get node with a declaration
- * @returns {Array} `['declaration', ['property', x], ['propertyDelim'],
- * ['value', y]]`
- */
- function getDeclaration() {
- var startPos = pos;
- var x = [getProperty()]
- .concat(getSC())
- .concat([getPropertyDelim()])
- .concat(getSC())
- .concat([getValue()]);
- var token = tokens[startPos];
- return new Node(NodeType.DeclarationType, x, token.ln, token.col);
- }
- /**
- * Check if token is a semicolon
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is a semicolon, otherwise `0`
- */
- function checkDeclDelim(i) {
- return i < tokensLength && tokens[i].type === TokenType.Semicolon ? 1 : 0;
- }
- /**
- * Get node with a semicolon
- * @returns {Array} `['declDelim']`
- */
- function getDeclDelim() {
- var startPos = pos++;
- var token = tokens[startPos];
- return new Node(NodeType.DeclDelimType, ';', token.ln, token.col);
- }
- function checkDeepSelector(i) {
- if (tokens[i + 2] &&
- tokens[i].value + tokens[i + 1].value + tokens[i + 2].value === '/deep/') {
- return 3;
- }
- }
- function getDeepSelector() {
- var _pos = pos++;
- var ident = getIdent();
- ident.content = '/deep/';
- ident.start.column -= 1;
- pos = _pos + 3;
- return ident;
- }
- /**
- * Check if token is a comma
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is a comma, otherwise `0`
- */
- function checkDelim(i) {
- return i < tokensLength && tokens[i].type === TokenType.Comma ? 1 : 0;
- }
- /**
- * Get node with a comma
- * @returns {Array} `['delim']`
- */
- function getDelim() {
- var startPos = pos++;
- var token = tokens[startPos];
- return new Node(NodeType.DelimType, ',', token.ln, token.col);
- }
- /**
- * Check if token is part of a number with dimension unit (e.g. `10px`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkDimension(i) {
- var ln = checkNumber(i),
- li;
- if (i >= tokensLength ||
- !ln ||
- i + ln >= tokensLength) return 0;
- return (li = checkNmName2(i + ln)) ? ln + li : 0;
- }
- /**
- * Get node of a number with dimension unit
- * @returns {Array} `['dimension', ['number', x], ['ident', y]]` where
- * `x` is a number converted to string (e.g. `'10'`) and `y` is
- * a dimension unit (e.g. `'px'`).
- */
- function getDimension() {
- var startPos = pos,
- x = [getNumber()],
- token = tokens[pos];
- ident = new Node(NodeType.IdentType, getNmName2(), token.ln, token.col);
- x.push(ident);
- token = tokens[startPos];
- return new Node(NodeType.DimensionType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of an escaped string (e.g. `~"ms:something"`).
- * @param {Number} i Token's index number
- * @returns {Numer} Length of the string (including `~` and quotes)
- */
- function checkEscapedString(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (tokens[i].type === TokenType.Tilde && (l = checkString(i + 1)))
- return i + l - start;
- else return 0;
- }
- /**
- * Get node with an escaped string
- * @returns {Array} `['escapedString', ['string', x]]` where `x` is a string
- * without `~` but with quotes
- */
- function getEscapedString() {
- var startPos = pos++;
- var x = tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.EscapedStringType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkFilter(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkFilterp(i)) i += l;
- else return 0;
- if (tokens[i].type === TokenType.Colon) i++;
- else return 0;
- if (l = checkFilterv(i)) i += l;
- else return 0;
- return i - start;
- }
- /**
- * @returns {Array} `['filter', x, y]`
- */
- function getFilter() {
- var startPos = pos,
- x = [getFilterp()];
- pos++;
- x.push(getFilterv());
- var token = tokens[startPos];
- return new Node(NodeType.FilterType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkFilterp(i) {
- var start = i,
- l,
- x;
- if (i >= tokensLength) return 0;
- if (tokens[i].value === 'filter') l = 1;
- else {
- x = joinValues2(i, 2);
- if (x === '-filter' || x === '_filter' || x === '*filter') l = 2;
- else {
- x = joinValues2(i, 4);
- if (x === '-ms-filter') l = 4;
- else return 0;
- }
- }
- tokens[start].filterp_l = l;
- i += l;
- if (checkSC(i)) i += l;
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getFilterp() {
- var startPos = pos,
- token = tokens[startPos],
- x;
- var identValue = joinValues2(pos, token.filterp_l);
- ident = new Node(NodeType.IdentType, identValue, token.ln, token.col);
- pos += tokens[pos].filterp_l;
- x = [ident].concat(getSC());
- return new Node(NodeType.PropertyType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkFilterv(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkProgid(i) || checkEscapedString(i)) i += l;
- else return 0;
- while (l = checkProgid(i) || checkEscapedString(i)) {
- i += l;
- }
- tokens[start].last_progid = i;
- if (i < tokensLength && (l = checkSC(i))) i += l;
- if (i < tokensLength && (l = checkImportant(i))) i += l;
- return i - start;
- }
- /**
- * progid+:x -> [#filterv].concat(x)
- * @returns {Array}
- */
- function getFilterv() {
- var startPos = pos,
- last_progid = tokens[pos].last_progid,
- x = getSC();
- while (pos < last_progid) {
- x.push(checkProgid(pos) ? getProgid() : getEscapedString());
- }
- if (checkSC(pos)) x = x.concat(getSC());
- if (pos < tokensLength && checkImportant(pos)) x.push(getImportant());
- var token = tokens[startPos];
- return new Node(NodeType.FiltervType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkFunctionExpression(i) {
- var start = i;
- if (i >= tokensLength || tokens[i++].value !== 'expression' ||
- i >= tokensLength || tokens[i].type !== TokenType.LeftParenthesis) return 0;
- return tokens[i].right - start + 1;
- }
- /**
- * @returns {Array}
- */
- function getFunctionExpression() {
- var startPos = pos++,
- x;
- x = joinValues(pos + 1, tokens[pos].right - 1);
- pos = tokens[pos].right + 1;
- var token = tokens[startPos];
- return new Node(NodeType.FunctionExpressionType, [x], token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkFunction(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkIdent(i)) i +=l;
- else return 0;
- return i < tokensLength && tokens[i].type === TokenType.LeftParenthesis ?
- tokens[i].right - start + 1 : 0;
- }
- /**
- * @returns {Array}
- */
- function getFunction() {
- var startPos = pos,
- token = tokens[pos],
- ident = getIdent(),
- x = [ident],
- body;
- body = ident.content === 'not' ? getNotArguments() : getArguments();
- x.push(body);
- return new Node(NodeType.FunctionType, x, token.ln, token.col);
- }
- /**
- * @returns {Array}
- */
- function getArguments() {
- var startPos = pos,
- x = [],
- body;
- pos++;
- while (pos < tokensLength && tokens[pos].type !== TokenType.RightParenthesis) {
- if (checkDeclaration(pos)) x.push(getDeclaration());
- else if (checkArgument(pos)) {
- body = getArgument();
- if (typeof body.content === 'string') x.push(body);
- else x = x.concat(body);
- } else if (checkClass(pos)) x.push(getClass());
- else throwError(pos);
- }
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.ArgumentsType, x, token.ln, token.col);
- }
- /**
- * @returns {Array}
- */
- function getNotArguments() {
- var startPos = pos++,
- x = [];
- while (pos < tokensLength && tokens[pos].type !== TokenType.RightParenthesis) {
- if (checkSimpleSelector(pos)) x.push(getSimpleSelector());
- else throwError(pos);
- }
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.ArgumentsType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of an identifier
- * @param {Number} i Token's index number
- * @returns {Number} Length of the identifier
- */
- function checkIdent(i) {
- var start = i,
- wasIdent,
- l;
- if (i >= tokensLength) return 0;
- // Check if token is part of an identifier starting with `_`:
- if (tokens[i].type === TokenType.LowLine) return checkIdentLowLine(i);
- // If token is a character, `-`, `$` or `*`, skip it & continue:
- if (tokens[i].type === TokenType.HyphenMinus ||
- tokens[i].type === TokenType.Identifier ||
- tokens[i].type === TokenType.DollarSign ||
- tokens[i].type === TokenType.Asterisk) i++;
- else return 0;
- // Remember if previous token's type was identifier:
- wasIdent = tokens[i - 1].type === TokenType.Identifier;
- for (; i < tokensLength; i++) {
- if (l = checkInterpolatedVariable(i)) i += l;
- if (i >= tokensLength) break;
- if (tokens[i].type !== TokenType.HyphenMinus &&
- tokens[i].type !== TokenType.LowLine) {
- if (tokens[i].type !== TokenType.Identifier &&
- (tokens[i].type !== TokenType.DecimalNumber || !wasIdent)) break;
- else wasIdent = true;
- }
- }
- if (!wasIdent && tokens[start].type !== TokenType.Asterisk) return 0;
- tokens[start].ident_last = i - 1;
- return i - start;
- }
- /**
- * Check if token is part of an identifier starting with `_`
- * @param {Number} i Token's index number
- * @returns {Number} Length of the identifier
- */
- function checkIdentLowLine(i) {
- var start = i;
- if (i++ >= tokensLength) return 0;
- for (; i < tokensLength; i++) {
- if (tokens[i].type !== TokenType.HyphenMinus &&
- tokens[i].type !== TokenType.DecimalNumber &&
- tokens[i].type !== TokenType.LowLine &&
- tokens[i].type !== TokenType.Identifier) break;
- }
- // Save index number of the last token of the identifier:
- tokens[start].ident_last = i - 1;
- return i - start;
- }
- /**
- * Get node with an identifier
- * @returns {Array} `['ident', x]` where `x` is identifier's name
- */
- function getIdent() {
- var startPos = pos,
- x = joinValues(pos, tokens[pos].ident_last);
- pos = tokens[pos].ident_last + 1;
- var token = tokens[startPos];
- return new Node(NodeType.IdentType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of `!important` word
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkImportant(i) {
- var start = i,
- l;
- if (i >= tokensLength ||
- tokens[i++].type !== TokenType.ExclamationMark) return 0;
- if (l = checkSC(i)) i += l;
- return tokens[i].value === 'important' ? i - start + 1 : 0;
- }
- /**
- * Get node with `!important` word
- * @returns {Array} `['important', sc]` where `sc` is optional whitespace
- */
- function getImportant() {
- var startPos = pos++,
- x = getSC();
- if (!x || !x.length) x = '';
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.ImportantType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of an include (`@include` or `@extend` directive).
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkInclude(i) {
- var l;
- if (i >= tokensLength) return 0;
- if (l = checkInclude1(i)) tokens[i].include_type = 1;
- else if (l = checkInclude2(i)) tokens[i].include_type = 2;
- return l;
- }
- /**
- * Get node with included mixin
- * @returns {Array} `['include', x]`
- */
- function getInclude() {
- switch (tokens[pos].include_type) {
- case 1: return getInclude1();
- case 2: return getInclude2();
- }
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkInclude1(i) {
- var start = i,
- l;
- if (l = checkClass(i) || checkShash(i)) i += l;
- else return 0;
- while (i < tokensLength) {
- if (l = checkClass(i) || checkShash(i) || checkSC(i)) i += l;
- else if (tokens[i].type == TokenType.GreaterThanSign) i++;
- else break;
- }
- if (l = checkArguments(i)) i += l;
- else return 0;
- if (i < tokensLength && (l = checkSC(i))) i += l;
- if (i < tokensLength && (l = checkImportant(i))) i += l;
- return i - start;
- }
- /**
- * @returns {Array} `['include', x]`
- */
- function getInclude1() {
- var startPos = pos,
- x = [];
- x.push(checkClass(pos) ? getClass() : getShash());
- while (pos < tokensLength) {
- if (checkClass(pos)) x.push(getClass());
- else if (checkShash(pos)) x.push(getShash());
- else if (checkSC(pos)) x = x.concat(getSC());
- else if (checkOperator(pos)) x.push(getOperator());
- else break;
- }
- x.push(getArguments());
- x = x.concat(getSC());
- if (checkImportant(pos)) x.push(getImportant());
- var token = tokens[startPos];
- return new Node(NodeType.IncludeType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkInclude2(i) {
- var start = i,
- l;
- if (l = checkClass(i) || checkShash(i)) i += l;
- else return 0;
- while (i < tokensLength) {
- if (l = checkClass(i) || checkShash(i) || checkSC(i)) i += l;
- else if (tokens[i].type == TokenType.GreaterThanSign) i++;
- else break;
- }
- return i - start;
- }
- /**
- * @returns {Array} `['include', x]`
- */
- function getInclude2() {
- var startPos = pos,
- x = [];
- x.push(checkClass(pos) ? getClass() : getShash());
- while (pos < tokensLength) {
- if (checkClass(pos)) x.push(getClass());
- else if (checkShash(pos)) x.push(getShash());
- else if (checkSC(pos)) x = x.concat(getSC());
- else if (checkOperator(pos)) x.push(getOperator());
- else break;
- }
- var token = tokens[startPos];
- return new Node(NodeType.IncludeType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkIncludeSelector(i) {
- var start = i,
- l;
- while (i < tokensLength) {
- if (l = checkSimpleSelector2(i)) i += l;
- else break;
- }
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getIncludeSelector() {
- var startPos = pos,
- x = [],
- t;
- while (pos < tokensLength && checkSimpleSelector2(pos)) {
- t = getSimpleSelector2();
- if (t.content === 'string') x.push(t);
- else x = x.concat(t);
- }
- var token = tokens[startPos];
- return new Node(NodeType.SimpleselectorType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of LESS interpolated variable
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkInterpolatedVariable(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (tokens[i].type !== TokenType.CommercialAt ||
- !tokens[i + 1] || tokens[i + 1].type !== TokenType.LeftCurlyBracket) return 0;
- i += 2;
- if (l = checkIdent(i)) i += l;
- else return 0;
- return tokens[i].type === TokenType.RightCurlyBracket ? i - start + 1 : 0;
- }
- /**
- * Get node with LESS interpolated variable
- * @returns {Array} `['interpolatedVariable', x]`
- */
- function getInterpolatedVariable() {
- var startPos = pos,
- x = [];
- // Skip `@{`:
- pos += 2;
- x.push(getIdent());
- // Skip `}`:
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.InterpolatedVariableType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a LESS mixin
- * @param {Number} i Token's index number
- * @returns {Number} Length of the mixin
- */
- function checkMixin(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkClass(i) || checkShash(i)) i +=l;
- else return 0;
- if (l = checkSC(i)) i += l;
- if (l = checkArguments(i)) i += l;
- if (l = checkSC(i)) i += l;
- if (l = checkBlock(i)) i += l;
- else return 0;
- return i - start;
- }
- /**
- * Get node with a mixin
- * @returns {Array} `['mixin', x]`
- */
- function getMixin() {
- var startPos = pos,
- x = [];
- x.push(checkClass(pos) ? getClass() : getShash());
- x = x.concat(getSC());
- if (checkArguments(pos)) x.push(getArguments());
- x = x.concat(getSC());
- if (checkBlock(pos)) x.push(getBlock());
- var token = tokens[startPos];
- return new Node(NodeType.MixinType, x, token.ln, token.col);
- }
- /**
- * Check if token is a namespace sign (`|`)
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is `|`, `0` if not
- */
- function checkNamespace(i) {
- return i < tokensLength && tokens[i].type === TokenType.VerticalLine ? 1 : 0;
- }
- /**
- * Get node with a namespace sign
- * @returns {Array} `['namespace']`
- */
- function getNamespace() {
- var startPos = pos++;
- var token = tokens[startPos];
- return new Node(NodeType.NamespaceType, '|', token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNmName(i) {
- var start = i;
- if (i >= tokensLength) return 0;
- // start char / word
- if (tokens[i].type === TokenType.HyphenMinus ||
- tokens[i].type === TokenType.LowLine ||
- tokens[i].type === TokenType.Identifier ||
- tokens[i].type === TokenType.DecimalNumber) i++;
- else return 0;
- for (; i < tokensLength; i++) {
- if (tokens[i].type !== TokenType.HyphenMinus &&
- tokens[i].type !== TokenType.LowLine &&
- tokens[i].type !== TokenType.Identifier &&
- tokens[i].type !== TokenType.DecimalNumber) break;
- }
- tokens[start].nm_name_last = i - 1;
- return i - start;
- }
- /**
- * @returns {String}
- */
- function getNmName() {
- var s = joinValues(pos, tokens[pos].nm_name_last);
- pos = tokens[pos].nm_name_last + 1;
- return s;
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNmName2(i) {
- if (tokens[i].type === TokenType.Identifier) return 1;
- else if (tokens[i].type !== TokenType.DecimalNumber) return 0;
- i++;
- return i < tokensLength && tokens[i].type === TokenType.Identifier ? 2 : 1;
- }
- /**
- * @returns {String}
- */
- function getNmName2() {
- var s = tokens[pos].value;
- if (tokens[pos++].type === TokenType.DecimalNumber &&
- pos < tokensLength &&
- tokens[pos].type === TokenType.Identifier) s += tokens[pos++].value;
- return s;
- }
- /**
- * Check if token is part of an nth-selector's identifier (e.g. `2n+1`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNth(i) {
- if (i >= tokensLength) return 0;
- return checkNth1(i) || checkNth2(i);
- }
- /**
- * Check if token is part of an nth-selector's identifier in the form of
- * sequence of decimals and n-s (e.g. `3`, `n`, `2n+1`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNth1(i) {
- var start = i;
- for (; i < tokensLength; i++) {
- if (tokens[i].type !== TokenType.DecimalNumber &&
- tokens[i].value !== 'n') break;
- }
- if (i !== start) tokens[start].nth_last = i - 1;
- return i - start;
- }
- /**
- * Get node for nth-selector's identifier (e.g. `2n+1`)
- * @returns {Array} `['nth', x]` where `x` is identifier's text
- */
- function getNth() {
- var startPos = pos,
- x;
- if (tokens[pos].nth_last) {
- x = joinValues(pos, tokens[pos].nth_last);
- pos = tokens[pos].nth_last + 1;
- } else {
- x = tokens[pos++].value;
- }
- var token = tokens[startPos];
- return new Node(NodeType.NthType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of `even` or `odd` nth-selector's identifier
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNth2(i) {
- return tokens[i].value === 'even' || tokens[i].value === 'odd' ? 1 : 0;
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNthf(i) {
- var start = i,
- l = 0;
- if (tokens[i++].type !== TokenType.Colon) return 0;
- // There was `:`:
- l++;
- if (tokens[i++].value !== 'nth' || tokens[i++].value !== '-') return 0;
- // There was either `nth-` or `last-`:
- l += 2;
- if ('child' === tokens[i].value) {
- l += 1;
- } else if ('last-child' === tokens[i].value +
- tokens[i + 1].value +
- tokens[i + 2].value) {
- l += 3;
- } else if ('of-type' === tokens[i].value +
- tokens[i + 1].value +
- tokens[i + 2].value) {
- l += 3;
- } else if ('last-of-type' === tokens[i].value +
- tokens[i + 1].value +
- tokens[i + 2].value +
- tokens[i + 3].value +
- tokens[i + 4].value) {
- l += 5;
- } else return 0;
- tokens[start + 1].nthf_last = start + l - 1;
- return l;
- }
- /**
- * @returns {String}
- */
- function getNthf() {
- pos++;
- var s = joinValues(pos, tokens[pos].nthf_last);
- pos = tokens[pos].nthf_last + 1;
- return s;
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkNthselector(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkNthf(i)) i += l;
- else return 0;
- if (tokens[i].type !== TokenType.LeftParenthesis || !tokens[i].right) return 0;
- l++;
- var rp = tokens[i++].right;
- while (i < rp) {
- if (l = checkSC(i) ||
- checkUnary(i) ||
- checkNth(i)) i += l;
- else return 0;
- }
- return rp - start + 1;
- }
- /**
- * @returns {Array}
- */
- function getNthselector() {
- var startPos = pos,
- token = tokens[pos],
- nthf = new Node(NodeType.IdentType, getNthf(), token.ln, token.col),
- x = [];
- x.push(nthf);
- pos++;
- while (tokens[pos].type !== TokenType.RightParenthesis) {
- if (checkSC(pos)) x = x.concat(getSC());
- else if (checkUnary(pos)) x.push(getUnary());
- else if (checkNth(pos)) x.push(getNth());
- }
- pos++;
- return new Node(NodeType.NthselectorType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a number
- * @param {Number} i Token's index number
- * @returns {Number} Length of number
- */
- function checkNumber(i) {
- if (i >= tokensLength) return 0;
- if (tokens[i].number_l) return tokens[i].number_l;
- // `10`:
- if (i < tokensLength && tokens[i].type === TokenType.DecimalNumber &&
- (!tokens[i + 1] ||
- (tokens[i + 1] && tokens[i + 1].type !== TokenType.FullStop)))
- return (tokens[i].number_l = 1, tokens[i].number_l);
- // `10.`:
- if (i < tokensLength &&
- tokens[i].type === TokenType.DecimalNumber &&
- tokens[i + 1] && tokens[i + 1].type === TokenType.FullStop &&
- (!tokens[i + 2] || (tokens[i + 2].type !== TokenType.DecimalNumber)))
- return (tokens[i].number_l = 2, tokens[i].number_l);
- // `.10`:
- if (i < tokensLength &&
- tokens[i].type === TokenType.FullStop &&
- tokens[i + 1].type === TokenType.DecimalNumber)
- return (tokens[i].number_l = 2, tokens[i].number_l);
- // `10.10`:
- if (i < tokensLength &&
- tokens[i].type === TokenType.DecimalNumber &&
- tokens[i + 1] && tokens[i + 1].type === TokenType.FullStop &&
- tokens[i + 2] && tokens[i + 2].type === TokenType.DecimalNumber)
- return (tokens[i].number_l = 3, tokens[i].number_l);
- return 0;
- }
- /**
- * Get node with number
- * @returns {Array} `['number', x]` where `x` is a number converted
- * to string.
- */
- function getNumber() {
- var x = '',
- startPos = pos,
- l = tokens[pos].number_l;
- for (var j = 0; j < l; j++) {
- x += tokens[pos + j].value;
- }
- pos += l;
- var token = tokens[startPos];
- return new Node(NodeType.NumberType, x, token.ln, token.col);
- }
- /**
- * Check if token is an operator (`/`, `,`, `:`, `=`, `>`, `<` or `*`)
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is an operator, otherwise `0`
- */
- function checkOperator(i) {
- if (i >= tokensLength) return 0;
- switch(tokens[i].type) {
- case TokenType.Solidus:
- case TokenType.Comma:
- case TokenType.Colon:
- case TokenType.EqualsSign:
- case TokenType.LessThanSign:
- case TokenType.GreaterThanSign:
- case TokenType.Asterisk:
- return 1;
- }
- return 0;
- }
- /**
- * Get node with an operator
- * @returns {Array} `['operator', x]` where `x` is an operator converted
- * to string.
- */
- function getOperator() {
- var startPos = pos,
- x = tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.OperatorType, x, token.ln, token.col);
- }
- /**
- * Check if token is a parent selector (`&`).
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkParentSelector(i) {
- return i < tokensLength && tokens[i].type === TokenType.Ampersand ? 1 : 0;
- }
- /**
- * Get node with a parent selector
- * @returns {Array} `['parentSelector']`
- */
- function getParentSelector() {
- var startPos = pos++;
- var token = tokens[startPos];
- return new Node(NodeType.ParentSelectorType, '&', token.ln, token.col);
- }
- /**
- * Check if token is part of a number with percent sign (e.g. `10%`)
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkPercentage(i) {
- var x;
- if (i >= tokensLength) return 0;
- x = checkNumber(i);
- if (!x || i + x >= tokensLength) return 0;
- return tokens[i + x].type === TokenType.PercentSign ? x + 1 : 0;
- }
- /**
- * Get node of number with percent sign
- * @returns {Array} `['percentage', ['number', x]]` where `x` is a number
- * (without percent sign) converted to string.
- */
- function getPercentage() {
- var startPos = pos,
- x = getNumber();
- pos++;
- var token = tokens[startPos];
- return new Node(NodeType.PercentageType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkProgid(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkSC(i)) i += l;
- if (joinValues2(i, 6) === 'progid:DXImageTransform.Microsoft.') i += 6;
- else return 0;
- if (l = checkIdent(i)) i += l;
- else return 0;
- if (l = checkSC(i)) i += l;
- if (tokens[i].type === TokenType.LeftParenthesis) {
- tokens[start].progid_end = tokens[i].right;
- i = tokens[i].right + 1;
- } else return 0;
- if (l = checkSC(i)) i += l;
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getProgid() {
- var startPos = pos,
- progid_end = tokens[pos].progid_end,
- x;
- x = []
- .concat(getSC())
- .concat([_getProgid(progid_end)])
- .concat(getSC());
- var token = tokens[startPos];
- return new Node(NodeType.ProgidType, x, token.ln, token.col);
- }
- /**
- * @param {Number} progid_end
- * @returns {Array}
- */
- function _getProgid(progid_end) {
- var startPos = pos,
- x = joinValues(pos, progid_end);
- pos = progid_end + 1;
- var token = tokens[startPos];
- return new Node(NodeType.RawType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a property
- * @param {Number} i Token's index number
- * @returns {Number} Length of the property
- */
- function checkProperty(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkVariable(i) || checkIdent(i)) i += l;
- else return 0;
- return i - start;
- }
- /**
- * Get node with a property
- * @returns {Array} `['property', x]`
- */
- function getProperty() {
- var startPos = pos,
- x = [];
- if (checkVariable(pos)) x.push(getVariable());
- else x.push(getIdent());
- var token = tokens[startPos];
- return new Node(NodeType.PropertyType, x, token.ln, token.col);
- }
- /**
- * Check if token is a colon
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is a colon, otherwise `0`
- */
- function checkPropertyDelim(i) {
- return i < tokensLength && tokens[i].type === TokenType.Colon ? 1 : 0;
- }
- /**
- * Get node with a colon
- * @returns {Array} `['propertyDelim']`
- */
- function getPropertyDelim() {
- var startPos = pos++;
- var token = tokens[startPos];
- return new Node(NodeType.PropertyDelimType, ':', token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkPseudo(i) {
- return checkPseudoe(i) ||
- checkPseudoc(i);
- }
- /**
- * @returns {Array}
- */
- function getPseudo() {
- if (checkPseudoe(pos)) return getPseudoe();
- if (checkPseudoc(pos)) return getPseudoc();
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkPseudoe(i) {
- var l;
- if (i >= tokensLength || tokens[i++].type !== TokenType.Colon ||
- i >= tokensLength || tokens[i++].type !== TokenType.Colon) return 0;
- return (l = checkInterpolatedVariable(i) || checkIdent(i)) ? l + 2 : 0;
- }
- /**
- * @returns {Array}
- */
- function getPseudoe() {
- var startPos = pos,
- x = [];
- pos += 2;
- x.push(checkInterpolatedVariable(pos) ? getInterpolatedVariable() : getIdent());
- var token = tokens[startPos];
- return new Node(NodeType.PseudoeType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkPseudoc(i) {
- var l;
- if (i >= tokensLength || tokens[i++].type !== TokenType.Colon) return 0;
- return (l = checkInterpolatedVariable(i) || checkFunction(i) || checkIdent(i)) ? l + 1 : 0;
- }
- /**
- * @returns {Array}
- */
- function getPseudoc() {
- var startPos = pos,
- x = [];
- pos ++;
- if (checkInterpolatedVariable(pos)) x.push(getInterpolatedVariable());
- else if (checkFunction(pos)) x.push(getFunction());
- else x.push(getIdent());
- var token = tokens[startPos];
- return new Node(NodeType.PseudocType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkRuleset(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (tokens[start].ruleset_l) return tokens[start].ruleset_l;
- while (i < tokensLength) {
- if (l = checkBlock(i)) {i += l; break;}
- else if (l = checkSelector(i)) i += l;
- else return 0;
- }
- tokens[start].ruleset_l = i - start;
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getRuleset() {
- var startPos = pos,
- x = [];
- while (pos < tokensLength) {
- if (checkBlock(pos)) {x.push(getBlock()); break;}
- else if (checkSelector(pos)) x.push(getSelector());
- else break;
- }
- var token = tokens[startPos];
- return new Node(NodeType.RulesetType, x, token.ln, token.col);
- }
- /**
- * Check if token is marked as a space (if it's a space or a tab
- * or a line break).
- * @param i
- * @returns {Number} Number of spaces in a row starting with the given token.
- */
- function checkS(i) {
- return i < tokensLength && tokens[i].ws ? tokens[i].ws_last - i + 1 : 0;
- }
- /**
- * Get node with spaces
- * @returns {Array} `['s', x]` where `x` is a string containing spaces
- */
- function getS() {
- var startPos = pos,
- x = joinValues(pos, tokens[pos].ws_last);
- pos = tokens[pos].ws_last + 1;
- var token = tokens[startPos];
- return new Node(NodeType.SType, x, token.ln, token.col);
- }
- /**
- * Check if token is a space or a comment.
- * @param {Number} i Token's index number
- * @returns {Number} Number of similar (space or comment) tokens
- * in a row starting with the given token.
- */
- function checkSC(i) {
- if (i >= tokensLength) return 0;
- var l,
- lsc = 0,
- ln = tokens[i].ln;
- while (i < tokensLength) {
- if (!(l = checkS(i)) &&
- !(l = checkCommentML(i)) &&
- !(l = checkCommentSL(i))) break;
- i += l;
- lsc += l;
- }
- return lsc || 0;
- }
- /**
- * Get node with spaces and comments
- * @returns {Array} Array containing nodes with spaces (if there are any)
- * and nodes with comments (if there are any):
- * `[['s', x]*, ['comment', y]*]` where `x` is a string of spaces
- * and `y` is a comment's text (without `/*` and `* /`).
- */
- function getSC() {
- var sc = [],
- ln;
- if (pos >= tokensLength) return sc;
- ln = tokens[pos].ln;
- while (pos < tokensLength) {
- if (checkS(pos)) sc.push(getS());
- else if (checkCommentML(pos)) sc.push(getCommentML());
- else if (checkCommentSL(pos)) sc.push(getCommentSL());
- else break;
- }
- return sc;
- }
- /**
- * Check if token is part of a selector
- * @param {Number} i Token's index number
- * @returns {Number} Length of the selector
- */
- function checkSelector(i) {
- var start = i,
- l;
- while (i < tokensLength) {
- if (l = checkSimpleSelector(i) || checkDelim(i)) i += l;
- else break;
- }
- if (i !== start) tokens[start].selector_end = i - 1;
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getSelector() {
- var startPos = pos,
- x = [],
- selector_end = tokens[pos].selector_end;
- while (pos <= selector_end) {
- x.push(checkDelim(pos) ? getDelim() : getSimpleSelector());
- }
- var token = tokens[startPos];
- return new Node(NodeType.SelectorType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a hexadecimal number (e.g. `#fff`) inside
- * a simple selector
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkShash(i) {
- var l;
- if (i >= tokensLength || tokens[i].type !== TokenType.NumberSign) return 0;
- return (l = checkNmName(i + 1)) ? l + 1 : 0;
- }
- /**
- * Get node with a hexadecimal number (e.g. `#fff`) inside a simple
- * selector
- * @returns {Array} `['shash', x]` where `x` is a hexadecimal number
- * converted to string (without `#`, e.g. `fff`)
- */
- function getShash() {
- var startPos = pos,
- x = [];
- pos++;
- x.push(getNmName());
- var token = tokens[startPos];
- return new Node(NodeType.ShashType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkSimpleSelector(i) {
- var start = i,
- l;
- while (i < tokensLength) {
- if (l = checkSimpleSelector1(i)) i += l;
- else break;
- }
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getSimpleSelector() {
- var startPos = pos,
- x = [],
- t;
- while (pos < tokensLength) {
- if (!checkSimpleSelector1(pos)) break;
- t = getSimpleSelector1();
- if ((needInfo && typeof t[1] === 'string') || typeof t[0] === 'string') x.push(t);
- else x = x.concat(t);
- }
- var token = tokens[startPos];
- return new Node(NodeType.SimpleselectorType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkSimpleSelector1(i) {
- var l;
- if (l = checkParentSelector(i)) tokens[i].simpleselector1_child = 1;
- else if (l = checkNthselector(i)) tokens[i].simpleselector1_child = 2;
- else if (l = checkCombinator(i)) tokens[i].simpleselector1_child = 3;
- else if (l = checkAttrib(i)) tokens[i].simpleselector1_child = 4;
- else if (l = checkPseudo(i)) tokens[i].simpleselector1_child = 5;
- else if (l = checkShash(i)) tokens[i].simpleselector1_child = 6;
- else if (l = checkAny(i)) tokens[i].simpleselector1_child = 7;
- else if (l = checkSC(i)) tokens[i].simpleselector1_child = 8;
- else if (l = checkNamespace(i)) tokens[i].simpleselector1_child = 9;
- else if (l = checkDeepSelector(i)) tokens[i].simpleselector1_child = 10;
- return l;
- }
- /**
- * @returns {Array}
- */
- function getSimpleSelector1() {
- var childType = tokens[pos].simpleselector1_child;
- if (childType === 1) return getParentSelector();
- else if (childType === 2) return getNthselector();
- else if (childType === 3) return getCombinator();
- else if (childType === 4) return getAttrib();
- else if (childType === 5) return getPseudo();
- else if (childType === 6) return getShash();
- else if (childType === 7) return getAny();
- else if (childType === 8) return getSC();
- else if (childType === 9) return getNamespace();
- else if (childType === 10) return getDeepSelector();
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkSimpleSelector2(i) {
- return checkParentSelector(i) ||
- checkNthselector(i) ||
- checkAttrib(i) ||
- checkPseudo(i) ||
- checkShash(i) ||
- checkIdent(i) ||
- checkClass(i);
- }
- /**
- * @returns {Array}
- */
- function getSimpleSelector2() {
- if (checkParentSelector(pos)) return getParentSelector();
- else if (checkNthselector(pos)) return getNthselector();
- else if (checkAttrib(pos)) return getAttrib();
- else if (checkPseudo(pos)) return getPseudo();
- else if (checkShash(pos)) return getShash();
- else if (checkIdent(pos)) return getIdent();
- else if (checkClass(pos)) return getClass();
- }
- /**
- * Check if token is part of a string (text wrapped in quotes)
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is part of a string, `0` if not
- */
- function checkString(i) {
- return i < tokensLength && (tokens[i].type === TokenType.StringSQ || tokens[i].type === TokenType.StringDQ) ? 1 : 0;
- }
- /**
- * Get string's node
- * @returns {Array} `['string', x]` where `x` is a string (including
- * quotes).
- */
- function getString() {
- var startPos = pos,
- x = tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.StringType, x, token.ln, token.col);
- }
- /**
- * Validate stylesheet: it should consist of any number (0 or more) of
- * rulesets (sets of rules with selectors), @-rules, whitespaces or
- * comments.
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkStylesheet(i) {
- var start = i,
- l;
- // Check every token:
- while (i < tokensLength) {
- if (l = checkSC(i) ||
- checkDeclaration(i) ||
- checkDeclDelim(i) ||
- checkInclude(i) ||
- checkMixin(i) ||
- checkAtrule(i) ||
- checkRuleset(i)) i += l;
- else throwError(i);
- }
- return i - start;
- }
- /**
- * @returns {Array} `['stylesheet', x]` where `x` is all stylesheet's
- * nodes.
- */
- function getStylesheet() {
- var startPos = pos,
- x = [];
- while (pos < tokensLength) {
- if (checkSC(pos)) x = x.concat(getSC());
- else if (checkAtrule(pos)) x.push(getAtrule());
- else if (checkRuleset(pos)) x.push(getRuleset());
- else if (checkInclude(pos)) x.push(getInclude());
- else if (checkMixin(pos)) x.push(getMixin());
- else if (checkDeclaration(pos)) x.push(getDeclaration());
- else if (checkDeclDelim(pos)) x.push(getDeclDelim());
- else throwError(pos);
- }
- var token = tokens[startPos];
- return new Node(NodeType.StylesheetType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkTset(i) {
- return checkVhash(i) ||
- checkAny(i) ||
- checkSC(i) ||
- checkOperator(i);
- }
- /**
- * @returns {Array}
- */
- function getTset() {
- if (checkVhash(pos)) return getVhash();
- else if (checkAny(pos)) return getAny();
- else if (checkSC(pos)) return getSC();
- else if (checkOperator(pos)) return getOperator();
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkTsets(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- while (l = checkTset(i)) {
- i += l;
- }
- return i - start;
- }
- /**
- * @returns {Array}
- */
- function getTsets() {
- var x = [],
- t;
- while (t = getTset()) {
- if ((needInfo && typeof t[1] === 'string') || typeof t[0] === 'string') x.push(t);
- else x = x.concat(t);
- }
- return x;
- }
- /**
- * Check if token is an unary (arithmetical) sign (`+` or `-`)
- * @param {Number} i Token's index number
- * @returns {Number} `1` if token is an unary sign, `0` if not
- */
- function checkUnary(i) {
- return i < tokensLength && (tokens[i].type === TokenType.HyphenMinus || tokens[i].type === TokenType.PlusSign) ? 1 : 0;
- }
- /**
- * Get node with an unary (arithmetical) sign (`+` or `-`)
- * @returns {Array} `['unary', x]` where `x` is an unary sign
- * converted to string.
- */
- function getUnary() {
- var startPos = pos,
- x = tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.UnaryType, x, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkUnknown(i) {
- return i < tokensLength && tokens[i].type === TokenType.CommentSL ? 1 : 0;
- }
- /**
- * @returns {Array}
- */
- function getUnknown() {
- var startPos = pos,
- x = tokens[pos++].value;
- var token = tokens[startPos];
- return new Node(NodeType.UnknownType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of URI (e.g. `url('/css/styles.css')`)
- * @param {Number} i Token's index number
- * @returns {Number} Length of URI
- */
- function checkUri(i) {
- var start = i;
- if (i >= tokensLength || tokens[i++].value !== 'url' ||
- i >= tokensLength || tokens[i].type !== TokenType.LeftParenthesis)
- return 0;
- return tokens[i].right - start + 1;
- }
- /**
- * Get node with URI
- * @returns {Array} `['uri', x]` where `x` is URI's nodes (without `url`
- * and braces, e.g. `['string', ''/css/styles.css'']`).
- */
- function getUri() {
- var startPos = pos,
- uriExcluding = {},
- uri,
- token,
- l,
- raw;
- pos += 2;
- uriExcluding[TokenType.Space] = 1;
- uriExcluding[TokenType.Tab] = 1;
- uriExcluding[TokenType.Newline] = 1;
- uriExcluding[TokenType.LeftParenthesis] = 1;
- uriExcluding[TokenType.RightParenthesis] = 1;
- if (checkUri1(pos)) {
- uri = []
- .concat(getSC())
- .concat([getString()])
- .concat(getSC());
- pos++;
- } else {
- uri = getSC(),
- l = checkExcluding(uriExcluding, pos),
- token = tokens[pos];
- raw = new Node(NodeType.RawType, joinValues (pos, pos + l), token.ln, token.col);
- uri.push(raw);
- pos += l + 1;
- uri = uri.concat(getSC());
- pos++;
- }
- token = tokens[startPos];
- return new Node(NodeType.UriType, uri, token.ln, token.col);
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkUri1(i) {
- var start = i,
- l;
- if (i >= tokensLength) return 0;
- if (l = checkSC(i)) i += l;
- if (tokens[i].type !== TokenType.StringDQ && tokens[i].type !== TokenType.StringSQ) return 0;
- i++;
- if (l = checkSC(i)) i += l;
- return i - start;
- }
- /**
- * Check if token is part of a value
- * @param {Number} i Token's index number
- * @returns {Number} Length of the value
- */
- function checkValue(i) {
- var start = i,
- l, s, _i;
- while (i < tokensLength) {
- s = checkSC(i);
- _i = i + s;
- if (l = _checkValue(_i)) i += l + s;
- if (!l || checkBlock(_i)) break;
- }
- return i - start;
- }
- /**
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function _checkValue(i) {
- return checkEscapedString(i) ||
- checkInterpolatedVariable(i) ||
- checkVariable(i) ||
- checkVhash(i) ||
- checkBlock(i) ||
- checkAny(i) ||
- checkAtkeyword(i) ||
- checkOperator(i) ||
- checkImportant(i);
- }
- /**
- * @returns {Array}
- */
- function getValue() {
- var startPos = pos,
- x = [],
- s, _pos;
- while (pos < tokensLength) {
- s = checkSC(pos);
- _pos = pos + s;
- if (!_checkValue(_pos)) break;
- if (s) x = x.concat(getSC());
- x.push(_getValue());
- }
- var token = tokens[startPos];
- return new Node(NodeType.ValueType, x, token.ln, token.col);
- }
- /**
- * @returns {Array}
- */
- function _getValue() {
- if (checkEscapedString(pos)) return getEscapedString();
- else if (checkInterpolatedVariable(pos)) return getInterpolatedVariable();
- else if (checkVariable(pos)) return getVariable();
- else if (checkVhash(pos)) return getVhash();
- else if (checkBlock(pos)) return getBlock();
- else if (checkAny(pos)) return getAny();
- else if (checkAtkeyword(pos)) return getAtkeyword();
- else if (checkOperator(pos)) return getOperator();
- else if (checkImportant(pos)) return getImportant();
- }
- /**
- * Check if token is part of LESS variable
- * @param {Number} i Token's index number
- * @returns {Number} Length of the variable
- */
- function checkVariable(i) {
- var l;
- if (i >= tokensLength || tokens[i].type !== TokenType.CommercialAt) return 0;
- if (tokens[i - 1] &&
- tokens[i - 1].type === TokenType.CommercialAt &&
- tokens[i - 2] &&
- tokens[i - 2].type === TokenType.CommercialAt) return 0;
- return (l = checkVariable(i + 1) || checkIdent(i + 1)) ? l + 1 : 0;
- }
- /**
- * Get node with a variable
- * @returns {Array} `['variable', ['ident', x]]` where `x` is
- * a variable name.
- */
- function getVariable() {
- var startPos = pos,
- x = [];
- pos++;
- if (checkVariable(pos)) x.push(getVariable());
- else x.push(getIdent());
- var token = tokens[startPos];
- return new Node(NodeType.VariableType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a variables list (e.g. `@rest...`).
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkVariablesList(i) {
- var d = 0, // number of dots
- l;
- if (i >= tokensLength) return 0;
- if (l = checkVariable(i)) i+= l;
- else return 0;
- while (tokens[i] && tokens[i].type === TokenType.FullStop) {
- d++;
- i++;
- }
- return d === 3 ? l + d : 0;
- }
- /**
- * Get node with a variables list
- * @returns {Array} `['variableslist', ['variable', ['ident', x]]]` where
- * `x` is a variable name.
- */
- function getVariablesList() {
- var startPos = pos,
- x = [getVariable()];
- pos += 3;
- var token = tokens[startPos];
- return new Node(NodeType.VariablesListType, x, token.ln, token.col);
- }
- /**
- * Check if token is part of a hexadecimal number (e.g. `#fff`) inside
- * some value
- * @param {Number} i Token's index number
- * @returns {Number}
- */
- function checkVhash(i) {
- var l;
- if (i >= tokensLength || tokens[i].type !== TokenType.NumberSign) return 0;
- return (l = checkNmName2(i + 1)) ? l + 1 : 0;
- }
- /**
- * Get node with a hexadecimal number (e.g. `#fff`) inside some value
- * @returns {Array} `['vhash', x]` where `x` is a hexadecimal number
- * converted to string (without `#`, e.g. `'fff'`).
- */
- function getVhash() {
- var startPos = pos,
- x;
- pos++;
- x = getNmName2();
- var token = tokens[startPos];
- return new Node(NodeType.VhashType, x, token.ln, token.col);
- }
- return function(_tokens, rule, _needInfo) {
- tokens = _tokens;
- needInfo = _needInfo;
- tokensLength = tokens.length;
- pos = 0;
- return rules[rule]();
- };
- })();
|