| |
|
| |
|
| | const float = '-?\\d*(?:\\.\\d+)';
|
| | export const number = `(${float}?)`;
|
| | export const percentage = `(${float}?%)`;
|
| | export const numberOrPercentage = `(${float}?%?)`;
|
| | const clamp = (num, min, max) => Math.min(Math.max(min, num), max);
|
| |
|
| | const hexCharacters = 'a-f\\d';
|
| | const match3or4Hex = `#?[${hexCharacters}]{3}[${hexCharacters}]?`;
|
| | const match6or8Hex = `#?[${hexCharacters}]{6}([${hexCharacters}]{2})?`;
|
| | const nonHexChars = new RegExp(`[^#${hexCharacters}]`, 'gi');
|
| | const validHexSize = new RegExp(`^${match3or4Hex}$|^${match6or8Hex}$`, 'i');
|
| |
|
| |
|
| | export const hex_pattern = new RegExp(/^#([a-f0-9]{3,4}|[a-f0-9]{4}(?:[a-f0-9]{2}){1,2})\b$/, "i");
|
| |
|
| | export const hsl3_pattern = new RegExp(`^
|
| | hsla?\\(
|
| | \\s*(-?\\d*(?:\\.\\d+)?(?:deg|rad|turn)?)\\s*,
|
| | \\s*${percentage}\\s*,
|
| | \\s*${percentage}\\s*
|
| | (?:,\\s*${numberOrPercentage}\\s*)?
|
| | \\)
|
| | $
|
| | `.replace(/\n|\s/g, ''))
|
| |
|
| | export const hsl4_pattern = new RegExp(`^
|
| | hsla?\\(
|
| | \\s*(-?\\d*(?:\\.\\d+)?(?:deg|rad|turn)?)\\s*
|
| | \\s+${percentage}
|
| | \\s+${percentage}
|
| | \\s*(?:\\s*\\/\\s*${numberOrPercentage}\\s*)?
|
| | \\)
|
| | $
|
| | `.replace(/\n|\s/g, ''))
|
| |
|
| | export const rgb3_pattern = new RegExp(`^
|
| | rgba?\\(
|
| | \\s*${number}\\s*,
|
| | \\s*${number}\\s*,
|
| | \\s*${number}\\s*
|
| | (?:,\\s*${numberOrPercentage}\\s*)?
|
| | \\)
|
| | $
|
| | `.replace(/\n|\s/g, ''))
|
| |
|
| | export const rgb4_pattern = new RegExp(`^
|
| | rgba?\\(
|
| | \\s*${number}
|
| | \\s+${number}
|
| | \\s+${number}
|
| | \\s*(?:\\s*\\/\\s*${numberOrPercentage}\\s*)?
|
| | \\)
|
| | $
|
| | `.replace(/\n|\s/g, ''));
|
| |
|
| | export const transparent_pattern = new RegExp(/^transparent$/, 'i');
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | const parseRGB = (num) => {
|
| | let n = num;
|
| | if (typeof n !== 'number') {
|
| | n = n.endsWith('%') ? (parseFloat(n) * 255) / 100 : parseFloat(n);
|
| | }
|
| | return clamp(Math.round(n), 0, 255);
|
| | };
|
| |
|
| |
|
| | const parsePercentage = (percentage) => clamp(parseFloat(percentage), 0, 100);
|
| |
|
| |
|
| | function parseAlpha(alpha) {
|
| | let a = alpha;
|
| | if (typeof a !== 'number') {
|
| | a = a.endsWith('%') ? parseFloat(a) / 100 : parseFloat(a);
|
| | }
|
| | return clamp(a, 0, 1);
|
| | }
|
| |
|
| | export function getHEX(hex) {
|
| | const [r, g, b, a] = hex2Rgb(hex, { format: 'array' });
|
| | return getRGB([null, ...[r, g, b, a]]);
|
| | }
|
| |
|
| | export function getHSL([, h, s, l, a = 1]) {
|
| | let hh = h;
|
| | if (hh.endsWith('turn')) {
|
| | hh = (parseFloat(hh) * 360) / 1;
|
| | } else if (hh.endsWith('rad')) {
|
| | hh = Math.round((parseFloat(hh) * 180) / Math.PI);
|
| | } else {
|
| | hh = parseFloat(hh);
|
| | }
|
| | return {
|
| | type: 'hsl',
|
| | values: [hh, parsePercentage(s), parsePercentage(l)],
|
| | alpha: parseAlpha(a === null ? 1 : a)
|
| | };
|
| | }
|
| |
|
| | export function getRGB([, r, g, b, a = 1]) {
|
| | return {
|
| | type: 'rgb',
|
| | values: [r, g, b].map(parseRGB),
|
| | alpha: parseAlpha(a === null ? 1 : a)
|
| | };
|
| | }
|
| | export function hex2Rgb(hex, options = {}) {
|
| | if (typeof hex !== 'string' || nonHexChars.test(hex) || !validHexSize.test(hex)) {
|
| | throw new TypeError('Expected a valid hex string');
|
| | }
|
| |
|
| | hex = hex.replace(/^#/, '');
|
| | let alphaFromHex = 1;
|
| |
|
| | if (hex.length === 8) {
|
| | alphaFromHex = Number.parseInt(hex.slice(6, 8), 16) / 255;
|
| | hex = hex.slice(0, 6);
|
| | }
|
| |
|
| | if (hex.length === 4) {
|
| | alphaFromHex = Number.parseInt(hex.slice(3, 4).repeat(2), 16) / 255;
|
| | hex = hex.slice(0, 3);
|
| | }
|
| |
|
| | if (hex.length === 3) {
|
| | hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
| | }
|
| |
|
| | const number = Number.parseInt(hex, 16);
|
| | const red = number >> 16;
|
| | const green = (number >> 8) & 255;
|
| | const blue = number & 255;
|
| | const alpha = typeof options.alpha === 'number' ? options.alpha : alphaFromHex;
|
| |
|
| | if (options.format === 'array') {
|
| | return [red, green, blue, alpha];
|
| | }
|
| |
|
| | if (options.format === 'css') {
|
| | const alphaString = alpha === 1 ? '' : ` / ${Number((alpha * 100).toFixed(2))}%`;
|
| | return `rgb(${red} ${green} ${blue}${alphaString})`;
|
| | }
|
| |
|
| | return {red, green, blue, alpha};
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | export const colorName = {
|
| | 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]
|
| | }
|
| |
|
| |
|
| |
|
| | export const parseCSSColor = (str, debug=false) => {
|
| | if (typeof str !== 'string') {
|
| | console.error(`parseCSSColor: expected a string found ${typeof str}`,str);
|
| | return null;
|
| | }
|
| |
|
| | const hex = hex_pattern.exec(str);
|
| | if (hex) {
|
| | if (debug){
|
| | console.debug('parseCSSColor: hex', hex);
|
| | }
|
| | return getHEX(hex[0]);
|
| | }
|
| |
|
| | const hsl = hsl4_pattern.exec(str) || hsl3_pattern.exec(str);
|
| | if (hsl) {
|
| | if (debug){
|
| | console.debug('parseCSSColor: hsl', hsl);
|
| | }
|
| | return getHSL(hsl);
|
| | }
|
| |
|
| | const rgb =
|
| | rgb4_pattern.exec(str) ||
|
| | rgb3_pattern.exec(str)
|
| | if (rgb) {
|
| | if (debug){
|
| | console.debug('parseCSSColor: rgb', rgb);
|
| | }
|
| | return getRGB(rgb);
|
| | }
|
| |
|
| | if (transparent_pattern.exec(str)) {
|
| | if (debug){
|
| | console.debug('parseCSSColor: transparent');
|
| | }
|
| | return getRGB([null, 0, 0, 0, 0]);
|
| | }
|
| |
|
| | const cn = colorName[str.toLowerCase()];
|
| | if (cn) {
|
| | if (debug){
|
| | console.debug('parseCSSColor: colorName', cn);
|
| | }
|
| | return getRGB([null, cn[0], cn[1], cn[2], 1]);
|
| | }
|
| |
|
| | console.error('parseCSSColor: unknown color', str);
|
| | return null;
|
| | };
|
| |
|
| | export default parseCSSColor;
|
| |
|
| |
|