| /* MIT license */ | 
| var colorNames = require('color-name'); | 
| var swizzle = require('simple-swizzle'); | 
| var hasOwnProperty = Object.hasOwnProperty; | 
|   | 
| var reverseNames = Object.create(null); | 
|   | 
| // create a list of reverse color names | 
| for (var name in colorNames) { | 
|     if (hasOwnProperty.call(colorNames, name)) { | 
|         reverseNames[colorNames[name]] = name; | 
|     } | 
| } | 
|   | 
| var cs = module.exports = { | 
|     to: {}, | 
|     get: {} | 
| }; | 
|   | 
| cs.get = function (string) { | 
|     var prefix = string.substring(0, 3).toLowerCase(); | 
|     var val; | 
|     var model; | 
|     switch (prefix) { | 
|         case 'hsl': | 
|             val = cs.get.hsl(string); | 
|             model = 'hsl'; | 
|             break; | 
|         case 'hwb': | 
|             val = cs.get.hwb(string); | 
|             model = 'hwb'; | 
|             break; | 
|         default: | 
|             val = cs.get.rgb(string); | 
|             model = 'rgb'; | 
|             break; | 
|     } | 
|   | 
|     if (!val) { | 
|         return null; | 
|     } | 
|   | 
|     return {model: model, value: val}; | 
| }; | 
|   | 
| cs.get.rgb = function (string) { | 
|     if (!string) { | 
|         return null; | 
|     } | 
|   | 
|     var abbr = /^#([a-f0-9]{3,4})$/i; | 
|     var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; | 
|     var rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; | 
|     var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; | 
|     var keyword = /^(\w+)$/; | 
|   | 
|     var rgb = [0, 0, 0, 1]; | 
|     var match; | 
|     var i; | 
|     var hexAlpha; | 
|   | 
|     if (match = string.match(hex)) { | 
|         hexAlpha = match[2]; | 
|         match = match[1]; | 
|   | 
|         for (i = 0; i < 3; i++) { | 
|             // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 | 
|             var i2 = i * 2; | 
|             rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); | 
|         } | 
|   | 
|         if (hexAlpha) { | 
|             rgb[3] = parseInt(hexAlpha, 16) / 255; | 
|         } | 
|     } else if (match = string.match(abbr)) { | 
|         match = match[1]; | 
|         hexAlpha = match[3]; | 
|   | 
|         for (i = 0; i < 3; i++) { | 
|             rgb[i] = parseInt(match[i] + match[i], 16); | 
|         } | 
|   | 
|         if (hexAlpha) { | 
|             rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255; | 
|         } | 
|     } else if (match = string.match(rgba)) { | 
|         for (i = 0; i < 3; i++) { | 
|             rgb[i] = parseInt(match[i + 1], 0); | 
|         } | 
|   | 
|         if (match[4]) { | 
|             if (match[5]) { | 
|                 rgb[3] = parseFloat(match[4]) * 0.01; | 
|             } else { | 
|                 rgb[3] = parseFloat(match[4]); | 
|             } | 
|         } | 
|     } else if (match = string.match(per)) { | 
|         for (i = 0; i < 3; i++) { | 
|             rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); | 
|         } | 
|   | 
|         if (match[4]) { | 
|             if (match[5]) { | 
|                 rgb[3] = parseFloat(match[4]) * 0.01; | 
|             } else { | 
|                 rgb[3] = parseFloat(match[4]); | 
|             } | 
|         } | 
|     } else if (match = string.match(keyword)) { | 
|         if (match[1] === 'transparent') { | 
|             return [0, 0, 0, 0]; | 
|         } | 
|   | 
|         if (!hasOwnProperty.call(colorNames, match[1])) { | 
|             return null; | 
|         } | 
|   | 
|         rgb = colorNames[match[1]]; | 
|         rgb[3] = 1; | 
|   | 
|         return rgb; | 
|     } else { | 
|         return null; | 
|     } | 
|   | 
|     for (i = 0; i < 3; i++) { | 
|         rgb[i] = clamp(rgb[i], 0, 255); | 
|     } | 
|     rgb[3] = clamp(rgb[3], 0, 1); | 
|   | 
|     return rgb; | 
| }; | 
|   | 
| cs.get.hsl = function (string) { | 
|     if (!string) { | 
|         return null; | 
|     } | 
|   | 
|     var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; | 
|     var match = string.match(hsl); | 
|   | 
|     if (match) { | 
|         var alpha = parseFloat(match[4]); | 
|         var h = ((parseFloat(match[1]) % 360) + 360) % 360; | 
|         var s = clamp(parseFloat(match[2]), 0, 100); | 
|         var l = clamp(parseFloat(match[3]), 0, 100); | 
|         var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); | 
|   | 
|         return [h, s, l, a]; | 
|     } | 
|   | 
|     return null; | 
| }; | 
|   | 
| cs.get.hwb = function (string) { | 
|     if (!string) { | 
|         return null; | 
|     } | 
|   | 
|     var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; | 
|     var match = string.match(hwb); | 
|   | 
|     if (match) { | 
|         var alpha = parseFloat(match[4]); | 
|         var h = ((parseFloat(match[1]) % 360) + 360) % 360; | 
|         var w = clamp(parseFloat(match[2]), 0, 100); | 
|         var b = clamp(parseFloat(match[3]), 0, 100); | 
|         var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); | 
|         return [h, w, b, a]; | 
|     } | 
|   | 
|     return null; | 
| }; | 
|   | 
| cs.to.hex = function () { | 
|     var rgba = swizzle(arguments); | 
|   | 
|     return ( | 
|         '#' + | 
|         hexDouble(rgba[0]) + | 
|         hexDouble(rgba[1]) + | 
|         hexDouble(rgba[2]) + | 
|         (rgba[3] < 1 | 
|             ? (hexDouble(Math.round(rgba[3] * 255))) | 
|             : '') | 
|     ); | 
| }; | 
|   | 
| cs.to.rgb = function () { | 
|     var rgba = swizzle(arguments); | 
|   | 
|     return rgba.length < 4 || rgba[3] === 1 | 
|         ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' | 
|         : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; | 
| }; | 
|   | 
| cs.to.rgb.percent = function () { | 
|     var rgba = swizzle(arguments); | 
|   | 
|     var r = Math.round(rgba[0] / 255 * 100); | 
|     var g = Math.round(rgba[1] / 255 * 100); | 
|     var b = Math.round(rgba[2] / 255 * 100); | 
|   | 
|     return rgba.length < 4 || rgba[3] === 1 | 
|         ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' | 
|         : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; | 
| }; | 
|   | 
| cs.to.hsl = function () { | 
|     var hsla = swizzle(arguments); | 
|     return hsla.length < 4 || hsla[3] === 1 | 
|         ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' | 
|         : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; | 
| }; | 
|   | 
| // hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax | 
| // (hwb have alpha optional & 1 is default value) | 
| cs.to.hwb = function () { | 
|     var hwba = swizzle(arguments); | 
|   | 
|     var a = ''; | 
|     if (hwba.length >= 4 && hwba[3] !== 1) { | 
|         a = ', ' + hwba[3]; | 
|     } | 
|   | 
|     return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; | 
| }; | 
|   | 
| cs.to.keyword = function (rgb) { | 
|     return reverseNames[rgb.slice(0, 3)]; | 
| }; | 
|   | 
| // helpers | 
| function clamp(num, min, max) { | 
|     return Math.min(Math.max(min, num), max); | 
| } | 
|   | 
| function hexDouble(num) { | 
|     var str = Math.round(num).toString(16).toUpperCase(); | 
|     return (str.length < 2) ? '0' + str : str; | 
| } |