export const metadata = {
    title: "Custom Emojis Extension",
    description: "The Custom Emojis extension adds support for custom emojis in notes.",
}

# Custom Emojis Extension

The Custom Emojis extension adds support for adding personalized emojis to federated data. {{ className: 'lead' }}

## Structure Definition

<Row>
    <Col>
        <Properties name="CustomEmoji">
            <Property name="name" type="string" required={true}>
                Emoji name, surrounded by identification characters (for example, colons: `:happy_face:`).

                The following characters are allowed:
                - `a-z`
                - `A-Z`
                - `0-9`
                - `_`, `-`
                
                Identification characters must not match the name regex (must not be alphanumeric/underscore/hyphen). There may only be two identification characters, one at the beginning and one at the end.
            </Property>
            <Property name="content" type="ContentFormat" required={true} typeLink="/structures/content-format">
                Emoji content. Must be an image format (`image/*`).
            </Property>
        </Properties>
    </Col>

    <Col sticky>

    ```jsonc {{ 'title': 'Example Emoji' }}
    {
        "name": ":happy_face:",
        "content": {
            "image/webp": {
                "content": "https://cdn.example.com/emojis/happy_face.webp",
                "remote": true,
                "description": "A happy emoji smiling.",
                "size": null,
                "hash": null,
                "thumbhash": null,
                "width": null,
                "height": null,
                "fps": null,
                "duration": null
            }
        }
    }
    ```

    </Col>
</Row>

## Rendering

To render custom emojis, clients **should** perform the following steps:
1. Find all instances of custom emoji names in the text content.
2. Replace the custom emoji names with the corresponding emoji images in text.

If custom emojis are not supported, clients **should** leave the custom emoji names as-is. Images **should** have any associated `alt` text for accessibility.

```html {{ 'title': 'Example HTML/CSS' }}
<style>
img.emoji {
    display: inline;
    height: 1em;
}
</style>

<p>
    Hello, world! <img src="https://cdn.example.com/emojis/happy_face.webp" alt="A happy emoji smiling." class="emoji" />!
</p>
```

Emojis **should** be displayed at a fixed height (such as `1em`), but their width **should** be allowed to be flexible.

## Extension Definition

Custom Emojis can be added to any entity with text content. The extension ID is `pub.versia:custom_emojis`.

<Row>
    <Col>
        <Properties name="CustomEmojisExtension">
            <Property name="emojis" type="CustomEmoji[]" required={true} typeLink="/extensions/custom-emoji#structure-definition">
                [Custom emojis](/extensions/custom-emoji#structure-definition) to be added to the note.
            </Property>
        </Properties>
    </Col>

    <Col sticky>

    ```jsonc {{ 'title': 'Example Usage' }}
    {
        "id": "456df8ed-daf1-4062-abab-491071c7b8dd",
        "type": "Note",
        "created_at": "2024-04-09T01:38:51.743Z",
        "content": {
            "text/plain": {
                "content": "Hello, world :happy_face:!"
            }
        },
        ...
        "extensions": { // [!code focus:23]
            "pub.versia:custom_emojis": {
                "emojis": [
                    {
                        "name": ":happy_face:",
                        "content": {
                            "image/webp": {
                                "content": "https://cdn.example.com/emojis/happy_face.webp",
                                "remote": true,
                                "description": "A happy emoji smiling.",
                                "size": null,
                                "hash": null,
                                "thumbhash": null,
                                "width": null,
                                "height": null,
                                "fps": null,
                                "duration": null
                            }
                        }
                    }
                ]
            }
        }
    }
    ```

    </Col>
</Row>