pax_global_header00006660000000000000000000000064131251235100014503gustar00rootroot0000000000000052 comment=8e6724a288b330fedc29318b52c841c94a8b2ade color-2.0.0/000077500000000000000000000000001312512351000126205ustar00rootroot00000000000000color-2.0.0/.editorconfig000066400000000000000000000004101312512351000152700ustar00rootroot00000000000000root = true [*] indent_style = tab end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.coffee] indent_style = space [{package.json,*.yml}] indent_style = space indent_size = 2 [*.md] trim_trailing_whitespace = false color-2.0.0/.gitignore000066400000000000000000000000151312512351000146040ustar00rootroot00000000000000node_modules color-2.0.0/.travis.yml000066400000000000000000000000661312512351000147330ustar00rootroot00000000000000sudo: false language: node_js node_js: - 0.12 - 4 color-2.0.0/CONTRIBUTING.md000066400000000000000000000012341312512351000150510ustar00rootroot00000000000000Thanks for taking the time to contribute to color.js. Follow these guidelines to make the process smoother: 1. One feature per pull request. Each PR should have one focus, and all the code changes should be supporting that one feature or bug fix. Using a [separate branch](https://guides.github.com/introduction/flow/index.html) for each feature should help you manage developing multiple features at once. 2. Follow the style of the file when it comes to syntax like curly braces and indents. 3. Add a test for the feature or fix, if possible. See the `test` directory for existing tests and README describing how to run these tests. 4. Run tests with `npm test` color-2.0.0/LICENSE000066400000000000000000000020431312512351000136240ustar00rootroot00000000000000Copyright (c) 2012 Heather Arthur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. color-2.0.0/README.md000066400000000000000000000064031312512351000141020ustar00rootroot00000000000000# color [![Build Status](https://travis-ci.org/Qix-/color.svg?branch=master)](https://travis-ci.org/Qix-/color) > JavaScript library for immutable color conversion and manipulation with support for CSS color strings. ```js var color = Color('#7743CE').alpha(0.5).lighten(0.5); console.log(color.hsl().string()); // 'hsla(262, 59%, 81%, 0.5)' console.log(color.cmyk().round().array()); // [ 16, 25, 0, 8, 0.5 ] console.log(color.ansi256().object()); // { ansi256: 183, alpha: 0.5 } ``` ## Install ```console $ npm install color ``` ## Usage ```js var Color = require('color'); ``` ### Constructors ```js var color = Color('rgb(255, 255, 255)') var color = Color({r: 255, g: 255, b: 255}) var color = Color.rgb(255, 255, 255) var color = Color.rgb([255, 255, 255]) ``` Set the values for individual channels with `alpha`, `red`, `green`, `blue`, `hue`, `saturation` (hsl), `saturationv` (hsv), `lightness`, `whiteness`, `blackness`, `cyan`, `magenta`, `yellow`, `black` ### Getters ```js color.hsl(); ``` Convert a color to a different space (`hsl()`, `cmyk()`, etc.). ```js color.object(); // {r: 255, g: 255, b: 255} ``` Get a hash of the color value. Reflects the color's current model (see above). ```js color.rgb().array() // [255, 255, 255] ``` Get an array of the values with `array()`. Reflects the color's current model (see above). ```js color.rgbNumber() // 16777215 (0xffffff) ``` Get the rgb number value. ```js color.red() // 255 ``` Get the value for an individual channel. ### CSS Strings ```js color.hsl().string() // 'hsl(320, 50%, 100%)' ``` Calling `.string()` with a number rounds the numbers to that decimal place. It defaults to 1. ### Luminosity ```js color.luminosity(); // 0.412 ``` The [WCAG luminosity](http://www.w3.org/TR/WCAG20/#relativeluminancedef) of the color. 0 is black, 1 is white. ```js color.contrast(Color("blue")) // 12 ``` The [WCAG contrast ratio](http://www.w3.org/TR/WCAG20/#contrast-ratiodef) to another color, from 1 (same color) to 21 (contrast b/w white and black). ```js color.light(); // true color.dark(); // false ``` Get whether the color is "light" or "dark", useful for deciding text color. ### Manipulation ```js color.negate() // rgb(0, 100, 255) -> rgb(255, 155, 0) color.lighten(0.5) // hsl(100, 50%, 50%) -> hsl(100, 50%, 75%) color.darken(0.5) // hsl(100, 50%, 50%) -> hsl(100, 50%, 25%) color.saturate(0.5) // hsl(100, 50%, 50%) -> hsl(100, 75%, 50%) color.desaturate(0.5) // hsl(100, 50%, 50%) -> hsl(100, 25%, 50%) color.grayscale() // #5CBF54 -> #969696 color.whiten(0.5) // hwb(100, 50%, 50%) -> hwb(100, 75%, 50%) color.blacken(0.5) // hwb(100, 50%, 50%) -> hwb(100, 50%, 75%) color.fade(0.5) // rgba(10, 10, 10, 0.8) -> rgba(10, 10, 10, 0.4) color.opaquer(0.5) // rgba(10, 10, 10, 0.8) -> rgba(10, 10, 10, 1.0) color.rotate(180) // hsl(60, 20%, 20%) -> hsl(240, 20%, 20%) color.rotate(-90) // hsl(60, 20%, 20%) -> hsl(330, 20%, 20%) color.mix(Color("yellow")) // cyan -> rgb(128, 255, 128) color.mix(Color("yellow"), 0.3) // cyan -> rgb(77, 255, 179) // chaining color.green(100).grayscale().lighten(0.6) ``` ## Propers The API was inspired by [color-js](https://github.com/brehaut/color-js). Manipulation functions by CSS tools like Sass, LESS, and Stylus. color-2.0.0/index.js000066400000000000000000000252331312512351000142720ustar00rootroot00000000000000'use strict'; var colorString = require('color-string'); var convert = require('color-convert'); var _slice = [].slice; var skippedModels = [ // to be honest, I don't really feel like keyword belongs in color convert, but eh. 'keyword', // gray conflicts with some method names, and has its own method defined. 'gray', // shouldn't really be in color-convert either... 'hex' ]; var hashedModelKeys = {}; Object.keys(convert).forEach(function (model) { hashedModelKeys[_slice.call(convert[model].labels).sort().join('')] = model; }); var limiters = {}; function Color(obj, model) { if (!(this instanceof Color)) { return new Color(obj, model); } if (model && model in skippedModels) { model = null; } if (model && !(model in convert)) { throw new Error('Unknown model: ' + model); } var i; var channels; if (!obj) { this.model = 'rgb'; this.color = [0, 0, 0]; this.valpha = 1; } else if (obj instanceof Color) { this.model = obj.model; this.color = obj.color.slice(); this.valpha = obj.valpha; } else if (typeof obj === 'string') { var result = colorString.get(obj); if (result === null) { throw new Error('Unable to parse color from string: ' + obj); } this.model = result.model; channels = convert[this.model].channels; this.color = result.value.slice(0, channels); this.valpha = typeof result.value[channels] === 'number' ? result.value[channels] : 1; } else if (obj.length) { this.model = model || 'rgb'; channels = convert[this.model].channels; var newArr = _slice.call(obj, 0, channels); this.color = zeroArray(newArr, channels); this.valpha = typeof obj[channels] === 'number' ? obj[channels] : 1; } else if (typeof obj === 'number') { // this is always RGB - can be converted later on. obj &= 0xFFFFFF; this.model = 'rgb'; this.color = [ (obj >> 16) & 0xFF, (obj >> 8) & 0xFF, obj & 0xFF ]; this.valpha = 1; } else { this.valpha = 1; var keys = Object.keys(obj); if ('alpha' in obj) { keys.splice(keys.indexOf('alpha'), 1); this.valpha = typeof obj.alpha === 'number' ? obj.alpha : 0; } var hashedKeys = keys.sort().join(''); if (!(hashedKeys in hashedModelKeys)) { throw new Error('Unable to parse color from object: ' + JSON.stringify(obj)); } this.model = hashedModelKeys[hashedKeys]; var labels = convert[this.model].labels; var color = []; for (i = 0; i < labels.length; i++) { color.push(obj[labels[i]]); } this.color = zeroArray(color); } // perform limitations (clamping, etc.) if (limiters[this.model]) { channels = convert[this.model].channels; for (i = 0; i < channels; i++) { var limit = limiters[this.model][i]; if (limit) { this.color[i] = limit(this.color[i]); } } } this.valpha = Math.max(0, Math.min(1, this.valpha)); if (Object.freeze) { Object.freeze(this); } } Color.prototype = { toString: function () { return this.string(); }, toJSON: function () { return this[this.model](); }, string: function (places) { var self = this.model in colorString.to ? this : this.rgb(); self = self.round(typeof places === 'number' ? places : 1); var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); return colorString.to[self.model](args); }, percentString: function (places) { var self = this.rgb().round(typeof places === 'number' ? places : 1); var args = self.valpha === 1 ? self.color : self.color.concat(this.valpha); return colorString.to.rgb.percent(args); }, array: function () { return this.valpha === 1 ? this.color.slice() : this.color.concat(this.valpha); }, object: function () { var result = {}; var channels = convert[this.model].channels; var labels = convert[this.model].labels; for (var i = 0; i < channels; i++) { result[labels[i]] = this.color[i]; } if (this.valpha !== 1) { result.alpha = this.valpha; } return result; }, unitArray: function () { var rgb = this.rgb().color; rgb[0] /= 255; rgb[1] /= 255; rgb[2] /= 255; if (this.valpha !== 1) { rgb.push(this.valpha); } return rgb; }, unitObject: function () { var rgb = this.rgb().object(); rgb.r /= 255; rgb.g /= 255; rgb.b /= 255; if (this.valpha !== 1) { rgb.alpha = this.valpha; } return rgb; }, round: function (places) { places = Math.max(places || 0, 0); return new Color(this.color.map(roundToPlace(places)).concat(this.valpha), this.model); }, alpha: function (val) { if (arguments.length) { return new Color(this.color.concat(Math.max(0, Math.min(1, val))), this.model); } return this.valpha; }, // rgb red: getset('rgb', 0, maxfn(255)), green: getset('rgb', 1, maxfn(255)), blue: getset('rgb', 2, maxfn(255)), hue: getset(['hsl', 'hsv', 'hsl', 'hwb', 'hcg'], 0, function (val) { return ((val % 360) + 360) % 360; }), // eslint-disable-line brace-style saturationl: getset('hsl', 1, maxfn(100)), lightness: getset('hsl', 2, maxfn(100)), saturationv: getset('hsv', 1, maxfn(100)), value: getset('hsv', 2, maxfn(100)), chroma: getset('hcg', 1, maxfn(100)), gray: getset('hcg', 2, maxfn(100)), white: getset('hwb', 1, maxfn(100)), wblack: getset('hwb', 2, maxfn(100)), cyan: getset('cmyk', 0, maxfn(100)), magenta: getset('cmyk', 1, maxfn(100)), yellow: getset('cmyk', 2, maxfn(100)), black: getset('cmyk', 3, maxfn(100)), x: getset('xyz', 0, maxfn(100)), y: getset('xyz', 1, maxfn(100)), z: getset('xyz', 2, maxfn(100)), l: getset('lab', 0, maxfn(100)), a: getset('lab', 1), b: getset('lab', 2), keyword: function (val) { if (arguments.length) { return new Color(val); } return convert[this.model].keyword(this.color); }, hex: function (val) { if (arguments.length) { return new Color(val); } return colorString.to.hex(this.rgb().round().color); }, rgbNumber: function () { var rgb = this.rgb().color; return ((rgb[0] & 0xFF) << 16) | ((rgb[1] & 0xFF) << 8) | (rgb[2] & 0xFF); }, luminosity: function () { // http://www.w3.org/TR/WCAG20/#relativeluminancedef var rgb = this.rgb().color; var lum = []; for (var i = 0; i < rgb.length; i++) { var chan = rgb[i] / 255; lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); } return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; }, contrast: function (color2) { // http://www.w3.org/TR/WCAG20/#contrast-ratiodef var lum1 = this.luminosity(); var lum2 = color2.luminosity(); if (lum1 > lum2) { return (lum1 + 0.05) / (lum2 + 0.05); } return (lum2 + 0.05) / (lum1 + 0.05); }, level: function (color2) { var contrastRatio = this.contrast(color2); if (contrastRatio >= 7.1) { return 'AAA'; } return (contrastRatio >= 4.5) ? 'AA' : ''; }, dark: function () { // YIQ equation from http://24ways.org/2010/calculating-color-contrast var rgb = this.rgb().color; var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; return yiq < 128; }, light: function () { return !this.dark(); }, negate: function () { var rgb = this.rgb(); for (var i = 0; i < 3; i++) { rgb.color[i] = 255 - rgb.color[i]; } return rgb; }, lighten: function (ratio) { var hsl = this.hsl(); hsl.color[2] += hsl.color[2] * ratio; return hsl; }, darken: function (ratio) { var hsl = this.hsl(); hsl.color[2] -= hsl.color[2] * ratio; return hsl; }, saturate: function (ratio) { var hsl = this.hsl(); hsl.color[1] += hsl.color[1] * ratio; return hsl; }, desaturate: function (ratio) { var hsl = this.hsl(); hsl.color[1] -= hsl.color[1] * ratio; return hsl; }, whiten: function (ratio) { var hwb = this.hwb(); hwb.color[1] += hwb.color[1] * ratio; return hwb; }, blacken: function (ratio) { var hwb = this.hwb(); hwb.color[2] += hwb.color[2] * ratio; return hwb; }, grayscale: function () { // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale var rgb = this.rgb().color; var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; return Color.rgb(val, val, val); }, fade: function (ratio) { return this.alpha(this.valpha - (this.valpha * ratio)); }, opaquer: function (ratio) { return this.alpha(this.valpha + (this.valpha * ratio)); }, rotate: function (degrees) { var hsl = this.hsl(); var hue = hsl.color[0]; hue = (hue + degrees) % 360; hue = hue < 0 ? 360 + hue : hue; hsl.color[0] = hue; return hsl; }, mix: function (mixinColor, weight) { // ported from sass implementation in C // https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 var color1 = mixinColor.rgb(); var color2 = this.rgb(); var p = weight === undefined ? 0.5 : weight; var w = 2 * p - 1; var a = color1.alpha() - color2.alpha(); var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; var w2 = 1 - w1; return Color.rgb( w1 * color1.red() + w2 * color2.red(), w1 * color1.green() + w2 * color2.green(), w1 * color1.blue() + w2 * color2.blue(), color1.alpha() * p + color2.alpha() * (1 - p)); } }; // model conversion methods and static constructors Object.keys(convert).forEach(function (model) { if (skippedModels.indexOf(model) !== -1) { return; } var channels = convert[model].channels; // conversion methods Color.prototype[model] = function () { if (this.model === model) { return new Color(this); } if (arguments.length) { return new Color(arguments, model); } var newAlpha = typeof arguments[channels] === 'number' ? channels : this.valpha; return new Color(assertArray(convert[this.model][model].raw(this.color)).concat(newAlpha), model); }; // 'static' construction methods Color[model] = function (color) { if (typeof color === 'number') { color = zeroArray(_slice.call(arguments), channels); } return new Color(color, model); }; }); function roundTo(num, places) { return Number(num.toFixed(places)); } function roundToPlace(places) { return function (num) { return roundTo(num, places); }; } function getset(model, channel, modifier) { model = Array.isArray(model) ? model : [model]; model.forEach(function (m) { (limiters[m] || (limiters[m] = []))[channel] = modifier; }); model = model[0]; return function (val) { var result; if (arguments.length) { if (modifier) { val = modifier(val); } result = this[model](); result.color[channel] = val; return result; } result = this[model]().color[channel]; if (modifier) { result = modifier(result); } return result; }; } function maxfn(max) { return function (v) { return Math.max(0, Math.min(max, v)); }; } function assertArray(val) { return Array.isArray(val) ? val : [val]; } function zeroArray(arr, length) { for (var i = 0; i < length; i++) { if (typeof arr[i] !== 'number') { arr[i] = 0; } } return arr; } module.exports = Color; color-2.0.0/package.json000066400000000000000000000013231312512351000151050ustar00rootroot00000000000000{ "name": "color", "version": "2.0.0", "description": "Color conversion and manipulation with CSS string support", "keywords": [ "color", "colour", "css" ], "authors": [ "Josh Junon ", "Heather Arthur ", "Maxime Thirouin" ], "license": "MIT", "repository": "Qix-/color", "xo": { "rules": { "no-cond-assign": 0, "new-cap": 0 } }, "files": [ "CHANGELOG.md", "LICENSE", "index.js" ], "scripts": { "pretest": "xo", "test": "mocha" }, "dependencies": { "color-convert": "^1.8.2", "color-string": "^1.4.0" }, "devDependencies": { "mocha": "^2.2.5", "xo": "^0.12.1" } } color-2.0.0/test/000077500000000000000000000000001312512351000135775ustar00rootroot00000000000000color-2.0.0/test/index.js000066400000000000000000000277071312512351000152610ustar00rootroot00000000000000/* eslint-env node, mocha */ var assert = require('assert'); var Color = require('..'); var deepEqual = assert.deepEqual; var equal = assert.equal; var ok = assert.ok; var notStrictEqual = assert.notStrictEqual; var throws = assert.throws; it('Color() instance', function () { equal(new Color('red').red(), 255); ok((new Color()) instanceof Color); var c = Color(); notStrictEqual(c.rgb(), c.rgb()); }); it('Immutability', function () { var c = Color(0xFF0000); ok(c !== c.rgb()); ok(c != c.rgb()); // eslint-disable-line eqeqeq }); it('Color() argument', function () { deepEqual(Color('#0A1E19').rgb().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color('rgb(10, 30, 25)').rgb().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color('rgba(10, 30, 25, 0.4)').rgb().object(), { r: 10, g: 30, b: 25, alpha: 0.4 }); deepEqual(Color('rgb(4%, 12%, 10%)').rgb().object(), { r: 10, g: 31, b: 26 }); deepEqual(Color('rgba(4%, 12%, 10%, 0.4)').rgb().object(), { r: 10, g: 31, b: 26, alpha: 0.4 }); deepEqual(Color('blue').rgb().object(), { r: 0, g: 0, b: 255 }); deepEqual(Color('hsl(120, 50%, 60%)').hsl().object(), { h: 120, s: 50, l: 60 }); deepEqual(Color('hsla(120, 50%, 60%, 0.4)').hsl().object(), { h: 120, s: 50, l: 60, alpha: 0.4 }); deepEqual(Color('hwb(120, 50%, 60%)').hwb().object(), { h: 120, w: 50, b: 60 }); deepEqual(Color('hwb(120, 50%, 60%, 0.4)').hwb().object(), { h: 120, w: 50, b: 60, alpha: 0.4 }); deepEqual(Color({ r: 10, g: 30, b: 25 }).rgb().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color({ h: 10, s: 30, l: 25 }).hsl().object(), { h: 10, s: 30, l: 25 }); deepEqual(Color({ h: 10, s: 30, v: 25 }).hsv().object(), { h: 10, s: 30, v: 25 }); deepEqual(Color({ h: 10, w: 30, b: 25 }).hwb().object(), { h: 10, w: 30, b: 25 }); deepEqual(Color({ c: 10, m: 30, y: 25, k: 10 }).cmyk().object(), { c: 10, m: 30, y: 25, k: 10 }); }); it('Setters', function () { deepEqual(Color.rgb(10, 30, 25).rgb().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color.rgb(10, 30, 25, 0.4).rgb().object(), { r: 10, g: 30, b: 25, alpha: 0.4 }); deepEqual(Color.rgb([10, 30, 25]).rgb().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color.rgb([10, 30, 25, 0.4]).rgb().object(), { r: 10, g: 30, b: 25, alpha: 0.4 }); deepEqual(Color.rgb({ r: 10, g: 30, b: 25 }).rgb().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color.rgb({ r: 10, g: 30, b: 25, alpha: 0.4 }).rgb().object(), { r: 10, g: 30, b: 25, alpha: 0.4 }); deepEqual(Color.hsl([260, 10, 10]).hsl().object(), { h: 260, s: 10, l: 10 }); deepEqual(Color.hsv([260, 10, 10]).hsv().object(), { h: 260, s: 10, v: 10 }); deepEqual(Color.hwb([260, 10, 10]).hwb().object(), { h: 260, w: 10, b: 10 }); deepEqual(Color.cmyk([10, 10, 10, 10]).cmyk().object(), { c: 10, m: 10, y: 10, k: 10 }); }); it('Retain Alpha', function () { equal(Color.rgb(1, 2, 3, 0.4).ansi256().rgb().alpha(), 0.4); }); it('Translations', function () { deepEqual(Color.rgb(10, 30, 25).rgb().round().object(), { r: 10, g: 30, b: 25 }); deepEqual(Color.rgb(10, 30, 25).hsl().round().object(), { h: 165, s: 50, l: 8 }); deepEqual(Color.rgb(10, 30, 25).hsv().round().object(), { h: 165, s: 67, v: 12 }); deepEqual(Color.rgb(10, 30, 25).hwb().round().object(), { h: 165, w: 4, b: 88 }); deepEqual(Color.rgb(10, 30, 25).cmyk().round().object(), { c: 67, m: 0, y: 17, k: 88 }); }); it('Array getters', function () { deepEqual(Color({ r: 10, g: 20, b: 30 }).rgb().array(), [10, 20, 30]); deepEqual(Color({ r: 10, g: 20, b: 30 }).unitArray(), [10 / 255, 20 / 255, 30 / 255]); deepEqual(Color({ r: 10, g: 20, b: 30, alpha: 0.5 }).unitArray(), [10 / 255, 20 / 255, 30 / 255, 0.5]); deepEqual(Color({ h: 10, s: 20, l: 30 }).hsl().array(), [10, 20, 30]); deepEqual(Color({ h: 10, s: 20, v: 30 }).hsv().array(), [10, 20, 30]); deepEqual(Color({ h: 10, w: 20, b: 30 }).hwb().array(), [10, 20, 30]); deepEqual(Color({ c: 10, m: 20, y: 30, k: 40 }).cmyk().array(), [10, 20, 30, 40]); }); it('Multiple times', function () { var color = Color({ r: 10, g: 20, b: 30 }); deepEqual(color.rgb().array(), [10, 20, 30]); deepEqual(color.rgb().array(), [10, 20, 30]); }); it('Channel getters/setters', function () { equal(Color({ r: 10, g: 20, b: 30, alpha: 0.4 }).alpha(), 0.4); equal(Color({ r: 10, g: 20, b: 30, alpha: 0.4 }).alpha(0.7).alpha(), 0.7); equal(Color({ r: 10, g: 20, b: 30 }).red(), 10); equal(Color({ r: 10, g: 20, b: 30 }).red(100).red(), 100); equal(Color({ r: 10, g: 20, b: 30 }).green(), 20); equal(Color({ r: 10, g: 20, b: 30 }).green(200).green(), 200); equal(Color({ r: 10, g: 20, b: 30 }).blue(), 30); equal(Color({ r: 10, g: 20, b: 30 }).blue(60).blue(), 60); equal(Color({ h: 10, s: 20, l: 30 }).hue(), 10); equal(Color({ h: 10, s: 20, l: 30 }).hue(100).hue(), 100); equal(Color({ h: 10, w: 20, b: 30 }).hue(), 10); equal(Color({ h: 10, w: 20, b: 30 }).hue(100).hue(), 100); equal(Color({ h: 10, s: 20, l: 30 }).hue(), 10); equal(Color({ h: 10, s: 20, l: 30 }).hue(460).hue(), 100); equal(Color({ h: 10, w: 20, b: 30 }).hue(), 10); equal(Color({ h: 10, w: 20, b: 30 }).hue(-260).hue(), 100); }); it('Setting the same value', function () { var colorString = '#BADA55'; var color = Color(colorString); var alpha = color.alpha(); var red = color.red(); var green = color.green(); var blue = color.blue(); var hue = color.hue(); var saturation = color.saturationl(); var saturationv = color.saturationv(); var lightness = color.lightness(); var whiteness = color.white(); var blackness = color.wblack(); var cyan = color.cyan(); var magenta = color.magenta(); var yellow = color.yellow(); var black = color.black(); equal(color.hex(), colorString); color.alpha(alpha); equal(color.alpha(), alpha); equal(color.hex(), colorString); color.red(red); equal(color.red(), red); equal(color.hex(), colorString); color.green(green); equal(color.green(), green); equal(color.hex(), colorString); color.blue(blue); equal(color.blue(), blue); equal(color.hex(), colorString); color.hue(hue); equal(color.hue(), hue); equal(color.hex(), colorString); color.saturationl(saturation); equal(color.saturationl(), saturation); equal(color.hex(), colorString); color.saturationv(saturationv); equal(color.saturationv(), saturationv); equal(color.hex(), colorString); color.lightness(lightness); equal(color.lightness(), lightness); equal(color.hex(), colorString); color.white(whiteness); equal(color.white(), whiteness); equal(color.hex(), colorString); color.wblack(blackness); equal(color.wblack(), blackness); equal(color.hex(), colorString); color.cyan(cyan); equal(color.cyan(), cyan); equal(color.hex(), colorString); color.magenta(magenta); equal(color.magenta(), magenta); equal(color.hex(), colorString); color.yellow(yellow); equal(color.yellow(), yellow); equal(color.hex(), colorString); color.black(black); equal(color.black(), black); equal(color.hex(), colorString); }); it('Capping values', function () { equal(Color({ h: 400, s: 50, l: 10 }).hue(), 40); equal(Color({ h: 100, s: 50, l: 80 }).lighten(0.5).lightness(), 100); equal(Color({ h: -400, s: 50, l: 10 }).hue(), 320); // 0 == 360 equal(Color({ h: 400, w: 50, b: 10 }).hue(), 40); equal(Color({ h: 100, w: 50, b: 80 }).blacken(0.5).wblack(), 100); equal(Color({ h: -400, w: 50, b: 10 }).hue(), 320); equal(Color().red(400).red(), 255); equal(Color().red(-400).red(), 0); equal(Color.rgb(10, 10, 10, 12).alpha(), 1); equal(Color.rgb(10, 10, 10, -200).alpha(), 0); equal(Color().alpha(-12).alpha(), 0); equal(Color().alpha(3).alpha(), 1); }); it('Translate with channel setters', function () { deepEqual(Color({ r: 0, g: 0, b: 0 }).lightness(50).hsl().object(), { h: 0, s: 0, l: 50 }); deepEqual(Color({ r: 0, g: 0, b: 0 }).red(50).green(50).hsv().round().object(), { h: 60, s: 100, v: 20 }); }); it('CSS String getters', function () { equal(Color('rgb(10, 30, 25)').hex(), '#0A1E19'); equal(Color('rgb(10, 30, 25)').rgb().string(), 'rgb(10, 30, 25)'); equal(Color('rgb(10, 30, 25, 0.4)').rgb().string(), 'rgba(10, 30, 25, 0.4)'); equal(Color('rgb(10, 30, 25)').percentString(), 'rgb(4%, 12%, 10%)'); equal(Color('rgb(10, 30, 25, 0.3)').percentString(), 'rgba(4%, 12%, 10%, 0.3)'); equal(Color('rgb(10, 30, 25)').hsl().string(), 'hsl(165, 50%, 7.8%)'); equal(Color('rgb(10, 30, 25, 0.3)').hsl().string(), 'hsla(165, 50%, 7.8%, 0.3)'); equal(Color({ h: 0, s: 0, v: 100 }).hsl().string(), 'hsl(0, 0%, 100%)'); equal(Color('rgb(10, 30, 25)').hwb().string(0), 'hwb(165, 4%, 88%)'); equal(Color('rgb(10, 30, 25, 0.3)').hwb().string(0), 'hwb(165, 4%, 88%, 0.3)'); equal(Color('rgb(0, 0, 255)').keyword(), 'blue'); equal(Color.rgb(155.5, 243.1555, 88.1999).string(), 'rgb(156, 243, 88)'); }); it('Number getters', function () { equal(Color('rgb(10, 30, 25)').rgbNumber(), 0xA1E19); }); it('luminosity, etc.', function () { equal(Color('white').luminosity(), 1); equal(Color('black').luminosity(), 0); equal(Color('red').luminosity(), 0.2126); equal(Color('white').contrast(Color('black')), 21); equal(Math.round(Color('white').contrast(Color('red'))), 4); equal(Math.round(Color('red').contrast(Color('white'))), 4); equal(Color('blue').contrast(Color('blue')), 1); ok(Color('black').dark()); ok(!Color('black').light()); ok(Color('white').light()); ok(!Color('white').dark()); ok(Color('blue').dark()); ok(Color('darkgreen').dark()); ok(Color('pink').light()); ok(Color('goldenrod').light()); ok(Color('red').dark()); }); it('Manipulators wo/ mix', function () { deepEqual(Color({ r: 67, g: 122, b: 134 }).grayscale().rgb().round().object(), { r: 107, g: 107, b: 107 }); deepEqual(Color({ r: 67, g: 122, b: 134 }).negate().rgb().round().object(), { r: 188, g: 133, b: 121 }); equal(Color({ h: 100, s: 50, l: 60 }).lighten(0.5).lightness(), 90); equal(Color({ h: 100, s: 50, l: 60 }).darken(0.5).lightness(), 30); equal(Color({ h: 100, w: 50, b: 60 }).whiten(0.5).white(), 75); equal(Color({ h: 100, w: 50, b: 60 }).blacken(0.5).wblack(), 90); equal(Color({ h: 100, s: 40, l: 50 }).saturate(0.5).saturationl(), 60); equal(Color({ h: 100, s: 80, l: 60 }).desaturate(0.5).saturationl(), 40); equal(Color({ r: 10, g: 10, b: 10, alpha: 0.8 }).fade(0.5).alpha(), 0.4); equal(Color({ r: 10, g: 10, b: 10, alpha: 0.5 }).opaquer(0.5).alpha(), 0.75); equal(Color({ h: 60, s: 0, l: 0 }).rotate(180).hue(), 240); equal(Color({ h: 60, s: 0, l: 0 }).rotate(-180).hue(), 240); }); it('Mix: basic', function () { equal(Color('#f00').mix(Color('#00f')).hex(), '#800080'); }); it('Mix: weight', function () { equal(Color('#f00').mix(Color('#00f'), 0.25).hex(), '#BF0040'); }); it('Mix: alpha', function () { equal(Color('rgba(255, 0, 0, 0.5)').mix(Color('#00f')).rgb().string(0), 'rgba(64, 0, 191, 0.75)'); }); it('Mix: 0%', function () { equal(Color('#f00').mix(Color('#00f'), 0).hex(), '#FF0000'); }); it('Mix: 25%', function () { equal(Color('#f00').mix(Color('#00f'), 0.25).hex(), '#BF0040'); }); it('Mix: 50%', function () { equal(Color('#f00').mix(Color('#00f'), 0.5).hex(), '#800080'); }); it('Mix: 75%', function () { equal(Color('#f00').mix(Color('#00f'), 0.75).hex(), '#4000BF'); }); it('Mix: 100%', function () { equal(Color('#f00').mix(Color('#00f'), 1.0).hex(), '#0000FF'); }); it('Level', function () { equal(Color('white').level(Color('black')), 'AAA'); equal(Color('grey').level(Color('black')), 'AA'); }); it('Exceptions', function () { throws(function () { Color('unknow'); }, /Unable to parse color from string/); throws(function () { Color({}); }, /Unable to parse color from object/); });