Skip to content

markup

markup #

The HTML a page is written in: one element helper, escaped text, and the document shell.

  1. element writes one tag around already-rendered children; text is the only way a string becomes content, so every value passes through html.escape; inline_json is the only way data enters a <script>.
  2. document wraps a rendered body in the shell every page shares — charset, viewport, title, and the one stylesheet the standard components lay out with.

Attributes = Mapping[str, str | float | bool | None] #

Attribute values: None omits the attribute, True writes it bare, False omits it.

document(title, body) #

A complete HTML page: the shared head, title when given, body inside <main>.

document("Plant Journal", element("p", None, text("hello")))
Source code in capturegraph-lib/capturegraph/ui/markup.py
def document(title: str | None, body: str) -> str:
    """A complete HTML page: the shared head, ``title`` when given, ``body`` inside ``<main>``.

    ```python
    document("Plant Journal", element("p", None, text("hello")))
    ```
    """
    head = [
        element("meta", {"charset": "utf-8"}),
        element("meta", {"name": "viewport", "content": "width=device-width, initial-scale=1"}),
    ]
    if title is not None:
        head.append(element("title", None, text(title)))
    head.append(element("style", None, STYLE))
    return (
        "<!doctype html>\n"
        + element(
            "html",
            {"lang": "en"},
            element("head", None, "\n".join(head)),
            element("body", None, element("main", None, body)),
        )
        + "\n"
    )

element(tag, attributes=None, *children) #

<tag …>children</tag> — attributes escaped, children already HTML.

assert element("a", {"href": "../"}, text("Up")) == '<a href="../">Up</a>'
assert element("img", {"src": "files/0.jpeg", "alt": None}) == '<img src="files/0.jpeg">'
Source code in capturegraph-lib/capturegraph/ui/markup.py
def element(tag: str, attributes: Attributes | None = None, *children: str) -> str:
    """``<tag …>children</tag>`` — attributes escaped, ``children`` already HTML.

    ```python
    assert element("a", {"href": "../"}, text("Up")) == '<a href="../">Up</a>'
    assert element("img", {"src": "files/0.jpeg", "alt": None}) == '<img src="files/0.jpeg">'
    ```
    """
    attribute_text = "".join(_attribute(name, value) for name, value in (attributes or {}).items())
    if tag in VOID_TAGS:
        return f"<{tag}{attribute_text}>"
    return f"<{tag}{attribute_text}>{''.join(children)}</{tag}>"

inline_json(value) #

value as a JSON literal safe inside a <script> element.

assert inline_json({"t": "</script>"}) == '{"t": "<\\/script>"}'
Source code in capturegraph-lib/capturegraph/ui/markup.py
def inline_json(value: JSONValue) -> str:
    r"""``value`` as a JSON literal safe inside a ``<script>`` element.

    ```python
    assert inline_json({"t": "</script>"}) == '{"t": "<\\/script>"}'
    ```
    """
    return json.dumps(value).replace("</", "<\\/")

picture(src, caption, href=None) #

A <figure> of one image, captioned, wrapped in a link when href is given.

picture("files/0.jpeg", "Noon", "../sessions/0006380070917400/")
Source code in capturegraph-lib/capturegraph/ui/markup.py
def picture(src: str, caption: str | None, href: str | None = None) -> str:
    """A ``<figure>`` of one image, captioned, wrapped in a link when ``href`` is given.

    ```python
    picture("files/0.jpeg", "Noon", "../sessions/0006380070917400/")
    ```
    """
    image = element("img", {"src": src, "alt": caption or "", "loading": "lazy"})
    if href is not None:
        image = element("a", {"href": href}, image)
    parts = [image]
    if caption is not None:
        parts.append(element("figcaption", None, text(caption)))
    return element("figure", {"class": "cg-picture"}, *parts)

text(value) #

value as escaped text content.

assert text("<b> & co") == "&lt;b&gt; &amp; co"
Source code in capturegraph-lib/capturegraph/ui/markup.py
def text(value: object) -> str:
    """``value`` as escaped text content.

    ```python
    assert text("<b> & co") == "&lt;b&gt; &amp; co"
    ```
    """
    return html.escape(str(value), quote=False)