styled-components / polished

A lightweight toolset for writing styles in JavaScript ✨
https://polished.js.org/
MIT License
7.6k stars 209 forks source link

parseToRgb / parseToHsl float precision expected by the regex #634

Open johannpinson opened 1 year ago

johannpinson commented 1 year ago

The bug looks similar to the https://github.com/styled-components/polished/issues/610 with the alpha which fail from a 3-digit decimal. But this bug is about the hue/saturation/lightness values.

https://github.com/styled-components/polished/blob/a6c55c8b3feb0010c63c55eb5b18cc3090050c15/src/color/parseToRgb.js#L14

Because the parseToHsl can return a "long" float decimal, using it as a literal string can generate error. The code below is in a bug reproduction logic, because the lib allow to use the hsl as an object (HslColor | HslColor types).

Additional context

But my goal is to get/generate hsl props programmatically from a hex/rgb value without doing extra work like Math.round() / parseFloat() / .toFixed() since the polished lib looks to already do it for other functions/methods.

Exemple of expected result from using the parseToHsl result:

image

Mixin/Helper/Shorthand Usage

const {parseToRgb, parseToHsl, hsl} = require('polished')

const color = 'rgba(65 0 4 / 100%)'
const colorInHsl = parseToHsl(color)

const colorInHslStrInt = `hsl(${Math.round(colorInHsl.hue)}deg ${Math.round(colorInHsl.saturation * 100)}% ${Math.round(colorInHsl.lightness * 100)}%)`
const colorInHslStrToFixed = `hsl(${(colorInHsl.hue).toFixed(2)}deg ${(colorInHsl.saturation * 100).toFixed(1)}% ${(colorInHsl.lightness * 100).toFixed(1)}%)`
const colorInHslStrRawFloat = `hsl(${colorInHsl.hue}deg ${colorInHsl.saturation * 100}% ${colorInHsl.lightness * 100}%)`

console.log(colorInHsl) // log Object {hue: 356.3076923076923, saturation: 1, lightness: 0.12745098039215685, alpha: 1}
console.log(hsl(colorInHsl)) // log "#410004" 

console.log(colorInHslStrInt) // log "hsl(356deg 100% 13%)"
console.log(colorInHslStrToFixed) // log "hsl(356.31deg 100.0% 12.7%)"
console.log(colorInHslStrRawFloat) // log "hsl(356.3076923076923deg 100% 12.745098039215685%)"

console.log(parseToRgb(colorInHslStrInt)) // 'from int' => works
console.log(parseToRgb(colorInHslStrToFixed)) // 'from fixed float' => works because it respects the regex
console.log(parseToRgb(colorInHslStrFloat)) // 'from raw float' => error

What You Are Seeing

// CJS
PolishedError: An error occurred. See https://github.com/styled-components/polished/blob/main/src/internalHelpers/errors.md#5 for more information.

// ESM - Node
NonErrorEmittedError: (Emitted value instead of an instance of Error) Error: Couldn't parse the color string. Please provide the color as a string in hex, rgb, rgba, hsl or hsla notation.

What You Expected To See

Object {red: 66, green: 0, blue: 4}

or possible parseToHsl return:

Object {hue: 356.31, saturation: 1, lightness: 0.127, alpha: 1}
// lightness property has 3 decimal to allow the conversion into `12.7%`

Reproduction

Runkit example