aboutsummaryrefslogtreecommitdiff
path: root/mu4web/html_render.py
diff options
context:
space:
mode:
Diffstat (limited to 'mu4web/html_render.py')
-rw-r--r--mu4web/html_render.py71
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)