diff --git a/src/color.coffee b/src/color.coffee deleted file mode 100644 index b413b9e2c..000000000 --- a/src/color.coffee +++ /dev/null @@ -1,89 +0,0 @@ -_ = require 'underscore-plus' -ParsedColor = null - -# Essential: A simple color class returned from {Config::get} when the value -# at the key path is of type 'color'. -module.exports = -class Color - # Essential: Parse a {String} or {Object} into a {Color}. - # - # * `value` A {String} such as `'white'`, `#ff00ff`, or - # `'rgba(255, 15, 60, .75)'` or an {Object} with `red`, `green`, `blue`, - # and `alpha` properties. - # - # Returns a {Color} or `null` if it cannot be parsed. - @parse: (value) -> - return null if _.isArray(value) or _.isFunction(value) - return null unless _.isObject(value) or _.isString(value) - - ParsedColor ?= require 'color' - - try - parsedColor = new ParsedColor(value) - catch error - return null - - new Color(parsedColor.red(), parsedColor.green(), parsedColor.blue(), parsedColor.alpha()) - - constructor: (red, green, blue, alpha) -> - Object.defineProperties this, - red: - set: (newRed) -> red = parseColor(newRed) - get: -> red - enumerable: true - configurable: false - green: - set: (newGreen) -> green = parseColor(newGreen) - get: -> green - enumerable: true - configurable: false - blue: - set: (newBlue) -> blue = parseColor(newBlue) - get: -> blue - enumerable: true - configurable: false - alpha: - set: (newAlpha) -> alpha = parseAlpha(newAlpha) - get: -> alpha - enumerable: true - configurable: false - - @red = red - @green = green - @blue = blue - @alpha = alpha - - # Essential: Returns a {String} in the form `'#abcdef'`. - toHexString: -> - "##{numberToHexString(@red)}#{numberToHexString(@green)}#{numberToHexString(@blue)}" - - # Essential: Returns a {String} in the form `'rgba(25, 50, 75, .9)'`. - toRGBAString: -> - "rgba(#{@red}, #{@green}, #{@blue}, #{@alpha})" - - isEqual: (color) -> - return true if this is color - color = Color.parse(color) unless color instanceof Color - return false unless color? - color.red is @red and color.blue is @blue and color.green is @green and color.alpha is @alpha - - clone: -> new Color(@red, @green, @blue, @alpha) - -parseColor = (color) -> - color = parseInt(color) - color = 0 if isNaN(color) - color = Math.max(color, 0) - color = Math.min(color, 255) - color - -parseAlpha = (alpha) -> - alpha = parseFloat(alpha) - alpha = 1 if isNaN(alpha) - alpha = Math.max(alpha, 0) - alpha = Math.min(alpha, 1) - alpha - -numberToHexString = (number) -> - hex = number.toString(16) - hex = "0#{hex}" if number < 16 - hex diff --git a/src/color.js b/src/color.js new file mode 100644 index 000000000..9db9e9b16 --- /dev/null +++ b/src/color.js @@ -0,0 +1,134 @@ +/** @babel */ + +let ParsedColor = null + +// Essential: A simple color class returned from {Config::get} when the value +// at the key path is of type 'color'. +export default class Color { + // Essential: Parse a {String} or {Object} into a {Color}. + // + // * `value` A {String} such as `'white'`, `#ff00ff`, or + // `'rgba(255, 15, 60, .75)'` or an {Object} with `red`, `green`, `blue`, + // and `alpha` properties. + // + // Returns a {Color} or `null` if it cannot be parsed. + static parse (value) { + switch (typeof value) { + case 'string': + break + case 'object': + if (Array.isArray(value)) { return null } + break + default: + return null + } + + if (!ParsedColor) { + ParsedColor = require('color') + } + + try { + var parsedColor = new ParsedColor(value) + } catch (error) { + return null + } + + return new Color(parsedColor.red(), parsedColor.green(), parsedColor.blue(), parsedColor.alpha()) + } + + constructor (red, green, blue, alpha) { + this.red = red + this.green = green + this.blue = blue + this.alpha = alpha + } + + set red (red) { + this._red = parseColor(red) + } + + set green (green) { + this._green = parseColor(green) + } + + set blue (blue) { + this._blue = parseColor(blue) + } + + set alpha (alpha) { + this._alpha = parseAlpha(alpha) + } + + get red () { + return this._red + } + + get green () { + return this._green + } + + get blue () { + return this._blue + } + + get alpha () { + return this._alpha + } + + // Essential: Returns a {String} in the form `'#abcdef'`. + toHexString () { + return `#${numberToHexString(this.red)}${numberToHexString(this.green)}${numberToHexString(this.blue)}` + } + + // Essential: Returns a {String} in the form `'rgba(25, 50, 75, .9)'`. + toRGBAString () { + return `rgba(${this.red}, ${this.green}, ${this.blue}, ${this.alpha})` + } + + isEqual (color) { + if (this === color) { + return true + } + + if (!(color instanceof Color)) { + color = Color.parse(color) + } + + if (color == null) { + return false + } + + return color.red === this.red && color.blue === this.blue && color.green === this.green && color.alpha === this.alpha + } + + clone () { + return new Color(this.red, this.green, this.blue, this.alpha) + } +} + +function parseColor (colorString) { + const color = parseInt(colorString, 10) + if (isNaN(color)) { + return 0 + } else { + return Math.min(Math.max(color, 0), 255) + } +} + +function parseAlpha (alphaString) { + const alpha = parseFloat(alphaString) + if (isNaN(alpha)) { + return 1 + } else { + return Math.min(Math.max(alpha, 0), 1) + } +} + +function numberToHexString (number) { + const hex = number.toString(16) + if (number < 16) { + return `0${hex}` + } else { + return hex + } +}