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