Skip to content

Commit

Permalink
fix: enhanced hsl matching.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaywcjlove committed Jul 10, 2022
1 parent b251b7f commit b5dc4ed
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 30 deletions.
89 changes: 84 additions & 5 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ it('=> gradsToDegrees("200")', () => expect(gradsToDegrees('200')).toEqual(180))
it('=> gradsToDegrees(200)', () => expect(gradsToDegrees(200)).toEqual(180));
it('=> gradsToDegrees(-200)', () => expect(gradsToDegrees(200)).toEqual(180));
it('=> gradsToDegrees(+200)', () => expect(gradsToDegrees(200)).toEqual(180));

it('=> radiansToDegrees(3.14)', () => expect(radiansToDegrees(3.14)).toEqual(180));

it('=> hsl() ❌ ', () => expect(hslMatcher('')).toBeUndefined());
it('=> hsl() ❌ ', () => expect(hslMatcher('hsl()')).toBeUndefined());
it('=> hsl("") ❌ ', () => expect(hslMatcher('hsl("")')).toBeUndefined());
it('=> hsl("~~~~") ❌ ', () => expect(hslMatcher('hsl("~~~")')).toBeUndefined());
it('=> hsl(240, 100%, 50%, 23x) ❌ ', () => expect(hslMatcher('hsl(240, 100%, 50%, 23x)')).toBeFalsy());
it('=> hsl(240, 100%, 50%, 23x) ❌ ', () => expect(hslMatcher('hsl(240, 100%, 50%, 23x)')).toBeUndefined());
it('=> hsl(.9 .99% .999%/ ) ❌ ', () => expect(hslMatcher('hsl(.9 .99% .999%/ )')).toBeUndefined());
it('=> hsl(.9 .99% .999%, ) ❌ ', () => expect(hslMatcher('hsl(.9 .99% .999%, )')).toBeUndefined());
it('=> hsl(.9, .99% .999% ) ❌ ', () => expect(hslMatcher('hsl(.9, .99% .999% )')).toBeUndefined());

it('=> hsl(.9, .99%, -.999% ) ✅ ', () =>
expect(hslMatcher('hsl(.9, .99%, -.999% )')).toEqual({
h: '.9',
s: '.99%',
l: '-.999%',
a: undefined,
}));

