postcss-color-mod-function
Advanced tools
Comparing version 1.1.0 to 2.1.0
# Changes to PostCSS color-mod() Function | ||
### 2.1.0 (January 20, 2018) | ||
- Added support for legacy (comma-separated) `hsl()` colors | ||
- Added support for all `<hue>` units | ||
- Added use of legacy (comma-separated) `hsl()` colors when appropriate | ||
- Improved color conversions | ||
- Improved support for all `rgb()` colors | ||
- Removed external math and color dependencies | ||
### 2.0.0 (January 17, 2018) | ||
- Reverse blend/blenda percentage calculations (breaking change) | ||
- Other improvements (see 4e4de6e) | ||
### 1.1.0 (January 17, 2018) | ||
@@ -4,0 +18,0 @@ |
@@ -7,6 +7,380 @@ 'use strict'; | ||
var postcss = _interopDefault(require('postcss')); | ||
var names = _interopDefault(require('color-name')); | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
/* Convert Degree to Hue Degree | ||
/* ========================================================================== */ | ||
function convertDtoD(deg) { | ||
return deg % 360; | ||
} | ||
/* Convert Gradian to Hue Degree | ||
/* ========================================================================== */ | ||
function convertGtoD(grad) { | ||
return grad * 0.9 % 360; | ||
} | ||
/* Convert Radian to Hue Degree | ||
/* ========================================================================== */ | ||
function convertRtoD(rad) { | ||
return rad * 180 / Math.PI % 360; | ||
} | ||
/* Convert Turn to Hue Degree | ||
/* ========================================================================== */ | ||
function convertTtoD(turn) { | ||
return turn * 360 % 360; | ||
} | ||
/* Convert Red/Green/Blue to Red/Green/Blue (0 - 255) | ||
/* ========================================================================== */ | ||
/* Convert Red/Green/Blue to Hue/Saturation/Lightness | ||
/* ========================================================================== */ | ||
function convertRGBtoHSL(red, green, blue) { | ||
var fallbackHue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; | ||
var hue = convertRGBtoH(red, green, blue, fallbackHue); | ||
var whiteness = convertRGBtoW(red, green, blue); | ||
var value = convertRGBtoV(red, green, blue); | ||
var lightness = convertWVtoL(whiteness, value); | ||
var saturation = convertLVWtoS(lightness, value, whiteness); | ||
return [hue, saturation, lightness]; | ||
} | ||
/* Convert Red/Green/Blue to Hue/Whiteness/Blackness | ||
/* ========================================================================== */ | ||
function convertRGBtoHWB(red, green, blue) { | ||
var fallbackHue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; | ||
var hue = convertRGBtoH(red, green, blue, fallbackHue); | ||
var whiteness = convertRGBtoW(red, green, blue); | ||
var value = convertRGBtoV(red, green, blue); | ||
var blackness = convertVtoB(value); | ||
return [hue, whiteness, blackness]; | ||
} | ||
/* Convert Hue/Saturation/Lightness to Red/Green/Blue (and fallback Hue) | ||
/* ========================================================================== */ | ||
function convertHSLtoRGB(hue, saturation, lightness) { | ||
var hexagon = hue / 60; | ||
var t2 = lightness <= 50 ? lightness * (saturation + 100) / 10000 : (lightness + saturation) / 100 - lightness * saturation / 10000; | ||
var t1 = lightness * 0.02 - t2; | ||
var red = convertTTHtoChannel(t1, t2, hexagon + 2) * 100; | ||
var green = convertTTHtoChannel(t1, t2, hexagon) * 100; | ||
var blue = convertTTHtoChannel(t1, t2, hexagon - 2) * 100; | ||
return [red, green, blue]; | ||
} | ||
/* Convert Hue/Saturation/Lightness to Hue/Whiteness/Blackness | ||
/* ========================================================================== */ | ||
function convertHSLtoHWB(hue, saturation, lightness) { | ||
var _convertHSLtoRGB = convertHSLtoRGB(hue, saturation, lightness), | ||
_convertHSLtoRGB2 = _slicedToArray(_convertHSLtoRGB, 3), | ||
red = _convertHSLtoRGB2[0], | ||
green = _convertHSLtoRGB2[1], | ||
blue = _convertHSLtoRGB2[2]; | ||
var _convertRGBtoHWB = convertRGBtoHWB(red, green, blue, hue), | ||
_convertRGBtoHWB2 = _slicedToArray(_convertRGBtoHWB, 3), | ||
whiteness = _convertRGBtoHWB2[1], | ||
blackness = _convertRGBtoHWB2[2]; | ||
return [hue, whiteness, blackness]; | ||
} | ||
/* Convert Hue/Whiteness/Blackness to Hue/Saturation/Lightness | ||
/* ========================================================================== */ | ||
function convertHWBtoHSL(hue, whiteness, blackness) { | ||
var _convertHWBtoRGB = convertHWBtoRGB(hue, whiteness, blackness), | ||
_convertHWBtoRGB2 = _slicedToArray(_convertHWBtoRGB, 3), | ||
red = _convertHWBtoRGB2[0], | ||
green = _convertHWBtoRGB2[1], | ||
blue = _convertHWBtoRGB2[2]; | ||
var _convertRGBtoHSL = convertRGBtoHSL(red, green, blue, hue), | ||
_convertRGBtoHSL2 = _slicedToArray(_convertRGBtoHSL, 3), | ||
saturation = _convertRGBtoHSL2[1], | ||
lightness = _convertRGBtoHSL2[2]; | ||
return [hue, saturation, lightness]; | ||
} | ||
/* Convert Hue/Whiteness/Blackness to Red/Green/Blue (and fallback Hue) | ||
/* ========================================================================== */ | ||
function convertHWBtoRGB(hue, whiteness, blackness) { | ||
var _convertHSLtoRGB3 = convertHSLtoRGB(hue, 100, 50), | ||
_convertHSLtoRGB4 = _slicedToArray(_convertHSLtoRGB3, 3), | ||
hslRed = _convertHSLtoRGB4[0], | ||
hslGreen = _convertHSLtoRGB4[1], | ||
hslBlue = _convertHSLtoRGB4[2]; | ||
var tot = whiteness + blackness; | ||
var w = tot > 100 ? whiteness / tot * 100 : whiteness; | ||
var b = tot > 100 ? blackness / tot * 100 : blackness; | ||
var red = hslRed * (100 - w - b) / 100 + w; | ||
var green = hslGreen * (100 - w - b) / 100 + w; | ||
var blue = hslBlue * (100 - w - b) / 100 + w; | ||
return [red, green, blue]; | ||
} | ||
/* Convert Channel to Channel (0 - 255) | ||
/* ========================================================================== */ | ||
/* Convert Red/Green/Blue to Hue | ||
/* ========================================================================== */ | ||
function convertRGBtoH(red, green, blue) { | ||
var fallbackHue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; | ||
var whiteness = convertRGBtoW(red, green, blue); | ||
var value = convertRGBtoV(red, green, blue); | ||
var chroma = convertVWtoC(value, whiteness); | ||
if (chroma === 0) { | ||
return fallbackHue; | ||
} else { | ||
var segment = value === red ? (green - blue) / chroma : value === green ? (blue - red) / chroma : (red - green) / chroma; | ||
var shift = value === red ? segment < 0 ? 360 / 60 : 0 / 60 : value === green ? 120 / 60 : 240 / 60; | ||
var hue = (segment + shift) * 60; | ||
return hue; | ||
} | ||
} | ||
/* Convert Red/Green/Blue to Whiteness | ||
/* ========================================================================== */ | ||
function convertRGBtoW(red, green, blue) { | ||
return Math.min(red, green, blue); | ||
} | ||
/* Convert Red/Green/Blue to Value | ||
/* ========================================================================== */ | ||
function convertRGBtoV(red, green, blue) { | ||
return Math.max(red, green, blue); | ||
} | ||
/* Convert Value/Whiteness to Chroma | ||
/* ========================================================================== */ | ||
function convertVWtoC(value, whiteness) { | ||
return value - whiteness; | ||
} | ||
/* Convert Whiteness/Value to Lightness | ||
/* ========================================================================== */ | ||
function convertWVtoL(whiteness, value) { | ||
return (whiteness + value) / 2; | ||
} | ||
/* Convert Lightness/Value/Whiteness to Saturation | ||
/* ========================================================================== */ | ||
function convertLVWtoS(lightness, value, whiteness) { | ||
return whiteness === value ? 0 : lightness < 50 ? (value - whiteness) / (value + whiteness) * 100 : (value - whiteness) / (200 - value - whiteness) * 100; | ||
} | ||
/* Convert Value to Blackness | ||
/* ========================================================================== */ | ||
function convertVtoB(value) { | ||
return 100 - value; | ||
} | ||
/* Convert Hue parts to Channel | ||
/* ========================================================================== */ | ||
function convertTTHtoChannel(t1, t2, hexagon) { | ||
var althexagon = hexagon < 0 ? hexagon + 6 : hexagon >= 6 ? hexagon - 6 : hexagon; | ||
return althexagon < 1 ? (t2 - t1) * althexagon + t1 : althexagon < 3 ? t2 : althexagon < 4 ? (t2 - t1) * (4 - althexagon) + t1 : t1; | ||
} | ||
/* Convert a Name to Red/Green/Blue | ||
/* ========================================================================== */ | ||
function convertNtoRGB(name) { | ||
var names = { | ||
aliceblue: [240, 248, 255], | ||
antiquewhite: [250, 235, 215], | ||
aqua: [0, 255, 255], | ||
aquamarine: [127, 255, 212], | ||
azure: [240, 255, 255], | ||
beige: [245, 245, 220], | ||
bisque: [255, 228, 196], | ||
black: [0, 0, 0], | ||
blanchedalmond: [255, 235, 205], | ||
blue: [0, 0, 255], | ||
blueviolet: [138, 43, 226], | ||
brown: [165, 42, 42], | ||
burlywood: [222, 184, 135], | ||
cadetblue: [95, 158, 160], | ||
chartreuse: [127, 255, 0], | ||
chocolate: [210, 105, 30], | ||
coral: [255, 127, 80], | ||
cornflowerblue: [100, 149, 237], | ||
cornsilk: [255, 248, 220], | ||
crimson: [220, 20, 60], | ||
cyan: [0, 255, 255], | ||
darkblue: [0, 0, 139], | ||
darkcyan: [0, 139, 139], | ||
darkgoldenrod: [184, 134, 11], | ||
darkgray: [169, 169, 169], | ||
darkgreen: [0, 100, 0], | ||
darkgrey: [169, 169, 169], | ||
darkkhaki: [189, 183, 107], | ||
darkmagenta: [139, 0, 139], | ||
darkolivegreen: [85, 107, 47], | ||
darkorange: [255, 140, 0], | ||
darkorchid: [153, 50, 204], | ||
darkred: [139, 0, 0], | ||
darksalmon: [233, 150, 122], | ||
darkseagreen: [143, 188, 143], | ||
darkslateblue: [72, 61, 139], | ||
darkslategray: [47, 79, 79], | ||
darkslategrey: [47, 79, 79], | ||
darkturquoise: [0, 206, 209], | ||
darkviolet: [148, 0, 211], | ||
deeppink: [255, 20, 147], | ||
deepskyblue: [0, 191, 255], | ||
dimgray: [105, 105, 105], | ||
dimgrey: [105, 105, 105], | ||
dodgerblue: [30, 144, 255], | ||
firebrick: [178, 34, 34], | ||
floralwhite: [255, 250, 240], | ||
forestgreen: [34, 139, 34], | ||
fuchsia: [255, 0, 255], | ||
gainsboro: [220, 220, 220], | ||
ghostwhite: [248, 248, 255], | ||
gold: [255, 215, 0], | ||
goldenrod: [218, 165, 32], | ||
gray: [128, 128, 128], | ||
green: [0, 128, 0], | ||
greenyellow: [173, 255, 47], | ||
grey: [128, 128, 128], | ||
honeydew: [240, 255, 240], | ||
hotpink: [255, 105, 180], | ||
indianred: [205, 92, 92], | ||
indigo: [75, 0, 130], | ||
ivory: [255, 255, 240], | ||
khaki: [240, 230, 140], | ||
lavender: [230, 230, 250], | ||
lavenderblush: [255, 240, 245], | ||
lawngreen: [124, 252, 0], | ||
lemonchiffon: [255, 250, 205], | ||
lightblue: [173, 216, 230], | ||
lightcoral: [240, 128, 128], | ||
lightcyan: [224, 255, 255], | ||
lightgoldenrodyellow: [250, 250, 210], | ||
lightgray: [211, 211, 211], | ||
lightgreen: [144, 238, 144], | ||
lightgrey: [211, 211, 211], | ||
lightpink: [255, 182, 193], | ||
lightsalmon: [255, 160, 122], | ||
lightseagreen: [32, 178, 170], | ||
lightskyblue: [135, 206, 250], | ||
lightslategray: [119, 136, 153], | ||
lightslategrey: [119, 136, 153], | ||
lightsteelblue: [176, 196, 222], | ||
lightyellow: [255, 255, 224], | ||
lime: [0, 255, 0], | ||
limegreen: [50, 205, 50], | ||
linen: [250, 240, 230], | ||
magenta: [255, 0, 255], | ||
maroon: [128, 0, 0], | ||
mediumaquamarine: [102, 205, 170], | ||
mediumblue: [0, 0, 205], | ||
mediumorchid: [186, 85, 211], | ||
mediumpurple: [147, 112, 219], | ||
mediumseagreen: [60, 179, 113], | ||
mediumslateblue: [123, 104, 238], | ||
mediumspringgreen: [0, 250, 154], | ||
mediumturquoise: [72, 209, 204], | ||
mediumvioletred: [199, 21, 133], | ||
midnightblue: [25, 25, 112], | ||
mintcream: [245, 255, 250], | ||
mistyrose: [255, 228, 225], | ||
moccasin: [255, 228, 181], | ||
navajowhite: [255, 222, 173], | ||
navy: [0, 0, 128], | ||
oldlace: [253, 245, 230], | ||
olive: [128, 128, 0], | ||
olivedrab: [107, 142, 35], | ||
orange: [255, 165, 0], | ||
orangered: [255, 69, 0], | ||
orchid: [218, 112, 214], | ||
palegoldenrod: [238, 232, 170], | ||
palegreen: [152, 251, 152], | ||
paleturquoise: [175, 238, 238], | ||
palevioletred: [219, 112, 147], | ||
papayawhip: [255, 239, 213], | ||
peachpuff: [255, 218, 185], | ||
peru: [205, 133, 63], | ||
pink: [255, 192, 203], | ||
plum: [221, 160, 221], | ||
powderblue: [176, 224, 230], | ||
purple: [128, 0, 128], | ||
rebeccapurple: [102, 51, 153], | ||
red: [255, 0, 0], | ||
rosybrown: [188, 143, 143], | ||
royalblue: [65, 105, 225], | ||
saddlebrown: [139, 69, 19], | ||
salmon: [250, 128, 114], | ||
sandybrown: [244, 164, 96], | ||
seagreen: [46, 139, 87], | ||
seashell: [255, 245, 238], | ||
sienna: [160, 82, 45], | ||
silver: [192, 192, 192], | ||
skyblue: [135, 206, 235], | ||
slateblue: [106, 90, 205], | ||
slategray: [112, 128, 144], | ||
slategrey: [112, 128, 144], | ||
snow: [255, 250, 250], | ||
springgreen: [0, 255, 127], | ||
steelblue: [70, 130, 180], | ||
tan: [210, 180, 140], | ||
teal: [0, 128, 128], | ||
thistle: [216, 191, 216], | ||
tomato: [255, 99, 71], | ||
turquoise: [64, 224, 208], | ||
violet: [238, 130, 238], | ||
wheat: [245, 222, 179], | ||
white: [255, 255, 255], | ||
whitesmoke: [245, 245, 245], | ||
yellow: [255, 255, 0], | ||
yellowgreen: [154, 205, 50] | ||
}; | ||
return names[name]; | ||
} | ||
var _slicedToArray$1 = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -23,3 +397,3 @@ | ||
if (color.colorspace === 'rgb') { | ||
this.color.hue = rgb2hue(color.red, color.green, color.blue, color.hue || 0); | ||
this.color.hue = convertRGBtoH(color.red, color.green, color.blue, color.hue || 0); | ||
} | ||
@@ -120,4 +494,4 @@ } | ||
var hwb = color2hwb(this.color); | ||
var shade = { hue: 0, whiteness: 1, blackness: 0, colorspace: 'hwb' }; | ||
var colorspace = 'hwb'; | ||
var shade = { hue: 0, whiteness: 0, blackness: 100, colorspace: 'hwb' }; | ||
var colorspace = 'rgb'; | ||
@@ -130,4 +504,4 @@ return percentage === undefined ? hwb.blackness : new Color(_blend(hwb, shade, percentage, colorspace)); | ||
var hwb = color2hwb(this.color); | ||
var tint = { hue: 0, whiteness: 0, blackness: 1, colorspace: 'hwb' }; | ||
var colorspace = 'hwb'; | ||
var tint = { hue: 0, whiteness: 100, blackness: 0, colorspace: 'hwb' }; | ||
var colorspace = 'rgb'; | ||
@@ -146,10 +520,3 @@ return percentage === undefined ? hwb.blackness : new Color(_blend(hwb, tint, percentage, colorspace)); | ||
value: function toHSL() { | ||
var color = color2hsl(this.color); | ||
var isOpaque = color.alpha === 1; | ||
var hue = color.hue; | ||
var saturation = round(color.saturation * 100, 4); | ||
var lightness = round(color.lightness * 100, 4); | ||
var alpha = round(color.alpha * 100, 4); | ||
return `hsl(${hue} ${saturation}% ${lightness}%${isOpaque ? '' : ` / ${alpha}%`})`; | ||
return color2hslString(this.color); | ||
} | ||
@@ -159,22 +526,13 @@ }, { | ||
value: function toHWB() { | ||
var color = color2hwb(this.color); | ||
var isOpaque = color.alpha === 1; | ||
var hue = color.hue; | ||
var whiteness = round(color.whiteness * 100, 4); | ||
var blackness = round(color.blackness * 100, 4); | ||
var alpha = round(color.alpha * 100, 4); | ||
return `hwb(${hue} ${whiteness}% ${blackness}%${isOpaque ? '' : ` / ${alpha}%`})`; | ||
return color2hwbString(this.color); | ||
} | ||
}, { | ||
key: 'toLegacy', | ||
value: function toLegacy() { | ||
return color2legacyString(this.color); | ||
} | ||
}, { | ||
key: 'toRGB', | ||
value: function toRGB() { | ||
var color = color2rgb(this.color); | ||
var isOpaque = color.alpha === 1; | ||
var red = round(color.red * 100, 4); | ||
var green = round(color.green * 100, 4); | ||
var blue = round(color.blue * 100, 4); | ||
var alpha = round(color.alpha * 100, 4); | ||
return `rgb(${red}% ${green}% ${blue}%${isOpaque ? '' : ` / ${alpha}%`})`; | ||
return color2rgbString(this.color); | ||
} | ||
@@ -184,20 +542,8 @@ }, { | ||
value: function toRGBLegacy() { | ||
var color = color2rgb(this.color); | ||
var isOpaque = color.alpha === 1; | ||
var name = isOpaque ? 'rgb' : 'rgba'; | ||
var red = round(color.red * 255, 0); | ||
var green = round(color.green * 255, 0); | ||
var blue = round(color.blue * 255, 0); | ||
var alpha = round(color.alpha, 4); | ||
return `${name}(${red}, ${green}, ${blue}${isOpaque ? '' : `, ${alpha}`})`; | ||
return color2rgbLegacyString(this.color); | ||
} | ||
}, { | ||
key: 'toString', | ||
value: function toString(rawcolorspace) { | ||
var colorspace = rawcolorspace || this.color.colorspace; | ||
var color = colorspace === 'hsl' ? this.toHSL() : colorspace === 'hwb' ? this.toHWB() : this.toRGB(); | ||
return color; | ||
value: function toString() { | ||
return color2string(this.color); | ||
} | ||
@@ -210,4 +556,4 @@ }]); | ||
function _blend(base, color, percentage, colorspace, isBlendingAlpha) { | ||
// eslint-disable-line max-params | ||
var subtraction = 1 - percentage; | ||
var addition = percentage / 100; | ||
var subtraction = 1 - addition; | ||
@@ -227,6 +573,6 @@ if (colorspace === 'hsl') { | ||
var hue = h1 * percentage + h2 * subtraction, | ||
saturation = s1 * percentage + s2 * subtraction, | ||
lightness = l1 * percentage + l2 * subtraction, | ||
alpha = isBlendingAlpha ? a1 * percentage + a2 * subtraction : a1; | ||
var hue = h1 * subtraction + h2 * addition, | ||
saturation = s1 * subtraction + s2 * addition, | ||
lightness = l1 * subtraction + l2 * addition, | ||
alpha = isBlendingAlpha ? a1 * subtraction + a2 * addition : a1; | ||
@@ -248,6 +594,6 @@ | ||
var _hue2 = _h * percentage + _h2 * subtraction, | ||
whiteness = w1 * percentage + w2 * subtraction, | ||
blackness = b1 * percentage + b2 * subtraction, | ||
_alpha2 = isBlendingAlpha ? _a * percentage + _a2 * subtraction : _a; | ||
var _hue2 = _h * subtraction + _h2 * addition, | ||
whiteness = w1 * subtraction + w2 * addition, | ||
blackness = b1 * subtraction + b2 * addition, | ||
_alpha2 = isBlendingAlpha ? _a * subtraction + _a2 * addition : _a; | ||
@@ -268,6 +614,6 @@ return { hue: _hue2, whiteness, blackness, alpha: _alpha2, colorspace: 'hwb' }; | ||
var red = r1 * percentage + r2 * subtraction, | ||
green = g1 * percentage + g2 * subtraction, | ||
blue = _b * percentage + _b2 * subtraction, | ||
_alpha3 = isBlendingAlpha ? _a3 * percentage + _a4 * subtraction : _a3; | ||
var red = r1 * subtraction + r2 * addition, | ||
green = g1 * subtraction + g2 * addition, | ||
blue = _b * subtraction + _b2 * addition, | ||
_alpha3 = isBlendingAlpha ? _a3 * subtraction + _a4 * addition : _a3; | ||
@@ -289,19 +635,11 @@ return { red, green, blue, alpha: _alpha3, colorspace: 'rgb' }; | ||
// value of the channel | ||
var adjustment = channels[channel]; | ||
// normalized value of the channel | ||
var value = normalize(channels[channel], channel); | ||
// value limitations | ||
var min = 0; | ||
var max = isHue ? 360 : 1; | ||
// updated value | ||
var value = Math.min(Math.max(parseFloat(adjustment), min), max); | ||
// assign channel to new object | ||
if (isHue) { | ||
color.hue = value; | ||
} else { | ||
color[channel] = value; | ||
color[channel] = value; | ||
color.hue = isRGB ? rgb2hue(color.red, color.green, color.blue, base.hue || 0) : base.hue; | ||
if (isRGB) { | ||
// conditionally preserve the hue | ||
color.hue = convertRGBtoH(color.red, color.green, color.blue, base.hue || 0); | ||
} | ||
@@ -313,139 +651,48 @@ }); | ||
/* Convert colors | ||
/* ========================================================================== */ | ||
function normalize(value, channel) { | ||
// detect channel | ||
var isHue = channel === 'hue'; | ||
function color2hsl(color) { | ||
return color.colorspace === 'rgb' ? rgb2hsl(color, color.hue) : color.colorspace === 'hwb' ? rgb2hsl(hwb2rgb(color), color.hue) : color; | ||
} | ||
// value limitations | ||
var min = 0; | ||
var max = isHue ? 360 : 100; | ||
function color2hwb(color) { | ||
return color.colorspace === 'rgb' ? rgb2hwb(color, color.hue) : color.colorspace === 'hsl' ? rgb2hwb(hsl2rgb(color), color.hue) : color; | ||
} | ||
var normalizedValue = Math.min(Math.max(isHue ? value % 360 : value, min), max); | ||
function color2rgb(color) { | ||
return color.colorspace === 'hsl' ? hsl2rgb(color) : color.colorspace === 'hwb' ? hwb2rgb(color) : color; | ||
return normalizedValue; | ||
} | ||
/* Convert HSL to RGB | ||
/* Convert colors | ||
/* ========================================================================== */ | ||
function hsl2rgb(_ref) { | ||
var hue = _ref.hue, | ||
saturation = _ref.saturation, | ||
lightness = _ref.lightness, | ||
_ref$alpha = _ref.alpha, | ||
alpha = _ref$alpha === undefined ? 1 : _ref$alpha; | ||
function color2rgb(color) { | ||
var _ref = color.colorspace === 'hsl' ? convertHSLtoRGB(color.hue, color.saturation, color.lightness) : color.colorspace === 'hwb' ? convertHWBtoRGB(color.hue, color.whiteness, color.blackness) : [color.red, color.green, color.blue], | ||
_ref2 = _slicedToArray$1(_ref, 3), | ||
red = _ref2[0], | ||
green = _ref2[1], | ||
blue = _ref2[2]; | ||
var t2 = lightness <= 0.5 ? lightness * (saturation + 1) : lightness + saturation - lightness * saturation; | ||
var t1 = lightness * 2 - t2; | ||
var red = hue2rgb(t1, t2, hue / 60 + 2); | ||
var green = hue2rgb(t1, t2, hue / 60); | ||
var blue = hue2rgb(t1, t2, hue / 60 - 2); | ||
return { hue, red, green, blue, alpha, colorspace: 'rgb' }; | ||
return { red, green, blue, hue: color.hue, alpha: color.alpha, colorspace: 'rgb' }; | ||
} | ||
/* Convert HWB to RGB | ||
/* ========================================================================== */ | ||
function color2hsl(color) { | ||
var _ref3 = color.colorspace === 'rgb' ? convertRGBtoHSL(color.red, color.green, color.blue, color.hue) : color.colorspace === 'hwb' ? convertHWBtoHSL(color.hue, color.whiteness, color.blackness) : [color.hue, color.saturation, color.lightness], | ||
_ref4 = _slicedToArray$1(_ref3, 3), | ||
hue = _ref4[0], | ||
saturation = _ref4[1], | ||
lightness = _ref4[2]; | ||
function hwb2rgb(_ref2) { | ||
var hue = _ref2.hue, | ||
whiteness = _ref2.whiteness, | ||
blackness = _ref2.blackness, | ||
_ref2$alpha = _ref2.alpha, | ||
alpha = _ref2$alpha === undefined ? 1 : _ref2$alpha; | ||
var ratio = whiteness + blackness; | ||
var rwhiteness = ratio > 1 ? whiteness / ratio : whiteness; | ||
var rblackness = ratio > 1 ? blackness / ratio : blackness; | ||
var value = 1 - rblackness; | ||
var hexagon = 6 * hue / 360; | ||
var hexagonFloor = Math.floor(hexagon); | ||
var hexagonF = hexagonFloor % 6 ? 1 - (hexagon - hexagonFloor) : hexagon - hexagonFloor; | ||
var interpolation = rwhiteness + hexagonF * (value - rwhiteness); | ||
var _ref3 = hexagonFloor % 6 === 5 ? [value, rwhiteness, interpolation] : hexagonFloor % 6 === 4 ? [interpolation, rwhiteness, value] : hexagonFloor % 6 === 3 ? [rwhiteness, interpolation, value] : hexagonFloor % 6 === 2 ? [rwhiteness, value, interpolation] : hexagonFloor % 6 === 1 ? [interpolation, value, rwhiteness] : [value, interpolation, rwhiteness], | ||
_ref4 = _slicedToArray(_ref3, 3), | ||
red = _ref4[0], | ||
green = _ref4[1], | ||
blue = _ref4[2]; | ||
return { hue, red, green, blue, alpha, colorspace: 'rgb' }; | ||
return { hue, saturation, lightness, alpha: color.alpha, colorspace: 'hsl' }; | ||
} | ||
/* Convert RGB to HSL | ||
/* ========================================================================== */ | ||
function color2hwb(color) { | ||
var _ref5 = color.colorspace === 'rgb' ? convertRGBtoHWB(color.red, color.green, color.blue, color.hue) : color.colorspace === 'hsl' ? convertHSLtoHWB(color.hue, color.saturation, color.lightness) : [color.hue, color.whiteness, color.blackness], | ||
_ref6 = _slicedToArray$1(_ref5, 3), | ||
hue = _ref6[0], | ||
whiteness = _ref6[1], | ||
blackness = _ref6[2]; | ||
function rgb2hsl(_ref5) { | ||
var red = _ref5.red, | ||
green = _ref5.green, | ||
blue = _ref5.blue, | ||
_ref5$alpha = _ref5.alpha, | ||
alpha = _ref5$alpha === undefined ? 1 : _ref5$alpha; | ||
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
// eslint-disable-line max-params | ||
var hue = rgb2hue(red, green, blue, fallback); | ||
var whiteness = rgb2whiteness(red, green, blue); | ||
var value = rgb2value(red, green, blue); | ||
var lightness = wv2lightness(whiteness, value); | ||
var saturation = lvw2saturation(lightness, value, whiteness); | ||
return { hue, saturation, lightness, alpha, colorspace: 'hsl' }; | ||
return { hue, whiteness, blackness, alpha: color.alpha, colorspace: 'hwb' }; | ||
} | ||
/* Convert RGB to HWB | ||
/* ========================================================================== */ | ||
function rgb2hwb(_ref6) { | ||
var red = _ref6.red, | ||
green = _ref6.green, | ||
blue = _ref6.blue, | ||
_ref6$alpha = _ref6.alpha, | ||
alpha = _ref6$alpha === undefined ? 1 : _ref6$alpha; | ||
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; | ||
// eslint-disable-line max-params | ||
var hue = rgb2hue(red, green, blue, fallback); | ||
var whiteness = rgb2whiteness(red, green, blue); | ||
var value = rgb2value(red, green, blue); | ||
var blackness = 1 - value; | ||
return { hue, whiteness, blackness, alpha, colorspace: 'hwb' }; | ||
} | ||
/* Convert Hue to RGB | ||
/* ========================================================================== */ | ||
function hue2rgb(t1, t2, hue) { | ||
var huerange = hue < 0 ? hue + 6 : hue >= 6 ? hue - 6 : hue; | ||
var rgb = huerange < 1 ? (t2 - t1) * hue + t1 : hue < 3 ? t2 : hue < 4 ? (t2 - t1) * (4 - hue) + t1 : t1; | ||
return rgb; | ||
} | ||
/* Convert RGB to Hue | ||
/* ========================================================================== */ | ||
function rgb2hue(red, green, blue, fallback) { | ||
// eslint-disable-line max-params | ||
var whiteness = rgb2whiteness(red, green, blue); | ||
var value = rgb2value(red, green, blue); | ||
var chroma = vw2chroma(value, whiteness); | ||
if (chroma === 0) { | ||
return fallback; | ||
} else { | ||
var segment = value === red ? (green - blue) / chroma : value === green ? (blue - red) / chroma : (red - green) / chroma; | ||
var shift = value === red ? segment < 0 ? 360 / 60 : 0 / 60 : value === green ? 120 / 60 : 240 / 60; | ||
var hue = (segment + shift) * 60; | ||
return hue; | ||
} | ||
} | ||
/* Contrast functions | ||
@@ -457,5 +704,6 @@ /* ========================================================================== */ | ||
var hwb = color2hwb(color); | ||
var rgb = color2rgb(color); | ||
// compute the luminance of the color. | ||
var luminance = rgb2luminance(color.red, color.green, color.blue); | ||
var luminance = rgb2luminance(rgb.red, rgb.green, rgb.blue); | ||
@@ -467,3 +715,3 @@ // the maximum-contrast color, if it is less than .5 | ||
// otherwise, hwb(X, 0%, 100%), where X is the hue angle of the color | ||
} : { hue: hwb.hue, whiteness: 0, blackness: 1, alpha: hwb.alpha, colorspace: 'hwb' }; | ||
} : { hue: hwb.hue, whiteness: 0, blackness: 100, alpha: hwb.alpha, colorspace: 'hwb' }; | ||
@@ -479,3 +727,3 @@ // contrast ratio | ||
// color(maximum-contrast blend(minimum-contrast <percentage> hwb)) | ||
// color(maximum-contrast blend(minimum-contrast <percentage> hwb))); | ||
return _blend(maxContrastColor, minContrastColor, percentage, 'hwb', false); | ||
@@ -495,3 +743,3 @@ } | ||
// otherwise, if l2 is the relative luminance of the lighter of the colors | ||
: (l2 + 0.05) / (l2 + 0.05); | ||
: (l2 + 0.05) / (l1 + 0.05); | ||
} | ||
@@ -507,3 +755,5 @@ | ||
return 0.2126 * redLuminance + 0.7152 * greenLuminance + 0.0722 * blueLuminance; | ||
var luminance = 0.2126 * redLuminance + 0.7152 * greenLuminance + 0.0722 * blueLuminance; | ||
return luminance; | ||
} | ||
@@ -513,3 +763,5 @@ | ||
// https://drafts.csswg.org/css-color/#luminance | ||
return value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4); | ||
var luminance = value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4); | ||
return luminance; | ||
} | ||
@@ -528,3 +780,3 @@ | ||
// find the color with the smallest contrast ratio with the base color that is greater than 4.5 | ||
while (Math.abs(minW - maxW) > 1 || Math.abs(minB - maxB) > 1) { | ||
while (Math.abs(minW - maxW) > 100 || Math.abs(minB - maxB) > 100) { | ||
var midW = Math.round((maxW + minW) / 2); | ||
@@ -548,51 +800,76 @@ var midB = Math.round((maxB + minB) / 2); | ||
/* Convert RGB to Whiteness | ||
/* Match | ||
/* ========================================================================== */ | ||
function rgb2whiteness(red, green, blue) { | ||
return Math.min(red, green, blue); | ||
} | ||
var blueGreenRedMatch = /^(blue|green|red)$/i; | ||
/* Convert RGB to Value | ||
/* Stringifiers | ||
/* ========================================================================== */ | ||
function rgb2value(red, green, blue) { | ||
return Math.max(red, green, blue); | ||
function color2string(color) { | ||
return color.colorspace === 'hsl' ? color2hslString(color) : color.colorspace === 'hwb' ? color2hwbString(color) : color2rgbString(color); | ||
} | ||
/* Convert Whiteness and Value to Lightness | ||
/* ========================================================================== */ | ||
function color2hslString(color) { | ||
var hsl = color2hsl(color); | ||
var isOpaque = hsl.alpha === 100; | ||
var hue = hsl.hue; | ||
var saturation = Math.round(hsl.saturation * 10000000000) / 10000000000; | ||
var lightness = Math.round(hsl.lightness * 10000000000) / 10000000000; | ||
var alpha = Math.round(hsl.alpha * 10000000000) / 10000000000; | ||
function wv2lightness(whiteness, value) { | ||
return (whiteness + value) / 2; | ||
return `hsl(${hue} ${saturation}% ${lightness}%${isOpaque ? '' : ` / ${alpha}%`})`; | ||
} | ||
/* Convert Value and Whiteness to Chroma | ||
/* ========================================================================== */ | ||
function color2hwbString(color) { | ||
var hwb = color2hwb(color); | ||
var isOpaque = hwb.alpha === 100; | ||
var hue = hwb.hue; | ||
var whiteness = Math.round(hwb.whiteness * 10000000000) / 10000000000; | ||
var blackness = Math.round(hwb.blackness * 10000000000) / 10000000000; | ||
var alpha = Math.round(hwb.alpha * 10000000000) / 10000000000; | ||
function vw2chroma(value, whiteness) { | ||
return value - whiteness; | ||
return `hwb(${hue} ${whiteness}% ${blackness}%${isOpaque ? '' : ` / ${alpha}%`})`; | ||
} | ||
/* Convert Lightness, Value, and Whiteness to Saturation | ||
/* ========================================================================== */ | ||
function color2rgbString(color) { | ||
var rgb = color2rgb(color); | ||
var isOpaque = rgb.alpha === 100; | ||
var red = Math.round(rgb.red * 10000000000) / 10000000000; | ||
var green = Math.round(rgb.green * 10000000000) / 10000000000; | ||
var blue = Math.round(rgb.blue * 10000000000) / 10000000000; | ||
var alpha = Math.round(rgb.alpha * 10000000000) / 10000000000; | ||
function lvw2saturation(lightness, value, whiteness) { | ||
return whiteness === value ? 0 : lightness < 0.5 ? (value - whiteness) / (value + whiteness) : (value - whiteness) / (2 - value - whiteness); | ||
return `rgb(${red}% ${green}% ${blue}%${isOpaque ? '' : ` / ${alpha}%`})`; | ||
} | ||
/* Round to decimal place | ||
/* ========================================================================== */ | ||
function color2legacyString(color) { | ||
return color.colorspace === 'hsl' ? color2hslLegacyString(color) : color2rgbLegacyString(color); | ||
} | ||
function round(value, decimals) { | ||
return Number(`${Math.round(`${value}e${decimals}`)}e-${decimals}`); | ||
function color2rgbLegacyString(color) { | ||
var rgb = color2rgb(color); | ||
var isOpaque = rgb.alpha === 100; | ||
var name = isOpaque ? 'rgb' : 'rgba'; | ||
var red = Math.round(rgb.red * 255 / 100); | ||
var green = Math.round(rgb.green * 255 / 100); | ||
var blue = Math.round(rgb.blue * 255 / 100); | ||
var alpha = Math.round(rgb.alpha / 100 * 10000000000) / 10000000000; | ||
return `${name}(${red}, ${green}, ${blue}${isOpaque ? '' : `, ${alpha}`})`; | ||
} | ||
/* Match | ||
/* ========================================================================== */ | ||
function color2hslLegacyString(color) { | ||
var hsl = color2hsl(color); | ||
var isOpaque = hsl.alpha === 100; | ||
var name = isOpaque ? 'hsl' : 'hsla'; | ||
var hue = hsl.hue; | ||
var saturation = Math.round(hsl.saturation * 10000000000) / 10000000000; | ||
var lightness = Math.round(hsl.lightness * 10000000000) / 10000000000; | ||
var alpha = Math.round(hsl.alpha / 100 * 10000000000) / 10000000000; | ||
var blueGreenRedMatch = /^(blue|green|red)$/i; | ||
return `${name}(${hue}, ${saturation}%, ${lightness}%${isOpaque ? '' : `, ${alpha}`})`; | ||
} | ||
function manageUnresolved(node, opts, word, message) { | ||
// eslint-disable-line max-params | ||
if ('warn' === opts.unresolved) { | ||
@@ -605,3 +882,3 @@ opts.decl.warn(opts.result, message, { word }); | ||
var _slicedToArray$1 = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var _slicedToArray$2 = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
@@ -656,7 +933,11 @@ function _toArray(arr) { return Array.isArray(arr) ? arr : Array.from(arr); } | ||
var _transformArgsByParam = transformArgsByParams(node, [ | ||
// [ <percentage>{3} | <rgb-value>{3} ] [ / <alpha-value> ]? | ||
[transformRGBValue, transformRGBValue, transformRGBValue, isSlash, transformAlpha], | ||
// <number>#{3} [ , <alpha-value> ]? ] | ||
[transformRGBValue, isComma, transformRGBValue, isComma, transformRGBValue, isComma, transformAlpha]]), | ||
_transformArgsByParam2 = _slicedToArray$1(_transformArgsByParam, 4), | ||
// <percentage> <percentage> <percentage> [ , <alpha-value> ]? | ||
[transformPercentage, transformPercentage, transformPercentage, isSlash, transformAlpha], | ||
// <number> <number> <number> [ , <alpha-value> ]? | ||
[transformRGBNumber, transformRGBNumber, transformRGBNumber, isSlash, transformAlpha], | ||
// <percentage> , <percentage> , <percentage> [ , <alpha-value> ]? | ||
[transformPercentage, isComma, transformPercentage, isComma, transformPercentage, isComma, transformAlpha], | ||
// <number> , <number> , <number> [ , <alpha-value> ]? | ||
[transformRGBNumber, isComma, transformRGBNumber, isComma, transformRGBNumber, isComma, transformAlpha]]), | ||
_transformArgsByParam2 = _slicedToArray$2(_transformArgsByParam, 4), | ||
red = _transformArgsByParam2[0], | ||
@@ -666,3 +947,3 @@ green = _transformArgsByParam2[1], | ||
_transformArgsByParam3 = _transformArgsByParam2[3], | ||
alpha = _transformArgsByParam3 === undefined ? 1 : _transformArgsByParam3; | ||
alpha = _transformArgsByParam3 === undefined ? 100 : _transformArgsByParam3; | ||
@@ -681,7 +962,7 @@ if (red !== undefined) { | ||
var _transformArgsByParam4 = transformArgsByParams(node, [ | ||
// <hue> <percentage>{2} [ / <alpha-value> ]? | ||
// <hue> <percentage> <percentage> [ / <alpha-value> ]? | ||
[transformHue, transformPercentage, transformPercentage, isSlash, transformAlpha], | ||
// hue, <percentage>#{2} [ , <alpha-value> ]? ] | ||
// <hue> , <percentage> , <percentage> [ , <alpha-value> ]? | ||
[transformHue, isComma, transformPercentage, isComma, transformPercentage, isComma, transformAlpha]]), | ||
_transformArgsByParam5 = _slicedToArray$1(_transformArgsByParam4, 4), | ||
_transformArgsByParam5 = _slicedToArray$2(_transformArgsByParam4, 4), | ||
hue = _transformArgsByParam5[0], | ||
@@ -691,3 +972,3 @@ saturation = _transformArgsByParam5[1], | ||
_transformArgsByParam6 = _transformArgsByParam5[3], | ||
alpha = _transformArgsByParam6 === undefined ? 1 : _transformArgsByParam6; | ||
alpha = _transformArgsByParam6 === undefined ? 100 : _transformArgsByParam6; | ||
@@ -708,3 +989,3 @@ if (lightness !== undefined) { | ||
[transformHue, transformPercentage, transformPercentage, isSlash, transformAlpha]]), | ||
_transformArgsByParam8 = _slicedToArray$1(_transformArgsByParam7, 4), | ||
_transformArgsByParam8 = _slicedToArray$2(_transformArgsByParam7, 4), | ||
hue = _transformArgsByParam8[0], | ||
@@ -714,3 +995,3 @@ whiteness = _transformArgsByParam8[1], | ||
_transformArgsByParam9 = _transformArgsByParam8[3], | ||
alpha = _transformArgsByParam9 === undefined ? 1 : _transformArgsByParam9; | ||
alpha = _transformArgsByParam9 === undefined ? 100 : _transformArgsByParam9; | ||
@@ -735,3 +1016,9 @@ if (blackness !== undefined) { | ||
if (colorOrHueNode !== undefined) { | ||
var color = isHue(colorOrHueNode) ? new Color({ hue: transformHue(colorOrHueNode, opts), saturation: 1, lightness: 0.5, alpha: 1, colorspace: 'hsl' }) : transformColor(colorOrHueNode, opts); | ||
var color = isHue(colorOrHueNode) ? new Color({ | ||
hue: transformHue(colorOrHueNode, opts), | ||
saturation: 100, | ||
lightness: 50, | ||
alpha: 100, | ||
colorspace: 'hsl' | ||
}) : transformColor(colorOrHueNode, opts); | ||
@@ -755,3 +1042,3 @@ if (color) { | ||
var _slice = (node.value.match(hexColorMatch) || []).slice(1), | ||
_slice2 = _slicedToArray$1(_slice, 8), | ||
_slice2 = _slicedToArray$2(_slice, 8), | ||
r = _slice2[0], | ||
@@ -767,6 +1054,6 @@ g = _slice2[1], | ||
var color = new Color({ | ||
red: rr !== undefined ? parseInt(rr, 16) / 255 : r !== undefined ? parseInt(r + r, 16) / 255 : 0, | ||
green: gg !== undefined ? parseInt(gg, 16) / 255 : g !== undefined ? parseInt(g + g, 16) / 255 : 0, | ||
blue: bb !== undefined ? parseInt(bb, 16) / 255 : b !== undefined ? parseInt(b + b, 16) / 255 : 0, | ||
alpha: aa !== undefined ? parseInt(aa, 16) / 255 : a !== undefined ? parseInt(a + a, 16) / 255 : 1 | ||
red: rr !== undefined ? parseInt(rr, 16) / 2.55 : r !== undefined ? parseInt(r + r, 16) / 2.55 : 0, | ||
green: gg !== undefined ? parseInt(gg, 16) / 2.55 : g !== undefined ? parseInt(g + g, 16) / 2.55 : 0, | ||
blue: bb !== undefined ? parseInt(bb, 16) / 2.55 : b !== undefined ? parseInt(b + b, 16) / 2.55 : 0, | ||
alpha: aa !== undefined ? parseInt(aa, 16) / 2.55 : a !== undefined ? parseInt(a + a, 16) / 2.55 : 100 | ||
}); | ||
@@ -784,8 +1071,15 @@ | ||
// <named-color> | ||
var _names$node$value = _slicedToArray$1(names[node.value], 3), | ||
red = _names$node$value[0], | ||
green = _names$node$value[1], | ||
blue = _names$node$value[2]; | ||
var _convertNtoRGB = convertNtoRGB(node.value), | ||
_convertNtoRGB2 = _slicedToArray$2(_convertNtoRGB, 3), | ||
red = _convertNtoRGB2[0], | ||
green = _convertNtoRGB2[1], | ||
blue = _convertNtoRGB2[2]; | ||
var color = new Color({ red: red / 255, green: green / 255, blue: blue / 255, alpha: 1, colorspace: 'rgb' }); | ||
var color = new Color({ | ||
red: red / 2.55, | ||
green: green / 2.55, | ||
blue: blue / 2.55, | ||
alpha: 100, | ||
colorspace: 'rgb' | ||
}); | ||
@@ -830,16 +1124,24 @@ return color; | ||
function transformAlphaBlueGreenRedAdjuster(base, node, opts) { | ||
var _transformArgsByParam10 = transformArgsByParams(node, alphaMatch.test(node.value) ? [ | ||
var _transformArgsByParam10 = transformArgsByParams(node, alphaMatch.test(node.value) | ||
// a/alpha adjustments | ||
? [ | ||
// [ + | - ] <alpha-value> | ||
[transformMinusPlusOperator, transformAlpha], | ||
// * <alpha-value> | ||
// * <percentage> | ||
[transformTimesOperator, transformPercentage], | ||
// <alpha-value> | ||
[transformAlpha]] : [ | ||
// [ + | - ] <rgb-value> | ||
[transformMinusPlusOperator, transformRGBValue], | ||
[transformAlpha]] | ||
// blue/green/red adjustments | ||
: [ | ||
// [ + | - ] <percentage> | ||
[transformMinusPlusOperator, transformPercentage], | ||
// [ + | - ] <number> | ||
[transformMinusPlusOperator, transformRGBNumber], | ||
// * <percentage> | ||
[transformTimesOperator, transformPercentage], | ||
// <rgb-value> | ||
[transformRGBValue]]), | ||
_transformArgsByParam11 = _slicedToArray$1(_transformArgsByParam10, 2), | ||
// <percentage> | ||
[transformPercentage], | ||
// <number> | ||
[transformRGBNumber]]), | ||
_transformArgsByParam11 = _slicedToArray$2(_transformArgsByParam10, 2), | ||
operatorOrValue = _transformArgsByParam11[0], | ||
@@ -854,3 +1156,3 @@ adjustment = _transformArgsByParam11[1]; | ||
var modifiedValue = adjustment ? operatorOrValue === '+' ? existingValue + adjustment : operatorOrValue === '-' ? existingValue - adjustment : operatorOrValue === '*' ? existingValue * adjustment : adjustment : operatorOrValue; | ||
var modifiedValue = adjustment !== undefined ? operatorOrValue === '+' ? existingValue + Number(adjustment) : operatorOrValue === '-' ? existingValue - Number(adjustment) : operatorOrValue === '*' ? existingValue * Number(adjustment) : Number(adjustment) : Number(operatorOrValue); | ||
@@ -868,6 +1170,6 @@ var modifiedColor = base[channel](modifiedValue); | ||
var _transformArgsByParam12 = transformArgsByParams(node, [ | ||
// [ + | - ] <percentage> <percentage> <percentage> | ||
[transformMinusPlusOperator, transformPercentage, transformPercentage, transformPercentage], | ||
// [ + | - ] <number> <number> <number> | ||
[transformMinusPlusOperator, transformRGBNumber, transformRGBNumber, transformRGBNumber], | ||
// [ + | - ] <percentage> <percentage> <percentage> | ||
[transformMinusPlusOperator, transformPercentage, transformPercentage, transformPercentage], | ||
// [ + | - ] <hash-token> | ||
@@ -877,3 +1179,3 @@ [transformMinusPlusOperator, transformHexColor], | ||
[transformTimesOperator, transformPercentage]]), | ||
_transformArgsByParam13 = _slicedToArray$1(_transformArgsByParam12, 4), | ||
_transformArgsByParam13 = _slicedToArray$2(_transformArgsByParam12, 4), | ||
arg1 = _transformArgsByParam13[0], | ||
@@ -897,3 +1199,3 @@ arg2 = _transformArgsByParam13[1], | ||
} else { | ||
return manageUnresolved(node, opts, node.value, `Expected a valid rgb() adjuster)`); | ||
return manageUnresolved(node, opts, node.value, `Expected a valid rgb() adjuster`); | ||
} | ||
@@ -904,5 +1206,4 @@ } | ||
function transformBlendAdjuster(base, node, isAlphaBlend, opts) { | ||
// eslint-disable-line max-params | ||
var _transformArgsByParam14 = transformArgsByParams(node, [[transformColor, transformPercentage, transformColorSpace]]), | ||
_transformArgsByParam15 = _slicedToArray$1(_transformArgsByParam14, 3), | ||
_transformArgsByParam15 = _slicedToArray$2(_transformArgsByParam14, 3), | ||
color = _transformArgsByParam15[0], | ||
@@ -927,3 +1228,3 @@ percentage = _transformArgsByParam15[1], | ||
[transformPercentage]]), | ||
_transformArgsByParam18 = _slicedToArray$1(_transformArgsByParam17, 1), | ||
_transformArgsByParam18 = _slicedToArray$2(_transformArgsByParam17, 1), | ||
percentage = _transformArgsByParam18[0]; | ||
@@ -947,14 +1248,11 @@ | ||
[transformHue]]), | ||
_transformArgsByParam20 = _slicedToArray$1(_transformArgsByParam19, 2), | ||
_transformArgsByParam20 = _slicedToArray$2(_transformArgsByParam19, 2), | ||
operatorOrHue = _transformArgsByParam20[0], | ||
rawAdjustment = _transformArgsByParam20[1]; | ||
adjustment = _transformArgsByParam20[1]; | ||
if (operatorOrHue !== undefined) { | ||
var existingHue = base.hue(); | ||
var adjustment = parseFloat(rawAdjustment); | ||
var rawModifiedValue = adjustment ? operatorOrHue === '+' ? existingHue + adjustment : operatorOrHue === '-' ? existingHue - adjustment : operatorOrHue === '*' ? existingHue * adjustment : adjustment : parseFloat(operatorOrHue); | ||
var modifiedValue = adjustment !== undefined ? operatorOrHue === '+' ? existingHue + Number(adjustment) : operatorOrHue === '-' ? existingHue - Number(adjustment) : operatorOrHue === '*' ? existingHue * Number(adjustment) : Number(adjustment) : Number(operatorOrHue); | ||
var modifiedValue = rawModifiedValue < 0 ? 360 + rawModifiedValue % 360 : rawModifiedValue % 360; | ||
return base.hue(modifiedValue); | ||
@@ -971,11 +1269,10 @@ } else { | ||
var _transformArgsByParam21 = transformArgsByParams(node, [[transformMinusPlusTimesOperator, transformPercentage], [transformPercentage]]), | ||
_transformArgsByParam22 = _slicedToArray$1(_transformArgsByParam21, 2), | ||
_transformArgsByParam22 = _slicedToArray$2(_transformArgsByParam21, 2), | ||
operatorOrValue = _transformArgsByParam22[0], | ||
rawAdjustment = _transformArgsByParam22[1]; | ||
adjustment = _transformArgsByParam22[1]; | ||
if (operatorOrValue !== undefined) { | ||
var existingValue = base[channel](); | ||
var adjustment = parseFloat(rawAdjustment); | ||
var modifiedValue = adjustment ? operatorOrValue === '+' ? existingValue + adjustment : operatorOrValue === '-' ? existingValue - adjustment : operatorOrValue === '*' ? existingValue * adjustment : adjustment : parseFloat(operatorOrValue); | ||
var modifiedValue = adjustment !== undefined ? operatorOrValue === '+' ? existingValue + Number(adjustment) : operatorOrValue === '-' ? existingValue - Number(adjustment) : operatorOrValue === '*' ? existingValue * Number(adjustment) : Number(adjustment) : Number(operatorOrValue); | ||
@@ -995,7 +1292,7 @@ return base[channel](modifiedValue); | ||
[transformPercentage]]), | ||
_transformArgsByParam24 = _slicedToArray$1(_transformArgsByParam23, 1), | ||
_transformArgsByParam24 = _slicedToArray$2(_transformArgsByParam23, 1), | ||
percentage = _transformArgsByParam24[0]; | ||
if (percentage !== undefined) { | ||
var modifiedValue = parseFloat(percentage); | ||
var modifiedValue = Number(percentage); | ||
@@ -1025,3 +1322,3 @@ return base[channel](modifiedValue); | ||
// <number> | ||
return parseFloat(node.value); | ||
return node.value * 100; | ||
} else if (isPercentage(node)) { | ||
@@ -1035,20 +1332,7 @@ // <percentage> | ||
// return a transformed rgb value | ||
function transformRGBValue(node, opts) { | ||
if (isNumber(node)) { | ||
// <rgba-number> | ||
return transformRGBNumber(node, opts); | ||
} else if (isPercentage(node)) { | ||
// <percentage> | ||
return transformPercentage(node, opts); | ||
} else { | ||
return manageUnresolved(node, opts, node.value, `Expected a valid RGB value)`); | ||
} | ||
} | ||
// return a transformed rgb number | ||
function transformRGBNumber(node, opts) { | ||
if (isNumber(node)) { | ||
// <rgba-number> | ||
return parseFloat(node.value) / 255; | ||
// <number> | ||
return node.value / 2.55; | ||
} else { | ||
@@ -1062,4 +1346,18 @@ return manageUnresolved(node, opts, node.value, `Expected a valid RGB value)`); | ||
if (isHue(node)) { | ||
// <hue> | ||
return parseFloat(node.value); | ||
// <hue> = <number> | <angle> | ||
var unit = node.unit.toLowerCase(); | ||
if (unit === 'grad') { | ||
// if <angle> = <gradian> (400 per circle) | ||
return convertGtoD(node.value); | ||
} else if (unit === 'rad') { | ||
// if <angle> = <radian> (2π per circle) | ||
return convertRtoD(node.value); | ||
} else if (unit === 'turn') { | ||
// if <angle> = <turn> (1 per circle) | ||
return convertTtoD(node.value); | ||
} else { | ||
// if <angle> = [ <degree> | <number> ] (360 per circle) | ||
return convertDtoD(node.value); | ||
} | ||
} else { | ||
@@ -1074,3 +1372,3 @@ return manageUnresolved(node, opts, node.value, `Expected a valid hue`); | ||
// <percentage> | ||
return parseFloat(node.value) / 100; | ||
return Number(node.value); | ||
} else { | ||
@@ -1205,3 +1503,3 @@ return manageUnresolved(node, opts, node.value, `Expected a valid hue`); | ||
function isNamedColor(node) { | ||
return Object(node).type === 'word' && node.value in names; | ||
return Object(node).type === 'word' && Boolean(convertNtoRGB(node.value)); | ||
} | ||
@@ -1226,3 +1524,3 @@ | ||
function isHue(node) { | ||
return Object(node).type === 'number' && /^(deg)?$/.test(node.unit); | ||
return Object(node).type === 'number' && hueUnitMatch.test(node.unit); | ||
} | ||
@@ -1262,3 +1560,3 @@ | ||
function isPercentage(node) { | ||
return Object(node).type === 'number' && node.unit === '%'; | ||
return Object(node).type === 'number' && (node.unit === '%' || node.value === '0'); | ||
} | ||
@@ -1278,2 +1576,3 @@ | ||
var hslaMatch = /^hsla?$/i; | ||
var hueUnitMatch = /^(deg|grad|rad|turn)?$/i; | ||
var hueMatch = /^h(ue)?$/i; | ||
@@ -1293,3 +1592,3 @@ var hwbMatch = /^hwb$/i; | ||
var stringifierOpt = Object(opts).stringifier || function (color) { | ||
return color.toRGBLegacy(); | ||
return color.toLegacy(); | ||
}; | ||
@@ -1296,0 +1595,0 @@ |
@@ -9,3 +9,3 @@ // tooling | ||
const unresolvedOpt = String(Object(opts).unresolved || 'throw').toLowerCase(); | ||
const stringifierOpt = Object(opts).stringifier || (color => color.toRGBLegacy()); | ||
const stringifierOpt = Object(opts).stringifier || (color => color.toLegacy()); | ||
@@ -12,0 +12,0 @@ return (root, result) => { |
407
lib/color.js
@@ -0,1 +1,3 @@ | ||
import { convertRGBtoHSL, convertRGBtoHWB, convertHSLtoRGB, convertHSLtoHWB, convertHWBtoRGB, convertHWBtoHSL, convertRGBtoH } from './conversions'; | ||
export default class Color { | ||
@@ -6,3 +8,3 @@ constructor(color) { | ||
if (color.colorspace === 'rgb') { | ||
this.color.hue = rgb2hue(color.red, color.green, color.blue, color.hue || 0); | ||
this.color.hue = convertRGBtoH(color.red, color.green, color.blue, color.hue || 0); | ||
} | ||
@@ -101,4 +103,4 @@ } | ||
const hwb = color2hwb(this.color); | ||
const shade = { hue: 0, whiteness: 1, blackness: 0, colorspace: 'hwb' }; | ||
const colorspace = 'hwb'; | ||
const shade = { hue: 0, whiteness: 0, blackness: 100, colorspace: 'hwb' }; | ||
const colorspace = 'rgb'; | ||
@@ -112,4 +114,4 @@ return percentage === undefined | ||
const hwb = color2hwb(this.color); | ||
const tint = { hue: 0, whiteness: 0, blackness: 1, colorspace: 'hwb' }; | ||
const colorspace = 'hwb'; | ||
const tint = { hue: 0, whiteness: 100, blackness: 0, colorspace: 'hwb' }; | ||
const colorspace = 'rgb'; | ||
@@ -130,64 +132,23 @@ return percentage === undefined | ||
toHSL() { | ||
const color = color2hsl(this.color); | ||
const isOpaque = color.alpha === 1; | ||
const hue = color.hue; | ||
const saturation = round(color.saturation * 100, 4); | ||
const lightness = round(color.lightness * 100, 4); | ||
const alpha = round(color.alpha * 100, 4); | ||
return `hsl(${hue} ${saturation}% ${lightness}%${isOpaque | ||
? '' | ||
: ` / ${alpha}%`})`; | ||
return color2hslString(this.color); | ||
} | ||
toHWB() { | ||
const color = color2hwb(this.color); | ||
const isOpaque = color.alpha === 1; | ||
const hue = color.hue; | ||
const whiteness = round(color.whiteness * 100, 4); | ||
const blackness = round(color.blackness * 100, 4); | ||
const alpha = round(color.alpha * 100, 4); | ||
return color2hwbString(this.color); | ||
} | ||
return `hwb(${hue} ${whiteness}% ${blackness}%${isOpaque | ||
? '' | ||
: ` / ${alpha}%`})`; | ||
toLegacy() { | ||
return color2legacyString(this.color); | ||
} | ||
toRGB() { | ||
const color = color2rgb(this.color); | ||
const isOpaque = color.alpha === 1; | ||
const red = round(color.red * 100, 4); | ||
const green = round(color.green * 100, 4); | ||
const blue = round(color.blue * 100, 4); | ||
const alpha = round(color.alpha * 100, 4); | ||
return `rgb(${red}% ${green}% ${blue}%${isOpaque | ||
? '' | ||
: ` / ${alpha}%`})`; | ||
return color2rgbString(this.color); | ||
} | ||
toRGBLegacy() { | ||
const color = color2rgb(this.color); | ||
const isOpaque = color.alpha === 1; | ||
const name = isOpaque ? 'rgb' : 'rgba'; | ||
const red = round(color.red * 255, 0); | ||
const green = round(color.green * 255, 0); | ||
const blue = round(color.blue * 255, 0); | ||
const alpha = round(color.alpha, 4); | ||
return `${name}(${red}, ${green}, ${blue}${isOpaque | ||
? '' | ||
: `, ${alpha}`})`; | ||
return color2rgbLegacyString(this.color); | ||
} | ||
toString(rawcolorspace) { | ||
const colorspace = rawcolorspace || this.color.colorspace; | ||
const color = colorspace === 'hsl' | ||
? this.toHSL() | ||
: colorspace === 'hwb' | ||
? this.toHWB() | ||
: this.toRGB(); | ||
return color; | ||
toString() { | ||
return color2string(this.color); | ||
} | ||
@@ -199,4 +160,5 @@ } | ||
function blend(base, color, percentage, colorspace, isBlendingAlpha) { // eslint-disable-line max-params | ||
const subtraction = 1 - percentage; | ||
function blend(base, color, percentage, colorspace, isBlendingAlpha) { | ||
const addition = percentage / 100; | ||
const subtraction = 1 - addition; | ||
@@ -208,6 +170,8 @@ if (colorspace === 'hsl') { | ||
const [hue, saturation, lightness, alpha] = [ | ||
h1 * percentage + h2 * subtraction, | ||
s1 * percentage + s2 * subtraction, | ||
l1 * percentage + l2 * subtraction, | ||
isBlendingAlpha ? a1 * percentage + a2 * subtraction : a1 | ||
h1 * subtraction + h2 * addition, | ||
s1 * subtraction + s2 * addition, | ||
l1 * subtraction + l2 * addition, | ||
isBlendingAlpha | ||
? a1 * subtraction + a2 * addition | ||
: a1 | ||
]; | ||
@@ -221,6 +185,8 @@ | ||
const [hue, whiteness, blackness, alpha] = [ | ||
h1 * percentage + h2 * subtraction, | ||
w1 * percentage + w2 * subtraction, | ||
b1 * percentage + b2 * subtraction, | ||
isBlendingAlpha ? a1 * percentage + a2 * subtraction : a1 | ||
h1 * subtraction + h2 * addition, | ||
w1 * subtraction + w2 * addition, | ||
b1 * subtraction + b2 * addition, | ||
isBlendingAlpha | ||
? a1 * subtraction + a2 * addition | ||
: a1 | ||
]; | ||
@@ -234,6 +200,8 @@ | ||
const [red, green, blue, alpha] = [ | ||
r1 * percentage + r2 * subtraction, | ||
g1 * percentage + g2 * subtraction, | ||
b1 * percentage + b2 * subtraction, | ||
isBlendingAlpha ? a1 * percentage + a2 * subtraction : a1 | ||
r1 * subtraction + r2 * addition, | ||
g1 * subtraction + g2 * addition, | ||
b1 * subtraction + b2 * addition, | ||
isBlendingAlpha | ||
? a1 * subtraction + a2 * addition | ||
: a1 | ||
]; | ||
@@ -257,21 +225,11 @@ | ||
// value of the channel | ||
const adjustment = channels[channel]; | ||
// normalized value of the channel | ||
const value = normalize(channels[channel], channel); | ||
// value limitations | ||
const min = 0; | ||
const max = isHue ? 360 : 1; | ||
// updated value | ||
const value = Math.min(Math.max(parseFloat(adjustment), min), max); | ||
// assign channel to new object | ||
if (isHue) { | ||
color.hue = value; | ||
} else { | ||
color[channel] = value; | ||
color[channel] = value; | ||
color.hue = isRGB | ||
? rgb2hue(color.red, color.green, color.blue, base.hue || 0) | ||
: base.hue; | ||
if (isRGB) { | ||
// conditionally preserve the hue | ||
color.hue = convertRGBtoH(color.red, color.green, color.blue, base.hue || 0); | ||
} | ||
@@ -284,148 +242,50 @@ } | ||
/* Convert colors | ||
/* ========================================================================== */ | ||
function normalize(value, channel) { | ||
// detect channel | ||
const isHue = channel === 'hue'; | ||
function color2hsl(color) { | ||
return color.colorspace === 'rgb' | ||
? rgb2hsl(color, color.hue) | ||
: color.colorspace === 'hwb' | ||
? rgb2hsl(hwb2rgb(color), color.hue) | ||
: color; | ||
} | ||
// value limitations | ||
const min = 0; | ||
const max = isHue ? 360 : 100; | ||
function color2hwb(color) { | ||
return color.colorspace === 'rgb' | ||
? rgb2hwb(color, color.hue) | ||
: color.colorspace === 'hsl' | ||
? rgb2hwb(hsl2rgb(color), color.hue) | ||
: color; | ||
} | ||
const normalizedValue = Math.min(Math.max(isHue | ||
? value % 360 | ||
: value, min), max); | ||
function color2rgb(color) { | ||
return color.colorspace === 'hsl' | ||
? hsl2rgb(color) | ||
: color.colorspace === 'hwb' | ||
? hwb2rgb(color) | ||
: color; | ||
return normalizedValue; | ||
} | ||
/* Convert HSL to RGB | ||
/* Convert colors | ||
/* ========================================================================== */ | ||
function hsl2rgb({ hue, saturation, lightness, alpha = 1 }) { | ||
const t2 = lightness <= 0.5 | ||
? lightness * (saturation + 1) | ||
: lightness + saturation - lightness * saturation; | ||
function color2rgb(color) { | ||
const [ red, green, blue ] = color.colorspace === 'hsl' | ||
? convertHSLtoRGB(color.hue, color.saturation, color.lightness) | ||
: color.colorspace === 'hwb' | ||
? convertHWBtoRGB(color.hue, color.whiteness, color.blackness) | ||
: [ color.red, color.green, color.blue ]; | ||
const t1 = lightness * 2 - t2; | ||
const red = hue2rgb(t1, t2, hue / 60 + 2); | ||
const green = hue2rgb(t1, t2, hue / 60); | ||
const blue = hue2rgb(t1, t2, hue / 60 - 2); | ||
return { hue, red, green, blue, alpha, colorspace: 'rgb' }; | ||
return { red, green, blue, hue: color.hue, alpha: color.alpha, colorspace: 'rgb' }; | ||
} | ||
/* Convert HWB to RGB | ||
/* ========================================================================== */ | ||
function color2hsl(color) { | ||
const [ hue, saturation, lightness ] = color.colorspace === 'rgb' | ||
? convertRGBtoHSL(color.red, color.green, color.blue, color.hue) | ||
: color.colorspace === 'hwb' | ||
? convertHWBtoHSL(color.hue, color.whiteness, color.blackness) | ||
: [ color.hue, color.saturation, color.lightness ]; | ||
function hwb2rgb({ hue, whiteness, blackness, alpha = 1 }) { | ||
const ratio = whiteness + blackness; | ||
const rwhiteness = ratio > 1 ? whiteness / ratio : whiteness; | ||
const rblackness = ratio > 1 ? blackness / ratio : blackness; | ||
const value = 1 - rblackness; | ||
const hexagon = 6 * hue / 360; | ||
const hexagonFloor = Math.floor(hexagon); | ||
const hexagonF = hexagonFloor % 6 ? 1 - (hexagon - hexagonFloor) : hexagon - hexagonFloor; | ||
const interpolation = rwhiteness + hexagonF * (value - rwhiteness); | ||
const [red, green, blue] = hexagonFloor % 6 === 5 | ||
? [value, rwhiteness, interpolation] | ||
: hexagonFloor % 6 === 4 | ||
? [interpolation, rwhiteness, value] | ||
: hexagonFloor % 6 === 3 | ||
? [rwhiteness, interpolation, value] | ||
: hexagonFloor % 6 === 2 | ||
? [rwhiteness, value, interpolation] | ||
: hexagonFloor % 6 === 1 | ||
? [interpolation, value, rwhiteness] | ||
: [value, interpolation, rwhiteness]; | ||
return { hue, red, green, blue, alpha, colorspace: 'rgb' }; | ||
return { hue, saturation, lightness, alpha: color.alpha, colorspace: 'hsl' }; | ||
} | ||
/* Convert RGB to HSL | ||
/* ========================================================================== */ | ||
function color2hwb(color) { | ||
const [ hue, whiteness, blackness ] = color.colorspace === 'rgb' | ||
? convertRGBtoHWB(color.red, color.green, color.blue, color.hue) | ||
: color.colorspace === 'hsl' | ||
? convertHSLtoHWB(color.hue, color.saturation, color.lightness) | ||
: [ color.hue, color.whiteness, color.blackness ]; | ||
function rgb2hsl({ red, green, blue, alpha = 1 }, fallback = 0) { // eslint-disable-line max-params | ||
const hue = rgb2hue(red, green, blue, fallback); | ||
const whiteness = rgb2whiteness(red, green, blue); | ||
const value = rgb2value(red, green, blue); | ||
const lightness = wv2lightness(whiteness, value); | ||
const saturation = lvw2saturation(lightness, value, whiteness); | ||
return { hue, saturation, lightness, alpha, colorspace: 'hsl' }; | ||
return { hue, whiteness, blackness, alpha: color.alpha, colorspace: 'hwb' }; | ||
} | ||
/* Convert RGB to HWB | ||
/* ========================================================================== */ | ||
function rgb2hwb({ red, green, blue, alpha = 1 }, fallback = 0) { // eslint-disable-line max-params | ||
const hue = rgb2hue(red, green, blue, fallback); | ||
const whiteness = rgb2whiteness(red, green, blue); | ||
const value = rgb2value(red, green, blue); | ||
const blackness = 1 - value; | ||
return { hue, whiteness, blackness, alpha, colorspace: 'hwb' }; | ||
} | ||
/* Convert Hue to RGB | ||
/* ========================================================================== */ | ||
function hue2rgb(t1, t2, hue) { | ||
const huerange = hue < 0 ? hue + 6 : hue >= 6 ? hue - 6 : hue; | ||
const rgb = huerange < 1 | ||
? (t2 - t1) * hue + t1 | ||
: hue < 3 | ||
? t2 | ||
: hue < 4 | ||
? (t2 - t1) * (4 - hue) + t1 | ||
: t1; | ||
return rgb; | ||
} | ||
/* Convert RGB to Hue | ||
/* ========================================================================== */ | ||
function rgb2hue(red, green, blue, fallback) { // eslint-disable-line max-params | ||
const whiteness = rgb2whiteness(red, green, blue); | ||
const value = rgb2value(red, green, blue); | ||
const chroma = vw2chroma(value, whiteness); | ||
if (chroma === 0) { | ||
return fallback; | ||
} else { | ||
const segment = value === red | ||
? (green - blue) / chroma | ||
: value === green | ||
? (blue - red) / chroma | ||
: (red - green) / chroma; | ||
const shift = value === red | ||
? segment < 0 | ||
? 360 / 60 | ||
: 0 / 60 | ||
: value === green | ||
? 120 / 60 | ||
: 240 / 60; | ||
const hue = (segment + shift) * 60; | ||
return hue; | ||
} | ||
} | ||
/* Contrast functions | ||
@@ -437,5 +297,6 @@ /* ========================================================================== */ | ||
const hwb = color2hwb(color); | ||
const rgb = color2rgb(color); | ||
// compute the luminance of the color. | ||
const luminance = rgb2luminance(color.red, color.green, color.blue); | ||
const luminance = rgb2luminance(rgb.red, rgb.green, rgb.blue); | ||
@@ -447,3 +308,3 @@ // the maximum-contrast color, if it is less than .5 | ||
// otherwise, hwb(X, 0%, 100%), where X is the hue angle of the color | ||
: { hue: hwb.hue, whiteness: 0, blackness: 1, alpha: hwb.alpha, colorspace: 'hwb' }; | ||
: { hue: hwb.hue, whiteness: 0, blackness: 100, alpha: hwb.alpha, colorspace: 'hwb' }; | ||
@@ -459,3 +320,3 @@ // contrast ratio | ||
// color(maximum-contrast blend(minimum-contrast <percentage> hwb)) | ||
// color(maximum-contrast blend(minimum-contrast <percentage> hwb))); | ||
return blend(maxContrastColor, minContrastColor, percentage, 'hwb', false); | ||
@@ -475,3 +336,3 @@ } | ||
// otherwise, if l2 is the relative luminance of the lighter of the colors | ||
: (l2 + 0.05) / (l2 + 0.05); | ||
: (l2 + 0.05) / (l1 + 0.05); | ||
} | ||
@@ -487,3 +348,5 @@ | ||
// https://drafts.csswg.org/css-color/#luminance | ||
return 0.2126 * redLuminance + 0.7152 * greenLuminance + 0.0722 * blueLuminance; | ||
const luminance = 0.2126 * redLuminance + 0.7152 * greenLuminance + 0.0722 * blueLuminance; | ||
return luminance; | ||
} | ||
@@ -493,3 +356,5 @@ | ||
// https://drafts.csswg.org/css-color/#luminance | ||
return value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4); | ||
const luminance = value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) /1.055, 2.4); | ||
return luminance; | ||
} | ||
@@ -508,3 +373,3 @@ | ||
// find the color with the smallest contrast ratio with the base color that is greater than 4.5 | ||
while (Math.abs(minW - maxW) > 1 || Math.abs(minB - maxB) > 1) { | ||
while (Math.abs(minW - maxW) > 100 || Math.abs(minB - maxB) > 100) { | ||
const midW = Math.round((maxW + minW) / 2); | ||
@@ -528,51 +393,89 @@ const midB = Math.round((maxB + minB) / 2); | ||
/* Convert RGB to Whiteness | ||
/* Match | ||
/* ========================================================================== */ | ||
function rgb2whiteness(red, green, blue) { | ||
return Math.min(red, green, blue); | ||
} | ||
const blueGreenRedMatch = /^(blue|green|red)$/i; | ||
/* Convert RGB to Value | ||
/* Stringifiers | ||
/* ========================================================================== */ | ||
function rgb2value(red, green, blue) { | ||
return Math.max(red, green, blue) | ||
function color2string(color) { | ||
return color.colorspace === 'hsl' | ||
? color2hslString(color) | ||
: color.colorspace === 'hwb' | ||
? color2hwbString(color) | ||
: color2rgbString(color); | ||
} | ||
/* Convert Whiteness and Value to Lightness | ||
/* ========================================================================== */ | ||
function color2hslString(color) { | ||
const hsl = color2hsl(color); | ||
const isOpaque = hsl.alpha === 100; | ||
const hue = hsl.hue; | ||
const saturation = Math.round(hsl.saturation * 10000000000) / 10000000000; | ||
const lightness = Math.round(hsl.lightness * 10000000000) / 10000000000; | ||
const alpha = Math.round(hsl.alpha * 10000000000) / 10000000000; | ||
function wv2lightness(whiteness, value) { | ||
return (whiteness + value) / 2; | ||
return `hsl(${hue} ${saturation}% ${lightness}%${isOpaque | ||
? '' | ||
: ` / ${alpha}%`})`; | ||
} | ||
/* Convert Value and Whiteness to Chroma | ||
/* ========================================================================== */ | ||
function color2hwbString(color) { | ||
const hwb = color2hwb(color); | ||
const isOpaque = hwb.alpha === 100; | ||
const hue = hwb.hue; | ||
const whiteness = Math.round(hwb.whiteness * 10000000000) / 10000000000; | ||
const blackness = Math.round(hwb.blackness * 10000000000) / 10000000000; | ||
const alpha = Math.round(hwb.alpha * 10000000000) / 10000000000; | ||
function vw2chroma(value, whiteness) { | ||
return value - whiteness; | ||
return `hwb(${hue} ${whiteness}% ${blackness}%${isOpaque | ||
? '' | ||
: ` / ${alpha}%`})`; | ||
} | ||
/* Convert Lightness, Value, and Whiteness to Saturation | ||
/* ========================================================================== */ | ||
function color2rgbString(color) { | ||
const rgb = color2rgb(color); | ||
const isOpaque = rgb.alpha === 100; | ||
const red = Math.round(rgb.red * 10000000000) / 10000000000; | ||
const green = Math.round(rgb.green * 10000000000) / 10000000000; | ||
const blue = Math.round(rgb.blue * 10000000000) / 10000000000; | ||
const alpha = Math.round(rgb.alpha * 10000000000) / 10000000000; | ||
function lvw2saturation(lightness, value, whiteness) { | ||
return whiteness === value | ||
? 0 | ||
: lightness < 0.5 | ||
? (value - whiteness) / (value + whiteness) | ||
: (value - whiteness) / (2 - value - whiteness); | ||
return `rgb(${red}% ${green}% ${blue}%${isOpaque | ||
? '' | ||
: ` / ${alpha}%`})`; | ||
} | ||
/* Round to decimal place | ||
/* ========================================================================== */ | ||
function color2legacyString(color) { | ||
return color.colorspace === 'hsl' | ||
? color2hslLegacyString(color) | ||
: color2rgbLegacyString(color); | ||
} | ||
function round(value, decimals) { | ||
return Number(`${Math.round(`${value}e${decimals}`)}e-${decimals}`); | ||
function color2rgbLegacyString(color) { | ||
const rgb = color2rgb(color); | ||
const isOpaque = rgb.alpha === 100; | ||
const name = isOpaque ? 'rgb' : 'rgba'; | ||
const red = Math.round(rgb.red * 255 / 100); | ||
const green = Math.round(rgb.green * 255 / 100); | ||
const blue = Math.round(rgb.blue * 255 / 100); | ||
const alpha = Math.round(rgb.alpha / 100 * 10000000000) / 10000000000; | ||
return `${name}(${red}, ${green}, ${blue}${isOpaque | ||
? '' | ||
: `, ${alpha}`})`; | ||
} | ||
/* Match | ||
/* ========================================================================== */ | ||
function color2hslLegacyString(color) { | ||
const hsl = color2hsl(color); | ||
const isOpaque = hsl.alpha === 100; | ||
const name = isOpaque ? 'hsl' : 'hsla'; | ||
const hue = hsl.hue; | ||
const saturation = Math.round(hsl.saturation * 10000000000) / 10000000000; | ||
const lightness = Math.round(hsl.lightness * 10000000000) / 10000000000; | ||
const alpha = Math.round(hsl.alpha / 100 * 10000000000) / 10000000000; | ||
const blueGreenRedMatch = /^(blue|green|red)$/i; | ||
return `${name}(${hue}, ${saturation}%, ${lightness}%${isOpaque | ||
? '' | ||
: `, ${alpha}`})`; | ||
} |
@@ -1,2 +0,2 @@ | ||
export default function manageUnresolved(node, opts, word, message) { // eslint-disable-line max-params | ||
export default function manageUnresolved(node, opts, word, message) { | ||
if ('warn' === opts.unresolved) { | ||
@@ -3,0 +3,0 @@ opts.decl.warn(opts.result, message, { word }); |
// tooling | ||
import { convertDtoD, convertGtoD, convertRtoD, convertTtoD, convertNtoRGB } from './conversions'; | ||
import Color from './color'; | ||
import manageUnresolved from './manage-unresolved'; | ||
import names from 'color-name'; | ||
import parser from 'postcss-values-parser'; | ||
@@ -53,7 +53,11 @@ | ||
function transformRGBFunction(node, opts) { | ||
const [red, green, blue, alpha = 1] = transformArgsByParams(node, [ | ||
// [ <percentage>{3} | <rgb-value>{3} ] [ / <alpha-value> ]? | ||
[transformRGBValue, transformRGBValue, transformRGBValue, isSlash, transformAlpha], | ||
// <number>#{3} [ , <alpha-value> ]? ] | ||
[transformRGBValue, isComma, transformRGBValue, isComma, transformRGBValue, isComma, transformAlpha] | ||
const [red, green, blue, alpha = 100] = transformArgsByParams(node, [ | ||
// <percentage> <percentage> <percentage> [ , <alpha-value> ]? | ||
[transformPercentage, transformPercentage, transformPercentage, isSlash, transformAlpha], | ||
// <number> <number> <number> [ , <alpha-value> ]? | ||
[transformRGBNumber, transformRGBNumber, transformRGBNumber, isSlash, transformAlpha], | ||
// <percentage> , <percentage> , <percentage> [ , <alpha-value> ]? | ||
[transformPercentage, isComma, transformPercentage, isComma, transformPercentage, isComma, transformAlpha], | ||
// <number> , <number> , <number> [ , <alpha-value> ]? | ||
[transformRGBNumber, isComma, transformRGBNumber, isComma, transformRGBNumber, isComma, transformAlpha] | ||
]); | ||
@@ -72,6 +76,6 @@ | ||
function transformHSLFunction(node, opts) { | ||
const [hue, saturation, lightness, alpha = 1] = transformArgsByParams(node, [ | ||
// <hue> <percentage>{2} [ / <alpha-value> ]? | ||
const [hue, saturation, lightness, alpha = 100] = transformArgsByParams(node, [ | ||
// <hue> <percentage> <percentage> [ / <alpha-value> ]? | ||
[transformHue, transformPercentage, transformPercentage, isSlash, transformAlpha], | ||
// hue, <percentage>#{2} [ , <alpha-value> ]? ] | ||
// <hue> , <percentage> , <percentage> [ , <alpha-value> ]? | ||
[transformHue, isComma, transformPercentage, isComma, transformPercentage, isComma, transformAlpha] | ||
@@ -91,3 +95,3 @@ ]); | ||
function transformHWBFunction(node, opts) { | ||
const [hue, whiteness, blackness, alpha = 1] = transformArgsByParams(node, [ | ||
const [hue, whiteness, blackness, alpha = 100] = transformArgsByParams(node, [ | ||
// <hue> <percentage> <percentage> [ / <alpha-value> ]? | ||
@@ -113,3 +117,9 @@ [transformHue, transformPercentage, transformPercentage, isSlash, transformAlpha] | ||
const color = isHue(colorOrHueNode) | ||
? new Color({ hue: transformHue(colorOrHueNode, opts), saturation: 1, lightness: 0.5, alpha: 1, colorspace: 'hsl' }) | ||
? new Color({ | ||
hue: transformHue(colorOrHueNode, opts), | ||
saturation: 100, | ||
lightness: 50, | ||
alpha: 100, | ||
colorspace: 'hsl' | ||
}) | ||
: transformColor(colorOrHueNode, opts); | ||
@@ -136,6 +146,6 @@ | ||
const color = new Color({ | ||
red: rr !== undefined ? parseInt(rr, 16) / 255 : r !== undefined ? parseInt(r + r, 16) / 255 : 0, | ||
green: gg !== undefined ? parseInt(gg, 16) / 255 : g !== undefined ? parseInt(g + g, 16) / 255 : 0, | ||
blue: bb !== undefined ? parseInt(bb, 16) / 255 : b !== undefined ? parseInt(b + b, 16) / 255 : 0, | ||
alpha: aa !== undefined ? parseInt(aa, 16) / 255 : a !== undefined ? parseInt(a + a, 16) / 255 : 1 | ||
red: rr !== undefined ? parseInt(rr, 16) / 2.55 : r !== undefined ? parseInt(r + r, 16) / 2.55 : 0, | ||
green: gg !== undefined ? parseInt(gg, 16) / 2.55 : g !== undefined ? parseInt(g + g, 16) / 2.55 : 0, | ||
blue: bb !== undefined ? parseInt(bb, 16) / 2.55 : b !== undefined ? parseInt(b + b, 16) / 2.55 : 0, | ||
alpha: aa !== undefined ? parseInt(aa, 16) / 2.55 : a !== undefined ? parseInt(a + a, 16) / 2.55 : 100 | ||
}); | ||
@@ -153,5 +163,11 @@ | ||
// <named-color> | ||
const [red, green, blue] = names[node.value]; | ||
const [red, green, blue] = convertNtoRGB(node.value); | ||
const color = new Color({ red: red / 255, green: green / 255, blue: blue / 255, alpha: 1, colorspace: 'rgb' }); | ||
const color = new Color({ | ||
red: red / 2.55, | ||
green: green / 2.55, | ||
blue: blue / 2.55, | ||
alpha: 100, | ||
colorspace: 'rgb' | ||
}); | ||
@@ -197,6 +213,7 @@ return color; | ||
const [operatorOrValue, adjustment] = transformArgsByParams(node, alphaMatch.test(node.value) | ||
// a/alpha adjustments | ||
? [ | ||
// [ + | - ] <alpha-value> | ||
[transformMinusPlusOperator, transformAlpha], | ||
// * <alpha-value> | ||
// * <percentage> | ||
[transformTimesOperator, transformPercentage], | ||
@@ -206,9 +223,14 @@ // <alpha-value> | ||
] | ||
// blue/green/red adjustments | ||
: [ | ||
// [ + | - ] <rgb-value> | ||
[transformMinusPlusOperator, transformRGBValue], | ||
// [ + | - ] <percentage> | ||
[transformMinusPlusOperator, transformPercentage], | ||
// [ + | - ] <number> | ||
[transformMinusPlusOperator, transformRGBNumber], | ||
// * <percentage> | ||
[transformTimesOperator, transformPercentage], | ||
// <rgb-value> | ||
[transformRGBValue] | ||
// <percentage> | ||
[transformPercentage], | ||
// <number> | ||
[transformRGBNumber] | ||
] | ||
@@ -223,11 +245,11 @@ ); | ||
const modifiedValue = adjustment | ||
const modifiedValue = adjustment !== undefined | ||
? operatorOrValue === '+' | ||
? existingValue + adjustment | ||
? existingValue + Number(adjustment) | ||
: operatorOrValue === '-' | ||
? existingValue - adjustment | ||
? existingValue - Number(adjustment) | ||
: operatorOrValue === '*' | ||
? existingValue * adjustment | ||
: adjustment | ||
: operatorOrValue; | ||
? existingValue * Number(adjustment) | ||
: Number(adjustment) | ||
: Number(operatorOrValue); | ||
@@ -245,6 +267,6 @@ const modifiedColor = base[channel](modifiedValue); | ||
const [arg1, arg2, arg3, arg4] = transformArgsByParams(node, [ | ||
// [ + | - ] <percentage> <percentage> <percentage> | ||
[transformMinusPlusOperator, transformPercentage, transformPercentage, transformPercentage], | ||
// [ + | - ] <number> <number> <number> | ||
[transformMinusPlusOperator, transformRGBNumber, transformRGBNumber, transformRGBNumber], | ||
// [ + | - ] <percentage> <percentage> <percentage> | ||
[transformMinusPlusOperator, transformPercentage, transformPercentage, transformPercentage], | ||
// [ + | - ] <hash-token> | ||
@@ -294,3 +316,3 @@ [transformMinusPlusOperator, transformHexColor], | ||
} else { | ||
return manageUnresolved(node, opts, node.value, `Expected a valid rgb() adjuster)`); | ||
return manageUnresolved(node, opts, node.value, `Expected a valid rgb() adjuster`); | ||
} | ||
@@ -300,3 +322,3 @@ } | ||
// return a transformed color using a blend/blenda adjustment | ||
function transformBlendAdjuster(base, node, isAlphaBlend, opts) { // eslint-disable-line max-params | ||
function transformBlendAdjuster(base, node, isAlphaBlend, opts) { | ||
const [color, percentage, colorspace = 'rgb'] = transformArgsByParams(node, [ | ||
@@ -335,3 +357,3 @@ [transformColor, transformPercentage, transformColorSpace] | ||
function transformHueAdjuster(base, node, opts) { | ||
const [operatorOrHue, rawAdjustment] = transformArgsByParams(node, [ | ||
const [operatorOrHue, adjustment] = transformArgsByParams(node, [ | ||
// [ + | - | * ] <angle> | ||
@@ -345,18 +367,13 @@ [transformMinusPlusTimesOperator, transformHue], | ||
const existingHue = base.hue(); | ||
const adjustment = parseFloat(rawAdjustment); | ||
const rawModifiedValue = adjustment | ||
const modifiedValue = adjustment !== undefined | ||
? operatorOrHue === '+' | ||
? existingHue + adjustment | ||
? existingHue + Number(adjustment) | ||
: operatorOrHue === '-' | ||
? existingHue - adjustment | ||
? existingHue - Number(adjustment) | ||
: operatorOrHue === '*' | ||
? existingHue * adjustment | ||
: adjustment | ||
: parseFloat(operatorOrHue); | ||
? existingHue * Number(adjustment) | ||
: Number(adjustment) | ||
: Number(operatorOrHue); | ||
const modifiedValue = rawModifiedValue < 0 | ||
? 360 + rawModifiedValue % 360 | ||
: rawModifiedValue % 360; | ||
return base.hue(modifiedValue); | ||
@@ -371,3 +388,3 @@ } else { | ||
const channel = node.value.toLowerCase().replace(/^b$/, 'blackness').replace(/^l$/, 'lightness').replace(/^s$/, 'saturation').replace(/^w$/, 'whiteness'); | ||
const [operatorOrValue, rawAdjustment] = transformArgsByParams(node, [ | ||
const [operatorOrValue, adjustment] = transformArgsByParams(node, [ | ||
[transformMinusPlusTimesOperator, transformPercentage], | ||
@@ -379,13 +396,12 @@ [transformPercentage] | ||
const existingValue = base[channel](); | ||
const adjustment = parseFloat(rawAdjustment); | ||
const modifiedValue = adjustment | ||
const modifiedValue = adjustment !== undefined | ||
? operatorOrValue === '+' | ||
? existingValue + adjustment | ||
? existingValue + Number(adjustment) | ||
: operatorOrValue === '-' | ||
? existingValue - adjustment | ||
? existingValue - Number(adjustment) | ||
: operatorOrValue === '*' | ||
? existingValue * adjustment | ||
: adjustment | ||
: parseFloat(operatorOrValue); | ||
? existingValue * Number(adjustment) | ||
: Number(adjustment) | ||
: Number(operatorOrValue); | ||
@@ -407,3 +423,3 @@ return base[channel](modifiedValue); | ||
if (percentage !== undefined) { | ||
const modifiedValue = parseFloat(percentage); | ||
const modifiedValue = Number(percentage); | ||
@@ -433,3 +449,3 @@ return base[channel](modifiedValue); | ||
// <number> | ||
return parseFloat(node.value); | ||
return node.value * 100; | ||
} else if (isPercentage(node)) { | ||
@@ -443,20 +459,7 @@ // <percentage> | ||
// return a transformed rgb value | ||
function transformRGBValue(node, opts) { | ||
if (isNumber(node)) { | ||
// <rgba-number> | ||
return transformRGBNumber(node, opts); | ||
} else if (isPercentage(node)) { | ||
// <percentage> | ||
return transformPercentage(node, opts); | ||
} else { | ||
return manageUnresolved(node, opts, node.value, `Expected a valid RGB value)`); | ||
} | ||
} | ||
// return a transformed rgb number | ||
function transformRGBNumber(node, opts) { | ||
if (isNumber(node)) { | ||
// <rgba-number> | ||
return parseFloat(node.value) / 255; | ||
// <number> | ||
return node.value / 2.55; | ||
} else { | ||
@@ -470,4 +473,18 @@ return manageUnresolved(node, opts, node.value, `Expected a valid RGB value)`); | ||
if (isHue(node)) { | ||
// <hue> | ||
return parseFloat(node.value); | ||
// <hue> = <number> | <angle> | ||
const unit = node.unit.toLowerCase(); | ||
if (unit === 'grad') { | ||
// if <angle> = <gradian> (400 per circle) | ||
return convertGtoD(node.value); | ||
} else if (unit === 'rad') { | ||
// if <angle> = <radian> (2π per circle) | ||
return convertRtoD(node.value); | ||
} else if (unit === 'turn') { | ||
// if <angle> = <turn> (1 per circle) | ||
return convertTtoD(node.value); | ||
} else { | ||
// if <angle> = [ <degree> | <number> ] (360 per circle) | ||
return convertDtoD(node.value); | ||
} | ||
} else { | ||
@@ -482,3 +499,3 @@ return manageUnresolved(node, opts, node.value, `Expected a valid hue`); | ||
// <percentage> | ||
return parseFloat(node.value) / 100; | ||
return Number(node.value); | ||
} else { | ||
@@ -607,3 +624,3 @@ return manageUnresolved(node, opts, node.value, `Expected a valid hue`); | ||
function isNamedColor(node) { | ||
return Object(node).type === 'word' && node.value in names; | ||
return Object(node).type === 'word' && Boolean(convertNtoRGB(node.value)); | ||
} | ||
@@ -628,3 +645,3 @@ | ||
function isHue(node) { | ||
return Object(node).type === 'number' && /^(deg)?$/.test(node.unit); | ||
return Object(node).type === 'number' && hueUnitMatch.test(node.unit); | ||
} | ||
@@ -664,3 +681,3 @@ | ||
function isPercentage(node) { | ||
return Object(node).type === 'number' && node.unit === '%'; | ||
return Object(node).type === 'number' && (node.unit === '%' || node.value === '0'); | ||
} | ||
@@ -680,2 +697,3 @@ | ||
const hslaMatch = /^hsla?$/i; | ||
const hueUnitMatch = /^(deg|grad|rad|turn)?$/i; | ||
const hueMatch = /^h(ue)?$/i; | ||
@@ -682,0 +700,0 @@ const hwbMatch = /^hwb$/i; |
{ | ||
"name": "postcss-color-mod-function", | ||
"version": "1.1.0", | ||
"version": "2.1.0", | ||
"description": "Modify colors using the color-mod() function in CSS", | ||
@@ -29,3 +29,2 @@ "author": "Jonathan Neal <jonathantneal@hotmail.com>", | ||
"dependencies": { | ||
"color-name": "^1.1.3", | ||
"postcss": "^6.0", | ||
@@ -39,3 +38,3 @@ "postcss-values-parser": "^1.3.1" | ||
"echint": "^4.0", | ||
"eslint": "^4.15", | ||
"eslint": "^4.16", | ||
"eslint-config-dev": "2.0", | ||
@@ -49,3 +48,9 @@ "postcss-tape": "2.2", | ||
"extends": "dev", | ||
"parser": "babel-eslint" | ||
"parser": "babel-eslint", | ||
"rules": { | ||
"max-params": [ | ||
2, | ||
5 | ||
] | ||
} | ||
}, | ||
@@ -52,0 +57,0 @@ "keywords": [ |
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
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
116386
2
10
2603
- Removedcolor-name@^1.1.3
- Removedcolor-name@1.1.4(transitive)