Invalid pseudo selectors (#2445)

* token error

* error on bad pseudo selectors
This commit is contained in:
Will McGugan
2023-05-01 16:22:35 +01:00
committed by GitHub
parent 08de9a0fca
commit 20a1612361
4 changed files with 82 additions and 31 deletions

View File

@@ -61,6 +61,14 @@ VALID_STYLE_FLAGS: Final = {
"underline", "underline",
"uu", "uu",
} }
VALID_PSEUDO_CLASSES: Final = {
"blur",
"disabled",
"enabled",
"focus-within",
"focus",
"hover",
}
NULL_SPACING: Final = Spacing.all(0) NULL_SPACING: Final = Spacing.all(0)

View File

@@ -12,7 +12,9 @@ from rich.panel import Panel
from rich.syntax import Syntax from rich.syntax import Syntax
from rich.text import Text from rich.text import Text
from ..suggestions import get_suggestion
from ._error_tools import friendly_list from ._error_tools import friendly_list
from .constants import VALID_PSEUDO_CLASSES
class TokenError(Exception): class TokenError(Exception):
@@ -56,7 +58,7 @@ class TokenError(Exception):
line_numbers=True, line_numbers=True,
indent_guides=True, indent_guides=True,
line_range=(max(0, line_no - 2), line_no + 2), 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) syntax.stylize_range("reverse bold", self.start, self.end)
return Panel(syntax, border_style="red") return Panel(syntax, border_style="red")
@@ -227,6 +229,29 @@ class Tokenizer:
(line_no, col_no), (line_no, col_no),
referenced_by=None, 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) col_no += len(value)
if col_no >= len(line): if col_no >= len(line):
line_no += 1 line_no += 1

View File

@@ -140,52 +140,52 @@ A1
/**********************************************************************/ /**********************************************************************/
A:foo {} A:focus {}
A:foo:bar {} A:focus:hover {}
A A
:foo {} :focus {}
A A
:foo:bar {} :focus:hover {}
A A
:foo :focus
:bar {} :hover {}
A:foo-bar {} A:enabled {}
A A
:foo-bar {} :enabled {}
A :foo {} A :focus {}
A :foo :bar {} A :focus :hover {}
A :foo-bar {} A :enabled {}
.A:foo {} .A:focus {}
.A:foo:bar {} .A:focus:hover {}
.A .A
:foo {} :focus {}
.A .A
:foo:bar {} :focus:hover {}
.A .A
:foo :focus
:bar {} :hover {}
.A:foo-bar {} .A:enabled {}
.A .A
:foo-bar {} :enabled {}
#A:foo {} #A:focus {}
#A:foo:bar {} #A:focus:hover {}
#A #A
:foo {} :focus {}
#A #A
:foo:bar {} :focus:hover {}
#A #A
:foo :focus
:bar {} :hover {}
#A:foo-bar {} #A:enabled {}
#A #A
:foo-bar {} :enabled {}
A1.A1.A1:foo {} A1.A1.A1:focus {}
A1.A1#A1:foo {} A1.A1#A1:focus {}
A1:foo.A1:foo#A1:foo {} A1:focus.A1:focus#A1:focus {}
/**********************************************************************/ /**********************************************************************/

View File

@@ -1226,3 +1226,21 @@ class TestTypeNames:
stylesheet.add_source(f"StartType {separator} 1TestType {{}}") stylesheet.add_source(f"StartType {separator} 1TestType {{}}")
with pytest.raises(TokenError): with pytest.raises(TokenError):
stylesheet.parse() 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)