it('=> hsl(240, 100%, 50% ) ✅ ', () =>
expect(hslMatcher('hsl(240, 100%, 50% )')).toEqual({
Expand Down Expand Up @@ -109,8 +118,6 @@ it('=> hsl(.9, .99%, .999%, .9999) ✅ ', () =>
s: '.99%',
}));

it('=> hsl(.9, .99%, .999%, ) ❌ ', () => expect(hslMatcher('hsl(.9, .99%, .999%, )')).toBeUndefined());

it('=> hsl(0240, 0100%, 0050%, 01) ✅ ', () =>
expect(hslMatcher('hsl(0240, 0100%, 0050%, 01)')).toEqual({
a: '01',
Expand Down Expand Up @@ -151,6 +158,14 @@ it('=> hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3) ✅ ', () =>
a: '1E-3',
}));

it('=> hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3%) ✅ ', () =>
expect(hslMatcher('hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3%)')).toEqual({
h: '2.40e+2',
s: '1.00e+2%',
l: '5.00e+1%',
a: '1E-3%',
}));

// space separated (CSS Color Level 4)
it('=> hsl(240 100% 50%) ✅ ', () =>
expect(hslMatcher('hsl(240 100% 50%)')).toEqual({
Expand Down Expand Up @@ -229,6 +244,30 @@ it('=> hlsStringToRGB("hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3)")', () =>
a: 0.001,
}));

it('=> hlsStringToRGB("hsl(2.40e+2turn, 1.00e+2%, 5.00e+1%, 1E-3)")', () =>
expect(hlsStringToRGB('hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3)')).toEqual({
r: 0,
g: 0,
b: 255,
a: 0.001,
}));

it('=> hlsStringToRGB("hsl(2.40e+2 1.00e+2% 5.00e+1% / 1E-3)")', () =>
expect(hlsStringToRGB('hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3)')).toEqual({
r: 0,
g: 0,
b: 255,
a: 0.001,
}));

it('=> hlsStringToRGB("hsl(2.40e+2deg 1.00e+2% 5.00e+1% / 1E-3)")', () =>
expect(hlsStringToRGB('hsl(2.40e+2deg 1.00e+2% 5.00e+1% / 1E-3)')).toEqual({
r: 0,
g: 0,
b: 255,
a: 0.001,
}));

it('=> hlsStringToRGB("hsl(180deg, 100%, 50%, 0.1)")', () =>
expect(hlsStringToRGB('hsl(180deg, 100%, 50%, 0.1)')).toEqual({
r: 0,
Expand All @@ -237,6 +276,14 @@ it('=> hlsStringToRGB("hsl(180deg, 100%, 50%, 0.1)")', () =>
a: 0.1,
}));

it('=> hlsStringToRGB("hsl(180deg 100% 50% / 0.1)")', () =>
expect(hlsStringToRGB('hsl(180deg, 100%, 50%, 0.1)')).toEqual({
r: 0,
g: 255,
b: 255,
a: 0.1,
}));

it('=> hlsStringToRGB("hsl(0.5turn, 100%, 50%, 0.1)")', () =>
expect(hlsStringToRGB('hsl(0.5turn, 100%, 50%, 0.1)')).toEqual({
r: 0,
Expand All @@ -245,6 +292,14 @@ it('=> hlsStringToRGB("hsl(0.5turn, 100%, 50%, 0.1)")', () =>
a: 0.1,
}));

it('=> hlsStringToRGB("hsl(190deg 100% 36% / 53%)")', () =>
expect(hlsStringToRGB('hsl(190deg 100% 36% / 53%)')).toEqual({
r: 0,
g: 153,
b: 184,
a: 0.53,
}));

it('=> hlsStringToRGB("hsl(-240, -100%, -50%, -0.1)")', () =>
expect(hlsStringToRGB('hsl(-240, -100%, -50%, -0.1)')).toEqual({
r: 0,
Expand Down Expand Up @@ -316,6 +371,30 @@ it('=> hlsStringToRGB("hsl(.9, .99%, .999%, .9999)")', () =>
a: 0.9999,
}));

it('=> hlsStringToRGB("hsl(.9deg, .99%, .999%, .9999)")', () =>
expect(hlsStringToRGB('hsl(.9deg, .99%, .999%, .9999)')).toEqual({
r: 3,
g: 3,
b: 3,
a: 0.9999,
}));

it('=> hlsStringToRGB("hsl(-.9deg, .99%, .999%, .9999)")', () =>
expect(hlsStringToRGB('hsl(.9deg, .99%, .999%, .9999)')).toEqual({
r: 3,
g: 3,
b: 3,
a: 0.9999,
}));

it('=> hlsStringToRGB("hsl(+.9deg, .99%, .999%, .9999)")', () =>
expect(hlsStringToRGB('hsl(.9deg, .99%, .999%, .9999)')).toEqual({
r: 3,
g: 3,
b: 3,
a: 0.9999,
}));

it('=> hlsStringToRGB("hsl(240.5, 99.99%, 49.999%, 0.9999)")', () =>
expect(hlsStringToRGB('hsl(240.5, 99.99%, 49.999%, 0.9999)')).toEqual({
r: 2,
Expand Down
34 changes: 9 additions & 25 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
const MATCHER =
/hsla?\(\s*(\+?-?\d+\.?\d+(?:e\+)?(\d+)?(?:deg|rad|grad|turn)?)\s*,\s*(\+?\-?\d+\.?\d*?%)\s*,\s*(\+?\-?\d+\.?\d*?%)\s*(,\s*?\d*%|,\s*\+?-?\d*\.?\d*)?\s*\)/i;
// hsl(.9, .99%, .999%) // ✅✅✅✅
// hsl(.9, .99%, .999%, .9999) // fraction w/o leading zero
const MATCHER2 = /hsla?\(\s*(\.\d*)\s*,\s*(\.\d*%)\s*,\s*(\.\d*%)\s*(,\s*\.\d*\s*)?\)/i;
// hsl(240 100% 50%) // ✅✅✅✅
// hsl(240 100% 50% / 0.1) // space separated with opacity
const MATCHER3 = /hsla?\(\s*(\d*)\s\s*(\d*%)\s\s*(\d*%)\s*(\/\s*\d*.\d*\s*)?\)/i;
// hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3)
const MATCHER4 = /hsla?\(\s*(\d*.\d*e\+\d*)\s*,\s*(\d*.\d*e\+\d*%),\s*(\d*.\d*e\+\d*%)\s*(,\s*\d*E-\d*)?/i;
/hsla?\(\s*(\+?-?\d*\.?\d*(?:e\+)?(?:\d*)?(?:deg|rad|grad|turn)?)\s*,\s*(\+?\-?\d*\.?\d*(?:e\+)?(?:\d*)?%)\s*,\s*(\+?\-?\d*\.?\d*(?:e\+)?(?:\d*)?%)\s*(,\s*\+?\-?\s*(?:\d*\.?\d*(?:E-\d*)?%?)?)?\s*\)/i;
const MATCHER_SPACE =
/hsla?\(\s*(\+?-?\d*\.?\d*(?:e\+)?(?:\d*)?(?:deg|rad|grad|turn)?)\s*(\+?\-?\d*\.?\d*(?:e\+)?(?:\d*)?%)\s*(\+?\-?\d*\.?\d*(?:e\+)?(?:\d*)?%)\s*(\/\s*\+?\-?\s*(?:\d*\.?\d*(?:E-\d*)?%?)?)?\s*\)/i;

const aStr = (a?: string) => (a ? a.replace(/^(,|\/)\s*/, '').trim() : a);

Expand All @@ -33,22 +27,11 @@ export interface HSLAObjectStringColor extends HSLObjectStringColor {

/** Convert HLS string to HLS object or verify whether hls is valid */
export default function hslMatcher(hsl: string = ''): HSLAObjectStringColor | undefined {
const match = MATCHER.exec(hsl);
const match = MATCHER.exec(hsl) || MATCHER_SPACE.exec(hsl);
if (!!match) {
const [_, h, __, s, l, a] = match;
return {
h,
s,
l,
a: aStr(a),
};
}
const match2 = MATCHER2.exec(hsl);
const match3 = MATCHER3.exec(hsl);
const match4 = MATCHER4.exec(hsl);
const arr = match2 || match3 || match4;
if (!!arr) {
const [_, h, s, l, a] = arr;
const [_, h, s, l, a] = match;
if (a && a.trim() === ',') return;
if (a && a.trim() === '/') return;
return {
h,
s,
Expand Down Expand Up @@ -144,7 +127,8 @@ export function hlsStringToRGB(hls: string): RGBColor | RGBAColor | undefined {
* Values outside the range [0,1] are not invalid, but are clamped to that range when computed.
*/
if (alphaStr && /^\+?-?\d*(E-\d*|.\d*%?)?$/.test(alphaStr)) {
return { r: toFixed(255 * f(0)), g: toFixed(255 * f(8)), b: toFixed(255 * f(4)), a: Number(alphaStr) };
const alpha = /%/g.test(alphaStr) ? Number(alphaStr.replace(/%/g, '')) / 100 : Number(alphaStr);
return { r: toFixed(255 * f(0)), g: toFixed(255 * f(8)), b: toFixed(255 * f(4)), a: alpha };
}
return { r: toFixed(255 * f(0)), g: toFixed(255 * f(8)), b: toFixed(255 * f(4)) };
}
Expand Down

0 comments on commit b5dc4ed

Please # to comment.