mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Change whitespace trimming during css var sub, add more tests
This commit is contained in:
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from collections import defaultdict
|
||||
from functools import lru_cache
|
||||
from typing import Iterator, Iterable
|
||||
from typing import Iterator, Iterable, Optional
|
||||
|
||||
from rich import print
|
||||
from rich.cells import cell_len
|
||||
@@ -204,10 +204,6 @@ def parse_declarations(css: str, path: str) -> Styles:
|
||||
return styles_builder.styles
|
||||
|
||||
|
||||
def _is_whitespace(token: Token) -> bool:
|
||||
return token.name == "whitespace"
|
||||
|
||||
|
||||
def _unresolved(
|
||||
variable_name: str, location: tuple[int, int]
|
||||
) -> UnresolvedVariableError:
|
||||
@@ -241,16 +237,21 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
|
||||
variable_name = token.value[1:-1] # Trim the $ and the :, i.e. "$x:" -> "x"
|
||||
yield token
|
||||
|
||||
# Store the tokens for any variable definitions, and substitute
|
||||
# any variable references we encounter with them.
|
||||
leading_whitespace = True
|
||||
while True:
|
||||
token = next(tokens, None)
|
||||
if token.name == "whitespace":
|
||||
yield token
|
||||
else:
|
||||
break
|
||||
|
||||
# Store the tokens for any variable definitions, and substitute
|
||||
# any variable references we encounter with them.
|
||||
while True:
|
||||
if not token:
|
||||
break
|
||||
elif leading_whitespace and token.name == "whitespace":
|
||||
elif token.name == "whitespace":
|
||||
variables[variable_name].append(token)
|
||||
yield token
|
||||
leading_whitespace = False
|
||||
elif token.name == "variable_value_end":
|
||||
yield token
|
||||
break
|
||||
@@ -263,8 +264,8 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
|
||||
variable_tokens.extend(reference_tokens)
|
||||
ref_location = token.location
|
||||
ref_length = cell_len(token.value)
|
||||
for token in reference_tokens:
|
||||
yield token.with_reference(
|
||||
for _token in reference_tokens:
|
||||
yield _token.with_reference(
|
||||
ReferencedBy(
|
||||
name=ref_name,
|
||||
location=ref_location,
|
||||
@@ -278,6 +279,7 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
|
||||
else:
|
||||
variables[variable_name].append(token)
|
||||
yield token
|
||||
token = next(tokens, None)
|
||||
elif token.name == "variable_ref":
|
||||
variable_name = token.value[1:] # Trim the $, so $x -> x
|
||||
if variable_name in variables:
|
||||
@@ -299,6 +301,13 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
|
||||
|
||||
|
||||
def parse(css: str, path: str) -> Iterable[RuleSet]:
|
||||
"""Parse CSS by tokenizing it, performing variable substitution,
|
||||
and generating rule sets from it.
|
||||
|
||||
Args:
|
||||
css (str): The input CSS
|
||||
path (str): Path to the CSS
|
||||
"""
|
||||
tokens = iter(substitute_references(tokenize(css, path)))
|
||||
while True:
|
||||
token = next(tokens, None)
|
||||
|
||||
@@ -148,6 +148,30 @@ class TestVariableReferenceSubstitution:
|
||||
Token(name='declaration_set_end', value='}', path='', code=css, location=(1, 24), referenced_by=None)
|
||||
]
|
||||
|
||||
def test_variable_definition_eof(self):
|
||||
css = "$x: 1"
|
||||
assert list(substitute_references(tokenize(css, ""))) == [
|
||||
Token(name='variable_name', value='$x:', path='', code=css, location=(0, 0), referenced_by=None),
|
||||
Token(name='whitespace', value=' ', path='', code=css, location=(0, 3), referenced_by=None),
|
||||
Token(name='number', value='1', path='', code=css, location=(0, 4), referenced_by=None)
|
||||
]
|
||||
|
||||
def test_variable_reference_whitespace_trimming(self):
|
||||
css = "$x: 123;.thing{border: $x}"
|
||||
assert list(substitute_references(tokenize(css, ""))) == [
|
||||
Token(name='variable_name', value='$x:', path='', code=css, location=(0, 0), referenced_by=None),
|
||||
Token(name='whitespace', value=' ', path='', code=css, location=(0, 3), referenced_by=None),
|
||||
Token(name='number', value='123', path='', code=css, location=(0, 7), referenced_by=None),
|
||||
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 10), referenced_by=None),
|
||||
Token(name='selector_start_class', value='.thing', path='', code=css, location=(0, 11), referenced_by=None),
|
||||
Token(name='declaration_set_start', value='{', path='', code=css, location=(0, 17), referenced_by=None),
|
||||
Token(name='declaration_name', value='border:', path='', code=css, location=(0, 18), referenced_by=None),
|
||||
Token(name='whitespace', value=' ', path='', code=css, location=(0, 25), referenced_by=None),
|
||||
Token(name='number', value='123', path='', code=css, location=(0, 7),
|
||||
referenced_by=ReferencedBy(name='x', location=(0, 26), length=2)),
|
||||
Token(name='declaration_set_end', value='}', path='', code=css, location=(0, 28), referenced_by=None)
|
||||
]
|
||||
|
||||
|
||||
class TestParseLayout:
|
||||
def test_valid_layout_name(self):
|
||||
|
||||
Reference in New Issue
Block a user