Improve color parsing error handling

This commit is contained in:
Mikael Sand
2019-01-29 05:46:59 +02:00
parent 48d5106dcb
commit 5849c82e5c
2 changed files with 151 additions and 154 deletions
+147 -154
View File
@@ -1,35 +1,3 @@
const colorString = {};
colorString.get = function(string) {
const prefix = string.substring(0, 3).toLowerCase();
let val;
let model;
switch (prefix) {
case 'hsl':
val = colorString.get.hsl(string);
model = 'hsl';
break;
case 'hwb':
val = colorString.get.hwb(string);
model = 'hwb';
break;
default:
val = colorString.get.rgb(string);
model = 'rgb';
break;
}
if (!val) {
return null;
}
return { model: model, value: val };
};
function clamp(num, min, max) {
return Math.min(Math.max(min, num), max);
}
const colorNames = {
aliceblue: [240, 248, 255],
antiquewhite: [250, 235, 215],
@@ -181,11 +149,11 @@ const colorNames = {
yellowgreen: [154, 205, 50],
};
colorString.get.rgb = function(string) {
if (!string) {
return null;
}
function clamp(num, min, max) {
return Math.min(Math.max(min, num), max);
}
function rgbFromString(string) {
const abbr = /^#([a-f0-9]{3,4})$/i;
const hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i;
const rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d.]+)\s*)?\)$/;
@@ -262,13 +230,9 @@ colorString.get.rgb = function(string) {
rgb[3] = clamp(rgb[3], 0, 1);
return rgb;
};
colorString.get.hsl = function(string) {
if (!string) {
return null;
}
}
function hslFromString(string) {
const hsl = /^hsla?\(\s*([+-]?(?:\d*\.)?\d+)(?:deg)?\s*,\s*([+-]?[\d.]+)%\s*,\s*([+-]?[\d.]+)%\s*(?:,\s*([+-]?[\d.]+)\s*)?\)$/;
const match = string.match(hsl);
@@ -283,13 +247,9 @@ colorString.get.hsl = function(string) {
}
return null;
};
colorString.get.hwb = function(string) {
if (!string) {
return null;
}
}
function hwbFromString(string) {
const hwb = /^hwb\(\s*([+-]?\d*[.]?\d+)(?:deg)?\s*,\s*([+-]?[\d.]+)%\s*,\s*([+-]?[\d.]+)%\s*(?:,\s*([+-]?[\d.]+)\s*)?\)$/;
const match = string.match(hwb);
@@ -303,128 +263,161 @@ colorString.get.hwb = function(string) {
}
return null;
};
}
const convert = {};
const convert = {
hsl: function hslToRgb(hsl) {
const h = hsl[0] / 360;
const s = hsl[1] / 100;
const l = hsl[2] / 100;
let t1;
let t2;
let t3;
let rgb;
let val;
convert.hsl.rgb = function(hsl) {
const h = hsl[0] / 360;
const s = hsl[1] / 100;
const l = hsl[2] / 100;
let t1;
let t2;
let t3;
let rgb;
let val;
if (s === 0) {
val = l * 255;
return [val, val, val];
}
if (l < 0.5) {
t2 = l * (1 + s);
} else {
t2 = l + s - l * s;
}
t1 = 2 * l - t2;
rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) {
t3 = h + (1 / 3) * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
if (s === 0) {
val = l * 255;
return [val, val, val];
}
if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
val = t2;
} else if (3 * t3 < 2) {
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
if (l < 0.5) {
t2 = l * (1 + s);
} else {
val = t1;
t2 = l + s - l * s;
}
rgb[i] = val * 255;
}
t1 = 2 * l - t2;
return rgb;
rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) {
t3 = h + (1 / 3) * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
}
if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
val = t2;
} else if (3 * t3 < 2) {
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
} else {
val = t1;
}
rgb[i] = val * 255;
}
return rgb;
},
hwb: function hwbToRgb(hwb) {
const h = hwb[0] / 360;
let wh = hwb[1] / 100;
let bl = hwb[2] / 100;
const ratio = wh + bl;
let i;
let v;
let f;
let n;
// wh + bl cant be > 1
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
}
i = Math.floor(6 * h);
v = 1 - bl;
f = 6 * h - i;
if ((i & 0x01) !== 0) {
f = 1 - f;
}
n = wh + f * (v - wh); // linear interpolation
let r;
let g;
let b;
switch (i) {
default:
case 6:
case 0:
r = v;
g = n;
b = wh;
break;
case 1:
r = n;
g = v;
b = wh;
break;
case 2:
r = wh;
g = v;
b = n;
break;
case 3:
r = wh;
g = n;
b = v;
break;
case 4:
r = n;
g = wh;
b = v;
break;
case 5:
r = v;
g = wh;
b = n;
break;
}
return [r * 255, g * 255, b * 255];
},
};
// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
convert.hwb.rgb = function(hwb) {
const h = hwb[0] / 360;
let wh = hwb[1] / 100;
let bl = hwb[2] / 100;
const ratio = wh + bl;
let i;
let v;
let f;
let n;
// wh + bl cant be > 1
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
function colorFromString(string) {
if (!string || typeof string !== 'string') {
return null;
}
i = Math.floor(6 * h);
v = 1 - bl;
f = 6 * h - i;
if ((i & 0x01) !== 0) {
f = 1 - f;
}
n = wh + f * (v - wh); // linear interpolation
let r;
let g;
let b;
switch (i) {
const prefix = string.substring(0, 3).toLowerCase();
let value;
let model;
switch (prefix) {
case 'hsl':
value = hslFromString(string);
model = 'hsl';
break;
case 'hwb':
value = hwbFromString(string);
model = 'hwb';
break;
default:
case 6:
case 0:
r = v;
g = n;
b = wh;
break;
case 1:
r = n;
g = v;
b = wh;
break;
case 2:
r = wh;
g = v;
b = n;
break;
case 3:
r = wh;
g = n;
b = v;
break;
case 4:
r = n;
g = wh;
b = v;
break;
case 5:
r = v;
g = wh;
b = n;
value = rgbFromString(string);
model = 'rgb';
break;
}
return [r * 255, g * 255, b * 255];
};
if (!value) {
return null;
}
return [model, value];
}
export default function extractColor(color) {
const { value, model } = colorString.get(color);
return model === 'rgb' ? value : convert[model].rgb(value).concat(value[3]);
const result = colorFromString(color);
if (!result) {
return null;
}
const model = result[0];
const value = result[1];
return model === 'rgb' ? value : convert[model](value).concat(value[3]);
}
+4
View File
@@ -48,6 +48,10 @@ export default function extractGradient(props, parent) {
const offsetNumber = percentToFloat(offset);
if (stopColor && !isNaN(offsetNumber)) {
const color = extractColor(stopColor);
if (!color) {
console.warn(`"${stopColor}" is not a valid color`);
continue;
}
const r = color[0] / 255;
const g = color[1] / 255;
const b = color[2] / 255;