Skip to content

Instantly share code, notes, and snippets.

@jonobr1
Last active April 24, 2020 16:11
Show Gist options
  • Save jonobr1/5166698 to your computer and use it in GitHub Desktop.
Save jonobr1/5166698 to your computer and use it in GitHub Desktop.
Interpret any valid css string and return an r, g, b, (a) object with normalized values.
/**
* Interpret any valid css string as an r, g, b, (a) object.
* If nothing found then it returns an object that is black with
* no alpha.
*
* Usage: interpret('red'); // { r: 1, g: 0, b: 0 };
* interpret('#f00'); // { r: 1, g: 0, b: 0 };
* interpret('#ff000'); // { r: 1, g: 0, b: 0 };
* interpret('rgb(255, 0, 0)'); // { r: 1, g: 0, b: 0 };
* interpret('rgba(255, 0, 0, 1)'); // { r: 1, g: 0, b: 0, a: 1 };
* interpret('hsl()');
* interpret('hsla()');
*
* @author jonobr1 / http://jonobr1.com/
*/
(function() {
var root = this;
var previousInterpret = root.interpret || {};
var interpret = root.interpret = function(v) {
for (var i = 0, l = stringParsers.length; i < l; i++) {
var color = stringParsers[i](v);
if (color) {
return color;
}
}
/**
* Default to invisible black if can't find a color.
*/
return {
r: 0, g: 0, b: 0, a: 0
};
};
interpret.noConflict = function() {
root.interpret = previousInterpret;
return this;
};
/**
* CSS Color interpretation from
* https://github.com/brehaut/color-js/blob/master/color.js
* Copyright (c) 2008-2010, Andrew Brehaut, Tim Baumann, Matt Wilson
* All rights reserved.
*/
// css_colors maps color names onto their hex values
// these names are defined by W3C
var css_colors = {aliceblue:'#F0F8FF',antiquewhite:'#FAEBD7',aqua:'#00FFFF',aquamarine:'#7FFFD4',azure:'#F0FFFF',beige:'#F5F5DC',bisque:'#FFE4C4',black:'#000000',blanchedalmond:'#FFEBCD',blue:'#0000FF',blueviolet:'#8A2BE2',brown:'#A52A2A',burlywood:'#DEB887',cadetblue:'#5F9EA0',chartreuse:'#7FFF00',chocolate:'#D2691E',coral:'#FF7F50',cornflowerblue:'#6495ED',cornsilk:'#FFF8DC',crimson:'#DC143C',cyan:'#00FFFF',darkblue:'#00008B',darkcyan:'#008B8B',darkgoldenrod:'#B8860B',darkgray:'#A9A9A9',darkgrey:'#A9A9A9',darkgreen:'#006400',darkkhaki:'#BDB76B',darkmagenta:'#8B008B',darkolivegreen:'#556B2F',darkorange:'#FF8C00',darkorchid:'#9932CC',darkred:'#8B0000',darksalmon:'#E9967A',darkseagreen:'#8FBC8F',darkslateblue:'#483D8B',darkslategray:'#2F4F4F',darkslategrey:'#2F4F4F',darkturquoise:'#00CED1',darkviolet:'#9400D3',deeppink:'#FF1493',deepskyblue:'#00BFFF',dimgray:'#696969',dimgrey:'#696969',dodgerblue:'#1E90FF',firebrick:'#B22222',floralwhite:'#FFFAF0',forestgreen:'#228B22',fuchsia:'#FF00FF',gainsboro:'#DCDCDC',ghostwhite:'#F8F8FF',gold:'#FFD700',goldenrod:'#DAA520',gray:'#808080',grey:'#808080',green:'#008000',greenyellow:'#ADFF2F',honeydew:'#F0FFF0',hotpink:'#FF69B4',indianred:'#CD5C5C',indigo:'#4B0082',ivory:'#FFFFF0',khaki:'#F0E68C',lavender:'#E6E6FA',lavenderblush:'#FFF0F5',lawngreen:'#7CFC00',lemonchiffon:'#FFFACD',lightblue:'#ADD8E6',lightcoral:'#F08080',lightcyan:'#E0FFFF',lightgoldenrodyellow:'#FAFAD2',lightgray:'#D3D3D3',lightgrey:'#D3D3D3',lightgreen:'#90EE90',lightpink:'#FFB6C1',lightsalmon:'#FFA07A',lightseagreen:'#20B2AA',lightskyblue:'#87CEFA',lightslategray:'#778899',lightslategrey:'#778899',lightsteelblue:'#B0C4DE',lightyellow:'#FFFFE0',lime:'#00FF00',limegreen:'#32CD32',linen:'#FAF0E6',magenta:'#FF00FF',maroon:'#800000',mediumaquamarine:'#66CDAA',mediumblue:'#0000CD',mediumorchid:'#BA55D3',mediumpurple:'#9370D8',mediumseagreen:'#3CB371',mediumslateblue:'#7B68EE',mediumspringgreen:'#00FA9A',mediumturquoise:'#48D1CC',mediumvioletred:'#C71585',midnightblue:'#191970',mintcream:'#F5FFFA',mistyrose:'#FFE4E1',moccasin:'#FFE4B5',navajowhite:'#FFDEAD',navy:'#000080',oldlace:'#FDF5E6',olive:'#808000',olivedrab:'#6B8E23',orange:'#FFA500',orangered:'#FF4500',orchid:'#DA70D6',palegoldenrod:'#EEE8AA',palegreen:'#98FB98',paleturquoise:'#AFEEEE',palevioletred:'#D87093',papayawhip:'#FFEFD5',peachpuff:'#FFDAB9',peru:'#CD853F',pink:'#FFC0CB',plum:'#DDA0DD',powderblue:'#B0E0E6',purple:'#800080',red:'#FF0000',rosybrown:'#BC8F8F',royalblue:'#4169E1',saddlebrown:'#8B4513',salmon:'#FA8072',sandybrown:'#F4A460',seagreen:'#2E8B57',seashell:'#FFF5EE',sienna:'#A0522D',silver:'#C0C0C0',skyblue:'#87CEEB',slateblue:'#6A5ACD',slategray:'#708090',slategrey:'#708090',snow:'#FFFAFA',springgreen:'#00FF7F',transparent:'#000',steelblue:'#4682B4',tan:'#D2B48C',teal:'#008080',thistle:'#D8BFD8',tomato:'#FF6347',turquoise:'#40E0D0',violet:'#EE82EE',wheat:'#F5DEB3',white:'#FFFFFF',whitesmoke:'#F5F5F5',yellow:'#FFFF00',yellowgreen:'#9ACD32'};
// CSS value regexes, according to http://www.w3.org/TR/css3-values/
var css_integer = '(?:\\+|-)?\\d+';
var css_float = '(?:\\+|-)?\\d*\\.\\d+';
var css_number = '(?:' + css_integer + ')|(?:' + css_float + ')';
css_integer = '(' + css_integer + ')';
css_float = '(' + css_float + ')';
css_number = '(' + css_number + ')';
var css_percentage = css_number + '%';
var css_whitespace = '\\s*?';
// http://www.w3.org/TR/2003/CR-css3-color-20030514/
var hsl_hsla_regex = new RegExp([
'^hsl(a?)\\(', css_number, ',', css_percentage, ',', css_percentage, '(,', css_number, ')?\\)$'
].join(css_whitespace) );
var rgb_rgba_integer_regex = new RegExp([
'^rgb(a?)\\(', css_integer, ',', css_integer, ',', css_integer, '(,', css_number, ')?\\)$'
].join(css_whitespace) );
var rgb_rgba_percentage_regex = new RegExp([
'^rgb(a?)\\(', css_percentage, ',', css_percentage, ',', css_percentage, '(,', css_number, ')?\\)$'
].join(css_whitespace) );
var remove_comma_regex = /^,\s*/;
var hslToRgb = function(h, s, l, a) {
var r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
function hue2rgb(p, q, t){
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1 / 6) return p + (q - p) * 6 * t;
if(t < 1 / 2) return q;
if(t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
}
var alpha = _.isUndefined(a) || _.isNull(a) ? 1.0 : a.replace(remove_comma_regex, '');
return {
r: hue2rgb(p, q, h + 1 / 3),
g: hue2rgb(p, q, h),
b: hue2rgb(p, q, h - 1 / 3),
a: alpha
};
}
var stringParsers = [
// CSS RGB(A) literal
function(css) {
css = trim(css);
var withInteger = match(rgb_rgba_integer_regex, 255);
if (withInteger) {
return withInteger;
}
return match(rgb_rgba_percentage_regex, 100);
function match(regex, max_value) {
var colorGroups = css.match(regex);
if (!colorGroups || (!!colorGroups[1] + !!colorGroups[5] === 1)) {
return;
}
var alpha = _.isUndefined(colorGroups[5]) ? 1.0 : colorGroups[5].replace(remove_comma_regex, '');
return {
r: Math.min(1, Math.max(0, colorGroups[2] / max_value)),
g: Math.min(1, Math.max(0, colorGroups[3] / max_value)),
b: Math.min(1, Math.max(0, colorGroups[4] / max_value)),
a: Math.min(1, Math.max(alpha, 0))
};
}
},
function(css) {
var lower = css.toLowerCase();
if (lower in css_colors) {
css = css_colors[lower];
}
if (!css.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/)) {
return;
}
css = css.replace(/^#/, '');
var bytes = css.length / 3;
var max = Math.pow(16, bytes) - 1;
return {
r: parseInt(css.slice(0, bytes), 16) / max,
g: parseInt(css.slice(bytes * 1,bytes * 2), 16) / max,
b: parseInt(css.slice(bytes * 2), 16) / max,
a: 1.0
};
},
// css HSL(A) literal
function(css) {
var colorGroups = trim(css).match(hsl_hsla_regex);
// if there is an "a" after "hsl", there must be a fourth parameter and the other way round
if (!colorGroups || (!!colorGroups[1] + !!colorGroups[5] === 1)) {
return null;
}
var h = ((colorGroups[2] % 360 + 360) % 360) / 360;
var s = Math.max(0, Math.min(parseInt(colorGroups[3], 10) / 100, 1));
var l = Math.max(0, Math.min(parseInt(colorGroups[4], 10) / 100, 1));
return hslToRgb(h, s, l, colorGroups[5]);
}
];
function trim(str) {
return str.replace(/^\s+|\s+$/g, '');
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment