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)