color.js
1 let ParsedColor = null; 2 3 // Essential: A simple color class returned from {Config::get} when the value 4 // at the key path is of type 'color'. 5 module.exports = class Color { 6 // Essential: Parse a {String} or {Object} into a {Color}. 7 // 8 // * `value` A {String} such as `'white'`, `#ff00ff`, or 9 // `'rgba(255, 15, 60, .75)'` or an {Object} with `red`, `green`, `blue`, 10 // and `alpha` properties. 11 // 12 // Returns a {Color} or `null` if it cannot be parsed. 13 static parse(value) { 14 switch (typeof value) { 15 case 'string': 16 break; 17 case 'object': 18 if (Array.isArray(value)) { 19 return null; 20 } 21 break; 22 default: 23 return null; 24 } 25 26 if (!ParsedColor) { 27 ParsedColor = require('color'); 28 } 29 30 try { 31 var parsedColor = new ParsedColor(value); 32 } catch (error) { 33 return null; 34 } 35 36 return new Color( 37 parsedColor.red(), 38 parsedColor.green(), 39 parsedColor.blue(), 40 parsedColor.alpha() 41 ); 42 } 43 44 constructor(red, green, blue, alpha) { 45 this.red = red; 46 this.green = green; 47 this.blue = blue; 48 this.alpha = alpha; 49 } 50 51 set red(red) { 52 this._red = parseColor(red); 53 } 54 55 set green(green) { 56 this._green = parseColor(green); 57 } 58 59 set blue(blue) { 60 this._blue = parseColor(blue); 61 } 62 63 set alpha(alpha) { 64 this._alpha = parseAlpha(alpha); 65 } 66 67 get red() { 68 return this._red; 69 } 70 71 get green() { 72 return this._green; 73 } 74 75 get blue() { 76 return this._blue; 77 } 78 79 get alpha() { 80 return this._alpha; 81 } 82 83 // Essential: Returns a {String} in the form `'#abcdef'`. 84 toHexString() { 85 return `#${numberToHexString(this.red)}${numberToHexString( 86 this.green 87 )}${numberToHexString(this.blue)}`; 88 } 89 90 // Essential: Returns a {String} in the form `'rgba(25, 50, 75, .9)'`. 91 toRGBAString() { 92 return `rgba(${this.red}, ${this.green}, ${this.blue}, ${this.alpha})`; 93 } 94 95 toJSON() { 96 return this.alpha === 1 ? this.toHexString() : this.toRGBAString(); 97 } 98 99 toString() { 100 return this.toRGBAString(); 101 } 102 103 isEqual(color) { 104 if (this === color) { 105 return true; 106 } 107 108 if (!(color instanceof Color)) { 109 color = Color.parse(color); 110 } 111 112 if (color == null) { 113 return false; 114 } 115 116 return ( 117 color.red === this.red && 118 color.blue === this.blue && 119 color.green === this.green && 120 color.alpha === this.alpha 121 ); 122 } 123 124 clone() { 125 return new Color(this.red, this.green, this.blue, this.alpha); 126 } 127 }; 128 129 function parseColor(colorString) { 130 const color = parseInt(colorString, 10); 131 return isNaN(color) ? 0 : Math.min(Math.max(color, 0), 255); 132 } 133 134 function parseAlpha(alphaString) { 135 const alpha = parseFloat(alphaString); 136 return isNaN(alpha) ? 1 : Math.min(Math.max(alpha, 0), 1); 137 } 138 139 function numberToHexString(number) { 140 const hex = number.toString(16); 141 return number < 16 ? `0${hex}` : hex; 142 }