color-contrast-checker
Advanced tools
Comparing version 0.1.0 to 1.0.0
{ | ||
"name": "color-contrast-checker", | ||
"version": "0.1.0", | ||
"version": "1.0.0", | ||
"description": "This is an accessibility validator based on WCAG 2.0 standard for checking the color contrast.", | ||
"main": "src/color-contrast-checker.js", | ||
"dependencies": { | ||
"amdefine": ">=0.1.0" | ||
"amdefine": ">=0.2.0" | ||
}, | ||
@@ -36,5 +36,5 @@ "directories": { | ||
"gitHead": "45b65d45fc281ba90529183ff412299a7c1379d0", | ||
"_id": "color-contrast-checker@0.1.0", | ||
"_id": "color-contrast-checker@1.0.0", | ||
"_shasum": "a43bd41523775450e6f31ce38e64b44312157325", | ||
"_from": "color-contrast-checker@0.1.0", | ||
"_from": "color-contrast-checker@1.0.0", | ||
"_npmVersion": "2.13.1", | ||
@@ -48,3 +48,3 @@ "_nodeVersion": "0.12.0", | ||
"shasum": "a43bd41523775450e6f31ce38e64b44312157325", | ||
"tarball": "http://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-0.1.0.tgz" | ||
"tarball": "http://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-1.0.0.tgz" | ||
}, | ||
@@ -57,3 +57,3 @@ "maintainers": [ | ||
], | ||
"_resolved": "http://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-0.1.0.tgz" | ||
"_resolved": "http://registry.npmjs.org/color-contrast-checker/-/color-contrast-checker-1.0.0.tgz" | ||
} |
@@ -36,3 +36,3 @@ # Color Contast Checker v0.1 | ||
if (ccc.isLevelAA(color1, color2)) { | ||
if (ccc.isLevelAA(color1, color2, 14)) { | ||
alert("Valid Level AA"); | ||
@@ -45,2 +45,77 @@ } else { | ||
Advanced Usage: | ||
-------------- | ||
You can pass pairs and get results: | ||
``` | ||
var pairs = [ | ||
{ | ||
'colorA': '#000000', | ||
'colorB': '#000000', // All should fail | ||
'fontSize': 14 | ||
}, | ||
{ | ||
'colorA': '#000000', | ||
'colorB': '#FFFFFF', //All should pass | ||
'fontSize': 14 | ||
}, | ||
{ | ||
'colorA': '#000000', | ||
'colorB': '#848484', //AAA should fail | ||
'fontSize': 14 | ||
}, | ||
{ | ||
'colorA': '#000000', | ||
'colorB': '#848484', //All should pass (because of font) | ||
'fontSize': 19 | ||
}, | ||
{ | ||
'colorA': '#000000', | ||
'colorB': '#757575', //AA should pass AAA should fail | ||
'fontSize': 14 | ||
}, | ||
{ | ||
'colorA': '#000000', | ||
'colorB': '#656565', //All should fail | ||
'fontSize': 14 | ||
} | ||
]; | ||
var results = ccc.checkPairs(pairs); | ||
``` | ||
The result will look like this: | ||
``` | ||
[ | ||
{ | ||
'WCAG_AA' : false, | ||
'WCAG_AAA': false | ||
}, | ||
{ | ||
'WCAG_AA' : true, | ||
'WCAG_AAA': true | ||
}, | ||
{ | ||
'WCAG_AA' : true, | ||
'WCAG_AAA': false | ||
}, | ||
{ | ||
'WCAG_AA' : true, | ||
'WCAG_AAA': true | ||
}, | ||
{ | ||
'WCAG_AA' : true, | ||
'WCAG_AAA': false | ||
}, | ||
{ | ||
'WCAG_AA' : false, | ||
'WCAG_AAA': false | ||
} | ||
] | ||
``` | ||
Its sweet and simple completely based on http://www.w3.org/TR/WCAG20/#contrast-ratiodef. |
@@ -11,2 +11,11 @@ if (typeof define !== 'function') { var define = require('amdefine')(module) } | ||
ColorContrastChecker.prototype = { | ||
fontSize: 14, | ||
rgbClass : { | ||
toString: function() { | ||
return '<r: ' + this.r + | ||
' g: ' + this.g + | ||
' b: ' + this.b + | ||
' >'; | ||
} | ||
}, | ||
isValidColorCode : function (hex){ | ||
@@ -16,4 +25,9 @@ var regColorcode = /^(#)?([0-9a-fA-F]{6})([0-9a-fA-F]{6})?$/; | ||
}, | ||
getRelativeLuminance : function (foreground, background){ | ||
if(!foreground || !background) | ||
check : function (colorA, colorB, fontSize){ | ||
if (typeof fontSize !== 'undefined') { | ||
this.fontSize = fontSize; | ||
} | ||
if(!colorA || !colorB) | ||
return false; | ||
@@ -24,77 +38,158 @@ | ||
var l2; /* lower value */ | ||
var contrast; | ||
var l1R, l1G, l1B, l2R, l2G, l2B; | ||
var txtSizeOp; | ||
color1 = this.removeHash(foreground); | ||
color2 = this.removeHash(background); | ||
l1R = parseInt("0x"+color1.substr(0,2), 16)/255; | ||
if (l1R <= 0.03928) { | ||
l1R = l1R/12.92; | ||
} else { | ||
l1R = Math.pow(((l1R+0.055)/1.055),2.4); | ||
if (!this.isValidColorCode(colorA)) { | ||
throw new Exception("Invalid Color :" + colorA); | ||
} | ||
l1G = parseInt("0x"+color1.substr(2,2), 16)/255; | ||
if (l1G <= 0.03928) { | ||
l1G = l1G/12.92; | ||
} else { | ||
l1G = Math.pow(((l1G+0.055)/1.055),2.4); | ||
if (!this.isValidColorCode(colorB)) { | ||
throw new Exception("Invalid Color :" + colorB); | ||
} | ||
l1B = parseInt("0x"+color1.substr(4,2), 16)/255; | ||
if (l1B <= 0.03928) { | ||
l1B = l1B/12.92; | ||
} else { | ||
l1B = Math.pow(((l1B+0.055)/1.055),2.4); | ||
color1 = this.getRGBFromHex(colorA); | ||
color2 = this.getRGBFromHex(colorB); | ||
var l1RGB = this.calculateLRGB(color1); | ||
var l2RGB = this.calculateLRGB(color2); | ||
/* where L is luminosity and is defined as */ | ||
l1 = this.calculateLuminance(l1RGB); | ||
l2 = this.calculateLuminance(l2RGB); | ||
return this.verifyContrastRatio(this.getContrastRatio(l1, l2)); | ||
}, | ||
checkPairs: function (pairs) { | ||
var results = []; | ||
for (var i in pairs) { | ||
var pair = pairs[i]; | ||
if (typeof pair.fontSize !== 'undefined') { | ||
results.push( | ||
this.check( | ||
pair.colorA, | ||
pair.colorB, | ||
pair.fontSize | ||
) | ||
); | ||
} else { | ||
results.push( | ||
this.check( | ||
pair.colorA, | ||
pair.colorB | ||
) | ||
); | ||
} | ||
} | ||
l2R = parseInt("0x"+color2.substr(0,2), 16)/255; | ||
if (l2R <= 0.03928) { | ||
l2R = l2R/12.92; | ||
} else { | ||
l2R = Math.pow(((l2R+0.055)/1.055),2.4); | ||
return results; | ||
}, | ||
calculateLuminance: function(lRGB) { | ||
return (0.2126 * lRGB.r) + (0.7152 * lRGB.g) + (0.0722 * lRGB.b); | ||
}, | ||
isLevelAA : function(colorA, colorB, fontSize) { | ||
var result = this.check(colorA, colorB, fontSize); | ||
return result.WCAG_AA; | ||
}, | ||
isLevelAAA : function(colorA, colorB, fontSize) { | ||
var result = this.check(colorA, colorB, fontSize); | ||
return result.WCAG_AAA; | ||
}, | ||
getRGBFromHex : function(color) { | ||
var rgb = Object.create(this.rgbClass), | ||
rVal, | ||
gVal, | ||
bVal; | ||
if (typeof color !== 'string') { | ||
throw new Error('must use string'); | ||
} | ||
l2G = parseInt("0x"+color2.substr(2,2), 16)/255; | ||
if (l2G <= 0.03928) { | ||
l2G = l2G/12.92; | ||
} else { | ||
l2G = Math.pow(((l2G+0.055)/1.055),2.4); | ||
rVal = parseInt(color.slice(1, 3), 16); | ||
gVal = parseInt(color.slice(3, 5), 16); | ||
bVal = parseInt(color.slice(5, 7), 16); | ||
rgb.r = rVal; | ||
rgb.g = gVal; | ||
rgb.b = bVal; | ||
return rgb; | ||
}, | ||
calculateSRGB : function(rgb) { | ||
var sRGB = Object.create(this.rgbClass), | ||
key; | ||
for (key in rgb) { | ||
if (rgb.hasOwnProperty(key)) { | ||
sRGB[key] = parseFloat((rgb[key] / 255), 10); | ||
} | ||
} | ||
l2B = parseInt("0x"+color2.substr(4,2), 16)/255; | ||
if (l2B <= 0.03928) { | ||
l2B = l2B/12.92; | ||
return sRGB; | ||
}, | ||
calculateLRGB: function (rgb) { | ||
var sRGB = this.calculateSRGB(rgb); | ||
var lRGB = Object.create(this.rgbClass), | ||
key, | ||
val = 0; | ||
for (key in sRGB) { | ||
if (sRGB.hasOwnProperty(key)) { | ||
val = parseFloat(sRGB[key], 10); | ||
if (val <= 0.03928) { | ||
lRGB[key] = (val / 12.92); | ||
} else { | ||
lRGB[key] = Math.pow(((val + 0.055) / 1.055), 2.4); | ||
} | ||
} | ||
} | ||
return lRGB; | ||
}, | ||
getContrastRatio : function(lumA, lumB) { | ||
var ratio, | ||
lighter, | ||
darker; | ||
if (lumA >= lumB) { | ||
lighter = lumA; | ||
darker = lumB; | ||
} else { | ||
l2B = Math.pow(((l2B+0.055)/1.055),2.4); | ||
lighter = lumB; | ||
darker = lumA; | ||
} | ||
/* where L is luminosity and is defined as */ | ||
l1 = (0.2126*l1R) + (0.7152*l1G) + (0.0722*l1B); /* using linearised R, G, and B value */ | ||
l2 = (0.2126*l2R) + (0.7152*l2G) + (0.0722*l2B); /* using linearised R, G, and B value */ | ||
/* and L2 is the lower value. */ | ||
l1 = l1 + 0.05; | ||
l2 = l2 + 0.05; | ||
if (l1 < l2) { | ||
var temp = l1; | ||
l1 = l2; | ||
l2 = temp; | ||
} | ||
return {'l1': l1, 'l2': l2}; | ||
ratio = (lighter + 0.05) / (darker + 0.05); | ||
return ratio; | ||
}, | ||
isLevelAA : function(foreground, background) { | ||
verifyContrastRatio : function(ratio) { | ||
var luminance = this.getRelativeLuminance(foreground, background); | ||
var result = luminance.l1/luminance.l2; | ||
result = result.toFixed(1); | ||
var resultsClass = { | ||
toString: function() { | ||
return '< WCAG-AA: ' + ((this.WCAG_AA) ? 'pass' : 'fail') + | ||
' WCAG-AAA: ' + ((this.WCAG_AAA) ? 'pass' : 'fail') + | ||
' >'; | ||
} | ||
}; | ||
var WCAG_REQ_RATIO_AA_LG = 3.0, | ||
WCAG_REQ_RATIO_AA_SM = 4.5, | ||
WCAG_REQ_RATIO_AAA_LG = 4.5, | ||
WCAG_REQ_RATIO_AAA_SM = 7.0, | ||
WCAG_FONT_CUTOFF = 18; | ||
if (result >= 3) | ||
return true; | ||
else | ||
return false; | ||
}, | ||
removeHash : function (string) { | ||
if(string) return string.replace("#",""); | ||
}, | ||
addHash : function (string) { | ||
if(string) return "#" + string; | ||
var results = Object.create(resultsClass), | ||
fontSize = this.fontSize || 14; | ||
if (fontSize >= WCAG_FONT_CUTOFF) { | ||
results.WCAG_AA = (ratio >= WCAG_REQ_RATIO_AA_LG); | ||
results.WCAG_AAA = (ratio >= WCAG_REQ_RATIO_AAA_LG); | ||
} else { | ||
results.WCAG_AA = (ratio >= WCAG_REQ_RATIO_AA_SM); | ||
results.WCAG_AAA = (ratio >= WCAG_REQ_RATIO_AAA_SM); | ||
} | ||
return results; | ||
} | ||
}; | ||
@@ -101,0 +196,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
116843
18
2397
119
4
2
Updatedamdefine@>=0.2.0