Coverage for phml\compiler\steps\embedded.py: 100%
16 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-06 14:03 -0500
« prev ^ index » next coverage.py v6.5.0, created at 2023-04-06 14:03 -0500
1from html import escape
2from typing import Any
4from phml.embedded import exec_embedded, exec_embedded_blocks
5from phml.helpers import build_recursive_context
6from phml.nodes import Element, Literal, Parent
8from .base import comp_step
10ESCAPE_OPTIONS = {
11 "quote": False,
12}
15def _process_attributes(node: Element, context: dict[str, Any]):
16 context = build_recursive_context(node, context)
17 for attribute in list(node.attributes.keys()):
18 if attribute.startswith(":"):
19 result = exec_embedded(
20 str(node[attribute]).strip(),
21 f"<{node.tag} {attribute}='{node[attribute]}'>",
22 **context,
23 )
24 if result is not None:
25 node.pop(attribute, None)
26 if isinstance(result, str):
27 node[attribute.lstrip(":")] = escape(result, **ESCAPE_OPTIONS)
28 else:
29 node[attribute.lstrip(":")] = result
30 else:
31 if isinstance(node[attribute], str):
32 value = exec_embedded_blocks(
33 str(node.attributes[attribute]).strip(),
34 f"<{node.tag} {attribute}='{node.attributes[attribute]}'>",
35 **context,
36 )
37 if value is not None:
38 node[attribute] = escape(value, **ESCAPE_OPTIONS)
41@comp_step
42def step_execute_embedded_python(node: Parent, _, context: dict[str, Any]):
43 """Step to process embedded python inside of attributes and text nodes."""
44 for child in node:
45 if isinstance(child, Element):
46 _process_attributes(
47 child,
48 build_recursive_context(child, context),
49 )
50 elif Literal.is_text(child) and "{{" in child.content:
51 child.content = escape(
52 exec_embedded_blocks(
53 child.content.strip(),
54 f"Text in <{node.tag}> at {node.position!r}",
55 **build_recursive_context(child, context),
56 ),
57 **ESCAPE_OPTIONS,
58 )