Skip to content

Commit

Permalink
Update valueType(), parseColor()
Browse files Browse the repository at this point in the history
  • Loading branch information
asamuzaK committed Dec 14, 2024
1 parent aff8b07 commit cd7a423
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 183 deletions.
165 changes: 4 additions & 161 deletions lib/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
********************************************************************/
'use strict';

const { resolve } = require('@asamuzakjp/css-color');
const namedColors = require('./named_colors.json');
const { hslToRgb } = require('./utils/colorSpace');
const { isColor, resolve } = require('@asamuzakjp/css-color');

exports.TYPES = {
INTEGER: 1,
Expand All @@ -29,12 +27,7 @@ var lengthRegEx = /^(0|[-+]?[0-9]*\.?[0-9]+(in|cm|em|mm|pt|pc|px|ex|rem|vh|vw|ch
var percentRegEx = /^[-+]?[0-9]*\.?[0-9]+%$/;
var urlRegEx = /^url\(\s*([^)]*)\s*\)$/;
var stringRegEx = /^("[^"]*"|'[^']*')$/;
var colorRegEx1 = /^#([0-9a-fA-F]{3,4}){1,2}$/;
var colorRegEx2 = /^rgb\(([^)]*)\)$/;
var colorRegEx3 = /^rgba\(([^)]*)\)$/;
var calcRegEx = /^calc\(([^)]*)\)$/;
var colorRegEx4 =
/^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)/;
var angleRegEx = /^([-+]?[0-9]*\.?[0-9]+)(deg|grad|rad)$/;

