-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
feat(Color) Regex and color code cleanup and new color format support #8916
Changes from 6 commits
c26f998
9792c44
8db4286
048eb28
453248f
a962ce1
b3bca21
3eb2bf7
b445f9c
f17c216
979bfb3
29a5598
5a5c134
4d15b1c
89ccb5f
f3eadd8
ed671f0
77d2dbb
d4e98a5
649ba3c
02f0c5a
2406fa3
e3bfa4c
b648cb4
c78c568
43a2d1c
210a24a
fd75870
4b3693f
ed121bc
d90d07a
713a425
362879f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -279,19 +279,17 @@ export class Color { | |
* @return {TRGBAColorSource | undefined} source | ||
*/ | ||
static sourceFromRgb(color: string): TRGBAColorSource | undefined { | ||
const match = color.match(reRGBa); | ||
const match = color.match(reRGBa()); | ||
if (match) { | ||
const r = | ||
(parseInt(match[1], 10) / (/%$/.test(match[1]) ? 100 : 1)) * | ||
(/%$/.test(match[1]) ? 255 : 1), | ||
g = | ||
(parseInt(match[2], 10) / (/%$/.test(match[2]) ? 100 : 1)) * | ||
(/%$/.test(match[2]) ? 255 : 1), | ||
b = | ||
(parseInt(match[3], 10) / (/%$/.test(match[3]) ? 100 : 1)) * | ||
(/%$/.test(match[3]) ? 255 : 1); | ||
|
||
return [r, g, b, match[4] ? parseFloat(match[4]) : 1]; | ||
const [r, g, b] = match.slice(1, 4).map((value) => { | ||
const parsedValue = parseInt(value, 10); | ||
return value.endsWith('%') | ||
? Math.round(parsedValue * 2.55) | ||
: parsedValue; | ||
}); | ||
const alpha = match[4] ?? '1'; | ||
const a = parseFloat(alpha) / (alpha.endsWith('%') ? 100 : 1); | ||
return [r, g, b, a]; | ||
} | ||
} | ||
|
||
|
@@ -326,14 +324,14 @@ export class Color { | |
* @see http://http://www.w3.org/TR/css3-color/#hsl-color | ||
*/ | ||
static sourceFromHsl(color: string): TRGBAColorSource | undefined { | ||
const match = color.match(reHSLa); | ||
const match = color.match(reHSLa()); | ||
if (!match) { | ||
return; | ||
} | ||
|
||
const h = (((parseFloat(match[1]) % 360) + 360) % 360) / 360, | ||
s = parseFloat(match[2]) / (/%$/.test(match[2]) ? 100 : 1), | ||
l = parseFloat(match[3]) / (/%$/.test(match[3]) ? 100 : 1); | ||
s = parseFloat(match[2]) / 100, | ||
l = parseFloat(match[3]) / 100; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s and l are always percentages only. |
||
let r: number, g: number, b: number; | ||
|
||
if (s === 0) { | ||
|
@@ -374,31 +372,19 @@ export class Color { | |
* @return {TRGBAColorSource | undefined} source | ||
*/ | ||
static sourceFromHex(color: string): TRGBAColorSource | undefined { | ||
if (color.match(reHex)) { | ||
if (color.match(reHex())) { | ||
const value = color.slice(color.indexOf('#') + 1), | ||
isShortNotation = value.length === 3 || value.length === 4, | ||
isRGBa = value.length === 8 || value.length === 4, | ||
r = isShortNotation | ||
? value.charAt(0) + value.charAt(0) | ||
: value.substring(0, 2), | ||
g = isShortNotation | ||
? value.charAt(1) + value.charAt(1) | ||
: value.substring(2, 4), | ||
b = isShortNotation | ||
? value.charAt(2) + value.charAt(2) | ||
: value.substring(4, 6), | ||
a = isRGBa | ||
? isShortNotation | ||
? value.charAt(3) + value.charAt(3) | ||
: value.substring(6, 8) | ||
: 'FF'; | ||
|
||
return [ | ||
parseInt(r, 16), | ||
parseInt(g, 16), | ||
parseInt(b, 16), | ||
parseFloat((parseInt(a, 16) / 255).toFixed(2)), | ||
]; | ||
isShortNotation = value.length === 3 || value.length === 4; | ||
let expandedValue: string[]; | ||
if (isShortNotation) { | ||
expandedValue = value.split('').map((hex) => hex + hex); | ||
asturur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} else { | ||
expandedValue = value.match(/.{2}/g)!; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am guessing this split everything to couples |
||
} | ||
const [r, g, b, a = 255] = expandedValue.map((hexCouple) => | ||
parseInt(hexCouple, 16) | ||
); | ||
return [r, g, b, a / 255]; | ||
ShaMan123 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is great! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in my head there was the fun experiment that 150 colors can be represented by 2 digits in base64 encoding. And so that should be possible to reduce this map to have custom hashed keys to which color names resolve univocally. But i m not sure is easy or hard, but for sure would be fun. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So desu, ne?! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,107 @@ | ||
/** | ||
* Regex matching color in RGB or RGBA formats (ex: rgb(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) | ||
asturur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* @static | ||
* @field | ||
* @memberOf Color | ||
* Also matching rgba(r g b / a) as per new specs | ||
* https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb | ||
* Formal syntax at the time of writing: | ||
* <rgb()> = | ||
* rgb( [ <percentage> | none ]{3} [ / [ <alpha-value> | none ] ]? ) | | ||
* rgb( [ <number> | none ]{3} [ / [ <alpha-value> | none ] ]? ) | ||
* <alpha-value> = <number> | <percentage> | ||
* | ||
* For learners this is how you can read this regex | ||
* Regular expression for matching an rgba or rgb CSS color value | ||
* | ||
* /^ # Beginning of the string | ||
* rgba? # "rgb" or "rgba" | ||
* \(\s* # Opening parenthesis and optional whitespace | ||
* (\d{1,3} # One to three digits R channel | ||
* (?:\.\d+)? # Optional decimal with one or more digits | ||
* ) # End of capturing group for the first color component | ||
* %? # Optional percent sign after the first color component | ||
* \s* # Optional whitespace | ||
* [\s|,] # Separator between color components can be a space or comma | ||
* \s* # Optional whitespace | ||
* (\d{1,3} # One to three digits G channel | ||
* (?:\.\d+)? # Optional decimal with one or more digits | ||
* ) # End of capturing group for the second color component | ||
* %? # Optional percent sign after the second color component | ||
* \s* # Optional whitespace | ||
* [\s|,] # Separator between color components can be a space or comma | ||
* \s* # Optional whitespace | ||
* (\d{1,3} # One to three digits B channel | ||
* (?:\.\d+)? # Optional decimal with one or more digits | ||
* ) # End of capturing group for the third color component | ||
* %? # Optional percent sign after the third color component | ||
* \s* # Optional whitespace | ||
* (?: # Beginning of non-capturing group for alpha value | ||
* \s* # Optional whitespace | ||
* [,/] # Comma or slash separator for alpha value | ||
* \s* # Optional whitespace | ||
* (\d{0,3} # Zero to three digits | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. start of capturing group |
||
* (?:\.\d+)? # Optional decimal with one or more digits | ||
* ) # End of capturing group for alpha value | ||
* %? # Optional percent sign after alpha value | ||
* \s* # Optional whitespace | ||
* )? # End of non-capturing group for alpha value (optional) | ||
* \) # Closing parenthesis | ||
* $ # End of the string | ||
* | ||
* The alpha channel can be in the format 0.4 .7 or 1 or 73% | ||
* | ||
* WARNING this regex doesn't fail on off spec colors. it matches everything that could be a color. | ||
* So the spec does not allow for rgba(30 , 45% 35, 49%) but this will work anyway for us | ||
asturur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
// eslint-disable-next-line max-len | ||
export const reRGBa = | ||
/^rgba?\(\s*(\d{1,3}(?:\.\d+)?%?)\s*,\s*(\d{1,3}(?:\.\d+)?%?)\s*,\s*(\d{1,3}(?:\.\d+)?%?)\s*(?:\s*,\s*((?:\d*\.?\d+)?)\s*)?\)$/i; | ||
export const reRGBa = () => | ||
/^rgba?\(\s*(\d{1,3}(?:\.\d+)?%?)\s*[\s|,]\s*(\d{1,3}(?:\.\d+)?%?)\s*[\s|,]\s*(\d{1,3}(?:\.\d+)?%?)\s*(?:\s*[,/]\s*(\d{0,3}(?:\.\d+)?%?)\s*)?\)$/i; | ||
|
||
/** | ||
* Regex matching color in HSL or HSLA formats (ex: hsl(200, 80%, 10%), hsla(300, 50%, 80%, 0.5), hsla( 300 , 50% , 80% , 0.5 )) | ||
* @static | ||
* @field | ||
* @memberOf Color | ||
* Regex matching color in HSL or HSLA formats (ex: hsl(0, 0, 0), rgba(255, 100, 10, 0.5), rgba( 255 , 100 , 10 , 0.5 ), rgb(1,1,1), rgba(100%, 60%, 10%, 0.5)) | ||
* Also matching rgba(r g b / a) as per new specs | ||
Comment on lines
+58
to
+59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rgb left overs => hsl |
||
* https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl | ||
* Formal syntax at the time of writing: | ||
* <hsl()> = | ||
* hsl( [ <hue> | none ] [ <percentage> | none ] [ <percentage> | none ] [ / [ <alpha-value> | none ] ]? ) | ||
* | ||
* <hue> = | ||
* <number> | | ||
* <angle> | ||
* | ||
* <alpha-value> = | ||
* <number> | | ||
* <percentage> | ||
* | ||
* For learners this is how you can read this regex | ||
* Regular expression for matching an hsla or hsl CSS color value | ||
* | ||
* /^hsla?\( // Matches the beginning of the string and the opening parenthesis of "hsl" or "hsla" | ||
* \s* // Matches any whitespace characters (space, tab, etc.) zero or more times | ||
* (\d{1,3}) // Hue: Matches one to three digits and captures it in a group | ||
* \s* // Matches any whitespace characters zero or more times | ||
* [\s|,] // Matches a space, tab or comma | ||
* \s* // Matches any whitespace characters zero or more times | ||
* (\d{1,3}%) // Saturation: Matches one to three digits followed by a percentage sign and captures it in a group | ||
* \s* // Matches any whitespace characters zero or more times | ||
* [\s|,] // Matches a space, tab or comma | ||
* \s* // Matches any whitespace characters zero or more times | ||
* (\d{1,3}%) // Lightness: Matches one to three digits followed by a percentage sign and captures it in a group | ||
* \s* // Matches any whitespace characters zero or more times | ||
* (?: // Alpha: Begins a non-capturing group for the alpha value | ||
* \s* // Matches any whitespace characters zero or more times | ||
* [,/] // Matches a comma or forward slash | ||
* \s* // Matches any whitespace characters zero or more times | ||
* (\d*(?:\.\d+)?%?) // Matches zero or more digits, optionally followed by a decimal point and one or more digits, followed by an optional percentage sign and captures it in a group | ||
* \s* // Matches any whitespace characters zero or more times | ||
* )? // Makes the alpha value group optional | ||
* \) // Matches the closing parenthesis | ||
* $/i // Matches the end of the string and sets the regular expression to case-insensitive mode | ||
* | ||
* WARNING this regex doesn't fail on off spec colors. it matches everything that could be a color. | ||
asturur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* So the spec does not allow for hsl(30 , 45% 35, 49%) but this will work anyway for us | ||
asturur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
export const reHSLa = | ||
/^hsla?\(\s*(\d{1,3})\s*,\s*(\d{1,3}%)\s*,\s*(\d{1,3}%)\s*(?:\s*,\s*(\d+(?:\.\d+)?)\s*)?\)$/i; | ||
export const reHSLa = () => | ||
/^hsla?\(\s*(\d{1,3})\s*[\s|,]\s*(\d{1,3}%)\s*[\s|,]\s*(\d{1,3}%)\s*(?:\s*[,/]\s*(\d*(?:\.\d+)?%?)\s*)?\)$/i; | ||
|
||
/** | ||
* Regex matching color in HEX format (ex: #FF5544CC, #FF5555, 010155, aff) | ||
* @static | ||
* @field | ||
* @memberOf Color | ||
*/ | ||
export const reHex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i; | ||
export const reHex = () => /^#?(([0-9a-f]){3,4}|([0-9a-f]{2}){3,4})$/i; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. skipped commenting intentionally? or because it is simpler? or just fed up? not a must. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i didn't do that i was tired. I should follow up |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i wonder... this seems correct and i noticed was off.
I m trying to think of some non obvious value that could break.
But i prefer to discover in this case and in case fix later because this seems wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh I see.
What if the value is < -360. Now it fails, before it was safe.
Please revert this.
I didn't think of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that is fine, we discovered.