Merge branch 'hsl-spaces'

This commit is contained in:
Robin Malfait 2021-09-01 17:29:52 +02:00
commit d5c87f9632
No known key found for this signature in database
GPG Key ID: 92F53D68B9041AFE
5 changed files with 106 additions and 109 deletions

76
package-lock.json generated
View File

@ -11,8 +11,8 @@
"arg": "^5.0.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.2",
"color": "^4.0.1",
"cosmiconfig": "^7.0.1",
"culori": "^0.19.1",
"detective": "^5.2.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
@ -3434,15 +3434,6 @@
"node": ">=0.10.0"
}
},
"node_modules/color": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/color/-/color-4.0.1.tgz",
"integrity": "sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA==",
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.6.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -3459,15 +3450,6 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/color-string": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz",
"integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/colord": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.7.0.tgz",
@ -3828,6 +3810,11 @@
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
"dev": true
},
"node_modules/culori": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/culori/-/culori-0.19.1.tgz",
"integrity": "sha512-K/NLpdtNnSQwH2Ru/Fk39wDL40v9PxTBFY6jHQegJDhmBqrE/d9mJB/AD4odSZJml10AlJjZdm6+I9JM3nE/EQ=="
},
"node_modules/data-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
@ -9121,19 +9108,6 @@
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/simple-swizzle/node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@ -12928,15 +12902,6 @@
"object-visit": "^1.0.0"
}
},
"color": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/color/-/color-4.0.1.tgz",
"integrity": "sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA==",
"requires": {
"color-convert": "^2.0.1",
"color-string": "^1.6.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -12950,15 +12915,6 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"color-string": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz",
"integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"colord": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.7.0.tgz",
@ -13232,6 +13188,11 @@
}
}
},
"culori": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/culori/-/culori-0.19.1.tgz",
"integrity": "sha512-K/NLpdtNnSQwH2Ru/Fk39wDL40v9PxTBFY6jHQegJDhmBqrE/d9mJB/AD4odSZJml10AlJjZdm6+I9JM3nE/EQ=="
},
"data-urls": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
@ -17174,21 +17135,6 @@
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==",
"dev": true
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"requires": {
"is-arrayish": "^0.3.1"
},
"dependencies": {
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
}
}
},
"sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",

View File

@ -70,8 +70,8 @@
"arg": "^5.0.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.2",
"color": "^4.0.1",
"cosmiconfig": "^7.0.1",
"culori": "^0.19.1",
"detective": "^5.2.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",

View File

