From d028d4a3c772fb4e655c573f7f03b2d19e58f512 Mon Sep 17 00:00:00 2001 From: Affan Ziya Date: Wed, 16 Sep 2026 13:37:45 +0530 Subject: [PATCH 1/2] escape dimension units starting with e and a digit on serialize --- tests/test_tinycss2.py | 18 ++++++++++++++++++ tinycss2/ast.py | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tests/test_tinycss2.py b/tests/test_tinycss2.py index fb1130a..44c7785 100644 --- a/tests/test_tinycss2.py +++ b/tests/test_tinycss2.py @@ -669,6 +669,24 @@ def test_serialize_rules_with_functions(): assert serialize(rules) == source +@pytest.mark.parametrize('source', [ + r'1\65 5', # unit "e5" + r'1\45 5', # unit "E5" + r'2\65 3px', # unit "e3px" +]) +def test_serialize_dimension_e_unit(source): + # A dimension whose unit starts with e/E followed by a digit must not be + # serialized as a bare "1e5": that re-parses as a number in scientific + # notation, changing the token type (and value). Serialization has to keep + # escaping the leading e so the token round-trips as the same dimension. + (dimension,) = parse_component_value_list(source) + assert dimension.type == 'dimension' + (reparsed,) = parse_component_value_list(serialize([dimension])) + assert reparsed.type == 'dimension' + assert reparsed.value == dimension.value + assert reparsed.lower_unit == dimension.lower_unit + + def test_backslash_delim(): source = '\\\nfoo' tokens = parse_component_value_list(source) diff --git a/tinycss2/ast.py b/tinycss2/ast.py index 2831abc..9f40daa 100644 --- a/tinycss2/ast.py +++ b/tinycss2/ast.py @@ -568,7 +568,8 @@ def _serialize_to(self, write): write(self.representation) # Disambiguate with scientific notation unit = self.unit - if unit in ('e', 'E') or unit.startswith(('e-', 'E-')): + if unit in ('e', 'E') or unit.startswith(('e-', 'E-')) or ( + len(unit) >= 2 and unit[0] in 'eE' and unit[1] in '0123456789'): write('\\65 ') write(serialize_name(unit[1:])) else: From 3b187ad80d89328177667443a954ed7c4efe34bd Mon Sep 17 00:00:00 2001 From: Affan Ziya Date: Fri, 18 Sep 2026 10:03:23 +0530 Subject: [PATCH 2/2] Fold dimension e-unit escape into a single condition --- tinycss2/ast.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tinycss2/ast.py b/tinycss2/ast.py index 9f40daa..324955d 100644 --- a/tinycss2/ast.py +++ b/tinycss2/ast.py @@ -568,8 +568,7 @@ def _serialize_to(self, write): write(self.representation) # Disambiguate with scientific notation unit = self.unit - if unit in ('e', 'E') or unit.startswith(('e-', 'E-')) or ( - len(unit) >= 2 and unit[0] in 'eE' and unit[1] in '0123456789'): + if unit[0] in 'eE' and (len(unit) == 1 or unit[1] in '+-0123456789'): write('\\65 ') write(serialize_name(unit[1:])) else: