Skip to content

Commit ad0cbdb

Browse files
authored
fix: make no-invalid-properties var() case-insensitive (#232)
* fix: make no-invalid-properties var() case-insensitive * add case-sensitivity tests for variables * include an additional test
1 parent 74409ed commit ad0cbdb

File tree

2 files changed

+212
-4
lines changed

2 files changed

+212
-4
lines changed

src/rules/no-invalid-properties.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function getVarFallbackList(value) {
3737

3838
while (true) {
3939
const match = currentValue.match(
40-
/var\(\s*(--[^,\s)]+)\s*(?:,\s*(.+))?\)/u,
40+
/var\(\s*(--[^,\s)]+)\s*(?:,\s*(.+))?\)/iu,
4141
);
4242

4343
if (!match) {
@@ -54,7 +54,7 @@ function getVarFallbackList(value) {
5454
}
5555

5656
// If fallback is not another var(), we're done
57-
if (!fallback.includes("var(")) {
57+
if (!fallback.toLowerCase().includes("var(")) {
5858
list.push(fallback);
5959
break;
6060
}
@@ -129,7 +129,7 @@ export default {
129129
replacements.push(new Map());
130130
},
131131

132-
"Function[name=var]"(node) {
132+
"Function[name=/^var$/i]"(node) {
133133
const map = replacements.at(-1);
134134
if (!map) {
135135
return;
@@ -166,7 +166,10 @@ export default {
166166
// When `var()` is used, we store all the values to `valueList` with the replacement of `var()` with there values or fallback values
167167
for (const child of valueNodes) {
168168
// If value is a function starts with `var()`
169-
if (child.type === "Function" && child.name === "var") {
169+
if (
170+
child.type === "Function" &&
171+
child.name.toLowerCase() === "var"
172+
) {
170173
const varValue = vars.get(child.children[0].name);
171174

172175
// If the variable is found, use its value, otherwise check for fallback values

tests/rules/no-invalid-properties.test.js

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,29 @@ ruleTester.run("no-invalid-properties", rule, {
5555
":root { --my-color: red; }\na { color: var(--my-color, var(--fallback-color, var(--foo, var(--bar)))) }",
5656
":root { --my-color: red; }\na { color: var(--my-color, var(--fallback-color, var(--foo, var(--bar, blue)))) }",
5757
":root { --color: red }\na { border-top: 1px var(--style, var(--fallback, solid)) var(--color, blue); }",
58+
"a { color: VAR(--my-color, red) }",
59+
":root { --my-heading: 3rem; }\na { color: vAr(--my-color, red) }",
60+
":root { --my-heading: 3rem; --foo: red }\na { color: VAR(--my-color, VAR(--foo, blue)) }",
61+
":root { --my-heading: 3rem; }\na { color: VAR(--my-color, vAr(--foo, blue)) }",
62+
"a { color: vAR(--my-color, VaR(--foo, VAR(--bar, blue))) }",
63+
":root { --my-color: red; }\na { color: Var(--my-color, blue) }",
64+
":root { --my-fallback: red; }\na { color: var(--my-color, VAR(--my-fallback)) }",
65+
":root { --my-fallback: red; }\na { color: VAR(--my-color, var(--my-fallback, blue)) }",
66+
":root { --foo: red; }\na { color: vAr(--my-color, VAR(--my-fallback, VaR(--foo))) }",
67+
"a { color: VAR(--my-color, vAr(--my-fallback, VAR(--foo, blue))) }",
68+
":root { --my-color: red; }\na { color: Var(--my-color, VAR(--fallback-color)) }",
69+
":root { --my-color: red; --fallback-color: blue; }\na { color: VAR(--my-color, var(--fallback-color)) }",
70+
":root { --my-color: red; }\na { color: var(--my-color, VaR(--fallback-color, blue)) }",
71+
":root { --my-color: red; }\na { color: VAR(--my-color, vAr(--fallback-color, VAR(--foo))) }",
72+
":root { --my-color: red; }\na { color: vAr(--my-color, VAR(--fallback-color, var(--foo, blue))) }",
73+
":root { --my-color: red; }\na { color: VAR(--my-color, vAr(--fallback-color, VAR(--foo, var(--bar)))) }",
74+
":root { --my-color: red; }\na { color: vAr(--my-color, VAR(--fallback-color, var(--foo, VaR(--bar, blue)))) }",
75+
":root { --color: red }\na { border-top: 1px VAR(--style, vAr(--fallback, solid)) VaR(--color, blue); }",
76+
":root { --MY-COLOR: red; }\na { color: var(--MY-COLOR) }",
77+
":root { --my-color: red; }\na { color: var(--MY-COLOR, red) }",
78+
":root { --MY-COLOR: red; }\na { color: var(--my-color, blue) }",
79+
":root { --FALLBACK-COLOR: blue; }\na { color: var(--MY-COLOR, var(--FALLBACK-COLOR)) }",
80+
":root { --fallback-color: blue; }\na { color: VAR(--MY-COLOR, VaR(--fallback-color)) }",
5881
{
5982
code: "a { my-custom-color: red; }",
6083
languageOptions: {
@@ -69,6 +92,10 @@ ruleTester.run("no-invalid-properties", rule, {
6992
code: "a { color: var(--my-color); }",
7093
options: [{ allowUnknownVariables: true }],
7194
},
95+
{
96+
code: "a { color: VAR(--my-color); }",
97+
options: [{ allowUnknownVariables: true }],
98+
},
7299
{
73100
code: "a { --my-color: red; color: var(--my-color); background-color: var(--unknown-var); }",
74101
options: [{ allowUnknownVariables: true }],
@@ -77,6 +104,10 @@ ruleTester.run("no-invalid-properties", rule, {
77104
code: ":root { --color: red }\na { border-top: 1px var(--style, var(--fallback)) var(--color, blue); }",
78105
options: [{ allowUnknownVariables: true }],
79106
},
107+
{
108+
code: ":root { --color: red }\na { border-top: 1px VAR(--style, VAR(--fallback)) VAR(--color, blue); }",
109+
options: [{ allowUnknownVariables: true }],
110+
},
80111

81112
/*
82113
* CSSTree doesn't currently support custom functions properly, so leaving
@@ -295,6 +326,36 @@ ruleTester.run("no-invalid-properties", rule, {
295326
},
296327
],
297328
},
329+
{
330+
code: "a { color: var(--MY-COLOR); }",
331+
errors: [
332+
{
333+
messageId: "unknownVar",
334+
data: {
335+
var: "--MY-COLOR",
336+
},
337+
line: 1,
338+
column: 16,
339+
endLine: 1,
340+
endColumn: 26,
341+
},
342+
],
343+
},
344+
{
345+
code: "a { --my-color: red; color: var(--MY-COLOR); }",
346+
errors: [
347+
{
348+
messageId: "unknownVar",
349+
data: {
350+
var: "--MY-COLOR",
351+
},
352+
line: 1,
353+
column: 33,
354+
endLine: 1,
355+
endColumn: 43,
356+
},
357+
],
358+
},
298359
{
299360
code: "a { .foo { color: var(--undefined-var); } }",
300361
errors: [
@@ -310,6 +371,21 @@ ruleTester.run("no-invalid-properties", rule, {
310371
},
311372
],
312373
},
374+
{
375+
code: "a { color: var(--MY-COLOR, var(--FALLBACK-COLOR)); }",
376+
errors: [
377+
{
378+
messageId: "unknownVar",
379+
data: {
380+
var: "--MY-COLOR",
381+
},
382+
line: 1,
383+
column: 16,
384+
endLine: 1,
385+
endColumn: 26,
386+
},
387+
],
388+
},
313389
{
314390
code: "a { --my-color: 10px; color: var(--my-color); }",
315391
errors: [
@@ -592,5 +668,134 @@ ruleTester.run("no-invalid-properties", rule, {
592668
},
593669
],
594670
},
671+
{
672+
code: "a { color: VAR(--my-color); }",
673+
errors: [
674+
{
675+
messageId: "unknownVar",
676+
data: {
677+
var: "--my-color",
678+
},
679+
line: 1,
680+
column: 16,
681+
endLine: 1,
682+
endColumn: 26,
683+
},
684+
],
685+
},
686+
{
687+
code: "a { border-top: 1px vAr(--style, solid) VaR(--color); }",
688+
errors: [
689+
{
690+
messageId: "unknownVar",
691+
data: {
692+
var: "--color",
693+
},
694+
line: 1,
695+
column: 45,
696+
endLine: 1,
697+
endColumn: 52,
698+
},
699+
],
700+
},
701+
{
702+
code: ":root { --style: foo }\na { border-top: 1px VAR(--style) VAR(--color, red); }",
703+
errors: [
704+
{
705+
messageId: "invalidPropertyValue",
706+
data: {
707+
property: "border-top",
708+
value: "foo",
709+
expected: "<line-width> || <line-style> || <color>",
710+
},
711+
line: 2,
712+
column: 21,
713+
endLine: 2,
714+
endColumn: 33,
715+
},
716+
],
717+
},
718+
{
719+
code: ":root { --style: foo }\na { border-top: 1px VAR(--style, solid) VAR(--color, red); }",
720+
errors: [
721+
{
722+
messageId: "invalidPropertyValue",
723+
data: {
724+
property: "border-top",
725+
value: "foo",
726+
expected: "<line-width> || <line-style> || <color>",
727+
},
728+
line: 2,
729+
column: 21,
730+
endLine: 2,
731+
endColumn: 40,
732+
},
733+
],
734+
},
735+
{
736+
code: ":root { --color: foo }\na { border-top: 1px VAR(--style, VAR(--fallback, solid)) VAR(--color); }",
737+
errors: [
738+
{
739+
messageId: "invalidPropertyValue",
740+
data: {
741+
property: "border-top",
742+
value: "foo",
743+
expected: "<line-width> || <line-style> || <color>",
744+
},
745+
line: 2,
746+
column: 58,
747+
endLine: 2,
748+
endColumn: 70,
749+
},
750+
],
751+
},
752+
{
753+
code: ":root { --color: foo }\na { border-top: 1px VAR(--style, VAR(--fallback)) VAR(--color); }",
754+
options: [{ allowUnknownVariables: true }],
755+
errors: [
756+
{
757+
messageId: "invalidPropertyValue",
758+
data: {
759+
property: "border-top",
760+
value: "foo",
761+
expected: "<line-width> || <line-style> || <color>",
762+
},
763+
line: 2,
764+
column: 51,
765+
endLine: 2,
766+
endColumn: 63,
767+
},
768+
],
769+
},
770+
{
771+
code: ":root { --color: foo }\na { border-top: 1px VAR(--style, VAR(--fallback)) VAR(--color); }",
772+
errors: [
773+
{
774+
messageId: "unknownVar",
775+
data: {
776+
var: "--style",
777+
},
778+
line: 2,
779+
column: 25,
780+
endLine: 2,
781+
endColumn: 32,
782+
},
783+
],
784+
},
785+
{
786+
code: ":root { --color: red }\na { colorr: VAR(--color, blue); }",
787+
errors: [
788+
{
789+
messageId: "unknownProperty",
790+
data: {
791+
property: "colorr",
792+
},
793+
line: 2,
794+
column: 5,
795+
endLine: 2,
796+
endColumn: 11,
797+
},
798+
],
799+
},
595800
],
596801
});

0 commit comments

Comments
 (0)