Skip to content

Commit

Permalink
Update regexps to handle scientific notation
Browse files Browse the repository at this point in the history
  • Loading branch information
kurkle committed Feb 9, 2020
1 parent 0d41848 commit 62efdf8
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 36 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ rgb(255, 0, 0, 0.5)
rgb(50%, 50%, 50%, 50%)
rgb(0 0 100% / 80%)
rgba(200, 20, 233, 0.2)
rgba(200, 20, 233, 2e-1)
```

- hsl(a)
Expand All @@ -42,6 +43,7 @@ rgba(200, 20, 233, 0.2)
hsl(240deg, 100%, 50.5%)
hsl(0deg 100% 50%)
hsla(12, 10%, 50%, .3)
hsla(-1.2, 10.2%, 50.9%, 0.4)
```

- hwb
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kurkle/color",
"version": "0.1.1",
"version": "0.1.2",
"description": "css color parsing, manupulation and conversion",
"main": "dist/color.js",
"module": "dist/color.esm.js",
Expand Down
54 changes: 34 additions & 20 deletions src/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import {b2n, n2b, round} from './byte';
* @private
*/
function modHSL(v, i, ratio) {
var tmp = rgb2hsl(v);
tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));
tmp = hsl2rgb(tmp);
v.r = tmp[0];
v.g = tmp[1];
v.b = tmp[2];
if (v) {
let tmp = rgb2hsl(v);
tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));
tmp = hsl2rgb(tmp);
v.r = tmp[0];
v.g = tmp[1];
v.b = tmp[2];
}
}

/**
Expand Down Expand Up @@ -58,6 +60,16 @@ function fromObject(input) {
return v;
}

/**
* @param {string} str
*/
function functionParse(str) {
if (str.charAt(0) === 'r') {
return rgbParse(str);
}
return hueParse(str);
}

