Skip to content

Commit d1a393e

Browse files
Add formatting for v-for expressions
1 parent 1074bae commit d1a393e

4 files changed

Lines changed: 55 additions & 9 deletions

File tree

ruff_cgx/template_formatter.py

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,48 @@ def format_python_expression(expr: str) -> str:
6464
return expr
6565

6666

67-
def format_template(template_node):
67+
def format_list_expression(expr: str) -> str:
68+
"""
69+
Format a Python list expression (v-for syntax) using ruff with single quotes.
70+
71+
The v-for syntax is: "item in items" or "(item, index) in items"
72+
We need to format both the target and iterable parts separately.
73+
74+
Args:
75+
expr: The list expression as a string (e.g., "item in items")
76+
77+
Returns:
78+
Formatted expression as a string (using single quotes)
79+
"""
80+
if not expr or not expr.strip():
81+
return expr
82+
83+
try:
84+
expr = expr.strip()
85+
86+
# Split on ' in ' to separate target from iterable
87+
# We use the first occurrence to handle cases where
88+
# 'in' might appear in the iterable
89+
parts = expr.split(" in ", 1)
90+
91+
if len(parts) != 2:
92+
# If no ' in ' found, return as-is (malformed v-for expression)
93+
return expr
94+
95+
target, iterable = parts
96+
97+
# Format each part using format_python_expression
98+
formatted_target = format_python_expression(target.strip())
99+
formatted_iterable = format_python_expression(iterable.strip())
100+
101+
return f"{formatted_target} in {formatted_iterable}"
102+
103+
except Exception as e:
104+
logger.debug(f"Could not format list expression '{expr}': {e}")
105+
return expr
106+
107+
108+
def format_template(template_node) -> tuple[list[str], tuple[int, int]]:
68109
"""
69110
Returns formatted node and the original location of the template node
70111
"""
@@ -130,16 +171,17 @@ def format_attribute(key, value):
130171
# Format Python expressions in bindings, events, and directives
131172
if key.startswith((":", "@", "v-")) and isinstance(value, str) and value.strip():
132173
value = value.strip()
133-
# For v-for, don't format as it has special syntax
134-
# For v-slot, don't format as it has special syntax
135-
if not key.startswith(("v-for", "v-slot", "#")):
174+
if key.startswith("v-for"):
175+
formatted_value = format_list_expression(value)
176+
return f'{key}="{formatted_value}"'
177+
else:
136178
formatted_value = format_python_expression(value)
137179
return f'{key}="{formatted_value}"'
138180

139181
return f'{key}="{value}"'
140182

141183

142-
def format_node(node, depth):
184+
def format_node(node, depth: int) -> list[str]:
143185
result = []
144186
indent = depth * INDENT
145187

tests/data/template.cgx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
@example="hai" :attr="10"
77
blaat="True"
88
attribute />
9-
<nested>
9+
<nested #header >
1010
<attrs
1111
key3="fda"
1212
key0="blasd"
@@ -35,7 +35,7 @@ comment
3535
v-else>
3636
<!-- Some comment here -->
3737
</toet>
38-
<item> With text content <!--toet --> bloeb</item>
38+
<item v-slot:footer > With text content <!--toet --> bloeb</item>
3939
</root>
4040
</template>
4141

tests/test_formatter_cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def test_format_template(capsys, data_path):
5151
blaat="True"
5252
@example="hai"
5353
/>
54-
<nested>
54+
<nested #header>
5555
<attrs
5656
key0="blasd"
5757
:key1="'asdf'"
@@ -83,7 +83,7 @@ def test_format_template(capsys, data_path):
8383
<toet v-else>
8484
<!-- Some comment here -->
8585
</toet>
86-
<item>
86+
<item v-slot:footer>
8787
With text content
8888
<!--toet -->
8989
bloeb

tests/test_formatter_template.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,7 @@ def test_format_attribute_with_expression():
118118
# v-if directive with expression
119119
result = format_attribute("v-if", "counter==0")
120120
assert result == 'v-if="counter == 0"'
121+
122+
# v-for directive with expression
123+
result = format_attribute("v-for", " it in enumerate( items, start = 0 ) ")
124+
assert result == 'v-for="it in enumerate(items, start=0)"'

0 commit comments

Comments
 (0)