Improve type detection for arbitrary color values (#8201)

This commit is contained in:
Brad Cornes 2022-04-28 11:18:51 +01:00 • committed by GitHub
parent 89bf2ed46d
commit cc696338b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 19 deletions

View file

@ -8,13 +8,15 @@ let ALPHA_SEP = /\s*[,/]\s*/
let CUSTOM_PROPERTY = /var\(--(?:[^ )]*?)\)/
let RGB = new RegExp(
`^rgba?\\(\\s*(${VALUE.source}|${CUSTOM_PROPERTY.source})${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source})${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source})(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`
`^(rgb)a?\\(\\s*(${VALUE.source}|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`
)
let HSL = new RegExp(
`^hsla?\\(\\s*((?:${VALUE.source})(?:deg|rad|grad|turn)?|${CUSTOM_PROPERTY.source})${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source})${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source})(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`
`^(hsl)a?\\(\\s*((?:${VALUE.source})(?:deg|rad|grad|turn)?|${CUSTOM_PROPERTY.source})(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?(?:${ALPHA_SEP.source}(${VALUE.source}|${CUSTOM_PROPERTY.source}))?\\s*\\)$`
)
export function parseColor(value) {
// In "loose" mode the color may contain fewer than 3 parts, as long as at least
// one of the parts is variable.
export function parseColor(value, { loose = false } = {}) {
if (typeof value !== 'string') {
return null
}
@ -42,27 +44,27 @@ export function parseColor(value) {
}
}
let rgbMatch = value.match(RGB)
let match = value.match(RGB) ?? value.match(HSL)
if (rgbMatch !== null) {
return {
mode: 'rgb',
color: [rgbMatch[1], rgbMatch[2], rgbMatch[3]].map((v) => v.toString()),
alpha: rgbMatch[4]?.toString?.(),
}
if (match === null) {
return null
}
let hslMatch = value.match(HSL)
let color = [match[2], match[3], match[4]].filter(Boolean).map((v) => v.toString())
if (hslMatch !== null) {
return {
mode: 'hsl',
color: [hslMatch[1], hslMatch[2], hslMatch[3]].map((v) => v.toString()),
alpha: hslMatch[4]?.toString?.(),
}
if (!loose && color.length !== 3) {
return null
}
return null
if (color.length < 3 && !color.some((part) => /^var\(.*?\)$/.test(part))) {
return null
}
return {
mode: match[1],
color,
alpha: match[5]?.toString?.(),
}
}
export function formatColor({ mode, color, alpha }) {

View file

@ -121,7 +121,7 @@ export function color(value) {
part = normalize(part)
if (part.startsWith('var(')) return true
if (parseColor(part) !== null) return colors++, true
if (parseColor(part, { loose: true }) !== null) return colors++, true
return false
})

View file

@ -68,6 +68,8 @@ it('should support arbitrary values for various background utilities', () => {
<!-- By implicit type -->
<div class="bg-[url('/image-1-0.png')]"></div>
<div class="bg-[#ff0000]"></div>
<div class="bg-[rgb(var(--bg-color))]"></div>
<div class="bg-[hsl(var(--bg-color))]"></div>
<!-- By explicit type -->
<div class="bg-[url:var(--image-url)]"></div>
@ -89,6 +91,14 @@ it('should support arbitrary values for various background utilities', () => {
background-color: rgb(255 0 0 / var(--tw-bg-opacity));
}
.bg-\[rgb\(var\(--bg-color\)\)\] {
background-color: rgb(var(--bg-color));
}
.bg-\[hsl\(var\(--bg-color\)\)\] {
background-color: hsl(var(--bg-color));
}
.bg-\[color\:var\(--bg-color\)\] {
background-color: var(--bg-color);
}