62 lines
1.8 KiB
Python
62 lines
1.8 KiB
Python
from typing import Any
|
|
|
|
CELL_GAP = " | "
|
|
_TEXT_KEYS = ("summary", "text", "expression", "credit")
|
|
_INLINE_KEYS = ("text", "alternative_text", "expression")
|
|
|
|
|
|
def _button(button: dict[str, Any]) -> str:
|
|
label = _inline(button.get("text"))
|
|
url = button.get("url")
|
|
return f"{label} ({url})" if isinstance(url, str) else label
|
|
|
|
|
|
def _inline(value: object) -> str:
|
|
if isinstance(value, str):
|
|
return value
|
|
if isinstance(value, list):
|
|
return "".join(_inline(item) for item in value)
|
|
if not isinstance(value, dict):
|
|
return ""
|
|
button = value.get("button")
|
|
if isinstance(button, dict):
|
|
return _button(button)
|
|
return next((_inline(value[key]) for key in _INLINE_KEYS if key in value), "")
|
|
|
|
|
|
def _children(block: dict[str, Any], key: str) -> list[Any]:
|
|
value = block.get(key)
|
|
return value if isinstance(value, list) else []
|
|
|
|
|
|
def _row(row: object) -> str:
|
|
cells = row if isinstance(row, list) else []
|
|
return CELL_GAP.join(
|
|
_inline(cell.get("text")) for cell in cells if isinstance(cell, dict)
|
|
)
|
|
|
|
|
|
def _block(block: object) -> list[str]:
|
|
if not isinstance(block, dict):
|
|
return []
|
|
lines = [_inline(block[key]) for key in _TEXT_KEYS if key in block]
|
|
lines += [_row(row) for row in _children(block, "cells")]
|
|
lines += [
|
|
_button(button)
|
|
for button in _children(block, "buttons")
|
|
if isinstance(button, dict)
|
|
]
|
|
for key in ("items", "blocks"):
|
|
for child in _children(block, key):
|
|
lines += _block(child)
|
|
lines += _block(block.get("caption"))
|
|
lines = [line for line in lines if line]
|
|
label = block.get("label")
|
|
if isinstance(label, str) and lines:
|
|
lines[0] = f"{label} {lines[0]}"
|
|
return lines
|
|
|
|
|
|
def rich_text(rich: object) -> str | None:
|
|
return "\n".join(_block(rich)) or None
|