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

Parse a string as a markup document.

class HTMLFormat(phml.core.formats.format.Format):
 22class HTMLFormat(Format):
 23    """Logic for parsing and compiling html files."""
 24
 25    extension: list[str] = ["html", "htm"]
 26
 27    @classmethod
 28    def parse(cls, data: str, auto_close: bool = True) -> str:
 29        return parse_markup(data, cls.__name__, auto_close)
 30
 31    @classmethod
 32    def compile(
 33        cls,
 34        ast: AST,
 35        config: Config,
 36        components: Optional[dict[str, dict[str, list | NODE]]] = None,
 37        **kwargs,
 38    ) -> AST:
 39        """Compile and process the given ast and return the resulting ast."""
 40
 41        components = components or {}
 42        src = deepcopy(ast)
 43
 44        # 1. Search for all python elements and get source info.
 45        #    - Remove when done
 46        virtual_python = VirtualPython()
 47
 48        for python_block in find_all(src, {"tag": "python"}):
 49            if (
 50                len(python_block.children) == 1
 51                and python_block.children[0].type == "text"
 52            ):
 53                virtual_python += VirtualPython(
 54                    python_block.children[0].normalized(),
 55                    context={**kwargs}
 56                )
 57
 58        remove_nodes(src, ["element", {"tag": "python"}])
 59
 60        # 2. Replace specific element node with given replacement components
 61        # replace_components(src, components, virtual_python, **kwargs)
 62
 63        # 3. Search each element and find @if, @elif, and @else
 64        #    - Execute those statements
 65
 66        apply_conditions(src, config, virtual_python, components, **kwargs)
 67
 68        for python_block in find_all(src, {"tag": "python"}):
 69            if (
 70                len(python_block.children) == 1
 71                and python_block.children[0].type == "text"
 72            ):
 73                virtual_python += VirtualPython(
 74                    python_block.children[0].normalized(),
 75                    context={**kwargs}
 76                )
 77
 78        remove_nodes(src, ["element", {"tag": "python"}])
 79
 80        # 4. Search for python blocks and process them.
 81
 82        apply_python(src, virtual_python, **kwargs)
 83        remove_nodes(src, {"tag": "slot"})
 84
 85        return src
 86
 87    @classmethod
 88    def render(
 89        cls,
 90        ast: AST,
 91        config: Config,
 92        components: Optional[dict[str, dict[str, list | NODE]]] = None,
 93        indent: int = 4,
 94        **kwargs,
 95    ) -> str:
 96        indent = indent or 4
 97        components = components or {}
 98        src = ast
 99
100        # 1. Search for all python elements and get source info.
101        #    - Remove when done
102        virtual_python = VirtualPython()
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        # 2. Replace specific element node with given replacement components
112        # replace_components(src, components, virtual_python, **kwargs)
113
114        # 3. Search each element and find @if, @elif, and @else
115        #    - Execute those statements
116
117        apply_conditions(src, config, virtual_python, components, **kwargs)
118
119        for python_block in find_all(src, {"tag": "python"}):
120            if len(python_block.children) == 1:
121                if python_block.children[0].type == "text":
122                    virtual_python += VirtualPython(python_block.children[0].normalized())
123
124        remove_nodes(src, ["element", {"tag": "python"}])
125
126        # 4. Search for python blocks and process them.
127
128        apply_python(src, virtual_python, **kwargs)
129        remove_nodes(src, {"tag": "slot"})
130
131        return ASTRenderer(src, indent).compile()

Logic for parsing and compiling html files.

HTMLFormat()
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:
27    @classmethod
28    def parse(cls, data: str, auto_close: bool = True) -> str:
29        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, config: dict[typing.Literal['enabled'], dict[typing.Literal['html', 'markdown'], bool]], 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:
31    @classmethod
32    def compile(
33        cls,
34        ast: AST,
35        config: Config,
36        components: Optional[dict[str, dict[str, list | NODE]]] = None,
37        **kwargs,
38    ) -> AST:
39        """Compile and process the given ast and return the resulting ast."""
40
41        components = components or {}
42        src = deepcopy(ast)
43
44        # 1. Search for all python elements and get source info.
45        #    - Remove when done
46        virtual_python = VirtualPython()
47
48        for python_block in find_all(src, {"tag": "python"}):
49            if (
50                len(python_block.children) == 1
51                and python_block.children[0].type == "text"
52            ):
53                virtual_python += VirtualPython(
54                    python_block.children[0].normalized(),
55                    context={**kwargs}
56                )
57
58        remove_nodes(src, ["element", {"tag": "python"}])
59
60        # 2. Replace specific element node with given replacement components
61        # replace_components(src, components, virtual_python, **kwargs)
62
63        # 3. Search each element and find @if, @elif, and @else
64        #    - Execute those statements
65
66        apply_conditions(src, config, virtual_python, components, **kwargs)
67
68        for python_block in find_all(src, {"tag": "python"}):
69            if (
70                len(python_block.children) == 1
71                and python_block.children[0].type == "text"
72            ):
73                virtual_python += VirtualPython(
74                    python_block.children[0].normalized(),
75                    context={**kwargs}
76                )
77
78        remove_nodes(src, ["element", {"tag": "python"}])
79
80        # 4. Search for python blocks and process them.
81
82        apply_python(src, virtual_python, **kwargs)
83        remove_nodes(src, {"tag": "slot"})
84
85        return src

Compile and process the given ast and return the resulting ast.

@classmethod
def render( cls, ast: phml.core.nodes.AST.AST, config: dict[typing.Literal['enabled'], dict[typing.Literal['html', 'markdown'], bool]], 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:
 87    @classmethod
 88    def render(
 89        cls,
 90        ast: AST,
 91        config: Config,
 92        components: Optional[dict[str, dict[str, list | NODE]]] = None,
 93        indent: int = 4,
 94        **kwargs,
 95    ) -> str:
 96        indent = indent or 4
 97        components = components or {}
 98        src = ast
 99
100        # 1. Search for all python elements and get source info.
101        #    - Remove when done
102        virtual_python = VirtualPython()
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        # 2. Replace specific element node with given replacement components
112        # replace_components(src, components, virtual_python, **kwargs)
113
114        # 3. Search each element and find @if, @elif, and @else
115        #    - Execute those statements
116
117        apply_conditions(src, config, virtual_python, components, **kwargs)
118
119        for python_block in find_all(src, {"tag": "python"}):
120            if len(python_block.children) == 1:
121                if python_block.children[0].type == "text":
122                    virtual_python += VirtualPython(python_block.children[0].normalized())
123
124        remove_nodes(src, ["element", {"tag": "python"}])
125
126        # 4. Search for python blocks and process them.
127
128        apply_python(src, virtual_python, **kwargs)
129        remove_nodes(src, {"tag": "slot"})
130
131        return ASTRenderer(src, indent).compile()

Compile the given phml.core.nodes.AST into string of a given format.