@@ -28,6 +28,25 @@ module.exports = class LessParser extends Parser {
2828 variableNode ( this . lastNode ) ;
2929 }
3030
31+ each ( tokens ) {
32+ // prepend a space so the `name` will be parsed correctly
33+ tokens [ 0 ] [ 1 ] = ` ${ tokens [ 0 ] [ 1 ] } ` ;
34+
35+ const firstParenIndex = tokens . findIndex ( ( t ) => t [ 0 ] === '(' ) ;
36+ const lastParen = tokens . reverse ( ) . find ( ( t ) => t [ 0 ] === ')' ) ;
37+ const lastParenIndex = tokens . reverse ( ) . indexOf ( lastParen ) ;
38+ const paramTokens = tokens . splice ( firstParenIndex , lastParenIndex ) ;
39+ const params = paramTokens . map ( ( t ) => t [ 1 ] ) . join ( '' ) ;
40+
41+ for ( const token of tokens . reverse ( ) ) {
42+ this . tokenizer . back ( token ) ;
43+ }
44+
45+ this . atrule ( this . tokenizer . nextToken ( ) ) ;
46+ this . lastNode . function = true ;
47+ this . lastNode . params = params ;
48+ }
49+
3150 init ( node , line , column ) {
3251 super . init ( node , line , column ) ;
3352 this . lastNode = node ;
@@ -53,6 +72,53 @@ module.exports = class LessParser extends Parser {
5372 }
5473 }
5574
75+ mixin ( tokens ) {
76+ const [ first ] = tokens ;
77+ const identifier = first [ 1 ] . slice ( 0 , 1 ) ;
78+ const bracketsIndex = tokens . findIndex ( ( t ) => t [ 0 ] === 'brackets' ) ;
79+ const firstParenIndex = tokens . findIndex ( ( t ) => t [ 0 ] === '(' ) ;
80+ let important = '' ;
81+
82+ // fix for #86. if rulesets are mixin params, they need to be converted to a brackets token
83+ if ( ( bracketsIndex < 0 || bracketsIndex > 3 ) && firstParenIndex > 0 ) {
84+ const lastParenIndex = tokens . findIndex ( ( t ) => t [ 0 ] === ')' ) ;
85+
86+ const contents = tokens . slice ( firstParenIndex , lastParenIndex + firstParenIndex ) ;
87+ const brackets = contents . map ( ( t ) => t [ 1 ] ) . join ( '' ) ;
88+ const [ paren ] = tokens . slice ( firstParenIndex ) ;
89+ const start = [ paren [ 2 ] , paren [ 3 ] ] ;
90+ const [ last ] = tokens . slice ( lastParenIndex , lastParenIndex + 1 ) ;
91+ const end = [ last [ 2 ] , last [ 3 ] ] ;
92+ const newToken = [ 'brackets' , brackets ] . concat ( start , end ) ;
93+
94+ const tokensBefore = tokens . slice ( 0 , firstParenIndex ) ;
95+ const tokensAfter = tokens . slice ( lastParenIndex + 1 ) ;
96+ tokens = tokensBefore ;
97+ tokens . push ( newToken ) ;
98+ tokens = tokens . concat ( tokensAfter ) ;
99+ }
100+
101+ const importantIndex = tokens . findIndex ( ( t ) => importantPattern . test ( t [ 1 ] ) ) ;
102+
103+ if ( importantIndex > 0 ) {
104+ [ , important ] = tokens [ importantIndex ] ;
105+ tokens . splice ( importantIndex , 1 ) ;
106+ }
107+
108+ for ( const token of tokens . reverse ( ) ) {
109+ this . tokenizer . back ( token ) ;
110+ }
111+
112+ this . atrule ( this . tokenizer . nextToken ( ) ) ;
113+ this . lastNode . mixin = true ;
114+ this . lastNode . raws . identifier = identifier ;
115+
116+ if ( important ) {
117+ this . lastNode . important = true ;
118+ this . lastNode . raws . important = important ;
119+ }
120+ }
121+
56122 other ( token ) {
57123 if ( ! isInlineComment . bind ( this ) ( token ) ) {
58124 super . other ( token ) ;
@@ -84,56 +150,18 @@ module.exports = class LessParser extends Parser {
84150 unknownWord ( tokens ) {
85151 // NOTE: keep commented for examining unknown structures
86152 // console.log('unknown', tokens);
87- // console.log(this.root.first);
88153
89154 const [ first ] = tokens ;
90155
156+ // #121 support `each` - http://lesscss.org/functions/#list-functions-each
157+ if ( tokens [ 0 ] [ 1 ] === 'each' && tokens [ 1 ] [ 0 ] === '(' ) {
158+ this . each ( tokens ) ;
159+ return ;
160+ }
161+
91162 // TODO: move this into a util function/file
92163 if ( isMixinToken ( first ) ) {
93- const identifier = first [ 1 ] . slice ( 0 , 1 ) ;
94- const bracketsIndex = tokens . findIndex ( ( t ) => t [ 0 ] === 'brackets' ) ;
95- const firstParenIndex = tokens . findIndex ( ( t ) => t [ 0 ] === '(' ) ;
96- let important = '' ;
97-
98- // fix for #86. if rulesets are mixin params, they need to be converted to a brackets token
99- if ( ( bracketsIndex < 0 || bracketsIndex > 3 ) && firstParenIndex > 0 ) {
100- const lastParenIndex = tokens . findIndex ( ( t ) => t [ 0 ] === ')' ) ;
101-
102- const contents = tokens . slice ( firstParenIndex , lastParenIndex + firstParenIndex ) ;
103- const brackets = contents . map ( ( t ) => t [ 1 ] ) . join ( '' ) ;
104- const [ paren ] = tokens . slice ( firstParenIndex ) ;
105- const start = [ paren [ 2 ] , paren [ 3 ] ] ;
106- const [ last ] = tokens . slice ( lastParenIndex , lastParenIndex + 1 ) ;
107- const end = [ last [ 2 ] , last [ 3 ] ] ;
108- const newToken = [ 'brackets' , brackets ] . concat ( start , end ) ;
109-
110- const tokensBefore = tokens . slice ( 0 , firstParenIndex ) ;
111- const tokensAfter = tokens . slice ( lastParenIndex + 1 ) ;
112- tokens = tokensBefore ;
113- tokens . push ( newToken ) ;
114- tokens = tokens . concat ( tokensAfter ) ;
115- }
116-
117- const importantIndex = tokens . findIndex ( ( t ) => importantPattern . test ( t [ 1 ] ) ) ;
118-
119- if ( importantIndex > 0 ) {
120- [ , important ] = tokens [ importantIndex ] ;
121- tokens . splice ( importantIndex , 1 ) ;
122- }
123-
124- for ( const token of tokens . reverse ( ) ) {
125- this . tokenizer . back ( token ) ;
126- }
127-
128- this . atrule ( this . tokenizer . nextToken ( ) ) ;
129- this . lastNode . mixin = true ;
130- this . lastNode . raws . identifier = identifier ;
131-
132- if ( important ) {
133- this . lastNode . important = true ;
134- this . lastNode . raws . important = important ;
135- }
136-
164+ this . mixin ( tokens ) ;
137165 return ;
138166 }
139167
0 commit comments