phml.builder
phml.utils.builder
This module serves as a utility to make building elements and ast's easier.
1"""phml.utils.builder 2 3This module serves as a utility to make building elements and ast's easier. 4""" 5 6from __future__ import annotations 7 8from typing import Optional 9 10from phml.nodes import All_Nodes, Comment, DocType, Element, Root, Text 11 12__all__ = ["p"] 13 14 15def __process_children(node, children: list[str | list | int | All_Nodes]): 16 for child in children: 17 if isinstance(child, str): 18 node.children.append(Text(child, node)) 19 elif isinstance(child, int): 20 node.children.append(Text(str(child), node)) 21 elif isinstance(child, All_Nodes): 22 child.parent = node 23 node.children.append(child) 24 elif isinstance(child, list): 25 for nested_child in child: 26 if isinstance(nested_child, str): 27 node.children.append(Text(nested_child, node)) 28 elif isinstance(nested_child, int): 29 node.children.append(Text(str(nested_child), node)) 30 elif isinstance(nested_child, All_Nodes): 31 nested_child.parent = node 32 node.children.append(nested_child) 33 else: 34 raise TypeError( 35 f"Unkown type <{type(nested_child).__name__}> in {child}:\ 36 {nested_child}" 37 ) 38 39 40def p( # pylint: disable=[invalid-name,keyword-arg-before-vararg] 41 selector: Optional[str] = None, 42 *args: str | list | int | All_Nodes, 43): 44 """Generic factory for creating phml nodes.""" 45 46 # Get all children | non dict objects 47 children = [child for child in args if isinstance(child, (str, list, int, All_Nodes))] 48 49 # Get all properties | dict objects 50 props = [prop for prop in args if isinstance(prop, dict)] 51 52 if selector is not None: 53 # Is a comment 54 if isinstance(selector, str) and selector.startswith("<!--"): 55 return Comment(selector.replace("<!--", "").replace("-->", "")) 56 57 # Is a text node 58 if ( 59 isinstance(selector, str) 60 and (len(selector.split(" ")) > 1 or selector.split("\n")) 61 and len(args) == 0 62 ): 63 return Text(selector) 64 65 if not isinstance(selector, str): 66 args = [selector, *args] 67 selector = None 68 69 if selector is not None: 70 return parse_node(selector, props, children) 71 72 return parse_root(children) 73 74 75def parse_root(children: list): 76 """From the given information return a built root node.""" 77 78 node = Root() 79 __process_children(node, children) 80 81 82def parse_node(selector: str, props: dict, children: list): 83 """From the provided selector, props, and children build an element node.""" 84 from phml.utils import parse_specifiers # pylint: disable=import-outside-toplevel 85 86 node = parse_specifiers(selector) 87 if len(node) > 1: 88 raise Exception("Selector can not be a complex selector") 89 if not isinstance(node[0], dict) or len(node[0]["attributes"]) > 0: 90 raise EncodingWarning("Selector must be of the format `tag?[#id][.classes...]`") 91 92 node = node[0] 93 94 node["tag"] = "div" if node["tag"] == "*" else node["tag"] 95 96 if node["tag"].lower() == "doctype": 97 str_children = [child for child in children if isinstance(child, str)] 98 if len(str_children) > 0: 99 return DocType(str_children[0]) 100 return DocType() 101 102 if node["tag"].lower() == "text": 103 return Text(" ".join([child for child in children if isinstance(child, str)])) 104 105 properties = {} 106 for prop in props: 107 properties.update(prop) 108 109 if len(node["classList"]) > 0: 110 properties["class"] = properties["class"] or "" 111 properties["class"] += " ".join(node["classList"]) 112 if node["id"] is not None: 113 properties["id"] = node["id"] 114 115 node = Element( 116 node["tag"], 117 properties=properties, 118 startend=len(children) == 0, 119 ) 120 121 __process_children(node, children) 122 return node
def
p( selector: Optional[str] = None, *args: str | list | int | phml.nodes.root.Root | phml.nodes.element.Element | phml.nodes.text.Text | phml.nodes.comment.Comment | phml.nodes.doctype.DocType | phml.nodes.parent.Parent | phml.nodes.node.Node | phml.nodes.literal.Literal):
41def p( # pylint: disable=[invalid-name,keyword-arg-before-vararg] 42 selector: Optional[str] = None, 43 *args: str | list | int | All_Nodes, 44): 45 """Generic factory for creating phml nodes.""" 46 47 # Get all children | non dict objects 48 children = [child for child in args if isinstance(child, (str, list, int, All_Nodes))] 49 50 # Get all properties | dict objects 51 props = [prop for prop in args if isinstance(prop, dict)] 52 53 if selector is not None: 54 # Is a comment 55 if isinstance(selector, str) and selector.startswith("<!--"): 56 return Comment(selector.replace("<!--", "").replace("-->", "")) 57 58 # Is a text node 59 if ( 60 isinstance(selector, str) 61 and (len(selector.split(" ")) > 1 or selector.split("\n")) 62 and len(args) == 0 63 ): 64 return Text(selector) 65 66 if not isinstance(selector, str): 67 args = [selector, *args] 68 selector = None 69 70 if selector is not None: 71 return parse_node(selector, props, children) 72 73 return parse_root(children)
Generic factory for creating phml nodes.