99
1010
1111class NodeContext:
12- def __init__(
13- self, parent: t.Any, node_element: "Element", node_content: t.Any
14- ) -> None:
12+ def __init__(self, node_element: "Element", node_content: t.Any) -> None:
1513 self.node_element = node_element
16- self.parent_element = parent
1714 self.node_content = node_content
1815
19- def get_content(self, item: t.Any) -> str:
20- if item is None or type(item) is bool :
21- return ""
16+ @property
17+ def element(self) -> "Element" :
18+ return self.node_element
2219
20+ def get_content(self, item: t.Any) -> str:
2321 if isinstance(item, NodeContext):
22+ if isinstance(item.node_element, LazyComponent):
23+ item.node_content = item.node_element.resolve_lazy_element()
24+
25+ if isinstance(item.node_element, Component):
26+ item.node_content = item.node_element.resolve_content()
27+
2428 return item.render()
2529
26- if isinstance(item, (list, tuple)):
30+ if isinstance(item, (list, tuple, Fragment, t.Generator )):
2731 return "".join(self.get_content(child) for child in item)
2832
33+ if isinstance(item, Element):
34+ node_context = NodeContext(item, item.content)
35+ return node_context.render()
36+
37+ if item is None or type(item) is bool:
38+ return ""
39+
2940 return str(item)
3041
3142 def render(self) -> str:
32- inner_html = self.node_element.render_content(self.node_content, self)
43+ inner_html = self.node_element.render_content(Fragment( self.node_content) , self)
3344 attrs = self.node_element.render_attributes(self)
3445
3546 return self.node_element.render_tag(attrs, inner_html)
@@ -66,36 +77,32 @@ def render_with_context(
6677 yield FactoryBuildContext(self.ctx, self.root, element)
6778
6879 def child_node_context(
69- self, element: t.Any, child: t.Any
80+ self, child: t.Any
7081 ) -> t.Union[NodeContext, t.List[NodeContext]]:
7182 if isinstance(child, Element):
72- if isinstance(child, LazyComponent):
73- child.set_context_data(self)
74-
7583 if isinstance(child, Component):
76- content = self.child_node_context(child, child.resolve_content())
7784 child.exports(self)
78- else:
79- content = self.child_node_context(child, child.content)
80- return NodeContext(parent=element, node_element=child, node_content=content)
8185
82- if isinstance(child, (list, tuple, Fragment)):
83- return [self.child_node_context(element, child=item) for item in child]
86+ content = self.child_node_context(child.content)
87+ return NodeContext(node_element=child, node_content=content)
88+
89+ if isinstance(child, (list, tuple, Fragment, t.Generator)):
90+ return [self.child_node_context(child=item) for item in child]
8491
8592 if callable(child):
8693 with self.render_with_context(child) as factory_ctx:
87- return factory_ctx.build_context(parent=element )
94+ return factory_ctx.build_context()
8895
8996 return child
9097
9198 def get_node_context(
9299 self, element: t.Union["Element", "Fragment"], parent: t.Any
93100 ) -> t.Union[t.List[NodeContext], NodeContext]:
94- if isinstance(element, (list, tuple, Fragment)):
95- return [self.child_node_context(parent, child=child) for child in element]
101+ if isinstance(element, (list, tuple, Fragment, t.Generator )):
102+ return [self.child_node_context(child=child) for child in element]
96103
97- content = self.child_node_context(parent, element.content)
98- return NodeContext(parent, node_element=element, node_content=content)
104+ content = self.child_node_context(element.content)
105+ return NodeContext(node_element=element, node_content=content)
99106
100107 def build_context(self, parent=None) -> t.Union[NodeContext, t.List[NodeContext]]:
101108 return self.get_node_context(self.root, parent=parent)
@@ -332,16 +339,20 @@ def __init__(
332339
333340
334341class Fragment:
335- def __init__(self, *contents: t.Union[Element, t.Any]) -> None:
342+ def __init__(self, *contents: t.Union["Fragment", " Element" , t.Any]) -> None:
336343 self.content = list(contents)
337344
345+ def resolve_content(self, content) -> t.Generator:
346+ for item in content:
347+ if isinstance(item, Fragment):
348+ yield from self.resolve_content(item.content)
349+ elif isinstance(item, (list, tuple, t.Generator)):
350+ yield from self.resolve_content(item)
351+ else:
352+ yield item
353+
338354 def __iter__(self):
339- for item in self.content:
340- if isinstance(item, (Fragment, list, tuple)):
341- for y in item:
342- yield y
343- continue
344- yield item
355+ return self.resolve_content(self.content)
345356
346357
347358class LazyComponent(BaseElement):
@@ -353,32 +364,19 @@ class LazyComponent(BaseElement):
353364
354365 def __init__(self, resolver: t.Callable, **attrs) -> None:
355366 self.tag = "lazy-component"
356-
357367 super(LazyComponent, self).__init__(**attrs)
358-
359368 self._resolver = resolver
360- self._ctx: t.Optional[BuildContext] = None
361-
362- def set_context_data(self, ctx: BuildContext) -> None:
363- self._ctx = ctx
364-
365- def resolve_lazy_element(
366- self, parent: t.Optional["Element"] = None
367- ) -> t.Union[NodeContext, t.List[NodeContext]]:
368- assert (
369- self._ctx is not None
370- ), "please set_context_data() before resolving element."
371369
372- element = self._resolver()
373- return self._ctx.child_node_context(parent, element )
370+ def resolve_lazy_element(self) -> t.Union[NodeContext, t.List[NodeContext]]:
371+ return self._resolver( )
374372
375373 def render_tag(self, attrs: str, inner_html: str) -> str:
376374 if attrs:
377375 return f"<div {attrs}>{inner_html}</div>"
378376 return inner_html
379377
380378 def render_content(self, content: t.Any, ctx: NodeContext) -> t.Any:
381- resolved_content = self.resolve_lazy_element(ctx.parent_element )
379+ resolved_content = self.resolve_lazy_element()
382380 return ctx.get_content(resolved_content)
383381
384382
0 commit comments