# Message formatting Zulip supports an extended version of Markdown for messages, as well as some HTML level special behavior. The Zulip help center article on [message formatting](/help/format-your-message-using-markdown) is the primary documentation for Zulip's markup features. This article is currently a changelog for updates to these features. The [render a message](/api/render-message) endpoint can be used to get the current HTML version of any Markdown syntax for message content. ## Code blocks **Changes**: As of Zulip 4.0 (feature level 33), [code blocks][help-code] can have a `data-code-language` attribute attached to the outer HTML `div` element, which records the programming language that was selected for syntax highlighting. This field is used in the [playgrounds][help-playgrounds] feature for code blocks. ## Global times **Changes**: In Zulip 3.0 (feature level 8), added [global time mentions][help-global-time] to supported Markdown message formatting features. ## Links to channels, topics, and messages Zulip's markup supports special readable Markdown syntax for [linking to channels, topics, and messages](/help/link-to-a-message-or-conversation). Sample HTML formats are as follows: ``` html #announce #announce > Zulip updates #announce > Zulip updates #announce > Zulip updates @ 💬 ``` The `near` and `with` operators are documented in more detail in the [search and URL documentation](/api/construct-narrow). When rendering topic links with the `with` operator, the code doing the rendering may pick the ID arbitrarily among messages accessible to the client and/or acting user at the time of rendering. Currently, the server chooses the message ID to use for `with` operators as the latest message ID in the topic accessible to the user who wrote the message. The older stream/topic link elements include a `data-stream-id`, which historically was used in order to display the current channel name if the channel had been renamed. That field is **deprecated**, because displaying an updated value for the most common forms of this syntax requires parsing the URL to get the topic to use anyway. When a topic is an empty string, it is replaced with `realm_empty_topic_display_name` found in the [`POST /register`](/api/register-queue) response and wrapped with the `` tag. Sample HTML formats with `"realm_empty_topic_display_name": "general chat"` are as follows: ```html #announce > general chat #announce > general chat #announce > general chat @ 💬 ``` **Changes**: In Zulip 11.0 (feature level 400), the server switched its strategy for `with` URL construction to choose the latest accessible message ID in a topic. Previously, it used the oldest. Before Zulip 10.0 (feature level 347), the `with` field was never used in topic link URLs generated by the server; the markup currently used only for empty topics was used for all topic links. Before Zulip 10.0 (feature level 346), empty string was not a valid topic name in syntaxes for linking to topics and messages. In Zulip 10.0 (feature level 319), added Markdown syntax for linking to a specific message in a conversation. Declared the `data-stream-id` field to be deprecated as detailed above. In Zulip 11.0 (feature level 383), clients can decide what channel view a.stream channel link elements take you to -- i.e., the href for those is the default behavior of the link that also encodes the channel alongside the data-stream-id field, but clients can override that default based on `web_channel_default_view` setting. ## Images When a Zulip message is sent linking to an uploaded image, Zulip will generate an image preview element with the following format: ``` html
``` **Changes**: See [Changes to image formatting](#changes-to-image-formatting). ### Image-loading placeholders If the server has yet to generate thumbnails for the image by the time the message is sent, the `img` element will temporarily reference a loading indicator image and have the `image-loading-placeholder` class, which clients can use to identify loading indicators and replace them with a more native loading indicator element if desired. For example: ``` html
``` Once the server has a working thumbnail, such messages will be updated via an `update_message` event, with the `rendering_only: true` flag (telling clients not to adjust message edit history), with appropriate adjusted `rendered_content`. A client should process those events by just using the updated rendering. If thumbnailing failed, the same type of event will edit the message's rendered form to remove the image preview element, so no special client-side logic should be required to process such errors. Note that in the uncommon situation that the thumbnailing system is backlogged, an individual message containing multiple image previews may be re-rendered multiple times as each image finishes thumbnailing and triggers a message update. ### Transcoded images Image elements whose formats are not widely supported by web browsers (e.g., HEIC and TIFF) may contain a `data-transcoded-image` attribute, which specifies a high-resolution thumbnail format that clients may opt to present instead of the original image. If the `data-transcoded-image` attribute is present, clients should use the `data-original-content-type` attribute to decide whether to display the original image or use the transcoded version. Transcoded images are presented with this structure in image previews: ``` html
``` ### Recommended client processing of image previews Clients are recommended to do the following when processing image previews: - Clients that would like to use the image's aspect ratio to lay out one or more images in the message feed may use the `data-original-dimensions` attribute, which is present even if the image is a placeholder spinner. This attribute encodes the dimensions of the original image as `{width}x{height}`. These dimensions are for the image as rendered, _after_ any EXIF rotation and mirroring has been applied. - If the client would like to control the thumbnail resolution used, it can replace the final section of the URL (`840x560.webp` in the example above) with the `name` of its preferred format from the set of supported formats provided by the server in the `server_thumbnail_formats` portion of the `register` response. Clients should not make any assumptions about what format the server will use as the "default" thumbnail resolution, as it may change over time. - Download button type elements should provide the original image (encoded via the `href` of the containing `a` tag). - The content-type of the original image is provided on a `data-original-content-type` attribute, so clients can decide if they are capable of rendering the original image. - For images whose formats which are not widely-accepted by browsers (e.g., HEIC and TIFF), the image may contain a `data-transcoded-image` attribute, which specifies a high-resolution thumbnail format which clients may use instead of the original image. - Lightbox elements for viewing an image should be designed to immediately display any already-downloaded thumbnail while fetching the original-quality image or an appropriate higher-quality thumbnail from the server, to be transparently swapped in once it is available. Clients that would like to size the lightbox based on the size of the original image can use the `data-original-dimensions` attribute, as described above. - Animated images will have a `data-animated` attribute on the `img` tag. As detailed in `server_thumbnail_formats`, both animated and still images are available for clients to use, depending on their preference. See, for example, the [web setting][help-previews] to control whether animated images are autoplayed in the message feed. - Clients should not assume that the requested format is the format that they will receive; in rare cases where the client has an out-of-date list of `server_thumbnail_formats`, the server will provide an approximation of the client's requested format. Because of this, clients should not assume that the pixel dimensions or file format match what they requested. - No other processing of the URLs is recommended. ### Changes to image formatting **In Zulip 10.0** (feature level 336), added `data-original-content-type` attribute to convey the type of the original image, and optional `data-transcoded-image` attribute for images with formats which are not widely supported by browsers. **In Zulip 9.2** (feature levels 278-279, and 287+), added `data-original-dimensions` to the `image-loading-placeholder` spinner images, containing the dimensions of the original image. **In Zulip 9.0** (feature level 276), added `data-original-dimensions` attribute to images that have been thumbnailed, containing the dimensions of the full-size version of the image. Thumbnailing itself was reintroduced at feature level 275. Previously, with the exception of Zulip servers that used the beta Thumbor-based implementation years ago, all image previews in Zulip messages were not thumbnailed; the `a` tag and the `img` tag would both point to the original image. Clients that correctly implement the current API should handle Thumbor-based older thumbnails correctly, as long as they do not assume that `data-original-dimensions` is present. Clients should not assume that messages sent prior to the introduction of thumbnailing have been re-rendered to use the new format or have thumbnails available. ## Video embeddings and previews When a Zulip message is sent linking to an uploaded video, Zulip may generate a video preview element with the following format. ``` html
``` ## Audio Players When the Markdown media syntax is used with an uploaded file with an audio `Content-Type`, Zulip will generate an HTML5 `