require semi-colons

This commit is contained in:
Will McGugan
2022-04-11 15:25:21 +01:00
parent c7a93f3d0b
commit 4f63fc086f
10 changed files with 804 additions and 119 deletions

View File

@@ -34,7 +34,7 @@ The _panel_ color is typically used as a background to emphasize text on the def
The default panel color is derived from the surface color by blending it towards either white or black text (depending on mode).
Unlike background and surface, the panel color is automatically selected so that it can always be lightened or darkened by the full degree.
Unlike background and surface, the panel color is automatically selected so that it can always be lightened or darkened by the full range.
### Accent

View File

@@ -86,8 +86,8 @@ Tweet {
TweetHeader {
height:1
background: $accent
height:1;
background: $accent;
color: $text-accent
}
@@ -103,7 +103,7 @@ TweetBody {
background: $accent;
color: $text-accent;
width:20;
height: 3
height: 3;
/* border-top: hidden $accent-darken-3; */
border: tall $accent-darken-2;
/* border-left: tall $accent-darken-1; */
@@ -119,7 +119,7 @@ TweetBody {
background: $accent-lighten-1;
color: $text-accent-lighten-1;
width: 20;
height: 3
height: 3;
border: tall $accent-darken-1;
/* border-left: tall $accent-darken-3; */

View File

@@ -393,20 +393,12 @@ class App(DOMNode):
await widget.post_message(events.MouseCapture(self, self.mouse_position))
def panic(self, *renderables: RenderableType) -> None:
"""Exits the app with a traceback.
"""Exits the app after displaying a message.
Args:
*renderables (RenderableType, optional): A rich renderable, such as a Traceback to
display on exit.
*renderables (RenderableType, optional): Rich renderables to display on exit.
"""
if not renderables:
renderables = (
Traceback(
show_locals=True, width=None, locals_max_length=5, suppress=[rich]
),
)
prerendered = [
Segments(self.console.render(renderable, self.console.options))
for renderable in renderables
@@ -415,6 +407,29 @@ class App(DOMNode):
self._exit_renderables.extend(prerendered)
self.close_messages_no_wait()
def on_exception(self, error: Exception) -> None:
"""Called with an unhandled exception.
Args:
error (Exception): An exception instance.
"""
if hasattr(error, "__rich__"):
# Exception has a rich method, so we can defer to that for the rendering
self.panic(error)
else:
# Use default exception rendering
self.fatal_error()
def fatal_error(self) -> None:
"""Exits the app after an unhandled exception."""
traceback = Traceback(
show_locals=True, width=None, locals_max_length=5, suppress=[rich]
)
self._exit_renderables.append(
Segments(self.console.render(traceback, self.console.options))
)
self.close_messages_no_wait()
def _print_error_renderables(self) -> None:
for renderable in self._exit_renderables:
self.error_console.print(renderable)
@@ -430,12 +445,9 @@ class App(DOMNode):
self.stylesheet.read(self.css_file)
if self.css is not None:
self.stylesheet.parse(self.css, path=f"<{self.__class__.__name__}>")
except StylesheetParseError as error:
self.panic(error)
self._print_error_renderables()
return
except Exception as error:
self.panic()
self.on_exception(error)
self._print_error_renderables()
return
@@ -468,8 +480,8 @@ class App(DOMNode):
await self.close_all()
finally:
driver.stop_application_mode()
except:
self.panic()
except Exception as error:
self.on_exception(error)
finally:
self._running = False
if self._exit_renderables:
@@ -567,8 +579,8 @@ class App(DOMNode):
if sync_available:
console.file.write("\x1bP=2s\x1b\\")
console.file.flush()
except Exception:
self.panic()
except Exception as error:
self.on_exception(error)
def refresh_css(self, animate: bool = True) -> None:
"""Refresh CSS.
@@ -589,8 +601,8 @@ class App(DOMNode):
console = self.console
try:
console.print(renderable)
except Exception:
self.panic()
except Exception as error:
self.on_exception(error)
def measure(self, renderable: RenderableType, max_width=100_000) -> int:
"""Get the optimal width for a widget or renderable.

View File

@@ -22,6 +22,7 @@ from .model import RuleSet
from .parse import parse
from .styles import RulesMap
from .tokenize import tokenize_values, Token
from .tokenizer import TokenizeError
from .types import Specificity3, Specificity4
from ..dom import DOMNode
from .. import log
@@ -53,7 +54,7 @@ class StylesheetErrors:
theme="ansi_light",
line_numbers=True,
indent_guides=True,
line_range=(max(0, line_no - 2), line_no + 1),
line_range=(max(0, line_no - 2), line_no + 2),
highlight_lines={line_no},
)
return Panel(syntax, border_style="red")
@@ -147,8 +148,10 @@ class Stylesheet:
raise StylesheetError(f"unable to read {filename!r}; {error}")
try:
rules = list(parse(css, path, variables=self.variables))
except TokenizeError:
raise
except Exception as error:
raise StylesheetError(f"failed to parse {filename!r}; {error}")
raise StylesheetError(f"failed to parse {filename!r}; {error!r}")
else:
self.source.append((css, path))
self.rules.extend(rules)
@@ -168,6 +171,8 @@ class Stylesheet:
"""
try:
rules = list(parse(css, path, variables=self.variables))
except TokenizeError:
raise
except Exception as error:
raise StylesheetError(f"failed to parse css; {error}")
else:

View File

@@ -87,7 +87,7 @@ expect_declaration_solo = Expect(
# The value(s)/content from a rule declaration e.g. "text: red;"
# ^---^
expect_declaration_content = Expect(
declaration_end=r"\n|;",
declaration_end=r";",
whitespace=r"\s+",
comment_start=COMMENT_START,
**DECLARATION_VALUES,
@@ -97,7 +97,7 @@ expect_declaration_content = Expect(
)
expect_declaration_content_solo = Expect(
declaration_end=r"\n|;",
declaration_end=r";",
whitespace=r"\s+",
comment_start=COMMENT_START,
**DECLARATION_VALUES,

View File

@@ -3,19 +3,62 @@ from __future__ import annotations
import re
from typing import NamedTuple
from rich.console import Group, RenderableType
from rich.highlighter import ReprHighlighter
from rich.padding import Padding
from rich.panel import Panel
import rich.repr
from rich.syntax import Syntax
from rich.text import Text
class EOFError(Exception):
pass
from .._loop import loop_last
class TokenizeError(Exception):
def __init__(self, col_no: int, row_no: int, message: str) -> None:
def __init__(
self, path: str, code: str, line_no: int, col_no: int, message: str
) -> None:
self.path = path
self.code = code
self.line_no = line_no
self.col_no = col_no
self.row_no = row_no
super().__init__(message)
@classmethod
def _get_snippet(cls, code: str, line_no: int) -> Panel:
syntax = Syntax(
code,
lexer="scss",
theme="ansi_light",
line_numbers=True,
indent_guides=True,
line_range=(max(0, line_no - 2), line_no + 2),
highlight_lines={line_no},
)
return Panel(syntax, border_style="red")
def __rich__(self) -> RenderableType:
highlighter = ReprHighlighter()
errors: list[RenderableType] = []
append = errors.append
message = str(self)
append(Text(" Tokenizer error in stylesheet:", style="bold red"))
append(highlighter(f" {self.path or '<unknown>'}:{self.line_no}:{self.col_no}"))
append(self._get_snippet(self.code, self.line_no))
final_message = ""
for is_last, message_part in loop_last(message.split(";")):
end = "" if is_last else "\n"
final_message += f"{message_part.strip()};{end}"
append(Padding(highlighter(Text(final_message, "red")), pad=(0, 1)))
return Group(*errors)
class EOFError(TokenizeError):
pass
class Expect:
def __init__(self, **tokens: str) -> None:
@@ -51,7 +94,7 @@ class Token(NamedTuple):
path: str
code: str
location: tuple[int, int]
referenced_by: ReferencedBy | None
referenced_by: ReferencedBy | None = None
def with_reference(self, by: ReferencedBy | None) -> "Token":
"""Return a copy of the Token, with reference information attached.
@@ -76,8 +119,9 @@ class Token(NamedTuple):
yield "name", self.name
yield "value", self.value
yield "path", self.path
yield "code", self.code
yield "location", self.location
yield "referenced_by", self.referenced_by
yield "referenced_by", self.referenced_by, None
class Tokenizer:
@@ -95,11 +139,15 @@ class Tokenizer:
if expect._expect_eof:
return Token("eof", "", self.path, self.code, (line_no, col_no), None)
else:
raise EOFError()
raise EOFError(
self.path, self.code, line_no, col_no, "Unexpected end of file"
)
line = self.lines[line_no]
match = expect.match(line, col_no)
if match is None:
raise TokenizeError(
self.path,
self.code,
line_no,
col_no,
"expected " + ", ".join(name.upper() for name in expect.names),
@@ -136,7 +184,9 @@ class Tokenizer:
while True:
if line_no >= len(self.lines):
raise EOFError()
raise EOFError(
self.path, self.code, line_no, col_no, "Unexpected end of file"
)
line = self.lines[line_no]
match = expect.search(line, col_no)

View File

@@ -53,7 +53,7 @@ class DOMNode(MessagePump):
self.INLINE_STYLES, repr(self), node=self
)
self.styles = RenderStyles(self, self._css_styles, self._inline_styles)
self._default_styles = Styles.parse(self.DEFAULT_STYLES, repr(self))
self._default_styles = Styles.parse(self.DEFAULT_STYLES, f"{self.__class__}")
self._default_rules = self._default_styles.extract_rules((0, 0, 0))
super().__init__()

View File

@@ -232,7 +232,7 @@ class MessagePump:
except CancelledError:
raise
except Exception as error:
self.app.panic()
self.app.panic(error)
break
finally:
if self._message_queue.empty():

View File

@@ -20,7 +20,7 @@ class Screen(Widget):
DEFAULT_STYLES = """
layout: dock
layout: dock;
docks: _default=top;
"""
@@ -131,8 +131,8 @@ class Screen(Widget):
self, unclipped_region.size, virtual_size, container_size
)
)
except Exception:
self.app.panic()
except Exception as error:
self.app.panic(error)
self.app.refresh()
self._dirty_widgets.clear()

View File

@@ -20,65 +20,310 @@ VALID_VARIABLE_NAMES = [
def test_variable_declaration_valid_names(name):
css = f"${name}: black on red;"
assert list(tokenize(css, "")) == [
Token(name='variable_name', value=f'${name}:', path='', code=css, location=(0, 0), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 14), referenced_by=None),
Token(name='token', value='black', path='', code=css, location=(0, 15), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 20), referenced_by=None),
Token(name='token', value='on', path='', code=css, location=(0, 21), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 23), referenced_by=None),
Token(name='token', value='red', path='', code=css, location=(0, 24), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 27), referenced_by=None),
Token(
name="variable_name",
value=f"${name}:",
path="",
code=css,
location=(0, 0),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 14),
referenced_by=None,
),
Token(
name="token",
value="black",
path="",
code=css,
location=(0, 15),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 20),
referenced_by=None,
),
Token(
name="token",
value="on",
path="",
code=css,
location=(0, 21),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 23),
referenced_by=None,
),
Token(
name="token",
value="red",
path="",
code=css,
location=(0, 24),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 27),
referenced_by=None,
),
]
def test_variable_declaration_multiple_values():
css = "$x: 2vw\t4% 6s red;"
assert list(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='scalar', value='2vw', path='', code=css, location=(0, 4), referenced_by=None),
Token(name='whitespace', value='\t', path='', code=css, location=(0, 7), referenced_by=None),
Token(name='scalar', value='4%', path='', code=css, location=(0, 8), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 10), referenced_by=None),
Token(name='duration', value='6s', path='', code=css, location=(0, 11), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 13), referenced_by=None),
Token(name='token', value='red', path='', code=css, location=(0, 15), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 18), referenced_by=None),
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="scalar",
value="2vw",
path="",
code=css,
location=(0, 4),
referenced_by=None,
),
Token(
name="whitespace",
value="\t",
path="",
code=css,
location=(0, 7),
referenced_by=None,
),
Token(
name="scalar",
value="4%",
path="",
code=css,
location=(0, 8),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 10),
referenced_by=None,
),
Token(
name="duration",
value="6s",
path="",
code=css,
location=(0, 11),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 13),
referenced_by=None,
),
Token(
name="token",
value="red",
path="",
code=css,
location=(0, 15),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 18),
referenced_by=None,
),
]
def test_variable_declaration_comment_ignored():
css = "$x: red; /* comment */"
assert list(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='token', value='red', path='', code=css, location=(0, 4), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 7), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 8), referenced_by=None),
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="token",
value="red",
path="",
code=css,
location=(0, 4),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 7),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 8),
referenced_by=None,
),
]
def test_variable_declaration_comment_interspersed_ignored():
css = "$x: re/* comment */d;"
assert list(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='token', value='re', path='', code=css, location=(0, 4), referenced_by=None),
Token(name='token', value='d', path='', code=css, location=(0, 19), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 20), referenced_by=None),
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="token",
value="re",
path="",
code=css,
location=(0, 4),
referenced_by=None,
),
Token(
name="token",
value="d",
path="",
code=css,
location=(0, 19),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 20),
referenced_by=None,
),
]
def test_variable_declaration_no_semicolon():
css = "$x: 1\n$y: 2"
assert list(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),
Token(name='variable_value_end', value='\n', path='', code=css, location=(0, 5), referenced_by=None),
Token(name='variable_name', value='$y:', path='', code=css, location=(1, 0), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(1, 3), referenced_by=None),
Token(name='number', value='2', path='', code=css, location=(1, 4), referenced_by=None),
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,
),
Token(
name="variable_value_end",
value="\n",
path="",
code=css,
location=(0, 5),
referenced_by=None,
),
Token(
name="variable_name",
value="$y:",
path="",
code=css,
location=(1, 0),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(1, 3),
referenced_by=None,
),
Token(
name="number",
value="2",
path="",
code=css,
location=(1, 4),
referenced_by=None,
),
]
@@ -92,68 +337,441 @@ def test_variables_declarations_amongst_rulesets():
css = "$x:1; .thing{text:red;} $y:2;"
tokens = list(tokenize(css, ""))
assert tokens == [
Token(name='variable_name', value='$x:', path='', code=css, location=(0, 0), referenced_by=None),
Token(name='number', value='1', path='', code=css, location=(0, 3), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 4), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 5), referenced_by=None),
Token(name='selector_start_class', value='.thing', path='', code=css, location=(0, 6), referenced_by=None),
Token(name='declaration_set_start', value='{', path='', code=css, location=(0, 12), referenced_by=None),
Token(name='declaration_name', value='text:', path='', code=css, location=(0, 13), referenced_by=None),
Token(name='token', value='red', path='', code=css, location=(0, 18), referenced_by=None),
Token(name='declaration_end', value=';', path='', code=css, location=(0, 21), referenced_by=None),
Token(name='declaration_set_end', value='}', path='', code=css, location=(0, 22), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 23), referenced_by=None),
Token(name='variable_name', value='$y:', path='', code=css, location=(0, 24), referenced_by=None),
Token(name='number', value='2', path='', code=css, location=(0, 27), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 28), referenced_by=None),
Token(
name="variable_name",
value="$x:",
path="",
code=css,
location=(0, 0),
referenced_by=None,
),
Token(
name="number",
value="1",
path="",
code=css,
location=(0, 3),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 4),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 5),
referenced_by=None,
),
Token(
name="selector_start_class",
value=".thing",
path="",
code=css,
location=(0, 6),
referenced_by=None,
),
Token(
name="declaration_set_start",
value="{",
path="",
code=css,
location=(0, 12),
referenced_by=None,
),
Token(
name="declaration_name",
value="text:",
path="",
code=css,
location=(0, 13),
referenced_by=None,
),
Token(
name="token",
value="red",
path="",
code=css,
location=(0, 18),
referenced_by=None,
),
Token(
name="declaration_end",
value=";",
path="",
code=css,
location=(0, 21),
referenced_by=None,
),
Token(
name="declaration_set_end",
value="}",
path="",
code=css,
location=(0, 22),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 23),
referenced_by=None,
),
Token(
name="variable_name",
value="$y:",
path="",
code=css,
location=(0, 24),
referenced_by=None,
),
Token(
name="number",
value="2",
path="",
code=css,
location=(0, 27),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 28),
referenced_by=None,
),
]
def test_variables_reference_in_rule_declaration_value():
css = ".warn{text: $warning;}"
assert list(tokenize(css, "")) == [
Token(name='selector_start_class', value='.warn', path='', code=css, location=(0, 0), referenced_by=None),
Token(name='declaration_set_start', value='{', path='', code=css, location=(0, 5), referenced_by=None),
Token(name='declaration_name', value='text:', path='', code=css, location=(0, 6), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 11), referenced_by=None),
Token(name='variable_ref', value='$warning', path='', code=css, location=(0, 12), referenced_by=None),
Token(name='declaration_end', value=';', path='', code=css, location=(0, 20), referenced_by=None),
Token(name='declaration_set_end', value='}', path='', code=css, location=(0, 21), referenced_by=None),
Token(
name="selector_start_class",
value=".warn",
path="",
code=css,
location=(0, 0),
referenced_by=None,
),
Token(
name="declaration_set_start",
value="{",
path="",
code=css,
location=(0, 5),
referenced_by=None,
),
Token(
name="declaration_name",
value="text:",
path="",
code=css,
location=(0, 6),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 11),
referenced_by=None,
),
Token(
name="variable_ref",
value="$warning",
path="",
code=css,
location=(0, 12),
referenced_by=None,
),
Token(
name="declaration_end",
value=";",
path="",
code=css,
location=(0, 20),
referenced_by=None,
),
Token(
name="declaration_set_end",
value="}",
path="",
code=css,
location=(0, 21),
referenced_by=None,
),
]
def test_variables_reference_in_rule_declaration_value_multiple():
css = ".card{padding: $pad-y $pad-x;}"
assert list(tokenize(css, "")) == [
Token(name='selector_start_class', value='.card', path='', code=css, location=(0, 0), referenced_by=None),
Token(name='declaration_set_start', value='{', path='', code=css, location=(0, 5), referenced_by=None),
Token(name='declaration_name', value='padding:', path='', code=css, location=(0, 6), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 14), referenced_by=None),
Token(name='variable_ref', value='$pad-y', path='', code=css, location=(0, 15), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 21), referenced_by=None),
Token(name='variable_ref', value='$pad-x', path='', code=css, location=(0, 22), referenced_by=None),
Token(name='declaration_end', value=';', path='', code=css, location=(0, 28), referenced_by=None),
Token(name='declaration_set_end', value='}', path='', code=css, location=(0, 29), referenced_by=None)
Token(
name="selector_start_class",
value=".card",
path="",
code=css,
location=(0, 0),
referenced_by=None,
),
Token(
name="declaration_set_start",
value="{",
path="",
code=css,
location=(0, 5),
referenced_by=None,
),
Token(
name="declaration_name",
value="padding:",
path="",
code=css,
location=(0, 6),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 14),
referenced_by=None,
),
Token(
name="variable_ref",
value="$pad-y",
path="",
code=css,
location=(0, 15),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 21),
referenced_by=None,
),
Token(
name="variable_ref",
value="$pad-x",
path="",
code=css,
location=(0, 22),
referenced_by=None,
),
Token(
name="declaration_end",
value=";",
path="",
code=css,
location=(0, 28),
referenced_by=None,
),
Token(
name="declaration_set_end",
value="}",
path="",
code=css,
location=(0, 29),
referenced_by=None,
),
]
def test_variables_reference_in_variable_declaration():
css = "$x: $y;"
assert list(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='variable_ref', value='$y', path='', code=css, location=(0, 4), referenced_by=None),
Token(name='variable_value_end', value=';', path='', code=css, location=(0, 6), referenced_by=None)
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="variable_ref",
value="$y",
path="",
code=css,
location=(0, 4),
referenced_by=None,
),
Token(
name="variable_value_end",
value=";",
path="",
code=css,
location=(0, 6),
referenced_by=None,
),
]
def test_variable_references_in_variable_declaration_multiple():
css = "$x: $y $z\n"
assert list(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='variable_ref', value='$y', path='', code=css, location=(0, 4), referenced_by=None),
Token(name='whitespace', value=' ', path='', code=css, location=(0, 6), referenced_by=None),
Token(name='variable_ref', value='$z', path='', code=css, location=(0, 8), referenced_by=None),
Token(name='variable_value_end', value='\n', path='', code=css, location=(0, 10), referenced_by=None)
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="variable_ref",
value="$y",
path="",
code=css,
location=(0, 4),
referenced_by=None,
),
Token(
name="whitespace",
value=" ",
path="",
code=css,
location=(0, 6),
referenced_by=None,
),
Token(
name="variable_ref",
value="$z",
path="",
code=css,
location=(0, 8),
referenced_by=None,
),
Token(
name="variable_value_end",
value="\n",
path="",
code=css,
location=(0, 10),
referenced_by=None,
),
]
def test_allow_new_lines():
css = ".foo{margin: 1\n1 0 0}"
tokens = list(tokenize(css, ""))
print(repr(tokens))
expected = [
Token(
name="selector_start_class",
value=".foo",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(0, 0),
),
Token(
name="declaration_set_start",
value="{",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(0, 4),
),
Token(
name="declaration_name",
value="margin:",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(0, 5),
),
Token(
name="whitespace",
value=" ",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(0, 12),
),
Token(
name="number",
value="1",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(0, 13),
),
Token(
name="whitespace",
value="\n",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(0, 14),
),
Token(
name="number",
value="1",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(1, 0),
),
Token(
name="whitespace",
value=" ",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(1, 1),
),
Token(
name="number",
value="0",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(1, 2),
),
Token(
name="whitespace",
value=" ",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(1, 3),
),
Token(
name="number",
value="0",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(1, 4),
),
Token(
name="declaration_set_end",
value="}",
path="",
code=".foo{margin: 1\n1 0 0}",
location=(1, 5),
),
]
assert list(tokenize(css, "")) == expected