From 591a7ea33e36c5f065620643238c68ec4094f861 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 18 Sep 2016 02:05:43 +0200 Subject: [PATCH 1/3] Support #rrggbbaa and #rgba --- lib/color.js | 7 ++++--- test/parse.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/color.js b/lib/color.js index 9336b1a..e36a2d5 100644 --- a/lib/color.js +++ b/lib/color.js @@ -53,15 +53,16 @@ function color(obj) { // Assume hex syntax if (obj.length < 6) { // Allow CSS shorthand - obj = obj.replace(/^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i, '$1$1$2$2$3$3'); + obj = obj.replace(/^#?([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?$/i, '$1$1$2$2$3$3$4$4'); } // Split obj into red, green, and blue components - var hexMatch = obj.match(/^#?([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/i); + var hexMatch = obj.match(/^#?([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])?$/i); if (hexMatch) { return new color.RGB( parseInt(hexMatch[1], 16) / 255, parseInt(hexMatch[2], 16) / 255, - parseInt(hexMatch[3], 16) / 255 + parseInt(hexMatch[3], 16) / 255, + hexMatch[4] ? parseInt(hexMatch[4], 16) / 255 : 1 ); } diff --git a/test/parse.js b/test/parse.js index 42f7018..41c688e 100644 --- a/test/parse.js +++ b/test/parse.js @@ -48,4 +48,36 @@ describe('parsing', function () { expect(color('cmyk(100,100%,100%)'), 'to be false'); }); }); + + describe('with #rrggbbaa', function () { + var instance = color('#00ff0080'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#00ff00'); + }); + + it('should have its alpha channel set correctly', function () { + expect(instance.alpha().toFixed(2), 'to equal', '0.50'); + }); + }); + + describe('with #rgba', function () { + var instance = color('#0f08'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#00ff00'); + }); + + it('should have its alpha channel set correctly', function () { + expect(instance.alpha().toFixed(2), 'to equal', '0.53'); + }); + }); }); From 7945c712526231ded8674d7e64f0b843bf78970a Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 18 Sep 2016 02:43:16 +0200 Subject: [PATCH 2/3] Support more of the new csswg color draft syntaxes. --- lib/color.js | 33 ++++++++++-------- test/parse.js | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 14 deletions(-) diff --git a/lib/color.js b/lib/color.js index e36a2d5..a8bfa55 100644 --- a/lib/color.js +++ b/lib/color.js @@ -2,18 +2,27 @@ var installedColorSpaces = [], undef = function (obj) { return typeof obj === 'undefined'; }, - channelRegExp = /\s*(\.\d+|\d+(?:\.\d+)?)(%)?\s*/, + channelRegExp = /\s*(\.\d+|\d+(?:\.\d+)?)(%|deg)?\s*/, percentageChannelRegExp = /\s*(\.\d+|100|\d?\d(?:\.\d+)?)%\s*/, - alphaChannelRegExp = /\s*(\.\d+|\d+(?:\.\d+)?)\s*/, cssColorRegExp = new RegExp( '^(rgb|hsl|hsv)a?' + '\\(' + - channelRegExp.source + ',' + - channelRegExp.source + ',' + + channelRegExp.source + '[, ]' + + channelRegExp.source + '[, ]' + channelRegExp.source + - '(?:,' + alphaChannelRegExp.source + ')?' + + '(?:[,/]' + channelRegExp.source + ')?' + '\\)$', 'i'); +function divisor(unit, channelNumber, hasHue) { + if (unit === '%') { + return 100; + } else if (unit === 'deg' || (hasHue && channelNumber === 0)) { + return 360; + } else if (!unit) { + return 255; + } +} + function color(obj) { if (Array.isArray(obj)) { if (typeof obj[0] === 'string' && typeof color[obj[0]] === 'function') { @@ -35,19 +44,15 @@ function color(obj) { var matchCssSyntax = obj.match(cssColorRegExp); if (matchCssSyntax) { var colorSpaceName = matchCssSyntax[1].toUpperCase(), - alpha = undef(matchCssSyntax[8]) ? matchCssSyntax[8] : parseFloat(matchCssSyntax[8]), - hasHue = colorSpaceName[0] === 'H', - firstChannelDivisor = matchCssSyntax[3] ? 100 : (hasHue ? 360 : 255), - secondChannelDivisor = (matchCssSyntax[5] || hasHue) ? 100 : 255, - thirdChannelDivisor = (matchCssSyntax[7] || hasHue) ? 100 : 255; + hasHue = colorSpaceName[0] === 'H'; if (undef(color[colorSpaceName])) { throw new Error('color.' + colorSpaceName + ' is not installed.'); } return new color[colorSpaceName]( - parseFloat(matchCssSyntax[2]) / firstChannelDivisor, - parseFloat(matchCssSyntax[4]) / secondChannelDivisor, - parseFloat(matchCssSyntax[6]) / thirdChannelDivisor, - alpha + parseFloat(matchCssSyntax[2]) / divisor(matchCssSyntax[3], 0, hasHue), + parseFloat(matchCssSyntax[4]) / divisor(matchCssSyntax[5], 1, hasHue), + parseFloat(matchCssSyntax[6]) / divisor(matchCssSyntax[7], 2, hasHue), + undef(matchCssSyntax[8]) ? matchCssSyntax[8] : parseFloat(matchCssSyntax[8]) / (matchCssSyntax[9] ? 100 : 255) ); } // Assume hex syntax diff --git a/test/parse.js b/test/parse.js index 41c688e..0644c47 100644 --- a/test/parse.js +++ b/test/parse.js @@ -80,4 +80,96 @@ describe('parsing', function () { expect(instance.alpha().toFixed(2), 'to equal', '0.53'); }); }); + + describe('with rgb(r, g, b)', function () { + var instance = color('rgb(10, 20, 30)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#0a141e'); + }); + }); + + describe('with rgb(r,g,b)', function () { + var instance = color('rgb(10,20,30)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#0a141e'); + }); + }); + + describe('with rgb(r g b)', function () { + var instance = color('rgb(10 20 30)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#0a141e'); + }); + }); + + describe('with rgba(r g b / a)', function () { + var instance = color('rgba(10 20 30 / 50%)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#0a141e'); + }); + + it('should have its alpha channel set correctly', function () { + expect(instance.alpha().toFixed(2), 'to equal', '0.50'); + }); + }); + + describe('with rgba(r g b/a)', function () { + var instance = color('rgba(10 20 30/50%)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#0a141e'); + }); + + it('should have its alpha channel set correctly', function () { + expect(instance.alpha().toFixed(2), 'to equal', '0.50'); + }); + }); + + describe('with hsl(h s l) and the hue given as a percentage', function () { + var instance = color('hsl(10% 20% 30%)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#5c503d'); + }); + }); + + describe('with hsl(h s l) and the hue given as an angle', function () { + var instance = color('hsl(10deg 20% 30%)'); + + it('should return a color instance', function () { + expect(instance, 'to be a color instance'); + }); + + it('should be green', function () { + expect(instance.hex(), 'to equal', '#5c423d'); + }); + }); }); From 1e7a377bbc35f7529e4f63d766c2e0073b298b61 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Sun, 27 Nov 2022 19:01:04 +0100 Subject: [PATCH 3/3] Change the hexa method to return #rrggbbaa instead of #aarrggbb --- lib/color.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/color.js b/lib/color.js index 0944b50..4b6e6e6 100644 --- a/lib/color.js +++ b/lib/color.js @@ -326,12 +326,7 @@ color.installColorSpace('RGB', ['red', 'green', 'blue', 'alpha'], { hexa: function () { var alphaString = Math.round(this._alpha * 255).toString(16); - return ( - '#' + - '00'.substr(0, 2 - alphaString.length) + - alphaString + - this.hex().substr(1, 6) - ); + return this.hex() + '00'.substr(0, 2 - alphaString.length) + alphaString; }, css: function () {