export default class Color {
/**
* constructor
Expand All @@ -74,7 +86,7 @@ export default class Color {
v = fromObject(input);
} else if (type === 'string') {
// @ts-ignore
v = hexParse(input) || nameParse(input) || rgbParse(input) || hueParse(input);
v = hexParse(input) || nameParse(input) || functionParse(input);
}

/** @type {RGBA} */
Expand Down Expand Up @@ -137,19 +149,21 @@ export default class Color {
*/
mix(color, weight) {
const me = this;
const c1 = me.rgb;
const c2 = color.rgb;
let w2; // using instead of undefined in the next line
const p = weight === w2 ? 0.5 : weight;
const w = 2 * p - 1;
const a = c1.a - c2.a;
const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
w2 = 1 - w1;
c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5;
c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5;
c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5;
c1.a = p * c1.a + (1 - p) * c2.a;
me.rgb = c1;
if (color) {
const c1 = me.rgb;
const c2 = color.rgb;
let w2; // using instead of undefined in the next line
const p = weight === w2 ? 0.5 : weight;
const w = 2 * p - 1;
const a = c1.a - c2.a;
const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
w2 = 1 - w1;
c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5;
c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5;
c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5;
c1.a = p * c1.a + (1 - p) * c2.a;
me.rgb = c1;
}
return me;
}

Expand Down
26 changes: 15 additions & 11 deletions src/hue.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @module Index
*/

import {b2n, n2p, n2b} from './byte';
import {b2n, n2p, n2b, p2b} from './byte';

/**
* @typedef {import('./index.js').RGBA} RGBA
Expand All @@ -12,7 +12,7 @@ import {b2n, n2p, n2b} from './byte';
/**
* @private
*/
const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([+-]?\d*[\.]?\d+)(?:deg)?[\s,]+([+-]?\d*[\.]?\d+)%[\s,]+([+-]?\d*[\.]?\d+)%\s*(?:[\s,]+([+-]?\d*[\.]?\d+)\s*)?\)/; // eslint-disable-line no-useless-escape
const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;

// https://jsfiddle.net/Lamik/reuk63ay/91
/**
Expand Down Expand Up @@ -75,14 +75,14 @@ function hwb2rgbn(h, w, b) {
* @returns {number[]} - [h, s, l]
*/
export function rgb2hsl(v) {
var range = 255;
var r = v.r / range;
var g = v.g / range;
var b = v.b / range;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var l = (max + min) / 2;
var h, s, d;
const range = 255;
const r = v.r / range;
const g = v.g / range;
const b = v.b / range;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const l = (max + min) / 2;
let h, s, d;
if (max !== min) {
d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
Expand Down Expand Up @@ -166,7 +166,7 @@ export function hueParse(str) {
}
// v is undefined
if (m[5] !== v) {
a = n2b(+m[5]);
a = m[6] ? p2b(+m[5]) : n2b(+m[5]);
}
const h = hue(+m[2]);
const p1 = +m[3] / 100;
Expand Down Expand Up @@ -203,8 +203,12 @@ export function rotate(v, deg) {
/**
* Return hsl(a) string from color components
* @param {RGBA} v - the color
* @return {string|undefined}
*/
export function hslString(v) {
if (!v) {
return;
}
const a = rgb2hsl(v);
const h = a[0];
const s = n2p(a[1]);
Expand Down
10 changes: 6 additions & 4 deletions src/rgb.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {p2b, b2n} from './byte';
/**
* @private
*/
const RGB_RE = /^rgba?\(\s*([+-]?[\d\.]+)(%)?[\s,]+([+-]?[\d\.]+)(%)?[\s,]+([+-]?[\d\.]+)(%)?\s*(?:[\s,/]+([+-]?[\d\.]+)(%)?\s*)?\)$/; // eslint-disable-line no-useless-escape
const RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;

/**
* Parse rgb(a) string to RGBA
Expand Down Expand Up @@ -54,7 +54,9 @@ export function rgbParse(str) {
* @param {RGBA} v - the color
*/
export function rgbString(v) {
return v.a < 255
? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})`
: `rgb(${v.r}, ${v.g}, ${v.b})`;
return v && (
v.a < 255
? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})`
: `rgb(${v.r}, ${v.g}, ${v.b})`
);
}
6 changes: 6 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ assert.deepEqual(new Color('#c814e900').rgb, {r: 200, g: 20, b: 233, a: 0});
assert.deepEqual(new Color('#c814e9ff').rgb, {r: 200, g: 20, b: 233, a: 1});
assert.deepEqual(new Color('rgba(200, 20, 233, 0.2)').rgb, {r: 200, g: 20, b: 233, a: 0.2});
assert.deepEqual(new Color('rgba(200, 20, 233, 0)').rgb, {r: 200, g: 20, b: 233, a: 0});
assert.deepEqual(new Color('rgba(200, 20, 233, 1e-15)').rgb, {r: 200, g: 20, b: 233, a: 0});
assert.deepEqual(new Color('rgba(100%, 30%, 90%, 0.2)').rgb, {r: 255, g: 77, b: 229, a: 0.2});
assert.deepEqual(new Color('rgba(255, 0, 0, .5)').rgb, {r: 255, g: 0, b: 0, a: 0.5});
assert.deepEqual(new Color('hsla(12, 10%, 50%, .3)').rgb, {r: 140, g: 120, b: 115, a: 0.3});
assert.deepEqual(new Color('hsla(12, 10%, 50%, 30%)').rgb, {r: 140, g: 120, b: 115, a: 0.3});
assert.deepEqual(new Color('hwb(244, 100%, 100%, 0.6)').rgb, {r: 128, g: 128, b: 128, a: 0.6});
assert.deepEqual(new Color('hsla(240.0384227364303,4.12843378950259%,48.71943371204973%,0.3)').rgb, {r: 119, g: 119, b: 129, a: 0.3});
assert.deepEqual(new Color('hsla(-10.0, 100%, 50%, -0.2)').hslString(), 'hsla(350, 100%, 50%, 0)');
assert.deepEqual(new Color('hsla(-1e1, 1e2%, 50%, -2e-1)').hslString(), 'hsla(350, 100%, 50%, 0)');

assert.deepEqual(new Color('blue').rgb, {r: 0, g: 0, b: 255, a: 1});
assert.deepEqual(new Color('blue').rgb, {r: 0, g: 0, b: 255, a: 1});
Expand Down Expand Up @@ -84,3 +87,6 @@ assert.strictEqual(new Color('cyan').mix(new Color('yellow')).rgbString(), 'rgb(
assert.strictEqual(new Color('cyan').mix(new Color('yellow'), 0.3).rgbString(), 'rgb(179, 255, 77)');

assert.strictEqual(new Color('rgba(10, 10, 10, 0.8)').clone().rgbString(), 'rgba(10, 10, 10, 0.8)');

assert.strictEqual(new Color('invalid-color-value').lighten(0.1).hslString(), undefined);
assert.strictEqual(new Color('invalid-color-value').mix(undefined, 0.5).rgbString(), undefined);

0 comments on commit 62efdf8

Please sign in to comment.