diff --git a/proposals/3765-rich-room-topics.md b/proposals/3765-rich-room-topics.md new file mode 100644 index 0000000000..ed84737e2a --- /dev/null +++ b/proposals/3765-rich-room-topics.md @@ -0,0 +1,132 @@ +# MSC3765: Rich text in room topics + +## Problem + +Topics are a central piece of room meta data and usually made easily +accessible to room members in clients. As a result, room administrators +often extend the use of topics to collect helpful peripheral information +that is related to the room’s purpose. Most commonly these are links to +external resources. At the moment, topics are limited to [plain text] +which, depending on the number and length of URLs and other content, +easily gets inconvenient to consume and calls for richer text formatting +options. + +## Proposal + +Drawing from extensible events as described in [MSC1767], a new content +block `m.topic` is defined, which wraps an `m.text` content block that +allows representing the room topic in different mime types. In current +room versions, this content block is added to the content of [`m.room.topic`] +events as shown below[^1]. + +```json5 +{ + "type": "m.room.topic", + "state_key": "", + "content": { + "m.topic": { + "m.text": [ { + "mimetype": "text/html", + "body": "All about pizza | Recipes" + }, { + "body": "All about **pizza** | [Recipes](https://recipes.pizza.net)" + }] + }, + "topic": "All about **pizza** | [Recipes](https://recipes.pizza.net)" + }, + ... +} +``` + +In line with [MSC1767], clients should render the first mime type in the +array that they understand. Further details of how `m.text` works may +be found in [MSC1767] and are not repeated here. + +The wrapping `m.topic` content block is similar to `m.caption` for file +uploads as defined in [MSC3551]. It avoids clients accidentally rendering +the topic as a room message. ([MSC1767] specifies that unknown events with +an `m.text` content block should be rendered as a regular room message, and +while [MSC1767] had explicitly excluded state events from being treated as +extensible, this is being changed with [MSC4252].) The extra content block, therefore, allows putting +a fallback representation that is actually designated for the timeline +into a separate `content['m.text']` field. In addition, the `m.topic` content +block also serves as a good place for additional fields to be added by +other MSCs in the future. + +It is recommended that clients always include a plain text variant within `m.text` when +sending `m.room.topic` events. This prevents bad UX in situations where a plain +text topic is sufficient such as the public rooms directory. + +Additionally, clients should duplicate the plain text topic into the existing +`topic` field for backwards compatibility with clients that don't support +`m.topic` yet. This also helps prevent inconsistencies since such clients +are likely to delete the `m.topic` content block when updating `m.room.topic` +themselves. + +In order to prevent formatting abuse in room topics, clients are +encouraged to limit the length of topics during both entry and display, +for instance, by capping the number of displayed lines. Additionally, +clients should ignore things like headings and enumerations (or format them +as regular text). A future MSC may introduce a mechanism to capture extended +multiline details that are not suitable for room topics in a separate field +or event type. + +On the server side, any logic that currently operates on the `topic` field is +updated to use the `m.topic` content block instead: + +- In [`/_matrix/client/v3/createRoom`], the `topic` parameter should cause `m.room.topic` + to be written with a `text/plain` mimetype in `m.topic`. If at the same time an + `m.room.topic` event is supplied in `initial_state`, it is overwritten entirely. + A future MSC may generalize the `topic` parameter to allow specifying other mime + types without `initial_state`. +- In [`GET /_matrix/client/v3/publicRooms`], [`GET /_matrix/federation/v1/publicRooms`] + and their `POST` siblings, the `topic` response field should be read from the + `text/plain` mimetype of `m.topic` if it exists or omitted otherwise. + A plain text topic is sufficient here because this data is commonly + only displayed to users that are *not* a member of the room yet. These + users don't commonly have the same need for rich room topics as users + who already reside in the room. A future MSC may update these endpoints + to support rich text topics. +- The same logic is applied to [`/_matrix/client/v1/rooms/{roomId}/hierarchy`] + and [`/_matrix/federation/v1/hierarchy/{roomId}`]. +- In [server side search], the `room_events` category is expanded to search + over the `m.text` content block of `m.room.topic` events. + +## Potential issues + +None. + +## Alternatives + +The combination of `format` and `formatted_body` currently utilised to +enable HTML in `m.room.message` events could be generalised to +`m.room.topic` events. However, this would only allow for a single +format in addition to plain text and is a weaker form of reuse than +described in the introductory section of [MSC1767]. + +## Security considerations + +Allowing HTML in room topics is subject to the same security +considerations that apply to HTML in room messages. In particular, +topics are already included in the content that clients should [sanitise] +for unsafe HTML. + +## Unstable prefix + +While this MSC is not considered stable, `m.topic` should be referred to +as `org.matrix.msc3765.topic`. + +[^1]: A future MSC may discuss how to adopt the `m.topic` content block in + new room versions which support extensible events. + +[plain text]: https://spec.matrix.org/v1.12/client-server-api/#mroomtopic +[MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 +[MSC4252]: https://github.com/matrix-org/matrix-spec-proposals/pull/4252 +[sanitise]: https://spec.matrix.org/v1.12/client-server-api/#security-considerations +[server side search]: https://spec.matrix.org/v1.12/client-server-api/#server-side-search +[`m.room.topic`]: https://spec.matrix.org/v1.12/client-server-api/#mroomtopic +[`/_matrix/client/v1/rooms/{roomId}/hierarchy`]: https://spec.matrix.org/v1.12/client-server-api/#get_matrixclientv1roomsroomidhierarchy +[`/_matrix/client/v3/createRoom`]: https://spec.matrix.org/v1.12/client-server-api/#post_matrixclientv3createroom +[`/_matrix/federation/v1/hierarchy/{roomId}`]: https://spec.matrix.org/v1.12/server-server-api/#get_matrixfederationv1hierarchyroomid +[`GET /_matrix/client/v3/publicRooms`]: https://spec.matrix.org/v1.12/client-server-api/#get_matrixclientv3publicrooms +[`GET /_matrix/federation/v1/publicRooms`]: https://spec.matrix.org/v1.12/server-server-api/#get_matrixfederationv1publicrooms