mirror of
https://codeberg.org/fediverse/fep.git
synced 2026-08-05 03:35:52 +00:00
FEP-9098: Custom emojis (#647)
Reviewed-on: https://codeberg.org/fediverse/fep/pulls/647 Co-authored-by: silverpill <silverpill@firemail.cc> Co-committed-by: silverpill <silverpill@firemail.cc>
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
---
|
||||
slug: "9098"
|
||||
authors: silverpill <@silverpill@mitra.social>
|
||||
type: implementation
|
||||
status: DRAFT
|
||||
dateReceived: 2025-07-06
|
||||
discussionsTo: https://codeberg.org/silverpill/feps/issues
|
||||
---
|
||||
# FEP-9098: Custom emojis
|
||||
|
||||
## Summary
|
||||
|
||||
This document describes how custom emojis are implemented in [ActivityPub] network.
|
||||
|
||||
## History
|
||||
|
||||
Custom emojis were introduced by Pleroma ([commits](https://gitgud.io/lambadalambda/pleroma/-/compare/c17c8ce36d35db03a007a264cc2e507afa9b803e...7c82b8219734102ff24d9dc24226c08351e608cc)) and Mastodon ([PR](https://github.com/mastodon/mastodon/pull/4988)) in 2017.
|
||||
|
||||
## Requirements
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC-2119].
|
||||
|
||||
## Emoji object
|
||||
|
||||
Custom emojis are represented as `Emoji` objects (the full type IRI is `http://joinmastodon.org/ns#Emoji`). The `Emoji` object has the following properties:
|
||||
|
||||
- `id` (RECOMMENDED): the unique identifier of the custom emoji. Some implementations omit this property (i.e. the object is anonymous).
|
||||
- `type` (REQUIRED): the `Emoji` string.
|
||||
- `name` (REQUIRED): the [shortcode][Shortcode] of the custom emoji (the name of the emoji, enclosed in colons).
|
||||
- `updated` (OPTIONAL): the date when custom emoji was updated, formatted as [RFC-3339] timestamp.
|
||||
- `icon` (REQUIRED): `Image` object describing emoji image.
|
||||
- `type` (REQUIRED): the `Image` string.
|
||||
- `url` (REQUIRED): the URL of the emoji image.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "https://social.example/emoji/blobcat",
|
||||
"type": "Emoji",
|
||||
"name": ":blobcat:",
|
||||
"updated": "1970-01-01T00:00:00Z",
|
||||
"icon": {
|
||||
"type": "Image",
|
||||
"url": "https://social.example/media/blobcat.png"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Uniqueness
|
||||
|
||||
The primary unique identifier of a custom emoji is a combination of its name and the domain name. The domain name can be extracted from the `id` of `Emoji` object or from the `id` of the object within which it is embedded.
|
||||
|
||||
If `id` is not guaranteed to be globally unique, it MUST be omitted.
|
||||
|
||||
### Accessibility
|
||||
|
||||
The short description of a custom emoji can be specified with the `alternateName` property (the full IRI is `http://schema.org/alternateName`).
|
||||
|
||||
### Compatibility
|
||||
|
||||
In order to be compatible with as many servers as possible, implementations SHOULD comply with the following additional requirements:
|
||||
|
||||
- Name contains at least two characters ([Mastodon](https://github.com/mastodon/mastodon/blob/v4.3.7/app/models/custom_emoji.rb#L28)).
|
||||
- Name matches the regular expression `^[a-zA-Z0-9_]+$` ([Mastodon](https://github.com/mastodon/mastodon/blob/v4.3.7/app/models/custom_emoji.rb#L30)).
|
||||
- Image media type is `image/png`, `image/gif` or `image/webp` ([Mastodon](https://github.com/mastodon/mastodon/blob/v4.3.7/app/models/custom_emoji.rb#L37)).
|
||||
- Image size is not greater than 256 KB ([Mastodon](https://github.com/mastodon/mastodon/blob/v4.3.7/app/models/custom_emoji.rb#L27)).
|
||||
- Image is a square (some clients may display non-squre emojis with a wrong aspect ratio).
|
||||
|
||||
## Using custom emojis
|
||||
|
||||
### Microsyntax
|
||||
|
||||
Custom emojis can be inserted into textual representations of an object using [shortcodes][Shortcode] (shortcode is a name of an emoji enclosed in colons: `:emojiname:`). These textual representations are often specified with `name`, `summary` and `content` properties.
|
||||
|
||||
The corresponding `Emoji` objects are added to the `tag` array of the object.
|
||||
|
||||
Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "Note",
|
||||
"content": "<p>:blobcat:</p>",
|
||||
"tag": [
|
||||
{
|
||||
"id": "https://social.example/emoji/blobcat",
|
||||
"type": "Emoji",
|
||||
"name": ":blobcat:",
|
||||
"icon": {
|
||||
"type": "Image",
|
||||
"url": "https://social.example/media/blobcat.png"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Rendering
|
||||
|
||||
Applications typically replace custom emoji shortcodes with `<img>` HTML tags and render the output as HTML.
|
||||
|
||||
To prevent [Cross-Site Scripting (XSS)][XSS] attacks, implementers MUST ensure that:
|
||||
|
||||
- Emoji names, descriptions, URLs and other strings that are used in replacements do not contain reserved HTML characters.
|
||||
- When HTML content (e.g. `summary`, `content`) is processed, shortcodes are replaced only inside [Text][DOM-Text] nodes.
|
||||
- Reserved HTML characters in text are escaped before replacing shortcodes.
|
||||
|
||||
## Implementations
|
||||
|
||||
This document is based on implementations of custom emojis in Pleroma, Mastodon, Misskey and Fedibird.
|
||||
|
||||
## References
|
||||
|
||||
- Christine Lemmer-Webber, Jessica Tallon, Erin Shepherd, Amy Guy, Evan Prodromou, [ActivityPub], 2018
|
||||
- S. Bradner, [Key words for use in RFCs to Indicate Requirement Levels][RFC-2119], 1997
|
||||
- G. Klyne, C. Newman, [Date and Time on the Internet: Timestamps][RFC-3339], 2002
|
||||
|
||||
[ActivityPub]: https://www.w3.org/TR/activitypub/
|
||||
[RFC-2119]: https://tools.ietf.org/html/rfc2119.html
|
||||
[RFC-3339]: https://www.rfc-editor.org/rfc/rfc3339
|
||||
[Shortcode]: https://emojipedia.org/shortcodes
|
||||
[XSS]: https://owasp.org/www-community/attacks/xss/
|
||||
[DOM-Text]: https://developer.mozilla.org/en-US/docs/Web/API/Text
|
||||
|
||||
## Copyright
|
||||
|
||||
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
|
||||
|
||||
To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work.
|
||||
Reference in New Issue
Block a user