Skip to content

Commit

Permalink
Merge pull request #36 from One-com/feature/rrggbbaa
Browse files Browse the repository at this point in the history
Support #rrggbbaa and #rgba
  • Loading branch information
papandreou committed Nov 29, 2022
2 parents 50fb015 + 1e7a377 commit 7ed619b
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 26 deletions.
57 changes: 31 additions & 26 deletions lib/color.js
Expand Up @@ -2,24 +2,33 @@ var installedColorSpaces = [];
var undef = function (obj) {
return typeof obj === 'undefined';
};
var channelRegExp = /\s*(\.\d+|\d+(?:\.\d+)?)(%)?\s*/;
var channelRegExp = /\s*(\.\d+|\d+(?:\.\d+)?)(%|deg)?\s*/;
var percentageChannelRegExp = /\s*(\.\d+|100|\d?\d(?:\.\d+)?)%\s*/;
var alphaChannelRegExp = /\s*(\.\d+|\d+(?:\.\d+)?)\s*/;
var cssColorRegExp = new RegExp(
'^(rgb|hsl|hsv)a?' +
'\\(' +
channelRegExp.source +
',' +
'[, ]' +
channelRegExp.source +
',' +
'[, ]' +
channelRegExp.source +
'(?:[,/]' +
channelRegExp.source +
'(?:,' +
alphaChannelRegExp.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') {
Expand All @@ -46,37 +55,38 @@ function color(obj) {
var matchCssSyntax = obj.match(cssColorRegExp);
if (matchCssSyntax) {
var colorSpaceName = matchCssSyntax[1].toUpperCase();
var alpha = undef(matchCssSyntax[8])
? matchCssSyntax[8]
: parseFloat(matchCssSyntax[8]);
var hasHue = colorSpaceName[0] === 'H';
var firstChannelDivisor = matchCssSyntax[3] ? 100 : hasHue ? 360 : 255;
var secondChannelDivisor = matchCssSyntax[5] || hasHue ? 100 : 255;
var thirdChannelDivisor = matchCssSyntax[7] || hasHue ? 100 : 255;
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
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
// Split obj into the red, green, blue, and optionally alpha component
var hexMatch = obj.match(
/^#?([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/i
/^#?([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
);
}

Expand Down Expand Up @@ -316,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 () {
Expand Down
124 changes: 124 additions & 0 deletions test/parse.js
Expand Up @@ -53,4 +53,128 @@ 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');
});
});

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');
});
});
});

0 comments on commit 7ed619b

Please sign in to comment.