From 96bfb4166152c884e271db8cd32bfce660f9a3f3 Mon Sep 17 00:00:00 2001 From: BenjaminJ Date: Fri, 18 Oct 2024 12:30:47 +0200 Subject: [PATCH] feat: Add support for new HSL syntax along side legacy one --- src/lib/colors/strategies/hsl-strategy.ts | 15 +- .../hsl-extractor.test.ts | 142 ++++++++++++++++++ 2 files changed, 153 insertions(+), 4 deletions(-) diff --git a/src/lib/colors/strategies/hsl-strategy.ts b/src/lib/colors/strategies/hsl-strategy.ts index 8755616b..99336c52 100644 --- a/src/lib/colors/strategies/hsl-strategy.ts +++ b/src/lib/colors/strategies/hsl-strategy.ts @@ -5,15 +5,20 @@ import { DOT_VALUE, ALPHA, EOL } from '../../util/regexp'; import ColorStrategy from './__strategy-base'; const R_HUE = `\\d*${DOT_VALUE}?`; -const R_SATURATION = `(?:\\d{1,3}${DOT_VALUE}?|${DOT_VALUE})%`; +const R_SATURATION = `(?:\\d{1,3}${DOT_VALUE}?|${DOT_VALUE})`; const R_LUMINANCE = R_SATURATION; +const R_ALPHA = `([ ,]\\s*${ALPHA}\\s*|\\s*\\/\\s*${R_SATURATION}%?\\s*)?`; + +const HSL_NEW_SYNTAX = `hsla?\\(\\s*${R_HUE}(deg)?\\s*\\s*${R_SATURATION}%?\\s*\\s*${R_LUMINANCE}%?\\s*${R_ALPHA}\\)`; +const HSL_LEGACY_SYNTAX = `hsl\\(\\s*${R_HUE}\\s*,\\s*${R_SATURATION}%\\s*,\\s*${R_LUMINANCE}%\\s*\\)`; +const HSLA_LEGACY_SYNTAX = `hsla\\(\\s*${R_HUE}\\s*,\\s*${R_SATURATION}%\\s*,\\s*${R_LUMINANCE}%\\s*,\\s*${ALPHA}\\s*\\)`; export const REGEXP = new RegExp( - `((?:hsl\\(\\s*${R_HUE}\\s*,\\s*${R_SATURATION}\\s*,\\s*${R_LUMINANCE}\\s*\\))|(?:hsla\\(\\s*${R_HUE}\\s*,\\s*${R_SATURATION}\\s*,\\s*${R_LUMINANCE}\\s*,\\s*${ALPHA}\\s*\\)))${EOL}`, + `(${HSL_LEGACY_SYNTAX}|${HSLA_LEGACY_SYNTAX}|${HSL_NEW_SYNTAX})${EOL}`, 'gi', ); export const REGEXP_ONE = new RegExp( - `^((?:hsl\\(\\s*${R_HUE}\\s*,\\s*${R_SATURATION}\\s*,\\s*${R_LUMINANCE}\\s*\\))|(?:hsla\\(\\s*${R_HUE}\\s*,\\s*${R_SATURATION}\\s*,\\s*${R_LUMINANCE}\\s*,\\s*${ALPHA}\\s*\\)))${EOL}`, + `^(${HSL_LEGACY_SYNTAX}|${HSLA_LEGACY_SYNTAX}|${HSL_NEW_SYNTAX})${EOL}`, 'i', ); // export const REGEXP_ONE = /^((?:hsl\(\d*\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\))|(?:hsla\(\d*\s*,\s*(?:\d{1,3}%\s*,\s*){2}(?:[0-1]|1\.0|[0](?:\.\d+){0,1}|(?:\.\d+))\)))(?:$|"|'|,| |;|\)|\r|\n)/i; @@ -30,7 +35,9 @@ function extractHSLValue(value: string) { .replace(/hsl(a){0,1}\(/, '') .replace(/\)/, '') .replace(/%/g, '') - .split(/,/gi) + .replace(/deg/, '') + .replaceAll(',', ' ') + .split(/\s+/) .map((c) => parseFloat(c)); return [h, s, l, a]; } diff --git a/test/unit/color-extractor-strategies/hsl-extractor.test.ts b/test/unit/color-extractor-strategies/hsl-extractor.test.ts index 04877de7..96783b47 100644 --- a/test/unit/color-extractor-strategies/hsl-extractor.test.ts +++ b/test/unit/color-extractor-strategies/hsl-extractor.test.ts @@ -3,8 +3,36 @@ import { describe, it } from 'mocha'; import { REGEXP } from '../../../src/lib/colors/strategies/hsl-strategy'; import { regex_exec } from '../../test-util'; +import HSLStrategy from '../../../src/lib/colors/strategies/hsl-strategy'; describe('Test hsl(a) color Regex', () => { + it('Should match new hsl syntax', function () { + assert.equal( + regex_exec('hsl(120deg 75% 25%)', REGEXP)[1], + 'hsl(120deg 75% 25%)', + ); + assert.equal( + regex_exec('hsl(120 75 25)', REGEXP)[1], + 'hsl(120 75 25)', + ); /* deg and % units are optional */ + assert.equal( + regex_exec('hsl(120deg 75% 25% / 60%)', REGEXP)[1], + 'hsl(120deg 75% 25% / 60%)', + ); + assert.equal( + regex_exec('hsl(120deg 75% 25)', REGEXP)[1], + 'hsl(120deg 75% 25)', + ); + assert.equal( + regex_exec('hsl(120deg 75 25%)', REGEXP)[1], + 'hsl(120deg 75 25%)', + ); + assert.equal(regex_exec('hsl(120 75% 25%)', REGEXP)[1], 'hsl(120 75% 25%)'); + // assert.equal( + // regex_exec('hsl(none 75% 25%)', REGEXP)[1], + // 'hsl(120deg 75% 25% / 60%)', + // ); // Not supported yet + }); it('Should match a simple hsl color', function () { assert.equal( regex_exec('hsl(200, 10%, 10%)', REGEXP)[1], @@ -135,3 +163,117 @@ describe('Test hsl(a) color Regex', () => { ); }); }); + +describe('Extract color', () => { + it('Should match new hsl syntax', function () { + assert.deepEqual( + HSLStrategy.extractColor('hsl(120deg 75% 25%)')?.rgb, + [16, 112, 16], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(120 75 25)')?.rgb, + [16, 112, 16], + ); /* deg and % units are optional */ + assert.deepEqual( + HSLStrategy.extractColor('hsl(120deg 75% 25% / 60%)')?.rgb, + [16, 112, 16], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(120deg 75% 25)')?.rgb, + [16, 112, 16], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(120deg 75 25%)')?.rgb, + [16, 112, 16], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(120 75% 25%)')?.rgb, + [16, 112, 16], + ); + // assert.equal( + // regex_exec('hsl(none 75% 25%)'), + // 'hsl(120deg 75% 25% / 60%)', + // ); // Not supported yet + }); + it('Should match a simple hsl color', function () { + assert.deepEqual( + HSLStrategy.extractColor('hsl(200, 10%, 10%)')?.rgb, + [23, 26, 28], + ); + }); + it('Should match a simple hsla color', function () { + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10%, 0)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10%, 0.3)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10%, .3)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10%, 1)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10%, 1.0)')?.rgb, + [23, 26, 28], + ); + }); + it('Should accept dot values (hsl)', function () { + assert.deepEqual( + HSLStrategy.extractColor('hsl(200.1, 10%, 10%)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(200, 10.1%, 10%)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(200, 10%, 10.1%)')?.rgb, + [23, 27, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(200, 10%, 10.1111111%)')?.rgb, + [23, 27, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(200.1, 10.1%, 10.1%)')?.rgb, + [23, 27, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsl(.1, 10.1%, 10.1%)')?.rgb, + [28, 23, 23], + ); + }); + + it('Should accept dot values (hsla)', function () { + assert.deepEqual( + HSLStrategy.extractColor('hsla(200.1, 10%, 10%, 1)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10.1%, 10%, 1)')?.rgb, + [23, 26, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10.1%, 1)')?.rgb, + [23, 27, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200, 10%, 10.1%, 1.0)')?.rgb, + [23, 27, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(200.1, 10.1%, 10.1%, 1)')?.rgb, + [23, 27, 28], + ); + assert.deepEqual( + HSLStrategy.extractColor('hsla(.1, 10.1%, 10.1%, 1)')?.rgb, + [28, 23, 23], + ); + }); +});