phml.core.formats.html_format
1from copy import deepcopy 2from typing import Optional 3 4from phml.core.nodes import AST, NODE 5from phml.core.virtual_python import VirtualPython 6from phml.utilities import find_all, remove_nodes 7 8from .compile import ASTRenderer, apply_conditions, apply_python 9from .format import Format 10from .parse import parse_hypertest_markup 11 12 13def parse_markup(data: str, class_name: str, auto_close: bool = True) -> AST: 14 """Parse a string as a markup document.""" 15 return parse_hypertest_markup(data, class_name, auto_close) 16 17 18class HTMLFormat(Format): 19 """Logic for parsing and compiling html files.""" 20 21 extension: list[str] = ["html", "htm"] 22 23 @classmethod 24 def parse(cls, data: str, auto_close: bool = True) -> str: 25 return parse_markup(data, cls.__name__, auto_close) 26 27 @classmethod 28 def compile( 29 cls, 30 ast: AST, 31 components: Optional[dict[str, dict[str, list | NODE]]] = None, 32 **kwargs, 33 ) -> AST: 34 """Compile and process the given ast and return the resulting ast.""" 35 36 components = components or {} 37 src = deepcopy(ast) 38 39 # 1. Search for all python elements and get source info. 40 # - Remove when done 41 virtual_python = VirtualPython() 42 43 for python_block in find_all(src, {"tag": "python"}): 44 if len(python_block.children) == 1: 45 if python_block.children[0].type == "text": 46 virtual_python += VirtualPython(python_block.children[0].normalized()) 47 48 remove_nodes(src, ["element", {"tag": "python"}]) 49 50 # 2. Replace specific element node with given replacement components 51 # replace_components(src, components, virtual_python, **kwargs) 52 53 # 3. Search each element and find @if, @elif, and @else 54 # - Execute those statements 55 56 apply_conditions(src, virtual_python, components, **kwargs) 57 58 for python_block in find_all(src, {"tag": "python"}): 59 if len(python_block.children) == 1: 60 if python_block.children[0].type == "text": 61 virtual_python += VirtualPython(python_block.children[0].normalized()) 62 63 remove_nodes(src, ["element", {"tag": "python"}]) 64 65 66 # 4. Search for python blocks and process them. 67 68 apply_python(src, virtual_python, **kwargs) 69 remove_nodes(src, {"tag": "slot"}) 70 71 return src 72 73 @classmethod 74 def render( 75 cls, 76 ast: AST, 77 components: Optional[dict[str, dict[str, list | NODE]]] = None, 78 indent: int = 4, 79 **kwargs, 80 ) -> str: 81 indent = indent or 4 82 components = components or {} 83 src = ast 84 85 # 1. Search for all python elements and get source info. 86 # - Remove when done 87 virtual_python = VirtualPython() 88 89 for python_block in find_all(src, {"tag": "python"}): 90 if len(python_block.children) == 1: 91 if python_block.children[0].type == "text": 92 virtual_python += VirtualPython(python_block.children[0].normalized()) 93 94 remove_nodes(src, ["element", {"tag": "python"}]) 95 96 # 2. Replace specific element node with given replacement components 97 # replace_components(src, components, virtual_python, **kwargs) 98 99 # 3. Search each element and find @if, @elif, and @else 100 # - Execute those statements 101 102 apply_conditions(src, virtual_python, components, **kwargs) 103 104 for python_block in find_all(src, {"tag": "python"}): 105 if len(python_block.children) == 1: 106 if python_block.children[0].type == "text": 107 virtual_python += VirtualPython(python_block.children[0].normalized()) 108 109 remove_nodes(src, ["element", {"tag": "python"}]) 110 111 112 # 4. Search for python blocks and process them. 113 114 apply_python(src, virtual_python, **kwargs) 115 remove_nodes(src, {"tag": "slot"}) 116 117 return ASTRenderer(src, indent).compile()
14def parse_markup(data: str, class_name: str, auto_close: bool = True) -> AST: 15 """Parse a string as a markup document.""" 16 return parse_hypertest_markup(data, class_name, auto_close)
Parse a string as a markup document.
19class HTMLFormat(Format): 20 """Logic for parsing and compiling html files.""" 21 22 extension: list[str] = ["html", "htm"] 23 24 @classmethod 25 def parse(cls, data: str, auto_close: bool = True) -> str: 26 return parse_markup(data, cls.__name__, auto_close) 27 28 @classmethod 29 def compile( 30 cls, 31 ast: AST, 32 components: Optional[dict[str, dict[str, list | NODE]]] = None, 33 **kwargs, 34 ) -> AST: 35 """Compile and process the given ast and return the resulting ast.""" 36 37 components = components or {} 38 src = deepcopy(ast) 39 40 # 1. Search for all python elements and get source info. 41 # - Remove when done 42 virtual_python = VirtualPython() 43 44 for python_block in find_all(src, {"tag": "python"}): 45 if len(python_block.children) == 1: 46 if python_block.children[0].type == "text": 47 virtual_python += VirtualPython(python_block.children[0].normalized()) 48 49 remove_nodes(src, ["element", {"tag": "python"}]) 50 51 # 2. Replace specific element node with given replacement components 52 # replace_components(src, components, virtual_python, **kwargs) 53 54 # 3. Search each element and find @if, @elif, and @else 55 # - Execute those statements 56 57 apply_conditions(src, virtual_python, components, **kwargs) 58 59 for python_block in find_all(src, {"tag": "python"}): 60 if len(python_block.children) == 1: 61 if python_block.children[0].type == "text": 62 virtual_python += VirtualPython(python_block.children[0].normalized()) 63 64 remove_nodes(src, ["element", {"tag": "python"}]) 65 66 67 # 4. Search for python blocks and process them. 68 69 apply_python(src, virtual_python, **kwargs) 70 remove_nodes(src, {"tag": "slot"}) 71 72 return src 73 74 @classmethod 75 def render( 76 cls, 77 ast: AST, 78 components: Optional[dict[str, dict[str, list | NODE]]] = None, 79 indent: int = 4, 80 **kwargs, 81 ) -> str: 82 indent = indent or 4 83 components = components or {} 84 src = ast 85 86 # 1. Search for all python elements and get source info. 87 # - Remove when done 88 virtual_python = VirtualPython() 89 90 for python_block in find_all(src, {"tag": "python"}): 91 if len(python_block.children) == 1: 92 if python_block.children[0].type == "text": 93 virtual_python += VirtualPython(python_block.children[0].normalized()) 94 95 remove_nodes(src, ["element", {"tag": "python"}]) 96 97 # 2. Replace specific element node with given replacement components 98 # replace_components(src, components, virtual_python, **kwargs) 99 100 # 3. Search each element and find @if, @elif, and @else 101 # - Execute those statements 102 103 apply_conditions(src, virtual_python, components, **kwargs) 104 105 for python_block in find_all(src, {"tag": "python"}): 106 if len(python_block.children) == 1: 107 if python_block.children[0].type == "text": 108 virtual_python += VirtualPython(python_block.children[0].normalized()) 109 110 remove_nodes(src, ["element", {"tag": "python"}]) 111 112 113 # 4. Search for python blocks and process them. 114 115 apply_python(src, virtual_python, **kwargs) 116 remove_nodes(src, {"tag": "slot"}) 117 118 return ASTRenderer(src, indent).compile()
Logic for parsing and compiling html files.
extension: list[str] = ['html', 'htm']
The extension or extensions for the file format. When writing to a file and extensions is a list then the first extensions in the list is used for the file extension.
@classmethod
def
parse(cls, data: str, auto_close: bool = True) -> str:
24 @classmethod 25 def parse(cls, data: str, auto_close: bool = True) -> str: 26 return parse_markup(data, cls.__name__, auto_close)
Parse the given data into a phml.core.nodes.AST.
@classmethod
def
compile( cls, ast: phml.core.nodes.AST.AST, components: Optional[dict[str, dict[str, list | phml.core.nodes.nodes.Root | phml.core.nodes.nodes.Element | phml.core.nodes.nodes.Text | phml.core.nodes.nodes.Comment | phml.core.nodes.nodes.DocType | phml.core.nodes.nodes.Parent | phml.core.nodes.nodes.Node | phml.core.nodes.nodes.Literal]]] = None, **kwargs) -> phml.core.nodes.AST.AST:
28 @classmethod 29 def compile( 30 cls, 31 ast: AST, 32 components: Optional[dict[str, dict[str, list | NODE]]] = None, 33 **kwargs, 34 ) -> AST: 35 """Compile and process the given ast and return the resulting ast.""" 36 37 components = components or {} 38 src = deepcopy(ast) 39 40 # 1. Search for all python elements and get source info. 41 # - Remove when done 42 virtual_python = VirtualPython() 43 44 for python_block in find_all(src, {"tag": "python"}): 45 if len(python_block.children) == 1: 46 if python_block.children[0].type == "text": 47 virtual_python += VirtualPython(python_block.children[0].normalized()) 48 49 remove_nodes(src, ["element", {"tag": "python"}]) 50 51 # 2. Replace specific element node with given replacement components 52 # replace_components(src, components, virtual_python, **kwargs) 53 54 # 3. Search each element and find @if, @elif, and @else 55 # - Execute those statements 56 57 apply_conditions(src, virtual_python, components, **kwargs) 58 59 for python_block in find_all(src, {"tag": "python"}): 60 if len(python_block.children) == 1: 61 if python_block.children[0].type == "text": 62 virtual_python += VirtualPython(python_block.children[0].normalized()) 63 64 remove_nodes(src, ["element", {"tag": "python"}]) 65 66 67 # 4. Search for python blocks and process them. 68 69 apply_python(src, virtual_python, **kwargs) 70 remove_nodes(src, {"tag": "slot"}) 71 72 return src
Compile and process the given ast and return the resulting ast.
@classmethod
def
render( cls, ast: phml.core.nodes.AST.AST, components: Optional[dict[str, dict[str, list | phml.core.nodes.nodes.Root | phml.core.nodes.nodes.Element | phml.core.nodes.nodes.Text | phml.core.nodes.nodes.Comment | phml.core.nodes.nodes.DocType | phml.core.nodes.nodes.Parent | phml.core.nodes.nodes.Node | phml.core.nodes.nodes.Literal]]] = None, indent: int = 4, **kwargs) -> str:
74 @classmethod 75 def render( 76 cls, 77 ast: AST, 78 components: Optional[dict[str, dict[str, list | NODE]]] = None, 79 indent: int = 4, 80 **kwargs, 81 ) -> str: 82 indent = indent or 4 83 components = components or {} 84 src = ast 85 86 # 1. Search for all python elements and get source info. 87 # - Remove when done 88 virtual_python = VirtualPython() 89 90 for python_block in find_all(src, {"tag": "python"}): 91 if len(python_block.children) == 1: 92 if python_block.children[0].type == "text": 93 virtual_python += VirtualPython(python_block.children[0].normalized()) 94 95 remove_nodes(src, ["element", {"tag": "python"}]) 96 97 # 2. Replace specific element node with given replacement components 98 # replace_components(src, components, virtual_python, **kwargs) 99 100 # 3. Search each element and find @if, @elif, and @else 101 # - Execute those statements 102 103 apply_conditions(src, virtual_python, components, **kwargs) 104 105 for python_block in find_all(src, {"tag": "python"}): 106 if len(python_block.children) == 1: 107 if python_block.children[0].type == "text": 108 virtual_python += VirtualPython(python_block.children[0].normalized()) 109 110 remove_nodes(src, ["element", {"tag": "python"}]) 111 112 113 # 4. Search for python blocks and process them. 114 115 apply_python(src, virtual_python, **kwargs) 116 remove_nodes(src, {"tag": "slot"}) 117 118 return ASTRenderer(src, indent).compile()
Compile the given phml.core.nodes.AST into string of a given format.