UNPKG

color-tf

Version:

RGB, HSL, HSV, HWB and more color models convertors

104 lines (90 loc) 3.11 kB
'use strict'; var hsl2hsv = require('./hsl2hsv.js'); var hsl2rgb = require('./hsl2rgb.js'); var hsv2hsl = require('./hsv2hsl.js'); var hsv2hwb = require('./hsv2hwb.js'); var hsv2rgb = require('./hsv2rgb.js'); var hwb2hsv = require('./hwb2hsv.js'); var hwb2rgb = require('./hwb2rgb.js'); var rgb2hsl = require('./rgb2hsl.js'); var rgb2hsv = require('./rgb2hsv.js'); var rgb2hwb = require('./rgb2hwb.js'); var rgbToHex = require('./rgbToHex.js'); var hexToRgb = require('./hexToRgb.js'); var lib = /*#__PURE__*/Object.freeze({ hsl2hsv: hsl2hsv, hsl2rgb: hsl2rgb, hsv2hsl: hsv2hsl, hsv2hwb: hsv2hwb, hsv2rgb: hsv2rgb, hwb2hsv: hwb2hsv, hwb2rgb: hwb2rgb, rgb2hsl: rgb2hsl, rgb2hsv: rgb2hsv, rgb2hwb: rgb2hwb }); /** * @return fns to compose between 2 keys in lib object e.g. fns.reduceRight((fn, f) => (...a) => f(...fn(...a))) */ var getFnPath = (lib, fromKey, toKey) => { let nodes = [fromKey]; const visited = new Map(); // map node key => parent key while (nodes.length) { // search breadth-first const newNodes = []; for (const k of nodes) { if (lib[k + '2' + toKey]) { // done, we can stop const fns = [`${k}2${toKey}`]; for (let key = k; visited.has(key) && key !== fromKey; key = visited.get(key)) { fns.push(`${visited.get(key)}2${key}`); } return fns; } Object.keys(lib) .filter(s => s.slice(0, 3) === k) .map(s => s.slice(4)) .filter(key => !visited.has(key)) .forEach(key => { visited.set(key, k); newNodes.push(key); }); } nodes = newNodes; } }; const roundH = ([h, s, l]) => [Math.round(360 * h) % 360, Math.round(100 * s), Math.round(100 * l)]; /** * all functions available from a Proxy (to generate missing ones dynamically) * foo2bar for functions with input/output in [0, 1] * fooToBar for functions with natural inputs [0,255] for r,g,b, [0,360[ for hue, [0, 100] for the rest */ var proxy = new Proxy( new Map([...Object.entries(lib), ['rgbToHex', rgbToHex], ['hexToRgb', hexToRgb]]), { get: (map, key) => { if (typeof key !== 'string') return map; if (map.has(key)) return map.get(key); const fromKey = key.slice(0, 3); const toKey = key.slice(-3).toLowerCase(); const k = fromKey + '2' + toKey; let fn = lib[k]; if (!fn) { // todo check fromKey, toKey are in available keys, else getPath might be in infinite loop const fns = getFnPath(lib, fromKey, toKey).map(n => lib[n]); fn = fns.reduceRight((f, g) => (...a) => g(...f(...a))); map.set(k, fn); } if (key[3] === '2') return fn; const K = fromKey + 'To' + toKey[0].toUpperCase() + toKey.slice(1); const FN = fromKey === 'rgb' ? (r, g, b) => roundH(fn(r / 255, g / 255, b / 255)) : toKey === 'rgb' ? (h, x, y) => fn(h / 360, x / 100, y / 100).map(v => Math.round(v * 255)) : (h, x, y) => roundH(fn(h / 360, x / 100, y / 100)); map.set(K, FN); return FN; } } ); module.exports = proxy;