|
| 1 | +# MSC3765: Rich text in room topics |
| 2 | + |
| 3 | +## Problem |
| 4 | + |
| 5 | +Topics are a central piece of room meta data and usually made easily |
| 6 | +accessible to room members in clients. As a result, room administrators |
| 7 | +often extend the use of topics to collect helpful peripheral information |
| 8 | +that is related to the room’s purpose. Most commonly these are links to |
| 9 | +external resources. At the moment, topics are limited to [plain text] |
| 10 | +which, depending on the number and length of URLs and other content, |
| 11 | +easily gets inconvenient to consume and calls for richer text formatting |
| 12 | +options. |
| 13 | + |
| 14 | +## Proposal |
| 15 | + |
| 16 | +Drawing from extensible events as described in [MSC1767], a new content |
| 17 | +block `m.topic` is defined, which wraps an `m.text` content block that |
| 18 | +allows representing the room topic in different mime types. In current |
| 19 | +room versions, this content block is added to the content of [`m.room.topic`] |
| 20 | +events as shown below[^1]. |
| 21 | + |
| 22 | +```json5 |
| 23 | +{ |
| 24 | + "type": "m.room.topic", |
| 25 | + "state_key": "", |
| 26 | + "content": { |
| 27 | + "m.topic": { |
| 28 | + "m.text": [ { |
| 29 | + "mimetype": "text/html", |
| 30 | + "body": "All about <b>pizza</b> | <a href=\"https://recipes.pizza.net\">Recipes</a>" |
| 31 | + }, { |
| 32 | + "body": "All about **pizza** | [Recipes](https://recipes.pizza.net)" |
| 33 | + }] |
| 34 | + }, |
| 35 | + "topic": "All about **pizza** | [Recipes](https://recipes.pizza.net)" |
| 36 | + }, |
| 37 | + ... |
| 38 | +} |
| 39 | +``` |
| 40 | + |
| 41 | +In line with [MSC1767], clients should render the first mime type in the |
| 42 | +array that they understand. Further details of how `m.text` works may |
| 43 | +be found in [MSC1767] and are not repeated here. |
| 44 | + |
| 45 | +The wrapping `m.topic` content block is similar to `m.caption` for file |
| 46 | +uploads as defined in [MSC3551]. It avoids clients accidentally rendering |
| 47 | +the topic as a room message. ([MSC1767] specifies that unknown events with |
| 48 | +an `m.text` content block should be rendered as a regular room message, and |
| 49 | +while [MSC1767] had explicitly excluded state events from being treated as |
| 50 | +extensible, this is being changed with [MSC4252].) The extra content block, therefore, allows putting |
| 51 | +a fallback representation that is actually designated for the timeline |
| 52 | +into a separate `content['m.text']` field. In addition, the `m.topic` content |
| 53 | +block also serves as a good place for additional fields to be added by |
| 54 | +other MSCs in the future. |
| 55 | + |
| 56 | +It is recommended that clients always include a plain text variant within `m.text` when |
| 57 | +sending `m.room.topic` events. This prevents bad UX in situations where a plain |
| 58 | +text topic is sufficient such as the public rooms directory. |
| 59 | + |
| 60 | +Additionally, clients should duplicate the plain text topic into the existing |
| 61 | +`topic` field for backwards compatibility with clients that don't support |
| 62 | +`m.topic` yet. This also helps prevent inconsistencies since such clients |
| 63 | +are likely to delete the `m.topic` content block when updating `m.room.topic` |
| 64 | +themselves. |
| 65 | + |
| 66 | +In order to prevent formatting abuse in room topics, clients are |
| 67 | +encouraged to limit the length of topics during both entry and display, |
| 68 | +for instance, by capping the number of displayed lines. Additionally, |
| 69 | +clients should ignore things like headings and enumerations (or format them |
| 70 | +as regular text). A future MSC may introduce a mechanism to capture extended |
| 71 | +multiline details that are not suitable for room topics in a separate field |
| 72 | +or event type. |
| 73 | + |
| 74 | +On the server side, any logic that currently operates on the `topic` field is |
| 75 | +updated to use the `m.topic` content block instead: |
| 76 | + |
| 77 | +- In [`/_matrix/client/v3/createRoom`], the `topic` parameter should cause `m.room.topic` |
| 78 | + to be written with a `text/plain` mimetype in `m.topic`. If at the same time an |
| 79 | + `m.room.topic` event is supplied in `initial_state`, it is overwritten entirely. |
| 80 | + A future MSC may generalize the `topic` parameter to allow specifying other mime |
| 81 | + types without `initial_state`. |
| 82 | +- In [`GET /_matrix/client/v3/publicRooms`], [`GET /_matrix/federation/v1/publicRooms`] |
| 83 | + and their `POST` siblings, the `topic` response field should be read from the |
| 84 | + `text/plain` mimetype of `m.topic` if it exists or omitted otherwise. |
| 85 | + A plain text topic is sufficient here because this data is commonly |
| 86 | + only displayed to users that are *not* a member of the room yet. These |
| 87 | + users don't commonly have the same need for rich room topics as users |
| 88 | + who already reside in the room. A future MSC may update these endpoints |
| 89 | + to support rich text topics. |
| 90 | +- The same logic is applied to [`/_matrix/client/v1/rooms/{roomId}/hierarchy`] |
| 91 | + and [`/_matrix/federation/v1/hierarchy/{roomId}`]. |
| 92 | +- In [server side search], the `room_events` category is expanded to search |
| 93 | + over the `m.text` content block of `m.room.topic` events. |
| 94 | + |
| 95 | +## Potential issues |
| 96 | + |
| 97 | +None. |
| 98 | + |
| 99 | +## Alternatives |
| 100 | + |
| 101 | +The combination of `format` and `formatted_body` currently utilised to |
| 102 | +enable HTML in `m.room.message` events could be generalised to |
| 103 | +`m.room.topic` events. However, this would only allow for a single |
| 104 | +format in addition to plain text and is a weaker form of reuse than |
| 105 | +described in the introductory section of [MSC1767]. |
| 106 | + |
| 107 | +## Security considerations |
| 108 | + |
| 109 | +Allowing HTML in room topics is subject to the same security |
| 110 | +considerations that apply to HTML in room messages. In particular, |
| 111 | +topics are already included in the content that clients should [sanitise] |
| 112 | +for unsafe HTML. |
| 113 | + |
| 114 | +## Unstable prefix |
| 115 | + |
| 116 | +While this MSC is not considered stable, `m.topic` should be referred to |
| 117 | +as `org.matrix.msc3765.topic`. |
| 118 | + |
| 119 | +[^1]: A future MSC may discuss how to adopt the `m.topic` content block in |
| 120 | + new room versions which support extensible events. |
| 121 | + |
| 122 | +[plain text]: https://spec.matrix.org/v1.12/client-server-api/#mroomtopic |
| 123 | +[MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767 |
| 124 | +[MSC4252]: https://github.com/matrix-org/matrix-spec-proposals/pull/4252 |
| 125 | +[sanitise]: https://spec.matrix.org/v1.12/client-server-api/#security-considerations |
| 126 | +[server side search]: https://spec.matrix.org/v1.12/client-server-api/#server-side-search |
| 127 | +[`m.room.topic`]: https://spec.matrix.org/v1.12/client-server-api/#mroomtopic |
| 128 | +[`/_matrix/client/v1/rooms/{roomId}/hierarchy`]: https://spec.matrix.org/v1.12/client-server-api/#get_matrixclientv1roomsroomidhierarchy |
| 129 | +[`/_matrix/client/v3/createRoom`]: https://spec.matrix.org/v1.12/client-server-api/#post_matrixclientv3createroom |
| 130 | +[`/_matrix/federation/v1/hierarchy/{roomId}`]: https://spec.matrix.org/v1.12/server-server-api/#get_matrixfederationv1hierarchyroomid |
| 131 | +[`GET /_matrix/client/v3/publicRooms`]: https://spec.matrix.org/v1.12/client-server-api/#get_matrixclientv3publicrooms |
| 132 | +[`GET /_matrix/federation/v1/publicRooms`]: https://spec.matrix.org/v1.12/server-server-api/#get_matrixfederationv1publicrooms |
0 commit comments