52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import date, datetime
|
|
from html import escape
|
|
from typing import Any
|
|
|
|
|
|
def text(value: Any) -> str:
|
|
if value is None or value == "":
|
|
return "nicht erfasst"
|
|
if isinstance(value, (date, datetime)):
|
|
return value.strftime("%d.%m.%Y")
|
|
return escape(str(value))
|
|
|
|
|
|
def paragraph(value: Any) -> str:
|
|
content = text(value)
|
|
return content.replace("\n", "<br>")
|
|
|
|
|
|
def yes_no(value: Any) -> str:
|
|
labels = {"yes": "Ja", "no": "Nein", "na": "Nicht zutreffend", True: "Ja", False: "Nein"}
|
|
return text(labels.get(value, value))
|
|
|
|
|
|
def definition_list(rows: list[tuple[str, Any]]) -> str:
|
|
items = "".join(
|
|
f"<div class=\"definition-row\"><dt>{text(label)}</dt><dd>{paragraph(value)}</dd></div>"
|
|
for label, value in rows
|
|
if value not in (None, "", [])
|
|
)
|
|
return f"<dl class=\"definition-list\">{items}</dl>"
|
|
|
|
|
|
def table(headers: list[str], rows: list[list[Any]], css_class: str = "") -> str:
|
|
head = "".join(f"<th>{text(header)}</th>" for header in headers)
|
|
body = "".join(
|
|
"<tr>" + "".join(f"<td>{paragraph(cell)}</td>" for cell in row) + "</tr>"
|
|
for row in rows
|
|
)
|
|
return f"<table class=\"data-table {css_class}\"><thead><tr>{head}</tr></thead><tbody>{body}</tbody></table>"
|
|
|
|
|
|
def section(chapter_id: str, title: str, body: str, bookmark_label: str | None = None) -> str:
|
|
bookmark_attr = (
|
|
f' data-bookmark-label="{text(bookmark_label)}"' if bookmark_label is not None else ""
|
|
)
|
|
heading = bookmark_label or title
|
|
return (
|
|
f'<section class="chapter" id="{text(chapter_id)}">'
|
|
f'<h2 class="chapter-title"{bookmark_attr}>{text(heading)}</h2>{body}</section>'
|
|
)
|