Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions src/rules/color-contrast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Rule: Check the color contrast any time background color and foreground color are set
*/

CSSLint.addRule({

// rule information
id: "color-contrast",
name: "Check color contast",
desc: "Checks color contrast when background color and foreground color are set",
browsers: "All",

// initialization
init: function(parser, reporter) {
"use strict";
var rule = this,
bgColorDef,
colorDef;


function startRule(event) {
bgColorDef = false;
colorDef = false;
rule.col = event.col;
rule.line = event.line;
}

// event handler for end of rule
function endRule() {
var BRIGHTNESS = 126,
HUE = 501,
brightness,
hue;

// calculate the brightness of a color
function calcBrightness(cd) {
var value = (299 * cd.red) + (587 * cd.green) + (114 * cd.blue);

value = value / 1000;

return value;
}

function calcHue(fg, bg) {
var value = Math.abs(fg.red - bg.red) +
Math.abs(fg.green - bg.green) +
Math.abs(fg.blue - bg.blue);

return value;
}

if (bgColorDef && colorDef) {
// calculate the contrast
brightness = Math.abs(calcBrightness(bgColorDef) - calcBrightness(colorDef));
hue = calcHue(colorDef, bgColorDef);

if (brightness < BRIGHTNESS || hue < HUE) {
reporter.report("There is not enough contrast between background and foreground colors.", rule.line, rule.col, rule);
}
}
}

parser.addListener("startrule", startRule);
parser.addListener("startfontface", startRule);

// check for use of "background" with color, "background-color", and "color"
parser.addListener("property", function(event) {
var name = event.property.toString().toLowerCase(),
parts = event.value.parts;

// get the color values used
function getColor() {
var ndx = parts.length - 1,
color;

// if value is type 'color', red, green, and blue are also set
while (ndx > -1 && !color) {
if (parts[ndx].type === "color") {
color = { red: parts[ndx].red, green: parts[ndx].green, blue: parts[ndx].blue };
}
ndx -= 1;
}

return color;
}

if (name === "background-color") {
bgColorDef = getColor();
} else if (name === "background") {
bgColorDef = getColor();
} else if (name === "color") {
colorDef = getColor();
}
});

parser.addListener("endrule", endRule);
parser.addListener("endfontface", endRule);

}

});
38 changes: 38 additions & 0 deletions tests/rules/color-contrast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(function() {
"use strict";
var Assert = YUITest.Assert;

YUITest.TestRunner.add(new YUITest.TestCase({

name: "color-contrast rule errors",

"background specified without enough color contrast should result in a warning": function() {
var result = CSSLint.verify(".foo{background: #fff url('smiley.gif') no-repeat fixed center; color: #c8c8c8;}", { "color-contrast": 1 });

Assert.areEqual(1, result.messages.length);
Assert.areEqual("warning", result.messages[0].type);
Assert.areEqual("There is not enough contrast between background and foreground colors.", result.messages[0].message);
},

"background-color without enough color contrast should result in a warning": function() {
var result = CSSLint.verify(".foo{background-color: rgb(255, 255, 255); color: rgb(200, 200, 200);}", { "color-contrast": 1 });

Assert.areEqual(1, result.messages.length);
Assert.areEqual("warning", result.messages[0].type);
Assert.areEqual("There is not enough contrast between background and foreground colors.", result.messages[0].message);
},

"background with enough color contrast should not result in a warning": function() {
var result = CSSLint.verify(".foo{background: #fff url('smiley.gif') no-repeat fixed center; color: #000;}", { "background-color": 1 });

Assert.areEqual(0, result.messages.length);
},

"background-color with enough color contrast should not result in a warning": function() {
var result = CSSLint.verify(".foo{background-color: #fff; color: #000;}", { "background-color": 1 });

Assert.areEqual(0, result.messages.length);
}
}));

})();