@@ -20,15 +20,16 @@ export class LESSParser extends cssParser.Parser {
20
20
super ( new lessScanner . LESSScanner ( ) ) ;
21
21
}
22
22
23
- public _parseStylesheetStatement ( ) : nodes . Node {
23
+ public _parseStylesheetStatement ( isNested : boolean = false ) : nodes . Node {
24
24
if ( this . peek ( TokenType . AtKeyword ) ) {
25
25
return this . _parseVariableDeclaration ( )
26
26
|| this . _parsePlugin ( )
27
- || super . _parseStylesheetAtStatement ( ) ;
27
+ || super . _parseStylesheetAtStatement ( isNested ) ;
28
28
}
29
29
30
30
return this . _tryParseMixinDeclaration ( )
31
- || this . _tryParseMixinReference ( true )
31
+ || this . _tryParseMixinReference ( )
32
+ || this . _parseFunction ( )
32
33
|| this . _parseRuleset ( true ) ;
33
34
}
34
35
@@ -104,7 +105,7 @@ export class LESSParser extends cssParser.Parser {
104
105
|| this . _tryParseMixinDeclaration ( )
105
106
|| this . _tryParseMixinReference ( )
106
107
|| this . _parseDetachedRuleSetMixin ( )
107
- || this . _parseStylesheetStatement ( ) ;
108
+ || this . _parseStylesheetStatement ( isNested ) ;
108
109
}
109
110
110
111
public _parseMediaFeatureName ( ) : nodes . Node {
@@ -115,13 +116,15 @@ export class LESSParser extends cssParser.Parser {
115
116
let node = < nodes . VariableDeclaration > this . create ( nodes . VariableDeclaration ) ;
116
117
117
118
let mark = this . mark ( ) ;
118
- if ( ! node . setVariable ( this . _parseVariable ( ) ) ) {
119
+ if ( ! this . peekDelim ( '@' ) && ! this . peek ( TokenType . AtKeyword ) || ! node . setVariable ( this . _parseVariable ( ) ) ) {
119
120
return null ;
120
121
}
121
122
122
123
if ( this . accept ( TokenType . Colon ) ) {
123
124
node . colonPosition = this . prevToken . offset ;
124
- if ( ! node . setValue ( this . _parseDetachedRuleSet ( ) || this . _parseExpr ( ) ) ) {
125
+ if ( node . setValue ( this . _parseDetachedRuleSet ( ) ) ) {
126
+ node . needsSemicolon = false ;
127
+ } else if ( ! node . setValue ( this . _parseExpr ( ) ) ) {
125
128
return < nodes . VariableDeclaration > this . finish ( node , ParseError . VariableValueExpected , [ ] , panic ) ;
126
129
}
127
130
@@ -150,23 +153,24 @@ export class LESSParser extends cssParser.Parser {
150
153
}
151
154
152
155
public _parseDetachedRuleSetBody ( ) : nodes . Node {
153
- return this . _tryParseKeyframeSelector ( ) || this . _tryParseRuleset ( true ) || super . _parseRuleSetDeclaration ( ) ;
156
+ return this . _tryParseKeyframeSelector ( ) || this . _parseRuleSetDeclaration ( ) ;
154
157
}
155
158
156
159
public _parseVariable ( ) : nodes . Variable {
157
- if ( ! this . peekDelim ( '@' ) && ! this . peek ( TokenType . AtKeyword ) ) {
160
+ if ( ! this . peekDelim ( '@' ) && ! this . peekDelim ( '$' ) && ! this . peek ( TokenType . AtKeyword ) ) {
158
161
return null ;
159
162
}
160
163
161
164
let node = < nodes . Variable > this . create ( nodes . Variable ) ;
162
165
let mark = this . mark ( ) ;
163
- while ( this . acceptDelim ( '@' ) ) {
166
+
167
+ while ( this . acceptDelim ( '@' ) || this . acceptDelim ( '$' ) ) {
164
168
if ( this . hasWhitespace ( ) ) {
165
169
this . restoreAtMark ( mark ) ;
166
170
return null ;
167
171
}
168
172
}
169
- if ( ! this . accept ( TokenType . AtKeyword ) ) {
173
+ if ( ! this . accept ( TokenType . AtKeyword ) && ! this . accept ( TokenType . Ident ) ) {
170
174
this . restoreAtMark ( mark ) ;
171
175
return null ;
172
176
}
@@ -179,7 +183,8 @@ export class LESSParser extends cssParser.Parser {
179
183
180
184
term = < nodes . Term > this . create ( nodes . Term ) ;
181
185
if ( term . setExpression ( this . _parseVariable ( ) ) ||
182
- term . setExpression ( this . _parseEscaped ( ) ) ) {
186
+ term . setExpression ( this . _parseEscaped ( ) ) ||
187
+ term . setExpression ( this . _tryParseMixinReference ( ) ) ) {
183
188
184
189
return < nodes . Term > this . finish ( term ) ;
185
190
}
@@ -247,12 +252,14 @@ export class LESSParser extends cssParser.Parser {
247
252
|| this . _parseImport ( )
248
253
|| this . _parseSupports ( true ) // @supports
249
254
|| this . _parseDetachedRuleSetMixin ( ) // less detached ruleset mixin
250
- || this . _parseVariableDeclaration ( ) ; // Variable declarations
255
+ || this . _parseVariableDeclaration ( ) // Variable declarations
256
+ || this . _parseUnknownAtRule ( ) ;
251
257
252
258
}
253
259
return this . _tryParseMixinDeclaration ( )
254
260
|| this . _tryParseRuleset ( true ) // nested ruleset
255
261
|| this . _tryParseMixinReference ( ) // less mixin reference
262
+ || this . _parseFunction ( )
256
263
|| this . _parseExtend ( ) // less extend declaration
257
264
|| super . _parseRuleSetDeclaration ( ) ; // try css ruleset declaration as the last option
258
265
}
@@ -332,7 +339,10 @@ export class LESSParser extends cssParser.Parser {
332
339
}
333
340
334
341
private peekInterpolatedIdent ( ) {
335
- return this . peek ( TokenType . Ident ) || this . peekDelim ( '@' ) || this . peekDelim ( '-' ) ;
342
+ return this . peek ( TokenType . Ident ) ||
343
+ this . peekDelim ( '@' ) ||
344
+ this . peekDelim ( '$' ) ||
345
+ this . peekDelim ( '-' ) ;
336
346
}
337
347
338
348
public _acceptInterpolatedIdent ( node : nodes . Node ) : boolean {
@@ -361,9 +371,10 @@ export class LESSParser extends cssParser.Parser {
361
371
}
362
372
363
373
public _parseInterpolation ( ) : nodes . Node {
364
- // @{name}
374
+ // @{name} Variable or
375
+ // ${name} Property
365
376
let mark = this . mark ( ) ;
366
- if ( this . peekDelim ( '@' ) ) {
377
+ if ( this . peekDelim ( '@' ) || this . peekDelim ( '$' ) ) {
367
378
let node = this . createNode ( nodes . NodeType . Interpolation ) ;
368
379
this . consumeToken ( ) ;
369
380
if ( this . hasWhitespace ( ) || ! this . accept ( TokenType . CurlyL ) ) {
@@ -492,7 +503,7 @@ export class LESSParser extends cssParser.Parser {
492
503
}
493
504
let mark = this . mark ( ) ;
494
505
let node = < nodes . MixinReference > this . create ( nodes . MixinReference ) ;
495
- if ( ! node . addChild ( this . _parseVariable ( ) ) || ! this . accept ( TokenType . ParenthesisL ) ) {
506
+ if ( node . addChild ( this . _parseVariable ( ) ) && ( this . hasWhitespace ( ) || ! this . accept ( TokenType . ParenthesisL ) ) ) {
496
507
this . restoreAtMark ( mark ) ;
497
508
return null ;
498
509
}
@@ -503,7 +514,7 @@ export class LESSParser extends cssParser.Parser {
503
514
}
504
515
505
516
506
- public _tryParseMixinReference ( atRoot = false ) : nodes . Node {
517
+ public _tryParseMixinReference ( ) : nodes . Node {
507
518
let mark = this . mark ( ) ;
508
519
let node = < nodes . MixinReference > this . create ( nodes . MixinReference ) ;
509
520
@@ -602,7 +613,7 @@ export class LESSParser extends cssParser.Parser {
602
613
this . accept ( TokenType . Colon ) ;
603
614
hasContent = true ;
604
615
}
605
- if ( ! node . setDefaultValue ( this . _parseExpr ( true ) ) && ! hasContent ) {
616
+ if ( ! node . setDefaultValue ( this . _parseDetachedRuleSet ( ) || this . _parseExpr ( true ) ) && ! hasContent ) {
606
617
return null ;
607
618
}
608
619
return this . finish ( node ) ;
@@ -647,6 +658,37 @@ export class LESSParser extends cssParser.Parser {
647
658
return this . finish ( node ) ;
648
659
}
649
660
661
+ public _parseFunction ( ) : nodes . Function {
662
+
663
+ let pos = this . mark ( ) ;
664
+ let node = < nodes . Function > this . create ( nodes . Function ) ;
665
+
666
+ if ( ! node . setIdentifier ( this . _parseFunctionIdentifier ( ) ) ) {
667
+ return null ;
668
+ }
669
+
670
+ if ( this . hasWhitespace ( ) || ! this . accept ( TokenType . ParenthesisL ) ) {
671
+ this . restoreAtMark ( pos ) ;
672
+ return null ;
673
+ }
674
+
675
+ if ( node . getArguments ( ) . addChild ( this . _parseMixinArgument ( ) ) ) {
676
+ while ( this . accept ( TokenType . Comma ) || this . accept ( TokenType . SemiColon ) ) {
677
+ if ( this . peek ( TokenType . ParenthesisR ) ) {
678
+ break ;
679
+ }
680
+ if ( ! node . getArguments ( ) . addChild ( this . _parseMixinArgument ( ) ) ) {
681
+ return this . finish ( node , ParseError . ExpressionExpected ) ;
682
+ }
683
+ }
684
+ }
685
+
686
+ if ( ! this . accept ( TokenType . ParenthesisR ) ) {
687
+ return < nodes . Function > this . finish ( node , ParseError . RightParenthesisExpected ) ;
688
+ }
689
+ return < nodes . Function > this . finish ( node ) ;
690
+ }
691
+
650
692
public _parseFunctionIdentifier ( ) : nodes . Identifier {
651
693
if ( this . peekDelim ( '%' ) ) {
652
694
let node = < nodes . Identifier > this . create ( nodes . Identifier ) ;
0 commit comments