Source code for pyicat_plus.utils.html_utils
import html
_SELF_CLOSING = {"br", "img", "hr", "meta", "link", "input"}
def _normalize_attr_name(name):
if name.endswith("_"):
name = name[:-1]
if name.startswith("_"):
name = name[1:]
return name
def _format_attrs(attrs):
if not attrs:
return ""
parts = []
for key, value in attrs.items():
if value is None:
continue
key = _normalize_attr_name(key)
value = html.escape(str(value), quote=True)
parts.append(f' {key}="{value}"')
return "".join(parts)
class _Tag:
def __init__(self, page, name):
self._page = page
self._name = name
def __call__(self, *content, **attrs):
attr_text = _format_attrs(attrs)
if self._name in _SELF_CLOSING:
self._page._append(f"<{self._name}{attr_text} />")
return None
if content:
inner = "".join(str(part) for part in content)
self._page._append(f"<{self._name}{attr_text}>{inner}</{self._name}>")
return None
self._page._append(f"<{self._name}{attr_text}>")
return None
def close(self):
if self._name in _SELF_CLOSING:
return None
self._page._append(f"</{self._name}>")
return None
[docs]
class HtmlPage:
def __init__(self, mode=None):
self._parts = []
self._title = ""
self._footer = ""
self._mode = mode
self._init_called = False
def _append(self, text):
self._parts.append(text)
[docs]
def init(self, title="", footer=""):
self._title = title
self._footer = footer
self._init_called = True
[docs]
def escape(self, text):
return html.escape(str(text), quote=True)
def __getattr__(self, name):
if name.startswith("_"):
raise AttributeError(name)
tag = _Tag(self, name)
self.__dict__[name] = tag
return tag
def __str__(self):
title = html.escape(self._title, quote=True) if self._title else ""
footer = html.escape(self._footer, quote=True) if self._footer else ""
parts = [
"<!DOCTYPE html>",
"<html>",
"<head>",
'<meta charset="utf-8" />',
]
if title:
parts.append(f"<title>{title}</title>")
parts.extend(["</head>", "<body>"])
parts.extend(self._parts)
if footer:
parts.append(f'<div class="footer">{footer}</div>')
parts.extend(["</body>", "</html>"])
return "\n".join(parts)