feat: notification markup support

This commit is contained in:
2026-05-04 23:05:23 +02:00
parent 5e8f9e44bb
commit 4a271ac4d8
3 changed files with 37 additions and 2 deletions

28
sims/utils/markup.py Normal file
View File

@@ -0,0 +1,28 @@
import re
from html import escape as html_escape
import gi
gi.require_version("Pango", "1.0")
from gi.repository import GLib, Pango
# Pango cannot render <img ...> from the freedesktop notification spec; strip it.
_IMG_RE = re.compile(r"<img\b[^>]*/?>", re.IGNORECASE)
def render_body_markup(body: str) -> tuple[str, bool]:
"""Return ``(text, is_markup)`` for a notification body.
If the body parses as Pango markup, ``text`` is the cleaned-up markup
string and ``is_markup`` is True. Otherwise ``text`` is the XML-escaped
plain text and ``is_markup`` is False.
"""
if not body:
return "", False
candidate = _IMG_RE.sub("", body)
try:
Pango.parse_markup(candidate, -1, "\0")
except GLib.Error:
return html_escape(body, quote=False), False
return candidate, True

View File

@@ -6,6 +6,8 @@ from fabric.widgets.image import Image
from fabric.widgets.label import Label from fabric.widgets.label import Label
from gi.repository import GdkPixbuf from gi.repository import GdkPixbuf
from sims.utils.markup import render_body_markup
NOTIFICATION_IMAGE_SIZE = 64 NOTIFICATION_IMAGE_SIZE = 64
@@ -76,9 +78,11 @@ class NotificationWidget(Box):
) )
if body: if body:
body_text, body_is_markup = render_body_markup(body)
body_kwargs = {"markup": body_text} if body_is_markup else {"label": body_text}
text_children.append( text_children.append(
Label( Label(
label=body, **body_kwargs,
line_wrap="word-char", line_wrap="word-char",
v_align="start", v_align="start",
h_align="start", h_align="start",

View File

@@ -7,6 +7,7 @@ from fabric.widgets.image import Image
from fabric.widgets.label import Label from fabric.widgets.label import Label
from sims.services.notification_history import HistoryEntry from sims.services.notification_history import HistoryEntry
from sims.utils.markup import render_body_markup
def _time_ago(ts: float, now: float | None = None) -> str: def _time_ago(ts: float, now: float | None = None) -> str:
@@ -71,9 +72,11 @@ class NotificationHistoryEntryWidget(Box):
text_children.append(header) text_children.append(header)
if entry.body: if entry.body:
body_text, body_is_markup = render_body_markup(entry.body)
body_kwargs = {"markup": body_text} if body_is_markup else {"label": body_text}
text_children.append( text_children.append(
Label( Label(
label=entry.body, **body_kwargs,
line_wrap="word-char", line_wrap="word-char",
h_align="start", h_align="start",
v_align="start", v_align="start",