Skip to content

Commit a2a1e90

Browse files
Use renderer text-element API for template text nodes (#180)
1 parent 1e5c25b commit a2a1e90

2 files changed

Lines changed: 70 additions & 14 deletions

File tree

collagraph/fragment.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,13 @@ def create(self):
317317
return
318318

319319
# Create the element
320-
self.element = self.renderer.create_element(self.tag)
320+
if self.tag == "TEXT_ELEMENT":
321+
self.element = self.renderer.create_text_element()
322+
else:
323+
self.element = self.renderer.create_element(self.tag)
321324
# Set all static attributes
322325
for attr, value in self._attributes.items():
323-
self.renderer.set_attribute(self.element, attr, value)
326+
self._set_attr(attr, value)
324327

325328
# Add all event handlers
326329
# TODO: check what happens within v-for constructs?
@@ -385,14 +388,20 @@ def mount(self, target: Any, anchor: Any | None = None):
385388

386389
def _set_attr(self, attr, value):
387390
if self.element:
388-
self.renderer.set_attribute(self.element, attr, value)
391+
if self.tag == "TEXT_ELEMENT" and attr == "content":
392+
self.renderer.set_element_text(self.element, value)
393+
else:
394+
self.renderer.set_attribute(self.element, attr, value)
389395
if self._mounted:
390396
if component := self._component_parent():
391397
component.updated()
392398

393399
def _rem_attr(self, attr):
394400
if self.element:
395-
self.renderer.remove_attribute(self.element, attr, None)
401+
if self.tag == "TEXT_ELEMENT" and attr == "content":
402+
self.renderer.set_element_text(self.element, "")
403+
else:
404+
self.renderer.remove_attribute(self.element, attr, None)
396405
if self._mounted:
397406
if component := self._component_parent():
398407
component.updated()

tests/test_text_expressions.py

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@
44
from collagraph.renderers.dict_renderer import format_dict
55

66

7+
class TrackingDictRenderer(DictRenderer):
8+
def __init__(self):
9+
super().__init__()
10+
self.created_text_elements = 0
11+
self.set_text_calls = 0
12+
13+
def create_text_element(self):
14+
self.created_text_elements += 1
15+
return super().create_text_element()
16+
17+
def set_element_text(self, el: dict, value: str):
18+
self.set_text_calls += 1
19+
super().set_element_text(el, value)
20+
21+
722
def test_text_elements():
823
from tests.data.text.expressions import Example
924

@@ -82,14 +97,14 @@ def test_text_elements():
8297
assert multiline["type"] == "TEXT_ELEMENT"
8398
assert static_multiline["type"] == "TEXT_ELEMENT"
8499
assert complex_multiline["type"] == "TEXT_ELEMENT"
85-
assert static["attrs"]["content"] == "Static content"
86-
assert dynamic["attrs"]["content"] == "Dynamic foo"
87-
assert multiple["attrs"]["content"] == r"Even bar dyna{}mic\{} foo"
88-
assert quoted["attrs"]["content"] == 'Quote "foo" and slash \\\\ bar'
89-
assert multiline["attrs"]["content"] == 'Line "foo"\nnext bar'
90-
assert static_multiline["attrs"]["content"] == "First line\nsecond line"
100+
assert static["text"] == "Static content"
101+
assert dynamic["text"] == "Dynamic foo"
102+
assert multiple["text"] == r"Even bar dyna{}mic\{} foo"
103+
assert quoted["text"] == 'Quote "foo" and slash \\\\ bar'
104+
assert multiline["text"] == 'Line "foo"\nnext bar'
105+
assert static_multiline["text"] == "First line\nsecond line"
91106
assert (
92-
complex_multiline["attrs"]["content"]
107+
complex_multiline["text"]
93108
== 'Complex "foo"\nmiddle {{literal}} bar\ntail foo/bar'
94109
)
95110

@@ -98,6 +113,38 @@ def test_text_elements():
98113
assert split_p["children"][1]["type"] == "TEXT_ELEMENT"
99114
assert split_p["children"][2]["type"] == "span"
100115
assert split_p["children"][3]["type"] == "TEXT_ELEMENT"
101-
assert split_p["children"][0]["attrs"]["content"] == "Split"
102-
assert split_p["children"][1]["attrs"]["content"] == " and split by "
103-
assert split_p["children"][3]["attrs"]["content"] == " element"
116+
assert split_p["children"][0]["text"] == "Split"
117+
assert split_p["children"][1]["text"] == " and split by "
118+
assert split_p["children"][3]["text"] == " element"
119+
120+
121+
def test_text_elements_use_text_renderer_api(parse_source):
122+
App, _ = parse_source(
123+
"""
124+
<item>
125+
Text content here
126+
</item>
127+
128+
<script>
129+
import collagraph as cg
130+
131+
class App(cg.Component):
132+
pass
133+
</script>
134+
"""
135+
)
136+
137+
renderer = TrackingDictRenderer()
138+
container = {"type": "root"}
139+
gui = Collagraph(
140+
renderer=renderer,
141+
event_loop_type=EventLoopType.SYNC,
142+
)
143+
gui.render(App, container)
144+
145+
assert container["children"][0]["type"] == "item"
146+
assert container["children"][0]["children"][0]["type"] == "TEXT_ELEMENT"
147+
assert container["children"][0]["children"][0]["text"] == "\nText content here\n"
148+
149+
assert renderer.created_text_elements == 1
150+
assert renderer.set_text_calls == 1

0 commit comments

Comments
 (0)