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 collections import defaultdict
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from typing import Iterator, Iterable
|
from typing import Iterator, Iterable, Optional
|
||||||
|
|
||||||
from rich import print
|
from rich import print
|
||||||
from rich.cells import cell_len
|
from rich.cells import cell_len
|
||||||
@@ -204,10 +204,6 @@ def parse_declarations(css: str, path: str) -> Styles:
|
|||||||
return styles_builder.styles
|
return styles_builder.styles
|
||||||
|
|
||||||
|
|
||||||
def _is_whitespace(token: Token) -> bool:
|
|
||||||
return token.name == "whitespace"
|
|
||||||
|
|
||||||
|
|
||||||
def _unresolved(
|
def _unresolved(
|
||||||
variable_name: str, location: tuple[int, int]
|
variable_name: str, location: tuple[int, int]
|
||||||
) -> UnresolvedVariableError:
|
) -> 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"
|
variable_name = token.value[1:-1] # Trim the $ and the :, i.e. "$x:" -> "x"
|
||||||
yield token
|
yield token
|
||||||
|
|
||||||
# Store the tokens for any variable definitions, and substitute
|
|
||||||
# any variable references we encounter with them.
|
|
||||||
leading_whitespace = True
|
|
||||||
while True:
|
while True:
|
||||||
token = next(tokens, None)
|
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:
|
if not token:
|
||||||
break
|
break
|
||||||
elif leading_whitespace and token.name == "whitespace":
|
elif token.name == "whitespace":
|
||||||
|
variables[variable_name].append(token)
|
||||||
yield token
|
yield token
|
||||||
leading_whitespace = False
|
|
||||||
elif token.name == "variable_value_end":
|
elif token.name == "variable_value_end":
|
||||||
yield token
|
yield token
|
||||||
break
|
break
|
||||||
@@ -263,8 +264,8 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
|
|||||||
variable_tokens.extend(reference_tokens)
|
variable_tokens.extend(reference_tokens)
|
||||||
ref_location = token.location
|
ref_location = token.location
|
||||||
ref_length = cell_len(token.value)
|
ref_length = cell_len(token.value)
|
||||||
for token in reference_tokens:
|
for _token in reference_tokens:
|
||||||
yield token.with_reference(
|
yield _token.with_reference(
|
||||||
ReferencedBy(
|
ReferencedBy(
|
||||||
name=ref_name,
|
name=ref_name,
|
||||||
location=ref_location,
|
location=ref_location,
|
||||||
@@ -278,6 +279,7 @@ def substitute_references(tokens: Iterator[Token]) -> Iterable[Token]:
|
|||||||
else:
|
else:
|
||||||
variables[variable_name].append(token)
|
variables[variable_name].append(token)
|
||||||
yield token
|
yield token
|
||||||
|
token = next(tokens, None)
|
||||||
elif token.name == "variable_ref":
|
elif token.name == "variable_ref":
|
||||||
variable_name = token.value[1:] # Trim the $, so $x -> x
|
variable_name = token.value[1:] # Trim the $, so $x -> x
|
||||||
if variable_name in variables:
|
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]:
|
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)))
|
tokens = iter(substitute_references(tokenize(css, path)))
|
||||||
while True:
|
while True:
|
||||||
token = next(tokens, None)
|
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)
|
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:
|
class TestParseLayout:
|
||||||
def test_valid_layout_name(self):
|
def test_valid_layout_name(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user