Skip to content

Commit 71e188a

Browse files
committed
Still adjusting node and build context
1 parent 05d5122 commit 71e188a

File tree

5 files changed

+66
-62
lines changed

5 files changed

+66
-62
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ fmt format:clean ## Run code formatters
2929
ruff format py_html
3030
ruff check --fix py_html
3131

32+
ruff-fix: ## Run Ruff fixer
33+
ruff check py_html --fix --unsafe-fixes
34+
3235
test:clean ## Run tests
3336
pytest
3437

bootstrap_exercise.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def template():
2626
content = BootstrapHTML(
2727
content=[
2828
el.Body(
29-
content=lambda ctx: el.Fragment(
29+
content=el.Fragment(
3030
"""
3131
<div class="container-fluid">
3232
<h1>My First Bootstrap Page</h1>
@@ -66,7 +66,7 @@ def template():
6666
content=(
6767
el.H1(content="Avatars Examples"),
6868
el.Div(class_name="mt-2", content=(
69-
BAvatar(text="Foo", class_name="mx-2", size="72px"),
69+
lambda ctx: BAvatar(text="Foo", class_name="mx-2", size="72px"),
7070
BAvatar(icon="people-fill", class_name="mx-2", size="72px"),
7171
BAvatar(
7272
icon="people-fill",
@@ -76,7 +76,7 @@ def template():
7676
variant="primary",
7777
badge_variant="dark"
7878
),
79-
BAvatar(
79+
lambda ctx: BAvatar(
8080
icon="people-fill",
8181
class_name="mx-2",
8282
size="45px",
@@ -102,7 +102,7 @@ def template():
102102
variant="primary",
103103
badge_variant="dark"
104104
),
105-
BAvatar(
105+
lambda ctx: BAvatar(
106106
icon="people-fill",
107107
size="45px",
108108
badge=BIcon(icon_name="exclamation-circle-fill", variant="warning"),

py_html/contrib/bootstrap/avatar.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ def resolve_content(self) -> t.Union[Fragment, Element]:
102102
content=self.badge,
103103
variant=self.badge_variant,
104104
position=self.badge_position,
105+
style=StyleCSS(font_size=f"calc({self.size} * 0.28)"),
105106
)
106107
if self.badge
107108
else el.Comment(),
@@ -201,8 +202,8 @@ def get_parent_style(self) -> StyleCSS:
201202
return StyleCSS(padding_left=formular, padding_right=formular)
202203
return StyleCSS()
203204

204-
def render_content(self, content: t.Any, ctx: NodeContext) -> str:
205-
for node in list(content) if isinstance(content, (list, tuple)) else [content]:
205+
def render_content(self, content: Fragment, ctx: NodeContext) -> str:
206+
for node in content:
206207
if isinstance(node.element, BAvatar):
207208
if self.size:
208209
node.element.size = self.size

py_html/el/base.py

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,38 @@
99

1010

1111
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:
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

334341
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:
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

347358
class 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

py_html/el/elements/semantics.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,18 @@ def __init__(
1818
self.content = content
1919

2020
def render_content(self, content: t.Any, ctx: NodeContext) -> str:
21-
if isinstance(content, (dict, StyleCSS)):
22-
ensure_style_css = StyleCSS(**content)
23-
24-
inner_html = " ".join(
25-
(
26-
f"{k} " + "{" + f"{v.render()}" + "}"
27-
for k, v in ensure_style_css.items()
21+
for item in content:
22+
if isinstance(item, (dict, StyleCSS)):
23+
ensure_style_css = StyleCSS(**item)
24+
25+
inner_html = " ".join(
26+
(
27+
f"{k} " + "{" + f"{v.render()}" + "}"
28+
for k, v in ensure_style_css.items()
29+
)
2830
)
29-
)
30-
return inner_html
31+
32+
return inner_html
3133
return ctx.get_content(content)
3234

3335

0 commit comments

Comments
 (0)