@@ -4,6 +4,7 @@ import visitors from '../visitors';
4
4
import getParserInput from './parser-input' ;
5
5
import * as utils from '../utils' ;
6
6
import functionRegistry from '../functions/function-registry' ;
7
+ import { ContainerSyntaxOptions , MediaSyntaxOptions } from '../tree/atrule-syntax' ;
7
8
8
9
//
9
10
// less.js - parser
@@ -1698,7 +1699,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
1698
1699
const options = ( dir ? this . importOptions ( ) : null ) || { } ;
1699
1700
1700
1701
if ( ( path = this . entities . quoted ( ) || this . entities . url ( ) ) ) {
1701
- features = this . mediaFeatures ( ) ;
1702
+ features = this . mediaFeatures ( { } ) ;
1702
1703
1703
1704
if ( ! parserInput . $char ( ';' ) ) {
1704
1705
parserInput . i = index ;
@@ -1752,22 +1753,39 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
1752
1753
}
1753
1754
} ,
1754
1755
1755
- mediaFeature : function ( ) {
1756
+ mediaFeature : function ( syntaxOptions ) {
1756
1757
const entities = this . entities ;
1757
1758
const nodes = [ ] ;
1758
1759
let e ;
1759
1760
let p ;
1761
+ let rangeP ;
1760
1762
parserInput . save ( ) ;
1761
1763
do {
1762
1764
e = entities . keyword ( ) || entities . variable ( ) || entities . mixinLookup ( ) ;
1763
1765
if ( e ) {
1764
1766
nodes . push ( e ) ;
1765
1767
} else if ( parserInput . $char ( '(' ) ) {
1766
1768
p = this . property ( ) ;
1767
- e = this . value ( ) ;
1769
+ parserInput . save ( ) ;
1770
+ if ( ! p && syntaxOptions . queryInParens && parserInput . $re ( / ^ [ 0 - 9 a - z - ] * \s * ( [ < > ] = | < = | > = | [ < > ] | = ) / ) ) {
1771
+ parserInput . restore ( ) ;
1772
+ p = this . condition ( ) ;
1773
+
1774
+ parserInput . save ( ) ;
1775
+ rangeP = this . atomicCondition ( null , p . rvalue ) ;
1776
+ if ( ! rangeP ) {
1777
+ parserInput . restore ( ) ;
1778
+ }
1779
+ } else {
1780
+ parserInput . restore ( ) ;
1781
+ e = this . value ( ) ;
1782
+ }
1768
1783
if ( parserInput . $char ( ')' ) ) {
1769
- if ( p && e ) {
1770
- nodes . push ( new ( tree . Paren ) ( new ( tree . Declaration ) ( p , e , null , null , parserInput . i + currentIndex , fileInfo , true ) ) ) ;
1784
+ if ( p && ! e ) {
1785
+ nodes . push ( new ( tree . Paren ) ( new ( tree . QueryInParens ) ( p . op , p . lvalue , p . rvalue , rangeP ? rangeP . op : null , rangeP ? rangeP . rvalue : null , p . _index ) ) ) ;
1786
+ e = p ;
1787
+ } else if ( p && e ) {
1788
+ nodes . push ( new ( tree . Paren ) ( new ( tree . Declaration ) ( p , e , null , null , parserInput . i + currentIndex , fileInfo , true ) ) ) ;
1771
1789
} else if ( e ) {
1772
1790
nodes . push ( new ( tree . Paren ) ( e ) ) ;
1773
1791
} else {
@@ -1785,12 +1803,12 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
1785
1803
}
1786
1804
} ,
1787
1805
1788
- mediaFeatures : function ( ) {
1806
+ mediaFeatures : function ( syntaxOptions ) {
1789
1807
const entities = this . entities ;
1790
1808
const features = [ ] ;
1791
1809
let e ;
1792
1810
do {
1793
- e = this . mediaFeature ( ) ;
1811
+ e = this . mediaFeature ( syntaxOptions ) ;
1794
1812
if ( e ) {
1795
1813
features . push ( e ) ;
1796
1814
if ( ! parserInput . $char ( ',' ) ) { break ; }
@@ -1806,38 +1824,44 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
1806
1824
return features . length > 0 ? features : null ;
1807
1825
} ,
1808
1826
1809
- media : function ( ) {
1810
- let features ;
1811
- let rules ;
1812
- let media ;
1827
+ prepareAndGetNestableAtRule : function ( treeType , index , debugInfo , syntaxOptions ) {
1828
+ const features = this . mediaFeatures ( syntaxOptions ) ;
1829
+
1830
+ const rules = this . block ( ) ;
1831
+
1832
+ if ( ! rules ) {
1833
+ error ( 'media definitions require block statements after any features' ) ;
1834
+ }
1835
+
1836
+ parserInput . forget ( ) ;
1837
+
1838
+ const atRule = new ( treeType ) ( rules , features , index + currentIndex , fileInfo ) ;
1839
+ if ( context . dumpLineNumbers ) {
1840
+ atRule . debugInfo = debugInfo ;
1841
+ }
1842
+
1843
+ return atRule ;
1844
+ } ,
1845
+
1846
+ nestableAtRule : function ( ) {
1813
1847
let debugInfo ;
1814
1848
const index = parserInput . i ;
1815
1849
1816
1850
if ( context . dumpLineNumbers ) {
1817
1851
debugInfo = getDebugInfo ( index ) ;
1818
1852
}
1819
-
1820
1853
parserInput . save ( ) ;
1821
1854
1822
- if ( parserInput . $str ( '@media' ) ) {
1823
- features = this . mediaFeatures ( ) ;
1824
-
1825
- rules = this . block ( ) ;
1826
-
1827
- if ( ! rules ) {
1828
- error ( 'media definitions require block statements after any features' ) ;
1855
+ if ( parserInput . $peekChar ( '@' ) ) {
1856
+ if ( parserInput . $str ( '@media' ) ) {
1857
+ return this . prepareAndGetNestableAtRule ( tree . Media , index , debugInfo , MediaSyntaxOptions ) ;
1829
1858
}
1830
-
1831
- parserInput . forget ( ) ;
1832
-
1833
- media = new ( tree . Media ) ( rules , features , index + currentIndex , fileInfo ) ;
1834
- if ( context . dumpLineNumbers ) {
1835
- media . debugInfo = debugInfo ;
1859
+
1860
+ if ( parserInput . $str ( '@container' ) ) {
1861
+ return this . prepareAndGetNestableAtRule ( tree . Container , index , debugInfo , ContainerSyntaxOptions ) ;
1836
1862
}
1837
-
1838
- return media ;
1839
1863
}
1840
-
1864
+
1841
1865
parserInput . restore ( ) ;
1842
1866
} ,
1843
1867
@@ -1919,7 +1943,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
1919
1943
1920
1944
if ( parserInput . currentChar ( ) !== '@' ) { return ; }
1921
1945
1922
- value = this [ 'import' ] ( ) || this . plugin ( ) || this . media ( ) ;
1946
+ value = this [ 'import' ] ( ) || this . plugin ( ) || this . nestableAtRule ( ) ;
1923
1947
if ( value ) {
1924
1948
return value ;
1925
1949
}
@@ -2231,7 +2255,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
2231
2255
parserInput . forget ( ) ;
2232
2256
return body ;
2233
2257
} ,
2234
- atomicCondition : function ( ) {
2258
+ atomicCondition : function ( needsParens , preparsedCond ) {
2235
2259
const entities = this . entities ;
2236
2260
const index = parserInput . i ;
2237
2261
let a ;
@@ -2243,7 +2267,12 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
2243
2267
return this . addition ( ) || entities . keyword ( ) || entities . quoted ( ) || entities . mixinLookup ( ) ;
2244
2268
} ) . bind ( this )
2245
2269
2246
- a = cond ( ) ;
2270
+ if ( preparsedCond ) {
2271
+ a = preparsedCond ;
2272
+ } else {
2273
+ a = cond ( ) ;
2274
+ }
2275
+
2247
2276
if ( a ) {
2248
2277
if ( parserInput . $char ( '>' ) ) {
2249
2278
if ( parserInput . $char ( '=' ) ) {
@@ -2275,7 +2304,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
2275
2304
} else {
2276
2305
error ( 'expected expression' ) ;
2277
2306
}
2278
- } else {
2307
+ } else if ( ! preparsedCond ) {
2279
2308
c = new ( tree . Condition ) ( '=' , a , new ( tree . Keyword ) ( 'true' ) , index + currentIndex , false ) ;
2280
2309
}
2281
2310
return c ;
@@ -2422,4 +2451,4 @@ Parser.serializeVars = vars => {
2422
2451
return s ;
2423
2452
} ;
2424
2453
2425
- export default Parser ;
2454
+ export default Parser ;
0 commit comments