import html
from collections.abc import Callable
from ..defaults import DEFAULT_PROP, resolve_defaults
from .html import Html
from .mixins.label_element import LabelElement
class ChatMessage(LabelElement):
@resolve_defaults
def __init__(self,
text: str | list[str] | None = None,
name: str | None = DEFAULT_PROP | None,
label: str | None = DEFAULT_PROP | None,
stamp: str | None = DEFAULT_PROP | None,
avatar: str | None = DEFAULT_PROP | None,
sent: bool = DEFAULT_PROP | False,
text_html: bool = False,
sanitize: Callable[[str], str] | bool = True,
) -> None:
"""Chat Message
Based on Quasar's `Chat Message `_ component.
:param text: the message body (can be a list of strings for multiple message parts)
:param name: the name of the message author
:param label: renders a label header/section only
:param stamp: timestamp of the message
:param avatar: URL to an avatar
:param sent: render as a sent message (so from current user) (default: ``False``)
:param text_html: render text as HTML (default: ``False``)
:param sanitize: sanitization mode (only relevant when ``text_html=True``):
``True`` (default) uses client-side sanitization via DOMPurify,
``False`` disables sanitization (use only with trusted content),
or pass a callable to apply server-side sanitization
"""
if sanitize is None:
raise TypeError('`sanitize` must be `True`, `False` or a callable; `None` is no longer supported')
super().__init__(tag='q-chat-message', label=label)
if text is None:
text = []
if isinstance(text, str):
text = [text]
self._original_text = list(text)
if not text_html:
text = [html.escape(part) for part in text]
text = [part.replace('\n', '
') for part in text]
sanitize = False
self._props.set_optional('name', name)
self._props.set_optional('stamp', stamp)
self._props.set_optional('avatar', avatar)
self._props['sent'] = sent
with self:
for line in text:
Html(line, sanitize=sanitize)
def _render_markdown(self) -> str:
name = self._props.get('name', '')
text = '\n'.join(self._original_text)
return f'**{name}**: {text}' if name else text
def _displayed_contents(self, *, only_visible: bool) -> list:
return [*super()._displayed_contents(only_visible=only_visible), self._props.get('name')]