diff --git a/src/textual/color.py b/src/textual/color.py index 0257f7830..af3802896 100644 --- a/src/textual/color.py +++ b/src/textual/color.py @@ -127,9 +127,7 @@ class Color(NamedTuple): Returns: Color: A new color. """ - print("A") r, g, b = hls_to_rgb(h, l, s) - print("B") return cls(int(r * 255 + 0.5), int(g * 255 + 0.5), int(b * 255 + 0.5)) def __rich__(self) -> Text: @@ -342,17 +340,17 @@ class Color(NamedTuple): clamp(float_a, 0.0, 1.0), ) elif hsl is not None: - h, s, l = [value.strip() for value in hsl.split(",")] - h = clamp(int(h), 0, 360) / 360 + h, s, l = hsl.split(",") + h = clamp(float(h), 0, 360) / 360 s = percentage_string_to_float(s) l = percentage_string_to_float(l) color = Color.from_hls(h, l, s) elif hsla is not None: - h, s, l, a = [value.strip() for value in hsl.split(",")] - h = clamp(h, 0, 360) + h, s, l, a = hsla.split(",") + h = clamp(float(h), 0, 360) / 360 s = percentage_string_to_float(s) l = percentage_string_to_float(l) - a = clamp(a, 0.0, 1.0) + a = clamp(float(a), 0.0, 1.0) color = Color.from_hls(h, l, s).with_alpha(a) else: raise AssertionError("Can't get here if RE_COLOR matches") diff --git a/src/textual/css/tokenize.py b/src/textual/css/tokenize.py index 879a66e80..7cee24ce2 100644 --- a/src/textual/css/tokenize.py +++ b/src/textual/css/tokenize.py @@ -8,7 +8,7 @@ from textual.css.tokenizer import Expect, Tokenizer, Token PERCENT = r"-?\d+\.?\d*%" DECIMAL = r"-?\d+\.?\d*" -COMMA = r",\s*" +COMMA = r"\s*,\s*" OPEN_BRACE = r"\(\s*" CLOSE_BRACE = r"\s*\)" @@ -20,7 +20,7 @@ COMMENT_START = r"\/\*" SCALAR = rf"{DECIMAL}(?:fr|%|w|h|vw|vh)" DURATION = r"\d+\.?\d*(?:ms|s)" NUMBER = r"\-?\d+\.?\d*" -COLOR = f"{HEX_COLOR}|{RGB_COLOR}|{HSL_COLOR}" +COLOR = rf"{HEX_COLOR}|{RGB_COLOR}|{HSL_COLOR}" KEY_VALUE = r"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\-\/]+" TOKEN = "[a-zA-Z][a-zA-Z0-9_-]*" STRING = r"\".*?\"" diff --git a/tests/css/test_parse.py b/tests/css/test_parse.py index dd1e73809..b9b03f3bf 100644 --- a/tests/css/test_parse.py +++ b/tests/css/test_parse.py @@ -904,6 +904,32 @@ class TestParseText: assert styles.background == Color.parse("red") +class TestParseColor: + """More in-depth tests around parsing of CSS colors""" + + @pytest.mark.parametrize("value,result", [ + ("rgb(1,255,50)", Color(1, 255, 50)), + ("rgb( 1, 255,50 )", Color(1, 255, 50)), + ("rgba( 1, 255,50,0.3 )", Color(1, 255, 50, 0.3)), + ("rgba( 1, 255,50, 1.3 )", Color(1, 255, 50, 1.0)), + ("hsl( 180, 50%, 50% )", Color(64, 191, 191)), + ("hsl(180,50%,50%)", Color(64, 191, 191)), + ("hsla(180,50%,50%,0.25)", Color(64, 191, 191, 0.25)), + ("hsla( 180, 50% ,50%,0.25 )", Color(64, 191, 191, 0.25)), + ("hsla( 180, 50% , 50% , 1.5 )", Color(64, 191, 191)), + ]) + def test_rgb_and_hsl(self, value, result): + css = f""".box {{ + color: {value}; + }} + """ + stylesheet = Stylesheet() + stylesheet.add_source(css) + + styles = stylesheet.rules[0].styles + assert styles.color == result + + class TestParseOffset: @pytest.mark.parametrize( "offset_x, parsed_x, offset_y, parsed_y",