Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve type detection for arbitrary color values #8201

Merged
merged 1 commit into from Apr 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 20 additions & 18 deletions src/util/color.js
Expand Up @@ -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*\\)$`
)
Comment on lines 10 to 15
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second and third color parts have been made optional, and the amount of parts is validated later instead (line 55)


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
}
Expand Down Expand Up @@ -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 }) {
Expand Down
2 changes: 1 addition & 1 deletion src/util/dataTypes.js
Expand Up @@ -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
})
Expand Down
10 changes: 10 additions & 0 deletions tests/arbitrary-values.test.js
Expand Up @@ -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>
Expand All @@ -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);
}
Expand Down