Skip to content

Commit 4e19a7e

Browse files
Fix end location of self-closing elements
1 parent 30f399a commit 4e19a7e

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

collagraph/sfc/parser.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def __init__(self, *args, **kwargs):
4545
self.root = Element("root", attrs={}, location=(-1, -1))
4646
self.stack = [self.root]
4747

48-
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]):
48+
def _handle_tag(self, tag: str, attrs: list[tuple[str, str | None]]) -> Element:
4949
# The tag parameter is lower-cased by the HTMLParser.
5050
# In order to figure out whether the tag indicates
5151
# an imported class, we need the original casing for
@@ -68,6 +68,11 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]):
6868
parent = self.stack[-1]
6969
parent.children.append(node)
7070
node.parent = ref(parent)
71+
72+
return node
73+
74+
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]):
75+
node = self._handle_tag(tag, attrs)
7176
# Make the new node the last on the stack
7277
self.stack.append(node)
7378

@@ -81,6 +86,20 @@ def handle_endtag(self, tag: str):
8186
if node.tag.lower() == tag:
8287
break
8388

89+
def handle_startendtag(self, tag: str, attrs):
90+
"""Handle self-closing tags"""
91+
node = self._handle_tag(tag, attrs)
92+
# Get the full text and split it
93+
text = self.get_starttag_text()
94+
lines = text.splitlines()
95+
# Find the location of where the tag is actually closed
96+
column = lines[-1].index("/>")
97+
# Figure out how many lines the tag spans
98+
line_span_count = len(lines) - 1
99+
line, _ = self.getpos()
100+
# Set the end to be exactly where the '/>' is located
101+
node.end = (line + line_span_count, column)
102+
84103
def handle_data(self, data: str):
85104
if data.strip():
86105
# Add item as child to the last on the stack

tests/test_parser.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
from textwrap import dedent
2+
13
import pytest
24

35
from collagraph import Collagraph, EventLoopType
46
from collagraph.renderers import DictRenderer
7+
from collagraph.sfc.parser import CGXParser
58

69

710
def test_parser_unclosed_element(parse_source):
@@ -49,3 +52,28 @@ class App(cg.Component):
4952
</script>
5053
"""
5154
)
55+
56+
57+
def test_parser_element_start_end(parse_source):
58+
parser = CGXParser()
59+
parser.feed(
60+
dedent("""\
61+
<long-item
62+
@with-many="toet"
63+
:attrs="blaat"
64+
:that-take="foo"
65+
a-lot-of="space"
66+
/>
67+
68+
<other />
69+
""")
70+
)
71+
72+
assert parser.root
73+
long_item = parser.root.children[0]
74+
assert long_item.location == (1, 0)
75+
assert long_item.end == (6, 0)
76+
77+
short_item = parser.root.children[1]
78+
assert short_item.location == (8, 0)
79+
assert short_item.end == (8, 7)

0 commit comments

Comments
 (0)