Skip to content

Commit 5d87e8b

Browse files
Fix for parsing cgx files without template nodes (#4)
* Fix for parsing cgx files without template nodes * Add some whitespace within a root nodes' children
1 parent 5e3de3d commit 5d87e8b

6 files changed

Lines changed: 132 additions & 15 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "ruff-cgx"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
description = "Ruff linter and formatter for collagraph single-file components"
55
readme = "README.md"
66
requires-python = ">=3.10"

ruff_cgx/formatter.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313

1414
def format_script(path, script_node, source_lines, check):
15+
"""
16+
Returns formatted source and the original location of the node
17+
"""
1518
start, end = script_node.location[0], script_node.end[0] - 1
1619

1720
source = "".join(source_lines[start:end])
@@ -66,29 +69,48 @@ def format_file(path, check=False, write=True):
6669
lines = fh.readlines()
6770

6871
script_node = parser.root.child_with_tag("script")
69-
template_node = parser.root.child_with_tag("template")
72+
template_nodes = [
73+
node
74+
for node in parser.root.children
75+
if not hasattr(node, "tag") or node.tag != "script"
76+
]
7077

7178
script_content, script_location = format_script(path, script_node, lines, check)
72-
template_content, template_location = format_template(
73-
template_node, lines, parser=parser
74-
)
75-
76-
changed = (
77-
lines[script_location[0] : script_location[1]] != script_content
78-
or lines[template_location[0] : template_location[1]] != template_content
79+
formatted_template_nodes = [
80+
format_template(node, lines, parser=parser) for node in template_nodes
81+
]
82+
83+
changed_script = lines[script_location[0] : script_location[1]] != script_content
84+
changed_template = any(
85+
[
86+
lines[template_location[0] : template_location[1]] != template_content
87+
for template_content, template_location in formatted_template_nodes
88+
]
7989
)
90+
needs_newline_at_end_of_file = not lines[-1].endswith("\n")
91+
changed = changed_script or changed_template or needs_newline_at_end_of_file
8092
if check:
8193
if changed:
8294
logger.warning(f"Would change: {path}")
8395
return 1
8496
return 0
8597

86-
if script_location[0] > template_location[0]:
87-
lines[script_location[0] : script_location[1]] = script_content
88-
lines[template_location[0] : template_location[1]] = template_content
89-
else:
90-
lines[script_location[0] : script_location[1]] = script_content
91-
lines[template_location[0] : template_location[1]] = template_content
98+
formatted_parts = reversed(
99+
sorted(
100+
[
101+
(script_content, script_location),
102+
*formatted_template_nodes,
103+
],
104+
key=lambda x: x[1][0],
105+
)
106+
)
107+
108+
for formatted_content, (start, end) in formatted_parts:
109+
lines[start:end] = formatted_content
110+
111+
if needs_newline_at_end_of_file:
112+
lines.append("\n")
113+
92114
if not write:
93115
return lines
94116

ruff_cgx/template_formatter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323

2424

2525
def format_template(template_node, lines, parser):
26+
"""
27+
Returns formatted node and the original location of the template node
28+
"""
2629
# Find beginning and end of script block
2730
start, end = template_node.location[0] - 1, template_node.end[0]
2831

tests/data/no_template.cgx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<node />
2+
3+
<script>
4+
from collagraph import Component
5+
class Node(Component):
6+
pass
7+
</script>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<node />
2+
3+
4+
5+
6+
<script>
7+
from collagraph import Component
8+
class Node(Component):
9+
pass
10+
</script>
11+
12+
13+
14+
<other-node>
15+
16+
17+
<should-work-just-fine />
18+
</other-node>

tests/test_formatter.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,70 @@ class Simple(Component):
105105
stdout = capsys.readouterr().out
106106

107107
assert "1 file reformatted" in stdout, stdout
108+
109+
110+
def test_works_with_no_template(capsys, data_path):
111+
"""
112+
Also checks that a newline will be added at the end
113+
of the file.
114+
"""
115+
template_cgx = data_path / "no_template.cgx"
116+
117+
lines = format_file(template_cgx, write=False)
118+
119+
expected = textwrap.dedent(
120+
"""
121+
<node />
122+
123+
<script>
124+
from collagraph import Component
125+
126+
127+
class Node(Component):
128+
pass
129+
</script>
130+
"""
131+
).lstrip()
132+
assert "".join(lines) == expected
133+
134+
stdout = capsys.readouterr().out
135+
136+
assert "1 file reformatted" in stdout, stdout
137+
138+
139+
def test_works_with_no_template_elaborate(capsys, data_path):
140+
"""
141+
Also checks that whitespace between root nodes is preserved.
142+
"""
143+
template_cgx = data_path / "no_template_elaborate.cgx"
144+
145+
lines = format_file(template_cgx, write=False)
146+
147+
expected = textwrap.dedent(
148+
"""
149+
<node />
150+
151+
152+
153+
154+
<script>
155+
from collagraph import Component
156+
157+
158+
class Node(Component):
159+
pass
160+
</script>
161+
162+
163+
164+
<other-node>
165+
<should-work-just-fine />
166+
</other-node>
167+
168+
"""
169+
).lstrip()
170+
assert "".join(lines) == expected
171+
172+
stdout = capsys.readouterr().out
173+
174+
assert "1 file reformatted" in stdout, stdout

0 commit comments

Comments
 (0)