Skip to content

Commit

Permalink
Support HSL with hue units in arbitrary values (#6726)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwathan committed Dec 24, 2021
1 parent da7396c commit 1d5aa27
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 22 deletions.
27 changes: 20 additions & 7 deletions src/util/color.js
Expand Up @@ -5,8 +5,11 @@ let SHORT_HEX = /^#([a-f\d])([a-f\d])([a-f\d])([a-f\d])?$/i
let VALUE = `(?:\\d+|\\d*\\.\\d+)%?`
let SEP = `(?:\\s*,\\s*|\\s+)`
let ALPHA_SEP = `\\s*[,/]\\s*`
let RGB_HSL = new RegExp(
`^(rgb|hsl)a?\\(\\s*(${VALUE})${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`
let RGB = new RegExp(
`^rgba?\\(\\s*(${VALUE})${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`
)
let HSL = new RegExp(
`^hsla?\\(\\s*((?:${VALUE})(?:deg|rad|grad|turn)?)${SEP}(${VALUE})${SEP}(${VALUE})(?:${ALPHA_SEP}(${VALUE}))?\\s*\\)$`
)

export function parseColor(value) {
Expand Down Expand Up @@ -37,13 +40,23 @@ export function parseColor(value) {
}
}

let match = value.match(RGB_HSL)
let rgbMatch = value.match(RGB)

if (rgbMatch !== null) {
return {
mode: 'rgb',
color: [rgbMatch[1], rgbMatch[2], rgbMatch[3]].map((v) => v.toString()),
alpha: rgbMatch[4]?.toString?.(),
}
}

let hslMatch = value.match(HSL)

if (match !== null) {
if (hslMatch !== null) {
return {
mode: match[1],
color: [match[2], match[3], match[4]].map((v) => v.toString()),
alpha: match[5]?.toString?.(),
mode: 'hsl',
color: [hslMatch[1], hslMatch[2], hslMatch[3]].map((v) => v.toString()),
alpha: hslMatch[4]?.toString?.(),
}
}

Expand Down
7 changes: 7 additions & 0 deletions tests/arbitrary-values.test.css
Expand Up @@ -603,6 +603,13 @@
.bg-\[hsla\(0\2c 100\%\2c 50\%\2c 0\.3\)\] {
background-color: hsla(0, 100%, 50%, 0.3);
}
.bg-\[hsl\(0rad\2c 100\%\2c 50\%\)\] {
--tw-bg-opacity: 1;
background-color: hsl(0rad 100% 50% / var(--tw-bg-opacity));
}
.bg-\[hsla\(0turn\2c 100\%\2c 50\%\2c 0\.3\)\] {
background-color: hsla(0turn, 100%, 50%, 0.3);
}
.bg-\[\#0f0_var\(--value\)\] {
background-color: #0f0 var(--value);
}
Expand Down
1 change: 1 addition & 0 deletions tests/arbitrary-values.test.html
Expand Up @@ -216,6 +216,7 @@
<div class="bg-[rgb(123,_456,_123)_black]"></div>
<div class="bg-[rgb(123_456_789)]"></div>
<div class="bg-[hsl(0,100%,50%)] bg-[hsla(0,100%,50%,0.3)]"></div>
<div class="bg-[hsl(0rad,100%,50%)] bg-[hsla(0turn,100%,50%,0.3)]"></div>
<div class="bg-[#0f0_var(--value)]"></div>
<div class="bg-[var(--value1)_var(--value2)]"></div>
<div class="bg-[color:var(--value1)_var(--value2)]"></div>
Expand Down
46 changes: 31 additions & 15 deletions tests/color.test.js
Expand Up @@ -2,21 +2,37 @@ import { parseColor, formatColor } from '../src/util/color'

describe('parseColor', () => {
it.each`
color | output
${'black'} | ${{ mode: 'rgb', color: ['0', '0', '0'], alpha: undefined }}
${'#0088cc'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: undefined }}
${'#08c'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: undefined }}
${'#0088cc99'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: '0.6' }}
${'#08c9'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: '0.6' }}
${'rgb(0, 30, 60)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: undefined }}
${'rgba(0, 30, 60, 0.5)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: '0.5' }}
${'rgb(0 30 60)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: undefined }}
${'rgb(0 30 60 / 0.5)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: '0.5' }}
${'hsl(0, 30%, 60%)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: undefined }}
${'hsla(0, 30%, 60%, 0.5)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: '0.5' }}
${'hsl(0 30% 60%)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: undefined }}
${'hsl(0 30% 60% / 0.5)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: '0.5' }}
${'transparent'} | ${{ mode: 'rgb', color: ['0', '0', '0'], alpha: '0' }}
color | output
${'black'} | ${{ mode: 'rgb', color: ['0', '0', '0'], alpha: undefined }}
${'#0088cc'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: undefined }}
${'#08c'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: undefined }}
${'#0088cc99'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: '0.6' }}
${'#08c9'} | ${{ mode: 'rgb', color: ['0', '136', '204'], alpha: '0.6' }}
${'rgb(0, 30, 60)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: undefined }}
${'rgba(0, 30, 60, 0.5)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: '0.5' }}
${'rgb(0 30 60)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: undefined }}
${'rgb(0 30 60 / 0.5)'} | ${{ mode: 'rgb', color: ['0', '30', '60'], alpha: '0.5' }}
${'hsl(0, 30%, 60%)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: undefined }}
${'hsl(0deg, 30%, 60%)'} | ${{ mode: 'hsl', color: ['0deg', '30%', '60%'], alpha: undefined }}
${'hsl(0rad, 30%, 60%)'} | ${{ mode: 'hsl', color: ['0rad', '30%', '60%'], alpha: undefined }}
${'hsl(0grad, 30%, 60%)'} | ${{ mode: 'hsl', color: ['0grad', '30%', '60%'], alpha: undefined }}
${'hsl(0turn, 30%, 60%)'} | ${{ mode: 'hsl', color: ['0turn', '30%', '60%'], alpha: undefined }}
${'hsla(0, 30%, 60%, 0.5)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: '0.5' }}
${'hsla(0deg, 30%, 60%, 0.5)'} | ${{ mode: 'hsl', color: ['0deg', '30%', '60%'], alpha: '0.5' }}
${'hsla(0rad, 30%, 60%, 0.5)'} | ${{ mode: 'hsl', color: ['0rad', '30%', '60%'], alpha: '0.5' }}
${'hsla(0grad, 30%, 60%, 0.5)'} | ${{ mode: 'hsl', color: ['0grad', '30%', '60%'], alpha: '0.5' }}
${'hsla(0turn, 30%, 60%, 0.5)'} | ${{ mode: 'hsl', color: ['0turn', '30%', '60%'], alpha: '0.5' }}
${'hsl(0 30% 60%)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: undefined }}
${'hsl(0deg 30% 60%)'} | ${{ mode: 'hsl', color: ['0deg', '30%', '60%'], alpha: undefined }}
${'hsl(0rad 30% 60%)'} | ${{ mode: 'hsl', color: ['0rad', '30%', '60%'], alpha: undefined }}
${'hsl(0grad 30% 60%)'} | ${{ mode: 'hsl', color: ['0grad', '30%', '60%'], alpha: undefined }}
${'hsl(0turn 30% 60%)'} | ${{ mode: 'hsl', color: ['0turn', '30%', '60%'], alpha: undefined }}
${'hsl(0 30% 60% / 0.5)'} | ${{ mode: 'hsl', color: ['0', '30%', '60%'], alpha: '0.5' }}
${'hsl(0deg 30% 60% / 0.5)'} | ${{ mode: 'hsl', color: ['0deg', '30%', '60%'], alpha: '0.5' }}
${'hsl(0rad 30% 60% / 0.5)'} | ${{ mode: 'hsl', color: ['0rad', '30%', '60%'], alpha: '0.5' }}
${'hsl(0grad 30% 60% / 0.5)'} | ${{ mode: 'hsl', color: ['0grad', '30%', '60%'], alpha: '0.5' }}
${'hsl(0turn 30% 60% / 0.5)'} | ${{ mode: 'hsl', color: ['0turn', '30%', '60%'], alpha: '0.5' }}
${'transparent'} | ${{ mode: 'rgb', color: ['0', '0', '0'], alpha: '0' }}
`('should parse "$color" to the correct value', ({ color, output }) => {
expect(parseColor(color)).toEqual(output)
})
Expand Down

0 comments on commit 1d5aa27

Please sign in to comment.