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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy