mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
479 lines
18 KiB
Markdown
479 lines
18 KiB
Markdown
# 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
|
|
<!-- Syntax: #**announce** -->
|
|
<a class="stream" data-stream-id="9"
|
|
href="/#narrow/channel/9-announce">
|
|
#announce
|
|
</a>
|
|
|
|
<!-- Syntax: #**announce>Zulip updates** -->
|
|
<a class="stream-topic" data-stream-id="9"
|
|
href="/#narrow/channel/9-announce/topic/Zulip.20updates/with/214">
|
|
#announce > Zulip updates
|
|
</a>
|
|
|
|
<!-- Syntax: #**announce>Zulip updates**
|
|
Generated only if topic had no messages or the link was rendered
|
|
before Zulip 10.0 (feature level 347) -->
|
|
<a class="stream-topic" data-stream-id="9"
|
|
href="/#narrow/channel/9-announce/topic/Zulip.20updates">
|
|
#announce > Zulip updates
|
|
</a>
|
|
|
|
<!-- Syntax: #**announce>Zulip updates@214** -->
|
|
<a class="message-link"
|
|
href="/#narrow/channel/9-announce/topic/Zulip.20updates/near/214">
|
|
#announce > Zulip updates @ 💬
|
|
</a>
|
|
```
|
|
|
|
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 `<em>` tag.
|
|
|
|
Sample HTML formats with `"realm_empty_topic_display_name": "general chat"`
|
|
are as follows:
|
|
```html
|
|
<!-- Syntax: #**announce>** -->
|
|
<a class="stream-topic" data-stream-id="9"
|
|
href="/#narrow/channel/9-announce/topic/with/214">
|
|
#announce > <em>general chat</em>
|
|
</a>
|
|
|
|
<!-- Syntax: #**announce>**
|
|
Generated only if topic had no messages or the link was rendered
|
|
before Zulip 10.0 (feature level 347) -->
|
|
<a class="stream-topic" data-stream-id="9"
|
|
href="/#narrow/channel/9-announce/topic/">
|
|
#announce > <em>general chat</em>
|
|
</a>
|
|
|
|
<!-- Syntax: #**announce>@214** -->
|
|
<a class="message-link"
|
|
href="/#narrow/channel/9-announce/topic//near/214">
|
|
#announce > <em>general chat</em> @ 💬
|
|
</a>
|
|
```
|
|
|
|
**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
|
|
<div class="message_inline_image">
|
|
<a href="/user_uploads/path/to/example.png" title="example.png">
|
|
<img data-original-dimensions="1920x1080"
|
|
data-original-content-type="image/png"
|
|
src="/user_uploads/thumbnail/path/to/example.png/840x560.webp">
|
|
</a>
|
|
</div>
|
|
```
|
|
|
|
**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
|
|
<div class="message_inline_image">
|
|
<a href="/user_uploads/path/to/example.png" title="example.png">
|
|
<img class="image-loading-placeholder"
|
|
data-original-dimensions="1920x1080"
|
|
data-original-content-type="image/png"
|
|
src="/path/to/spinner.png">
|
|
</a>
|
|
</div>
|
|
```
|
|
|
|
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
|
|
<div class="message_inline_image">
|
|
<a href="/user_uploads/path/to/example.heic" title="example.heic">
|
|
<img data-original-dimensions="1920x1080"
|
|
data-original-content-type="image/heic"
|
|
data-transcoded-image="1920x1080.webp"
|
|
src="/user_uploads/thumbnail/path/to/example.heic/840x560.webp">
|
|
</a>
|
|
</div>
|
|
```
|
|
|
|
### 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
|
|
<div class="message_inline_image message_inline_video">
|
|
<a href="/user_uploads/path/to/video.mp4">
|
|
<video preload="metadata" src="/user_uploads/path/to/video.mp4">
|
|
</video>
|
|
</a>
|
|
</div>
|
|
```
|
|
|
|
## Audio Players
|
|
|
|
When the Markdown media syntax is used with an uploaded file with an
|
|
audio `Content-Type`, Zulip will generate an HTML5 `<audio>` player
|
|
element. Supported MIME types are currently `audio/aac`, `audio/flac`,
|
|
`audio/mpeg`, and `audio/wav`.
|
|
|
|
For example, `[file.mp3](/user_uploads/path/to/file.mp3)` renders as:
|
|
|
|
``` html
|
|
<audio controls preload="metadata"
|
|
src="/user_uploads/path/to/file.mp3" title="file.mp3">
|
|
</audio>
|
|
```
|
|
|
|
If the Zulip server has rewritten the URL of the audio file, it will
|
|
provide the URL in a `data-original-url` parameter. The Zulip server
|
|
does this for all non-uploaded file audio URLs.
|
|
|
|
``` html
|
|
<audio controls preload="metadata"
|
|
data-original-url="https://example.com/path/to/original/file.mp3"
|
|
src="https://zulipcdn.example.com/path/to/playable/file.mp3" title="file.mp3">
|
|
</audio>
|
|
```
|
|
|
|
Clients that cannot render an audio player are recommended to convert
|
|
audio elements into a link to the original URL.
|
|
|
|
The Zulip server does not validate whether uploaded files with an
|
|
audio `Content-Type` are actually playable.
|
|
|
|
**Changes**: New in Zulip 11.0 (feature level 405).
|
|
|
|
## Mentions and silent mentions
|
|
|
|
Zulip markup supports [mentioning](/help/mention-a-user-or-group)
|
|
users, user groups, and a few special "wildcard" mentions (the three
|
|
spellings of a channel wildcard mention: `@**all**`, `@**everyone**`,
|
|
`@**channel**` and the topic wildcard mention `@**topic**`).
|
|
|
|
Mentions result in a message being highlighted for the target user(s),
|
|
both in the UI and in notifications, and may also result in the target
|
|
user(s) following the conversation, [depending on their
|
|
settings](/help/follow-a-topic#follow-topics-where-you-are-mentioned).
|
|
|
|
Silent mentions of users or groups have none of those side effects,
|
|
but nonetheless uniquely identify the user or group
|
|
identified. (There's no such thing as a silent wildcard mention).
|
|
|
|
Permissions for mentioning users work as follows:
|
|
|
|
- Any user can mention any other user, though mentions by [muted
|
|
users](/help/mute-a-user) are automatically marked as read and thus do
|
|
not trigger notifications or otherwise get highlighted like unread
|
|
mentions.
|
|
|
|
- Wildcard mentions are permitted except where [organization-level
|
|
restrictions](/help/restrict-wildcard-mentions) apply.
|
|
|
|
- User groups can be mentioned if and only if the acting user is in
|
|
the `can_mention_group` group for that group. All user groups can be
|
|
silently mentioned by any user.
|
|
|
|
- System groups, when (silently) mentioned, should be displayed using
|
|
their description, not their `role:nobody` style API names; see the
|
|
main [system group
|
|
documentation](/api/group-setting-values#system-groups) for
|
|
details. System groups can only be silently mentioned right now,
|
|
because they happen to all use the empty `Nobody` group for
|
|
`can_mention_group`; clients should just use `can_mention_group` to
|
|
determine which groups to offer in typeahead in similar contexts.
|
|
|
|
- Requests to send or edit a message that are impermissible due to
|
|
including a mention where the acting user does not have permission to
|
|
mention the target will return an error. Mention syntax that does not
|
|
correspond to a real user or group is ignored.
|
|
|
|
Sample markup for `@**Example User**`:
|
|
|
|
``` html
|
|
<span class="user-mention" data-user-id="31">@Example User</span>
|
|
```
|
|
|
|
Sample markup for `@_**Example User**`:
|
|
|
|
``` html
|
|
<span class="user-mention silent" data-user-id="31">Example User</span>
|
|
```
|
|
|
|
Sample markup for `@**topic**`:
|
|
|
|
``` html
|
|
<span class="topic-mention">@topic</span>
|
|
```
|
|
|
|
Sample markup for `@**channel**`:
|
|
|
|
``` html
|
|
<span class="user-mention channel-wildcard-mention"
|
|
data-user-id="*">@channel</span>
|
|
```
|
|
|
|
Sample markup for `@*support*`, assuming "support" is a valid group:
|
|
``` html
|
|
<span class="user-group-mention"
|
|
data-user-group-id="17">@support</span>
|
|
```
|
|
|
|
Sample markup for `@_*support*`, assuming "support" is a valid group:
|
|
``` html
|
|
<span class="user-group-mention silent"
|
|
data-user-group-id="17">support</span>
|
|
```
|
|
|
|
Sample markup for `@_*role:administrators*`:
|
|
``` html
|
|
<span class="user-group-mention silent"
|
|
data-user-group-id="5">Administrators</span>
|
|
```
|
|
|
|
When processing mentions, clients should look up the user or group
|
|
referenced by ID, and update the textual name for the mention to the
|
|
current name for the user or group with that ID. Note that for system
|
|
groups, this requires special logic to look up the user-facing name
|
|
for that group; see [system
|
|
groups](/api/group-setting-values#system-groups) for details.
|
|
|
|
**Changes**: Prior to Zulip 10.0 (feature level 333), it was not
|
|
possible to silently mention [system
|
|
groups](/api/group-setting-values#system-groups).
|
|
|
|
In Zulip 9.0 (feature level 247), `channel` was added to the supported
|
|
[wildcard][help-mention-all] options used in the
|
|
[mentions][help-mentions] Markdown message formatting feature.
|
|
|
|
## Spoilers
|
|
|
|
**Changes**: In Zulip 3.0 (feature level 15), added
|
|
[spoilers][help-spoilers] to supported Markdown message formatting
|
|
features.
|
|
|
|
## Removed features
|
|
|
|
### Removed legacy Dropbox link preview markup
|
|
|
|
In Zulip 11.0 (feature level 395), the Zulip server stopped generating
|
|
legacy Dropbox link previews. Dropbox links are now previewed just
|
|
like standard Zulip image/link previews. However, some legacy Dropbox
|
|
previews may exist in existing messages.
|
|
|
|
Clients are recommended to prune these previews from message HTML;
|
|
since they always appear after the actual link, there is no loss of
|
|
information/functionality. They can be recognized via the classes
|
|
`message_inline_ref`, `message_inline_image_desc`, and
|
|
`message_inline_image_title`:
|
|
|
|
``` html
|
|
<div class="message_inline_ref">
|
|
<a href="https://www.dropbox.com/sh/cm39k9e04z7fhim/AAAII5NK-9daee3FcF41anEua?dl=" title="Saves">
|
|
<img src="/path/to/folder_dropbox.png">
|
|
</a>
|
|
<div><div class="message_inline_image_title">Saves</div>
|
|
<desc class="message_inline_image_desc"></desc>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
### Removed legacy avatar markup
|
|
|
|
In Zulip 4.0 (feature level 24), the rarely used `!avatar()`
|
|
and `!gravatar()` markup syntax, which was never documented and had an
|
|
inconsistent syntax, were removed.
|
|
|
|
## Related articles
|
|
|
|
* [Markdown formatting](/help/format-your-message-using-markdown)
|
|
* [Send a message](/api/send-message)
|
|
* [Render a message](/api/render-message)
|
|
|
|
[help-code]: /help/code-blocks
|
|
[help-playgrounds]: /help/code-blocks#code-playgrounds
|
|
[help-spoilers]: /help/spoilers
|
|
[help-global-time]: /help/global-times
|
|
[help-mentions]: /help/mention-a-user-or-group
|
|
[help-mention-all]: /help/mention-a-user-or-group#mention-everyone-on-a-channel
|
|
[help-previews]: /help/image-video-and-website-previews#configure-how-animated-images-are-played
|