Browse Source

Support HSL colors (#679)

* refactor: split rgb parsing and convertion in two functions

This will be useful for the following as we will need a function to convert from hsl to hex. To do that, we'll need a function to convert from hsl to rgb and then from rgb to hex. So, this commit helps us reuse the code for doing the last step.

* feat: add support for hsl colors

* refactor: rename test file
master
Antoine Cottineau 2 years ago
committed by GitHub
parent
commit
074dd6dc20
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 11 deletions
  1. +11
    -0
      src/colorConversions.test.js
  2. +70
    -11
      src/colorToHex.js

src/rgba2hex.test.js → src/colorConversions.test.js View File

@ -40,4 +40,15 @@ describe('colorToHex', () => {
it('return undefined when undefined', () => {
expect(colorToHex(undefined)).toEqual(undefined)
})
it('should transform hsl to hex', () => {
expect(colorToHex('hsl(0, 0%, 0%)')).toEqual('#000000')
expect(colorToHex('hsl(0, 0%, 100%)')).toEqual('#ffffff')
expect(colorToHex('hsl(0, 0%, 50%)')).toEqual('#808080')
expect(colorToHex('hsl(34, 87%, 50%)')).toEqual('#ee8e11')
expect(colorToHex('hsl(137, 83%, 71%)')).toEqual('#78f29a')
expect(colorToHex('hsl(360 100% 100%)')).toEqual('#ffffff')
expect(colorToHex('hsla(137, 83%, 71%, 0.5)')).toEqual('#78f29a')
expect(colorToHex('hsla(360 100% 100% / 1.0)')).toEqual('#ffffff')
})
})

+ 70
- 11
src/colorToHex.js View File

@ -1,7 +1,8 @@
export function colorToHex(c) {
if (c === undefined) return c
if (c === "none") return c
if (c.includes('rgb')) return rgb2hex(c)
if (c === 'none') return c
if (c.includes('rgb')) return rgb2hex(parseRgb(c))
if (c.includes('hsl')) return hsl2hex(parseHsl(c))
if (c.includes('#')) {
if (!isValidHex(c)) throw Error('Invalid color: ' + c)
if (c.length === 4) return '#' + c[1] + c[1] + c[2] + c[2] + c[3] + c[3]
@ -16,16 +17,74 @@ function isValidHex(color) {
return /^#([0-9A-Fa-f]{3}){1,2}$/i.test(color)
}
function rgb2hex(rgb) {
rgb = rgb.match(
/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i
function parseRgb(rgb) {
return rgb
.match(
/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i
)
.slice(1)
}
function rgb2hex(rgbArray) {
if (rgbArray.length != 3) {
return ''
}
return (
'#' +
parseInt(rgbArray[0]).toString(16).padStart(2, '0') +
parseInt(rgbArray[1]).toString(16).padStart(2, '0') +
parseInt(rgbArray[2]).toString(16).padStart(2, '0')
)
return rgb && rgb.length === 4
? '#' +
('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) +
('0' + parseInt(rgb[2], 10).toString(16)).slice(-2) +
('0' + parseInt(rgb[3], 10).toString(16)).slice(-2)
: ''
}
function parseHsl(hsl) {
const matches = hsl.match(
/^hsla*\((\d{1,3})\s*[, ]\s*(\d{1,3})%\s*[, ]\s*(\d{1,3})%.*\)/i
)
if (matches === null) {
throw Error('Invalid color: ' + hsl)
}
const h = matches[1] / 360
const s = matches[2] / 100
const l = matches[3] / 100
return [h, s, l]
}
function hsl2hex(hslArray) {
if (hslArray.length != 3) {
return ''
}
const [h, s, l] = hslArray
var r, g, b
if (s === 0) {
r = g = b = l
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1
if (t > 1) t -= 1
if (t < 1 / 6) return p + (q - p) * 6 * t
if (t < 1 / 2) return q
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
return p
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s
const p = 2 * l - q
r = hue2rgb(p, q, h + 1 / 3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1 / 3)
}
return rgb2hex([
Math.round(r * 255),
Math.round(g * 255),
Math.round(b * 255),
])
}
function colourNameToHex(color) {

Loading…
Cancel
Save