mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Invalid pseudo selectors (#2445)
* token error * error on bad pseudo selectors
This commit is contained in:
@@ -61,6 +61,14 @@ VALID_STYLE_FLAGS: Final = {
|
||||
"underline",
|
||||
"uu",
|
||||
}
|
||||
VALID_PSEUDO_CLASSES: Final = {
|
||||
"blur",
|
||||
"disabled",
|
||||
"enabled",
|
||||
"focus-within",
|
||||
"focus",
|
||||
"hover",
|
||||
}
|
||||
|
||||
|
||||
NULL_SPACING: Final = Spacing.all(0)
|
||||
|
||||
@@ -12,7 +12,9 @@ from rich.panel import Panel
|
||||
from rich.syntax import Syntax
|
||||
from rich.text import Text
|
||||
|
||||
from ..suggestions import get_suggestion
|
||||
from ._error_tools import friendly_list
|
||||
from .constants import VALID_PSEUDO_CLASSES
|
||||
|
||||
|
||||
class TokenError(Exception):
|
||||
@@ -56,7 +58,7 @@ class TokenError(Exception):
|
||||
line_numbers=True,
|
||||
indent_guides=True,
|
||||
line_range=(max(0, line_no - 2), line_no + 2),
|
||||
highlight_lines={line_no},
|
||||
highlight_lines={line_no + 1},
|
||||
)
|
||||
syntax.stylize_range("reverse bold", self.start, self.end)
|
||||
return Panel(syntax, border_style="red")
|
||||
@@ -227,6 +229,29 @@ class Tokenizer:
|
||||
(line_no, col_no),
|
||||
referenced_by=None,
|
||||
)
|
||||
|
||||
if (
|
||||
token.name == "pseudo_class"
|
||||
and token.value.strip(":") not in VALID_PSEUDO_CLASSES
|
||||
):
|
||||
pseudo_class = token.value.strip(":")
|
||||
suggestion = get_suggestion(pseudo_class, list(VALID_PSEUDO_CLASSES))
|
||||
all_valid = f"must be one of {friendly_list(VALID_PSEUDO_CLASSES)}"
|
||||
if suggestion:
|
||||
raise TokenError(
|
||||
self.path,
|
||||
self.code,
|
||||
(line_no, col_no),
|
||||
f"unknown pseudo-class {pseudo_class!r}; did you mean {suggestion!r}?; {all_valid}",
|
||||
)
|
||||
else:
|
||||
raise TokenError(
|
||||
self.path,
|
||||
self.code,
|
||||
(line_no, col_no),
|
||||
f"unknown pseudo-class {pseudo_class!r}; {all_valid}",
|
||||
)
|
||||
|
||||
col_no += len(value)
|
||||
if col_no >= len(line):
|
||||
line_no += 1
|
||||
|
||||
@@ -140,52 +140,52 @@ A1
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
A:foo {}
|
||||
A:foo:bar {}
|
||||
A:focus {}
|
||||
A:focus:hover {}
|
||||
A
|
||||
:foo {}
|
||||
:focus {}
|
||||
A
|
||||
:foo:bar {}
|
||||
:focus:hover {}
|
||||
A
|
||||
:foo
|
||||
:bar {}
|
||||
A:foo-bar {}
|
||||
:focus
|
||||
:hover {}
|
||||
A:enabled {}
|
||||
A
|
||||
:foo-bar {}
|
||||
:enabled {}
|
||||
|
||||
A :foo {}
|
||||
A :foo :bar {}
|
||||
A :foo-bar {}
|
||||
A :focus {}
|
||||
A :focus :hover {}
|
||||
A :enabled {}
|
||||
|
||||
.A:foo {}
|
||||
.A:foo:bar {}
|
||||
.A:focus {}
|
||||
.A:focus:hover {}
|
||||
.A
|
||||
:foo {}
|
||||
:focus {}
|
||||
.A
|
||||
:foo:bar {}
|
||||
:focus:hover {}
|
||||
.A
|
||||
:foo
|
||||
:bar {}
|
||||
.A:foo-bar {}
|
||||
:focus
|
||||
:hover {}
|
||||
.A:enabled {}
|
||||
.A
|
||||
:foo-bar {}
|
||||
:enabled {}
|
||||
|
||||
#A:foo {}
|
||||
#A:foo:bar {}
|
||||
#A:focus {}
|
||||
#A:focus:hover {}
|
||||
#A
|
||||
:foo {}
|
||||
:focus {}
|
||||
#A
|
||||
:foo:bar {}
|
||||
:focus:hover {}
|
||||
#A
|
||||
:foo
|
||||
:bar {}
|
||||
#A:foo-bar {}
|
||||
:focus
|
||||
:hover {}
|
||||
#A:enabled {}
|
||||
#A
|
||||
:foo-bar {}
|
||||
:enabled {}
|
||||
|
||||
A1.A1.A1:foo {}
|
||||
A1.A1#A1:foo {}
|
||||
A1:foo.A1:foo#A1:foo {}
|
||||
A1.A1.A1:focus {}
|
||||
A1.A1#A1:focus {}
|
||||
A1:focus.A1:focus#A1:focus {}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
@@ -1226,3 +1226,21 @@ class TestTypeNames:
|
||||
stylesheet.add_source(f"StartType {separator} 1TestType {{}}")
|
||||
with pytest.raises(TokenError):
|
||||
stylesheet.parse()
|
||||
|
||||
|
||||
def test_parse_bad_psuedo_selector():
|
||||
"""Check unknown selector raises a token error."""
|
||||
|
||||
bad_selector = """\
|
||||
Widget:foo{
|
||||
border: red;
|
||||
}
|
||||
"""
|
||||
|
||||
stylesheet = Stylesheet()
|
||||
stylesheet.add_source(bad_selector, "foo")
|
||||
|
||||
with pytest.raises(TokenError) as error:
|
||||
stylesheet.parse()
|
||||
|
||||
assert error.value.start == (0, 6)
|
||||
|
||||
Reference in New Issue
Block a user