9
9
10
10
11
11
class 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 :
15
13
self .node_element = node_element
16
- self .parent_element = parent
17
14
self .node_content = node_content
18
15
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
22
19
20
+ def get_content (self , item : t .Any ) -> str :
23
21
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
+
24
28
return item .render ()
25
29
26
- if isinstance (item , (list , tuple )):
30
+ if isinstance (item , (list , tuple , Fragment , t . Generator )):
27
31
return "" .join (self .get_content (child ) for child in item )
28
32
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
+
29
40
return str (item )
30
41
31
42
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 )
33
44
attrs = self .node_element .render_attributes (self )
34
45
35
46
return self .node_element .render_tag (attrs , inner_html )
@@ -66,36 +77,32 @@ def render_with_context(
66
77
yield FactoryBuildContext (self .ctx , self .root , element )
67
78
68
79
def child_node_context (
69
- self , element : t . Any , child : t .Any
80
+ self , child : t .Any
70
81
) -> t .Union [NodeContext , t .List [NodeContext ]]:
71
82
if isinstance (child , Element ):
72
- if isinstance (child , LazyComponent ):
73
- child .set_context_data (self )
74
-
75
83
if isinstance (child , Component ):
76
- content = self .child_node_context (child , child .resolve_content ())
77
84
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 )
81
85
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 ]
84
91
85
92
if callable (child ):
86
93
with self .render_with_context (child ) as factory_ctx :
87
- return factory_ctx .build_context (parent = element )
94
+ return factory_ctx .build_context ()
88
95
89
96
return child
90
97
91
98
def get_node_context (
92
99
self , element : t .Union ["Element" , "Fragment" ], parent : t .Any
93
100
) -> 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 ]
96
103
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 )
99
106
100
107
def build_context (self , parent = None ) -> t .Union [NodeContext , t .List [NodeContext ]]:
101
108
return self .get_node_context (self .root , parent = parent )
@@ -332,16 +339,20 @@ def __init__(
332
339
333
340
334
341
class Fragment :
335
- def __init__ (self , * contents : t .Union [Element , t .Any ]) -> None :
342
+ def __init__ (self , * contents : t .Union ["Fragment" , " Element" , t .Any ]) -> None :
336
343
self .content = list (contents )
337
344
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
+
338
354
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 )
345
356
346
357
347
358
class LazyComponent (BaseElement ):
@@ -353,32 +364,19 @@ class LazyComponent(BaseElement):
353
364
354
365
def __init__ (self , resolver : t .Callable , ** attrs ) -> None :
355
366
self .tag = "lazy-component"
356
-
357
367
super (LazyComponent , self ).__init__ (** attrs )
358
-
359
368
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."
371
369
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 ( )
374
372
375
373
def render_tag (self , attrs : str , inner_html : str ) -> str :
376
374
if attrs :
377
375
return f"<div { attrs } >{ inner_html } </div>"
378
376
return inner_html
379
377
380
378
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 ()
382
380
return ctx .get_content (resolved_content )
383
381
384
382
0 commit comments