Skip to content

Commit 36626c8

Browse files
authored
fix(issue#4242): add support for layer at-rule (#4337)
* Add support for layer at-rule. * Add tests for layer at-rule.
1 parent 1a5553d commit 36626c8

File tree

5 files changed

+198
-2
lines changed

5 files changed

+198
-2
lines changed

packages/less/src/less/parser/parser.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,7 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
20652065
let hasUnknown;
20662066
let hasBlock = true;
20672067
let isRooted = true;
2068+
let isKeywordList = false;
20682069

20692070
if (parserInput.currentChar() !== '@') { return; }
20702071

@@ -2105,6 +2106,9 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
21052106
case '@starting-style':
21062107
isRooted = false;
21072108
break;
2109+
case '@layer':
2110+
isRooted = false;
2111+
break;
21082112
default:
21092113
hasUnknown = true;
21102114
break;
@@ -2137,9 +2141,38 @@ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
21372141

21382142
if (hasBlock) {
21392143
rules = this.blockRuleset();
2144+
2145+
parserInput.save();
2146+
2147+
if (!rules && !isRooted) {
2148+
value = this.entity();
2149+
rules = this.blockRuleset();
2150+
}
2151+
2152+
if (!rules && !isRooted) {
2153+
parserInput.restore();
2154+
2155+
let e = [];
2156+
value = this.entity();
2157+
2158+
while (parserInput.$char(',')) {
2159+
e.push(value);
2160+
value = this.entity();
2161+
}
2162+
2163+
if (value && e.length > 0) {
2164+
e.push(value);
2165+
value = e;
2166+
isKeywordList = true;
2167+
} else {
2168+
rules = this.blockRuleset();
2169+
}
2170+
} else {
2171+
parserInput.forget();
2172+
}
21402173
}
21412174

2142-
if (rules || (!hasBlock && value && parserInput.$char(';'))) {
2175+
if (rules || isKeywordList || (!hasBlock && value && parserInput.$char(';'))) {
21432176
parserInput.forget();
21442177
return new(tree.AtRule)(name, value, rules, index + currentIndex, fileInfo,
21452178
context.dumpLineNumbers ? getDebugInfo(index) : null,

packages/less/src/less/tree/atrule.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ AtRule.prototype = Object.assign(new Node(), {
7777
}
7878
},
7979

80+
keywordList(rules) {
81+
if (!Array.isArray(rules)) {
82+
return false;
83+
} else {
84+
return rules.filter(function (node) { return (node.type === 'Keyword' || node.type === 'Comment'); }).length === rules.length;
85+
}
86+
},
87+
8088
accept(visitor) {
8189
const value = this.value, rules = this.rules, declarations = this.declarations;
8290

@@ -127,6 +135,9 @@ AtRule.prototype = Object.assign(new Node(), {
127135

128136
if (value) {
129137
value = value.eval(context);
138+
if (value.value && this.keywordList(value.value)) {
139+
value = new Anonymous(value.value.map(keyword => keyword.value).join(', '), this.getIndex(), this.fileInfo());
140+
}
130141
}
131142

132143
if (rules) {
@@ -143,7 +154,7 @@ AtRule.prototype = Object.assign(new Node(), {
143154
}
144155
if (this.simpleBlock && rules) {
145156
rules[0].functionRegistry = context.frames[0].functionRegistry.inherit();
146-
rules= rules.map(function (rule) { return rule.eval(context); });
157+
rules = rules.map(function (rule) { return rule.eval(context); });
147158
}
148159

149160
// restore media bubbling information
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
@layer {
2+
.main::before {
3+
color: #f00;
4+
}
5+
}
6+
@layer legacy {
7+
.sub-rule ul {
8+
color: white;
9+
}
10+
}
11+
@layer primevue {
12+
.test {
13+
foo: bar;
14+
}
15+
}
16+
@layer reset, base, components, utilities;
17+
@layer reset {
18+
*,
19+
*::before,
20+
*::after {
21+
box-sizing: border-box;
22+
}
23+
}
24+
@layer base {
25+
body {
26+
margin: 0;
27+
font-family: system-ui, sans-serif;
28+
}
29+
body header {
30+
background-color: #f0f0f0;
31+
padding: 1rem;
32+
}
33+
}
34+
@layer components {
35+
.button {
36+
display: inline-block;
37+
padding: 0.5rem 1rem;
38+
background-color: blue;
39+
color: white;
40+
}
41+
.button:hover {
42+
background-color: darkblue;
43+
}
44+
}
45+
@layer utilities {
46+
.text-center {
47+
text-align: center;
48+
}
49+
.responsive {
50+
width: 100%;
51+
}
52+
@media (min-width: 768px) {
53+
.responsive {
54+
width: 50%;
55+
}
56+
}
57+
}
58+
.parent {
59+
color: black;
60+
}
61+
.parent .child {
62+
color: red;
63+
}
64+
.parent:hover {
65+
background: lightgray;
66+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.sub-rule {
2+
ul {
3+
color: white;
4+
}
5+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
.main {
2+
@layer {
3+
&::before {
4+
color: #f00;
5+
}
6+
}
7+
}
8+
9+
@layer legacy {
10+
@import "./import/layer-import.less";
11+
}
12+
13+
@layer-name: primevue;
14+
15+
@layer @layer-name {
16+
.test {
17+
foo: bar;
18+
}
19+
}
20+
21+
@layer reset, base, components, utilities;
22+
23+
@layer reset {
24+
25+
*,
26+
*::before,
27+
*::after {
28+
box-sizing: border-box;
29+
}
30+
}
31+
32+
@layer base {
33+
body {
34+
margin: 0;
35+
font-family: system-ui, sans-serif;
36+
37+
header {
38+
background-color: #f0f0f0;
39+
padding: 1rem;
40+
}
41+
}
42+
}
43+
44+
@layer components {
45+
.button {
46+
display: inline-block;
47+
padding: 0.5rem 1rem;
48+
background-color: blue;
49+
color: white;
50+
51+
&:hover {
52+
background-color: darkblue;
53+
}
54+
}
55+
}
56+
57+
@layer utilities {
58+
.text-center {
59+
text-align: center;
60+
}
61+
62+
.responsive {
63+
width: 100%;
64+
65+
@media (min-width: 768px) {
66+
width: 50%;
67+
}
68+
}
69+
}
70+
71+
.parent {
72+
color: black;
73+
74+
.child {
75+
color: red;
76+
}
77+
78+
&:hover {
79+
background: lightgray;
80+
}
81+
}

0 commit comments

Comments
 (0)