This is a very old question, but I just wanted to provide an up-to-date answer.
My solution can be a bit daunting to look at, but I believe it comes close to the extent of possible values, including the new CSS Color Level 4.
/** Regular expression for valid CSS number */
const cssNumberMatcher = /[+-]?(?=\.\d|\d)\d*(?:\.\d+)?(?:[eE][+-]?\d+)?/
/** Regular expression for color component separator */
const separatorMatcher = /(?=[,\s])\s*(?:,\s*)?/
/** Regular expression for alpha separator */
const alphaSeparatorMatcher = /\s*[,\/]\s*/
const num = cssNumberMatcher.source
const sep = separatorMatcher.source
const asep = alphaSeparatorMatcher.source
/**
* Regular expression for HSL color string
*
* The pattern is less strict than actual CSS, mainly for
* performance reasons. Notably, it does NOT impose
* consistent separator (comma vs. space)
*/
const hslMatcher = new RegExp(
`hsla?\\(\\s*(${num}(?:deg|rad|grad|turn)?)${sep}(${num})%${sep}(${num})%(?:${asep}(${num}%?))?\\s*\\)`,
'i',
)
/**
* Attempts to match the given color string with the HSL
* string pattern, and extracts the color components
*
* Since the standard unit for S and L values is percent,
* the % sign is not included in the captured values.
*
* @param colorString
* @returns an array containing the matched HSL values, or `null`
*/
function matchHslString(colorString) {
const match = hslMatcher.exec(colorString)
return match?.slice(1) ?? null
}
It's up to you now how to generate the hex string from those HSL values. You will need to transform it first to RGB model, then to Hex.
Here are the supported formats (up to CSS Color Level 4):
const valid = [
'hsl(240, 100%, 50%)', // comma separated
'hsl(240, 100%, 50%, 0.1)', // comma separated with opacity
'hsl(240, 100%, 50%, 10%)', // comma separated with % opacity
'hsl(240,100%,50%,0.1)', // comma separated without spaces
'hsl(180deg, 100%, 50%, 0.1)', // hue with 'deg'
'hsl(3.14rad, 100%, 50%, 0.1)', // hue with 'rad'
'hsl(200grad, 100%, 50%, 0.1)', // hue with 'grad'
'hsl(0.5turn, 100%, 50%, 0.1)', // hue with 'turn'
'hsl(-240, -100%, -50%, -0.1)', // negative values
'hsl(+240, +100%, +50%, +0.1)', // explicit positive sign
'hsl(240.5, 99.99%, 49.999%, 0.9999)', // non-integer values
'hsl(.9, .99%, .999%, .9999)', // fraction w/o leading zero
'hsl(0240, 0100%, 0050%, 01)', // leading zeros
'hsl(240.0, 100.00%, 50.000%, 1.0000)', // trailing decimal zeros
'hsl(2400, 1000%, 1000%, 10)', // out of range values
'hsl(-2400.01deg, -1000.5%, -1000.05%, -100)', // combination of above
'hsl(2.40e+2, 1.00e+2%, 5.00e+1%, 1E-3)', // scientific notation
'hsl(240 100% 50%)', // space separated (CSS Color Level 4)
'hsl(240 100% 50% / 0.1)', // space separated with opacity
'hsla(240, 100%, 50%)', // hsla() alias
'hsla(240, 100%, 50%, 0.1)', // hsla() with opacity
'HSL(240Deg, 100%, 50%)', // case insensitive
]
The snippets above were taken from my library simpler-color
.