Skip to content

Commit 663702f

Browse files
author
Nicholas C. Zakas
committed
Created rule to check for fallback colors when CSS3 colors are in use (fixes #207)
1 parent 5cdcc15 commit 663702f

2 files changed

Lines changed: 229 additions & 0 deletions

File tree

src/rules/fallback-colors.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
/*global CSSLint*/
3+
CSSLint.addRule({
4+
5+
//rule information
6+
id: "fallback-colors",
7+
name: "Require fallback colors",
8+
desc: "For older browsers that don't support RGBA, HSL, or HSLA, provide a fallback color.",
9+
browsers: "IE6,IE7,IE8",
10+
11+
//initialization
12+
init: function(parser, reporter){
13+
var rule = this,
14+
lastProperty,
15+
propertiesToCheck = {
16+
color: 1,
17+
background: 1,
18+
"background-color": 1
19+
},
20+
properties;
21+
22+
function startRule(event){
23+
properties = {};
24+
lastProperty = null;
25+
}
26+
27+
parser.addListener("startrule", startRule);
28+
parser.addListener("startfontface", startRule);
29+
parser.addListener("startpage", startRule);
30+
parser.addListener("startpagemargin", startRule);
31+
parser.addListener("startkeyframerule", startRule);
32+
33+
parser.addListener("property", function(event){
34+
var property = event.property,
35+
name = property.text.toLowerCase(),
36+
parts = event.value.parts,
37+
i = 0,
38+
colorType = "",
39+
len = parts.length;
40+
41+
if(propertiesToCheck[name]){
42+
while(i < len){
43+
if (parts[i].type == "color"){
44+
if ("alpha" in parts[i] || "hue" in parts[i]){
45+
46+
if (/([^\)]+)\(/.test(parts[i])){
47+
colorType = RegExp.$1.toUpperCase();
48+
}
49+
50+
if (!lastProperty || (lastProperty.property.text.toLowerCase() != name || lastProperty.colorType != "compat")){
51+
reporter.report("Fallback " + name + " (hex or RGB) should precede " + colorType + " " + name + ".", event.line, event.col, rule);
52+
}
53+
} else {
54+
event.colorType = "compat";
55+
}
56+
}
57+
58+
i++;
59+
}
60+
}
61+
62+
lastProperty = event;
63+
});
64+
65+
}
66+
67+
});

tests/rules/fallback-colors.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
(function(){
2+
3+
/*global YUITest, CSSLint*/
4+
var Assert = YUITest.Assert;
5+
6+
YUITest.TestRunner.add(new YUITest.TestCase({
7+
8+
name: "Fallback Colors Rule Errors",
9+
10+
"Using only a named color should not result in a warning": function(){
11+
var result = CSSLint.verify(".hex { color: red; }", { "fallback-colors": 1 });
12+
Assert.areEqual(0, result.messages.length);
13+
},
14+
15+
"Using only a hex color should not result in a warning": function(){
16+
var result = CSSLint.verify(".hex { color: #fff; }", { "fallback-colors": 1 });
17+
Assert.areEqual(0, result.messages.length);
18+
},
19+
20+
"Using only rgb() should not result in a warning": function(){
21+
var result = CSSLint.verify(".rgb { color: rgb(0, 0, 0); }", { "fallback-colors": 1 });
22+
Assert.areEqual(0, result.messages.length);
23+
},
24+
25+
"Using only rgba() should result in a warning": function(){
26+
var result = CSSLint.verify(".rgba { color: rgba(0, 0, 0, 0.5); }", { "fallback-colors": 1 });
27+
Assert.areEqual(1, result.messages.length);
28+
Assert.areEqual("warning", result.messages[0].type);
29+
Assert.areEqual("Fallback color (hex or RGB) should precede RGBA color.", result.messages[0].message);
30+
},
31+
32+
"Using only hsl() should result in a warning": function(){
33+
var result = CSSLint.verify(".hsl { color: hsl(0, 0%, 0%); }", { "fallback-colors": 1 });
34+
Assert.areEqual(1, result.messages.length);
35+
Assert.areEqual("warning", result.messages[0].type);
36+
Assert.areEqual("Fallback color (hex or RGB) should precede HSL color.", result.messages[0].message);
37+
},
38+
39+
"Using only hsla() should result in a warning": function(){
40+
var result = CSSLint.verify(".hsla { color: hsla(0, 0%, 0%, 0.5); }", { "fallback-colors": 1 });
41+
Assert.areEqual(1, result.messages.length);
42+
Assert.areEqual("warning", result.messages[0].type);
43+
Assert.areEqual("Fallback color (hex or RGB) should precede HSLA color.", result.messages[0].message);
44+
},
45+
46+
"Using rgba() with a fallback should not result in a warning": function(){
47+
var result = CSSLint.verify(".rgba { color: #fff; color: rgba(0, 0, 0, 0.5); }", { "fallback-colors": 1 });
48+
Assert.areEqual(0, result.messages.length);
49+
},
50+
51+
"Using hsl() with a fallback should not result in a warning": function(){
52+
var result = CSSLint.verify(".hsl { color: #fff; color: hsl(0, 0%, 0%); }", { "fallback-colors": 1 });
53+
Assert.areEqual(0, result.messages.length);
54+
},
55+
56+
"Using hsla() with a fallback should not result in a warning": function(){
57+
var result = CSSLint.verify(".hsla { color: #fff; color: hsla(0, 0%, 0%, 0.5); }", { "fallback-colors": 1 });
58+
Assert.areEqual(0, result.messages.length);
59+
},
60+
61+
"Using rgba() with fallback color afterwards should result in a warning": function(){
62+
var result = CSSLint.verify(".rgba { color: rgba(0, 0, 0, 0.5); color: #fff; }", { "fallback-colors": 1 });
63+
Assert.areEqual(1, result.messages.length);
64+
Assert.areEqual("warning", result.messages[0].type);
65+
Assert.areEqual("Fallback color (hex or RGB) should precede RGBA color.", result.messages[0].message);
66+
},
67+
68+
"Using hsl() with fallback color afterwards should result in a warning": function(){
69+
var result = CSSLint.verify(".hsl { color: hsl(0, 0%, 0%); color: #fff; }", { "fallback-colors": 1 });
70+
Assert.areEqual(1, result.messages.length);
71+
Assert.areEqual("warning", result.messages[0].type);
72+
Assert.areEqual("Fallback color (hex or RGB) should precede HSL color.", result.messages[0].message);
73+
},
74+
75+
"Using hsla() with fallback color afterwards should result in a warning": function(){
76+
var result = CSSLint.verify(".hsla { color: hsla(0, 0%, 0%, 0.5); color: #fff; }", { "fallback-colors": 1 });
77+
Assert.areEqual(1, result.messages.length);
78+
Assert.areEqual("warning", result.messages[0].type);
79+
Assert.areEqual("Fallback color (hex or RGB) should precede HSLA color.", result.messages[0].message);
80+
},
81+
82+
83+
"Using only a named background-color should not result in a warning": function(){
84+
var result = CSSLint.verify(".hex { background-color: red; }", { "fallback-colors": 1 });
85+
Assert.areEqual(0, result.messages.length);
86+
},
87+
88+
"Using only a hex background-color should not result in a warning": function(){
89+
var result = CSSLint.verify(".hex { background-color: #fff; }", { "fallback-colors": 1 });
90+
Assert.areEqual(0, result.messages.length);
91+
},
92+
93+
"Using only rgb() background-color should not result in a warning": function(){
94+
var result = CSSLint.verify(".rgb { background-color: rgb(0, 0, 0); }", { "fallback-colors": 1 });
95+
Assert.areEqual(0, result.messages.length);
96+
},
97+
98+
"Using only rgba() background-color should result in a warning": function(){
99+
var result = CSSLint.verify(".rgba { background-color: rgba(0, 0, 0, 0.5); }", { "fallback-colors": 1 });
100+
Assert.areEqual(1, result.messages.length);
101+
Assert.areEqual("warning", result.messages[0].type);
102+
Assert.areEqual("Fallback background-color (hex or RGB) should precede RGBA background-color.", result.messages[0].message);
103+
},
104+
105+
"Using only hsl() background-color should result in a warning": function(){
106+
var result = CSSLint.verify(".hsl { background-color: hsl(0, 0%, 0%); }", { "fallback-colors": 1 });
107+
Assert.areEqual(1, result.messages.length);
108+
Assert.areEqual("warning", result.messages[0].type);
109+
Assert.areEqual("Fallback background-color (hex or RGB) should precede HSL background-color.", result.messages[0].message);
110+
},
111+
112+
"Using only hsla() background-color should result in a warning": function(){
113+
var result = CSSLint.verify(".hsla { background-color: hsla(0, 0%, 0%, 0.5); }", { "fallback-colors": 1 });
114+
Assert.areEqual(1, result.messages.length);
115+
Assert.areEqual("warning", result.messages[0].type);
116+
Assert.areEqual("Fallback background-color (hex or RGB) should precede HSLA background-color.", result.messages[0].message);
117+
},
118+
119+
"Using rgba() with a fallback background-color should not result in a warning": function(){
120+
var result = CSSLint.verify(".rgba { background-color: #fff; background-color: rgba(0, 0, 0, 0.5); }", { "fallback-colors": 1 });
121+
Assert.areEqual(0, result.messages.length);
122+
},
123+
124+
"Using hsl() with a fallback background-color should not result in a warning": function(){
125+
var result = CSSLint.verify(".hsl { background-color: #fff; background-color: hsl(0, 0%, 0%); }", { "fallback-colors": 1 });
126+
Assert.areEqual(0, result.messages.length);
127+
},
128+
129+
"Using hsla() with a fallback background-color should not result in a warning": function(){
130+
var result = CSSLint.verify(".hsla { background-color: #fff; background-color: hsla(0, 0%, 0%, 0.5); }", { "fallback-colors": 1 });
131+
Assert.areEqual(0, result.messages.length);
132+
},
133+
134+
"Using rgba() with fallback background-color afterwards should result in a warning": function(){
135+
var result = CSSLint.verify(".rgba { background-color: rgba(0, 0, 0, 0.5); background-color: #fff; }", { "fallback-colors": 1 });
136+
Assert.areEqual(1, result.messages.length);
137+
Assert.areEqual("warning", result.messages[0].type);
138+
Assert.areEqual("Fallback background-color (hex or RGB) should precede RGBA background-color.", result.messages[0].message);
139+
},
140+
141+
"Using hsl() with fallback background-color afterwards should result in a warning": function(){
142+
var result = CSSLint.verify(".hsl { background-color: hsl(0, 0%, 0%); background-color: #fff; }", { "fallback-colors": 1 });
143+
Assert.areEqual(1, result.messages.length);
144+
Assert.areEqual("warning", result.messages[0].type);
145+
Assert.areEqual("Fallback background-color (hex or RGB) should precede HSL background-color.", result.messages[0].message);
146+
},
147+
148+
"Using hsla() with fallback background-color afterwards should result in a warning": function(){
149+
var result = CSSLint.verify(".hsla { background-color: hsla(0, 0%, 0%, 0.5); background-color: #fff; }", { "fallback-colors": 1 });
150+
Assert.areEqual(1, result.messages.length);
151+
Assert.areEqual("warning", result.messages[0].type);
152+
Assert.areEqual("Fallback background-color (hex or RGB) should precede HSLA background-color.", result.messages[0].message);
153+
}
154+
155+
156+
157+
158+
159+
160+
}));
161+
162+
})();

0 commit comments

Comments
 (0)