diff --git a/edit.html b/edit.html
index 50b6c57b..19375978 100644
--- a/edit.html
+++ b/edit.html
@@ -72,6 +72,7 @@
+
diff --git a/install-usercss.html b/install-usercss.html
index 8aac40de..047f8918 100644
--- a/install-usercss.html
+++ b/install-usercss.html
@@ -35,6 +35,7 @@
+
diff --git a/js/color-parser.js b/js/color-parser.js
deleted file mode 100644
index 29e7eda8..00000000
--- a/js/color-parser.js
+++ /dev/null
@@ -1,40 +0,0 @@
-'use strict';
-
-// eslint-disable-next-line no-var
-var colorParser = (() => {
- const el = document.createElement('div');
- // https://bugs.webkit.org/show_bug.cgi?id=14563
- document.head.appendChild(el);
-
- function parseRGB(color) {
- const [r, g, b, a = 1] = color.match(/[.\d]+/g).map(Number);
- return {r, g, b, a};
- }
-
- function parse(color) {
- el.style.color = color;
- if (el.style.color === '') {
- throw new Error(chrome.i18n.getMessage('styleMetaErrorColor', color));
- }
- color = getComputedStyle(el).color;
- el.style.color = '';
- return parseRGB(color);
- }
-
- function format({r, g, b, a = 1}) {
- if (a === 1) {
- return `rgb(${r}, ${g}, ${b})`;
- }
- return `rgba(${r}, ${g}, ${b}, ${a})`;
- }
-
- function formatHex({r, g, b, a = null}) {
- let hex = '#' + (0x1000000 + (r << 16) + (g << 8) + (b | 0)).toString(16).substr(1);
- if (a !== null) {
- hex += (0x100 + Math.floor(a * 255)).toString(16).substr(1);
- }
- return hex;
- }
-
- return {parse, format, formatHex};
-})();
diff --git a/js/usercss.js b/js/usercss.js
index a8823751..8d18b16f 100644
--- a/js/usercss.js
+++ b/js/usercss.js
@@ -1,4 +1,4 @@
-/* global loadScript mozParser semverCompare colorParser styleCodeEmpty */
+/* global loadScript mozParser semverCompare colorConverter styleCodeEmpty */
'use strict';
// eslint-disable-next-line no-var
@@ -76,9 +76,10 @@ var usercss = (() => {
}
if (rgb) {
if (vars[name].type === 'color') {
- // eslint-disable-next-line no-use-before-define
- const color = colorParser.parse(vars[name].value);
- return `${color.r}, ${color.g}, ${color.b}`;
+ const color = colorConverter.parse(vars[name].value);
+ if (!color) return null;
+ const {r, g, b} = color;
+ return `${r}, ${g}, ${b}`;
}
return null;
}
@@ -545,7 +546,7 @@ var usercss = (() => {
} else if (va.type === 'checkbox' && !/^[01]$/.test(va[value])) {
throw new Error(chrome.i18n.getMessage('styleMetaErrorCheckbox'));
} else if (va.type === 'color') {
- va[value] = colorParser.format(colorParser.parse(va[value]));
+ va[value] = colorConverter.format(colorConverter.parse(va[value]), 'rgb');
}
}
diff --git a/manifest.json b/manifest.json
index f5233c18..83e92fda 100644
--- a/manifest.json
+++ b/manifest.json
@@ -27,14 +27,14 @@
"background/storage.js",
"js/prefs.js",
"js/script-loader.js",
- "js/color-parser.js",
"js/usercss.js",
"background/background.js",
"background/usercss-helper.js",
"background/style-via-api.js",
"background/search-db.js",
"background/update.js",
- "vendor/node-semver/semver.js"
+ "vendor/node-semver/semver.js",
+ "vendor-overwrites/colorpicker/colorconverter.js"
]
},
"commands": {
diff --git a/popup.html b/popup.html
index 12f9b0e9..edca583b 100644
--- a/popup.html
+++ b/popup.html
@@ -141,6 +141,7 @@
+
diff --git a/vendor-overwrites/colorpicker/colorconverter.js b/vendor-overwrites/colorpicker/colorconverter.js
new file mode 100644
index 00000000..45808ff1
--- /dev/null
+++ b/vendor-overwrites/colorpicker/colorconverter.js
@@ -0,0 +1,318 @@
+'use strict';
+
+const colorConverter = (() => {
+
+ return {
+ parse,
+ format,
+ formatAlpha,
+ RGBtoHSV,
+ HSVtoRGB,
+ HSLtoHSV,
+ HSVtoHSL,
+ constrainHue,
+ snapToInt,
+ // NAMED_COLORS is added below
+ };
+
+ function format(color, type, hexUppercase) {
+ const a = formatAlpha(color.a);
+ const hasA = Boolean(a);
+ if (type === 'rgb' && color.type === 'hsl') {
+ color = HSVtoRGB(HSLtoHSV(color));
+ }
+ const {r, g, b, h, s, l} = color;
+ switch (type) {
+ case 'hex': {
+ const rgbStr = (0x1000000 + (r << 16) + (g << 8) + (b | 0)).toString(16).slice(1);
+ const aStr = hasA ? (0x100 + Math.round(a * 255)).toString(16).slice(1) : '';
+ const hexStr = `#${rgbStr + aStr}`.replace(/^#(.)\1(.)\2(.)\3(?:(.)\4)?$/, '#$1$2$3$4');
+ return hexUppercase ? hexStr.toUpperCase() : hexStr.toLowerCase();
+ }
+ case 'rgb':
+ return hasA ?
+ `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${a})` :
+ `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
+ case 'hsl':
+ return hasA ?
+ `hsla(${h}, ${s}%, ${l}%, ${a})` :
+ `hsl(${h}, ${s}%, ${l}%)`;
+ }
+ }
+
+ function parse(str) {
+ if (typeof str !== 'string') return;
+ str = str.trim();
+ if (!str) return;
+
+ if (str[0] !== '#' && !str.includes('(')) {
+ // eslint-disable-next-line no-use-before-define
+ str = colorConverter.NAMED_COLORS.get(str);
+ if (!str) return;
+ }
+
+ if (str[0] === '#') {
+ str = str.slice(1);
+ const [r, g, b, a = 255] = str.length <= 4 ?
+ str.match(/(.)/g).map(c => parseInt(c + c, 16)) :
+ str.match(/(..)/g).map(c => parseInt(c, 16));
+ return {type: 'hex', r, g, b, a: a === 255 ? undefined : a / 255};
+ }
+
+ const [, type, value] = str.match(/^(rgb|hsl)a?\((.*?)\)|$/i);
+ if (!type) return;
+
+ const comma = value.includes(',') && !value.includes('/');
+ const num = value.split(comma ? /\s*,\s*/ : /\s+(?!\/)|\s*\/\s*/);
+ if (num.length < 3 || num.length > 4) return;
+
+ let a = !num[3] ? 1 : parseFloat(num[3]) / (num[3].endsWith('%') ? 100 : 1);
+ if (isNaN(a)) a = 1;
+
+ const first = num[0];
+ if (/rgb/i.test(type)) {
+ const k = first.endsWith('%') ? 2.55 : 1;
+ const [r, g, b] = num.map(s => parseFloat(s) * k);
+ return {type: 'rgb', r, g, b, a};
+ } else {
+ let h = parseFloat(first);
+ if (first.endsWith('grad')) h *= 360 / 400;
+ else if (first.endsWith('rad')) h *= 180 / Math.PI;
+ else if (first.endsWith('turn')) h *= 360;
+ const s = parseFloat(num[1]);
+ const l = parseFloat(num[2]);
+ return {type: 'hsl', h, s, l, a};
+ }
+ }
+
+ function formatAlpha(a) {
+ return isNaN(a) ? '' :
+ (a + .5e-6).toFixed(7).slice(0, -1).replace(/^0(?=\.[1-9])|^1\.0+?$|\.?0+$/g, '');
+ }
+
+ function RGBtoHSV({r, g, b, a}) {
+ r /= 255;
+ g /= 255;
+ b /= 255;
+ const MaxC = Math.max(r, g, b);
+ const MinC = Math.min(r, g, b);
+ const DeltaC = MaxC - MinC;
+
+ let h =
+ DeltaC === 0 ? 0 :
+ MaxC === r ? 60 * (((g - b) / DeltaC) % 6) :
+ MaxC === g ? 60 * (((b - r) / DeltaC) + 2) :
+ MaxC === b ? 60 * (((r - g) / DeltaC) + 4) :
+ 0;
+ h = constrainHue(h);
+ return {
+ h,
+ s: MaxC === 0 ? 0 : DeltaC / MaxC,
+ v: MaxC,
+ a,
+ };
+ }
+
+ function HSVtoRGB({h, s, v}) {
+ h = constrainHue(h) % 360;
+ const C = s * v;
+ const X = C * (1 - Math.abs((h / 60) % 2 - 1));
+ const m = v - C;
+ const [r, g, b] =
+ h >= 0 && h < 60 ? [C, X, 0] :
+ h >= 60 && h < 120 ? [X, C, 0] :
+ h >= 120 && h < 180 ? [0, C, X] :
+ h >= 180 && h < 240 ? [0, X, C] :
+ h >= 240 && h < 300 ? [X, 0, C] :
+ h >= 300 && h < 360 ? [C, 0, X] : [];
+ return {
+ r: snapToInt(Math.round((r + m) * 255)),
+ g: snapToInt(Math.round((g + m) * 255)),
+ b: snapToInt(Math.round((b + m) * 255)),
+ };
+ }
+
+ function HSLtoHSV({h, s, l, a}) {
+ const t = s * (l < 50 ? l : 100 - l) / 100;
+ return {
+ h: constrainHue(h),
+ s: t + l ? 200 * t / (t + l) / 100 : 0,
+ v: (t + l) / 100,
+ a,
+ };
+ }
+
+ function HSVtoHSL({h, s, v}) {
+ const l = (2 - s) * v / 2;
+ const t = l < .5 ? l * 2 : 2 - l * 2;
+ return {
+ h: Math.round(constrainHue(h)),
+ s: Math.round(t ? s * v / t * 100 : 0),
+ l: Math.round(l * 100),
+ };
+ }
+
+ function constrainHue(h) {
+ return h < 0 ? h % 360 + 360 :
+ h > 360 ? h % 360 :
+ h;
+ }
+
+ function snapToInt(num) {
+ const int = Math.round(num);
+ return Math.abs(int - num) < 1e-3 ? int : num;
+ }
+})();
+
+colorConverter.NAMED_COLORS = new Map([
+ ['transparent', 'rgba(0, 0, 0, 0)'],
+ // CSS4 named colors
+ ['aliceblue', '#f0f8ff'],
+ ['antiquewhite', '#faebd7'],
+ ['aqua', '#00ffff'],
+ ['aquamarine', '#7fffd4'],
+ ['azure', '#f0ffff'],
+ ['beige', '#f5f5dc'],
+ ['bisque', '#ffe4c4'],
+ ['black', '#000000'],
+ ['blanchedalmond', '#ffebcd'],
+ ['blue', '#0000ff'],
+ ['blueviolet', '#8a2be2'],
+ ['brown', '#a52a2a'],
+ ['burlywood', '#deb887'],
+ ['cadetblue', '#5f9ea0'],
+ ['chartreuse', '#7fff00'],
+ ['chocolate', '#d2691e'],
+ ['coral', '#ff7f50'],
+ ['cornflowerblue', '#6495ed'],
+ ['cornsilk', '#fff8dc'],
+ ['crimson', '#dc143c'],
+ ['cyan', '#00ffff'],
+ ['darkblue', '#00008b'],
+ ['darkcyan', '#008b8b'],
+ ['darkgoldenrod', '#b8860b'],
+ ['darkgray', '#a9a9a9'],
+ ['darkgrey', '#a9a9a9'],
+ ['darkgreen', '#006400'],
+ ['darkkhaki', '#bdb76b'],
+ ['darkmagenta', '#8b008b'],
+ ['darkolivegreen', '#556b2f'],
+ ['darkorange', '#ff8c00'],
+ ['darkorchid', '#9932cc'],
+ ['darkred', '#8b0000'],
+ ['darksalmon', '#e9967a'],
+ ['darkseagreen', '#8fbc8f'],
+ ['darkslateblue', '#483d8b'],
+ ['darkslategray', '#2f4f4f'],
+ ['darkslategrey', '#2f4f4f'],
+ ['darkturquoise', '#00ced1'],
+ ['darkviolet', '#9400d3'],
+ ['deeppink', '#ff1493'],
+ ['deepskyblue', '#00bfff'],
+ ['dimgray', '#696969'],
+ ['dimgrey', '#696969'],
+ ['dodgerblue', '#1e90ff'],
+ ['firebrick', '#b22222'],
+ ['floralwhite', '#fffaf0'],
+ ['forestgreen', '#228b22'],
+ ['fuchsia', '#ff00ff'],
+ ['gainsboro', '#dcdcdc'],
+ ['ghostwhite', '#f8f8ff'],
+ ['gold', '#ffd700'],
+ ['goldenrod', '#daa520'],
+ ['gray', '#808080'],
+ ['grey', '#808080'],
+ ['green', '#008000'],
+ ['greenyellow', '#adff2f'],
+ ['honeydew', '#f0fff0'],
+ ['hotpink', '#ff69b4'],
+ ['indianred', '#cd5c5c'],
+ ['indigo', '#4b0082'],
+ ['ivory', '#fffff0'],
+ ['khaki', '#f0e68c'],
+ ['lavender', '#e6e6fa'],
+ ['lavenderblush', '#fff0f5'],
+ ['lawngreen', '#7cfc00'],
+ ['lemonchiffon', '#fffacd'],
+ ['lightblue', '#add8e6'],
+ ['lightcoral', '#f08080'],
+ ['lightcyan', '#e0ffff'],
+ ['lightgoldenrodyellow', '#fafad2'],
+ ['lightgray', '#d3d3d3'],
+ ['lightgrey', '#d3d3d3'],
+ ['lightgreen', '#90ee90'],
+ ['lightpink', '#ffb6c1'],
+ ['lightsalmon', '#ffa07a'],
+ ['lightseagreen', '#20b2aa'],
+ ['lightskyblue', '#87cefa'],
+ ['lightslategray', '#778899'],
+ ['lightslategrey', '#778899'],
+ ['lightsteelblue', '#b0c4de'],
+ ['lightyellow', '#ffffe0'],
+ ['lime', '#00ff00'],
+ ['limegreen', '#32cd32'],
+ ['linen', '#faf0e6'],
+ ['magenta', '#ff00ff'],
+ ['maroon', '#800000'],
+ ['mediumaquamarine', '#66cdaa'],
+ ['mediumblue', '#0000cd'],
+ ['mediumorchid', '#ba55d3'],
+ ['mediumpurple', '#9370db'],
+ ['mediumseagreen', '#3cb371'],
+ ['mediumslateblue', '#7b68ee'],
+ ['mediumspringgreen', '#00fa9a'],
+ ['mediumturquoise', '#48d1cc'],
+ ['mediumvioletred', '#c71585'],
+ ['midnightblue', '#191970'],
+ ['mintcream', '#f5fffa'],
+ ['mistyrose', '#ffe4e1'],
+ ['moccasin', '#ffe4b5'],
+ ['navajowhite', '#ffdead'],
+ ['navy', '#000080'],
+ ['oldlace', '#fdf5e6'],
+ ['olive', '#808000'],
+ ['olivedrab', '#6b8e23'],
+ ['orange', '#ffa500'],
+ ['orangered', '#ff4500'],
+ ['orchid', '#da70d6'],
+ ['palegoldenrod', '#eee8aa'],
+ ['palegreen', '#98fb98'],
+ ['paleturquoise', '#afeeee'],
+ ['palevioletred', '#db7093'],
+ ['papayawhip', '#ffefd5'],
+ ['peachpuff', '#ffdab9'],
+ ['peru', '#cd853f'],
+ ['pink', '#ffc0cb'],
+ ['plum', '#dda0dd'],
+ ['powderblue', '#b0e0e6'],
+ ['purple', '#800080'],
+ ['rebeccapurple', '#663399'],
+ ['red', '#ff0000'],
+ ['rosybrown', '#bc8f8f'],
+ ['royalblue', '#4169e1'],
+ ['saddlebrown', '#8b4513'],
+ ['salmon', '#fa8072'],
+ ['sandybrown', '#f4a460'],
+ ['seagreen', '#2e8b57'],
+ ['seashell', '#fff5ee'],
+ ['sienna', '#a0522d'],
+ ['silver', '#c0c0c0'],
+ ['skyblue', '#87ceeb'],
+ ['slateblue', '#6a5acd'],
+ ['slategray', '#708090'],
+ ['slategrey', '#708090'],
+ ['snow', '#fffafa'],
+ ['springgreen', '#00ff7f'],
+ ['steelblue', '#4682b4'],
+ ['tan', '#d2b48c'],
+ ['teal', '#008080'],
+ ['thistle', '#d8bfd8'],
+ ['tomato', '#ff6347'],
+ ['turquoise', '#40e0d0'],
+ ['violet', '#ee82ee'],
+ ['wheat', '#f5deb3'],
+ ['white', '#ffffff'],
+ ['whitesmoke', '#f5f5f5'],
+ ['yellow', '#ffff00'],
+ ['yellowgreen', '#9acd32'],
+]);
diff --git a/vendor-overwrites/colorpicker/colorpicker.js b/vendor-overwrites/colorpicker/colorpicker.js
index fac862e1..3bb15863 100644
--- a/vendor-overwrites/colorpicker/colorpicker.js
+++ b/vendor-overwrites/colorpicker/colorpicker.js
@@ -1,4 +1,4 @@
-/* global CodeMirror NAMED_COLORS */
+/* global CodeMirror colorConverter */
'use strict';
(window.CodeMirror ? window.CodeMirror.prototype : window).colorpicker = function () {
@@ -57,8 +57,6 @@
hide,
setColor,
getColor,
- stringToColor,
- colorToString,
options,
};
return PUBLIC_API;
@@ -178,7 +176,7 @@
Object.defineProperty($inputs.hsl, 'color', {get: inputsToHSL});
Object.defineProperty($inputs, 'color', {get: () => $inputs[currentFormat].color});
- HUE_COLORS.forEach(color => Object.assign(color, stringToColor(color.hex)));
+ HUE_COLORS.forEach(color => Object.assign(color, colorConverter.parse(color.hex)));
initialized = true;
}
@@ -235,7 +233,7 @@
function setColor(color) {
switch (typeof color) {
case 'string':
- color = stringToColor(color);
+ color = colorConverter.parse(color);
break;
case 'object': {
const {r, g, b, a} = color;
@@ -267,7 +265,9 @@
return;
}
readCurrentColorFromRamps();
- const color = type === 'hsl' ? HSVtoHSL(HSV) : HSVtoRGB(HSV);
+ const color = type === 'hsl' ?
+ colorConverter.HSVtoHSL(HSV) :
+ colorConverter.HSVtoRGB(HSV);
return type ? colorToString(color, type) : color;
}
@@ -279,7 +279,7 @@
HSV.h = HSV.s = HSV.v = 0;
} else {
const {x, y} = dragging.saturationPointerPos;
- HSV.h = snapToInt((dragging.hueKnobPos / $hue.offsetWidth) * 360);
+ HSV.h = colorConverter.snapToInt((dragging.hueKnobPos / $hue.offsetWidth) * 360);
HSV.s = x / $sat.offsetWidth;
HSV.v = ($sat.offsetHeight - y) / $sat.offsetHeight;
}
@@ -304,7 +304,7 @@
function setFromHueElement(event) {
const {left, width} = getScreenBounds($hue);
const currentX = event ? getTouchPosition(event).clientX :
- left + width * constrainHue(HSV.h) / 360;
+ left + width * colorConverter.constrainHue(HSV.h) / 360;
const normalizedH = constrain(0, 1, (currentX - left) / width);
const x = dragging.hueKnobPos = width * normalizedH;
$hueKnob.style.left = (x - Math.round($hueKnob.offsetWidth / 2)) + 'px';
@@ -443,9 +443,11 @@
//region State-to-DOM
function setFromColor(color) {
- color = typeof color === 'string' ? stringToColor(color) : color;
- color = color || stringToColor('#f00');
- const newHSV = color.type === 'hsl' ? HSLtoHSV(color) : RGBtoHSV(color);
+ color = typeof color === 'string' ? colorConverter.parse(color) : color;
+ color = color || colorConverter.parse('#f00');
+ const newHSV = color.type === 'hsl' ?
+ colorConverter.HSLtoHSV(color) :
+ colorConverter.RGBtoHSV(color);
if (Object.keys(newHSV).every(k => Math.abs(newHSV[k] - HSV[k]) < 1e-3)) {
return;
}
@@ -489,7 +491,7 @@
}
function renderInputs() {
- const rgb = HSVtoRGB(HSV);
+ const rgb = colorConverter.HSVtoRGB(HSV);
switch (currentFormat) {
case 'hex':
$hexCode.value = colorToString(rgb, 'hex');
@@ -502,7 +504,7 @@
break;
}
case 'hsl': {
- const {h, s, l} = HSVtoHSL(HSV);
+ const {h, s, l} = colorConverter.HSVtoHSL(HSV);
$hsl.h.value = h;
$hsl.s.value = s;
$hsl.l.value = l;
@@ -723,144 +725,17 @@
//region Color conversion utilities
function colorToString(color, type = currentFormat) {
- const a = alphaToString(color.a);
- const hasA = Boolean(a);
- if (type === 'rgb' && color.type === 'hsl') {
- color = HSVtoRGB(HSLtoHSV(color));
- }
- const {r, g, b, h, s, l} = color;
- switch (type) {
- case 'hex': {
- const rgbStr = (0x1000000 + (r << 16) + (g << 8) + (b | 0)).toString(16).slice(1);
- const aStr = hasA ? (0x100 + Math.round(a * 255)).toString(16).slice(1) : '';
- const hexStr = `#${rgbStr + aStr}`.replace(/^#(.)\1(.)\2(.)\3(?:(.)\4)?$/, '#$1$2$3$4');
- return options.hexUppercase ? hexStr.toUpperCase() : hexStr.toLowerCase();
- }
- case 'rgb':
- return hasA ?
- `rgba(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)}, ${a})` :
- `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
- case 'hsl':
- return hasA ?
- `hsla(${h}, ${s}%, ${l}%, ${a})` :
- `hsl(${h}, ${s}%, ${l}%)`;
- }
+ return colorConverter.format(color, type, options.hexUppercase);
}
- function stringToColor(str) {
- if (typeof str !== 'string') return;
- str = str.trim();
- if (!str) return;
-
- if (str[0] !== '#' && !str.includes('(')) {
- str = NAMED_COLORS.get(str);
- if (!str) return;
- }
-
- if (str[0] === '#') {
- str = str.slice(1);
- const [r, g, b, a = 255] = str.length <= 4 ?
- str.match(/(.)/g).map(c => parseInt(c + c, 16)) :
- str.match(/(..)/g).map(c => parseInt(c, 16));
- return {type: 'hex', r, g, b, a: a === 255 ? undefined : a / 255};
- }
-
- const [, type, value] = str.match(/^(rgb|hsl)a?\((.*?)\)|$/i);
- if (!type) return;
-
- const comma = value.includes(',') && !value.includes('/');
- const num = value.split(comma ? /\s*,\s*/ : /\s+(?!\/)|\s*\/\s*/);
- if (num.length < 3 || num.length > 4) return;
-
- let a = !num[3] ? 1 : parseFloat(num[3]) / (num[3].endsWith('%') ? 100 : 1);
- if (isNaN(a)) a = 1;
-
- const first = num[0];
- if (/rgb/i.test(type)) {
- const k = first.endsWith('%') ? 2.55 : 1;
- const [r, g, b] = num.map(s => parseFloat(s) * k);
- return {type: 'rgb', r, g, b, a};
- } else {
- let h = parseFloat(first);
- if (first.endsWith('grad')) h *= 360 / 400;
- else if (first.endsWith('rad')) h *= 180 / Math.PI;
- else if (first.endsWith('turn')) h *= 360;
- const s = parseFloat(num[1]);
- const l = parseFloat(num[2]);
- return {type: 'hsl', h, s, l, a};
- }
- }
-
- function constrainHue(h) {
- return h < 0 ? h % 360 + 360 :
- h > 360 ? h % 360 :
- h;
- }
-
- function RGBtoHSV({r, g, b, a}) {
- r /= 255;
- g /= 255;
- b /= 255;
- const MaxC = Math.max(r, g, b);
- const MinC = Math.min(r, g, b);
- const DeltaC = MaxC - MinC;
-
- let h =
- DeltaC === 0 ? 0 :
- MaxC === r ? 60 * (((g - b) / DeltaC) % 6) :
- MaxC === g ? 60 * (((b - r) / DeltaC) + 2) :
- MaxC === b ? 60 * (((r - g) / DeltaC) + 4) :
- 0;
- h = constrainHue(h);
- return {
- h,
- s: MaxC === 0 ? 0 : DeltaC / MaxC,
- v: MaxC,
- a,
- };
- }
-
- function HSVtoRGB({h, s, v}) {
- h = constrainHue(h) % 360;
- const C = s * v;
- const X = C * (1 - Math.abs((h / 60) % 2 - 1));
- const m = v - C;
- const [r, g, b] =
- h >= 0 && h < 60 ? [C, X, 0] :
- h >= 60 && h < 120 ? [X, C, 0] :
- h >= 120 && h < 180 ? [0, C, X] :
- h >= 180 && h < 240 ? [0, X, C] :
- h >= 240 && h < 300 ? [X, 0, C] :
- h >= 300 && h < 360 ? [C, 0, X] : [];
- return {
- r: snapToInt(Math.round((r + m) * 255)),
- g: snapToInt(Math.round((g + m) * 255)),
- b: snapToInt(Math.round((b + m) * 255)),
- };
- }
-
- function HSLtoHSV({h, s, l, a}) {
- const t = s * (l < 50 ? l : 100 - l) / 100;
- return {
- h: constrainHue(h),
- s: t + l ? 200 * t / (t + l) / 100 : 0,
- v: (t + l) / 100,
- a,
- };
- }
-
- function HSVtoHSL({h, s, v}) {
- const l = (2 - s) * v / 2;
- const t = l < .5 ? l * 2 : 2 - l * 2;
- return {
- h: Math.round(constrainHue(h)),
- s: Math.round(t ? s * v / t * 100 : 0),
- l: Math.round(l * 100),
- };
+ function alphaToString(a = HSV.a) {
+ return colorConverter.formatAlpha(a);
}
function currentColorToString(format = currentFormat, alpha = HSV.a) {
- const converted = format === 'hsl' ? HSVtoHSL(HSV) : HSVtoRGB(HSV);
+ const converted = format === 'hsl' ?
+ colorConverter.HSVtoHSL(HSV) :
+ colorConverter.HSVtoRGB(HSV);
converted.a = isNaN(alpha) || alpha === 1 ? undefined : alpha;
return colorToString(converted, format);
}
@@ -887,10 +762,6 @@
return HUE_COLORS[0].hex;
}
- function alphaToString(a = HSV.a) {
- return isNaN(a) ? '' : (a + .5e-6).toFixed(7).slice(0, -1).replace(/^0(?=\.[1-9])|^1\.0+?$|\.?0+$/g, '');
- }
-
//endregion
//region Miscellaneous utilities
@@ -964,11 +835,6 @@
return value < min ? min : value > max ? max : value;
}
- function snapToInt(num) {
- const int = Math.round(num);
- return Math.abs(int - num) < 1e-3 ? int : num;
- }
-
function parseAs(el, parser) {
const num = parser(el.value);
if (!isNaN(num) &&
diff --git a/vendor-overwrites/colorpicker/colorview.js b/vendor-overwrites/colorpicker/colorview.js
index ab088665..f6750713 100644
--- a/vendor-overwrites/colorpicker/colorview.js
+++ b/vendor-overwrites/colorpicker/colorview.js
@@ -1,159 +1,6 @@
-/* global CodeMirror */
+/* global CodeMirror colorConverter */
'use strict';
-const NAMED_COLORS = new Map([
- ['transparent', 'rgba(0, 0, 0, 0)'],
- // CSS4 named colors
- ['aliceblue', '#f0f8ff'],
- ['antiquewhite', '#faebd7'],
- ['aqua', '#00ffff'],
- ['aquamarine', '#7fffd4'],
- ['azure', '#f0ffff'],
- ['beige', '#f5f5dc'],
- ['bisque', '#ffe4c4'],
- ['black', '#000000'],
- ['blanchedalmond', '#ffebcd'],
- ['blue', '#0000ff'],
- ['blueviolet', '#8a2be2'],
- ['brown', '#a52a2a'],
- ['burlywood', '#deb887'],
- ['cadetblue', '#5f9ea0'],
- ['chartreuse', '#7fff00'],
- ['chocolate', '#d2691e'],
- ['coral', '#ff7f50'],
- ['cornflowerblue', '#6495ed'],
- ['cornsilk', '#fff8dc'],
- ['crimson', '#dc143c'],
- ['cyan', '#00ffff'],
- ['darkblue', '#00008b'],
- ['darkcyan', '#008b8b'],
- ['darkgoldenrod', '#b8860b'],
- ['darkgray', '#a9a9a9'],
- ['darkgrey', '#a9a9a9'],
- ['darkgreen', '#006400'],
- ['darkkhaki', '#bdb76b'],
- ['darkmagenta', '#8b008b'],
- ['darkolivegreen', '#556b2f'],
- ['darkorange', '#ff8c00'],
- ['darkorchid', '#9932cc'],
- ['darkred', '#8b0000'],
- ['darksalmon', '#e9967a'],
- ['darkseagreen', '#8fbc8f'],
- ['darkslateblue', '#483d8b'],
- ['darkslategray', '#2f4f4f'],
- ['darkslategrey', '#2f4f4f'],
- ['darkturquoise', '#00ced1'],
- ['darkviolet', '#9400d3'],
- ['deeppink', '#ff1493'],
- ['deepskyblue', '#00bfff'],
- ['dimgray', '#696969'],
- ['dimgrey', '#696969'],
- ['dodgerblue', '#1e90ff'],
- ['firebrick', '#b22222'],
- ['floralwhite', '#fffaf0'],
- ['forestgreen', '#228b22'],
- ['fuchsia', '#ff00ff'],
- ['gainsboro', '#dcdcdc'],
- ['ghostwhite', '#f8f8ff'],
- ['gold', '#ffd700'],
- ['goldenrod', '#daa520'],
- ['gray', '#808080'],
- ['grey', '#808080'],
- ['green', '#008000'],
- ['greenyellow', '#adff2f'],
- ['honeydew', '#f0fff0'],
- ['hotpink', '#ff69b4'],
- ['indianred', '#cd5c5c'],
- ['indigo', '#4b0082'],
- ['ivory', '#fffff0'],
- ['khaki', '#f0e68c'],
- ['lavender', '#e6e6fa'],
- ['lavenderblush', '#fff0f5'],
- ['lawngreen', '#7cfc00'],
- ['lemonchiffon', '#fffacd'],
- ['lightblue', '#add8e6'],
- ['lightcoral', '#f08080'],
- ['lightcyan', '#e0ffff'],
- ['lightgoldenrodyellow', '#fafad2'],
- ['lightgray', '#d3d3d3'],
- ['lightgrey', '#d3d3d3'],
- ['lightgreen', '#90ee90'],
- ['lightpink', '#ffb6c1'],
- ['lightsalmon', '#ffa07a'],
- ['lightseagreen', '#20b2aa'],
- ['lightskyblue', '#87cefa'],
- ['lightslategray', '#778899'],
- ['lightslategrey', '#778899'],
- ['lightsteelblue', '#b0c4de'],
- ['lightyellow', '#ffffe0'],
- ['lime', '#00ff00'],
- ['limegreen', '#32cd32'],
- ['linen', '#faf0e6'],
- ['magenta', '#ff00ff'],
- ['maroon', '#800000'],
- ['mediumaquamarine', '#66cdaa'],
- ['mediumblue', '#0000cd'],
- ['mediumorchid', '#ba55d3'],
- ['mediumpurple', '#9370db'],
- ['mediumseagreen', '#3cb371'],
- ['mediumslateblue', '#7b68ee'],
- ['mediumspringgreen', '#00fa9a'],
- ['mediumturquoise', '#48d1cc'],
- ['mediumvioletred', '#c71585'],
- ['midnightblue', '#191970'],
- ['mintcream', '#f5fffa'],
- ['mistyrose', '#ffe4e1'],
- ['moccasin', '#ffe4b5'],
- ['navajowhite', '#ffdead'],
- ['navy', '#000080'],
- ['oldlace', '#fdf5e6'],
- ['olive', '#808000'],
- ['olivedrab', '#6b8e23'],
- ['orange', '#ffa500'],
- ['orangered', '#ff4500'],
- ['orchid', '#da70d6'],
- ['palegoldenrod', '#eee8aa'],
- ['palegreen', '#98fb98'],
- ['paleturquoise', '#afeeee'],
- ['palevioletred', '#db7093'],
- ['papayawhip', '#ffefd5'],
- ['peachpuff', '#ffdab9'],
- ['peru', '#cd853f'],
- ['pink', '#ffc0cb'],
- ['plum', '#dda0dd'],
- ['powderblue', '#b0e0e6'],
- ['purple', '#800080'],
- ['rebeccapurple', '#663399'],
- ['red', '#ff0000'],
- ['rosybrown', '#bc8f8f'],
- ['royalblue', '#4169e1'],
- ['saddlebrown', '#8b4513'],
- ['salmon', '#fa8072'],
- ['sandybrown', '#f4a460'],
- ['seagreen', '#2e8b57'],
- ['seashell', '#fff5ee'],
- ['sienna', '#a0522d'],
- ['silver', '#c0c0c0'],
- ['skyblue', '#87ceeb'],
- ['slateblue', '#6a5acd'],
- ['slategray', '#708090'],
- ['slategrey', '#708090'],
- ['snow', '#fffafa'],
- ['springgreen', '#00ff7f'],
- ['steelblue', '#4682b4'],
- ['tan', '#d2b48c'],
- ['teal', '#008080'],
- ['thistle', '#d8bfd8'],
- ['tomato', '#ff6347'],
- ['turquoise', '#40e0d0'],
- ['violet', '#ee82ee'],
- ['wheat', '#f5deb3'],
- ['white', '#ffffff'],
- ['whitesmoke', '#f5f5f5'],
- ['yellow', '#ffff00'],
- ['yellowgreen', '#9acd32'],
-]);
-
(() => {
//region Constants
@@ -193,8 +40,12 @@ const NAMED_COLORS = new Map([
!CSS.supports('color', 'hsl(1turn, 2%, 3%)') && /deg|g?rad|turn/,
].filter(Boolean).map(rx => rx.source).join('|') || '^$', 'i'),
};
- const RX_DETECT = new RegExp('(^|[\\s():,/])(' + RX_COLOR.hex.source +
- '|(?:rgb|hsl)a?(?=\\()|(?:' + [...NAMED_COLORS.keys()].join('|') + ')(?=[\\s;()/]|$))', 'gi');
+ const RX_DETECT = new RegExp('(^|[\\s():,/])' +
+ '(' +
+ RX_COLOR.hex.source + '|' +
+ '(?:rgb|hsl)a?(?=\\()|(?:' + [...colorConverter.NAMED_COLORS.keys()].join('|') + ')' +
+ '(?=[\\s;()/]|$)' +
+ ')', 'gi');
const RX_DETECT_FUNC = /(rgb|hsl)a?\(/iy;
const RX_COMMENT = /\/\*(?:.(?!\*\/))*(?:.?\*\/|$)/g;
@@ -532,7 +383,7 @@ const NAMED_COLORS = new Map([
function checkColor() {
if (isHex) return testAt(RX_COLOR.hex, 0, color);
- if (!isFunc) return NAMED_COLORS.has(color.toLowerCase());
+ if (!isFunc) return colorConverter.NAMED_COLORS.has(color.toLowerCase());
const colorLower = color.toLowerCase();
if (cache.has(colorLower)) return true;
@@ -558,8 +409,8 @@ const NAMED_COLORS = new Map([
function getSafeColorValue() {
if (isHex && color.length !== 5 && color.length !== 9) return color;
if (!isFunc || !RX_COLOR.unsupported.test(color)) return color;
- const value = state.popup.stringToColor(color);
- return state.popup.colorToString(value, 'rgb');
+ const value = colorConverter.parse(color);
+ return colorConverter.format(value, 'rgb');
}
// update or skip or delete existing swatches
@@ -734,7 +585,7 @@ const NAMED_COLORS = new Map([
const value = color.slice(token.length + 1, -1);
return testAt(RX_COLOR[type], 0, value) && color;
}
- return (token[0] === '#' || NAMED_COLORS.has(token)) && token;
+ return (token[0] === '#' || colorConverter.NAMED_COLORS.has(token)) && token;
}
}