diff options
Diffstat (limited to 'mu4web/html_render.py')
-rw-r--r-- | mu4web/html_render.py | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/mu4web/html_render.py b/mu4web/html_render.py new file mode 100644 index 0000000..99140ad --- /dev/null +++ b/mu4web/html_render.py @@ -0,0 +1,71 @@ +import html +from typing import ( + Callable, + TypeAlias, + Union, +) + +HTML: TypeAlias = Union[tuple, + list['HTML'], + Callable[[], str], + None, str, int, float] + + +standalones = ['hr', 'br', 'meta'] +"""Tags which can't have a closing tag.""" + + +def _render_document(document: HTML) -> str: + if isinstance(document, tuple): + tag, *body = document + if body and isinstance(body[0], dict): + print(body[0]) + attributes = ' '.join(f'{a}="{html.escape(b)}"' + for a, b in body[0].items()) + body = body[1:] + start = f'<{tag} {attributes}>' + else: + start = f'<{tag}>' + + if tag in standalones: + return start + else: + if body: + items = ''.join(_render_document(b) for b in body) + else: + items = '' + return start + f'{items}</{tag}>' + elif callable(document): + return str(document()) + elif isinstance(document, list): + return ''.join(_render_document(e) for e in document) + elif document is None: + return '' + else: + # strings, and everything else + return html.escape(str(document)) + + +def render_document(document: HTML) -> str: + """ + Render an HTML structure to an Html string. + + The following Python types are converted as follows: + - Tuples + - The first value becomes the tags name + - The second value, if a dictionary, becomes the tags attributes + - All following values (including the second if not a dictionary) + gets individually passed to render_document. + - Lists + Each element gets passed to render_document + - Callable[[], str] + Gets called, and its output is included verbatim. Useful for + including strings which shouldn't be escaped. + - str + Gets escaped, and included + - int, float + Gets included as their default string representation. + - None + Becomes an empty string + """ + return '<!doctype html>\n' + _render_document(document) |