// This will return one of the above types based on the passed in string
Expand Down Expand Up @@ -74,53 +67,12 @@ exports.valueType = function valueType(val) {
if (angleRegEx.test(val)) {
return exports.TYPES.ANGLE;
}
if (colorRegEx1.test(val)) {
if (isColor(val)) {
return exports.TYPES.COLOR;
}

var res = colorRegEx2.exec(val);
var parts;
if (res !== null) {
parts = res[1].split(/\s*,\s*/);
if (parts.length !== 3) {
return undefined;
}
if (
parts.every(percentRegEx.test.bind(percentRegEx)) ||
parts.every(integerRegEx.test.bind(integerRegEx))
) {
return exports.TYPES.COLOR;
}
return undefined;
}
res = colorRegEx3.exec(val);
if (res !== null) {
parts = res[1].split(/\s*,\s*/);
if (parts.length !== 4) {
return undefined;
}
if (
parts.slice(0, 3).every(percentRegEx.test.bind(percentRegEx)) ||
parts.slice(0, 3).every(integerRegEx.test.bind(integerRegEx))
) {
if (numberRegEx.test(parts[3])) {
return exports.TYPES.COLOR;
}
}
return undefined;
}

if (colorRegEx4.test(val)) {
return exports.TYPES.COLOR;
}

// could still be a color, one of the standard keyword colors
val = val.toLowerCase();

if (namedColors.includes(val)) {
return exports.TYPES.COLOR;
}

switch (val) {
// the following are deprecated in CSS3
case 'activeborder':
Expand Down Expand Up @@ -292,119 +244,10 @@ exports.parseColor = function parseColor(val) {
if (type === exports.TYPES.NULL_OR_EMPTY_STR) {
return val;
}
var red,
green,
blue,
hue,
saturation,
lightness,
alpha = 1;
var parts;
var res = colorRegEx1.exec(val);
// is it #aaa, #ababab, #aaaa, #abababaa
if (res) {
var defaultHex = val.substr(1);
var hex = val.substr(1);
if (hex.length === 3 || hex.length === 4) {
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];

if (defaultHex.length === 4) {
hex = hex + defaultHex[3] + defaultHex[3];
}
}
red = parseInt(hex.substr(0, 2), 16);
green = parseInt(hex.substr(2, 2), 16);
blue = parseInt(hex.substr(4, 2), 16);
if (hex.length === 8) {
var hexAlpha = hex.substr(6, 2);
var hexAlphaToRgbaAlpha = Number((parseInt(hexAlpha, 16) / 255).toFixed(3));

return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + hexAlphaToRgbaAlpha + ')';
}
return 'rgb(' + red + ', ' + green + ', ' + blue + ')';
}

res = val.includes(',') && colorRegEx2.exec(val);
if (res) {
parts = res[1].split(/\s*,\s*/);
if (parts.length !== 3) {
return undefined;
}
if (parts.every(percentRegEx.test.bind(percentRegEx))) {
red = Math.floor((parseFloat(parts[0].slice(0, -1)) * 255) / 100);
green = Math.floor((parseFloat(parts[1].slice(0, -1)) * 255) / 100);
blue = Math.floor((parseFloat(parts[2].slice(0, -1)) * 255) / 100);
} else if (parts.every(integerRegEx.test.bind(integerRegEx))) {
red = parseInt(parts[0], 10);
green = parseInt(parts[1], 10);
blue = parseInt(parts[2], 10);
} else {
return undefined;
}
red = Math.min(255, Math.max(0, red));
green = Math.min(255, Math.max(0, green));
blue = Math.min(255, Math.max(0, blue));
return 'rgb(' + red + ', ' + green + ', ' + blue + ')';
}

res = val.includes(',') && colorRegEx3.exec(val);
if (res) {
parts = res[1].split(/\s*,\s*/);
if (parts.length !== 4) {
return undefined;
}
if (parts.slice(0, 3).every(percentRegEx.test.bind(percentRegEx))) {
red = Math.floor((parseFloat(parts[0].slice(0, -1)) * 255) / 100);
green = Math.floor((parseFloat(parts[1].slice(0, -1)) * 255) / 100);
blue = Math.floor((parseFloat(parts[2].slice(0, -1)) * 255) / 100);
alpha = parseFloat(parts[3]);
} else if (parts.slice(0, 3).every(integerRegEx.test.bind(integerRegEx))) {
red = parseInt(parts[0], 10);
green = parseInt(parts[1], 10);
blue = parseInt(parts[2], 10);
alpha = parseFloat(parts[3]);
} else {
return undefined;
}
if (isNaN(alpha)) {
alpha = 1;
}
red = Math.min(255, Math.max(0, red));
green = Math.min(255, Math.max(0, green));
blue = Math.min(255, Math.max(0, blue));
alpha = Math.min(1, Math.max(0, alpha));
if (alpha === 1) {
return 'rgb(' + red + ', ' + green + ', ' + blue + ')';
}
return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + alpha + ')';
}

res = colorRegEx4.exec(val);
if (res) {
const [, _hue, _saturation, _lightness, _alphaString = ''] = res;
const _alpha = parseFloat(_alphaString.replace(',', '').trim());
if (!_hue || !_saturation || !_lightness) {
return undefined;
}
hue = parseFloat(_hue);
saturation = parseInt(_saturation, 10);
lightness = parseInt(_lightness, 10);
if (_alpha && numberRegEx.test(_alpha)) {
alpha = parseFloat(_alpha);
}

const [r, g, b] = hslToRgb(hue, saturation / 100, lightness / 100);
if (!_alphaString || alpha === 1) {
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')';
}

if (type === exports.TYPES.COLOR) {
if (/^[a-z]+$/i.test(val) && type === exports.TYPES.COLOR) {
return val;
}

res = resolve(val, {
var res = resolve(val, {
format: 'specifiedValue',
});
if (res) {
Expand Down
19 changes: 0 additions & 19 deletions lib/utils/colorSpace.js

This file was deleted.

12 changes: 9 additions & 3 deletions test/CSSStyleDeclaration.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ describe('CSSStyleDeclaration', () => {
style.color = 'rgba(0,0,0,0)';
assert.strictEqual(style.color, 'rgba(0, 0, 0, 0)');
style.color = 'rgba(5%, 10%, 20%, 0.4)';
assert.strictEqual(style.color, 'rgba(12, 25, 51, 0.4)');
assert.strictEqual(style.color, 'rgba(13, 26, 51, 0.4)');
style.color = 'rgb(33%, 34%, 33%)';
assert.strictEqual(style.color, 'rgb(84, 86, 84)');
assert.strictEqual(style.color, 'rgb(84, 87, 84)');
style.color = 'rgba(300, 200, 100, 1.5)';
assert.strictEqual(style.color, 'rgb(255, 200, 100)');
style.color = 'hsla(0, 1%, 2%, 0.5)';
Expand All @@ -199,13 +199,19 @@ describe('CSSStyleDeclaration', () => {
style.color = 'currentcolor';
assert.strictEqual(style.color, 'currentcolor');
style.color = '#ffffffff';
assert.strictEqual(style.color, 'rgba(255, 255, 255, 1)');
assert.strictEqual(style.color, 'rgb(255, 255, 255)');
style.color = '#fffa';
assert.strictEqual(style.color, 'rgba(255, 255, 255, 0.667)');
style.color = '#ffffff66';
assert.strictEqual(style.color, 'rgba(255, 255, 255, 0.4)');
});

it('invalid hex color value', () => {
var style = new CSSStyleDeclaration();
style.color = '#1234567';
assert.strictEqual(style.color, '');
});

it('short hand properties with embedded spaces', () => {
var style = new CSSStyleDeclaration();
style.background = 'rgb(0, 0, 0) url(/something/somewhere.jpg)';
Expand Down
7 changes: 7 additions & 0 deletions test/parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ describe('parseColor', () => {
assert.strictEqual(output, 'color-mix(in srgb, rgb(255, 0, 0), rgb(0, 0, 255))');
});

it('should not remove comments, trim or lower case letters if var() is used', () => {
let input = 'var( --custom-Color /* comment */)';
let output = parsers.parseColor(input);

assert.strictEqual(output, 'var( --custom-Color /* comment */)');
});

it.todo('Add more tests');
});
describe('parseAngle', () => {
Expand Down

0 comments on commit cd7a423

Please sign in to comment.