Skip to content

fix: add checks for preventing HSL colors from entering React state #9893

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

Merged
merged 5 commits into from
Sep 27, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore: add extra color helpers
  • Loading branch information
Parkreiner committed Sep 27, 2023
commit f34c7b99cfed1f3039ffb39e33f433c7509b4b12
53 changes: 53 additions & 0 deletions site/src/utils/colors.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,56 @@
/**
* Does not support shorthand hex string (e.g., #fff)
*/
const hexMatcher = /^#[0-9A-Fa-f]{6}$/;

export function isHexColor(input: string): boolean {
return hexMatcher.test(input);
}

/**
* Regex written and tested via Regex101. This doesn't catch every invalid HSL
* string and still requires some other checks, but it can do a lot by itself.
*
* Setup:
* - Supports capture groups for all three numeric values. Regex tries to fail
* the input as quickly as possible.
* - Regex is all-or-nothing – there is some tolerance for extra spaces, but
* this regex will fail any string that is missing any part of the format.
* - String is case-insensitive
* - String must start with HSL and have both parentheses
* - All three numeric values must be comma-delimited
* - Hue can be 1-3 digits. Rightmost digit (if it exists) can only be 1-3;
* other digits have no constraints. The degree unit ("deg") is optional
* - Both saturation and luminosity can be 1-3 digits. Rightmost digit (if it
* exists) can only ever be 1. Other digits have no constraints.
*/
const hslMatcher =
/^hsl\(((?:[1-3]?\d)?\d)(?:deg)?, *((?:1?\d)?\d)%, *((?:1?\d)?\d)%\)$/i;

export function isHslColor(input: string): boolean {
const [, hue, sat, lum] = hslMatcher.exec(input) ?? [];
if (hue === undefined || sat === undefined || lum === undefined) {
return false;
}

const hueN = Number(hue);
if (!Number.isInteger(hueN) || hueN < 0 || hueN >= 360) {
return false;
}

const satN = Number(sat);
if (!Number.isInteger(satN) || satN < 0 || satN > 100) {
return false;
}

const lumN = Number(sat);
if (!Number.isInteger(lumN) || lumN < 0 || lumN > 100) {
return false;
}

return true;
}

// Used to convert our theme colors to Hex since monaco theme only support hex colors
// From https://www.jameslmilner.com/posts/converting-rgb-hex-hsl-colors/
export function hslToHex(hsl: string): string {
Expand Down