mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
[css][bugfix] CSS colors can now have digits at the end of their names
This commit is contained in:
@@ -461,10 +461,25 @@ class StylesBuilder:
|
|||||||
def process_color(self, name: str, tokens: list[Token]) -> None:
|
def process_color(self, name: str, tokens: list[Token]) -> None:
|
||||||
"""Processes a simple color declaration."""
|
"""Processes a simple color declaration."""
|
||||||
name = name.replace("-", "_")
|
name = name.replace("-", "_")
|
||||||
for token in tokens:
|
token_indexes_to_skip = []
|
||||||
|
for i, token in enumerate(tokens):
|
||||||
|
if i in token_indexes_to_skip:
|
||||||
|
continue
|
||||||
if token.name in ("color", "token"):
|
if token.name in ("color", "token"):
|
||||||
|
value = token.value
|
||||||
|
# Color names can include digits (e.g. "turquoise4"): if the next token is a number
|
||||||
|
# we should consider it part of the color name:
|
||||||
|
next_token = tokens[i + 1] if len(tokens) > (i + 1) else None
|
||||||
|
if (
|
||||||
|
next_token
|
||||||
|
and next_token.name == "number"
|
||||||
|
and next_token.location[1] == token.location[1] + len(value)
|
||||||
|
):
|
||||||
|
value = value + next_token.value
|
||||||
|
# skip next token, as we included it in this one's value:
|
||||||
|
token_indexes_to_skip.append(i + 1)
|
||||||
try:
|
try:
|
||||||
self.styles._rules[name] = Color.parse(token.value)
|
self.styles._rules[name] = Color.parse(value)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self.error(
|
self.error(
|
||||||
name, token, f"failed to parse color {token.value!r}; {error}"
|
name, token, f"failed to parse color {token.value!r}; {error}"
|
||||||
|
|||||||
49
tests/css/test_stylesheet.py
Normal file
49
tests/css/test_stylesheet.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
from contextlib import nullcontext as does_not_raise
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from textual.color import Color
|
||||||
|
from textual.css.stylesheet import Stylesheet, StylesheetParseError
|
||||||
|
from textual.css.tokenizer import TokenizeError
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"css_value,expectation,expected_color",
|
||||||
|
[
|
||||||
|
# Valid values:
|
||||||
|
["red", does_not_raise(), Color(128, 0, 0)],
|
||||||
|
["dark_cyan", does_not_raise(), Color(0, 175, 135)],
|
||||||
|
["medium_turquoise", does_not_raise(), Color(95, 215, 215)],
|
||||||
|
["turquoise4", does_not_raise(), Color(0, 135, 135)],
|
||||||
|
["#ffcc00", does_not_raise(), Color(255, 204, 0)],
|
||||||
|
["#ffcc0033", does_not_raise(), Color(255, 204, 0, 0.2)],
|
||||||
|
["rgb(200,90,30)", does_not_raise(), Color(200, 90, 30)],
|
||||||
|
["rgba(200,90,30,0.3)", does_not_raise(), Color(200, 90, 30, 0.3)],
|
||||||
|
# Some invalid ones:
|
||||||
|
["coffee", pytest.raises(StylesheetParseError), None], # invalid color name
|
||||||
|
["turquoise10", pytest.raises(StylesheetParseError), None],
|
||||||
|
["turquoise 4", pytest.raises(StylesheetParseError), None], # space in it
|
||||||
|
["1", pytest.raises(StylesheetParseError), None], # invalid value
|
||||||
|
["()", pytest.raises(TokenizeError), None], # invalid tokens
|
||||||
|
# TODO: implement hex colors with 3 chars? @link https://devdocs.io/css/color_value
|
||||||
|
["#09f", pytest.raises(TokenizeError), None],
|
||||||
|
# TODO: allow spaces in rgb/rgba expressions?
|
||||||
|
["rgb(200, 90, 30)", pytest.raises(TokenizeError), None],
|
||||||
|
["rgba(200,90,30, 0.4)", pytest.raises(TokenizeError), None],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_color_property_parsing(css_value, expectation, expected_color):
|
||||||
|
stylesheet = Stylesheet()
|
||||||
|
css = """
|
||||||
|
* {
|
||||||
|
background: ${COLOR};
|
||||||
|
}
|
||||||
|
""".replace(
|
||||||
|
"${COLOR}", css_value
|
||||||
|
)
|
||||||
|
|
||||||
|
with expectation:
|
||||||
|
stylesheet.parse(css)
|
||||||
|
|
||||||
|
if expected_color:
|
||||||
|
css_rule = stylesheet.rules[0]
|
||||||
|
assert css_rule.styles.background == expected_color
|
||||||
Reference in New Issue
Block a user