Mobile chat renders message bodies as plain text. ThreadMessageItem.tsx puts the body in a bare <Text> via renderTextWithBoldMentions, which does linkify, emoji and bold @mentions and nothing else. Web renders the same messages as markdown, so formatting a message on desktop and reading it on mobile shows raw ** and backticks.
What web does
features/chat/hooks/use-message-rendering.tsx runs simpleMarkdownToHTML from @ecency/render-helper, sanitizes with DOMPurify, and renders Ecency post links through a dedicated card component.
Scope
Use the same simpleMarkdownToHTML so both clients share one definition of what chat markdown means, and render the result with react-native-render-html. Both are already dependencies (@ecency/render-helper ^2.5.23, react-native-render-html ^6.3.4), so no new packages.
Deliberately simpleMarkdownToHTML and not the full post renderer in postParser.tsx: chat is a lighter subset and should not diverge from web.
Must not regress
The existing chat rendering does several things the markdown path has to keep:
- linkify, including the Ecency profile link shortening in
setLinkText
- emoji substitution via
emojifyMessage
- bold
@mentions with the tap-to-open-profile behaviour
- image extraction in
parseMessageContent (images are pulled out of the body and rendered separately)
- the tap targets and long-press actions on the message row
Worth checking during implementation
- Angle brackets get eaten. Once a body goes through an HTML renderer, literal
<user> in a message is parsed as an unknown tag and disappears. The moderation bot posts help text containing !ban <user> [30d], so this is a live case, not hypothetical.
- Sanitization.
react-native-render-html will not execute scripts, but the allowed tag and attribute set should still be constrained rather than left at the default.
- List performance. Chat threads are long and virtualized; per-message HTML parsing is heavier than a
<Text>. Worth measuring on a long channel before and after, and memoizing per message id.
Related: the moderation commands in ecency/vision-web#1380 currently reply in plain text specifically because this renderer does not exist yet.
Mobile chat renders message bodies as plain text.
ThreadMessageItem.tsxputs the body in a bare<Text>viarenderTextWithBoldMentions, which does linkify, emoji and bold @mentions and nothing else. Web renders the same messages as markdown, so formatting a message on desktop and reading it on mobile shows raw**and backticks.What web does
features/chat/hooks/use-message-rendering.tsxrunssimpleMarkdownToHTMLfrom@ecency/render-helper, sanitizes with DOMPurify, and renders Ecency post links through a dedicated card component.Scope
Use the same
simpleMarkdownToHTMLso both clients share one definition of what chat markdown means, and render the result withreact-native-render-html. Both are already dependencies (@ecency/render-helper^2.5.23,react-native-render-html^6.3.4), so no new packages.Deliberately
simpleMarkdownToHTMLand not the full post renderer inpostParser.tsx: chat is a lighter subset and should not diverge from web.Must not regress
The existing chat rendering does several things the markdown path has to keep:
setLinkTextemojifyMessage@mentionswith the tap-to-open-profile behaviourparseMessageContent(images are pulled out of the body and rendered separately)Worth checking during implementation
<user>in a message is parsed as an unknown tag and disappears. The moderation bot posts help text containing!ban <user> [30d], so this is a live case, not hypothetical.react-native-render-htmlwill not execute scripts, but the allowed tag and attribute set should still be constrained rather than left at the default.<Text>. Worth measuring on a long channel before and after, and memoizing per message id.Related: the moderation commands in ecency/vision-web#1380 currently reply in plain text specifically because this renderer does not exist yet.