ContentFormat

The ContentFormat structure is used to represent content with metadata. It supports multiple content types for the same file, such as a PNG image and a WebP image.

A ContentFormat structure is defined as follows:

type ContentType = `${string}/${string}`;

type ContentFormat = {
    [key: ContentType]: {
        ...
    };
}

Implementation Guidelines

Text

Implementations should always process text content with the richest format available, such as HTML. However, they should also provide other formats like plain text and Markdown for compatibility with other systems.

HTML is the recommended content type for text content, and as such every text content should have an HTML representation. If the content is not HTML, it should be converted to HTML using appropriate conversion rules.

Rich formats include:

  • text/html
  • text/markdown
  • text/x.misskeymarkdown (Misskey Flavoured Markdown, common on ActivityPub)

Clients should display the richest possible format available. If the client does not support the richest format, it should fall back to the next richest format.

Images

It is a good idea to provide at least two versions of an image (if possible): one in the original format and another in a more efficient format like WebP/AVIF. This allows clients to choose the most suitable format based on their capabilities.

Entity Definition

  • Name
    content
    Required
    Required
    Type
    string | URI
    Description

    Structure data. If Content-Type is a binary format, this field should be a URI to the binary data. Otherwise, it should be the content itself. Refer to the remote property for more information.

  • Name
    remote
    Required
    Required
    Type
    boolean
    Description

    If true, the content is hosted remotely and should be fetched by the client. If false, the content is embedded in the entity.

  • Name
    description
    Type
    string
    Description

    A human-readable description of the content. Also known as alt text.

  • Name
    size
    Type
    u64
    Type
    number
    Description

    Size of the content in bytes.

  • Name
    hash
    Type
    Hash
    Description

    Hash of the content.

    type HashNames = "sha256" | "sha512" | "sha3-256" | "sha3-512" | "blake2b-256" | "blake2b-512" | "blake3-256" | "blake3-512" | "md5" | "sha1" | "sha224" | "sha384" | "sha3-224" | "sha3-384" | "blake2s-256" | "blake2s-512" | "blake3-224" | "blake3-384";
    
    type Hash = {
        [key in HashNames]: string;
    }
    
  • Name
    thumbhash
    Type
    string
    Description

    Image in ThumbHash format.

  • Name
    width
    Type
    u64
    Type
    number
    Description

    Width of the content in pixels. Only applicable to content types that have a width.

  • Name
    height
    Type
    u64
    Type
    number
    Description

    Height of the content in pixels. Only applicable to content types that have a height.

  • Name
    fps
    Type
    u64
    Type
    number
    Description

    Frames per second. Only applicable to video content.

  • Name
    duration
    Type
    f64
    Type
    number
    Description

    Duration of the content in seconds. Only applicable to content types that have a duration.

Images

{
    "image/png": {
        "content": "https://cdn.example.com/attachments/ece2f9d9-27d7-457d-b657-4ce9172bdcf8.png",
        "remote": true,
        "description": "A jolly horse running through mountains",
        "size": 453933,
        "hash": {
            "sha256": "91714fc336210d459d4f9d9233de663be2b87ffe923f1cfd76ece9d06f7c965d"
        },
        "thumbhash": "3OcRJYB4d3h/iIeHeEh3eIhw+j2w",
        "width": 1920,
        "height": 1080
    }
}

Text Formats

{
    "text/plain": {
        "content": "The consequences of today are determined by the actions of the past. To change your future, alter your decisions today.",
        "remote": false
    },
    "text/markdown": {
        "content": "> The consequences of today are determined by the actions of the past.\n> To change your future, alter your decisions today.",
        "remote": false
    },
    "text/html": {
        "content": "<blockquote><p>The consequences of today are determined by the actions of the past.</p><p>To change your future, alter your decisions today.</p></blockquote>",
        "remote": false
    }
}