@ -1,6 +1,6 @@
import selectorParser from 'postcss-selector-parser'
import postcss from 'postcss'
import createColor from 'color'
import * as culori from 'culori'
import escapeCommas from './escapeCommas'
import { withAlphaValue } from './withAlphaVariable'
import isKeyframeRule from './isKeyframeRule'
@ -222,12 +222,7 @@ function splitAlpha(modifier) {
}
function isColor(value) {
try {
createColor(value)
return true
} catch (e) {
return false
}
return culori.parse(value) !== undefined
}
export function asColor(modifier, lookup = {}, tailwindConfig = {}) {

View File

@ -1,25 +1,8 @@
import createColor from 'color'
import * as culori from 'culori'
import _ from 'lodash'
function hasAlpha(color) {
return (
color.startsWith('rgba(') ||
color.startsWith('hsla(') ||
(color.startsWith('#') && color.length === 9) ||
(color.startsWith('#') && color.length === 5)
)
}
export function toRgba(color) {
const [r, g, b, a] = createColor(color).rgb().array()
return [r, g, b, a === undefined && hasAlpha(color) ? 1 : a]
}
export function toHsla(color) {
const [h, s, l, a] = createColor(color).hsl().array()
return [h, `${s}%`, `${l}%`, a === undefined && hasAlpha(color) ? 1 : a]
function isValidColor(color) {
return culori.parse(color) !== undefined
}
export function withAlphaValue(color, alphaValue, defaultValue) {
@ -27,13 +10,33 @@ export function withAlphaValue(color, alphaValue, defaultValue) {
return color({ opacityValue: alphaValue })
}
try {
const isHSL = color.startsWith('hsl')
const [i, j, k] = isHSL ? toHsla(color) : toRgba(color)
return `${isHSL ? 'hsla' : 'rgba'}(${i}, ${j}, ${k}, ${alphaValue})`
} catch {
return defaultValue
if (isValidColor(color)) {
// Parse color
const parsed = culori.parse(color)
// Apply alpha value
parsed.alpha = alphaValue
// Format string
let value
if (parsed.mode === 'hsl') {
value = culori.formatHsl(parsed)
} else {
value = culori.formatRgb(parsed)
}
// Correctly apply CSS variable alpha value
if (typeof alphaValue === 'string' && alphaValue.startsWith('var(') && value.endsWith('NaN)')) {
value = value.replace('NaN)', `${alphaValue})`)
}
// Color could not be formatted correctly
if (!value.includes('NaN')) {
return value
}
}
return defaultValue
}
export default function withAlphaVariable({ color, property, variable }) {
@ -44,24 +47,29 @@ export default function withAlphaVariable({ color, property, variable }) {
}
}
try {
const isHSL = color.startsWith('hsl')
if (isValidColor(color)) {
const parsed = culori.parse(color)
const [i, j, k, a] = isHSL ? toHsla(color) : toRgba(color)
if (a !== undefined) {
if ('alpha' in parsed) {
// Has an alpha value, return color as-is
return {
[property]: color,
}
}
const formatFn = parsed.mode === 'hsl' ? 'formatHsl' : 'formatRgb'
const value = culori[formatFn]({
...parsed,
alpha: NaN, // intentionally set to `NaN` for replacing
}).replace('NaN)', `var(${variable}))`)
return {
[variable]: '1',
[property]: `${isHSL ? 'hsla' : 'rgba'}(${i}, ${j}, ${k}, var(${variable}))`,
}
} catch (error) {
return {
[property]: color,
[property]: value,
}
}
return {
[property]: color,
}
}

View File

@ -7,6 +7,16 @@ test('it adds the right custom property', () => {
'--tw-text-opacity': '1',
color: 'rgba(255, 0, 0, var(--tw-text-opacity))',
})
expect(
withAlphaVariable({
color: 'hsl(240 100% 50%)',
property: 'color',
variable: '--tw-text-opacity',
})
).toEqual({
'--tw-text-opacity': '1',
color: 'hsla(240, 100%, 50%, var(--tw-text-opacity))',
})
})
test('it ignores colors that cannot be parsed', () => {
@ -76,6 +86,15 @@ test('it ignores colors that already have an alpha channel', () => {
).toEqual({
'background-color': 'rgba(255, 255, 255, 0.5)',
})
expect(
withAlphaVariable({
color: 'rgba(255 255 255 / 0.5)',
property: 'background-color',
variable: '--tw-bg-opacity',
})
).toEqual({
'background-color': 'rgba(255 255 255 / 0.5)',
})
expect(
withAlphaVariable({
color: 'hsla(240, 100%, 50%, 1)',
@ -94,6 +113,15 @@ test('it ignores colors that already have an alpha channel', () => {
).toEqual({
'background-color': 'hsla(240, 100%, 50%, 0.5)',
})
expect(
withAlphaVariable({
color: 'hsl(240 100% 50% / 0.5)',
property: 'background-color',
variable: '--tw-bg-opacity',
})
).toEqual({
'background-color': 'hsl(240 100% 50% / 0.5)',
})
})
test('it allows a closure to be passed', () => {
@ -130,6 +158,16 @@ test('it transforms rgb and hsl to rgba and hsla', () => {
'--tw-bg-opacity': '1',
'background-color': 'rgba(50, 50, 50, var(--tw-bg-opacity))',
})
expect(
withAlphaVariable({
color: 'rgb(50 50 50)',
property: 'background-color',
variable: '--tw-bg-opacity',
})
).toEqual({
'--tw-bg-opacity': '1',
'background-color': 'rgba(50, 50, 50, var(--tw-bg-opacity))',
})
expect(
withAlphaVariable({
color: 'hsl(50, 50%, 50%)',
@ -140,4 +178,14 @@ test('it transforms rgb and hsl to rgba and hsla', () => {
'--tw-bg-opacity': '1',
'background-color': 'hsla(50, 50%, 50%, var(--tw-bg-opacity))',
})
expect(
withAlphaVariable({
color: 'hsl(50 50% 50%)',
property: 'background-color',
variable: '--tw-bg-opacity',
})
).toEqual({
'--tw-bg-opacity': '1',
'background-color': 'hsla(50, 50%, 50%, var(--tw-bg-opacity))',
})
})