feat: Add unique ID to every property on docs

This commit is contained in:
Jesse Wierzbinski 2024-12-24 14:01:09 +01:00
parent f27f206e2d
commit 9db7cfccda
No known key found for this signature in database
28 changed files with 144 additions and 116 deletions

View file

@ -19,7 +19,7 @@ Having the authorization is defined as:
<Row>
<Col>
<Properties>
<Properties name="Delete">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>

View file

@ -13,7 +13,7 @@ export const metadata = {
<Row>
<Col>
<Properties>
<Properties name="FollowAccept">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>

View file

@ -23,7 +23,7 @@ But it can also be used when Bob is already following Alice, in the case that:
<Row>
<Col>
<Properties>
<Properties name="FollowReject">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>

View file

@ -55,7 +55,7 @@ Once a follow relationship is established, the **followee**'s instance should se
<Row>
<Col>
<Properties>
<Properties name="Follow">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>

View file

@ -17,7 +17,7 @@ Check the entity's documentation page to see if it supports this (it will be not
<Row>
<Col>
<Properties>
<Properties name="InstanceMetadata">
<Property name="id" type="null">
This entity does not have an ID.
</Property>

View file

@ -15,7 +15,7 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
<Row>
<Col>
<Properties>
<Properties name="Note">
<Property name="attachments" type="ContentFormat[]" required={false} typeLink="/structures/content-format">
Media attachments to the note. May be any format. **Must** be remote.
</Property>

View file

@ -17,7 +17,7 @@ Any field in an entity not marked as `required` may be omitted or set to `null`.
<Row>
<Col>
<Properties>
<Properties name="Entity">
<Property name="id" type="string" required={true}>
Unique identifier for the entity. Must be unique within the instance. Can be any string. Max of 512 UTF-8 characters.
</Property>

View file

@ -28,7 +28,7 @@ Sometimes, [Users](/entities/user) want to unsubscribe from each other to stop s
<Row>
<Col>
<Properties>
<Properties name="Unfollow">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>

View file

@ -42,7 +42,7 @@ Instance **must** be the host of the instance the user is on (hostname with opti
<Row>
<Col>
<Properties>
<Properties name="User">
<Property name="avatar" type="ContentFormat" required={false} typeLink="/structures/content-format">
The user's avatar. Must be an image format (`image/*`).
</Property>

View file

@ -11,7 +11,7 @@ The Custom Emojis extension adds support for adding personalized emojis to feder
<Row>
<Col>
<Properties>
<Properties name="CustomEmoji">
<Property name="name" type="string" required={true}>
Emoji name, surrounded by identification characters (for example, colons: `:happy_face:`).
@ -72,7 +72,7 @@ Custom Emojis can be added to any entity with text content. The extension ID is
<Row>
<Col>
<Properties>
<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>

View file

@ -13,7 +13,7 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not
<Row>
<Col>
<Properties>
<Properties name="Group">
<Property name="type" type="string" required={true}>
Must be `pub.versia:groups/Group`.
</Property>
@ -84,7 +84,7 @@ Indicates that a [User](/entities/user) wishes to subscribe to a group.
<Row>
<Col>
<Properties>
<Properties name="GroupSubscribe">
<Property name="type" type="string" required={true}>
Must be `pub.versia:groups/Subscribe`.
</Property>
@ -121,7 +121,7 @@ Indicates that a [User](/entities/user) wishes to unsubscribe from a group.
<Row>
<Col>
<Properties>
<Properties name="GroupUnsubscribe">
<Property name="type" type="string" required={true}>
Must be `pub.versia:groups/Unsubscribe`.
</Property>
@ -158,7 +158,7 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use
<Row>
<Col>
<Properties>
<Properties name="GroupSubscribeAccept">
<Property name="type" type="string" required={true}>
Must be `pub.versia:groups/SubscribeAccept`.
</Property>
@ -195,7 +195,7 @@ Indicates that a [Group](#entity-definition) has rejected a [User](/entities/use
<Row>
<Col>
<Properties>
<Properties name="GroupSubscribeReject">
<Property name="type" type="string" required={true}>
Must be `pub.versia:groups/SubscribeReject`.
</Property>
@ -240,7 +240,7 @@ The `GroupFederate` entity allows a group to federate a note to all of its membe
<Row>
<Col>
<Properties>
<Properties name="GroupFederate">
<Property name="type" type="string" required={true}>
Must be `pub.versia:groups/Federate`.
</Property>

View file

@ -29,7 +29,7 @@ This extension adds the following metadata to instances:
<Row>
<Col>
<Properties>
<Properties name="InstanceMessagingExtension">
<Property name="endpoint" type="string" required={true}>
The endpoint to send federation debug messages to.

View file

@ -40,7 +40,7 @@ The entity defined in this document must be inserted in the `pub.versia:interact
<Row>
<Col>
<Properties>
<Properties name="InteractionControls">
<Property name="interaction_type">
Describes permissions for a specific interaction.

View file

@ -18,7 +18,7 @@ Likes are a way for users to show appreciation for a note, like Twitter's "heart
<Row>
<Col>
<Properties>
<Properties name="Like">
<Property name="type" type="string" required={true}>
Must be `pub.versia:likes/Like`.
</Property>
@ -55,7 +55,7 @@ Dislikes are a way for users to show disapproval for a note, like YouTube's "dis
<Row>
<Col>
<Properties>
<Properties name="Dislike">
<Property name="type" type="string" required={true}>
Must be `pub.versia:likes/Dislike`.
</Property>

View file

@ -32,7 +32,7 @@ Migration happens in three steps:
<Row>
<Col>
<Properties>
<Properties name="Migration">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>
@ -69,7 +69,7 @@ The following extensions to [User](/entities/user) are used by the migration ext
<Row>
<Col>
<Properties>
<Properties name="MigrationExtension">
<Property name="previous" type="URI" required={true} typeLink="/types#uri">
If this user has migrated from another instance, this property **MUST** be set to the URI of the user on the previous instance.
</Property>

View file

@ -44,7 +44,7 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)'
<Row>
<Col>
<Properties>
<Properties name="EntityExtension">
<Property name="extensions" type="Record<string, JSONData>" required={false}>
Custom extensions to the entity.
@ -85,7 +85,7 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)'
<Row>
<Col>
<Properties>
<Properties name="CustomEntity">
<Property name="type" type="string" required={true}>
The extension type. [Must follow naming conventions](#naming).
</Property>

View file

@ -19,7 +19,7 @@ Note that there is no `question` field: the question should be included in the `
<Row>
<Col>
<Properties>
<Properties name="Polls">
<Property name="options" type="ContentFormat[]" required="true">
Array of options for the poll. Each option is a [ContentFormat](/structures/content-format) that can contain the same properties as a Note's `content` (e.g. [Custom Emojis](/extensions/custom-emojis) or HTML hyperlinks).
</Property>
@ -98,7 +98,7 @@ If a vote is cast to a poll that is closed, the vote should be rejected with a `
<Row>
<Col>
<Properties>
<Properties name="Vote">
<Property name="type" type="string" required="true">
Must be `pub.versia:polls/Vote`.
</Property>

View file

@ -15,7 +15,7 @@ User reactions are (like every other entity) federated to all followers, and can
<Row>
<Col>
<Properties>
<Properties name="Reaction">
<Property name="type" type="string" required>
Must be `pub.versia:reactions/Reaction`.
</Property>

View file

@ -13,7 +13,7 @@ When an instance receives a report, it *should* be reviewed by a moderator or ad
<Row>
<Col>
<Properties>
<Properties name="Report">
<Property name="uri" type="null" required={false}>
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
</Property>

View file

@ -17,7 +17,7 @@ When a user shares a note, the note's original author **must** receive the entit
<Row>
<Col>
<Properties>
<Properties name="Share">
<Property name="type" type="string" required={true}>
Must be `pub.versia:share/Share`.
</Property>

View file

@ -14,7 +14,7 @@ All properties are optional.
<Row>
<Col>
<Properties>
<Properties name="Vanity">
<Property name="avatar_overlays" type="ContentFormat[]" typeLink="/structures/content-format" required={false}>
Overlay images to be placed on top of the user's avatar, like this: [example overlay from Discord](https://cdn.discordapp.com/avatar-decoration-presets/a_949a575b693c81ced8f56a7579d0969f.png).

View file

@ -22,7 +22,7 @@ Messages sent over the WebSocket connection are JSON objects.
<Row>
<Col>
<Properties>
<Properties name="WebSocketMessage">
<Property name="signature" type="string" required={true}>
Same as the `Versia-Signature` header in HTTP requests.
</Property>

View file

@ -14,7 +14,7 @@ ALL kinds of HTTP requests/responses between instances **MUST** include a [Signa
<Row>
<Col>
<Properties>
<Properties name="HTTP Request">
<Property name="Accept" type="string" required={true}>
Must include `application/json`.
</Property>
@ -61,7 +61,7 @@ IETF draft [draft-polli-ratelimit-headers-02](https://www.ietf.org/archive/id/dr
<Row>
<Col>
<Properties>
<Properties name="HTTP Response">
<Property name="Content-Type" type="string" required={true}>
Must include `application/json; charset=utf-8`.
</Property>

View file

@ -12,7 +12,7 @@ Versia Links are a way to reference entities in the Versia Protocol, in a way th
<Row>
<Col>
<Properties>
<Properties name="Versia Link">
<Property name="scheme" type="string" required={true}>
Must be `web+versia://` so that browsers and applications can recognize it.

View file

@ -17,7 +17,7 @@ Pages should be limited to a reasonable number of entities, such as 20 or 80.
<Row>
<Col>
<Properties>
<Properties name="Collection">
<Property name="author" type="URI | null" required={true} typeLink="/types#uri">
Author of the collection. Usually the user who owns the collection. [Can be set to `null` to represent the instance](/entities/instance-metadata#the-null-author).
</Property>
@ -88,7 +88,7 @@ URI Collections are identical to regular collections, but they contain only URIs
<Row>
<Col>
<Properties>
<Properties name="URICollection">
<Property name="author" type="URI | null" required={true} typeLink="/types#uri">
Author of the collection. Usually the user who owns the collection. [Can be set to `null` to represent the instance](/entities/instance-metadata#the-null-author).
</Property>

View file

@ -71,7 +71,7 @@ It is a good idea to provide at least two versions of an image (if possible): on
<Row>
<Col>
<Properties>
<Properties name="ContentFormat">
<Property name="content" type="string | URI" required={true}>
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.
</Property>

105
components/Property.tsx Normal file
View file

@ -0,0 +1,105 @@
"use client";
import Link from "next/link";
import { type ReactNode, createContext, useContext } from "react";
export const PropertyContext = createContext<{
name: string;
}>({
name: "",
});
export function Properties({
children,
name,
}: { children: ReactNode; name: string }) {
return (
<div className="my-6">
<ul className="m-0 max-w-[calc(theme(maxWidth.lg)-theme(spacing.8))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5">
<PropertyContext.Provider value={{ name }}>
{children}
</PropertyContext.Provider>
</ul>
</div>
);
}
const numberTypeTooltips = {
f64: "64-bit floating-point number",
i64: "64-bit signed integer",
u64: "64-bit unsigned integer",
};
export function Property({
name,
children,
type,
typeLink,
numberType,
required,
}: {
name: string;
children: ReactNode;
type?: string;
typeLink?: string;
numberType?: "f64" | "i64" | "u64";
required?: boolean;
}) {
const { name: contextName } = useContext(PropertyContext);
const idFormat = (name: string) =>
name
.toLowerCase()
.replace(/[^a-z0-9]/g, "-")
.replace(/-+/g, "-")
.replace(/^-|-$/g, "");
return (
<li className="m-0 px-0 py-4 first:pt-0 last:pb-0">
<dl
id={`${idFormat(contextName)}-${idFormat(name)}`}
className="m-0 flex flex-wrap items-center gap-x-3 gap-y-2"
>
<dt className="sr-only">Name</dt>
<dd>
<code>{name}</code>
</dd>
{required && (
<>
<dt className="sr-only">Required</dt>
<dd className="inline-flex items-center rounded-md bg-brand-50 px-2 py-0 text-xs font-medium text-brand-700 ring-1 ring-inset ring-brand-500/10 dark:bg-brand-500/10 dark:text-brand-100 dark:ring-brand-200/20">
Required
</dd>
</>
)}
{numberType && (
<>
<dt className="sr-only">Type</dt>
<dd
className="inline-flex items-center rounded-md bg-blue-50 px-2 py-0 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-500/10 dark:bg-blue-500/10 dark:text-blue-100 dark:ring-blue-200/20 hover:cursor-pointer"
title={numberTypeTooltips[numberType]}
>
{numberType}
</dd>
</>
)}
{type && (
<>
<dt className="sr-only">Type</dt>
<dd className="font-mono text-xs text-zinc-400 dark:text-zinc-500">
{typeLink ? (
<Link href={typeLink}>{type}</Link>
) : (
type
)}
</dd>
</>
)}
<dt className="sr-only">Description</dt>
<dd className="w-full flex-none [&>:first-child]:mt-0 [&>:last-child]:mb-0">
{children}
</dd>
</dl>
</li>
);
}

View file

@ -9,6 +9,7 @@ export const a = Link;
// biome-ignore lint/performance/noBarrelFile: <explanation>
export { Button } from "./Button";
export { CodeGroup, Code as code, Pre as pre } from "./Code";
export { Property, Properties } from "./Property";
export function wrapper({ children }: { children: ReactNode }) {
return (
@ -80,81 +81,3 @@ export function Col({
</div>
);
}
export function Properties({ children }: { children: ReactNode }) {
return (
<div className="my-6">
<ul className="m-0 max-w-[calc(theme(maxWidth.lg)-theme(spacing.8))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5">
{children}
</ul>
</div>
);
}
const numberTypeTooltips = {
f64: "64-bit floating-point number",
i64: "64-bit signed integer",
u64: "64-bit unsigned integer",
};
export function Property({
name,
children,
type,
typeLink,
numberType,
required,
}: {
name: string;
children: ReactNode;
type?: string;
typeLink?: string;
numberType?: "f64" | "i64" | "u64";
required?: boolean;
}) {
return (
<li className="m-0 px-0 py-4 first:pt-0 last:pb-0">
<dl className="m-0 flex flex-wrap items-center gap-x-3 gap-y-2">
<dt className="sr-only">Name</dt>
<dd>
<code>{name}</code>
</dd>
{required && (
<>
<dt className="sr-only">Required</dt>
<dd className="inline-flex items-center rounded-md bg-brand-50 px-2 py-0 text-xs font-medium text-brand-700 ring-1 ring-inset ring-brand-500/10 dark:bg-brand-500/10 dark:text-brand-100 dark:ring-brand-200/20">
Required
</dd>
</>
)}
{numberType && (
<>
<dt className="sr-only">Type</dt>
<dd
className="inline-flex items-center rounded-md bg-blue-50 px-2 py-0 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-500/10 dark:bg-blue-500/10 dark:text-blue-100 dark:ring-blue-200/20 hover:cursor-pointer"
title={numberTypeTooltips[numberType]}
>
{numberType}
</dd>
</>
)}
{type && (
<>
<dt className="sr-only">Type</dt>
<dd className="font-mono text-xs text-zinc-400 dark:text-zinc-500">
{typeLink ? (
<Link href={typeLink}>{type}</Link>
) : (
type
)}
</dd>
</>
)}
<dt className="sr-only">Description</dt>
<dd className="w-full flex-none [&>:first-child]:mt-0 [&>:last-child]:mb-0">
{children}
</dd>
</dl>
</li>
);
}