Skip to content

Commit 9765135

Browse files
authored
fix: treat at-rule names as case-insensitive across rules (#233)
1 parent 751b3ed commit 9765135

File tree

8 files changed

+337
-12
lines changed

8 files changed

+337
-12
lines changed

src/rules/no-duplicate-imports.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default {
4242
const imports = new Set();
4343

4444
return {
45-
"Atrule[name=import]"(node) {
45+
"Atrule[name=/^import$/i]"(node) {
4646
const url = node.prelude.children[0].value;
4747

4848
if (imports.has(url)) {

src/rules/no-duplicate-keyframe-selectors.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ export default {
3939
const seen = new Map();
4040

4141
return {
42-
"Atrule[name=keyframes]"() {
42+
"Atrule[name=/^keyframes$/i]"() {
4343
insideKeyframes = true;
4444
seen.clear();
4545
},
4646

47-
"Atrule[name=keyframes]:exit"() {
47+
"Atrule[name=/^keyframes$/i]:exit"() {
4848
insideKeyframes = false;
4949
},
5050

src/rules/use-baseline.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -527,11 +527,11 @@ export default {
527527
}
528528

529529
return {
530-
"Atrule[name=supports]"() {
530+
"Atrule[name=/^supports$/i]"() {
531531
supportsRules.push(new SupportsRule());
532532
},
533533

534-
"Atrule[name=supports] > AtrulePrelude > Condition"(node) {
534+
"Atrule[name=/^supports$/i] > AtrulePrelude > Condition"(node) {
535535
const supportsRule = supportsRules.last();
536536

537537
for (let i = 0; i < node.children.length; i++) {
@@ -667,11 +667,11 @@ export default {
667667
}
668668
},
669669

670-
"Atrule[name=supports]:exit"() {
670+
"Atrule[name=/^supports$/i]:exit"() {
671671
supportsRules.pop();
672672
},
673673

674-
"Atrule[name=media] > AtrulePrelude > MediaQueryList > MediaQuery > Condition"(
674+
"Atrule[name=/^media$/i] > AtrulePrelude > MediaQueryList > MediaQuery > Condition"(
675675
node,
676676
) {
677677
for (const child of node.children) {
@@ -719,11 +719,12 @@ export default {
719719

720720
Atrule(node) {
721721
// ignore unknown at-rules - no-invalid-at-rules already catches this
722-
if (!atRules.has(node.name)) {
722+
const atRuleName = node.name.toLowerCase();
723+
if (!atRules.has(atRuleName)) {
723724
return;
724725
}
725726

726-
const featureStatus = atRules.get(node.name);
727+
const featureStatus = atRules.get(atRuleName);
727728

728729
if (!baselineAvailability.isSupported(featureStatus)) {
729730
const loc = node.loc;

src/rules/use-layers.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export default {
7575
: null;
7676

7777
return {
78-
"Atrule[name=import]"(node) {
78+
"Atrule[name=/^import$/i]"(node) {
7979
// layer, if present, must always be the second child of the prelude
8080
const secondChild = node.prelude.children[1];
8181
const layerNode =
@@ -140,7 +140,7 @@ export default {
140140
});
141141
},
142142

143-
"Atrule[name=layer]"(node) {
143+
"Atrule[name=/^layer$/i]"(node) {
144144
layerDepth++;
145145

146146
if (!options.allowUnnamedLayers && !node.prelude) {
@@ -151,7 +151,7 @@ export default {
151151
}
152152
},
153153

154-
"Atrule[name=layer]:exit"() {
154+
"Atrule[name=/^layer$/i]:exit"() {
155155
layerDepth--;
156156
},
157157

tests/rules/no-duplicate-imports.test.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ ruleTester.run("no-duplicate-imports", rule, {
2727
"@import url('x.css');",
2828
"@import url('x.css'); @import url('y.css');",
2929
"@import 'x.css'; @import url('y.css'); @import 'z.css';",
30+
"@IMPORT url('x.css');",
31+
"@imPort url('x.css'); @IMport url('y.css');",
32+
"@IMPORT 'x.css'; @import url('y.css'); @IMport 'z.css';",
3033
],
3134
invalid: [
3235
{
@@ -157,5 +160,83 @@ ruleTester.run("no-duplicate-imports", rule, {
157160
},
158161
],
159162
},
163+
{
164+
code: "@IMPORT url('x.css');\n@IMPORT url('x.css');",
165+
output: "@IMPORT url('x.css');\n",
166+
errors: [
167+
{
168+
messageId: "duplicateImport",
169+
data: { url: "x.css" },
170+
line: 2,
171+
column: 1,
172+
endLine: 2,
173+
endColumn: 22,
174+
},
175+
],
176+
},
177+
{
178+
code: "@IMport url('x.css');@IMPORT url('x.css');",
179+
output: "@IMport url('x.css');",
180+
errors: [
181+
{
182+
messageId: "duplicateImport",
183+
data: { url: "x.css" },
184+
line: 1,
185+
column: 22,
186+
endLine: 1,
187+
endColumn: 43,
188+
},
189+
],
190+
},
191+
{
192+
code: "@IMPORT url('x.css');@IMPORT url('x.css');@IMPORT url('y.css')",
193+
output: "@IMPORT url('x.css');@IMPORT url('y.css')",
194+
errors: [
195+
{
196+
messageId: "duplicateImport",
197+
data: { url: "x.css" },
198+
line: 1,
199+
column: 22,
200+
endLine: 1,
201+
endColumn: 43,
202+
},
203+
],
204+
},
205+
{
206+
code: "@IMPORT url('x.css');\n@IMPORT 'x.css';\n@IMPORT 'x.css';",
207+
output: "@IMPORT url('x.css');\n@IMPORT 'x.css';",
208+
errors: [
209+
{
210+
messageId: "duplicateImport",
211+
data: { url: "x.css" },
212+
line: 2,
213+
column: 1,
214+
endLine: 2,
215+
endColumn: 17,
216+
},
217+
{
218+
messageId: "duplicateImport",
219+
data: { url: "x.css" },
220+
line: 3,
221+
column: 1,
222+
endLine: 3,
223+
endColumn: 17,
224+
},
225+
],
226+
},
227+
{
228+
code: "@IMPORT url('a.css');\n@import url('b.css');\n@IMPORT url('c.css');\n@import url('a.css');\n@IMPORT url('d.css');",
229+
output: "@IMPORT url('a.css');\n@import url('b.css');\n@IMPORT url('c.css');\n@IMPORT url('d.css');",
230+
errors: [
231+
{
232+
messageId: "duplicateImport",
233+
data: { url: "a.css" },
234+
line: 4,
235+
column: 1,
236+
endLine: 4,
237+
endColumn: 22,
238+
},
239+
],
240+
},
160241
],
161242
});

tests/rules/no-duplicate-keyframe-selectors.test.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, {
5151
dedent`@keyframes test {
5252
0% { opacity: 0; }
5353
0.0% { opacity: 1; }
54+
}`,
55+
dedent`@KEYFRAMES test {
56+
from { opacity: 0; }
57+
to { opacity: 1; }
58+
}`,
59+
dedent`@KeYFrames test {
60+
0% { opacity: 0; }
61+
100% { opacity: 1; }
62+
}`,
63+
dedent`@Keyframes test {
64+
from { opacity: 0; }
65+
50% { opacity: 0.5; }
66+
to { opacity: 1; }
5467
}`,
5568
],
5669
invalid: [
@@ -245,5 +258,67 @@ ruleTester.run("no-duplicate-keyframe-selectors", rule, {
245258
},
246259
],
247260
},
261+
{
262+
code: dedent`@KEYFRAMES test {
263+
0% { opacity: 0; }
264+
0% { opacity: 1; }
265+
}`,
266+
errors: [
267+
{
268+
messageId: "duplicateKeyframeSelector",
269+
line: 3,
270+
column: 5,
271+
endLine: 3,
272+
endColumn: 7,
273+
},
274+
],
275+
},
276+
{
277+
code: dedent`@Keyframes test {
278+
0% {
279+
opacity: 0;
280+
}
281+
282+
0% {
283+
opacity: 1;
284+
}
285+
286+
50% {
287+
opacity: 0.5;
288+
}
289+
290+
50% {
291+
opacity: 0.75;
292+
}
293+
294+
50% {
295+
opacity: 0.5;
296+
}
297+
298+
}`,
299+
errors: [
300+
{
301+
messageId: "duplicateKeyframeSelector",
302+
line: 6,
303+
column: 5,
304+
endLine: 6,
305+
endColumn: 7,
306+
},
307+
{
308+
messageId: "duplicateKeyframeSelector",
309+
line: 14,
310+
column: 5,
311+
endLine: 14,
312+
endColumn: 8,
313+
},
314+
{
315+
messageId: "duplicateKeyframeSelector",
316+
line: 18,
317+
column: 5,
318+
endLine: 18,
319+
endColumn: 8,
320+
},
321+
],
322+
},
248323
],
249324
});

0 commit comments

Comments
 (0)