Matrix: send formatted bodies, and m.emote #54

Closed
opened 2026-08-29 10:58:24 -04:00 by Salastil · 1 comment
Owner

Inbound is done (#50): a Matrix message carrying formatted_body is now shown with its own formatting. Outgoing is still plain m.text.

Saying it in HTML means turning what somebody typed into HTML. There is no markdown parser in the daemon to do that, and adding one is the actual work here - a hand-rolled converter would be a worse thing than a plain message, which is valid Matrix and renders correctly in every client.

Worth noting the frontend already has half of it: lib/format.ts turns BBCode and markdown into the restricted HTML that lib/richtext.tsx renders. If sending formatted text is wanted, the cheapest honest route is probably to reuse that on the way out rather than to teach the daemon markdown.

Also missing on the same path: outgoing m.emote. /me is read inbound (msgtype == "m.emote") but send_message always sends m.text, so an action sent from moho arrives as an ordinary line.


Filed from a protocol coverage survey.

Inbound is done (#50): a Matrix message carrying `formatted_body` is now shown with its own formatting. Outgoing is still plain `m.text`. Saying it in HTML means turning what somebody typed into HTML. There is no markdown parser in the daemon to do that, and adding one is the actual work here - a hand-rolled converter would be a worse thing than a plain message, which is valid Matrix and renders correctly in every client. Worth noting the frontend already has half of it: `lib/format.ts` turns BBCode and markdown into the restricted HTML that `lib/richtext.tsx` renders. If sending formatted text is wanted, the cheapest honest route is probably to reuse that on the way out rather than to teach the daemon markdown. Also missing on the same path: outgoing `m.emote`. `/me` is read inbound (`msgtype == "m.emote"`) but `send_message` always sends `m.text`, so an action sent from moho arrives as an ordinary line. --- _Filed from a protocol coverage survey._
Salastil added the feature label 2026-08-29 10:58:24 -04:00
Author
Owner

Finished — nobilis 1c16051

Both halves. /me sends m.emote (with // escaping a literal leading slash, as the IRC box does), and messages carry a formatted_body when there is formatting to carry.

The converter is a bounded subset rather than the markdown parser this issue assumed was needed: code fences, inline code, bold, italic, strike, line breaks. Everything else is left exactly as typed, which is the contract - headings and lists are document structure, and a chat line becoming one because it started with a hyphen is a surprise nobody asked for. Nothing is sent unless the formatting says something the plain body does not.

Edits carry it as well, and that shape is now built in one place for encrypted and unencrypted rooms - two copies is how a formatted body would have reached one and not the other.

Finished — nobilis [`1c16051`](https://git.salastil.com/Salastil/nobilis/commit/1c16051) Both halves. `/me` sends `m.emote` (with `//` escaping a literal leading slash, as the IRC box does), and messages carry a `formatted_body` when there is formatting to carry. The converter is a bounded subset rather than the markdown parser this issue assumed was needed: code fences, inline code, bold, italic, strike, line breaks. Everything else is left exactly as typed, which is the contract - headings and lists are document structure, and a chat line becoming one because it started with a hyphen is a surprise nobody asked for. Nothing is sent unless the formatting says something the plain body does not. Edits carry it as well, and that shape is now built in one place for encrypted and unencrypted rooms - two copies is how a formatted body would have reached one and not the other.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Salastil/moho#54