mirror of
https://github.com/versia-pub/docs.git
synced 2026-01-26 20:16:02 +01:00
commit
92c96bcd3e
82
app/api/basics/page.mdx
Normal file
82
app/api/basics/page.mdx
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
export const metadata = {
|
||||||
|
title: "API",
|
||||||
|
description: "Defines the server-to-server API for Versia's federation.",
|
||||||
|
}
|
||||||
|
|
||||||
|
# API
|
||||||
|
|
||||||
|
Versia defines a very simple API for server-to-server communication, mainly fetching and sending entities. It is clearly namespaced and versioned, to avoid confusion with implementations' existing HTTP APIs. {{ className: "lead" }}
|
||||||
|
|
||||||
|
## API Versioning
|
||||||
|
|
||||||
|
Every Versia API endpoint is prefixed with `/.versia/vX/`, where `X` is the version of the API. The current version is `0.6`, so the current API prefix is `/.versia/v0.6/`. This versioning is used to avoid breaking changes in the future, and to allow for backwards compatibility.
|
||||||
|
|
||||||
|
Requests not encrypted with TLS (aka HTTPS) **must not** be sent or responded to. All implementations are required to use TLS 1.2 or higher, and to support HTTP/2.
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Implementations have no obligation to support more than one Versia version. It is recommended to always support the latest version, as it helps avoid bogging down the network with old versions.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
## Signatures
|
||||||
|
|
||||||
|
API requests/responses between instances **must** include a [Signature](/signatures), signed with the [instance's private key](/entities/instance-metadata), as defined in [Signatures](/signatures).
|
||||||
|
|
||||||
|
## Encoding
|
||||||
|
|
||||||
|
"URL-encoding" is the mechanism used to encode data containing special characters in URLs. When this specification refers to "URL-encoding", it means the encoding defined in [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-2.1).
|
||||||
|
|
||||||
|
## Domain
|
||||||
|
|
||||||
|
Versia defines a **domain** as the hostname of an instance, which is used to identify the instance in the network. It **must** be a valid hostname, and cannot include a port number (the HTTPS port is always 443).
|
||||||
|
|
||||||
|
Defining a domain is very complicated, so please refer to the following examples:
|
||||||
|
|
||||||
|
``` {{ "title": "Valid Domains" }}
|
||||||
|
example.com
|
||||||
|
test.localhost
|
||||||
|
sus.example.org
|
||||||
|
xn--ls8h.la
|
||||||
|
1.0.1.7.0.8.0.0.0.0.7.4.0.1.0.0.2.ip6.arpa # We know what you did
|
||||||
|
```
|
||||||
|
|
||||||
|
``` {{ "title": "Invalid Domains" }}
|
||||||
|
example.com:3000 # ❌️ Invalid: port number is not allowed
|
||||||
|
test..localhost # ❌️ Invalid: double dot is not allowed
|
||||||
|
example.com. # ❌️ Invalid: trailing dot is not allowed
|
||||||
|
test.org/ # ❌️ Invalid: trailing slash is not allowed
|
||||||
|
test.org/sus # ❌️ Invalid: path is not allowed
|
||||||
|
💩.la # ❌️ Invalid: IDNs must be Punycode encoded
|
||||||
|
https://bob.org # ❌️ Invalid: protocol is not allowed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Redirects
|
||||||
|
|
||||||
|
API endpoints **MUST NOT** redirect to other endpoints, with the following exceptions:
|
||||||
|
- When the request does not have an `Accept: application/vnd.versia+json` header, the server **MAY** redirect to an HTML representation of the resource.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
HTTP to HTTPS redirects are **NOT** allowed for API endpoints.
|
||||||
|
|
||||||
|
This is to force all API communication to be encrypted, and to avoid accidentally leaking sensitive data over unencrypted connections.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
This is forbidden:
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /.versia/v0.6/entities/user/1234
|
||||||
|
Host: example.com
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
|
||||||
|
HTTP/1.1 301 Moved Permanently
|
||||||
|
Location: https://example.com/users/1234
|
||||||
|
```
|
||||||
|
|
||||||
|
This is allowed:
|
||||||
|
```http
|
||||||
|
GET /.versia/v0.6/entities/user/1234
|
||||||
|
Host: example.com
|
||||||
|
Accept: text/html
|
||||||
|
|
||||||
|
HTTP/1.1 301 Moved Permanently
|
||||||
|
Location: https://example.com/users/1234
|
||||||
|
```
|
||||||
238
app/api/endpoints/page.mdx
Normal file
238
app/api/endpoints/page.mdx
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
export const metadata = {
|
||||||
|
title: "API Endpoints",
|
||||||
|
description: "Explains all endpoints in Versia's federation API.",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Endpoints
|
||||||
|
|
||||||
|
## Well-known
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This endpoint is exempt from the signature requirement. No signatures are required for requests or responses to it.
|
||||||
|
|
||||||
|
The following `Accept` headers are also allowed for requests to this endpoint:
|
||||||
|
- `application/jrd+json`
|
||||||
|
- `application/json`
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
|
||||||
|
<Properties name="Well-known">
|
||||||
|
<Property name="endpoint">
|
||||||
|
Must be `/.well-known/versia`.
|
||||||
|
</Property>
|
||||||
|
<Property name="method">
|
||||||
|
Must be `GET`.
|
||||||
|
</Property>
|
||||||
|
<Property name="response">
|
||||||
|
A small JSON object with a single attribute:
|
||||||
|
|
||||||
|
- `versions`: Supported Versia Protocol versions.
|
||||||
|
- Versions marked as "Working Draft X" are represented as `0.X`.
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col sticky>
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example request' }}
|
||||||
|
GET /.well-known/versia
|
||||||
|
Host: b.social
|
||||||
|
Accept: application/jrd+json
|
||||||
|
```
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example response' }}
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/jrd+json
|
||||||
|
|
||||||
|
{
|
||||||
|
"versions": [
|
||||||
|
"0.6.0",
|
||||||
|
"0.5.0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
## Instance metadata
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This endpoint is exempt from the signature requirement. No signatures are required for requests or responses to it.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
|
||||||
|
<Properties name="InstanceMetadata">
|
||||||
|
<Property name="endpoint">
|
||||||
|
Must be `/.versia/v0.6/instance`.
|
||||||
|
</Property>
|
||||||
|
<Property name="method">
|
||||||
|
Must be `GET`.
|
||||||
|
</Property>
|
||||||
|
<Property name="response">
|
||||||
|
Instance's metadata, as defined in the [Instance Metadata](/entities/instance-metadata) document.
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
<Col sticky>
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example request' }}
|
||||||
|
GET /.versia/v0.6/instance
|
||||||
|
Host: b.social
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
```
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example response' }}
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/vnd.versia+json; charset=utf-8
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "InstanceMetadata",
|
||||||
|
"name": "Bob!!",
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
## Entity data
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Properties name="EntityData">
|
||||||
|
<Property name="endpoint">
|
||||||
|
Must be `/.versia/v0.6/entities/{entity_type}/{id}`.
|
||||||
|
|
||||||
|
- `{entity_type}`: The type of the entity to fetch, URL-encoded.
|
||||||
|
- `{id}`: The ID of the entity to fetch, URL-encoded.
|
||||||
|
|
||||||
|
Example: `GET /.versia/v0.6/entities/pub.versia%3Agroups%2FGroup/1234` fetches the [Group](/extensions/groups) entity with ID `1234`.
|
||||||
|
</Property>
|
||||||
|
<Property name="method">
|
||||||
|
Must be `GET`.
|
||||||
|
</Property>
|
||||||
|
<Property name="response">
|
||||||
|
Entity data as JSON, as defined in its [Entity](/entities) definition document.
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col sticky>
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example request' }}
|
||||||
|
GET /.versia/v0.6/entities/user/1234
|
||||||
|
Host: b.social
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
```
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example response' }}
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/vnd.versia+json; charset=utf-8
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "User",
|
||||||
|
"id": "1234",
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
## Entity collections
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Properties name="EntityCollection">
|
||||||
|
<Property name="endpoint">
|
||||||
|
Must be `/.versia/v0.6/entities/{entity_type}/{id}/collections/{collection_type}`.
|
||||||
|
|
||||||
|
- `{entity_type}`: The type of the entity to fetch, URL-encoded.
|
||||||
|
- `{id}`: The ID of the entity to fetch, URL-encoded.
|
||||||
|
- `{collection_type}`: The type of the collection to fetch, URL-encoded.
|
||||||
|
|
||||||
|
Example: `GET /.versia/v0.6/entities/User/1234/collections/followers` fetches the followers of the user with ID `1234`.
|
||||||
|
</Property>
|
||||||
|
<Property name="method">
|
||||||
|
Must be `GET`.
|
||||||
|
</Property>
|
||||||
|
<Property name="response">
|
||||||
|
Must be either a [Collection](/structures/collection) or a [URICollection](/structures/collection#uri-collection) as JSON.
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col sticky>
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example request' }}
|
||||||
|
GET /.versia/v0.6/entities/user/1234/collections/followers
|
||||||
|
Host: b.social
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
```
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example response' }}
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Content-Type: application/vnd.versia+json; charset=utf-8
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "Followers",
|
||||||
|
"id": "1234",
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
### Pagination
|
||||||
|
|
||||||
|
Collections MUST support pagination, using the following URI parameters:
|
||||||
|
|
||||||
|
- `offset`: The number of items to skip before returning the first item. This is a zero-based index.
|
||||||
|
- `limit`: The maximum number of items to return. This is a one-based index. Implementations MUST support a minimum of `1` and a maximum of `40` items.
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example paginated collection request' }}
|
||||||
|
GET /.versia/v0.6/entities/user/1234/collections/followers?offset=10&limit=20
|
||||||
|
Host: b.social
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inbox
|
||||||
|
|
||||||
|
The inbox endpoint is used for instances to send entities to each other. It is a single endpoint that can receive messages for every user (also known as a shared inbox).
|
||||||
|
|
||||||
|
The delivery mechanism is described further in the [Federation](/federation#inboxes) document.
|
||||||
|
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Properties name="Inbox">
|
||||||
|
<Property name="endpoint">
|
||||||
|
Must be `/.versia/v0.6/inbox`.
|
||||||
|
</Property>
|
||||||
|
<Property name="method">
|
||||||
|
Must be `POST`.
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col sticky>
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example request' }}
|
||||||
|
POST /.versia/v0.6/inbox
|
||||||
|
Host: b.social
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
Content-Type: application/vnd.versia+json; charset=utf-8
|
||||||
|
|
||||||
|
{
|
||||||
|
"type": "Note",
|
||||||
|
"id": "1234",
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
@ -8,6 +8,27 @@ export const metadata = {
|
||||||
|
|
||||||
This page lists changes since Working Draft 3. {{ className: 'lead' }}
|
This page lists changes since Working Draft 3. {{ className: 'lead' }}
|
||||||
|
|
||||||
|
## Since WD 5
|
||||||
|
|
||||||
|
- Added a new `content-type` for Versia entities: `application/vnd.versia+json`.
|
||||||
|
- Overhauled the Instance-to-Instance API to have clearly defined and namespaced endpoints, under `/.versia/v0.6/`, instead of letting implementations define their own endpoints.
|
||||||
|
- Removed per-User keypairs: now, only the instance keypair is used for signing.
|
||||||
|
- Moved [Delegation](/extensions/delegation) to an extension
|
||||||
|
- Changed the contents of the [Well-Known Versia Endpoint](/api/endpoints#well-known) to only list supported protocol versions.
|
||||||
|
- Modified how URIs and references to other entities are handled:
|
||||||
|
- The `uri` field has been removed from all entities.
|
||||||
|
- Every field that used to be a URI now uses that entity's `id` field.
|
||||||
|
- New endpoints have been defined under `/.versia/v0.6/` to fetch entities by their `id`.
|
||||||
|
- Added [References](/types#reference) as a way to refer to other entities.
|
||||||
|
- Changed usage of "`null` authors" to simply being an optional field.
|
||||||
|
- Added more guidelines on [JSON data handling](/json).
|
||||||
|
- Clarified the meaning of [Domain](/api/basics#domain) in the context of Versia.
|
||||||
|
- Changes to [Note](/entities/note):
|
||||||
|
- `is_sensitive`, `attachments`, `mentions` and `previews` are now required.
|
||||||
|
- Changes to [User](/entities/user):
|
||||||
|
- `fields`, `manually_approves_followers` and `indexable` are now required.
|
||||||
|
- Removed "short pronoun" from [Vanity Extension](/extensions/vanity) (union types are tricky to parse in strongly typed languages).
|
||||||
|
|
||||||
## Since WD 4
|
## Since WD 4
|
||||||
|
|
||||||
- Removed URI from [Report](/extensions/reports), and replaced `reason` with `tags`.
|
- Removed URI from [Report](/extensions/reports), and replaced `reason` with `tags`.
|
||||||
|
|
|
||||||
|
|
@ -5,32 +5,33 @@ export const metadata = {
|
||||||
|
|
||||||
# Delete
|
# Delete
|
||||||
|
|
||||||
Signals the deletion of an entity. It is a [**Transient Entity**](/entities#transient-entities). {{ className: 'lead' }}
|
Signals the deletion of an entity. {{ className: 'lead' }}
|
||||||
|
|
||||||
## Authorization
|
## Authorization
|
||||||
|
|
||||||
Implementations **must** ensure that the author of the `Delete` entity has the authorization to delete the target entity.
|
Implementations **must** ensure that the author of the `Delete` entity has the authorization to delete the target entity.
|
||||||
|
|
||||||
Having the authorization is defined as:
|
Having the authorization is defined as:
|
||||||
- The author is the creator of the target entity (including [delegation](/federation/delegation)).
|
- The author is the creator of the target entity (including [delegation](/extensions/delegation)).
|
||||||
- The author is the instance.
|
- The author is the instance.
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Delete">
|
<Properties name="Delete">
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the `User` who is deleting the entity.
|
||||||
</Property>
|
|
||||||
<Property name="author" type="URI | null" required={true} typeLink="/types#uri">
|
|
||||||
URI of the `User` who is deleting the entity. [Can be set to `null` to represent the instance](/entities/instance-metadata#the-null-author).
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="deleted_type" type="string" required={true}>
|
<Property name="deleted_type" type="string" required={true}>
|
||||||
Type of the entity being deleted.
|
Type of the entity being deleted.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="deleted" type="URI" required={true} typeLink="/types#uri">
|
<Property name="deleted" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the entity being deleted.
|
[Reference](/types#reference) to the entity being deleted.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -40,11 +41,10 @@ Having the authorization is defined as:
|
||||||
```jsonc {{ title: 'Example Delete' }}
|
```jsonc {{ title: 'Example Delete' }}
|
||||||
{
|
{
|
||||||
"type": "Delete",
|
"type": "Delete",
|
||||||
"id": "9b3212b8-529c-435a-8798-09ebbc17ca74",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"deleted_type": "Note",
|
"deleted_type": "Note",
|
||||||
"deleted": "https://example.com/notes/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
"deleted": "02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,17 +11,18 @@ export const metadata = {
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="FollowAccept">
|
<Properties name="FollowAccept">
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the `User` considered the 'followee', i.e. the user who is being followed.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="follower" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the `User` considered the 'followee', i.e. the user who is being followed.
|
[Reference](/types#reference) to the `User` considered the 'follower', i.e. the user who is trying to follow the author.
|
||||||
</Property>
|
|
||||||
<Property name="follower" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the `User` considered the 'follower', i.e. the user who is trying to follow the author.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -31,10 +32,9 @@ export const metadata = {
|
||||||
```jsonc {{ title: 'Example FollowAccept' }}
|
```jsonc {{ title: 'Example FollowAccept' }}
|
||||||
{
|
{
|
||||||
"type": "FollowAccept",
|
"type": "FollowAccept",
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"follower": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
"follower": "example.com:02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,17 +21,18 @@ But it can also be used when Bob is already following Alice, in the case that:
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="FollowReject">
|
<Properties name="FollowReject">
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the `User` considered the 'followee', i.e. the user who is being followed.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="follower" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the `User` considered the 'followee', i.e. the user who is being followed.
|
[Reference](/types#reference) to the `User` considered the 'follower', i.e. the user who is trying to follow the author.
|
||||||
</Property>
|
|
||||||
<Property name="follower" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the `User` considered the 'follower', i.e. the user who is trying to follow the author.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -41,10 +42,9 @@ But it can also be used when Bob is already following Alice, in the case that:
|
||||||
```jsonc {{ title: 'Example FollowReject' }}
|
```jsonc {{ title: 'Example FollowReject' }}
|
||||||
{
|
{
|
||||||
"type": "FollowReject",
|
"type": "FollowReject",
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"follower": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
"follower": "example.com:02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,17 +53,18 @@ Once a follow relationship is established, the **followee**'s instance should se
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Follow">
|
<Properties name="Follow">
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the `User` considered the 'follower'.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="followee" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the `User` considered the 'follower'.
|
[Reference](/types#reference) to the `User` that is being followed.
|
||||||
</Property>
|
|
||||||
<Property name="followee" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the `User` that is being followed.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -73,10 +74,9 @@ Once a follow relationship is established, the **followee**'s instance should se
|
||||||
```jsonc {{ title: 'Example Follow' }}
|
```jsonc {{ title: 'Example Follow' }}
|
||||||
{
|
{
|
||||||
"type": "Follow",
|
"type": "Follow",
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"followee": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
"followee": "example.com:02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,6 @@ export const metadata = {
|
||||||
|
|
||||||
Contains metadata about a Versia instance, such as capabilities and endpoints. {{ className: 'lead' }}
|
Contains metadata about a Versia instance, such as capabilities and endpoints. {{ className: 'lead' }}
|
||||||
|
|
||||||
## The `null` Author
|
|
||||||
|
|
||||||
On some entities that have an `author` field, the `author` can be `null` to represent the instance itself as the author (like ActivityPub's Server Actors). In this case, the instance's public key should be used to verify the entity. To know which instance's public key to use, the entity signature should be used.
|
|
||||||
|
|
||||||
Check the entity's documentation page to see if it supports this (it will be noted in the `author` field).
|
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
|
|
@ -21,9 +15,6 @@ Check the entity's documentation page to see if it supports this (it will be not
|
||||||
<Property name="id" type="null">
|
<Property name="id" type="null">
|
||||||
This entity does not have an ID.
|
This entity does not have an ID.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="uri" type="null">
|
|
||||||
This entity does not have a URI.
|
|
||||||
</Property>
|
|
||||||
<Property name="name" type="string" required={true}>
|
<Property name="name" type="string" required={true}>
|
||||||
Friendly name of the instance, for humans.
|
Friendly name of the instance, for humans.
|
||||||
</Property>
|
</Property>
|
||||||
|
|
@ -57,11 +48,8 @@ Check the entity's documentation page to see if it supports this (it will be not
|
||||||
<Property name="description" type="string" required={false}>
|
<Property name="description" type="string" required={false}>
|
||||||
Long description of the instance, for humans. Should be around 100-200 words.
|
Long description of the instance, for humans. Should be around 100-200 words.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="host" type="string" required={true}>
|
<Property name="domain" type="Domain" typeLink="/api/basics#domain" required={true}>
|
||||||
Hostname of the instance. Includes the port if it is not the default (i.e. `443` for HTTPS).
|
Domain of the instance, used for federation.
|
||||||
</Property>
|
|
||||||
<Property name="shared_inbox" type="URI" required={false}>
|
|
||||||
URI to the instance's shared inbox, if supported.
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="public_key" type="PublicKey" required={true}>
|
<Property name="public_key" type="PublicKey" required={true}>
|
||||||
Public key of the instance.
|
Public key of the instance.
|
||||||
|
|
@ -76,20 +64,6 @@ Check the entity's documentation page to see if it supports this (it will be not
|
||||||
- `algorithm`: Algorithm used for the public key. Can only be `ed25519` for now.
|
- `algorithm`: Algorithm used for the public key. Can only be `ed25519` for now.
|
||||||
- `key`: Instance public key, in [SPKI-encoded base64](/signatures#exporting-the-public-key).
|
- `key`: Instance public key, in [SPKI-encoded base64](/signatures#exporting-the-public-key).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="moderators" type="URI" required={false}>
|
|
||||||
URI to [Collection](/structures/collection) of instance moderators.
|
|
||||||
|
|
||||||
<Note>
|
|
||||||
This is for human consumption (such as moderator contact), not for any kind of protocol authorization.
|
|
||||||
</Note>
|
|
||||||
</Property>
|
|
||||||
<Property name="admins" type="URI" required={false}>
|
|
||||||
URI to [Collection](/structures/collection) of instance administrators.
|
|
||||||
|
|
||||||
<Note>
|
|
||||||
This is for human consumption (such as admin contact), not for any kind of protocol authorization.
|
|
||||||
</Note>
|
|
||||||
</Property>
|
|
||||||
<Property name="logo" type="ContentFormat" required={false} typeLink="/structures/content-format">
|
<Property name="logo" type="ContentFormat" required={false} typeLink="/structures/content-format">
|
||||||
Logo of the instance. Must be an image format (`image/*`).
|
Logo of the instance. Must be an image format (`image/*`).
|
||||||
</Property>
|
</Property>
|
||||||
|
|
@ -122,10 +96,7 @@ Check the entity's documentation page to see if it supports this (it will be not
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"description": "Server for Jim's Jolly Jimjams, a social network for fans of Jimjams.",
|
"description": "Server for Jim's Jolly Jimjams, a social network for fans of Jimjams.",
|
||||||
"host": "social.jimjams.com",
|
"domain": "social.jimjams.com",
|
||||||
"shared_inbox": "https://social.jimjams.com/inbox",
|
|
||||||
"moderators": "https://social.jimjams.com/moderators",
|
|
||||||
"admins": "https://social.jimjams.com/admins",
|
|
||||||
"logo": {
|
"logo": {
|
||||||
"image/png": {
|
"image/png": {
|
||||||
"content": "https://social.jimjams.com/files/logo.png"
|
"content": "https://social.jimjams.com/files/logo.png"
|
||||||
|
|
@ -148,3 +119,12 @@ Check the entity's documentation page to see if it supports this (it will be not
|
||||||
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
### Collections
|
||||||
|
|
||||||
|
The following [Collections](/structures/collection) are available:
|
||||||
|
|
||||||
|
- `moderators`: [Collection](/structures/collection) of instance moderators ([Users](/entities/user)).
|
||||||
|
- `admins`: [Collection](/structures/collection) of instance administrators ([Users](/entities/user)).
|
||||||
|
|
||||||
|
These can be fetched using the [Federation API](/api/endpoints#entity-collections)
|
||||||
|
|
@ -16,11 +16,11 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Note">
|
<Properties name="Note">
|
||||||
<Property name="attachments" type="ContentFormat[]" required={false} typeLink="/structures/content-format">
|
<Property name="attachments" type="ContentFormat[]" required={true} typeLink="/structures/content-format">
|
||||||
Media attachments to the note. May be any format. **Must** be remote.
|
Media attachments to the note. May be any format. **Must** be remote.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the `User` considered the author of the note.
|
[Reference](/types#reference) to the `User` considered the author of the note.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="category" type="Category" required={false}>
|
<Property name="category" type="Category" required={false}>
|
||||||
Category of the note. Useful for clients to render notes differently depending on their intended purpose.
|
Category of the note. Useful for clients to render notes differently depending on their intended purpose.
|
||||||
|
|
@ -36,28 +36,6 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
| "messaging"; // Like Discord, Element (Matrix), Signal
|
| "messaging"; // Like Discord, Element (Matrix), Signal
|
||||||
```
|
```
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="collections" type="NoteCollections" required={true}>
|
|
||||||
Collections related to the note. Must contain at least `replies` and `quotes`.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
type URI = string;
|
|
||||||
|
|
||||||
type NoteCollections = {
|
|
||||||
replies: URI;
|
|
||||||
quotes: URI;
|
|
||||||
// Same format as type on Extensions
|
|
||||||
[key: ExtensionsKey]: URI;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
All URIs must resolve to either a [Collection](/structures/collection) or a [URI Collection](/structures/collection#uri-collection) of the appropriate entities. Extensions may add additional collections.
|
|
||||||
|
|
||||||
### Replies
|
|
||||||
All replies to this note (have this note as their `replies_to`). [URI Collection](/structures/collection#uri-collection) of [Note](/entities/note) entities.
|
|
||||||
|
|
||||||
### Quotes
|
|
||||||
All quotes of this note (have this note as their `quotes`). [URI Collection](/structures/collection#uri-collection) of [Note](/entities/note) entities.
|
|
||||||
</Property>
|
|
||||||
<Property name="content" type="ContentFormat" required={false} typeLink="/structures/content-format">
|
<Property name="content" type="ContentFormat" required={false} typeLink="/structures/content-format">
|
||||||
The content of the note. Must be text format (`text/html`, `text/markdown`, etc). Must not be remote.
|
The content of the note. Must be text format (`text/html`, `text/markdown`, etc). Must not be remote.
|
||||||
</Property>
|
</Property>
|
||||||
|
|
@ -72,8 +50,8 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="group" type="URI | "public" | "followers"" required={false} typeLink="/types#uri">
|
<Property name="group" type="Reference | "public" | "followers"" required={false} typeLink="/types#reference">
|
||||||
URI of a [Group](/extensions/groups) that the note is only visible in, or one of the following strings:
|
[Reference](/types#reference) to a [Group](/extensions/groups) that the note is only visible in, or one of the following strings:
|
||||||
- `public`: The note is visible to anyone.
|
- `public`: The note is visible to anyone.
|
||||||
- `followers`: The note is visible only to the author's followers.
|
- `followers`: The note is visible only to the author's followers.
|
||||||
|
|
||||||
|
|
@ -83,13 +61,13 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
If the implementation does not support the [Groups Extension](/extensions/groups), any value other than `public` or `followers` should be treated as `null`.
|
If the implementation does not support the [Groups Extension](/extensions/groups), any value other than `public` or `followers` should be treated as `null`.
|
||||||
</Note>
|
</Note>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="is_sensitive" type="boolean" required={false}>
|
<Property name="is_sensitive" type="boolean" required={true}>
|
||||||
Whether the note contains "sensitive content". This can be used with `subject` as a "content warning" feature.
|
Whether the note contains "sensitive content". This can be used with `subject` as a "content warning" feature.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="mentions" type="URI[]" required={false} typeLink="/types#uri">
|
<Property name="mentions" type="Reference[]" required={true} typeLink="/types#reference">
|
||||||
URIs of [Users](/entities/user) that should be notified of the note. Similar to Twitter's `@` mentions. The note may also contain mentions in the content, however only the mentions in this field should trigger notifications.
|
[References](/types#reference) to [Users](/entities/user) that should be notified of the note. Similar to Twitter's `@` mentions. The note may also contain mentions in the content, however only the mentions in this field should trigger notifications.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="previews" type="LinkPreview[]" required={false}>
|
<Property name="previews" type="LinkPreview[]" required={true}>
|
||||||
Previews for any links in the publication. This is to avoid the [stampeding mastodon problem](https://github.com/mastodon/mastodon/issues/23662) where a link preview is fetched by every instance that sees the publication, creating an accidental DDOS attack.
|
Previews for any links in the publication. This is to avoid the [stampeding mastodon problem](https://github.com/mastodon/mastodon/issues/23662) where a link preview is fetched by every instance that sees the publication, creating an accidental DDOS attack.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
|
@ -106,11 +84,11 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
Implementations should make sure not to trust the previews, as they could be faked by malicious remote instances. This is not a very good attack vector, but it is still possible to redirect users to malicious links.
|
Implementations should make sure not to trust the previews, as they could be faked by malicious remote instances. This is not a very good attack vector, but it is still possible to redirect users to malicious links.
|
||||||
</Note>
|
</Note>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="quotes" type="URI" required={false} typeLink="/types#uri">
|
<Property name="quotes" type="Reference" required={false} typeLink="/types#reference">
|
||||||
URI of the note that this note is quoting, if any. Quoting is similar to replying, but does not notify the author of the quoted note. Inspired by Twitter's "quote tweet" feature.
|
[Reference](/types#reference) to the note that this note is quoting, if any. Quoting is similar to replying, but does not notify the author of the quoted note. Inspired by Twitter's "quote tweet" feature.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="replies_to" type="URI" required={false} typeLink="/types#uri">
|
<Property name="replies_to" type="Reference" required={false} typeLink="/types#reference">
|
||||||
URI of the note that this note is a reply to, if any.
|
[Reference](/types#reference) to the note that this note is a reply to, if any.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="subject" type="string" required={false}>
|
<Property name="subject" type="string" required={false}>
|
||||||
A subject for the note. Useful for clients to display a "content warning" or "spoiler" feature, such as on Mastodon. Must be a plaintext string (`text/plain`).
|
A subject for the note. Useful for clients to display a "content warning" or "spoiler" feature, such as on Mastodon. Must be a plaintext string (`text/plain`).
|
||||||
|
|
@ -123,7 +101,6 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
{
|
{
|
||||||
"id": "01902e09-0f8b-72de-8ee3-9afc0cf5eae1",
|
"id": "01902e09-0f8b-72de-8ee3-9afc0cf5eae1",
|
||||||
"type": "Note",
|
"type": "Note",
|
||||||
"uri": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1",
|
|
||||||
"created_at": "2024-06-19T01:07:44.139Z",
|
"created_at": "2024-06-19T01:07:44.139Z",
|
||||||
"attachments": [ // [!code focus:100]
|
"attachments": [ // [!code focus:100]
|
||||||
{
|
{
|
||||||
|
|
@ -131,6 +108,9 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
"content": "https://cdn.versia.social/29e810bf4707fef373d886af322089d5db300fce66e4e073efc26827f10825f6/image.webp",
|
"content": "https://cdn.versia.social/29e810bf4707fef373d886af322089d5db300fce66e4e073efc26827f10825f6/image.webp",
|
||||||
"remote": true,
|
"remote": true,
|
||||||
"thumbhash": "1QcSHQRnh493V4dIh4eXh1h4kJUI",
|
"thumbhash": "1QcSHQRnh493V4dIh4eXh1h4kJUI",
|
||||||
|
"description": null,
|
||||||
|
"fps": null,
|
||||||
|
"duration": null,
|
||||||
"height": 960,
|
"height": 960,
|
||||||
"size": 221275,
|
"size": 221275,
|
||||||
"hash": {
|
"hash": {
|
||||||
|
|
@ -143,6 +123,12 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"content": "https://cdn.lysand.org/68c02dd11c179ef4d170b05393f6e72133dd0ad733f40d41b42363d8784e8d5d/fire.txt",
|
"content": "https://cdn.lysand.org/68c02dd11c179ef4d170b05393f6e72133dd0ad733f40d41b42363d8784e8d5d/fire.txt",
|
||||||
"remote": true,
|
"remote": true,
|
||||||
|
"description": null,
|
||||||
|
"thumbhash": null,
|
||||||
|
"width": null,
|
||||||
|
"height": null,
|
||||||
|
"fps": null,
|
||||||
|
"duration": null
|
||||||
"size": 8,
|
"size": 8,
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "68c02dd11c179ef4d170b05393f6e72133dd0ad733f40d41b42363d8784e8d5d"
|
"sha256": "68c02dd11c179ef4d170b05393f6e72133dd0ad733f40d41b42363d8784e8d5d"
|
||||||
|
|
@ -150,15 +136,8 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"author": "https://versia.social/users/018eb863-753f-76ff-83d6-fd590de7740a",
|
"author": "018eb863-753f-76ff-83d6-fd590de7740a",
|
||||||
"category": "microblog",
|
"category": "microblog",
|
||||||
"collections": {
|
|
||||||
"replies": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/replies",
|
|
||||||
"quotes": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/quotes",
|
|
||||||
"pub.versia:likes/Likes": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/likes",
|
|
||||||
"pub.versia:likes/Dislikes": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/dislikes",
|
|
||||||
"pub.versia:reactions/Reactions": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/reactions"
|
|
||||||
},
|
|
||||||
"content": {
|
"content": {
|
||||||
"text/html": {
|
"text/html": {
|
||||||
"content": "<p>In the next versia-fe update: account settings, finally!</p>"
|
"content": "<p>In the next versia-fe update: account settings, finally!</p>"
|
||||||
|
|
@ -180,9 +159,21 @@ Notes represent a piece of content on a Versia instance. They can be posted by [
|
||||||
"group": "public",
|
"group": "public",
|
||||||
"is_sensitive": false,
|
"is_sensitive": false,
|
||||||
"mentions": [],
|
"mentions": [],
|
||||||
"subject": "Versia development"
|
"subject": "Versia development",
|
||||||
|
"previews": [],
|
||||||
|
"quotes": null,
|
||||||
|
"replies_to": null
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
### Collections
|
||||||
|
|
||||||
|
The following [Collections](/structures/collection) are available:
|
||||||
|
|
||||||
|
- `replies`: [URI Collection](/structures/collection#uri-collection) of [Note](/entities/note) entities that are replies to this note.
|
||||||
|
- `quotes`: [URI Collection](/structures/collection#uri-collection) of [Note](/entities/note) entities that quote this note.
|
||||||
|
|
||||||
|
These can be fetched using the [Federation API](/api/endpoints#entity-collections)
|
||||||
|
|
@ -6,36 +6,39 @@ export const metadata = {
|
||||||
|
|
||||||
# Entities
|
# Entities
|
||||||
|
|
||||||
Entities are the foundation of the Versia protocol. A similar concept to entities are the [ActivityStreams](https://www.w3.org/TR/activitystreams-core/) objects, which are used to represent activities in the [ActivityPub](https://www.w3.org/TR/activitypub/) protocol. {{ className: 'lead' }}
|
Entities are the foundation of the Versia protocol. They are similar to: {{ className: 'lead' }}
|
||||||
|
|
||||||
## Entity Definition
|
- [ActivityStreams](https://www.w3.org/TR/activitystreams-core/) objects
|
||||||
|
- [Matrix](https://matrix.org/) events.
|
||||||
|
|
||||||
|
## Definition
|
||||||
|
|
||||||
An entity is a simple JSON object that represents a core data structure in Versia. Entities are used to represent various types of data, such as users, notes, and more. Each entity has a unique `id` property that is used to identify it within the instance.
|
An entity is a simple JSON object that represents a core data structure in Versia. Entities are used to represent various types of data, such as users, notes, and more. Each entity has a unique `id` property that is used to identify it within the instance.
|
||||||
|
|
||||||
Any field in an entity not marked as `required` may be omitted or set to `null`.
|
Any field in an entity not marked as `required` may be set to `null`. These fields **must not** be omitted: they must be present with a `null` value if not set.
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
||||||
<Properties name="Entity">
|
<Properties name="Entity">
|
||||||
<Property name="id" type="string" required={true}>
|
<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.
|
Unique identifier for the entity. Must be unique within the instance. Can be any string with the following character sets:
|
||||||
|
|
||||||
|
- `a-z`
|
||||||
|
- `A-Z`
|
||||||
|
- `0-9`
|
||||||
|
- `-`, `_`
|
||||||
|
|
||||||
|
Not present on [Transient Entities](#transient-entities).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Type of the entity. Custom types must follow [Extension Naming](/extensions#naming).
|
Type of the entity. Custom types must follow [Extension Naming](/extensions#naming).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="created_at" type="RFC3339" required={true} typeLink="/types#rfc3339">
|
<Property name="created_at" type="RFC3339" required={true} typeLink="/types#rfc-3339">
|
||||||
Date and time when the entity was created. Must be an [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) timestamp.
|
Date and time when the entity was created. Must be an [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) timestamp.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
Handling of dates that are valid but obviously incorrect (e.g. in the future) is left to the Implementation's discretion.
|
Handling of dates that are valid but obviously incorrect (e.g. in the future) is left to the Implementation's discretion. Sending a [Note](/entities/note) created on `13-12-1337` is very funny, but don't be surprised if it is rejected.
|
||||||
</Note>
|
|
||||||
</Property>
|
|
||||||
<Property name="uri" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the entity. Should be unique and resolve to the entity. Must be an absolute URI.
|
|
||||||
|
|
||||||
<Note>
|
|
||||||
[**Transient Entities**](/entities#transient-entities) do not require a URI.
|
|
||||||
</Note>
|
</Note>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="$schema" type="string" required={false}>
|
<Property name="$schema" type="string" required={false}>
|
||||||
|
|
@ -56,12 +59,11 @@ Any field in an entity not marked as `required` may be omitted or set to `null`.
|
||||||
|
|
||||||
```jsonc {{ 'title': 'Example Entity' }}
|
```jsonc {{ 'title': 'Example Entity' }}
|
||||||
{
|
{
|
||||||
"id": "9a8928b6-2526-4979-aab1-ef2f88cd5700",
|
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||||
"type": "Delete",
|
"type": "pub.versia:likes/Like",
|
||||||
"created_at": "2022-01-01T12:00:00Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://bongo.social/users/63a00ab3-39b1-49eb-b88e-ed65d2361f3e",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"deleted_type": "Note",
|
"liked": "otherexample.org:fmKZ763jzIU8"
|
||||||
"deleted": "https://bongo.social/notes/54059ce2-9332-46fa-bf6a-598b5493b81b",
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -70,7 +72,6 @@ Any field in an entity not marked as `required` may be omitted or set to `null`.
|
||||||
"id": "f0aacf0b-df7a-4ee5-a2ba-6c4acafd8642",
|
"id": "f0aacf0b-df7a-4ee5-a2ba-6c4acafd8642",
|
||||||
"type": "org.space:Zlorbs/Zlorb",
|
"type": "org.space:Zlorbs/Zlorb",
|
||||||
"created_at": "2023-04-13T08:00:00Z",
|
"created_at": "2023-04-13T08:00:00Z",
|
||||||
"uri": "https://space.org/zlorbs/f0aacf0b-df7a-4ee5-a2ba-6c4acafd8642",
|
|
||||||
"extensions": { // [!code focus:100]
|
"extensions": { // [!code focus:100]
|
||||||
"org.space:zlorbs": {
|
"org.space:zlorbs": {
|
||||||
"zlorb_type": "giant",
|
"zlorb_type": "giant",
|
||||||
|
|
@ -88,14 +89,6 @@ Any field in an entity not marked as `required` may be omitted or set to `null`.
|
||||||
|
|
||||||
## Transient Entities
|
## Transient Entities
|
||||||
|
|
||||||
Some entities are transient, meaning they do not have a URI. These entities are used for actions that do not require a permanent record, such as deletions or migrations.
|
Some entities are **transient**, meaning they cannot be fetched using the [Federation API](/api/endpoints). These entities are used for actions that do not require a permanent record, such as deletions or migrations. Transient Entities do not have an `id` field.
|
||||||
|
|
||||||
Implementations **must not** rely on other implementations to store transient entities in their database.
|
Implementations **must not** rely on other implementations to store transient entities in their database.
|
||||||
|
|
||||||
## Serialization
|
|
||||||
|
|
||||||
When serialized to a string, the JSON representation of an entity must follow the following rules:
|
|
||||||
- Keys must be sorted lexicographically.
|
|
||||||
- Must use UTF-8 encoding.
|
|
||||||
- Must be **signed** using the relevant [User](/entities/user)'s private key, or the [instance's private key](/entities/instance-metadata) if the entity is not associated with a particular user.
|
|
||||||
- Must use Unix-style `\n` line endings (LF).
|
|
||||||
|
|
@ -26,17 +26,18 @@ Sometimes, [Users](/entities/user) want to unsubscribe from each other to stop s
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Unfollow">
|
<Properties name="Unfollow">
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the `User` considered the 'follower', i.e. the user who is unsubscribing from the followee.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="followee" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the `User` considered the 'follower', i.e. the user who is unsubscribing from the followee.
|
[Reference](/types#reference) to the `User` considered the 'followee', i.e. the user who is being unsubscribed from.
|
||||||
</Property>
|
|
||||||
<Property name="followee" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the `User` considered the 'followee', i.e. the user who is being unsubscribed from.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -46,10 +47,9 @@ Sometimes, [Users](/entities/user) want to unsubscribe from each other to stop s
|
||||||
```jsonc {{ title: 'Example Unfollow' }}
|
```jsonc {{ title: 'Example Unfollow' }}
|
||||||
{
|
{
|
||||||
"type": "Unfollow",
|
"type": "Unfollow",
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"followee": "https://example.com/users/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
"followee": "example.com:02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ Usernames can be changed by the user, so it is recommended to use `id` for long-
|
||||||
|
|
||||||
### Instance
|
### Instance
|
||||||
|
|
||||||
Instance **must** be the host of the instance the user is on (hostname with optional port).
|
Instance **must** be the [Domain](/api/basics#domain) that the user is on.
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ Instance **must** be the host of the instance the user is on (hostname with opti
|
||||||
<Property name="display_name" type="string" required={false}>
|
<Property name="display_name" type="string" required={false}>
|
||||||
Display name, as shown to other users. May contain emojis and any Unicode character.
|
Display name, as shown to other users. May contain emojis and any Unicode character.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="fields" type="Field[]" required={false}>
|
<Property name="fields" type="Field[]" required={true}>
|
||||||
Custom key/value pairs. For example, metadata like socials or pronouns. Must be text format (`text/*`).
|
Custom key/value pairs. For example, metadata like socials or pronouns. Must be text format (`text/*`).
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
|
@ -70,63 +70,11 @@ Instance **must** be the host of the instance the user is on (hostname with opti
|
||||||
<Property name="header" type="ContentFormat" required={false} typeLink="/structures/content-format">
|
<Property name="header" type="ContentFormat" required={false} typeLink="/structures/content-format">
|
||||||
A header image for the user's profile. Also known as a cover photo or a banner. Must be an image format (`image/*`).
|
A header image for the user's profile. Also known as a cover photo or a banner. Must be an image format (`image/*`).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="public_key" type="PublicKey" required={true}>
|
<Property name="manually_approves_followers" type="boolean" required={true}>
|
||||||
The user's public key. Must follow the [Versia Public Key](/signatures) format. `actor` may be a URI to another user's profile, in which case this key may allow the other user act on behalf of this user (see [delegation](/federation/delegation)).
|
If `true`, the user must approve any new followers manually. If `false`, followers are automatically approved. This does not affect federation, and is meant to be used for clients to display correct UI.
|
||||||
|
|
||||||
- `algorithm`: Must be `ed25519` for now.
|
|
||||||
- `key`: The public key in [SPKI-encoded base64](/signatures#exporting-the-public-key). Must be the key associated with the `actor` URI.
|
|
||||||
- `actor`: URI to a user's profile, most often the user's own profile.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
type URI = string;
|
|
||||||
|
|
||||||
type PublicKey = {
|
|
||||||
actor: URI;
|
|
||||||
algorithm: string;
|
|
||||||
key: string;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="manually_approves_followers" type="boolean" required={false}>
|
<Property name="indexable" type="boolean" required={true}>
|
||||||
If `true`, the user must approve any new followers manually. If `false`, followers are automatically approved. This does not affect federation, and is meant to be used for clients to display correct UI. Defaults to `false`.
|
User consent to be indexed by search engines. If `false`, the user's profile should not be indexed.
|
||||||
</Property>
|
|
||||||
<Property name="indexable" type="boolean" required={false}>
|
|
||||||
User consent to be indexed by search engines. If `false`, the user's profile should not be indexed. Defaults to `true`.
|
|
||||||
</Property>
|
|
||||||
<Property name="inbox" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
The user's federation inbox. Refer to the [federation documentation](/federation).
|
|
||||||
|
|
||||||
Some instances may also have a shared inbox. Refer to [Instance Metadata](/entities/instance-metadata) for more information.
|
|
||||||
</Property>
|
|
||||||
<Property name="collections" type="UserCollections" required={true}>
|
|
||||||
Collections related to the user. Must contain at least `outbox`, `followers`, `following`, and `featured`.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
type URI = string;
|
|
||||||
|
|
||||||
type UserCollections = {
|
|
||||||
outbox: URI;
|
|
||||||
followers: URI;
|
|
||||||
following: URI;
|
|
||||||
featured: URI;
|
|
||||||
// Same format as type on Extensions
|
|
||||||
[key: ExtensionsKey]: URI;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
All URIs must resolve to either a [Collection](/structures/collection) or a [URI Collection](/structures/collection#uri-collection) of the appropriate entities. Extensions may add additional collections.
|
|
||||||
|
|
||||||
### Outbox
|
|
||||||
The user's federation outbox. Refer to the [federation documentation](/federation). [Collection](/structures/collection) of [Note](/entities/note) entities.
|
|
||||||
|
|
||||||
### Followers
|
|
||||||
User's followers. [URI Collection](/structures/collection#uri-collection) of [User](/entities/user) entities.
|
|
||||||
|
|
||||||
### Following
|
|
||||||
Users that the user follows. [URI Collection](/structures/collection#uri-collection) of [User](/entities/user) entities.
|
|
||||||
|
|
||||||
### Featured
|
|
||||||
[Notes](/entities/note) that the user wants to feature (also known as "pin") on their profile. [Collection](/structures/collection) of [Note](/entities/note) entities. Only notes authored by the user can be featured.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
||||||
|
|
@ -137,7 +85,6 @@ Instance **must** be the host of the instance the user is on (hostname with opti
|
||||||
{
|
{
|
||||||
"id": "018ec082-0ae1-761c-b2c5-22275a611771",
|
"id": "018ec082-0ae1-761c-b2c5-22275a611771",
|
||||||
"type": "User",
|
"type": "User",
|
||||||
"uri": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771",
|
|
||||||
"created_at": "2024-04-09T01:38:51.743Z",
|
"created_at": "2024-04-09T01:38:51.743Z",
|
||||||
"avatar": { // [!code focus:100]
|
"avatar": { // [!code focus:100]
|
||||||
"image/png": {
|
"image/png": {
|
||||||
|
|
@ -152,14 +99,6 @@ Instance **must** be the host of the instance the user is on (hostname with opti
|
||||||
"content": "🌸🌸🌸"
|
"content": "🌸🌸🌸"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"collections": {
|
|
||||||
"featured": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/featured",
|
|
||||||
"followers": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/followers",
|
|
||||||
"following": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/following",
|
|
||||||
"pub.versia:likes/Dislikes": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/dislikes",
|
|
||||||
"pub.versia:likes/Likes": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/likes",
|
|
||||||
"outbox": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/outbox",
|
|
||||||
},
|
|
||||||
"display_name": "April The Pink (limited Sand Edition)",
|
"display_name": "April The Pink (limited Sand Edition)",
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"pub.versia:custom_emojis": {
|
"pub.versia:custom_emojis": {
|
||||||
|
|
@ -181,17 +120,22 @@ Instance **must** be the host of the instance the user is on (hostname with opti
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"header": null,
|
"header": null,
|
||||||
"inbox": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/inbox",
|
|
||||||
"indexable": false,
|
"indexable": false,
|
||||||
"manually_approves_followers": false,
|
"manually_approves_followers": false,
|
||||||
"public_key": {
|
|
||||||
"actor": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771",
|
|
||||||
"algorithm": "ed25519",
|
|
||||||
"key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
||||||
},
|
|
||||||
"username": "aprl"
|
"username": "aprl"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
### Collections
|
||||||
|
|
||||||
|
The following [Collections](/structures/collection) are available:
|
||||||
|
|
||||||
|
- `outbox`: [Collection](/structures/collection) of notes authored by the user.
|
||||||
|
- `followers`: [URI Collection](/structures/collection#uri-collection) of users that follow the user.
|
||||||
|
- `following`: [URI Collection](/structures/collection#uri-collection) of users that the user follows.
|
||||||
|
- `featured`: [Collection](/structures/collection) of notes that the user wants to feature on their profile ("pinned" notes).
|
||||||
|
|
||||||
|
These can be fetched using the [Federation API](/api/endpoints#entity-collections)
|
||||||
|
|
@ -15,7 +15,11 @@ The Custom Emojis extension adds support for adding personalized emojis to feder
|
||||||
<Property name="name" type="string" required={true}>
|
<Property name="name" type="string" required={true}>
|
||||||
Emoji name, surrounded by identification characters (for example, colons: `:happy_face:`).
|
Emoji name, surrounded by identification characters (for example, colons: `:happy_face:`).
|
||||||
|
|
||||||
Name must match the regex `^[a-zA-Z0-9_-]+$`.
|
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.
|
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>
|
||||||
|
|
@ -34,7 +38,7 @@ The Custom Emojis extension adds support for adding personalized emojis to feder
|
||||||
"image/webp": {
|
"image/webp": {
|
||||||
"content": "https://cdn.example.com/emojis/happy_face.webp",
|
"content": "https://cdn.example.com/emojis/happy_face.webp",
|
||||||
"remote": true,
|
"remote": true,
|
||||||
"description": "A happy emoji smiling.",
|
"description": "A happy emoji smiling."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,18 +89,14 @@ Custom Emojis can be added to any entity with text content. The extension ID is
|
||||||
{
|
{
|
||||||
"id": "456df8ed-daf1-4062-abab-491071c7b8dd",
|
"id": "456df8ed-daf1-4062-abab-491071c7b8dd",
|
||||||
"type": "Note",
|
"type": "Note",
|
||||||
"uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd",
|
|
||||||
"created_at": "2024-04-09T01:38:51.743Z",
|
"created_at": "2024-04-09T01:38:51.743Z",
|
||||||
"collections": {
|
|
||||||
"replies": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/replies",
|
|
||||||
"quotes": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/quotes"
|
|
||||||
},
|
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"content": "Hello, world :happy_face:!"
|
"content": "Hello, world :happy_face:!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extensions": { // [!code focus:16]
|
...
|
||||||
|
"extensions": { // [!code focus:23]
|
||||||
"pub.versia:custom_emojis": {
|
"pub.versia:custom_emojis": {
|
||||||
"emojis": [
|
"emojis": [
|
||||||
{
|
{
|
||||||
|
|
@ -105,7 +105,7 @@ Custom Emojis can be added to any entity with text content. The extension ID is
|
||||||
"image/webp": {
|
"image/webp": {
|
||||||
"content": "https://cdn.example.com/emojis/happy_face.webp",
|
"content": "https://cdn.example.com/emojis/happy_face.webp",
|
||||||
"remote": true,
|
"remote": true,
|
||||||
"description": "A happy emoji smiling.",
|
"description": "A happy emoji smiling."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
77
app/extensions/delegation/page.mdx
Normal file
77
app/extensions/delegation/page.mdx
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
export const metadata = {
|
||||||
|
title: 'Delegation Extension',
|
||||||
|
description: 'Lets users perform actions on other accounts\' behalf.'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Delegation Extension
|
||||||
|
|
||||||
|
Delegation is used to authorize actions on behalf of another user. {{ className: 'lead '}}
|
||||||
|
|
||||||
|
## Vocabulary
|
||||||
|
|
||||||
|
- **Delegator**: The user that is delegating actions to another user. (The user that owns the key)
|
||||||
|
- **Delegate**: The user that is being delegated actions. (The user that the key is pointing to)
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
Any actions or entities created by the **delegate** should be attributed to the **delegator** user in clients transparently to end-users (e.g. showing the **delegator** user's name and avatar). This allows for a form of "consensual impersonation" that is authorized by the **delegators** and **delegates**.
|
||||||
|
|
||||||
|
This is useful as a way to centralize all of a user's many "alt accounts" into a single, unified feed.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
If an instance encounters an action from a User that has a Delegator listed, but that Delegator does not allow the User to perform actions on their behalf, the actions **MUST** be shown as the User's own.
|
||||||
|
|
||||||
|
Also, if a User has a Delegator listed, but that Delegator does not allow the User to perform actions on their behalf, instances **SHOULD** mark the User with a warning about possible impersonation or fraud.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
## Extension Definition
|
||||||
|
|
||||||
|
The Delegation extension uses an ID of `pub.versia:delegation`.
|
||||||
|
|
||||||
|
If the extension is present, exactly **one** of the fields **MUST** be specified:
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<Properties name="Delegation">
|
||||||
|
<Property name="delegator" type="Reference">
|
||||||
|
If this user performs actions on behalf on another user, **MUST** have a reference to that user.
|
||||||
|
</Property>
|
||||||
|
<Property name="allowed_delegates" type="Reference[]">
|
||||||
|
If other users perform actions on behalf of this user, **MUST** have a list of references to all such users.
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
<Col sticky>
|
||||||
|
|
||||||
|
```jsonc {{ title: "Example Delegator" }}
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
"type": "User",
|
||||||
|
"id": "73cb1728-75d7-4080-8d28-4adf49bb0a0d",
|
||||||
|
// ...
|
||||||
|
"extensions": { // [!code focus:5]
|
||||||
|
"pub.versia:delegation": {
|
||||||
|
"delegator": "versia.example.com:bfb6bb39-bb08-4226-91ac-8adebc3da046"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```jsonc {{ title: "Example Delegates List" }}
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
"type": "User",
|
||||||
|
"id": "bfb6bb39-bb08-4226-91ac-8adebc3da046",
|
||||||
|
// ...
|
||||||
|
"extensions": { // [!code focus:7]
|
||||||
|
"pub.versia:delegation": {
|
||||||
|
"allowed_delegates": [
|
||||||
|
"versia.social:73cb1728-75d7-4080-8d28-4adf49bb0a0d"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
@ -27,7 +27,7 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not
|
||||||
|
|
||||||
Text only (`text/plain`, `text/html`, etc).
|
Text only (`text/plain`, `text/html`, etc).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="open" type="boolean" required={false}>
|
<Property name="open" type="boolean" required={true}>
|
||||||
Whether the group is open to all users or requires approval to join.
|
Whether the group is open to all users or requires approval to join.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
|
|
@ -36,12 +36,6 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not
|
||||||
It is similar to a [User](/entities/user)'s `manually_approves_followers` field.
|
It is similar to a [User](/entities/user)'s `manually_approves_followers` field.
|
||||||
</Note>
|
</Note>
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="members" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the group's members list. [URI Collection](/structures/collection#uri-collection) of [Users](/entities/user).
|
|
||||||
</Property>
|
|
||||||
<Property name="notes" type="URI" required={false} typeLink="/types#uri">
|
|
||||||
URI of the group's associated notes. [URI Collection](/structures/collection#uri-collection) of [Notes](/entities/note).
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
|
@ -51,7 +45,6 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/Group",
|
"type": "pub.versia:groups/Group",
|
||||||
"id": "ed480922-b095-4f09-9da5-c995be8f5960",
|
"id": "ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"uri": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"name": {
|
"name": {
|
||||||
"text/html": {
|
"text/html": {
|
||||||
"content": "The <strong>Woozy</strong> fan club"
|
"content": "The <strong>Woozy</strong> fan club"
|
||||||
|
|
@ -62,14 +55,22 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not
|
||||||
"content": "A group for fans of the Woozy emoji."
|
"content": "A group for fans of the Woozy emoji."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"open": false,
|
"open": false
|
||||||
"members": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960/members",
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
### Collections
|
||||||
|
|
||||||
|
The following [Collections](/structures/collection) are available:
|
||||||
|
|
||||||
|
- `members`: [URI Collection](/structures/collection#uri-collection) of [Users](/entities/user) that are members of the group.
|
||||||
|
- `notes`: [URI Collection](/structures/collection#uri-collection) of [Notes](/entities/note) that are associated with the group.
|
||||||
|
|
||||||
|
These can be fetched using the [Federation API](/api/endpoints#entity-collections)
|
||||||
|
|
||||||
## Subscribing to Groups
|
## Subscribing to Groups
|
||||||
|
|
||||||
[Users](/entities/user) may "subscribe" to a Group in order to receive all [Notes](/entities/note) posted to it. The mechanism by which federation is handled is described at [the end of this document](#federation).
|
[Users](/entities/user) may "subscribe" to a Group in order to receive all [Notes](/entities/note) posted to it. The mechanism by which federation is handled is described at [the end of this document](#federation).
|
||||||
|
|
@ -82,20 +83,21 @@ If the group accepts the subscription, the user will receive all notes posted to
|
||||||
|
|
||||||
Indicates that a [User](/entities/user) wishes to subscribe to a group.
|
Indicates that a [User](/entities/user) wishes to subscribe to a group.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="GroupSubscribe">
|
<Properties name="GroupSubscribe">
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:groups/Subscribe`.
|
Must be `pub.versia:groups/Subscribe`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="subscriber" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the [User](/entities/user) subscribing to the group.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="subscriber" type="URI" required={true} typeLink="/types#uri">
|
<Property name="group" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the [User](/entities/user) subscribing to the group.
|
[Reference](/types#reference) to the group to subscribe to.
|
||||||
</Property>
|
|
||||||
<Property name="group" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the group to subscribe to.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -105,9 +107,8 @@ Indicates that a [User](/entities/user) wishes to subscribe to a group.
|
||||||
```jsonc {{ title: "Example GroupSubscribe" }}
|
```jsonc {{ title: "Example GroupSubscribe" }}
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/Subscribe",
|
"type": "pub.versia:groups/Subscribe",
|
||||||
"id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0",
|
"subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
||||||
"subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
"group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"created_at": "2021-01-01T00:00:00Z"
|
"created_at": "2021-01-01T00:00:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -119,20 +120,21 @@ Indicates that a [User](/entities/user) wishes to subscribe to a group.
|
||||||
|
|
||||||
Indicates that a [User](/entities/user) wishes to unsubscribe from a group.
|
Indicates that a [User](/entities/user) wishes to unsubscribe from a group.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="GroupUnsubscribe">
|
<Properties name="GroupUnsubscribe">
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:groups/Unsubscribe`.
|
Must be `pub.versia:groups/Unsubscribe`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="subscriber" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the [User](/entities/user) unsubscribing from the group.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="subscriber" type="URI" required={true} typeLink="/types#uri">
|
<Property name="group" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the [User](/entities/user) unsubscribing from the group.
|
[Reference](/types#reference) to the group to unsubscribe from.
|
||||||
</Property>
|
|
||||||
<Property name="group" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the group to unsubscribe from.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -142,9 +144,8 @@ Indicates that a [User](/entities/user) wishes to unsubscribe from a group.
|
||||||
```jsonc {{ title: "Example GroupUnsubscribe" }}
|
```jsonc {{ title: "Example GroupUnsubscribe" }}
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/Unsubscribe",
|
"type": "pub.versia:groups/Unsubscribe",
|
||||||
"id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0",
|
"subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
||||||
"subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
"group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"created_at": "2021-01-01T00:00:00Z"
|
"created_at": "2021-01-01T00:00:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -154,7 +155,11 @@ Indicates that a [User](/entities/user) wishes to unsubscribe from a group.
|
||||||
|
|
||||||
### GroupSubscribeAccept
|
### GroupSubscribeAccept
|
||||||
|
|
||||||
Indicates that a [Group](#entity-definition) has accepted a [User](/entities/user)'s subscription request. Should be signed by the instance hosting the group.
|
Indicates that a [Group](#entity-definition) has accepted a [User](/entities/user)'s subscription request. Should be sent by the instance hosting the group.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
@ -162,14 +167,11 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:groups/SubscribeAccept`.
|
Must be `pub.versia:groups/SubscribeAccept`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="subscriber" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the [User](/entities/user) subscribing to the group.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="subscriber" type="URI" required={true} typeLink="/types#uri">
|
<Property name="group" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the [User](/entities/user) subscribing to the group.
|
[Reference](/types#reference) to the group that accepted the subscription.
|
||||||
</Property>
|
|
||||||
<Property name="group" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the group that accepted the subscription.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -179,9 +181,8 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use
|
||||||
```jsonc {{ title: "Example GroupSubscribeAccept" }}
|
```jsonc {{ title: "Example GroupSubscribeAccept" }}
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/SubscribeAccept",
|
"type": "pub.versia:groups/SubscribeAccept",
|
||||||
"id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0",
|
"subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
||||||
"subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
"group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"created_at": "2021-01-01T00:00:00Z"
|
"created_at": "2021-01-01T00:00:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -191,7 +192,11 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use
|
||||||
|
|
||||||
### GroupSubscribeReject
|
### GroupSubscribeReject
|
||||||
|
|
||||||
Indicates that a [Group](#entity-definition) has rejected a [User](/entities/user)'s subscription request. Should be signed by the instance hosting the group.
|
Indicates that a [Group](#entity-definition) has rejected a [User](/entities/user)'s subscription request. Should be sent by the instance hosting the group.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
@ -199,14 +204,11 @@ Indicates that a [Group](#entity-definition) has rejected a [User](/entities/use
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:groups/SubscribeReject`.
|
Must be `pub.versia:groups/SubscribeReject`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="subscriber" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the [User](/entities/user) subscribing to the group.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="subscriber" type="URI" required={true} typeLink="/types#uri">
|
<Property name="group" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the [User](/entities/user) subscribing to the group.
|
[Reference](/types#reference) to the group that rejected the subscription.
|
||||||
</Property>
|
|
||||||
<Property name="group" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the group that rejected the subscription.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -216,9 +218,8 @@ Indicates that a [Group](#entity-definition) has rejected a [User](/entities/use
|
||||||
```jsonc {{ title: "Example GroupSubscribeReject" }}
|
```jsonc {{ title: "Example GroupSubscribeReject" }}
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/SubscribeReject",
|
"type": "pub.versia:groups/SubscribeReject",
|
||||||
"id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0",
|
"subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
||||||
"subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc",
|
"group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"created_at": "2021-01-01T00:00:00Z"
|
"created_at": "2021-01-01T00:00:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -230,13 +231,17 @@ Indicates that a [Group](#entity-definition) has rejected a [User](/entities/use
|
||||||
|
|
||||||
Group federation represents a particularly challenging problem, as it requires a way to make sure every single [Note](/entities/note) posted to it is delivered to every single member of the group.
|
Group federation represents a particularly challenging problem, as it requires a way to make sure every single [Note](/entities/note) posted to it is delivered to every single member of the group.
|
||||||
|
|
||||||
All [Notes](/entities/note) posted to a group (using the `group` field) must be sent to its instance's [shared inbox](/federation#inboxes). Groups do not have an inbox of their own.
|
All [Notes](/entities/note) posted to a group (using the `group` field) must be sent to its instance's [inbox](/api/endpoints#inbox).
|
||||||
|
|
||||||
Once this is done, the group's instance must then federate this [Note](/entities/note) to every member of the group. However, this cannot be done the "normal way", as the group's instance does not have the private key to [sign](/signatures) the [Note](/entities/note).
|
Once this is done, the group's instance must then federate this [Note](/entities/note) to every member of the group. However, this cannot be done the "normal way", as the group's instance does not have the private key to [sign](/signatures) the [Note](/entities/note).
|
||||||
|
|
||||||
### GroupFederate
|
### GroupFederate
|
||||||
|
|
||||||
The `GroupFederate` entity allows a group to federate a note to all of its members, without needing to sign the note itself. It contains a URI to the note being federated, which must be fetched by the receiving instances. This entity is signed by the group's instance.
|
The `GroupFederate` entity allows a group to federate a note to all of its members, without needing to sign the note itself. It contains a URI to the note being federated, which must be fetched by the receiving instances. This entity is sent by the group's instance.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
|
|
@ -244,14 +249,11 @@ The `GroupFederate` entity allows a group to federate a note to all of its membe
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:groups/Federate`.
|
Must be `pub.versia:groups/Federate`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="uri" type="null" required={false}>
|
<Property name="note" type="Reference" required={true} typeLink="/types#reference">
|
||||||
This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI.
|
[Reference](/types#reference) to the note to federate.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="note" type="URI" required={true} typeLink="/types#uri">
|
<Property name="group" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the note to federate.
|
[Reference](/types#reference) to the group federating the note.
|
||||||
</Property>
|
|
||||||
<Property name="group" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI of the group federating the note.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -261,9 +263,8 @@ The `GroupFederate` entity allows a group to federate a note to all of its membe
|
||||||
```jsonc {{ title: "Example GroupFederate" }}
|
```jsonc {{ title: "Example GroupFederate" }}
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/Federate",
|
"type": "pub.versia:groups/Federate",
|
||||||
"id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0",
|
"note": "c5aa65fa-0356-4029-b61c-6b237e5d1393",
|
||||||
"note": "https://example.com/notes/ed480922-b095-4f09-9da5-c995be8f5960",
|
"group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"created_at": "2021-01-01T00:00:00Z"
|
"created_at": "2021-01-01T00:00:00Z"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -23,65 +23,21 @@ For example, let's consider the following scenario:
|
||||||
|
|
||||||
In this scenario, `jane.org` has no way of knowing what went wrong, as `joe.social` does not provide any feedback.
|
In this scenario, `jane.org` has no way of knowing what went wrong, as `joe.social` does not provide any feedback.
|
||||||
|
|
||||||
## Instance Metadata Extensions
|
|
||||||
|
|
||||||
This extension adds the following metadata to instances:
|
## Sending Messages
|
||||||
|
|
||||||
<Row>
|
To send a federation debug message, instances **should** make a `POST` request to the `/.versia/v0.6/messaging` endpoint with a simple text body containing a helpful message.
|
||||||
<Col>
|
|
||||||
<Properties name="InstanceMessagingExtension">
|
|
||||||
<Property name="endpoint" type="string" required={true}>
|
|
||||||
The endpoint to send federation debug messages to.
|
|
||||||
|
|
||||||
### Sending Messages
|
No signatures are required (either on the request or response), and no response body is expected.
|
||||||
|
|
||||||
To send a federation debug message, instances **should** make a `POST` request to the appropriate endpoint with a simple text body containing a helpful message.
|
```text {{ "title": "Helpful Message" }}
|
||||||
|
Validation failed for https://jane.org/users/nkGEd8eI98.
|
||||||
```text {{ "title": "Helpful Message" }}
|
Reasons:
|
||||||
Validation failed for https://jane.org/users/nkGEd8eI98.
|
|
||||||
Reasons:
|
|
||||||
- `username` must be alphanumeric. Found invalid character `@`.
|
- `username` must be alphanumeric. Found invalid character `@`.
|
||||||
```
|
```
|
||||||
|
|
||||||
Do not send useless messages, such as:
|
Do not send useless messages, such as:
|
||||||
|
|
||||||
```text {{ "title": "Unhelpful Message" }}
|
```text {{ "title": "Unhelpful Message" }}
|
||||||
Federation failed.
|
Federation failed.
|
||||||
```
|
```
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col sticky>
|
|
||||||
|
|
||||||
```jsonc {{ "title": "Example Instance Metadata" }}
|
|
||||||
{
|
|
||||||
"type": "InstanceMetadata",
|
|
||||||
"name": "Jane.org",
|
|
||||||
"software": {
|
|
||||||
"name": "Versia Server",
|
|
||||||
"version": "0.7.0"
|
|
||||||
},
|
|
||||||
"compatibility": {
|
|
||||||
"versions": [
|
|
||||||
"0.5.0"
|
|
||||||
],
|
|
||||||
"extensions": [
|
|
||||||
"pub.versia:reactions",
|
|
||||||
"pub.versia:polls",
|
|
||||||
"pub.versia:reports",
|
|
||||||
"pub.versia:instance_messaging"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"host": "jane.org",
|
|
||||||
"created_at": "2021-07-01T00:00:00Z",
|
|
||||||
"extensions": { // [!code focus:5]
|
|
||||||
"pub.versia:instance_messaging": {
|
|
||||||
"endpoint": "https://jane.org/api/reports",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
@ -15,17 +15,13 @@ The entity defined in this document must be inserted in the `pub.versia:interact
|
||||||
{
|
{
|
||||||
"id": "456df8ed-daf1-4062-abab-491071c7b8dd",
|
"id": "456df8ed-daf1-4062-abab-491071c7b8dd",
|
||||||
"type": "Note",
|
"type": "Note",
|
||||||
"uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd",
|
|
||||||
"created_at": "2024-04-09T01:38:51.743Z",
|
"created_at": "2024-04-09T01:38:51.743Z",
|
||||||
"collections": {
|
|
||||||
"replies": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/replies",
|
|
||||||
"quotes": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/quotes"
|
|
||||||
},
|
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"content": "Hello, world :happy_face:!"
|
"content": "Hello, world :happy_face:!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
...
|
||||||
"extensions": { // [!code focus:9]
|
"extensions": { // [!code focus:9]
|
||||||
"pub.versia:interaction_controls": {
|
"pub.versia:interaction_controls": {
|
||||||
"reply": {
|
"reply": {
|
||||||
|
|
@ -104,7 +100,7 @@ Extensions **may** choose to register their own interaction types (such as `pub.
|
||||||
|
|
||||||
### Handling Permission Errors
|
### Handling Permission Errors
|
||||||
|
|
||||||
Implementations that find a user attempting to create an interaction they are not allowed to **MUST** return a `403 Forbidden` HTTP status code when processing the Note during federation. The Note **must** also be discarded.
|
Implementations that find a user attempting to create an interaction they are not allowed to **MAY** return a `403 Forbidden` HTTP status code when processing the Note during federation, or use the [Instance Messaging](/extensions/instance-messaging) extension. The Note **must** be discarded.
|
||||||
|
|
||||||
It is important for implementations to backfill any related [Collections](/structures/collection)/[URI Collections](/structures/collection#uri-collection) (e.g. user followers) in order to not incorrectly reject Notes based off of outdated data.
|
It is important for implementations to backfill any related [Collections](/structures/collection)/[URI Collections](/structures/collection#uri-collection) (e.g. user followers) in order to not incorrectly reject Notes based off of outdated data.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ Likes are a way for users to show appreciation for a note, like Twitter's "heart
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:likes/Like`.
|
Must be `pub.versia:likes/Like`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
Creator of the Like.
|
[Reference](/types#reference) to the creator of the Like.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="liked" type="URI" required={true} typeLink="/types#uri">
|
<Property name="liked" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the note being liked. Must link to a [Note](/entities/note).
|
[Reference](/types#reference) to the note being liked.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -38,9 +38,8 @@ Likes are a way for users to show appreciation for a note, like Twitter's "heart
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||||
"type": "pub.versia:likes/Like",
|
"type": "pub.versia:likes/Like",
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"uri": "https://example.com/likes/3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"liked": "otherexample.org:fmKZ763jzIU8"
|
||||||
"liked": "https://otherexample.org/notes/fmKZ763jzIU8"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -59,11 +58,11 @@ Dislikes are a way for users to show disapproval for a note, like YouTube's "dis
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:likes/Dislike`.
|
Must be `pub.versia:likes/Dislike`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={true} typeLink="/types#reference">
|
||||||
Creator of the Dislike.
|
[Reference](/types#reference) to the creator of the Dislike.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="disliked" type="URI" required={true} typeLink="/types#uri">
|
<Property name="disliked" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the note being disliked. Must link to a [Note](/entities/note).
|
[Reference](/types#reference) to the note being disliked.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -75,9 +74,8 @@ Dislikes are a way for users to show disapproval for a note, like YouTube's "dis
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||||
"type": "pub.versia:likes/Dislike",
|
"type": "pub.versia:likes/Dislike",
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"uri": "https://example.com/dislikes/3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"disliked": "otherexample.org:fmKZ763jzIU8"
|
||||||
"disliked": "https://otherexample.org/notes/fmKZ763jzIU8"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -92,39 +90,15 @@ To undo a like or dislike, a [Delete](/entities/delete) entity should be used. T
|
||||||
|
|
||||||
The Likes extension adds the following collections to the [User](/entities/user) entity:
|
The Likes extension adds the following collections to the [User](/entities/user) entity:
|
||||||
|
|
||||||
- `likes`: A [URI Collection](/structures/collection#uri-collection) of all the notes the user has liked.
|
- `pub.versia:likes/Likes`: [URI Collection](/structures/collection#uri-collection) of all the notes the user has liked.
|
||||||
- `dislikes`: A [URI Collection](/structures/collection#uri-collection) of all the notes the user has disliked.
|
- `pub.versia:likes/Dislikes`: [URI Collection](/structures/collection#uri-collection) of all the notes the user has disliked.
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"type": "User",
|
|
||||||
...
|
|
||||||
"collections": {
|
|
||||||
...
|
|
||||||
"pub.versia:likes/Likes": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe/likes",
|
|
||||||
"pub.versia:likes/Dislikes": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe/dislikes"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Note Collections
|
## Note Collections
|
||||||
|
|
||||||
The Likes extension adds the following collections to the [Note](/entities/note) entity:
|
The Likes extension adds the following collections to the [Note](/entities/note) entity:
|
||||||
|
|
||||||
- `likes`: A [URI Collection](/structures/collection#uri-collection) of all the likes the note has received.
|
- `pub.versia:likes/Likes`: [URI Collection](/structures/collection#uri-collection) of all the likes the note has received.
|
||||||
- `dislikes`: A [URI Collection](/structures/collection#uri-collection) of all the dislikes the note has received.
|
- `pub.versia:likes/Dislikes`: [URI Collection](/structures/collection#uri-collection) of all the dislikes the note has received.
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"type": "Note",
|
|
||||||
...
|
|
||||||
"collections": {
|
|
||||||
...
|
|
||||||
"pub.versia:likes/Likes": "https://example.com/notes/fmKZ763jzIU8/likes",
|
|
||||||
"pub.versia:likes/Dislikes": "https://example.com/notes/fmKZ763jzIU8/dislikes"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interaction Types
|
## Interaction Types
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,20 +30,21 @@ Migration happens in three steps:
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Migration">
|
<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>
|
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:migration/Migration`.
|
Must be `pub.versia:migration/Migration`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" typeLink="/types#uri" required={true}>
|
<Property name="author" type="Reference" typeLink="/types#reference" required={true}>
|
||||||
URI of the [User](/entities/user) who is migrating.
|
[Reference](/types#reference) to the [User](/entities/user) who is migrating.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="destination" type="URI" required={true} typeLink="/types#uri">
|
<Property name="destination" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the destination [User](/entities/user) on the new instance.
|
[Reference](/types#reference) to the destination [User](/entities/user) on the new instance.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -52,11 +53,10 @@ Migration happens in three steps:
|
||||||
|
|
||||||
```json {{ title: "Example Entity" }}
|
```json {{ title: "Example Entity" }}
|
||||||
{
|
{
|
||||||
"id": "016f3de2-ad63-4e06-999e-1e6b41c981c5",
|
|
||||||
"type": "pub.versia:migration/Migration",
|
"type": "pub.versia:migration/Migration",
|
||||||
"author": "https://example.com/users/44df6e02-ef43-47e0-aff2-47041f3d09ed",
|
"author": "44df6e02-ef43-47e0-aff2-47041f3d09ed",
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"destination": "https://otherinstance.social/users/73e999a0-53d0-40a3-a5cc-be0408004726",
|
"destination": "otherinstance.social:73e999a0-53d0-40a3-a5cc-be0408004726",
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -70,11 +70,11 @@ The following extensions to [User](/entities/user) are used by the migration ext
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="MigrationExtension">
|
<Properties name="MigrationExtension">
|
||||||
<Property name="previous" type="URI" required={true} typeLink="/types#uri">
|
<Property name="previous" type="Reference" required={true} typeLink="/types#reference">
|
||||||
If this user has migrated from another instance, this property **MUST** be set to the URI of the user on the previous instance.
|
If this user has migrated from another instance, this property **MUST** be a [Reference](/types#reference) to the user on the previous instance.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="new" type="URI" required={false} typeLink="/types#uri">
|
<Property name="new" type="Reference" required={false} typeLink="/types#reference">
|
||||||
If this user has migrated to another instance, this property **MUST** be set to the URI of the user on the new instance.
|
If this user has migrated to another instance, this property **MUST** be a [Reference](/types#reference) to the URI of the user on the new instance.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -88,8 +88,8 @@ The following extensions to [User](/entities/user) are used by the migration ext
|
||||||
// ...
|
// ...
|
||||||
"extensions": { // [!code focus:100]
|
"extensions": { // [!code focus:100]
|
||||||
"pub.versia:migration": {
|
"pub.versia:migration": {
|
||||||
"previous": "https://oldinstance.social/users/44df6e02-ef43-47e0-aff2-47041f3d09ed",
|
"previous": "oldinstance.social:44df6e02-ef43-47e0-aff2-47041f3d09ed",
|
||||||
// "new": "https://newinstance.social/users/73e999a0-53d0-40a3-a5cc-be0408004726",
|
// "new": "newinstance.social:73e999a0-53d0-40a3-a5cc-be0408004726",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ export const metadata = {
|
||||||
|
|
||||||
Versia provides a set of core entities and structures to build a barebones social network. However, it is not possible nor desirable to cover every use case. This is where extensions come in, allowing parts of the system to be extended or replaced with custom functionality. {{ className: 'lead' }}
|
Versia provides a set of core entities and structures to build a barebones social network. However, it is not possible nor desirable to cover every use case. This is where extensions come in, allowing parts of the system to be extended or replaced with custom functionality. {{ className: 'lead' }}
|
||||||
|
|
||||||
By design, extensions can be mitchmatched in any combination, without requiring any changes to the core system. This allows for a high degree of customization and flexibility. Implementations that do not support a particular extension can simply ignore it without any issues.
|
By design, extensions can be implemented in any combination, without requiring any changes to the core system. This allows for a high degree of customization and flexibility. Implementations that do not support a particular extension can simply ignore it without any issues.
|
||||||
|
|
||||||
Extensions **should** be standardized and publicly documented.
|
Extensions **should** be standardized and publicly documented.
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@ Extensions **must not** be designed in a way that makes them required to underst
|
||||||
|
|
||||||
Versia extension names are composed of two parts:
|
Versia extension names are composed of two parts:
|
||||||
- The domain name of the extension author, in reverse order. Example: `pub.versia`
|
- The domain name of the extension author, in reverse order. Example: `pub.versia`
|
||||||
- The extension name, separated by a colon. `snake_case`. Example: `likes`
|
- The extension name, separated by a colon, in `snake_case`. Example: `likes`
|
||||||
|
|
||||||
``` {{ title: "Example Extension Name" }}
|
``` {{ title: "Example Extension Name" }}
|
||||||
pub.versia:likes
|
pub.versia:likes
|
||||||
|
|
@ -30,7 +30,7 @@ pub.versia:likes
|
||||||
### Custom entities
|
### Custom entities
|
||||||
|
|
||||||
Custom entities are named in the same way, but with an additional part:
|
Custom entities are named in the same way, but with an additional part:
|
||||||
- The entity name, separated by a slash. `PascalCase`. Example: `Like`
|
- The entity name, separated by a slash, in `PascalCase`. Example: `Like`
|
||||||
|
|
||||||
``` {{ title: "Example Custom Entity Type" }}
|
``` {{ title: "Example Custom Entity Type" }}
|
||||||
pub.versia:likes/Like
|
pub.versia:likes/Like
|
||||||
|
|
@ -49,9 +49,7 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)'
|
||||||
Custom extensions to the entity.
|
Custom extensions to the entity.
|
||||||
|
|
||||||
- `key`: The extension name.
|
- `key`: The extension name.
|
||||||
- `value`: Extension data. Can be any JSON-serializable data.
|
- `value`: Extension data. Can be any JSON object, following [Versia JSON rules](/json).
|
||||||
|
|
||||||
Extension data can be any JSON-serializable data.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -61,10 +59,9 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)'
|
||||||
{
|
{
|
||||||
"type": "pub.versia:groups/Group",
|
"type": "pub.versia:groups/Group",
|
||||||
"id": "ed480922-b095-4f09-9da5-c995be8f5960",
|
"id": "ed480922-b095-4f09-9da5-c995be8f5960",
|
||||||
"uri": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
|
|
||||||
"name": null,
|
"name": null,
|
||||||
"description": null,
|
"description": null,
|
||||||
"members": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960/members",
|
"open": true,
|
||||||
"extensions": { // [!code focus:100]
|
"extensions": { // [!code focus:100]
|
||||||
"com.example:gps": {
|
"com.example:gps": {
|
||||||
"location": {
|
"location": {
|
||||||
|
|
@ -87,12 +84,12 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)'
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="CustomEntity">
|
<Properties name="CustomEntity">
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
The extension type. [Must follow naming conventions](#naming).
|
The extension type, [following naming conventions](#naming).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="other">
|
<Property name="other">
|
||||||
Other properties of the custom entity. These are specific to the extension, and should be documented by the extension author.
|
Other properties of the custom entity. These are specific to the extension, and should be documented by the extension author.
|
||||||
|
|
||||||
Note that `id`, `uri` and `created_at` are still required for custom entities, unless the extension author specifies otherwise.
|
Note that `id` and `created_at` are still required for custom entities, unless the extension author specifies otherwise.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -102,8 +99,7 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)'
|
||||||
{
|
{
|
||||||
"type": "com.example:poll/Poll",
|
"type": "com.example:poll/Poll",
|
||||||
"id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
"id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||||
"uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"question": "What is your favourite colour?",
|
"question": "What is your favourite colour?",
|
||||||
"options": [
|
"options": [
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ Note that there is no `question` field: the question should be included in the `
|
||||||
<Property name="multiple_choice" type="boolean" required="true">
|
<Property name="multiple_choice" type="boolean" required="true">
|
||||||
Whether the poll allows multiple votes to be cast for different options.
|
Whether the poll allows multiple votes to be cast for different options.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="expires_at" type="RFC3339" typeLink="/types#rfc3339">
|
<Property name="expires_at" type="RFC3339" typeLink="/types#rfc-3339">
|
||||||
RFC 3339 timestamp of when the poll ends and no more votes can be cast. If not present, the poll does not expire.
|
RFC 3339 timestamp of when the poll ends and no more votes can be cast. If not present, the poll does not expire.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
@ -41,19 +41,15 @@ Note that there is no `question` field: the question should be included in the `
|
||||||
{
|
{
|
||||||
"id": "01902e09-0f8b-72de-8ee3-9afc0cf5eae1",
|
"id": "01902e09-0f8b-72de-8ee3-9afc0cf5eae1",
|
||||||
"type": "Note", // [!code focus]
|
"type": "Note", // [!code focus]
|
||||||
"uri": "https://versia.social/notes/01902e09-0f8b-72de-8ee3-9afc0cf5eae1",
|
|
||||||
"created_at": "2024-06-19T01:07:44.139Z",
|
"created_at": "2024-06-19T01:07:44.139Z",
|
||||||
"author": "https://versia.social/users/018eb863-753f-76ff-83d6-fd590de7740a",
|
"author": "versia.social:018eb863-753f-76ff-83d6-fd590de7740a",
|
||||||
"category": "microblog",
|
"category": "microblog",
|
||||||
"collections": {
|
|
||||||
"replies": "https://versia.social/notes/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/replies",
|
|
||||||
"quotes": "https://versia.social/notes/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/quotes"
|
|
||||||
},
|
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"content": "What is your favourite color?"
|
"content": "What is your favourite color?"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
...
|
||||||
"extensions": { // [!code focus:28]
|
"extensions": { // [!code focus:28]
|
||||||
"pub.versia:polls": {
|
"pub.versia:polls": {
|
||||||
"options": [
|
"options": [
|
||||||
|
|
@ -102,11 +98,11 @@ If a vote is cast to a poll that is closed, the vote should be rejected with a `
|
||||||
<Property name="type" type="string" required="true">
|
<Property name="type" type="string" required="true">
|
||||||
Must be `pub.versia:polls/Vote`.
|
Must be `pub.versia:polls/Vote`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required="true" typeLink="/types#uri">
|
<Property name="author" type="Reference" required="true" typeLink="/types#reference">
|
||||||
URI to the user who cast the vote.
|
[Reference](/types#reference) of the user who cast the vote.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="poll" type="URI" required="true" typeLink="/types#uri">
|
<Property name="poll" type="Reference" required="true" typeLink="/types#reference">
|
||||||
URI to the poll that the user voted on. Must link to a [Note](/entities/note) with a valid poll.
|
[Reference](/types#reference) to the note with poll that the user voted on.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="option" type="number" required="true" numberType="u64">
|
<Property name="option" type="number" required="true" numberType="u64">
|
||||||
Index of the option that the user voted for. This should be a valid index into the `options` array of the poll.
|
Index of the option that the user voted for. This should be a valid index into the `options` array of the poll.
|
||||||
|
|
@ -120,10 +116,9 @@ If a vote is cast to a poll that is closed, the vote should be rejected with a `
|
||||||
{
|
{
|
||||||
"id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
"id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||||
"type": "pub.versia:polls/Vote", // [!code focus]
|
"type": "pub.versia:polls/Vote", // [!code focus]
|
||||||
"uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3]
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3]
|
||||||
"poll": "https://example.com/notes/f08a124e-fe90-439e-8be4-15a428a72a19",
|
"poll": "example.com:f08a124e-fe90-439e-8be4-15a428a72a19",
|
||||||
"option": 1
|
"option": 1
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ User reactions are (like every other entity) federated to all followers, and can
|
||||||
<Property name="type" type="string" required>
|
<Property name="type" type="string" required>
|
||||||
Must be `pub.versia:reactions/Reaction`.
|
Must be `pub.versia:reactions/Reaction`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required typeLink="/types#uri">
|
<Property name="author" type="Reference" required typeLink="/types#reference">
|
||||||
URI of the [User](/entities/user) that is reacting.
|
[Reference](/types#reference) to the [User](/entities/user) that is reacting.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="object" type="URI" required typeLink="/types#uri">
|
<Property name="object" type="Reference" required typeLink="/types#reference">
|
||||||
URI of the [Note](/entities/note) attached to the reaction.
|
[Reference](/types#reference) to the [Note](/entities/note) attached to the reaction.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="content" type="string" required>
|
<Property name="content" type="string" required>
|
||||||
Emoji content of reaction. May also be arbitrary text, or [Custom Emoji](/extensions/custom-emojis) if supported.
|
Emoji content of reaction. May also be arbitrary text, or [Custom Emoji](/extensions/custom-emojis) if supported.
|
||||||
|
|
@ -39,10 +39,9 @@ User reactions are (like every other entity) federated to all followers, and can
|
||||||
{
|
{
|
||||||
"id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
"id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
||||||
"type": "pub.versia:reactions/Reaction", // [!code focus]
|
"type": "pub.versia:reactions/Reaction", // [!code focus]
|
||||||
"uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
|
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3]
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3]
|
||||||
"object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19",
|
"object": "example.com:f08a124e-fe90-439e-8be4-15a428a72a19",
|
||||||
"content": "😀",
|
"content": "😀",
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -52,20 +51,9 @@ User reactions are (like every other entity) federated to all followers, and can
|
||||||
|
|
||||||
## Note Collections
|
## Note Collections
|
||||||
|
|
||||||
The Likes extension adds the following collections to the [Note](/entities/note) entity:
|
The Reactions extension adds the following collections to the [Note](/entities/note) entity:
|
||||||
|
|
||||||
- `reactions`: A [URI Collection](/structures/collection#uri-collection) of all the reactions to the note.
|
- `pub.versia:reactions/Reactions`: [URI Collection](/structures/collection#uri-collection) of all the reactions to the note.
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"type": "Note",
|
|
||||||
...
|
|
||||||
"collections": {
|
|
||||||
...
|
|
||||||
"pub.versia:reactions/Reactions": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19/reactions"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interaction Types
|
## Interaction Types
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,21 @@ When an instance receives a report, it *should* be reviewed by a moderator or ad
|
||||||
|
|
||||||
## Entity Definition
|
## Entity Definition
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
This entity is a [**Transient Entity**](/entities#transient-entities).
|
||||||
|
</Warning>
|
||||||
|
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Report">
|
<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>
|
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:reports/Report`.
|
Must be `pub.versia:reports/Report`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={false} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={false} typeLink="/types#reference">
|
||||||
URI of the reporting [User](/entities/user). Optional if the report is anonymous.
|
[Reference](/types#reference) to the reporting [User](/entities/user). Optional if the report is anonymous.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="reported" type="URI[]" required={true} typeLink="/types#uri">
|
<Property name="reported" type="Reference[]" required={true} typeLink="/types#reference">
|
||||||
URIs of the content being reported.
|
[References](/types#reference) to the content being reported.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="tags" type="string[]" required={true}>
|
<Property name="tags" type="string[]" required={true}>
|
||||||
Report tags. Should be concise and clear, such as `spam`, `harassment`, `misinformation`, etc. Used for categorization.
|
Report tags. Should be concise and clear, such as `spam`, `harassment`, `misinformation`, etc. Used for categorization.
|
||||||
|
|
@ -39,12 +40,11 @@ When an instance receives a report, it *should* be reviewed by a moderator or ad
|
||||||
|
|
||||||
```jsonc {{ title: "Example Report" }}
|
```jsonc {{ title: "Example Report" }}
|
||||||
{
|
{
|
||||||
"id": "6f3001a1-641b-4763-a9c4-a089852eec84",
|
|
||||||
"type": "pub.versia:reports/Report",
|
"type": "pub.versia:reports/Report",
|
||||||
"author": "https://example.com/users/6f3001a1-641b-4763-a9c4-a089852eec84",
|
"author": "6f3001a1-641b-4763-a9c4-a089852eec84",
|
||||||
"reported": [
|
"reported": [
|
||||||
"https://test.com/publications/46f936a3-9a1e-4b02-8cde-0902a89769fa",
|
"test.com:46f936a3-9a1e-4b02-8cde-0902a89769fa",
|
||||||
"https://test.com/publications/213d7c56-fb9b-4646-a4d2-7d70aa7d106a"
|
"test.com:213d7c56-fb9b-4646-a4d2-7d70aa7d106a"
|
||||||
],
|
],
|
||||||
"tags": [
|
"tags": [
|
||||||
"spam",
|
"spam",
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@ When a user shares a note, the note's original author **must** receive the entit
|
||||||
<Property name="type" type="string" required={true}>
|
<Property name="type" type="string" required={true}>
|
||||||
Must be `pub.versia:share/Share`.
|
Must be `pub.versia:share/Share`.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="author" type="URI" required={true} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={true} typeLink="/types#referece">
|
||||||
Creator of the Share.
|
[Reference](/types#reference) to the creator of the Share.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="shared" type="URI" required={true} typeLink="/types#uri">
|
<Property name="shared" type="Reference" required={true} typeLink="/types#reference">
|
||||||
URI of the note being shared. Must link to a [Note](/entities/note).
|
[Reference](/types#reference) to the note being shared.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -37,9 +37,8 @@ When a user shares a note, the note's original author **must** receive the entit
|
||||||
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"id": "3e7e4750-afd4-4d99-a256-02f0710a0520",
|
||||||
"type": "pub.versia:share/Share",
|
"type": "pub.versia:share/Share",
|
||||||
"created_at": "2021-01-01T00:00:00.000Z",
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
"author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe",
|
||||||
"uri": "https://example.com/shares/3e7e4750-afd4-4d99-a256-02f0710a0520",
|
"shared": "otherexample.org:fmKZ763jzIU8"
|
||||||
"shared": "https://otherexample.org/notes/fmKZ763jzIU8"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -50,18 +49,7 @@ When a user shares a note, the note's original author **must** receive the entit
|
||||||
|
|
||||||
The Share extension adds the following collections to the [Note](/entities/note) entity:
|
The Share extension adds the following collections to the [Note](/entities/note) entity:
|
||||||
|
|
||||||
- `shares`: A [URI Collection](/structures/collection#uri-collection) of all the shares of the note.
|
- `pub.versia:share/Shares`: [URI Collection](/structures/collection#uri-collection) of all the shares of the note.
|
||||||
|
|
||||||
```jsonc
|
|
||||||
{
|
|
||||||
"type": "Note",
|
|
||||||
...
|
|
||||||
"collections": {
|
|
||||||
...
|
|
||||||
"pub.versia:share/Shares": "https://example.com/notes/fmKZ763jzIU8/shares"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Interaction Types
|
## Interaction Types
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,10 @@ All properties are optional.
|
||||||
Audio format (e.g. `audio/mpeg`).
|
Audio format (e.g. `audio/mpeg`).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="pronouns" type="{ [key: LanguageCode]: Pronoun[] }" required={false}>
|
<Property name="pronouns" type="{ [key: LanguageCode]: Pronoun[] }" required={false}>
|
||||||
An array of internationalized pronouns the user uses. Can be represented as a string or an object.
|
An array of internationalized pronouns the user uses.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
/* e.g. "he/him" */
|
interface Pronoun {
|
||||||
type ShortPronoun = string;
|
|
||||||
|
|
||||||
interface LongPronoun {
|
|
||||||
subject: string;
|
subject: string;
|
||||||
object: string;
|
object: string;
|
||||||
dependent_possessive: string;
|
dependent_possessive: string;
|
||||||
|
|
@ -56,12 +53,11 @@ All properties are optional.
|
||||||
reflexive: string;
|
reflexive: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pronoun = ShortPronoun | LongPronoun;
|
|
||||||
/* Example: en-US or fr */
|
/* Example: en-US or fr */
|
||||||
type LanguageCode = string;
|
type LanguageCode = string;
|
||||||
```
|
```
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="birthday" type="RFC3339" required={false} typeLink="/types#rfc3339">
|
<Property name="birthday" type="RFC3339" required={false} typeLink="/types#rfc-3339">
|
||||||
User's birthday. If year is left out or set to `0000`, implementations **SHOULD** not display the year.
|
User's birthday. If year is left out or set to `0000`, implementations **SHOULD** not display the year.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="location" type="string" required={false}>
|
<Property name="location" type="string" required={false}>
|
||||||
|
|
@ -72,8 +68,8 @@ All properties are optional.
|
||||||
<Property name="timezone" type="string" required={false}>
|
<Property name="timezone" type="string" required={false}>
|
||||||
User's timezone. Should be a valid [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) string.
|
User's timezone. Should be a valid [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) string.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="aliases" type="URI[]" required={false} typeLink="/types#uri">
|
<Property name="aliases" type="References[]" required={false} typeLink="/types#reference">
|
||||||
Versia profiles that should be considered aliases of this profile.
|
[References](/types#reference) to Versia profiles that should be considered aliases (or "alt accounts") of this profile.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -91,31 +87,37 @@ All properties are optional.
|
||||||
{
|
{
|
||||||
"image/png": {
|
"image/png": {
|
||||||
"content": "https://cdn.example.com/ab5081cf-b11f-408f-92c2-7c246f290593/cat_ears.png",
|
"content": "https://cdn.example.com/ab5081cf-b11f-408f-92c2-7c246f290593/cat_ears.png",
|
||||||
"remote": true,
|
"remote": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"avatar_mask": {
|
"avatar_mask": {
|
||||||
"image/png": {
|
"image/png": {
|
||||||
"content": "https://cdn.example.com/d8c42be1-d0f7-43ef-b4ab-5f614e1beba4/rounded_square.jpeg",
|
"content": "https://cdn.example.com/d8c42be1-d0f7-43ef-b4ab-5f614e1beba4/rounded_square.jpeg",
|
||||||
"remote": true,
|
"remote": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"image/png": {
|
"image/png": {
|
||||||
"content": "https://cdn.example.com/6492ddcd-311e-4921-9567-41b497762b09/untitled-file-0019822.png",
|
"content": "https://cdn.example.com/6492ddcd-311e-4921-9567-41b497762b09/untitled-file-0019822.png",
|
||||||
"remote": true,
|
"remote": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"audio": {
|
"audio": {
|
||||||
"audio/mpeg": {
|
"audio/mpeg": {
|
||||||
"content": "https://cdn.example.com/4da2f0d4-4728-4819-83e4-d614e4c5bebc/michael-jackson-thriller.mp3",
|
"content": "https://cdn.example.com/4da2f0d4-4728-4819-83e4-d614e4c5bebc/michael-jackson-thriller.mp3",
|
||||||
"remote": true,
|
"remote": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pronouns": {
|
"pronouns": {
|
||||||
"en-us": [
|
"en-us": [
|
||||||
"he/him",
|
{
|
||||||
|
"subject": "he",
|
||||||
|
"object": "him",
|
||||||
|
"dependent_possessive": "his",
|
||||||
|
"independent_possessive": "his",
|
||||||
|
"reflexive": "himself"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"subject": "they",
|
"subject": "they",
|
||||||
"object": "them",
|
"object": "them",
|
||||||
|
|
@ -129,8 +131,8 @@ All properties are optional.
|
||||||
"location": "+40.6894-074.0447/",
|
"location": "+40.6894-074.0447/",
|
||||||
"timezone": "America/New_York",
|
"timezone": "America/New_York",
|
||||||
"aliases": [
|
"aliases": [
|
||||||
"https://burger.social/accounts/349ee237-c672-41c1-aadc-677e185f795a",
|
"burger.social:349ee237-c672-41c1-aadc-677e185f795a",
|
||||||
"https://versia.social/users/f565ef02-035d-4974-ba5e-f62a8558331d"
|
"versia.social:f565ef02-035d-4974-ba5e-f62a8558331d"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
export const metadata = {
|
|
||||||
title: 'WebSocket Extension',
|
|
||||||
description:
|
|
||||||
'The WebSocket extension adds support for real-time communication between instances.',
|
|
||||||
}
|
|
||||||
|
|
||||||
# WebSockets Extension
|
|
||||||
|
|
||||||
<Note>
|
|
||||||
This document is **provided for informative purposes** and should not be used in a production environment. It is subject to change.
|
|
||||||
|
|
||||||
If internal testing proves unsuccessful at solving the problems with the HTTP delivery method, this document may be abandoned.
|
|
||||||
</Note>
|
|
||||||
|
|
||||||
Typically, communication between Versia instances is done via HTTP. However, HTTP suffers from some limitations, such as high latency and heavy overhead for small messages, making it less suitable for exchanging large amounts of entities at acceptable speeds. {{ className: 'lead' }}
|
|
||||||
|
|
||||||
This extension aims to address these limitations by adding support for the exchange of entities using WebSockets.
|
|
||||||
|
|
||||||
## Message Format
|
|
||||||
|
|
||||||
Messages sent over the WebSocket connection are JSON objects.
|
|
||||||
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<Properties name="WebSocketMessage">
|
|
||||||
<Property name="signature" type="string" required={true}>
|
|
||||||
Same as the `Versia-Signature` header in HTTP requests.
|
|
||||||
</Property>
|
|
||||||
<Property name="signed_at" type="string" required={true}>
|
|
||||||
Same as the `Versia-Signed-At` header in HTTP requests.
|
|
||||||
</Property>
|
|
||||||
<Property name="signed_by" type="URI" required={true}>
|
|
||||||
Same as the `Versia-Signed-By` header in HTTP requests.
|
|
||||||
</Property>
|
|
||||||
<Property name="entity" type="Entity" required={true} typeLink="/entities">
|
|
||||||
Same as the request body in HTTP requests. Must be a string (stringified JSON), not JSON.
|
|
||||||
</Property>
|
|
||||||
</Properties>
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
<Col sticky>
|
|
||||||
|
|
||||||
```jsonc {{ 'title': 'Example Message' }}
|
|
||||||
{
|
|
||||||
"signature": "/CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==",
|
|
||||||
"signed_at": "1729241807",
|
|
||||||
"signed_by": "https://bongo.social/users/63a00ab3-39b1-49eb-b88e-ed65d2361f3e",
|
|
||||||
"entity": "{\"id\":\"9a8928b6-2526-4979-aab1-ef2f88cd5700\",\"type\":\"Delete\",\"created_at\":\"2022-01-01T12:00:00Z\",\"author\":\"https://bongo.social/users/63a00ab3-39b1-49eb-b88e-ed65d2361f3e\",\"deleted\":\"https://bongo.social/notes/54059ce2-9332-46fa-bf6a-598b5493b81b\"}"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
## Connection Establishment
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
export const metadata = {
|
|
||||||
title: 'Delegation',
|
|
||||||
description: 'Delegation is used to authorize actions on behalf of another user',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Delegation
|
|
||||||
|
|
||||||
Delegation is used to authorize actions on behalf of another user. {{ className: 'lead' }}
|
|
||||||
|
|
||||||
## Vocabulary
|
|
||||||
|
|
||||||
- **Delegator**: The user that is delegating actions to another user. (The user that owns the key)
|
|
||||||
- **Delegate**: The user that is being delegated actions. (The user that the key is pointing to)
|
|
||||||
|
|
||||||
## The `actor` Field on Public Keys
|
|
||||||
|
|
||||||
[Users](/entities/user)'s `public_key` property contains a field called `actor`. This field contains the URI to the **delegator** user, which is used to authorize actions on behalf of the **delegate** user.
|
|
||||||
|
|
||||||
This means that the **delegator** user can sign requests with their private key, and any implementations should consider the **delegate** user as equivalent to the **delegator** user.
|
|
||||||
|
|
||||||
## Implementation Details
|
|
||||||
|
|
||||||
Any actions or entities created by the **delegate** should be attributed to the **delegator** user in clients transparently to end-users (e.g. showing the **delegator** user's name and avatar). This allows for a form of "consensual impersonation" that is authorized by the **delegators** and **delegates**.
|
|
||||||
|
|
||||||
This is useful as a way to centralize all of a user's many "alt accounts" into a single, unified feed.
|
|
||||||
|
|
@ -24,7 +24,7 @@ Accept: application/jrd+json
|
||||||
{
|
{
|
||||||
"subject": "acct:george@versia.social", // [!code focus:6]
|
"subject": "acct:george@versia.social", // [!code focus:6]
|
||||||
"aliases": [
|
"aliases": [
|
||||||
"https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771",
|
"https://versia.social/.versia/v0.6/entities/User/018ec082-0ae1-761c-b2c5-22275a611771",
|
||||||
"https://versia.social/@george"
|
"https://versia.social/@george"
|
||||||
],
|
],
|
||||||
"links": [
|
"links": [
|
||||||
|
|
@ -35,8 +35,8 @@ Accept: application/jrd+json
|
||||||
},
|
},
|
||||||
{ // [!code focus:5]
|
{ // [!code focus:5]
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"type": "application/json",
|
"type": "application/vnd.versia+json",
|
||||||
"href": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771"
|
"href": "https://versia.social/.versia/v0.6/entities/User/018ec082-0ae1-761c-b2c5-22275a611771"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"rel": "http://webfinger.net/rel/avatar",
|
"rel": "http://webfinger.net/rel/avatar",
|
||||||
|
|
@ -49,19 +49,40 @@ Accept: application/jrd+json
|
||||||
|
|
||||||
## Instance Discovery
|
## Instance Discovery
|
||||||
|
|
||||||
Instaance metadata can be accessed by making a `GET` request to the instance's Versia metadata endpoint, which is located at `/.well-known/versia`. This endpoint does not need any signatures in the output.
|
Instance metadata can be accessed in two steps:
|
||||||
|
|
||||||
|
1. Making a `GET` request to the instance's [`/.well-known/versia` endpoint](/api/endpoints#well-known) to discover supported Versia Protocol versions.
|
||||||
|
2. Picking a protocol version to use, and then querying the instance metadata endpoint as documented in the [Endpoints](/api/endpoints#instance-metadata) document.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
To discover the metadata of the instance `versia.social`, an instance would make a `GET` request to `https://versia.social/.well-known/versia`.
|
To discover the metadata of the instance `versia.social`, an instance would first make a `GET` request to `https://versia.social/.well-known/versia`.
|
||||||
|
|
||||||
This endpoint will return an [InstanceMetadata](/entities/instance-metadata) entity.
|
|
||||||
|
|
||||||
```http {{ 'title': 'Example Request' }}
|
```http {{ 'title': 'Example Request' }}
|
||||||
GET /.well-known/versia HTTP/1.1
|
GET /.well-known/versia HTTP/1.1
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```jsonc {{ 'title': 'Example Response' }}
|
||||||
|
{
|
||||||
|
"versions": [
|
||||||
|
"0.6.0",
|
||||||
|
"0.5.0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, we
|
||||||
|
- Pick version `0.6.0` to use
|
||||||
|
- Make a `GET` request to `https://versia.social/.versia/v0.6/instance`.
|
||||||
|
|
||||||
|
This endpoint will return an [InstanceMetadata](/entities/instance-metadata) entity.
|
||||||
|
|
||||||
|
```http {{ 'title': 'Example Request' }}
|
||||||
|
GET /.versia/v0.6/instance HTTP/1.1
|
||||||
|
Accept: application/vnd.versia+json
|
||||||
|
```
|
||||||
|
|
||||||
```jsonc {{ 'title': 'Example Response' }}
|
```jsonc {{ 'title': 'Example Response' }}
|
||||||
{
|
{
|
||||||
"type": "InstanceMetadata",
|
"type": "InstanceMetadata",
|
||||||
|
|
@ -72,7 +93,8 @@ Accept: application/json
|
||||||
},
|
},
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"versions": [
|
"versions": [
|
||||||
"0.5.0"
|
"0.5.0",
|
||||||
|
"0.6.0"
|
||||||
],
|
],
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"pub.versia:reactions",
|
"pub.versia:reactions",
|
||||||
|
|
@ -80,7 +102,10 @@ Accept: application/json
|
||||||
"pub.versia:reports"
|
"pub.versia:reports"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"host": "versia.social",
|
"domain": "versia.social",
|
||||||
"created_at": "2021-07-01T00:00:00Z"
|
"created_at": "2021-07-01T00:00:00Z",
|
||||||
|
"description": null,
|
||||||
|
"logo": null,
|
||||||
|
"banner": null
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -40,8 +40,8 @@ curl https://b.social/.well-known/webfinger?resource=acct:joe@b.social -H "Accep
|
||||||
"links": [
|
"links": [
|
||||||
{ // [!code focus:5]
|
{ // [!code focus:5]
|
||||||
"rel": "self",
|
"rel": "self",
|
||||||
"type": "application/json",
|
"type": "application/vnd.versia+json",
|
||||||
"href": "https://b.social/users/joe"
|
"href": "https://b.social/.versia/entities/User/joe"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +50,7 @@ curl https://b.social/.well-known/webfinger?resource=acct:joe@b.social -H "Accep
|
||||||
<Note>
|
<Note>
|
||||||
In a real Versia implementation, usernames would **not** be included in user profile's URL, as they can be changed. Instead, the `id` could be used.
|
In a real Versia implementation, usernames would **not** be included in user profile's URL, as they can be changed. Instead, the `id` could be used.
|
||||||
|
|
||||||
This is done for simplicity in this example.
|
This is done for brevity here.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
### Fetching the User
|
### Fetching the User
|
||||||
|
|
@ -58,12 +58,12 @@ curl https://b.social/.well-known/webfinger?resource=acct:joe@b.social -H "Accep
|
||||||
`a.social` fetches the user profile of `joe` from `b.social` using the URL provided in the WebFinger response.
|
`a.social` fetches the user profile of `joe` from `b.social` using the URL provided in the WebFinger response.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl https://b.social/users/joe \
|
# The request is signed by a.social's instance private key
|
||||||
-H "Accept: application/json" \
|
curl https://b.social/.versia/entities/User/joe \
|
||||||
|
-H "Accept: application/vnd.versia+json" \
|
||||||
-H "User-Agent: CoolServer/1.0 (https://coolserver.com)" \
|
-H "User-Agent: CoolServer/1.0 (https://coolserver.com)" \
|
||||||
# The request is signed by a.social's instance private key
|
|
||||||
-H "Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==" \
|
-H "Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==" \
|
||||||
-H "Versia-Signed-By: https://a.social/users/alice" \
|
-H "Versia-Signed-By: a.social" \
|
||||||
-H "Versia-Signed-At: 1729241687"
|
-H "Versia-Signed-At: 1729241687"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -71,30 +71,30 @@ curl https://b.social/users/joe \
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"id": "bde22zi3ca8762", // [!code focus:10]
|
"id": "bde22zi3ca8762", // [!code focus:3]
|
||||||
"type": "User",
|
"type": "User",
|
||||||
"uri": "https://b.social/users/joe",
|
|
||||||
"created_at": "2024-10-13T18:48:19Z",
|
"created_at": "2024-10-13T18:48:19Z",
|
||||||
"avatar": {
|
"avatar": {
|
||||||
"image/webp": {
|
"image/webp": {
|
||||||
"content": "https://cdn.b.social/avatars/joe.webp",
|
"content": "https://cdn.b.social/avatars/joe.webp",
|
||||||
"remote": true
|
"remote": true,
|
||||||
|
"description": null,
|
||||||
|
"size": null,
|
||||||
|
"hash": null,
|
||||||
|
"thumbhash": null,
|
||||||
|
"width": null,
|
||||||
|
"height": null,
|
||||||
|
"fps": null,
|
||||||
|
"duration": null
|
||||||
}
|
}
|
||||||
},
|
}, // [!code focus:3]
|
||||||
"collections": {
|
|
||||||
"featured": "https://b.social/users/joe/featured",
|
|
||||||
"followers": "https://b.social/users/joe/followers",
|
|
||||||
"following": "https://b.social/users/joe/following",
|
|
||||||
"outbox": "https://b.social/users/joe/outbox"
|
|
||||||
}, // [!code focus:9]
|
|
||||||
"display_name": "Joe Swanson (Winter Arc :gigachad:)",
|
"display_name": "Joe Swanson (Winter Arc :gigachad:)",
|
||||||
"inbox": "https://b.social/inbox",
|
|
||||||
"public_key": {
|
|
||||||
"actor": "https://b.social/users/joe",
|
|
||||||
"algorithm": "ed25519",
|
|
||||||
"key": "MCowBQYDK2VwAyEAOSCcfsde0Ya3vf/P6lzgK0pA8qCISqneaze3omLlQCQ="
|
|
||||||
},
|
|
||||||
"username": "joe",
|
"username": "joe",
|
||||||
|
"bio": null,
|
||||||
|
"header": null,
|
||||||
|
"fields": [],
|
||||||
|
"manually_approves_followers": false,
|
||||||
|
"indexable": true,
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"pub.versia:custom_emojis": {
|
"pub.versia:custom_emojis": {
|
||||||
"emojis": [
|
"emojis": [
|
||||||
|
|
@ -103,7 +103,15 @@ curl https://b.social/users/joe \
|
||||||
"content": {
|
"content": {
|
||||||
"image/png": {
|
"image/png": {
|
||||||
"content": "https://cdn.b.social/emojis/gigachad.png",
|
"content": "https://cdn.b.social/emojis/gigachad.png",
|
||||||
"remote": true
|
"remote": true,
|
||||||
|
"description": null,
|
||||||
|
"size": null,
|
||||||
|
"hash": null,
|
||||||
|
"thumbhash": null,
|
||||||
|
"width": null,
|
||||||
|
"height": null,
|
||||||
|
"fps": null,
|
||||||
|
"duration": null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,28 +131,46 @@ Finally, `a.social` serializes the note to send it to `joe`.
|
||||||
{
|
{
|
||||||
"id": "782addd9-c051-4eea-8ba4-23d561d0c5bb", // [!code focus:6]
|
"id": "782addd9-c051-4eea-8ba4-23d561d0c5bb", // [!code focus:6]
|
||||||
"type": "Note",
|
"type": "Note",
|
||||||
"uri": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb",
|
|
||||||
"created_at": "2024-12-01T12:19:06Z",
|
"created_at": "2024-12-01T12:19:06Z",
|
||||||
"author": "https://a.social/users/alice",
|
"author": "alice",
|
||||||
"category": "microblog",
|
"category": "microblog",
|
||||||
"collections": {
|
|
||||||
"replies": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb/replies",
|
|
||||||
"quotes": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb/quotes"
|
|
||||||
}, // [!code focus:11]
|
|
||||||
"content": {
|
"content": {
|
||||||
"text/html": {
|
"text/html": { // [!code focus:12]
|
||||||
"content": "Hello, <a class=\"u-url mention\" href=\"https://b.social/users/joe\">@joe@b.social</a>! How are you doing today?",
|
"content": "Hello, <a class=\"u-url mention\" href=\"https://b.social/users/bde22zi3ca8762\">@joe@b.social</a>! How are you doing today?",
|
||||||
"remote": false,
|
"remote": false,
|
||||||
|
"description": null,
|
||||||
|
"size": null,
|
||||||
|
"hash": null,
|
||||||
|
"thumbhash": null,
|
||||||
|
"width": null,
|
||||||
|
"height": null,
|
||||||
|
"fps": null,
|
||||||
|
"duration": null
|
||||||
},
|
},
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
"content": "Hello, @joe@b.social! How are you doing today?",
|
"content": "Hello, @joe@b.social! How are you doing today?",
|
||||||
"remote": false,
|
"remote": false,
|
||||||
|
"description": null,
|
||||||
|
"size": null,
|
||||||
|
"hash": null,
|
||||||
|
"thumbhash": null,
|
||||||
|
"width": null,
|
||||||
|
"height": null,
|
||||||
|
"fps": null,
|
||||||
|
"duration": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"group": "public",
|
"group": "public",
|
||||||
"mentions": [ // [!code focus:3]
|
"mentions": [ // [!code focus:3]
|
||||||
"https://b.social/users/joe"
|
"b.social:bde22zi3ca8762"
|
||||||
]
|
],
|
||||||
|
"attachments": [],
|
||||||
|
"is_sensitive": false,
|
||||||
|
"previews": [],
|
||||||
|
"replies_to": null,
|
||||||
|
"quotes": null,
|
||||||
|
"subject": null,
|
||||||
|
"device": null,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -155,13 +181,13 @@ It is now time for `a.social` to send the note to `joe`.
|
||||||
`a.social` sends the note to `joe`'s inbox at `b.social`.
|
`a.social` sends the note to `joe`'s inbox at `b.social`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -X POST https://b.social/inbox \
|
curl -X POST https://b.social/.versia/v0.6/inbox \
|
||||||
-H "Content-Type: application/json; charset=utf-8" \
|
-H "Content-Type: application/vnd.versia+json; charset=utf-8" \
|
||||||
-H "Accept: application/json" \
|
-H "Accept: application/json" \
|
||||||
-H "User-Agent: CoolerServer/1.0 (https://coolerserver.com)" \
|
-H "User-Agent: CoolerServer/1.0 (https://coolerserver.com)" \
|
||||||
# The request is signed by Alice's private key
|
# The request is signed by Alice's private key
|
||||||
-H "Versia-Signature: 9BrfplAPVH6OEqlV5eX7MazaZAInSCPODZcBEvMliBi/OwfbCAsezlb0O9jUX9ZcbBA68ThA4WUgS9V+42rfAQ==" \
|
-H "Versia-Signature: 9BrfplAPVH6OEqlV5eX7MazaZAInSCPODZcBEvMliBi/OwfbCAsezlb0O9jUX9ZcbBA68ThA4WUgS9V+42rfAQ==" \
|
||||||
-H "Versia-Signed-By: https://a.social/users/alice" \
|
-H "Versia-Signed-By: a.social" \
|
||||||
-H "Versia-Signed-At: 1733051946"
|
-H "Versia-Signed-At: 1733051946"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export const metadata = {
|
||||||
|
|
||||||
Versia uses the HTTP protocol for all communications between instances. HTTP requests must conform to certain standards to ensure compatibility between different implementations, as well as to ensure the security and integrity of the data being exchanged.
|
Versia uses the HTTP protocol for all communications between instances. HTTP requests must conform to certain standards to ensure compatibility between different implementations, as well as to ensure the security and integrity of the data being exchanged.
|
||||||
|
|
||||||
ALL kinds of HTTP requests/responses between instances **MUST** include a [Signature](/signatures), signed with either the relevant [User](/entities/user)'s private key or the [instance's private key](/entities/instance-metadata).
|
HTTP requests/responses between instances **must** include a [Signature](/signatures), signed with the [instance's private key](/entities/instance-metadata), as defined in [Signatures](/signatures).
|
||||||
|
|
||||||
## Requests
|
## Requests
|
||||||
|
|
||||||
|
|
@ -16,32 +16,37 @@ ALL kinds of HTTP requests/responses between instances **MUST** include a [Signa
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="HTTP Request">
|
<Properties name="HTTP Request">
|
||||||
<Property name="Accept" type="string" required={true}>
|
<Property name="Accept" type="string" required={true}>
|
||||||
Must include `application/json`.
|
Must be `application/vnd.versia+json`, unless specified otherwise. Basic `application/json` is **not** allowed.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Content-Type" type="string" required={true}>
|
<Property name="Content-Type" type="string" required={true}>
|
||||||
Must include `application/json; charset=utf-8`, if the request has a body.
|
Must be `application/vnd.versia+json; charset=utf-8` if the request has a body.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Versia-Signature" type="string" required={false}>
|
<Property name="Versia-Signature" type="string" required={true}>
|
||||||
See [Signatures](/signatures) for more information.
|
See [Signatures](/signatures) for more information.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Versia-Signed-By" type="URI" required={false} typeLink="/types#uri">
|
<Property name="Versia-Signed-By" type="Domain" required={true} typeLink="/api/basics#domain">
|
||||||
See [Signatures](/signatures).
|
See [Signatures](/signatures).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Versia-Signed-At" type="string" required={false}>
|
<Property name="Versia-Signed-At" type="number" required={true}>
|
||||||
See [Signatures](/signatures).
|
See [Signatures](/signatures).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="User-Agent" type="string" required={false}>
|
<Property name="User-Agent" type="string" required={false}>
|
||||||
A string identifying the software making the request.
|
A string identifying the software making the request. Should contain the name of the software, its version, and a link to its homepage.
|
||||||
|
|
||||||
|
``` {{ 'title': 'Example User-Agent' }}
|
||||||
|
CoolServer/1.0 (https://coolserver.com)
|
||||||
|
```
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
<Col sticky>
|
<Col sticky>
|
||||||
```http {{ 'title': 'Example Request' }}
|
```http {{ 'title': 'Example Request' }}
|
||||||
POST https://bob.com/users/1/inbox HTTP/1.1
|
POST https://bob.com/.versia/v0.6/inbox HTTP/1.1
|
||||||
|
# This specific endpoint returns plain JSON
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
User-Agent: CoolServer/1.0 (https://coolserver.com)
|
User-Agent: CoolServer/1.0 (https://coolserver.com)
|
||||||
Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==
|
Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==
|
||||||
Versia-Signed-By: https://example.com/users/1
|
Versia-Signed-By: example.com
|
||||||
Versia-Signed-At: 1729241687
|
Versia-Signed-At: 1729241687
|
||||||
```
|
```
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -49,9 +54,9 @@ ALL kinds of HTTP requests/responses between instances **MUST** include a [Signa
|
||||||
|
|
||||||
## Rate limits
|
## Rate limits
|
||||||
|
|
||||||
Implementations **MUST** respect the rate limits of remote instances.
|
Implementations **must** respect the rate limits of remote instances.
|
||||||
|
|
||||||
IETF draft [draft-polli-ratelimit-headers-02](https://www.ietf.org/archive/id/draft-polli-ratelimit-headers-02.html) **MUST** be used to communicate rate limits. Other rate limit headers/formats are not allowed.
|
IETF draft [draft-polli-ratelimit-headers-02](https://www.ietf.org/archive/id/draft-polli-ratelimit-headers-02.html) **must** be used to communicate rate limits. Other rate limit headers/formats are not allowed.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
This IETF draft is, well, a draft. However, there are no standards for rate limiting in HTTP, so this is the best we have.
|
This IETF draft is, well, a draft. However, there are no standards for rate limiting in HTTP, so this is the best we have.
|
||||||
|
|
@ -63,15 +68,15 @@ IETF draft [draft-polli-ratelimit-headers-02](https://www.ietf.org/archive/id/dr
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="HTTP Response">
|
<Properties name="HTTP Response">
|
||||||
<Property name="Content-Type" type="string" required={true}>
|
<Property name="Content-Type" type="string" required={true}>
|
||||||
Must include `application/json; charset=utf-8`.
|
Must include `application/vnd.versia+json; charset=utf-8`, unless specified otherwise.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Versia-Signature" type="string" required={false}>
|
<Property name="Versia-Signature" type="string" required={true}>
|
||||||
See [Signatures](/signatures) for more information.
|
See [Signatures](/signatures) for more information.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Versia-Signed-By" type="URI" required={false} typeLink="/types#uri">
|
<Property name="Versia-Signed-By" type="Domain" required={true} typeLink="/api/basics#domain">
|
||||||
See [Signatures](/signatures).
|
See [Signatures](/signatures).
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="Versia-Signed-At" type="string" required={false}>
|
<Property name="Versia-Signed-At" type="number" required={true}>
|
||||||
See [Signatures](/signatures).
|
See [Signatures](/signatures).
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
|
|
@ -79,9 +84,9 @@ IETF draft [draft-polli-ratelimit-headers-02](https://www.ietf.org/archive/id/dr
|
||||||
<Col sticky>
|
<Col sticky>
|
||||||
```http {{ 'title': 'Example Response' }}
|
```http {{ 'title': 'Example Response' }}
|
||||||
HTTP/1.1 200 OK
|
HTTP/1.1 200 OK
|
||||||
Content-Type: application/json; charset=utf-8
|
Content-Type: application/vnd.versia+json; charset=utf-8
|
||||||
Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==+7BvnWKITyGyTwHbb6fVYwRx1I
|
Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw==+7BvnWKITyGyTwHbb6fVYwRx1I
|
||||||
Versia-Signed-By: https://example.com/users/1
|
Versia-Signed-By: example.com
|
||||||
Versia-Signed-At: 1729241717
|
Versia-Signed-At: 1729241717
|
||||||
```
|
```
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -21,24 +21,30 @@ Federation is built on the [HyperText Transfer Protocol (HTTP)](https://tools.ie
|
||||||
|
|
||||||
## Inboxes
|
## Inboxes
|
||||||
|
|
||||||
Ever [User](/entities/user) has a personal HTTP endpoint called an inbox (e.g., `/users/3/inbox`). This endpoint is used to send and receive messages between users and instances. Messages are sent as JSON payloads over HTTP `POST` requests.
|
<Note>
|
||||||
|
See the [Inbox Endpoint](/api/endpoints#inbox) for more information on the inbox endpoint.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
Ever [Instance](/entities/instance-metadata) has a personal HTTP endpoint called an inbox (`/.versia/v0.6/inbox`). This endpoint is used to send and receive messages between users and instances. Messages are sent as JSON payloads over HTTP `POST` requests.
|
||||||
|
|
||||||
Let's consider the following example:
|
Let's consider the following example:
|
||||||
|
|
||||||
> Alice, on the instance `alice.example`, sends a message to Bob on the instance `bob.example`.
|
Alice, on the instance `alice.example`, sends a message to Bob on the instance `bob.example`.
|
||||||
|
|
||||||
To perform this action, Alice's instance sends a `POST` request to Bob's inbox endpoint, which can be found by checking the `inbox` field in Bob's [User](/entities/user) entity. This request contains the [Note](/entities/note) entity that Alice wants to send to Bob, with [the appropriate metadata](/federation/http) to ensure the message is valid.
|
To perform this action, Alice's instance sends a `POST` request to Bob's instance's inbox endpoint. This request contains the [Note](/entities/note) entity that Alice wants to send to Bob, with [the appropriate metadata](/federation/http) to ensure the message is valid.
|
||||||
|
|
||||||
Bob's instance receives the message and processes it according to the rules defined in the [Validation](/federation/validation) document.
|
Bob's instance receives the message and processes it according to the rules defined in the [Validation](/federation/validation) document.
|
||||||
|
|
||||||
### Shared Inboxes
|
|
||||||
|
|
||||||
In addition to personal inboxes, instances can also have shared inboxes. Shared inboxes are a single per-instance endpoint that can receive messages for multiple users. This is useful for instances that want to reduce the number of HTTP requests they need to handle.
|
|
||||||
|
|
||||||
Shared inboxes are defined in the [Instance Metadata](/entities/instance-metadata) entity. If supported, they should be used in place of personal inboxes.
|
|
||||||
|
|
||||||
## Outboxes
|
## Outboxes
|
||||||
|
|
||||||
In addition to inboxes, every user has an outbox (e.g., `/users/3/outbox`). The outbox is simply a [Collection](/structures/collection) of all the messages that a user has sent. When a user sends a message to another user, a copy of that message is accessible in the sender's outbox.
|
In addition to inboxes, every user has an outbox (at `/.versia/v0.6/entities/User/<id>/collections/outbox`). The outbox is simply a [Collection](/structures/collection) of all the messages that a user has sent. When a user sends a message to another user, a copy of that message is accessible in the sender's outbox.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
Implementations **should** filter out entities that are not relevant to the request author when returning the outbox.
|
||||||
|
|
||||||
|
For example, if Alice sends a [Note](/entities/note) to Bob on `direct` visibility:
|
||||||
|
- Alice's instance **should** return the [Note](/entities/note) in response to a request from Bob's instance.
|
||||||
|
- Alice's instance **should not** display the [Note](/entities/note) in her outbox in response to a request from Joe's instance.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
Outboxes are very useful for "backfilling" data when a new instance joins the network. By resolving the outboxes of all new users it encounters, a new instance can quickly catch up on all old messages.
|
Outboxes are very useful for "backfilling" data when a new instance joins the network. By resolving the outboxes of all new users it encounters, a new instance can quickly catch up on all old messages.
|
||||||
|
|
@ -6,7 +6,7 @@ export const metadata = {
|
||||||
|
|
||||||
# Validation
|
# Validation
|
||||||
|
|
||||||
Implementations **MUST** strictly validate all incoming data to ensure that it is well-formed and adheres to the Versia Protocol. If a request is invalid, the instance **MUST** return a `400 Bad Request` HTTP status code.
|
Implementations **MUST** strictly validate all incoming data to ensure that it is well-formed and adheres to the Versia Protocol. If a request is invalid, the instance **MUST** return a `422 Unprocessable Entity` HTTP status code.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
Remember that while *your* implementation may disallow or restrict some user input, other implementations may not. You **should not** apply those restrictions to data coming from other instances.
|
Remember that while *your* implementation may disallow or restrict some user input, other implementations may not. You **should not** apply those restrictions to data coming from other instances.
|
||||||
|
|
@ -16,13 +16,13 @@ Implementations **MUST** strictly validate all incoming data to ensure that it i
|
||||||
|
|
||||||
Things that should be validated include, but are not limited to:
|
Things that should be validated include, but are not limited to:
|
||||||
|
|
||||||
- The presence of **all required fields**.
|
- The presence of **all required fields**, and the presence of `null` on optional fields.
|
||||||
- The **format** of all fields (integers should not be strings, timestamps should be in RFC 3339 format, etc.).
|
- The **format** of all fields (integers should not be strings, timestamps should be in RFC 3339 format, etc.).
|
||||||
- The presence of **all required headers**.
|
- The presence of **all required headers**.
|
||||||
- The presence of a **valid signature**.
|
- The presence of a **valid signature**.
|
||||||
- The **length** of all fields (for example, the `username` field on a `User` entity) should be at least 1 character long.
|
- The **length** of all fields (for example, the `username` field on a `User` entity) should be at least 1 character long.
|
||||||
- Do not set arbitrary limits on the length of fields that other instances may send you. For example, a `bio` field should not be limited to 160 characters, even if your own implementation has such a limit.
|
- Do not set arbitrary limits on the length of fields that other instances may send you. For example, a `bio` field should not be limited to 160 characters, even if your own implementation has such a limit.
|
||||||
- If you do set limits, they should be reasonable, well-documented and should allow Users to easily view the remote original, by, for example, linking to it.
|
- If you do set limits, they should be reasonable, well-documented and should allow Users to easily view the remote original, by, for example, linking to it. A limit of `100 000` characters for a `bio` field is acceptable, but a limit of `160` characters is not.
|
||||||
- The **type**, **precision** and **scale** of all numeric fields.
|
- The **type**, **precision** and **scale** of all numeric fields.
|
||||||
- For example, a `size` field on a `ContentFormat` structure should be a positive integer, not a negative number or a floating-point number.
|
- For example, a `size` field on a `ContentFormat` structure should be a positive integer, not a negative number or a floating-point number.
|
||||||
<Note>
|
<Note>
|
||||||
|
|
@ -30,7 +30,7 @@ Things that should be validated include, but are not limited to:
|
||||||
|
|
||||||
Using the same type with a higher bit count, for example using a u128 instead of a u64, is acceptable. Beware of performance impacts this may cause.
|
Using the same type with a higher bit count, for example using a u128 instead of a u64, is acceptable. Beware of performance impacts this may cause.
|
||||||
</Note>
|
</Note>
|
||||||
- The **validity** of all URLs and URIs (run them through your favorite URL parser, optionally fetch the linked URL).
|
- The **validity** of all URLs and URIs (run them through your favorite URL parser).
|
||||||
- The **time** of all dates and times (people should not be born in the future, or in the year 0).
|
- The **time** of all dates and times (people should not be born in the future, or in the year 0).
|
||||||
|
|
||||||
It is your implementation's duty to reject data from other instances that does not adhere to the strict spec. **This is crucial to ensure the integrity of your instance and the network as a whole**. Allowing data that is technically valid but semantically incorrect can lead to the degradation of the entire Versia ecosystem.
|
It is your implementation's duty to reject data from other instances that does not adhere to the strict spec. **This is crucial to ensure the integrity of your instance and the network as a whole**. Allowing data that is technically valid but semantically incorrect can lead to the degradation of the entire Versia ecosystem.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { HeroPattern } from '@/components/HeroPattern'
|
||||||
|
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: 'Versia Documentation',
|
title: 'Versia Documentation',
|
||||||
description: 'Introduction to the Versia Protocol, a communication medium for federated applications, leveraging the HTTP stack.',
|
description: 'Introduction to the Versia Protocol, a communication medium for federated applications, using the HTTP stack.',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sections = [
|
export const sections = [
|
||||||
|
|
@ -16,7 +16,7 @@ export const sections = [
|
||||||
|
|
||||||
# Versia Federation Protocol
|
# Versia Federation Protocol
|
||||||
|
|
||||||
The Versia Protocol is designed as a communication medium for federated applications, leveraging the HTTP stack. Its simplicity ensures ease of implementation and comprehension. {{ className: 'lead' }}
|
The Versia Protocol is designed as a communication medium for federated applications, using the HTTP stack. Its simplicity ensures ease of implementation and comprehension. {{ className: 'lead' }}
|
||||||
|
|
||||||
<div className="not-prose mb-16 mt-6 flex gap-3">
|
<div className="not-prose mb-16 mt-6 flex gap-3">
|
||||||
<Button href="/entities" arrow="right">
|
<Button href="/entities" arrow="right">
|
||||||
|
|
@ -45,9 +45,8 @@ The Versia Protocol uses the following terms:
|
||||||
|
|
||||||
The Versia Protocol is heavily inspired by the [ActivityPub](https://www.w3.org/TR/activitypub/) specification. It is designed to be simple and easy to implement, with a focus on the following concepts:
|
The Versia Protocol is heavily inspired by the [ActivityPub](https://www.w3.org/TR/activitypub/) specification. It is designed to be simple and easy to implement, with a focus on the following concepts:
|
||||||
- **Simple Structures**: Entities are represented as JSON objects. No JSON-LD, no complex data structures, just plain JSON.
|
- **Simple Structures**: Entities are represented as JSON objects. No JSON-LD, no complex data structures, just plain JSON.
|
||||||
|
- As structures are kept simple, they are easy to parse with strongly-typed languages like Rust.
|
||||||
- **Modularity**: The protocol is divided into a **core protocol** and **extensions**. Implementations can choose to support only the core protocol or add extensions as needed.
|
- **Modularity**: The protocol is divided into a **core protocol** and **extensions**. Implementations can choose to support only the core protocol or add extensions as needed.
|
||||||
- **Namespacing**: To avoid extension conflicts, all extensions are namespaced.
|
- **Namespacing**: To avoid extension conflicts, all extensions are namespaced.
|
||||||
- **Signatures**: Most types of interactions **must** be signed with a private key. Unlike other protocols, signatures are **mandatory**, not optional.
|
- **Signatures**: Most types of interactions **must** be signed with a private key. Unlike other protocols, signatures are **mandatory**, not optional.
|
||||||
- **Developer-Friendliness**: Understanding and implementing your own Versia server should be easy. Documentation is aimed at developers first.
|
- **Developer-Friendliness**: Understanding and implementing your own Versia server should be easy. Documentation is aimed at developers first.
|
||||||
|
|
||||||
<Resources />
|
|
||||||
|
|
|
||||||
119
app/json/page.mdx
Normal file
119
app/json/page.mdx
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
export const metadata = {
|
||||||
|
title: 'JSON',
|
||||||
|
description:
|
||||||
|
'Guidelines on JSON handling and serialization',
|
||||||
|
}
|
||||||
|
|
||||||
|
# JSON
|
||||||
|
|
||||||
|
Identical data structures can be represented in many different ways in JSON. This document describes the rules that must be followed when using JSON in the Versia protocol.
|
||||||
|
|
||||||
|
## Encoding
|
||||||
|
|
||||||
|
All JSON data **must** be encoded in UTF-8. This is the only encoding supported by the Versia protocol.
|
||||||
|
|
||||||
|
Line endings must be in Unix-style `\n` (LF) format. The use of Windows-style `\r\n` (CRLF) line endings is not allowed.
|
||||||
|
|
||||||
|
## Keys
|
||||||
|
|
||||||
|
Keys in JSON must be strings, cannot be empty, and may only contain the following characters:
|
||||||
|
- `a-z`
|
||||||
|
- `A-Z`
|
||||||
|
- `0-9`
|
||||||
|
- `-`, `_`, `.`, `#`, `/`, `:`
|
||||||
|
|
||||||
|
Duplicate keys are **not** allowed.
|
||||||
|
|
||||||
|
``` json {{ "title": "Valid Keys" }}
|
||||||
|
{
|
||||||
|
"valid-key": "value",
|
||||||
|
"valid_key": "value",
|
||||||
|
"valid.key": "value",
|
||||||
|
"valid#key": "value",
|
||||||
|
"valid/key": "value",
|
||||||
|
"valid:key": "value"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Invalid Keys" }}
|
||||||
|
{
|
||||||
|
"invalid key": "value", // ❌️ Invalid: space is not allowed
|
||||||
|
"invalid@key": "value", // ❌️ Invalid: @ is not allowed
|
||||||
|
"": "value", // ❌️ Invalid: empty key is not allowed
|
||||||
|
9: "value", // ❌️ How did you even serialize this??
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Values
|
||||||
|
|
||||||
|
### Numbers
|
||||||
|
|
||||||
|
Numbers in JSON must be represented as decimal numbers. They can be integers or floating-point numbers, but must follow the following rules:
|
||||||
|
|
||||||
|
```json {{ "title": "Must not use scientific notation" }}
|
||||||
|
{
|
||||||
|
"value": 1e3, // ❌️ Invalid
|
||||||
|
"value2": 1000 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not have leading zeros" }}
|
||||||
|
{
|
||||||
|
"value": 01, // ❌️ Invalid
|
||||||
|
"value2": 1 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not have trailing decimal points" }}
|
||||||
|
{
|
||||||
|
"value": 1., // ❌️ Invalid
|
||||||
|
"value2": 1 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not have trailing zeros after the decimal point" }}
|
||||||
|
{
|
||||||
|
"value": 1.00, // ❌️ Invalid
|
||||||
|
"value2": 1.0, // ❌️ Invalid
|
||||||
|
"value3": 1 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not have leading decimal points" }}
|
||||||
|
{
|
||||||
|
"value": .1, // ❌️ Invalid
|
||||||
|
"value2": 0.1 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not use numbers outside the range -2⁵³ to 2⁵³ (included)." }}
|
||||||
|
{
|
||||||
|
"value": 18014398509481984, // ❌️ Invalid
|
||||||
|
"value2": -20873930 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not use the negative zero" }}
|
||||||
|
{
|
||||||
|
"value": -0, // ❌️ Invalid
|
||||||
|
"value2": 0 // ✅ Valid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not use Infinity or NaN" }}
|
||||||
|
{
|
||||||
|
"value": Infinity, // ❌️ Invalid
|
||||||
|
"value2": NaN // ❌️ Invalid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```json {{ "title": "Must not use hexadecimal or octal notation" }}
|
||||||
|
{
|
||||||
|
"value": 0x1A, // ❌️ Invalid
|
||||||
|
"value2": 0o17 // ❌️ Invalid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Optional Fields
|
||||||
|
|
||||||
|
Fields that are not marked as **required** may be set to `null`, or simply omitted.
|
||||||
|
|
@ -6,8 +6,8 @@ import type { Section } from "../components/SectionProvider";
|
||||||
import { Providers } from "./providers";
|
import { Providers } from "./providers";
|
||||||
|
|
||||||
import "@/styles/tailwind.css";
|
import "@/styles/tailwind.css";
|
||||||
import logo from "@/images/branding/logo.webp";
|
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
|
import logo from "@/images/branding/logo.webp";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: {
|
title: {
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ Versia Links are a way to reference entities in the Versia Protocol, in a way th
|
||||||
- `share/:instance/:id`: Share a note.
|
- `share/:instance/:id`: Share a note.
|
||||||
- `compose/:text`: Compose a new note. Text passed at the end will be added in the note compose field. Used for "Share with Versia" buttons on websites.
|
- `compose/:text`: Compose a new note. Text passed at the end will be added in the note compose field. Used for "Share with Versia" buttons on websites.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="instance" type="string" required={false}>
|
<Property name="instance" type="Domain" typeLink="/api/basics#domain" required={false}>
|
||||||
Instance hosting the referenced content, including the port if it is not the default (i.e. `443` for HTTPS).
|
Instance hosting the referenced content.
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -57,7 +57,7 @@ Versia Links are a way to reference entities in the Versia Protocol, in a way th
|
||||||
|
|
||||||
Versia clients **should** register themselves as handlers for the `web+versia://` scheme in the user's operating system. When a Versia Link is clicked, the client should open the entity in the client's interface.
|
Versia clients **should** register themselves as handlers for the `web+versia://` scheme in the user's operating system. When a Versia Link is clicked, the client should open the entity in the client's interface.
|
||||||
|
|
||||||
The default client ("frontend") on a Versia instance **should** also display Versia links for logged-out users on:
|
The default web client ("frontend") on a Versia instance **should** also display Versia links for logged-out users on:
|
||||||
- Profiles
|
- Profiles
|
||||||
- Notes
|
- Notes
|
||||||
- Groups
|
- Groups
|
||||||
|
|
|
||||||
35
app/page.tsx
35
app/page.tsx
|
|
@ -1,16 +1,16 @@
|
||||||
import { Guide } from "@/components/Guides";
|
|
||||||
import { Resource, type ResourceType } from "@/components/Resources";
|
|
||||||
import { TeamMember } from "@/components/Team";
|
|
||||||
import { wrapper } from "@/components/mdx";
|
|
||||||
import fastlyLogo from "@/images/logos/fastly.svg";
|
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
|
import { Guide } from "@/components/Guides";
|
||||||
|
import { wrapper } from "@/components/mdx";
|
||||||
|
import { Resource, type ResourceType } from "@/components/Resources";
|
||||||
|
import { TeamMember } from "@/components/Team";
|
||||||
|
import fastlyLogo from "@/images/logos/fastly.svg";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Versia Documentation",
|
title: "Versia Documentation",
|
||||||
description:
|
description:
|
||||||
"Introduction to the Versia Protocol, a communication medium for federated applications, leveraging the HTTP stack.",
|
"Introduction to the Versia Protocol, a communication medium for federated applications, using the HTTP stack.",
|
||||||
};
|
};
|
||||||
|
|
||||||
const Page: FC = () => {
|
const Page: FC = () => {
|
||||||
|
|
@ -225,29 +225,6 @@ const Page: FC = () => {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<TeamMember
|
|
||||||
name="Anna"
|
|
||||||
username="devminer"
|
|
||||||
avatarUrl="https://i.imgur.com/grHNY7G.png"
|
|
||||||
bio="Golang SDK, spec design."
|
|
||||||
socials={[
|
|
||||||
{
|
|
||||||
name: "Website",
|
|
||||||
icon: "bx:link",
|
|
||||||
url: "https://devminer.xyz/",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "GitHub",
|
|
||||||
icon: "bxl:github",
|
|
||||||
url: "https://github.com/TheDevMinerTV",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Matrix",
|
|
||||||
icon: "simple-icons:matrix",
|
|
||||||
url: "https://matrix.to/#/@devminer:devminer.xyz",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 id="team">Thanks</h2>
|
<h2 id="team">Thanks</h2>
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,6 @@ Developer-facing features (e.g. shared inboxes, reply backfilling, etc.) should
|
||||||
|
|
||||||
## Branching
|
## Branching
|
||||||
|
|
||||||
There should be **as little branching as possible**. This is reminiscent of the "one canonical way" principle: if there are multiple ways to do something, or a thing can be processed multiple ways, it should be simplified.
|
There should be **as little branching logic as possible**. This is reminiscent of the "one canonical way" principle: if there are multiple ways to do something, or a thing can be processed multiple ways, it should be simplified.
|
||||||
|
|
||||||
If there is a need for branching, nesting should be avoided: branches should be as flat as possible.
|
If there is a need for branching, nesting should be avoided: logic branches should be as flat as possible.
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { uwuifyDocument } from "@/lib/uwuify";
|
|
||||||
import { ThemeProvider, useTheme } from "next-themes";
|
import { ThemeProvider, useTheme } from "next-themes";
|
||||||
import { type ReactNode, useEffect } from "react";
|
import { type ReactNode, useEffect } from "react";
|
||||||
|
import { uwuifyDocument } from "@/lib/uwuify";
|
||||||
|
|
||||||
function ThemeWatcher() {
|
function ThemeWatcher() {
|
||||||
const { resolvedTheme, setTheme } = useTheme();
|
const { resolvedTheme, setTheme } = useTheme();
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ export const metadata = {
|
||||||
|
|
||||||
Versia's security model is designed to ensure the integrity and authenticity of data, with a simple but robust system of cryptographic signatures. This system is designed to be easy to implement and understand, while still providing strong guarantees.
|
Versia's security model is designed to ensure the integrity and authenticity of data, with a simple but robust system of cryptographic signatures. This system is designed to be easy to implement and understand, while still providing strong guarantees.
|
||||||
|
|
||||||
However, **it is of critical importance to understand the limitations of this system**. Versia's security model is designed to prevent impersonation attacks and data tampering, but it does not provide confidentiality. This means that while you can trust the data you receive, you should not assume that it is private.
|
However, **it is very important to understand the limitations of this system**. Versia's security model is designed to prevent impersonation attacks and data tampering, but it does not provide confidentiality. This means that while you can trust the data you receive, you should not assume that it is private.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
There are three main kinds of security that are commonly discussed in the context of cryptography:
|
There are three main kinds of security that are commonly discussed in the context of cryptography:
|
||||||
|
|
@ -47,13 +47,12 @@ There are several reasons why confidentiality is not covered as part of this spe
|
||||||
- Email
|
- Email
|
||||||
- The Web
|
- The Web
|
||||||
- Twitter
|
- Twitter
|
||||||
- TCP
|
|
||||||
|
|
||||||
Confidentiality is **several orders of magnitude more complex** than integrity and authenticity. It requires a completely different set of tools and assumptions, which are not feasible to reliably implement in a complex federated system (if you've ever seen `** Unable to decrypt: The sender's device has not sent us the keys for this message. **`, you know what we're talking about).
|
Confidentiality is **several orders of magnitude more complex** than integrity and authenticity. It requires a completely different set of tools and assumptions, which are not feasible to reliably implement in a complex federated system (if you've ever seen `** Unable to decrypt: The sender's device has not sent us the keys for this message. **`, you know what we're talking about).
|
||||||
|
|
||||||
Furthermore, adding more complex cryptography would make the specification significantly more complex, which would likely make it harder to implement for smaller developers with less resources.
|
Furthermore, adding more complex cryptography would make the specification significantly more complex, which would likely make it harder to implement for smaller developers with less resources.
|
||||||
|
|
||||||
Additionally, we would like to avoid re-creating what would essentially be a shoddier version of much stronger centralized platforms like [Signal](https://signal.org/). We feel, just like many others before us, that it is better to leave the confidentiality to the experts.
|
Additionally, we would like to avoid re-creating what would essentially be a shoddier version of much stronger centralized platforms like [Signal](https://signal.org/). We feel that it is better to leave the confidentiality to the experts.
|
||||||
|
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,15 @@ Versia uses cryptographic signatures to ensure the integrity and authenticity of
|
||||||
|
|
||||||
A signature consists of a series of headers in an HTTP request. The following headers are used:
|
A signature consists of a series of headers in an HTTP request. The following headers are used:
|
||||||
- **`Versia-Signature`**: The signature itself, encoded in base64.
|
- **`Versia-Signature`**: The signature itself, encoded in base64.
|
||||||
- **`Versia-Signed-By`**: URI of the user who signed the request, [or the string `instance $1`, to represent the instance, where `$1` is the instance's host](/entities/instance-metadata#the-null-author).
|
- **`Versia-Signed-By`**: [Domain](/api/basics#domain) of the instance authoring the request.
|
||||||
- **`Versia-Signed-At`**: The current Unix timestamp, in seconds (no milliseconds), when the request was signed. Timezone must be UTC, like all Unix timestamps.
|
- **`Versia-Signed-At`**: The current Unix timestamp, in seconds (integer), when the request was signed. Timezone must be UTC, like all Unix timestamps.
|
||||||
|
|
||||||
Signatures are **required on ALL federation traffic**. If a request does not have a signature, it **MUST** be rejected. Specifically, signatures must be put on:
|
Signatures must be put on:
|
||||||
- **All POST requests**.
|
- **All `POST` requests**.
|
||||||
- **All GET requests**.
|
- **All `GET` requests**.
|
||||||
- **All responses to GET requests** (for example, when fetching a user's profile). In this case, the HTTP method used in the signature string must be `GET`.
|
- **All responses to `GET` requests** (for example, when fetching a user's profile).
|
||||||
|
|
||||||
If a signature fails, is missing or is invalid, the instance **MUST** return a `401 Unauthorized` HTTP status code. If the signature timestamp is too old or too new (more than 5 minutes from the current time), the instance **MUST** return a `422 Unprocessable Entity` status code.
|
If a signature fails, is missing or is invalid, the instance **must** return a `401 Unauthorized` HTTP status code. If the signature is too old or too new (more than 5 minutes from the current time), the instance **must** return a `422 Unprocessable Entity` status code.
|
||||||
|
|
||||||
### Calculating the Signature
|
### Calculating the Signature
|
||||||
|
|
||||||
|
|
@ -36,12 +36,12 @@ $0 $1 $2 $3
|
||||||
```
|
```
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
- `$0` is the HTTP method (e.g. `GET`, `POST`) in lowercase.
|
- `$0` is the HTTP method (e.g. `GET`, `POST`) in lowercase. If signing a *response*, use the method of the original request.
|
||||||
- `$1` is the path of the request, in standard URI format (don't forget to URL-encode it).
|
- `$1` is the request pathname, URL-encoded.
|
||||||
- `$2` is the Unix timestamp when the request was signed, in UTC seconds.
|
- `$2` is the Unix timestamp when the request was signed, in UTC seconds (integer).
|
||||||
- `$3` is the SHA-256 hash of the request body, encoded in base64. (if it's a `GET` request, this should be the hash of an empty string)
|
- `$3` is the SHA-256 hash of the request body, encoded in base64. (if it's a `GET` request, this should be the hash of an empty string)
|
||||||
|
|
||||||
Sign this string using the user's private key. The resulting signature should be encoded in base64.
|
Sign this string using the instance's private key with the [Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519) algorithm. The resulting bytes **must** be encoded in base64.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
|
|
@ -50,25 +50,25 @@ post /notes 1729243417 n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=
|
||||||
|
|
||||||
### Verifying the Signature
|
### Verifying the Signature
|
||||||
|
|
||||||
To verify a signature, the instance must:
|
To verify a signature, the verifying instance must:
|
||||||
- Recreate the string as described above.
|
- Recreate the string as described above.
|
||||||
- Extract the signature provided in the `Versia-Signature` header.
|
- Extract the signature provided in the `Versia-Signature` header.
|
||||||
- Check that the `Versia-Signed-At` timestamp is within 5 minutes of the current time.
|
- Check that the `Versia-Signed-At` timestamp is within 5 minutes of the current time.
|
||||||
- Decode the signature from base64.
|
- Decode the signature from base64 to the raw bytes.
|
||||||
- Perform a signature verification using the user's public key.
|
- Perform a signature verification using the sender instance's public key.
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
The following example is written in TypeScript using the WebCrypto API.
|
The following example is written in TypeScript using the WebCrypto API.
|
||||||
|
|
||||||
`@bob`, from `bob.com`, wants to sign a request to `alice.com`. The request is a `POST` to `/notes`, with the following body:
|
`@bob`, from `bob.com`, wants to sign a request to `alice.com`. The request is a `POST` to `/.versia/v0.6/inbox`, with the following body:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"content": "Hello, world!"
|
"content": "Hello, world!"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Bob can be found at `https://bob.com/users/bf44e6ad-7c0a-4560-9938-cf3fd4066511`. His ed25519 private key, encoded in Base64 PKCS8, is `MC4CAQAwBQYDK2VwBCIEILrNXhbWxC/MhKQDsJOAAF1FH/R+Am5G/eZKnqNum5ro`.
|
Bob can be found at `https://bob.com/.versia/v0.6/entities/User/bf44e6ad-7c0a-4560-9938-cf3fd4066511`. His instance's ed25519 private key, encoded in Base64 [PKCS8](https://en.wikipedia.org/wiki/PKCS_8), is `MC4CAQAwBQYDK2VwBCIEILrNXhbWxC/MhKQDsJOAAF1FH/R+Am5G/eZKnqNum5ro`.
|
||||||
|
|
||||||
Here's how Bob would sign the request:
|
Here's how Bob would sign the request:
|
||||||
```typescript
|
```typescript
|
||||||
|
|
@ -97,7 +97,7 @@ const digest = await crypto.subtle.digest(
|
||||||
);
|
);
|
||||||
|
|
||||||
const stringToSign =
|
const stringToSign =
|
||||||
`post /notes ${timestamp} ${Buffer.from(digest).toString("base64")}`;
|
`post /.versia/v0.6/inbox ${timestamp} ${Buffer.from(digest).toString("base64")}`;
|
||||||
|
|
||||||
const signature = await crypto.subtle.sign(
|
const signature = await crypto.subtle.sign(
|
||||||
"Ed25519",
|
"Ed25519",
|
||||||
|
|
@ -113,25 +113,25 @@ To send the request, Bob would use the following code:
|
||||||
```typescript
|
```typescript
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
|
|
||||||
headers.set("Versia-Signed-By", "https://bob.com/users/bf44e6ad-7c0a-4560-9938-cf3fd4066511");
|
headers.set("Versia-Signed-By", "bob.com");
|
||||||
headers.set("Versia-Signed-At", timestamp);
|
headers.set("Versia-Signed-At", timestamp);
|
||||||
headers.set("Versia-Signature", base64Signature);
|
headers.set("Versia-Signature", base64Signature);
|
||||||
headers.set("Content-Type", "application/json");
|
headers.set("Content-Type", "application/vnd.versia+json; charset=utf-8");
|
||||||
|
|
||||||
const response = await fetch("https://alice.com/notes", {
|
const response = await fetch("https://alice.com/.versia/v0.6/inbox", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers,
|
headers,
|
||||||
body: content,
|
body: content,
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
On Alice's side, she would verify the signature using Bob's public key. Here, we assume that Alice has Bob's public key stored in a variable called `publicKey` (during real federation, this would be fetched from Bob's profile).
|
On Alice's side, she would verify the signature using Bob's instance's public key. Here, we assume that Alice has Bob's instance's public key stored in a variable called `publicKey` (during real federation, this would be fetched from the instance's [metadata endpoint](/api/endpoints#instance-metadata)).
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
const method = request.method.toLowerCase();
|
const method = request.method.toLowerCase();
|
||||||
const path = new URL(request.url).pathname;
|
const path = new URL(request.url).pathname;
|
||||||
const signature = request.headers.get("Versia-Signature");
|
const signature = request.headers.get("Versia-Signature");
|
||||||
const timestamp = request.headers.get("Versia-Signed-At");
|
const timestamp = Number(request.headers.get("Versia-Signed-At")) * 1000; // Convert to milliseconds
|
||||||
|
|
||||||
// Check if timestamp is within 5 minutes of the current time
|
// Check if timestamp is within 5 minutes of the current time
|
||||||
if (Math.abs(Date.now() - timestamp) > 300_000) {
|
if (Math.abs(Date.now() - timestamp) > 300_000) {
|
||||||
|
|
@ -160,12 +160,12 @@ if (!isVerified) {
|
||||||
|
|
||||||
## Exporting the Public Key
|
## Exporting the Public Key
|
||||||
|
|
||||||
Public keys are always encoded using `base64` and must be in SPKI format. You will need to look up the appropriate method for your cryptographic library to convert the key to this format.
|
Public keys are always encoded using `base64` and must be in [SPKI](https://en.wikipedia.org/wiki/Simple_public-key_infrastructure) format. You will need to look up the appropriate method for your cryptographic library to convert the key to this format.
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
This is **not** the same as the key's raw bytes.
|
This is **not** merely the key's raw bytes encoded as base64. You must export the key in [SPKI](https://en.wikipedia.org/wiki/Simple_public-key_infrastructure) format, *then* encode it as base64.
|
||||||
|
|
||||||
This is also not related to the commonly used "PEM" format.
|
This is also not the commonly used "PEM" format.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
```typescript {{ title: "Example using TypeScript and the WebCrypto API" }}
|
```typescript {{ title: "Example using TypeScript and the WebCrypto API" }}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ export const metadata = {
|
||||||
|
|
||||||
Collections are a way to represent paginated groups of entities. They are used everywhere lists of entities can be found, such as a user's outbox. {{ className: 'lead' }}
|
Collections are a way to represent paginated groups of entities. They are used everywhere lists of entities can be found, such as a user's outbox. {{ className: 'lead' }}
|
||||||
|
|
||||||
Pages should be limited to a reasonable number of entities, such as 20 or 80.
|
|
||||||
|
|
||||||
<Note>
|
<Note>
|
||||||
As Collections are independent and not part of a larger entity (like [ContentFormat](/structures/content-format)), they should have a valid [Signature](/signatures).
|
As Collections are independent and not part of a larger entity (like [ContentFormat](/structures/content-format)), they should have a valid [Signature](/signatures).
|
||||||
</Note>
|
</Note>
|
||||||
|
|
@ -18,31 +16,12 @@ Pages should be limited to a reasonable number of entities, such as 20 or 80.
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="Collection">
|
<Properties name="Collection">
|
||||||
<Property name="author" type="URI | null" required={true} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={false} typeLink="/types#reference">
|
||||||
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).
|
[Reference](/types#reference) to the author of the collection. Usually the user who "owns" the collection.
|
||||||
</Property>
|
|
||||||
<Property name="first" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI to the first page of the collection. Query parameters are allowed.
|
|
||||||
</Property>
|
|
||||||
<Property name="last" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI to the last page of the collection. Query parameters are allowed.
|
|
||||||
|
|
||||||
If the collection only has one page, this should be the same as `first`.
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="total" type="number" required={true} numberType="u64">
|
<Property name="total" type="number" required={true} numberType="u64">
|
||||||
Total number of entities in the collection, across all pages.
|
Total number of entities in the collection, across all pages.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="next" type="URI" required={false} typeLink="/types#uri">
|
|
||||||
URI to the next page of the collection. Query parameters are allowed.
|
|
||||||
|
|
||||||
If there is no next page, this should be `null`.
|
|
||||||
</Property>
|
|
||||||
<Property name="previous" type="URI" required={false} typeLink="/types#uri">
|
|
||||||
URI to the previous page of the collection. Query parameters are allowed.
|
|
||||||
|
|
||||||
|
|
||||||
If there is no previous page, this should be `null`.
|
|
||||||
</Property>
|
|
||||||
<Property name="items" type="Entity[]" required={true}>
|
<Property name="items" type="Entity[]" required={true}>
|
||||||
Collection contents. Must be an array of entities.
|
Collection contents. Must be an array of entities.
|
||||||
</Property>
|
</Property>
|
||||||
|
|
@ -54,17 +33,14 @@ Pages should be limited to a reasonable number of entities, such as 20 or 80.
|
||||||
```jsonc {{ 'title': 'Example Collection' }}
|
```jsonc {{ 'title': 'Example Collection' }}
|
||||||
{
|
{
|
||||||
"author": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771",
|
"author": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771",
|
||||||
"first": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/outbox?page=1",
|
|
||||||
"last": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/outbox?page=3",
|
|
||||||
"total": 46,
|
"total": 46,
|
||||||
"next": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/outbox?page=2",
|
|
||||||
"previous": null,
|
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "456df8ed-daf1-4062-abab-491071c7b8dd",
|
"id": "456df8ed-daf1-4062-abab-491071c7b8dd",
|
||||||
"type": "Note",
|
"type": "Note",
|
||||||
"uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd",
|
"uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd",
|
||||||
"created_at": "2024-04-09T01:38:51.743Z",
|
"created_at": "2024-04-09T01:38:51.743Z",
|
||||||
|
...
|
||||||
"collections": {
|
"collections": {
|
||||||
"replies": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/replies",
|
"replies": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/replies",
|
||||||
"quotes": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/quotes"
|
"quotes": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd/quotes"
|
||||||
|
|
@ -89,32 +65,14 @@ URI Collections are identical to regular collections, but they contain only URIs
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
<Properties name="URICollection">
|
<Properties name="URICollection">
|
||||||
<Property name="author" type="URI | null" required={true} typeLink="/types#uri">
|
<Property name="author" type="Reference" required={false} typeLink="/types#reference">
|
||||||
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).
|
[Reference](/types#reference) to the author of the collection. Usually the user who owns the collection.
|
||||||
</Property>
|
|
||||||
<Property name="first" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI to the first page of the collection. Query parameters are allowed.
|
|
||||||
</Property>
|
|
||||||
<Property name="last" type="URI" required={true} typeLink="/types#uri">
|
|
||||||
URI to the last page of the collection. Query parameters are allowed.
|
|
||||||
|
|
||||||
If the collection only has one page, this should be the same as `first`.
|
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="total" type="number" required={true} numberType="u64">
|
<Property name="total" type="number" required={true} numberType="u64">
|
||||||
Total number of entities in the collection, across all pages.
|
Total number of entities in the collection, across all pages.
|
||||||
</Property>
|
</Property>
|
||||||
<Property name="next" type="URI" required={false} typeLink="/types#uri">
|
<Property name="items" type="Reference[]" required={true}>
|
||||||
URI to the next page of the collection. Query parameters are allowed.
|
Collection contents. Must be an array of [References](/types#reference).
|
||||||
|
|
||||||
If there is no next page, this should be `null`.
|
|
||||||
</Property>
|
|
||||||
<Property name="previous" type="URI" required={false} typeLink="/types#uri">
|
|
||||||
URI to the previous page of the collection. Query parameters are allowed.
|
|
||||||
|
|
||||||
If there is no previous page, this should be `null`.
|
|
||||||
</Property>
|
|
||||||
<Property name="items" type="URI[]" required={true}>
|
|
||||||
Collection contents. Must be an array of URIs.
|
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
@ -123,15 +81,11 @@ URI Collections are identical to regular collections, but they contain only URIs
|
||||||
|
|
||||||
```jsonc {{ 'title': 'Example URI Collection' }}
|
```jsonc {{ 'title': 'Example URI Collection' }}
|
||||||
{
|
{
|
||||||
"author": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771",
|
"author": "018ec082-0ae1-761c-b2c5-22275a611771",
|
||||||
"first": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/followers?page=1",
|
|
||||||
"last": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/followers?page=3",
|
|
||||||
"total": 46,
|
"total": 46,
|
||||||
"next": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/followers?page=2",
|
|
||||||
"previous": null,
|
|
||||||
"items": [
|
"items": [
|
||||||
"https://versia.social/users/f8b0d4b4-d354-4798-bbc5-c2ba8acabfe3",
|
"versia.social:f8b0d4b4-d354-4798-bbc5-c2ba8acabfe3",
|
||||||
"https://social.bob.com/u/2B27E62snga763"
|
"social.bob.com:2B27E62snga763"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,47 @@
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type Hostname = string;
|
||||||
|
type Id = Entity["id"];
|
||||||
|
|
||||||
|
type Reference = `${Hostname}:${Id}` | `${Id}`;
|
||||||
|
```
|
||||||
|
|
||||||
|
A **reference** is a way to refer to any entity within the Versia network. It is a string composed of the following parts:
|
||||||
|
|
||||||
|
- The entity's instance's hostname. Optional if that same instance is the creator of the entity.
|
||||||
|
- Punycode encoding is used for internationalized domain names (IDNs).
|
||||||
|
- Example: `example.com`, `example.com:3000`, `xn--ls8h.xn--ls8h`.
|
||||||
|
- A colon (`:`) separator, if the hostname is present.
|
||||||
|
- The entity's unique identifier. This is the `id` property of the entity.
|
||||||
|
|
||||||
|
<Warning>
|
||||||
|
If the hostname is an IPv6 address, it must be enclosed in square brackets.
|
||||||
|
|
||||||
|
For example: `[2001:db8::1]:3000`.
|
||||||
|
</Warning>
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
These two examples are equivalent if the instance is `example.com`:
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"type": "Follow",
|
||||||
|
"author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus]
|
||||||
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
|
"followee": "test.org:02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"type": "Follow",
|
||||||
|
"author": "example.com:6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus]
|
||||||
|
"created_at": "2021-01-01T00:00:00.000Z",
|
||||||
|
"followee": "test.org:02e1e3b2-cb1f-4e4a-b82e-98866bee5de7"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## RFC3339
|
## RFC3339
|
||||||
|
|
||||||
|
|
|
||||||
102
biome.json
102
biome.json
|
|
@ -1,30 +1,49 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
|
||||||
"organizeImports": {
|
"assist": { "actions": { "source": { "organizeImports": "on" } } },
|
||||||
"enabled": true
|
"css": {
|
||||||
|
"parser": {
|
||||||
|
"tailwindDirectives": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"linter": {
|
"linter": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"all": true,
|
|
||||||
"correctness": {
|
|
||||||
"noNodejsModules": "off",
|
|
||||||
"useImportExtensions": "off",
|
|
||||||
"noUnknownFunction": "off"
|
|
||||||
},
|
|
||||||
"complexity": {
|
|
||||||
"noExcessiveCognitiveComplexity": "off"
|
|
||||||
},
|
|
||||||
"suspicious": {
|
"suspicious": {
|
||||||
"noReactSpecificProps": "off"
|
"noConsole": "off",
|
||||||
|
"noExplicitAny": "off",
|
||||||
|
"noDuplicateElseIf": "error",
|
||||||
|
"noDocumentCookie": "off",
|
||||||
|
"noReactSpecificProps": "off",
|
||||||
|
"noUnknownAtRules": "off"
|
||||||
},
|
},
|
||||||
"performance": {
|
"performance": {
|
||||||
"useTopLevelRegex": "off"
|
"noBarrelFile": "off",
|
||||||
|
"noNamespaceImport": "off",
|
||||||
|
"useTopLevelRegex": "off",
|
||||||
|
"noImgElement": "off"
|
||||||
|
},
|
||||||
|
"correctness": {
|
||||||
|
"noUnknownFunction": "off",
|
||||||
|
"noUndeclaredVariables": "off",
|
||||||
|
"useHookAtTopLevel": "off",
|
||||||
|
"noUnusedVariables": "off",
|
||||||
|
"noUnusedImports": "off",
|
||||||
|
"noUndeclaredDependencies": "off",
|
||||||
|
"useImportExtensions": "off",
|
||||||
|
"useJsxKeyInIterable": "off",
|
||||||
|
"useUniqueElementIds": "off"
|
||||||
|
},
|
||||||
|
"a11y": {
|
||||||
|
"noStaticElementInteractions": "off"
|
||||||
|
},
|
||||||
|
"complexity": {
|
||||||
|
"noExcessiveCognitiveComplexity": "off",
|
||||||
|
"noImportantStyles": "off"
|
||||||
},
|
},
|
||||||
"style": {
|
"style": {
|
||||||
"noDefaultExport": "off",
|
"noDefaultExport": "off",
|
||||||
"noParameterProperties": "off",
|
"noParameterProperties": "off",
|
||||||
"noNamespaceImport": "off",
|
|
||||||
"useFilenamingConvention": "off",
|
"useFilenamingConvention": "off",
|
||||||
"useNamingConvention": {
|
"useNamingConvention": {
|
||||||
"level": "warn",
|
"level": "warn",
|
||||||
|
|
@ -54,28 +73,22 @@
|
||||||
"PascalCase",
|
"PascalCase",
|
||||||
"snake_case"
|
"snake_case"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"selector": {
|
|
||||||
"kind": "classMethod",
|
|
||||||
"scope": "any"
|
|
||||||
},
|
|
||||||
"formats": ["camelCase", "PascalCase"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"selector": {
|
|
||||||
"kind": "functionParameter",
|
|
||||||
"scope": "any"
|
|
||||||
},
|
|
||||||
"formats": ["snake_case", "camelCase"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"nursery": {
|
"noParameterAssign": "error",
|
||||||
"noDuplicateElseIf": "warn"
|
"useAsConstAssertion": "error",
|
||||||
}
|
"useDefaultParameterLast": "error",
|
||||||
|
"useEnumInitializers": "error",
|
||||||
|
"useSelfClosingElements": "error",
|
||||||
|
"useSingleVarDeclarator": "error",
|
||||||
|
"noUnusedTemplateLiteral": "error",
|
||||||
|
"useNumberNamespace": "error",
|
||||||
|
"noInferrableTypes": "error",
|
||||||
|
"noUselessElse": "error"
|
||||||
|
},
|
||||||
|
"nursery": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"formatter": {
|
"formatter": {
|
||||||
|
|
@ -83,10 +96,27 @@
|
||||||
"indentStyle": "space",
|
"indentStyle": "space",
|
||||||
"indentWidth": 4
|
"indentWidth": 4
|
||||||
},
|
},
|
||||||
"javascript": {
|
"overrides": [
|
||||||
"globals": ["Bun"]
|
{
|
||||||
|
"includes": ["**/*.vue"],
|
||||||
|
"linter": {
|
||||||
|
"rules": {
|
||||||
|
"correctness": {
|
||||||
|
"noUnusedImports": "off"
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"useImportType": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": true
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"ignore": ["node_modules", ".next", ".output", "out", "public/pl.js"]
|
"includes": ["**", "!public"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
492
bun.lock
492
bun.lock
|
|
@ -1,216 +1,228 @@
|
||||||
{
|
{
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@versia-pub/docs",
|
"name": "@versia-pub/docs",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/autocomplete-core": "^1.19.1",
|
"@algolia/autocomplete-core": "^1.19.4",
|
||||||
"@headlessui/react": "^2.2.3",
|
"@headlessui/react": "^2.2.9",
|
||||||
"@headlessui/tailwindcss": "^0.2.2",
|
"@headlessui/tailwindcss": "^0.2.2",
|
||||||
"@mdx-js/loader": "^3.1.0",
|
"@mdx-js/loader": "^3.1.0",
|
||||||
"@mdx-js/react": "^3.1.0",
|
"@mdx-js/react": "^3.1.0",
|
||||||
"@next/mdx": "^15.3.2",
|
"@next/mdx": "^15.4.10",
|
||||||
"@sindresorhus/slugify": "^2.2.1",
|
"@radix-ui/react-hover-card": "^1.1.15",
|
||||||
"@tailwindcss/postcss": "^4.1.6",
|
"@sindresorhus/slugify": "^3.0.0",
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/postcss": "^4.1.18",
|
||||||
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "^22.15.18",
|
"@types/node": "^25.0.3",
|
||||||
"@types/react": "^19.1.4",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@types/react-highlight-words": "^0.20.0",
|
"@types/react-highlight-words": "^0.20.1",
|
||||||
"acorn": "^8.14.1",
|
"acorn": "^8.15.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"flexsearch": "^0.8.166",
|
"flexsearch": "^0.8.212",
|
||||||
"framer-motion": "^12.11.3",
|
"framer-motion": "^12.23.26",
|
||||||
"mdast-util-to-string": "^4.0.0",
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"mdx-annotations": "^0.1.4",
|
"mdx-annotations": "^0.1.4",
|
||||||
"next": "^15.3.2",
|
"next": "15.4.10",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"react": "^19.1.0",
|
"qss": "^3.0.0",
|
||||||
"react-dom": "^19.1.0",
|
"react": "^19.2.3",
|
||||||
|
"react-dom": "^19.2.3",
|
||||||
"react-highlight-words": "^0.21.0",
|
"react-highlight-words": "^0.21.0",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-mdx": "^3.1.0",
|
"remark-mdx": "^3.1.1",
|
||||||
"shiki": "^3.4.1",
|
"shiki": "^3.20.0",
|
||||||
"simple-functional-loader": "^1.2.1",
|
"simple-functional-loader": "^1.2.1",
|
||||||
"tailwindcss": "^4.1.6",
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.9.3",
|
||||||
"unist-util-filter": "^5.0.1",
|
"unist-util-filter": "^5.0.1",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
"uwuifier": "^4.2.2",
|
"uwuifier": "^4.2.2",
|
||||||
"zustand": "^5.0.4",
|
"zustand": "^5.0.9",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.9.4",
|
"@biomejs/biome": "^2.3.10",
|
||||||
"@iconify-icon/react": "^3.0.0",
|
"@iconify-icon/react": "^3.0.3",
|
||||||
"@next/bundle-analyzer": "^15.3.2",
|
"@next/bundle-analyzer": "^15.5.4",
|
||||||
"@shikijs/transformers": "^3.4.1",
|
"@shikijs/transformers": "^3.20.0",
|
||||||
"sharp": "^0.34.1",
|
"sharp": "^0.34.5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
|
"@tailwindcss/oxide",
|
||||||
"sharp",
|
"sharp",
|
||||||
"@biomejs/biome",
|
"@biomejs/biome",
|
||||||
],
|
],
|
||||||
"packages": {
|
"packages": {
|
||||||
"@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.19.1", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.19.1", "@algolia/autocomplete-shared": "1.19.1" } }, "sha512-MeZZN1NSPgfp2zhiaCyAW02jOWMftCJ06qoeEVEQ8v+kMlXL15SUYBpQwj7Gd+nV46KHqDrW+g5EGqhCsX6zWg=="],
|
"@algolia/abtesting": ["@algolia/abtesting@1.12.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-Y+7e2uPe376OH5O73OB1+vR40ZhbV2kzGh/AR/dPCWguoBOp1IK0o+uZQLX+7i32RMMBEKl3pj6KVEav100Kvg=="],
|
||||||
|
|
||||||
"@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.19.1", "", { "dependencies": { "@algolia/autocomplete-shared": "1.19.1" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-TPVerIGKbfOwd69ZNrriI6voKRwwj6Vmy4tD12/3RCh8zdvDOdRvc7LxeKPtgwJzavZkfH7nK9pb+4E+PCdgdg=="],
|
"@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.19.4", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.19.4", "@algolia/autocomplete-shared": "1.19.4" } }, "sha512-yVwXLrfwQ3dAndY12j1pfa0oyC5hTDv+/dgwvVHj57dY3zN6PbAmcHdV5DOOdGJrCMXff+fsPr8G2Ik8zWOPTw=="],
|
||||||
|
|
||||||
"@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.19.1", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-/GcOv70emuVdSHBAERW7/r4czMzJROkgLOl45+ugyxK79RzSkXV2esY638qSo6mzC7EVwglSJ8BQ0kAVKVxMjA=="],
|
"@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.19.4", "", { "dependencies": { "@algolia/autocomplete-shared": "1.19.4" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-K6TQhTKxx0Es1ZbjlAQjgm/QLDOtKvw23MX0xmpvO7AwkmlmaEXo2PwHdVSs3Bquv28CkO2BYKks7jVSIdcXUg=="],
|
||||||
|
|
||||||
"@algolia/client-abtesting": ["@algolia/client-abtesting@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-WIMT2Kxy+FFWXWQxIU8QgbTioL+SGE24zhpj0kipG4uQbzXwONaWt7ffaYLjfge3gcGSgJVv+1VlahVckafluQ=="],
|
"@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.19.4", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-V7tYDgRXP0AqL4alwZBWNm1HPWjJvEU94Nr7Qa2cuPcIAbsTAj7M/F/+Pv/iwOWXl3N7tzVzNkOWm7sX6JT1SQ=="],
|
||||||
|
|
||||||
"@algolia/client-analytics": ["@algolia/client-analytics@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-4B9gChENsQA9kFmFlb+x3YhBz2Gx3vSsm81FHI1yJ3fn2zlxREHmfrjyqYoMunsU7BybT/o5Nb7ccCbm/vfseA=="],
|
"@algolia/client-abtesting": ["@algolia/client-abtesting@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-5SWfl0UGuKxMBYlU2Y9BnlIKKEyhFU5jHE9F9jAd8nbhxZNLk0y7fXE+AZeFtyK1lkVw6O4B/e6c3XIVVCkmqw=="],
|
||||||
|
|
||||||
"@algolia/client-common": ["@algolia/client-common@5.23.4", "", {}, "sha512-bsj0lwU2ytiWLtl7sPunr+oLe+0YJql9FozJln5BnIiqfKOaseSDdV42060vUy+D4373f2XBI009K/rm2IXYMA=="],
|
"@algolia/client-analytics": ["@algolia/client-analytics@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-496K6B1l/0Jvyp3MbW/YIgmm1a6nkTrKXBM7DoEy9YAOJ8GywGpa2UYjNCW1UrOTt+em1ECzDjRx7PIzTR9YvA=="],
|
||||||
|
|
||||||
"@algolia/client-insights": ["@algolia/client-insights@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-XSCtAYvJ/hnfDHfRVMbBH0dayR+2ofVZy3jf5qyifjguC6rwxDsSdQvXpT0QFVyG+h8UPGtDhMPoUIng4wIcZA=="],
|
"@algolia/client-common": ["@algolia/client-common@5.46.1", "", {}, "sha512-3u6AuZ1Kiss6V5JPuZfVIUYfPi8im06QBCgKqLg82GUBJ3SwhiTdSZFIEgz2mzFuitFdW1PQi3c/65zE/3FgIw=="],
|
||||||
|
|
||||||
"@algolia/client-personalization": ["@algolia/client-personalization@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-l/0QvqgRFFOf7BnKSJ3myd1WbDr86ftVaa3PQwlsNh7IpIHmvVcT83Bi5zlORozVGMwaKfyPZo6O48PZELsOeA=="],
|
"@algolia/client-insights": ["@algolia/client-insights@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-LwuWjdO35HHl1rxtdn48t920Xl26Dl0SMxjxjFeAK/OwK/pIVfYjOZl/f3Pnm7Kixze+6HjpByVxEaqhTuAFaw=="],
|
||||||
|
|
||||||
"@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-TB0htrDgVacVGtPDyENoM6VIeYqR+pMsDovW94dfi2JoaRxfqu/tYmLpvgWcOknP6wLbr8bA+G7t/NiGksNAwQ=="],
|
"@algolia/client-personalization": ["@algolia/client-personalization@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-6LvJAlfEsn9SVq63MYAFX2iUxztUK2Q7BVZtI1vN87lDiJ/tSVFKgKS/jBVO03A39ePxJQiFv6EKv7lmoGlWtQ=="],
|
||||||
|
|
||||||
"@algolia/client-search": ["@algolia/client-search@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-uBGo6KwUP6z+u6HZWRui8UJClS7fgUIAiYd1prUqCbkzDiCngTOzxaJbEvrdkK0hGCQtnPDiuNhC5MhtVNN4Eg=="],
|
"@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-9GLUCyGGo7YOXHcNqbzca82XYHJTbuiI6iT0FTGc0BrnV2N4OcrznUuVKic/duiLSun5gcy/G2Bciw5Sav9f9w=="],
|
||||||
|
|
||||||
"@algolia/ingestion": ["@algolia/ingestion@1.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-Si6rFuGnSeEUPU9QchYvbknvEIyCRK7nkeaPVQdZpABU7m4V/tsiWdHmjVodtx3h20VZivJdHeQO9XbHxBOcCw=="],
|
"@algolia/client-search": ["@algolia/client-search@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-NL76o/BoEgU4ObY5oBEC3o6KSPpuXsnSta00tAxTm1iKUWOGR34DQEKhUt8xMHhMKleUNPM/rLPFiIVtfsGU8w=="],
|
||||||
|
|
||||||
"@algolia/monitoring": ["@algolia/monitoring@1.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-EXGoVVTshraqPJgr5cMd1fq7Jm71Ew6MpGCEaxI5PErBpJAmKdtjRIzs6JOGKHRaWLi+jdbJPYc2y8RN4qcx5Q=="],
|
"@algolia/ingestion": ["@algolia/ingestion@1.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-52Nc8WKC1FFXsdlXlTMl1Re/pTAbd2DiJiNdYmgHiikZcfF96G+Opx4qKiLUG1q7zp9e+ahNwXF6ED0XChMywg=="],
|
||||||
|
|
||||||
"@algolia/recommend": ["@algolia/recommend@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-1t6glwKVCkjvBNlng2itTf8fwaLSqkL4JaMENgR3WTGR8mmW2akocUy/ZYSQcG4TcR7qu4zW2UMGAwLoWoflgQ=="],
|
"@algolia/monitoring": ["@algolia/monitoring@1.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-1x2/2Y/eqz6l3QcEZ8u/zMhSCpjlhePyizJd3sXrmg031HjayYT5+IxikjpqkdF7TU/deCTd/TFUcxLJ2ZHXiQ=="],
|
||||||
|
|
||||||
"@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4" } }, "sha512-UUuizcgc5+VSY8hqzDFVdJ3Wcto03lpbFRGPgW12pHTlUQHUTADtIpIhkLLOZRCjXmCVhtr97Z+eR6LcRYXa3Q=="],
|
"@algolia/recommend": ["@algolia/recommend@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-SSd3KlQuplxV3aRs5+Z09XilFesgpPjtCG7BGRxLTVje5hn9BLmhjO4W3gKw01INUt44Z1r0Fwx5uqnhAouunA=="],
|
||||||
|
|
||||||
"@algolia/requester-fetch": ["@algolia/requester-fetch@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4" } }, "sha512-UhDg6elsek6NnV5z4VG1qMwR6vbp+rTMBEnl/v4hUyXQazU+CNdYkl++cpdmLwGI/7nXc28xtZiL90Es3I7viQ=="],
|
"@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1" } }, "sha512-3GfCwudeW6/3caKSdmOP6RXZEL4F3GiemCaXEStkTt2Re8f7NcGYAAZnGlHsCzvhlNEuDzPYdYxh4UweY8l/2w=="],
|
||||||
|
|
||||||
"@algolia/requester-node-http": ["@algolia/requester-node-http@5.23.4", "", { "dependencies": { "@algolia/client-common": "5.23.4" } }, "sha512-jXGzGBRUS0oywQwnaCA6mMDJO7LoC3dYSLsyNfIqxDR4SNGLhtg3je0Y31lc24OA4nYyKAYgVLtjfrpcpsWShg=="],
|
"@algolia/requester-fetch": ["@algolia/requester-fetch@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1" } }, "sha512-JUAxYfmnLYTVtAOFxVvXJ4GDHIhMuaP7JGyZXa/nCk3P8RrN5FCNTdRyftSnxyzwSIAd8qH3CjdBS9WwxxqcHQ=="],
|
||||||
|
|
||||||
|
"@algolia/requester-node-http": ["@algolia/requester-node-http@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1" } }, "sha512-VwbhV1xvTGiek3d2pOS6vNBC4dtbNadyRT+i1niZpGhOJWz1XnfhxNboVbXPGAyMJYz7kDrolbDvEzIDT93uUA=="],
|
||||||
|
|
||||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
"@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
|
"@biomejs/biome": ["@biomejs/biome@2.3.10", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.10", "@biomejs/cli-darwin-x64": "2.3.10", "@biomejs/cli-linux-arm64": "2.3.10", "@biomejs/cli-linux-arm64-musl": "2.3.10", "@biomejs/cli-linux-x64": "2.3.10", "@biomejs/cli-linux-x64-musl": "2.3.10", "@biomejs/cli-win32-arm64": "2.3.10", "@biomejs/cli-win32-x64": "2.3.10" }, "bin": { "biome": "bin/biome" } }, "sha512-/uWSUd1MHX2fjqNLHNL6zLYWBbrJeG412/8H7ESuK8ewoRoMPUgHDebqKrPTx/5n6f17Xzqc9hdg3MEqA5hXnQ=="],
|
||||||
|
|
||||||
"@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.9.4", "@biomejs/cli-darwin-x64": "1.9.4", "@biomejs/cli-linux-arm64": "1.9.4", "@biomejs/cli-linux-arm64-musl": "1.9.4", "@biomejs/cli-linux-x64": "1.9.4", "@biomejs/cli-linux-x64-musl": "1.9.4", "@biomejs/cli-win32-arm64": "1.9.4", "@biomejs/cli-win32-x64": "1.9.4" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="],
|
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="],
|
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="],
|
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="],
|
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="],
|
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-wwAkWD1MR95u+J4LkWP74/vGz+tRrIQvr8kfMMJY8KOQ8+HMVleREOcPYsQX82S7uueco60L58Wc6M1I9WA9Dw=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="],
|
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="],
|
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="],
|
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.10", "", { "os": "win32", "cpu": "x64" }, "sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="],
|
|
||||||
|
|
||||||
"@discoveryjs/json-ext": ["@discoveryjs/json-ext@0.5.7", "", {}, "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="],
|
"@discoveryjs/json-ext": ["@discoveryjs/json-ext@0.5.7", "", {}, "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
|
||||||
|
|
||||||
"@floating-ui/core": ["@floating-ui/core@1.6.9", "", { "dependencies": { "@floating-ui/utils": "^0.2.9" } }, "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw=="],
|
"@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="],
|
||||||
|
|
||||||
"@floating-ui/dom": ["@floating-ui/dom@1.6.13", "", { "dependencies": { "@floating-ui/core": "^1.6.0", "@floating-ui/utils": "^0.2.9" } }, "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w=="],
|
"@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="],
|
||||||
|
|
||||||
"@floating-ui/react": ["@floating-ui/react@0.26.28", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw=="],
|
"@floating-ui/react": ["@floating-ui/react@0.26.28", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.2", "@floating-ui/utils": "^0.2.8", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw=="],
|
||||||
|
|
||||||
"@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.2", "", { "dependencies": { "@floating-ui/dom": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A=="],
|
"@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="],
|
||||||
|
|
||||||
"@floating-ui/utils": ["@floating-ui/utils@0.2.9", "", {}, "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg=="],
|
"@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="],
|
||||||
|
|
||||||
"@headlessui/react": ["@headlessui/react@2.2.3", "", { "dependencies": { "@floating-ui/react": "^0.26.16", "@react-aria/focus": "^3.20.2", "@react-aria/interactions": "^3.25.0", "@tanstack/react-virtual": "^3.13.6", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-hgOJGXPifPlOczIeSwX8OjLWRJ5XdYApZFf7DeCbCrO1PXHkPhNTRrA9ZwJsgAG7SON1i2JcvIreF/kbgtJeaQ=="],
|
"@headlessui/react": ["@headlessui/react@2.2.9", "", { "dependencies": { "@floating-ui/react": "^0.26.16", "@react-aria/focus": "^3.20.2", "@react-aria/interactions": "^3.25.0", "@tanstack/react-virtual": "^3.13.9", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ=="],
|
||||||
|
|
||||||
"@headlessui/tailwindcss": ["@headlessui/tailwindcss@0.2.2", "", { "peerDependencies": { "tailwindcss": "^3.0 || ^4.0" } }, "sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw=="],
|
"@headlessui/tailwindcss": ["@headlessui/tailwindcss@0.2.2", "", { "peerDependencies": { "tailwindcss": "^3.0 || ^4.0" } }, "sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw=="],
|
||||||
|
|
||||||
"@iconify-icon/react": ["@iconify-icon/react@3.0.0", "", { "dependencies": { "iconify-icon": "^3.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-TOyzGUIfOFbmRQflMbf8k8bBGbeVAVCnvJ/rKz2SgBOV6VZLv7E9gzLvkPzfkZ2HZL+GbRtLNX/GJq2EI54OFQ=="],
|
"@iconify-icon/react": ["@iconify-icon/react@3.0.3", "", { "dependencies": { "iconify-icon": "^3.0.2" }, "peerDependencies": { "react": ">=18.0.0" } }, "sha512-i4N/J0+UZWQu5Ty9Z+SxsNsuNdY7w2TnSuI65Qw9UrWudvnRodKfTUMvyg0hvxSZolqAE1YJVZu1HqgfpgPX9w=="],
|
||||||
|
|
||||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.1.0" }, "os": "darwin", "cpu": "arm64" }, "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A=="],
|
"@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
|
||||||
|
|
||||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.1.0" }, "os": "darwin", "cpu": "x64" }, "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q=="],
|
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.1.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA=="],
|
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.1.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ=="],
|
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.1.0", "", { "os": "linux", "cpu": "arm" }, "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA=="],
|
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew=="],
|
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.1.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ=="],
|
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.1.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA=="],
|
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q=="],
|
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.1.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w=="],
|
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="],
|
||||||
|
|
||||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.1.0", "", { "os": "linux", "cpu": "x64" }, "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A=="],
|
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
|
||||||
|
|
||||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.1.0" }, "os": "linux", "cpu": "arm" }, "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA=="],
|
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
|
||||||
|
|
||||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.1.0" }, "os": "linux", "cpu": "arm64" }, "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ=="],
|
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
|
||||||
|
|
||||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.1.0" }, "os": "linux", "cpu": "s390x" }, "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA=="],
|
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
|
||||||
|
|
||||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.1.0" }, "os": "linux", "cpu": "x64" }, "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA=="],
|
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
|
||||||
|
|
||||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" }, "os": "linux", "cpu": "arm64" }, "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ=="],
|
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="],
|
||||||
|
|
||||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.1", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.1.0" }, "os": "linux", "cpu": "x64" }, "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg=="],
|
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="],
|
||||||
|
|
||||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.1", "", { "dependencies": { "@emnapi/runtime": "^1.4.0" }, "cpu": "none" }, "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg=="],
|
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="],
|
||||||
|
|
||||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw=="],
|
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
|
||||||
|
|
||||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.1", "", { "os": "win32", "cpu": "x64" }, "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw=="],
|
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
|
||||||
|
|
||||||
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
|
||||||
|
|
||||||
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="],
|
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
||||||
|
|
||||||
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||||
|
|
||||||
"@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="],
|
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="],
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="],
|
"@mdx-js/loader": ["@mdx-js/loader@3.1.1", "", { "dependencies": { "@mdx-js/mdx": "^3.0.0", "source-map": "^0.7.0" }, "peerDependencies": { "webpack": ">=5" }, "optionalPeers": ["webpack"] }, "sha512-0TTacJyZ9mDmY+VefuthVshaNIyCGZHJG2fMnGaDttCt8HmjUF7SizlHJpaCDoGnN635nK1wpzfpx/Xx5S4WnQ=="],
|
||||||
|
|
||||||
"@mdx-js/loader": ["@mdx-js/loader@3.1.0", "", { "dependencies": { "@mdx-js/mdx": "^3.0.0", "source-map": "^0.7.0" }, "peerDependencies": { "webpack": ">=5" }, "optionalPeers": ["webpack"] }, "sha512-xU/lwKdOyfXtQGqn3VnJjlDrmKXEvMi1mgYxVmukEUtVycIz1nh7oQ40bKTd4cA7rLStqu0740pnhGYxGoqsCg=="],
|
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="],
|
||||||
|
|
||||||
"@mdx-js/mdx": ["@mdx-js/mdx@3.1.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw=="],
|
"@mdx-js/react": ["@mdx-js/react@3.1.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw=="],
|
||||||
|
|
||||||
"@mdx-js/react": ["@mdx-js/react@3.1.0", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ=="],
|
"@next/bundle-analyzer": ["@next/bundle-analyzer@15.5.9", "", { "dependencies": { "webpack-bundle-analyzer": "4.10.1" } }, "sha512-lT1EBpFyGVN9u8M43f2jE78DsCu0A5KPA5OkF5PdIHrKDo4oTJ4lUQKciA9T2u9gccSXIPQcZb5TYkHF4f8iiw=="],
|
||||||
|
|
||||||
"@next/bundle-analyzer": ["@next/bundle-analyzer@15.3.2", "", { "dependencies": { "webpack-bundle-analyzer": "4.10.1" } }, "sha512-zY5O1PNKNxWEjaFX8gKzm77z2oL0cnj+m5aiqNBgay9LPLCDO13Cf+FJONeNq/nJjeXptwHFT9EMmTecF9U4Iw=="],
|
"@next/env": ["@next/env@15.4.10", "", {}, "sha512-knhmoJ0Vv7VRf6pZEPSnciUG1S4bIhWx+qTYBW/AjxEtlzsiNORPk8sFDCEvqLfmKuey56UB9FL1UdHEV3uBrg=="],
|
||||||
|
|
||||||
"@next/env": ["@next/env@15.3.2", "", {}, "sha512-xURk++7P7qR9JG1jJtLzPzf0qEvqCN0A/T3DXf8IPMKo9/6FfjxtEffRJIIew/bIL4T3C2jLLqBor8B/zVlx6g=="],
|
"@next/mdx": ["@next/mdx@15.5.9", "", { "dependencies": { "source-map": "^0.7.0" }, "peerDependencies": { "@mdx-js/loader": ">=0.15.0", "@mdx-js/react": ">=0.15.0" }, "optionalPeers": ["@mdx-js/loader", "@mdx-js/react"] }, "sha512-qG9GUKUMpnyD5vU+wNGFNsVDxuSdmYDaCEsScPNPIiplzfNSS7VZk1G2yQ2tgXz6KjFncdaqJPuDehFqFy/gjQ=="],
|
||||||
|
|
||||||
"@next/mdx": ["@next/mdx@15.3.2", "", { "dependencies": { "source-map": "^0.7.0" }, "peerDependencies": { "@mdx-js/loader": ">=0.15.0", "@mdx-js/react": ">=0.15.0" }, "optionalPeers": ["@mdx-js/loader", "@mdx-js/react"] }, "sha512-D6lSSbVzn1EiPwrBKG5QzXClcgdqiNCL8a3/6oROinzgZnYSxbVmnfs0UrqygtGSOmgW7sdJJSEOy555DoAwvw=="],
|
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A=="],
|
||||||
|
|
||||||
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2DR6kY/OGcokbnCsjHpNeQblqCZ85/1j6njYSkzRdpLn5At7OkSdmk7WyAmB9G0k25+VgqVZ/u356OSoQZ3z0g=="],
|
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.4.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw=="],
|
||||||
|
|
||||||
"@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ro/fdqaZWL6k1S/5CLv1I0DaZfDVJkWNaUU3un8Lg6m0YENWlDulmIWzV96Iou2wEYyEsZq51mwV8+XQXqMp3w=="],
|
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.4.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-covwwtZYhlbRWK2HlYX9835qXum4xYZ3E2Mra1mdQ+0ICGoMiw1+nVAn4d9Bo7R3JqSmK1grMq/va+0cdh7bJA=="],
|
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.4.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A=="],
|
||||||
|
|
||||||
"@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-KQkMEillvlW5Qk5mtGA/3Yz0/tzpNlSw6/3/ttsV1lNtMuOHcGii3zVeXZyi4EJmmLDKYcTcByV2wVsOhDt/zg=="],
|
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.4.8", "", { "os": "linux", "cpu": "x64" }, "sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uRBo6THWei0chz+Y5j37qzx+BtoDRFIkDzZjlpCItBRXyMPIg079eIkOCl3aqr2tkxL4HFyJ4GHDes7W8HuAUg=="],
|
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.4.8", "", { "os": "linux", "cpu": "x64" }, "sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA=="],
|
||||||
|
|
||||||
"@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-+uxFlPuCNx/T9PdMClOqeE8USKzj8tVz37KflT3Kdbx/LOlZBRI2yxuIcmx1mPNK8DwSOMNCr4ureSet7eyC0w=="],
|
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.4.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw=="],
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.3.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-LLTKmaI5cfD8dVzh5Vt7+OMo+AIOClEdIU/TSKbXXT2iScUTSxOGoBhfuv+FU8R9MLmrkIL1e2fBMkEEjYAtPQ=="],
|
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.4.8", "", { "os": "win32", "cpu": "x64" }, "sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg=="],
|
||||||
|
|
||||||
"@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-aW5B8wOPioJ4mBdMDXkt5f3j8pUr9W8AnlX0Df35uRWNT1Y6RIybxjnSUe+PhM+M1bwgyY8PHLmXZC6zT1o5tA=="],
|
|
||||||
|
|
||||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||||
|
|
||||||
|
|
@ -220,83 +232,119 @@
|
||||||
|
|
||||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
||||||
|
|
||||||
"@react-aria/focus": ["@react-aria/focus@3.20.2", "", { "dependencies": { "@react-aria/interactions": "^3.25.0", "@react-aria/utils": "^3.28.2", "@react-types/shared": "^3.29.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-Q3rouk/rzoF/3TuH6FzoAIKrl+kzZi9LHmr8S5EqLAOyP9TXIKG34x2j42dZsAhrw7TbF9gA8tBKwnCNH4ZV+Q=="],
|
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
|
||||||
|
|
||||||
"@react-aria/interactions": ["@react-aria/interactions@3.25.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.8", "@react-aria/utils": "^3.28.2", "@react-stately/flags": "^3.1.1", "@react-types/shared": "^3.29.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-GgIsDLlO8rDU/nFn6DfsbP9rfnzhm8QFjZkB9K9+r+MTSCn7bMntiWQgMM+5O6BiA8d7C7x4zuN4bZtc0RBdXQ=="],
|
"@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
|
||||||
|
|
||||||
"@react-aria/ssr": ["@react-aria/ssr@3.9.8", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-lQDE/c9uTfBSDOjaZUJS8xP2jCKVk4zjQeIlCH90xaLhHDgbpCdns3xvFpJJujfj3nI4Ll9K7A+ONUBDCASOuw=="],
|
"@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
|
||||||
|
|
||||||
"@react-aria/utils": ["@react-aria/utils@3.28.2", "", { "dependencies": { "@react-aria/ssr": "^3.9.8", "@react-stately/flags": "^3.1.1", "@react-stately/utils": "^3.10.6", "@react-types/shared": "^3.29.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-J8CcLbvnQgiBn54eeEvQQbIOfBF3A1QizxMw9P4cl9MkeR03ug7RnjTIdJY/n2p7t59kLeAB3tqiczhcj+Oi5w=="],
|
"@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
|
||||||
|
|
||||||
"@react-stately/flags": ["@react-stately/flags@3.1.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-XPR5gi5LfrPdhxZzdIlJDz/B5cBf63l4q6/AzNqVWFKgd0QqY5LvWJftXkklaIUpKSJkIKQb8dphuZXDtkWNqg=="],
|
"@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
|
||||||
|
|
||||||
"@react-stately/utils": ["@react-stately/utils@3.10.6", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-O76ip4InfTTzAJrg8OaZxKU4vvjMDOpfA/PGNOytiXwBbkct2ZeZwaimJ8Bt9W1bj5VsZ81/o/tW4BacbdDOMA=="],
|
"@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg=="],
|
||||||
|
|
||||||
"@react-types/shared": ["@react-types/shared@3.29.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-IDQYu/AHgZimObzCFdNl1LpZvQW/xcfLt3v20sorl5qRucDVj4S9os98sVTZ4IRIBjmS+MkjqpR5E70xan7ooA=="],
|
"@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
|
||||||
|
|
||||||
"@shikijs/core": ["@shikijs/core@3.4.1", "", { "dependencies": { "@shikijs/types": "3.4.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-GCqSd3KXRTKX1sViP7fIyyyf6do2QVg+fTd4IT00ucYCVSKiSN8HbFbfyjGsoZePNKWcQqXe4U4rrz2IVldG5A=="],
|
"@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
|
||||||
|
|
||||||
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.4.1", "", { "dependencies": { "@shikijs/types": "3.4.1", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-oGvRqN3Bsk+cGzmCb/5Kt/LfD7uyA8vCUUawyqmLti/AYNV7++zIZFEW8JwW5PrpPNWWx9RcZ/chnYLedzlVIQ=="],
|
"@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
|
||||||
|
|
||||||
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.4.1", "", { "dependencies": { "@shikijs/types": "3.4.1", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-p8I5KWgEDUcXRif9JjJUZtNeqCyxZ8xcslecDJMigsqSZfokwqQIsH4aGpdjzmDf8LIWvT+C3TCxnJQVaPmCbQ=="],
|
"@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
|
||||||
|
|
||||||
"@shikijs/langs": ["@shikijs/langs@3.4.1", "", { "dependencies": { "@shikijs/types": "3.4.1" } }, "sha512-v5A5ApJYcrcPLHcwAi0bViUU+Unh67UaXU9gGX3qfr2z3AqlqSZbC00W/3J4+tfGJASzwrWDro2R1er6SsCL1Q=="],
|
"@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||||
|
|
||||||
"@shikijs/themes": ["@shikijs/themes@3.4.1", "", { "dependencies": { "@shikijs/types": "3.4.1" } }, "sha512-XOJgs55mVVMZtNVJx1NVmdcfXG9HIyZGh7qpCw/Ok5UMjWgkmb8z15TgcmF3ItvHItijiIMl9BLcNO/tFSGl1w=="],
|
"@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
|
||||||
|
|
||||||
"@shikijs/transformers": ["@shikijs/transformers@3.4.1", "", { "dependencies": { "@shikijs/core": "3.4.1", "@shikijs/types": "3.4.1" } }, "sha512-Z3lbVQXHiXLC0bjDuGqsF3AAvvv4lQMoAXqIINZiOBgsk6CrnPZy0E2A+QUqv/MUaqp5qtYGsKDUJWbFE+buXw=="],
|
"@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
|
||||||
|
|
||||||
"@shikijs/types": ["@shikijs/types@3.4.1", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-4flT+pToGqRBb0UhGqXTV7rCqUS3fhc8z3S2Djc3E5USKhXwadeKGFVNB2rKXfohlrEozNJMtMiZaN8lfdj/ZQ=="],
|
"@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
|
||||||
|
|
||||||
|
"@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
|
||||||
|
|
||||||
|
"@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
|
||||||
|
|
||||||
|
"@react-aria/focus": ["@react-aria/focus@3.21.3", "", { "dependencies": { "@react-aria/interactions": "^3.26.0", "@react-aria/utils": "^3.32.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-FsquWvjSCwC2/sBk4b+OqJyONETUIXQ2vM0YdPAuC+QFQh2DT6TIBo6dOZVSezlhudDla69xFBd6JvCFq1AbUw=="],
|
||||||
|
|
||||||
|
"@react-aria/interactions": ["@react-aria/interactions@3.26.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-aria/utils": "^3.32.0", "@react-stately/flags": "^3.1.2", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-AAEcHiltjfbmP1i9iaVw34Mb7kbkiHpYdqieWufldh4aplWgsF11YQZOfaCJW4QoR2ML4Zzoa9nfFwLXA52R7Q=="],
|
||||||
|
|
||||||
|
"@react-aria/ssr": ["@react-aria/ssr@3.9.10", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ=="],
|
||||||
|
|
||||||
|
"@react-aria/utils": ["@react-aria/utils@3.32.0", "", { "dependencies": { "@react-aria/ssr": "^3.9.10", "@react-stately/flags": "^3.1.2", "@react-stately/utils": "^3.11.0", "@react-types/shared": "^3.32.1", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-/7Rud06+HVBIlTwmwmJa2W8xVtgxgzm0+kLbuFooZRzKDON6hhozS1dOMR/YLMxyJOaYOTpImcP4vRR9gL1hEg=="],
|
||||||
|
|
||||||
|
"@react-stately/flags": ["@react-stately/flags@3.1.2", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg=="],
|
||||||
|
|
||||||
|
"@react-stately/utils": ["@react-stately/utils@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-8LZpYowJ9eZmmYLpudbo/eclIRnbhWIJZ994ncmlKlouNzKohtM8qTC6B1w1pwUbiwGdUoyzLuQbeaIor5Dvcw=="],
|
||||||
|
|
||||||
|
"@react-types/shared": ["@react-types/shared@3.32.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w=="],
|
||||||
|
|
||||||
|
"@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="],
|
||||||
|
|
||||||
|
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="],
|
||||||
|
|
||||||
|
"@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ=="],
|
||||||
|
|
||||||
|
"@shikijs/langs": ["@shikijs/langs@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA=="],
|
||||||
|
|
||||||
|
"@shikijs/themes": ["@shikijs/themes@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ=="],
|
||||||
|
|
||||||
|
"@shikijs/transformers": ["@shikijs/transformers@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0" } }, "sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g=="],
|
||||||
|
|
||||||
|
"@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="],
|
||||||
|
|
||||||
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
|
"@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
|
||||||
|
|
||||||
"@sindresorhus/slugify": ["@sindresorhus/slugify@2.2.1", "", { "dependencies": { "@sindresorhus/transliterate": "^1.0.0", "escape-string-regexp": "^5.0.0" } }, "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw=="],
|
"@sindresorhus/slugify": ["@sindresorhus/slugify@3.0.0", "", { "dependencies": { "@sindresorhus/transliterate": "^2.0.0", "escape-string-regexp": "^5.0.0" } }, "sha512-SCrKh1zS96q+CuH5GumHcyQEVPsM4Ve8oE0E6tw7AAhGq50K8ojbTUOQnX/j9Mhcv/AXiIsbCfquovyGOo5fGw=="],
|
||||||
|
|
||||||
"@sindresorhus/transliterate": ["@sindresorhus/transliterate@1.6.0", "", { "dependencies": { "escape-string-regexp": "^5.0.0" } }, "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ=="],
|
"@sindresorhus/transliterate": ["@sindresorhus/transliterate@2.2.0", "", {}, "sha512-aLtANYAx3qvFilasPhZke27+Cm7WawGGuGiOd2EAp0lg1NdWKfulslcql/Qi7lNQ9odkPjwRbwk9c4CYsTh+Rg=="],
|
||||||
|
|
||||||
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
|
|
||||||
|
|
||||||
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
|
"@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
|
||||||
|
|
||||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.6", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.29.2", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.6" } }, "sha512-ed6zQbgmKsjsVvodAS1q1Ld2BolEuxJOSyyNc+vhkjdmfNUDCmQnlXBfQkHrlzNmslxHsQU/bFmzcEbv4xXsLg=="],
|
"@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.6", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.6", "@tailwindcss/oxide-darwin-arm64": "4.1.6", "@tailwindcss/oxide-darwin-x64": "4.1.6", "@tailwindcss/oxide-freebsd-x64": "4.1.6", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.6", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.6", "@tailwindcss/oxide-linux-arm64-musl": "4.1.6", "@tailwindcss/oxide-linux-x64-gnu": "4.1.6", "@tailwindcss/oxide-linux-x64-musl": "4.1.6", "@tailwindcss/oxide-wasm32-wasi": "4.1.6", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.6", "@tailwindcss/oxide-win32-x64-msvc": "4.1.6" } }, "sha512-0bpEBQiGx+227fW4G0fLQ8vuvyy5rsB1YIYNapTq3aRsJ9taF3f5cCaovDjN5pUGKKzcpMrZst/mhNaKAPOHOA=="],
|
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.6", "", { "os": "android", "cpu": "arm64" }, "sha512-VHwwPiwXtdIvOvqT/0/FLH/pizTVu78FOnI9jQo64kSAikFSZT7K4pjyzoDpSMaveJTGyAKvDjuhxJxKfmvjiQ=="],
|
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-weINOCcqv1HVBIGptNrk7c6lWgSFFiQMcCpKM4tnVi5x8OY2v1FrV76jwLukfT6pL1hyajc06tyVmZFYXoxvhQ=="],
|
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-3FzekhHG0ww1zQjQ1lPoq0wPrAIVXAbUkWdWM8u5BnYFZgb9ja5ejBqyTgjpo5mfy0hFOoMnMuVDI+7CXhXZaQ=="],
|
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4m5F5lpkBZhVQJq53oe5XgJ+aFYWdrgkMwViHjRsES3KEu2m1udR21B1I77RUqie0ZYNscFzY1v9aDssMBZ/1w=="],
|
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.6", "", { "os": "linux", "cpu": "arm" }, "sha512-qU0rHnA9P/ZoaDKouU1oGPxPWzDKtIfX7eOGi5jOWJKdxieUJdVV+CxWZOpDWlYTd4N3sFQvcnVLJWJ1cLP5TA=="],
|
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-jXy3TSTrbfgyd3UxPQeXC3wm8DAgmigzar99Km9Sf6L2OFfn/k+u3VqmpgHQw5QNfCpPe43em6Q7V76Wx7ogIQ=="],
|
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-8kjivE5xW0qAQ9HX9reVFmZj3t+VmljDLVRJpVBEoTR+3bKMnvC7iLcoSGNIUJGOZy1mLVq7x/gerVg0T+IsYw=="],
|
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-A4spQhwnWVpjWDLXnOW9PSinO2PTKJQNRmL/aIl2U/O+RARls8doDfs6R41+DAXK0ccacvRyDpR46aVQJJCoCg=="],
|
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-YRee+6ZqdzgiQAHVSLfl3RYmqeeaWVCk796MhXhLQu2kJu2COHBkqlqsqKYx3p8Hmk5pGCQd2jTAoMWWFeyG2A=="],
|
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.6", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@emnapi/wasi-threads": "^1.0.2", "@napi-rs/wasm-runtime": "^0.2.9", "@tybys/wasm-util": "^0.9.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-qAp4ooTYrBQ5pk5jgg54/U1rCJ/9FLYOkkQ/nTE+bVMseMfB6O7J8zb19YTpWuu4UdfRf5zzOrNKfl6T64MNrQ=="],
|
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-nqpDWk0Xr8ELO/nfRUDjk1pc9wDJ3ObeDdNMHLaymc4PJBWj11gdPCWZFKSK2AVKjJQC7J2EfmSmf47GN7OuLg=="],
|
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-5k9xF33xkfKpo9wCvYcegQ21VwIBU1/qEbYlVukfEIyQbEA47uK8AAwS7NVjNE3vHzcmxMYwd0l6L4pPjjm1rQ=="],
|
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="],
|
||||||
|
|
||||||
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.6", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.6", "@tailwindcss/oxide": "4.1.6", "postcss": "^8.4.41", "tailwindcss": "4.1.6" } }, "sha512-ELq+gDMBuRXPJlpE3PEen+1MhnHAQQrh2zF0dI1NXOlEWfr2qWf2CQdr5jl9yANv8RErQaQ2l6nIFO9OSCVq/g=="],
|
"@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.18", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "postcss": "^8.4.41", "tailwindcss": "4.1.18" } }, "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g=="],
|
||||||
|
|
||||||
"@tailwindcss/typography": ["@tailwindcss/typography@0.5.16", "", { "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA=="],
|
"@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="],
|
||||||
|
|
||||||
"@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.6", "", { "dependencies": { "@tanstack/virtual-core": "3.13.6" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-WT7nWs8ximoQ0CDx/ngoFP7HbQF9Q2wQe4nh2NB+u2486eX3nZRE40P9g6ccCVq7ZfTSH5gFOuCoVH5DLNS/aA=="],
|
"@tanstack/react-virtual": ["@tanstack/react-virtual@3.13.13", "", { "dependencies": { "@tanstack/virtual-core": "3.13.13" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-4o6oPMDvQv+9gMi8rE6gWmsOjtUZUYIJHv7EB+GblyYdi8U6OqLl8rhHWIUZSL1dUU2dPwTdTgybCKf9EjIrQg=="],
|
||||||
|
|
||||||
"@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.6", "", {}, "sha512-cnQUeWnhNP8tJ4WsGcYiX24Gjkc9ALstLbHcBj1t3E7EimN6n6kHH+DPV4PpDnuw00NApQp+ViojMj1GRdwYQg=="],
|
"@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.13", "", {}, "sha512-uQFoSdKKf5S8k51W5t7b2qpfkyIbdHMzAn+AMQvHPxKUPeo1SsGaA4JRISQT87jm28b7z8OEqPcg1IOZagQHcA=="],
|
||||||
|
|
||||||
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
|
"@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="],
|
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||||
|
|
||||||
"@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
|
"@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
|
||||||
|
|
||||||
|
|
@ -308,25 +356,25 @@
|
||||||
|
|
||||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@22.15.18", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg=="],
|
"@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.1.4", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g=="],
|
"@types/react": ["@types/react@19.2.7", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.1.5", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg=="],
|
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
||||||
|
|
||||||
"@types/react-highlight-words": ["@types/react-highlight-words@0.20.0", "", { "dependencies": { "@types/react": "*" } }, "sha512-Qm512TiOakvtNzHJ2+TNVHnLn5cJ2wLQV0+LrhuispVth6dRf5b8ydjq3Kc0thpZ7bz4s6RnG6meboAXHWRK+Q=="],
|
"@types/react-highlight-words": ["@types/react-highlight-words@0.20.1", "", { "dependencies": { "@types/react": "*" } }, "sha512-EgF6RaoibBurIhxk3X3d5xL0uMqjD7KtShvZ8S+d7/o6xZ+mQ4rct1a2E49vWA9r63OzrHCIyghqvQHASb/ERw=="],
|
||||||
|
|
||||||
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
||||||
|
|
||||||
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
||||||
|
|
||||||
"acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="],
|
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
|
||||||
|
|
||||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||||
|
|
||||||
"acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
|
"acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
|
||||||
|
|
||||||
"algoliasearch": ["algoliasearch@5.23.4", "", { "dependencies": { "@algolia/client-abtesting": "5.23.4", "@algolia/client-analytics": "5.23.4", "@algolia/client-common": "5.23.4", "@algolia/client-insights": "5.23.4", "@algolia/client-personalization": "5.23.4", "@algolia/client-query-suggestions": "5.23.4", "@algolia/client-search": "5.23.4", "@algolia/ingestion": "1.23.4", "@algolia/monitoring": "1.23.4", "@algolia/recommend": "5.23.4", "@algolia/requester-browser-xhr": "5.23.4", "@algolia/requester-fetch": "5.23.4", "@algolia/requester-node-http": "5.23.4" } }, "sha512-QzAKFHl3fm53s44VHrTdEo0TkpL3XVUYQpnZy1r6/EHvMAyIg+O4hwprzlsNmcCHTNyVcF2S13DAUn7XhkC6qg=="],
|
"algoliasearch": ["algoliasearch@5.46.1", "", { "dependencies": { "@algolia/abtesting": "1.12.1", "@algolia/client-abtesting": "5.46.1", "@algolia/client-analytics": "5.46.1", "@algolia/client-common": "5.46.1", "@algolia/client-insights": "5.46.1", "@algolia/client-personalization": "5.46.1", "@algolia/client-query-suggestions": "5.46.1", "@algolia/client-search": "5.46.1", "@algolia/ingestion": "1.46.1", "@algolia/monitoring": "1.46.1", "@algolia/recommend": "5.46.1", "@algolia/requester-browser-xhr": "5.46.1", "@algolia/requester-fetch": "5.46.1", "@algolia/requester-node-http": "5.46.1" } }, "sha512-39ol8Ulqb3MntofkXHlrcXKyU8BU0PXvQrXPBIX6eXj/EO4VT7651mhGVORI2oF8ydya9nFzT3fYDoqme/KL6w=="],
|
||||||
|
|
||||||
"astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
|
"astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
|
||||||
|
|
||||||
|
|
@ -336,9 +384,7 @@
|
||||||
|
|
||||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||||
|
|
||||||
"busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001715", "", {}, "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw=="],
|
|
||||||
|
|
||||||
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
|
||||||
|
|
||||||
|
|
@ -350,39 +396,29 @@
|
||||||
|
|
||||||
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
|
"character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
|
||||||
|
|
||||||
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
|
||||||
|
|
||||||
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
||||||
|
|
||||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||||
|
|
||||||
"collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="],
|
"collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="],
|
||||||
|
|
||||||
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
|
|
||||||
|
|
||||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
|
||||||
|
|
||||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
|
||||||
|
|
||||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
|
||||||
|
|
||||||
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
||||||
|
|
||||||
"commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
"commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
||||||
|
|
||||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||||
|
|
||||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||||
|
|
||||||
"debounce": ["debounce@1.2.1", "", {}, "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="],
|
"debounce": ["debounce@1.2.1", "", {}, "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.0", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"decode-named-character-reference": ["decode-named-character-reference@1.1.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w=="],
|
"decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="],
|
||||||
|
|
||||||
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
|
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
|
||||||
|
|
||||||
|
|
@ -390,7 +426,7 @@
|
||||||
|
|
||||||
"emojis-list": ["emojis-list@3.0.0", "", {}, "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="],
|
"emojis-list": ["emojis-list@3.0.0", "", {}, "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="],
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.18.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg=="],
|
"enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="],
|
||||||
|
|
||||||
"esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="],
|
"esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="],
|
||||||
|
|
||||||
|
|
@ -420,9 +456,9 @@
|
||||||
|
|
||||||
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
|
||||||
|
|
||||||
"flexsearch": ["flexsearch@0.8.166", "", {}, "sha512-X3GY9OfQyP1tjyy18PbGeFoxLNWlAedqv1dH/ikLS/6OYCGehX7LjJcR5Zuo0WSNqyqwbbhec1CucCwR+Rgfig=="],
|
"flexsearch": ["flexsearch@0.8.212", "", {}, "sha512-wSyJr1GUWoOOIISRu+X2IXiOcVfg9qqBRyCPRUdLMIGJqPzMo+jMRlvE83t14v1j0dRMEaBbER/adQjp6Du2pw=="],
|
||||||
|
|
||||||
"framer-motion": ["framer-motion@12.11.3", "", { "dependencies": { "motion-dom": "^12.11.2", "motion-utils": "^12.9.4", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-ksUtDFBZtrbQFt4bEMFrFgo7camhmXcLeuylKQxEYSd9czkZ4tZmFROxWczWeu51WqC2m91ifpvgGCBLd0uviQ=="],
|
"framer-motion": ["framer-motion@12.23.26", "", { "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA=="],
|
||||||
|
|
||||||
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
|
|
@ -444,16 +480,14 @@
|
||||||
|
|
||||||
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
|
"html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
|
||||||
|
|
||||||
"iconify-icon": ["iconify-icon@3.0.0", "", { "dependencies": { "@iconify/types": "^2.0.0" } }, "sha512-yPcnpkn8HUEUckrxxJBOer3jbGv3bqozHsLMLBRxhk3As1X76BgV2mS2a1HTNOIagR8nUs30H3qAd9GLe8Mnlg=="],
|
"iconify-icon": ["iconify-icon@3.0.2", "", { "dependencies": { "@iconify/types": "^2.0.0" } }, "sha512-DYPAumiUeUeT/GHT8x2wrAVKn1FqZJqFH0Y5pBefapWRreV1BBvqBVMb0020YQ2njmbR59r/IathL2d2OrDrxA=="],
|
||||||
|
|
||||||
"inline-style-parser": ["inline-style-parser@0.2.4", "", {}, "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q=="],
|
"inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
|
||||||
|
|
||||||
"is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
|
"is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
|
||||||
|
|
||||||
"is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
|
"is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
|
||||||
|
|
||||||
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
|
|
||||||
|
|
||||||
"is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
|
"is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
|
||||||
|
|
||||||
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
|
||||||
|
|
@ -468,43 +502,39 @@
|
||||||
|
|
||||||
"is-plain-object": ["is-plain-object@5.0.0", "", {}, "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="],
|
"is-plain-object": ["is-plain-object@5.0.0", "", {}, "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="],
|
||||||
|
|
||||||
"jiti": ["jiti@2.4.2", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A=="],
|
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||||
|
|
||||||
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||||
|
|
||||||
"lightningcss": ["lightningcss@1.29.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.29.2", "lightningcss-darwin-x64": "1.29.2", "lightningcss-freebsd-x64": "1.29.2", "lightningcss-linux-arm-gnueabihf": "1.29.2", "lightningcss-linux-arm64-gnu": "1.29.2", "lightningcss-linux-arm64-musl": "1.29.2", "lightningcss-linux-x64-gnu": "1.29.2", "lightningcss-linux-x64-musl": "1.29.2", "lightningcss-win32-arm64-msvc": "1.29.2", "lightningcss-win32-x64-msvc": "1.29.2" } }, "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA=="],
|
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
|
||||||
|
|
||||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.29.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA=="],
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
|
||||||
|
|
||||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.29.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w=="],
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
|
||||||
|
|
||||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.29.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg=="],
|
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.29.2", "", { "os": "linux", "cpu": "arm" }, "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg=="],
|
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.29.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ=="],
|
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.29.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ=="],
|
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
|
||||||
|
|
||||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.29.2", "", { "os": "linux", "cpu": "x64" }, "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg=="],
|
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
|
||||||
|
|
||||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.29.2", "", { "os": "linux", "cpu": "x64" }, "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w=="],
|
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
|
||||||
|
|
||||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.29.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw=="],
|
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
|
||||||
|
|
||||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA=="],
|
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
|
||||||
|
|
||||||
"loader-utils": ["loader-utils@2.0.4", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" } }, "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw=="],
|
"loader-utils": ["loader-utils@2.0.4", "", { "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" } }, "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw=="],
|
||||||
|
|
||||||
"lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="],
|
|
||||||
|
|
||||||
"lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="],
|
|
||||||
|
|
||||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
|
||||||
|
|
||||||
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
|
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.17", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } }, "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA=="],
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
"markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="],
|
"markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="],
|
||||||
|
|
||||||
|
|
@ -536,7 +566,7 @@
|
||||||
|
|
||||||
"mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="],
|
"mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="],
|
||||||
|
|
||||||
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="],
|
"mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="],
|
||||||
|
|
||||||
"mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="],
|
"mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="],
|
||||||
|
|
||||||
|
|
@ -620,15 +650,9 @@
|
||||||
|
|
||||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||||
|
|
||||||
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
|
"motion-dom": ["motion-dom@12.23.23", "", { "dependencies": { "motion-utils": "^12.23.6" } }, "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA=="],
|
||||||
|
|
||||||
"minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
|
"motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="],
|
||||||
|
|
||||||
"mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
|
|
||||||
|
|
||||||
"motion-dom": ["motion-dom@12.11.2", "", { "dependencies": { "motion-utils": "^12.9.4" } }, "sha512-wZ396XNNTI9GOkyrr80wFSbZc1JbIHSHTbLdririSbkEgahWWKmsHzsxyxqBBvuBU/iaQWVu1YCjdpXYNfo2yQ=="],
|
|
||||||
|
|
||||||
"motion-utils": ["motion-utils@12.9.4", "", {}, "sha512-BW3I65zeM76CMsfh3kHid9ansEJk9Qvl+K5cu4DVHKGsI52n76OJ4z2CUJUV+Mn3uEP9k1JJA3tClG0ggSrRcg=="],
|
|
||||||
|
|
||||||
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
||||||
|
|
||||||
|
|
@ -636,13 +660,13 @@
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
"next": ["next@15.3.2", "", { "dependencies": { "@next/env": "15.3.2", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.3.2", "@next/swc-darwin-x64": "15.3.2", "@next/swc-linux-arm64-gnu": "15.3.2", "@next/swc-linux-arm64-musl": "15.3.2", "@next/swc-linux-x64-gnu": "15.3.2", "@next/swc-linux-x64-musl": "15.3.2", "@next/swc-win32-arm64-msvc": "15.3.2", "@next/swc-win32-x64-msvc": "15.3.2", "sharp": "^0.34.1" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-CA3BatMyHkxZ48sgOCLdVHjFU36N7TF1HhqAHLFOkV6buwZnvMI84Cug8xD56B9mCuKrqXnLn94417GrZ/jjCQ=="],
|
"next": ["next@15.4.10", "", { "dependencies": { "@next/env": "15.4.10", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.4.8", "@next/swc-darwin-x64": "15.4.8", "@next/swc-linux-arm64-gnu": "15.4.8", "@next/swc-linux-arm64-musl": "15.4.8", "@next/swc-linux-x64-gnu": "15.4.8", "@next/swc-linux-x64-musl": "15.4.8", "@next/swc-win32-arm64-msvc": "15.4.8", "@next/swc-win32-x64-msvc": "15.4.8", "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-itVlc79QjpKMFMRhP+kbGKaSG/gZM6RCvwhEbwmCNF06CdDiNaoHcbeg0PqkEa2GOcn8KJ0nnc7+yL7EjoYLHQ=="],
|
||||||
|
|
||||||
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
|
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
|
||||||
|
|
||||||
"oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
|
"oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
|
||||||
|
|
||||||
"oniguruma-to-es": ["oniguruma-to-es@4.3.3", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg=="],
|
"oniguruma-to-es": ["oniguruma-to-es@4.3.4", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA=="],
|
||||||
|
|
||||||
"opener": ["opener@1.5.2", "", { "bin": { "opener": "bin/opener-bin.js" } }, "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A=="],
|
"opener": ["opener@1.5.2", "", { "bin": { "opener": "bin/opener-bin.js" } }, "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A=="],
|
||||||
|
|
||||||
|
|
@ -652,29 +676,31 @@
|
||||||
|
|
||||||
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
|
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||||
|
|
||||||
"postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
|
"postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
|
||||||
|
|
||||||
"property-information": ["property-information@7.0.0", "", {}, "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg=="],
|
"property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
|
||||||
|
|
||||||
|
"qss": ["qss@3.0.0", "", {}, "sha512-ZHoCB3M/3Voev64zhLLUOKDtaEdJ/lymsJJ7R3KBusVZ2ovNiIB7XOq3Xh6V1a8O+Vho+g2B5YElq9zW7D8aQw=="],
|
||||||
|
|
||||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||||
|
|
||||||
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
"react": ["react@19.2.3", "", {}, "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA=="],
|
||||||
|
|
||||||
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
"react-dom": ["react-dom@19.2.3", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.3" } }, "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg=="],
|
||||||
|
|
||||||
"react-highlight-words": ["react-highlight-words@0.21.0", "", { "dependencies": { "highlight-words-core": "^1.2.0", "memoize-one": "^4.0.0" }, "peerDependencies": { "react": "^0.14.0 || ^15.0.0 || ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-SdWEeU9fIINArEPO1rO5OxPyuhdEKZQhHzZZP1ie6UeXQf+CjycT1kWaB+9bwGcVbR0NowuHK3RqgqNg6bgBDQ=="],
|
"react-highlight-words": ["react-highlight-words@0.21.0", "", { "dependencies": { "highlight-words-core": "^1.2.0", "memoize-one": "^4.0.0" }, "peerDependencies": { "react": "^0.14.0 || ^15.0.0 || ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-SdWEeU9fIINArEPO1rO5OxPyuhdEKZQhHzZZP1ie6UeXQf+CjycT1kWaB+9bwGcVbR0NowuHK3RqgqNg6bgBDQ=="],
|
||||||
|
|
||||||
"recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="],
|
"recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="],
|
||||||
|
|
||||||
"recma-jsx": ["recma-jsx@1.0.0", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" } }, "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q=="],
|
"recma-jsx": ["recma-jsx@1.0.1", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" }, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w=="],
|
||||||
|
|
||||||
"recma-parse": ["recma-parse@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "esast-util-from-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ=="],
|
"recma-parse": ["recma-parse@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "esast-util-from-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ=="],
|
||||||
|
|
||||||
"recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="],
|
"recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="],
|
||||||
|
|
||||||
"regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="],
|
"regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
|
||||||
|
|
||||||
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
|
"regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
|
||||||
|
|
||||||
|
|
@ -686,7 +712,7 @@
|
||||||
|
|
||||||
"remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
|
"remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
|
||||||
|
|
||||||
"remark-mdx": ["remark-mdx@3.1.0", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA=="],
|
"remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="],
|
||||||
|
|
||||||
"remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
|
"remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
|
||||||
|
|
||||||
|
|
@ -698,45 +724,39 @@
|
||||||
|
|
||||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||||
|
|
||||||
"scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||||
|
|
||||||
"search-insights": ["search-insights@2.17.3", "", {}, "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ=="],
|
"search-insights": ["search-insights@2.17.3", "", {}, "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ=="],
|
||||||
|
|
||||||
"semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
|
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
||||||
|
|
||||||
"sharp": ["sharp@0.34.1", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.7.1" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.1", "@img/sharp-darwin-x64": "0.34.1", "@img/sharp-libvips-darwin-arm64": "1.1.0", "@img/sharp-libvips-darwin-x64": "1.1.0", "@img/sharp-libvips-linux-arm": "1.1.0", "@img/sharp-libvips-linux-arm64": "1.1.0", "@img/sharp-libvips-linux-ppc64": "1.1.0", "@img/sharp-libvips-linux-s390x": "1.1.0", "@img/sharp-libvips-linux-x64": "1.1.0", "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", "@img/sharp-libvips-linuxmusl-x64": "1.1.0", "@img/sharp-linux-arm": "0.34.1", "@img/sharp-linux-arm64": "0.34.1", "@img/sharp-linux-s390x": "0.34.1", "@img/sharp-linux-x64": "0.34.1", "@img/sharp-linuxmusl-arm64": "0.34.1", "@img/sharp-linuxmusl-x64": "0.34.1", "@img/sharp-wasm32": "0.34.1", "@img/sharp-win32-ia32": "0.34.1", "@img/sharp-win32-x64": "0.34.1" } }, "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg=="],
|
"sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
|
||||||
|
|
||||||
"shiki": ["shiki@3.4.1", "", { "dependencies": { "@shikijs/core": "3.4.1", "@shikijs/engine-javascript": "3.4.1", "@shikijs/engine-oniguruma": "3.4.1", "@shikijs/langs": "3.4.1", "@shikijs/themes": "3.4.1", "@shikijs/types": "3.4.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-PSnoczt+iWIOB4iRQ+XVPFtTuN1FcmuYzPgUBZTSv5pC6CozssIx2M4O5n4S9gJlUu9A3FxMU0ZPaHflky/6LA=="],
|
"shiki": ["shiki@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/engine-javascript": "3.20.0", "@shikijs/engine-oniguruma": "3.20.0", "@shikijs/langs": "3.20.0", "@shikijs/themes": "3.20.0", "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg=="],
|
||||||
|
|
||||||
"simple-functional-loader": ["simple-functional-loader@1.2.1", "", { "dependencies": { "loader-utils": "^2.0.0" } }, "sha512-GPDrxrQkE7ijm35QlfPFVp5hBHR6ZcaUq42TEDgf1U5iTL3IDLFvKAbHE/ODqpdfJJ7Xn4cr/slBn12jjNPkaQ=="],
|
"simple-functional-loader": ["simple-functional-loader@1.2.1", "", { "dependencies": { "loader-utils": "^2.0.0" } }, "sha512-GPDrxrQkE7ijm35QlfPFVp5hBHR6ZcaUq42TEDgf1U5iTL3IDLFvKAbHE/ODqpdfJJ7Xn4cr/slBn12jjNPkaQ=="],
|
||||||
|
|
||||||
"simple-swizzle": ["simple-swizzle@0.2.2", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg=="],
|
|
||||||
|
|
||||||
"sirv": ["sirv@2.0.4", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ=="],
|
"sirv": ["sirv@2.0.4", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ=="],
|
||||||
|
|
||||||
"source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="],
|
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
|
"space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
|
||||||
|
|
||||||
"streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
|
|
||||||
|
|
||||||
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
|
"stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
|
||||||
|
|
||||||
"style-to-js": ["style-to-js@1.1.16", "", { "dependencies": { "style-to-object": "1.0.8" } }, "sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw=="],
|
"style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
|
||||||
|
|
||||||
"style-to-object": ["style-to-object@1.0.8", "", { "dependencies": { "inline-style-parser": "0.2.4" } }, "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g=="],
|
"style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
|
||||||
|
|
||||||
"styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
|
"styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
|
||||||
|
|
||||||
"tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="],
|
"tabbable": ["tabbable@6.3.0", "", {}, "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.1.6", "", {}, "sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg=="],
|
"tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="],
|
||||||
|
|
||||||
"tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="],
|
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||||
|
|
||||||
"tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
|
|
||||||
|
|
||||||
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
||||||
|
|
||||||
|
|
@ -748,15 +768,15 @@
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||||
|
|
||||||
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
|
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
|
||||||
|
|
||||||
"unist-util-filter": ["unist-util-filter@5.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-pHx7D4Zt6+TsfwylH9+lYhBhzyhEnCXs/lbq/Hstxno5z4gVdyc2WEW0asfjGKPyG4pEKrnBv5hdkO6+aRnQJw=="],
|
"unist-util-filter": ["unist-util-filter@5.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-pHx7D4Zt6+TsfwylH9+lYhBhzyhEnCXs/lbq/Hstxno5z4gVdyc2WEW0asfjGKPyG4pEKrnBv5hdkO6+aRnQJw=="],
|
||||||
|
|
||||||
"unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="],
|
"unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
|
||||||
|
|
||||||
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
|
"unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
|
||||||
|
|
||||||
|
|
@ -766,9 +786,9 @@
|
||||||
|
|
||||||
"unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
|
"unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
|
||||||
|
|
||||||
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="],
|
"unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
|
||||||
|
|
||||||
"use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="],
|
"use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
|
||||||
|
|
||||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||||
|
|
||||||
|
|
@ -776,40 +796,32 @@
|
||||||
|
|
||||||
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
|
||||||
|
|
||||||
"vfile-message": ["vfile-message@4.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw=="],
|
"vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
|
||||||
|
|
||||||
"webpack-bundle-analyzer": ["webpack-bundle-analyzer@4.10.1", "", { "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", "acorn-walk": "^8.0.0", "commander": "^7.2.0", "debounce": "^1.2.1", "escape-string-regexp": "^4.0.0", "gzip-size": "^6.0.0", "html-escaper": "^2.0.2", "is-plain-object": "^5.0.0", "opener": "^1.5.2", "picocolors": "^1.0.0", "sirv": "^2.0.3", "ws": "^7.3.1" }, "bin": { "webpack-bundle-analyzer": "lib/bin/analyzer.js" } }, "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ=="],
|
"webpack-bundle-analyzer": ["webpack-bundle-analyzer@4.10.1", "", { "dependencies": { "@discoveryjs/json-ext": "0.5.7", "acorn": "^8.0.4", "acorn-walk": "^8.0.0", "commander": "^7.2.0", "debounce": "^1.2.1", "escape-string-regexp": "^4.0.0", "gzip-size": "^6.0.0", "html-escaper": "^2.0.2", "is-plain-object": "^5.0.0", "opener": "^1.5.2", "picocolors": "^1.0.0", "sirv": "^2.0.3", "ws": "^7.3.1" }, "bin": { "webpack-bundle-analyzer": "lib/bin/analyzer.js" } }, "sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ=="],
|
||||||
|
|
||||||
"ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
"ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||||
|
|
||||||
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
"zustand": ["zustand@5.0.9", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-ALBtUj0AfjJt3uNRQoL1tL2tMvj6Gp/6e39dnfT6uzpelGru8v1tPOGBzayOWbPJvujM8JojDk3E1LxeFisBNg=="],
|
||||||
|
|
||||||
"zustand": ["zustand@5.0.4", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ=="],
|
|
||||||
|
|
||||||
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.4.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.0.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.4.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.0.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.0", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.9", "", { "dependencies": { "@emnapi/core": "^1.4.0", "@emnapi/runtime": "^1.4.0", "@tybys/wasm-util": "^0.9.0" }, "bundled": true }, "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"@types/react-highlight-words/@types/react": ["@types/react@19.1.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw=="],
|
|
||||||
|
|
||||||
"esast-util-from-estree/estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="],
|
"esast-util-from-estree/estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="],
|
||||||
|
|
||||||
"estree-util-visit/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
|
"estree-util-visit/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
|
||||||
|
|
||||||
"lightningcss/detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
|
|
||||||
|
|
||||||
"mdx-annotations/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="],
|
"mdx-annotations/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="],
|
||||||
|
|
||||||
"micromark-util-events-to-acorn/estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="],
|
"micromark-util-events-to-acorn/estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="],
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import clsx from "clsx";
|
||||||
import {
|
import {
|
||||||
Children,
|
Children,
|
||||||
type ComponentPropsWithoutRef,
|
type ComponentPropsWithoutRef,
|
||||||
type ReactNode,
|
|
||||||
createContext,
|
createContext,
|
||||||
isValidElement,
|
isValidElement,
|
||||||
|
type ReactNode,
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
|
|
@ -144,8 +144,7 @@ function CodePanel({
|
||||||
label?: string;
|
label?: string;
|
||||||
code?: string;
|
code?: string;
|
||||||
}) {
|
}) {
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
const child = children as ReactNode & { props: any };
|
||||||
const child = Children.only(children) as ReactNode & { props: any };
|
|
||||||
|
|
||||||
if (isValidElement(child)) {
|
if (isValidElement(child)) {
|
||||||
tag = child.props.tag ?? tag;
|
tag = child.props.tag ?? tag;
|
||||||
|
|
@ -207,8 +206,7 @@ function CodeGroupHeader({
|
||||||
>
|
>
|
||||||
{getPanelTitle(
|
{getPanelTitle(
|
||||||
isValidElement(child)
|
isValidElement(child)
|
||||||
? // biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
? (child.props as any)
|
||||||
(child.props as any)
|
|
||||||
: {},
|
: {},
|
||||||
)}
|
)}
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|
@ -326,7 +324,6 @@ export function CodeGroup({
|
||||||
}: ComponentPropsWithoutRef<typeof CodeGroupPanels> & { title: string }) {
|
}: ComponentPropsWithoutRef<typeof CodeGroupPanels> & { title: string }) {
|
||||||
const languages =
|
const languages =
|
||||||
Children.map(children, (child) =>
|
Children.map(children, (child) =>
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
||||||
getPanelTitle(isValidElement(child) ? (child.props as any) : {}),
|
getPanelTitle(isValidElement(child) ? (child.props as any) : {}),
|
||||||
) ?? [];
|
) ?? [];
|
||||||
const tabGroupProps = useTabGroupProps(languages);
|
const tabGroupProps = useTabGroupProps(languages);
|
||||||
|
|
@ -375,8 +372,8 @@ export function Code({ children, ...props }: ComponentPropsWithoutRef<"code">) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation>
|
// biome-ignore lint/security/noDangerouslySetInnerHtml: HTML is trusted
|
||||||
// biome-ignore lint/style/useNamingConvention: <explanation>
|
// biome-ignore lint/style/useNamingConvention: Biome incorrectly tags this as bad naming
|
||||||
<code {...props} dangerouslySetInnerHTML={{ __html: children }} />
|
<code {...props} dangerouslySetInnerHTML={{ __html: children }} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ const FeedbackForm = forwardRef<
|
||||||
});
|
});
|
||||||
|
|
||||||
const FeedbackThanks = forwardRef<ComponentRef<"div">>(
|
const FeedbackThanks = forwardRef<ComponentRef<"div">>(
|
||||||
// biome-ignore lint/style/useNamingConvention: <explanation>
|
|
||||||
function FeedbackThanks(_props, ref) {
|
function FeedbackThanks(_props, ref) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Icon } from "@iconify-icon/react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
import { Icon } from "@iconify-icon/react";
|
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { Button } from "./Button";
|
import { Button } from "./Button";
|
||||||
import { navigation } from "./Navigation";
|
import { navigation } from "./Navigation";
|
||||||
|
|
@ -130,7 +129,7 @@ function SmallPrint() {
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return (
|
return (
|
||||||
<footer className="mx-auto w-full max-w-2xl space-y-10 pb-16 lg:max-w-5xl">
|
<footer className="mx-auto w-full max-w-2xl space-y-10 pb-16 lg:max-w-5xl print:hidden">
|
||||||
<PageNavigation />
|
<PageNavigation />
|
||||||
<SmallPrint />
|
<SmallPrint />
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export function GridPattern({
|
||||||
fill={`url(#${patternId})`}
|
fill={`url(#${patternId})`}
|
||||||
/>
|
/>
|
||||||
{squares && (
|
{squares && (
|
||||||
// biome-ignore lint/a11y/noSvgWithoutTitle: <explanation>
|
// biome-ignore lint/a11y/noSvgWithoutTitle: it's decoration
|
||||||
<svg
|
<svg
|
||||||
x={x}
|
x={x}
|
||||||
y={y}
|
y={y}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,11 @@ export function Guide({
|
||||||
href,
|
href,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
}: { href: string; name: string; description: string }) {
|
}: {
|
||||||
|
href: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-semibold text-zinc-900 dark:text-white">
|
<h3 className="text-sm font-semibold text-zinc-900 dark:text-white">
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import clsx from "clsx";
|
||||||
import { motion, useScroll, useTransform } from "framer-motion";
|
import { motion, useScroll, useTransform } from "framer-motion";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import {
|
import {
|
||||||
type CSSProperties,
|
|
||||||
type ComponentRef,
|
type ComponentRef,
|
||||||
type ReactNode,
|
type CSSProperties,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
|
type ReactNode,
|
||||||
} from "react";
|
} from "react";
|
||||||
|
|
||||||
import { Button } from "./Button";
|
import { Button } from "./Button";
|
||||||
|
|
@ -13,8 +13,8 @@ import { Logo } from "./Logo";
|
||||||
import {
|
import {
|
||||||
MobileNavigation,
|
MobileNavigation,
|
||||||
useIsInsideMobileNavigation,
|
useIsInsideMobileNavigation,
|
||||||
|
useMobileNavigationStore,
|
||||||
} from "./MobileNavigation";
|
} from "./MobileNavigation";
|
||||||
import { useMobileNavigationStore } from "./MobileNavigation";
|
|
||||||
import { MobileSearch, Search } from "./Search";
|
import { MobileSearch, Search } from "./Search";
|
||||||
import { ThemeToggle } from "./ThemeToggle";
|
import { ThemeToggle } from "./ThemeToggle";
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ export const Header = forwardRef<ComponentRef<"div">, { className?: string }>(
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden min-[500px]:contents">
|
<div className="hidden min-[500px]:contents">
|
||||||
<Button href="/changelog">Working Draft 5</Button>
|
<Button href="/changelog">Working Draft 6</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export function Layout({
|
||||||
<div className="h-full lg:ml-72 xl:ml-80">
|
<div className="h-full lg:ml-72 xl:ml-80">
|
||||||
<motion.header
|
<motion.header
|
||||||
layoutScroll={true}
|
layoutScroll={true}
|
||||||
className="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex"
|
className="contents lg:pointer-events-none lg:fixed lg:inset-0 lg:z-40 lg:flex print:hidden"
|
||||||
>
|
>
|
||||||
<div className="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:px-6 lg:pb-8 lg:pt-4 xl:w-80 lg:dark:border-white/10">
|
<div className="contents lg:pointer-events-auto lg:block lg:w-72 lg:overflow-y-auto lg:border-r lg:border-zinc-900/10 lg:px-6 lg:pb-8 lg:pt-4 xl:w-80 lg:dark:border-white/10">
|
||||||
<div className="hidden lg:flex">
|
<div className="hidden lg:flex">
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ import { Heading } from "./Heading";
|
||||||
|
|
||||||
const libraries = [
|
const libraries = [
|
||||||
{
|
{
|
||||||
href: "https://github.com/versia-pub/api/tree/main/federation",
|
href: "https://github.com/versia-pub/server/tree/main/packages/sdk",
|
||||||
name: "@versia/federation",
|
name: "@versia/sdk",
|
||||||
description:
|
description:
|
||||||
"Fully-featured federation toolkit with validation, signatures, parsing, and more.",
|
"Fully-featured federation toolkit with validation, signatures, parsing, and more.",
|
||||||
logo: logoTypescript,
|
logo: logoTypescript,
|
||||||
|
|
|
||||||
174
components/LinkPreview.tsx
Normal file
174
components/LinkPreview.tsx
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
"use client";
|
||||||
|
import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
|
||||||
|
|
||||||
|
import {
|
||||||
|
AnimatePresence,
|
||||||
|
motion,
|
||||||
|
useMotionValue,
|
||||||
|
useSpring,
|
||||||
|
} from "framer-motion";
|
||||||
|
import { encode } from "qss";
|
||||||
|
import {
|
||||||
|
type MouseEvent as ReactMouseEvent,
|
||||||
|
type ReactNode,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
|
|
||||||
|
type LinkPreviewProps = {
|
||||||
|
children: ReactNode;
|
||||||
|
url: string;
|
||||||
|
className?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
quality?: number;
|
||||||
|
layout?: string;
|
||||||
|
} & (
|
||||||
|
| { isStatic: true; imageSrc: string }
|
||||||
|
| { isStatic?: false; imageSrc?: never }
|
||||||
|
);
|
||||||
|
|
||||||
|
export const LinkPreview = ({
|
||||||
|
children,
|
||||||
|
url,
|
||||||
|
className,
|
||||||
|
width = 200,
|
||||||
|
height = 125,
|
||||||
|
isStatic = false,
|
||||||
|
imageSrc = "",
|
||||||
|
}: LinkPreviewProps) => {
|
||||||
|
let src: string;
|
||||||
|
|
||||||
|
if (isStatic) {
|
||||||
|
src = imageSrc;
|
||||||
|
} else {
|
||||||
|
const params = encode({
|
||||||
|
url,
|
||||||
|
screenshot: true,
|
||||||
|
meta: false,
|
||||||
|
embed: "screenshot.url",
|
||||||
|
colorScheme: "dark",
|
||||||
|
"viewport.isMobile": true,
|
||||||
|
"viewport.deviceScaleFactor": 1,
|
||||||
|
"viewport.width": width * 3,
|
||||||
|
"viewport.height": height * 3,
|
||||||
|
});
|
||||||
|
src = `https://api.microlink.io/?${params}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [isOpen, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const [isMounted, setIsMounted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsMounted(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const springConfig = { stiffness: 100, damping: 15 };
|
||||||
|
const x = useMotionValue(0);
|
||||||
|
|
||||||
|
const translateX = useSpring(x, springConfig);
|
||||||
|
|
||||||
|
const handleMouseMove = (
|
||||||
|
event: ReactMouseEvent<HTMLAnchorElement, MouseEvent>,
|
||||||
|
) => {
|
||||||
|
const targetRect = (
|
||||||
|
event.target as HTMLAnchorElement
|
||||||
|
).getBoundingClientRect();
|
||||||
|
const eventOffsetX = event.clientX - targetRect.left;
|
||||||
|
const offsetFromCenter = (eventOffsetX - targetRect.width / 2) / 2; // Reduce the effect to make it subtle
|
||||||
|
x.set(offsetFromCenter);
|
||||||
|
};
|
||||||
|
|
||||||
|
const [isCurrentOrigin, setIsCurrentOrigin] = useState(true);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (process && URL.canParse(url)) {
|
||||||
|
setIsCurrentOrigin(new URL(url).origin === window.location.origin);
|
||||||
|
}
|
||||||
|
}, [url]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isMounted
|
||||||
|
? createPortal(
|
||||||
|
<div className="hidden">
|
||||||
|
<img
|
||||||
|
src={src}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
aria-hidden={true}
|
||||||
|
/>
|
||||||
|
</div>,
|
||||||
|
document.body,
|
||||||
|
)
|
||||||
|
: null}
|
||||||
|
<HoverCardPrimitive.Root
|
||||||
|
openDelay={50}
|
||||||
|
closeDelay={100}
|
||||||
|
onOpenChange={(open) => {
|
||||||
|
setOpen(open);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HoverCardPrimitive.Trigger
|
||||||
|
onMouseMove={handleMouseMove}
|
||||||
|
href={url}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</HoverCardPrimitive.Trigger>
|
||||||
|
|
||||||
|
<HoverCardPrimitive.Portal>
|
||||||
|
<HoverCardPrimitive.Content
|
||||||
|
className="[transform-origin:var(--radix-hover-card-content-transform-origin)] not-prose z-100"
|
||||||
|
side="top"
|
||||||
|
align="center"
|
||||||
|
sideOffset={10}
|
||||||
|
>
|
||||||
|
<AnimatePresence>
|
||||||
|
{isOpen && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20, scale: 0.6 }}
|
||||||
|
animate={{
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
scale: 1,
|
||||||
|
transition: {
|
||||||
|
type: "spring",
|
||||||
|
stiffness: 260,
|
||||||
|
damping: 20,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
exit={{ opacity: 0, y: 20, scale: 0.6 }}
|
||||||
|
className="shadow-xl rounded-xl"
|
||||||
|
style={{
|
||||||
|
x: translateX,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href={url}
|
||||||
|
className="block p-1 bg-white border-2 border-transparent shadow rounded-xl hover:border-neutral-200 dark:hover:border-neutral-800"
|
||||||
|
target={
|
||||||
|
isCurrentOrigin ? "_self" : "_blank"
|
||||||
|
}
|
||||||
|
style={{ fontSize: 0 }}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={isStatic ? imageSrc : src}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
className="rounded-lg"
|
||||||
|
alt={`Preview for ${url}`}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</HoverCardPrimitive.Content>
|
||||||
|
</HoverCardPrimitive.Portal>
|
||||||
|
</HoverCardPrimitive.Root>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import type { ComponentPropsWithoutRef } from "react";
|
import type { ComponentPropsWithoutRef } from "react";
|
||||||
// Uncomment this on dev branches
|
// Uncomment this on dev branches
|
||||||
// import { Badge } from "./Metadata";
|
import { Badge } from "./Metadata";
|
||||||
|
|
||||||
export function Logo(props: ComponentPropsWithoutRef<"div">) {
|
export function Logo(props: ComponentPropsWithoutRef<"div">) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -17,9 +17,9 @@ export function Logo(props: ComponentPropsWithoutRef<"div">) {
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
className="h-full rounded-xs"
|
className="h-full rounded-xs"
|
||||||
/>
|
/>
|
||||||
<span className="fill-zinc-900 dark:fill-white font-semibold text-lg">
|
{/* <span className="fill-zinc-900 dark:fill-white font-semibold text-lg">
|
||||||
Versia Protocol {/* <Badge className="h-6!">Dev</Badge> */}
|
Versia Protocol <Badge className="h-6!">Dev</Badge>
|
||||||
</span>
|
</span> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ import { motion } from "framer-motion";
|
||||||
import { usePathname, useSearchParams } from "next/navigation";
|
import { usePathname, useSearchParams } from "next/navigation";
|
||||||
import {
|
import {
|
||||||
type ComponentPropsWithoutRef,
|
type ComponentPropsWithoutRef,
|
||||||
|
createContext,
|
||||||
type MouseEvent,
|
type MouseEvent,
|
||||||
Suspense,
|
Suspense,
|
||||||
createContext,
|
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useRef,
|
useRef,
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,6 @@ function NavigationGroup({
|
||||||
{link.href === pathname &&
|
{link.href === pathname &&
|
||||||
sections.length > 0 && (
|
sections.length > 0 && (
|
||||||
<motion.ul
|
<motion.ul
|
||||||
// biome-ignore lint/a11y/useSemanticElements: already a <ul>
|
|
||||||
role="list"
|
role="list"
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{
|
animate={{
|
||||||
|
|
@ -250,6 +249,7 @@ export const navigation: NavGroup[] = [
|
||||||
{ title: "Introduction", href: "/introduction" },
|
{ title: "Introduction", href: "/introduction" },
|
||||||
{ title: "SDKs", href: "/sdks" },
|
{ title: "SDKs", href: "/sdks" },
|
||||||
{ title: "Entities", href: "/entities" },
|
{ title: "Entities", href: "/entities" },
|
||||||
|
{ title: "JSON", href: "/json" },
|
||||||
{ title: "Signatures", href: "/signatures" },
|
{ title: "Signatures", href: "/signatures" },
|
||||||
{ title: "Security", href: "/security" },
|
{ title: "Security", href: "/security" },
|
||||||
{ title: "Federation", href: "/federation" },
|
{ title: "Federation", href: "/federation" },
|
||||||
|
|
@ -267,10 +267,16 @@ export const navigation: NavGroup[] = [
|
||||||
{ title: "HTTP", href: "/federation/http" },
|
{ title: "HTTP", href: "/federation/http" },
|
||||||
{ title: "Validation", href: "/federation/validation" },
|
{ title: "Validation", href: "/federation/validation" },
|
||||||
{ title: "Discovery", href: "/federation/discovery" },
|
{ title: "Discovery", href: "/federation/discovery" },
|
||||||
{ title: "Delegation", href: "/federation/delegation" },
|
|
||||||
{ title: "Example", href: "/federation/example" },
|
{ title: "Example", href: "/federation/example" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "API",
|
||||||
|
links: [
|
||||||
|
{ title: "Basics", href: "/api/basics" },
|
||||||
|
{ title: "Endpoints", href: "/api/endpoints" },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Structures",
|
title: "Structures",
|
||||||
links: [
|
links: [
|
||||||
|
|
@ -295,6 +301,7 @@ export const navigation: NavGroup[] = [
|
||||||
title: "Extensions",
|
title: "Extensions",
|
||||||
links: [
|
links: [
|
||||||
{ title: "Custom Emojis", href: "/extensions/custom-emojis" },
|
{ title: "Custom Emojis", href: "/extensions/custom-emojis" },
|
||||||
|
{ title: "Delegation", href: "/extensions/delegation" },
|
||||||
{ title: "Groups", href: "/extensions/groups" },
|
{ title: "Groups", href: "/extensions/groups" },
|
||||||
{
|
{
|
||||||
title: "Instance Messaging",
|
title: "Instance Messaging",
|
||||||
|
|
@ -311,7 +318,6 @@ export const navigation: NavGroup[] = [
|
||||||
{ title: "Reports", href: "/extensions/reports" },
|
{ title: "Reports", href: "/extensions/reports" },
|
||||||
{ title: "Share", href: "/extensions/share" },
|
{ title: "Share", href: "/extensions/share" },
|
||||||
{ title: "Vanity", href: "/extensions/vanity" },
|
{ title: "Vanity", href: "/extensions/vanity" },
|
||||||
{ title: "WebSockets", href: "/extensions/websockets" },
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
@ -334,7 +340,7 @@ export function Navigation(props: ComponentPropsWithoutRef<"nav">) {
|
||||||
variant="filled"
|
variant="filled"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
>
|
>
|
||||||
Working Draft 5
|
Working Draft 6
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { type ReactNode, createContext, useContext } from "react";
|
import { createContext, type ReactNode, useContext } from "react";
|
||||||
import { AnchorIcon } from "./Heading";
|
import { AnchorIcon } from "./Heading";
|
||||||
|
|
||||||
export const PropertyContext = createContext<{
|
export const PropertyContext = createContext<{
|
||||||
|
|
@ -13,7 +13,10 @@ export const PropertyContext = createContext<{
|
||||||
export function Properties({
|
export function Properties({
|
||||||
children,
|
children,
|
||||||
name,
|
name,
|
||||||
}: { children: ReactNode; name: string }) {
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
name: string;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="my-6">
|
<div className="my-6">
|
||||||
<ul className="m-0! max-w-[calc(var(--container-lg)-(--spacing(8)))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5">
|
<ul className="m-0! max-w-[calc(var(--container-lg)-(--spacing(8)))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { Icon } from "@iconify-icon/react";
|
||||||
import {
|
import {
|
||||||
type MotionValue,
|
type MotionValue,
|
||||||
motion,
|
motion,
|
||||||
|
|
@ -7,8 +8,6 @@ import {
|
||||||
useMotionValue,
|
useMotionValue,
|
||||||
} from "framer-motion";
|
} from "framer-motion";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
import { Icon } from "@iconify-icon/react";
|
|
||||||
import type { ComponentPropsWithoutRef, MouseEvent } from "react";
|
import type { ComponentPropsWithoutRef, MouseEvent } from "react";
|
||||||
import { GridPattern } from "./GridPattern";
|
import { GridPattern } from "./GridPattern";
|
||||||
import { Heading } from "./Heading";
|
import { Heading } from "./Heading";
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ import {
|
||||||
type ComponentPropsWithoutRef,
|
type ComponentPropsWithoutRef,
|
||||||
type ComponentRef,
|
type ComponentRef,
|
||||||
Fragment,
|
Fragment,
|
||||||
|
forwardRef,
|
||||||
type MouseEvent,
|
type MouseEvent,
|
||||||
type KeyboardEvent as ReactKeyboardEvent,
|
type KeyboardEvent as ReactKeyboardEvent,
|
||||||
Suspense,
|
Suspense,
|
||||||
type SyntheticEvent,
|
type SyntheticEvent,
|
||||||
forwardRef,
|
|
||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useId,
|
useId,
|
||||||
|
|
@ -164,7 +164,6 @@ function LoadingIcon(props: ComponentPropsWithoutRef<"svg">) {
|
||||||
|
|
||||||
function HighlightQuery({ text, query }: { text: string; query: string }) {
|
function HighlightQuery({ text, query }: { text: string; query: string }) {
|
||||||
return (
|
return (
|
||||||
// @ts-ignore
|
|
||||||
<Highlighter
|
<Highlighter
|
||||||
highlightClassName="underline bg-transparent text-brand-500"
|
highlightClassName="underline bg-transparent text-brand-500"
|
||||||
searchWords={[query]}
|
searchWords={[query]}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
createContext,
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
type RefObject,
|
type RefObject,
|
||||||
createContext,
|
|
||||||
useContext,
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useLayoutEffect,
|
useLayoutEffect,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { type StoreApi, createStore, useStore } from "zustand";
|
import { createStore, type StoreApi, useStore } from "zustand";
|
||||||
|
|
||||||
import { remToPx } from "../lib/remToPx";
|
import { remToPx } from "../lib/remToPx";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ import { Heading } from "./Heading";
|
||||||
import { Prose } from "./Prose";
|
import { Prose } from "./Prose";
|
||||||
|
|
||||||
export const a = Link;
|
export const a = Link;
|
||||||
// biome-ignore lint/performance/noBarrelFile: <explanation>
|
|
||||||
export { Button } from "./Button";
|
export { Button } from "./Button";
|
||||||
export { CodeGroup, Code as code, Pre as pre } from "./Code";
|
export { Code as code, CodeGroup, Pre as pre } from "./Code";
|
||||||
export { Property, Properties } from "./Property";
|
export { Properties, Property } from "./Property";
|
||||||
|
|
||||||
export function wrapper({ children }: { children: ReactNode }) {
|
export function wrapper({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -44,6 +43,37 @@ function InfoIcon(props: ComponentPropsWithoutRef<"svg">) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function WarningIcon(props: ComponentPropsWithoutRef<"svg">) {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth={1.5}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
d="M12 9v4"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M12 17h.01"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function Note({ children }: { children: ReactNode }) {
|
export function Note({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="my-6 flex gap-2.5 rounded-md border border-brand-500/20 bg-brand-50/50 p-4 leading-6 text-brand-900 dark:border-brand-500/30 dark:bg-brand-500/5 dark:text-brand-200 dark:[--tw-prose-links-hover:var(--color-brand-300)] dark:[--tw-prose-links:var(--color-white)]">
|
<div className="my-6 flex gap-2.5 rounded-md border border-brand-500/20 bg-brand-50/50 p-4 leading-6 text-brand-900 dark:border-brand-500/30 dark:bg-brand-500/5 dark:text-brand-200 dark:[--tw-prose-links-hover:var(--color-brand-300)] dark:[--tw-prose-links:var(--color-white)]">
|
||||||
|
|
@ -55,6 +85,17 @@ export function Note({ children }: { children: ReactNode }) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Warning({ children }: { children: ReactNode }) {
|
||||||
|
return (
|
||||||
|
<div className="my-6 flex gap-2.5 rounded-md border border-yellow-500/20 bg-yellow-50/50 p-4 leading-6 text-yellow-900 dark:border-yellow-500/30 dark:bg-yellow-500/5 dark:text-yellow-200 dark:[--tw-prose-links-hover:theme(colors.yellow.300)] dark:[--tw-prose-links:theme(colors.white)]">
|
||||||
|
<WarningIcon className="mt-1 h-4 w-4 flex-none fill-yellow-500 stroke-white dark:fill-yellow-200/20 dark:stroke-yellow-200" />
|
||||||
|
<div className="[&>:first-child]:mt-0 [&>:last-child]:mb-0">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function Row({ children }: { children: ReactNode }) {
|
export function Row({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
|
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import { visit } from "unist-util-visit";
|
||||||
|
|
||||||
function rehypeParseCodeBlocks() {
|
function rehypeParseCodeBlocks() {
|
||||||
return (tree) => {
|
return (tree) => {
|
||||||
// biome-ignore lint/style/useNamingConvention: <explanation>
|
|
||||||
visit(tree, "element", (node, _nodeIndex, parentNode) => {
|
visit(tree, "element", (node, _nodeIndex, parentNode) => {
|
||||||
if (node.tagName === "code" && node.properties.className) {
|
if (node.tagName === "code" && node.properties.className) {
|
||||||
parentNode.properties.language =
|
parentNode.properties.language =
|
||||||
|
|
@ -40,7 +39,7 @@ const highlighter = await createHighlighter({
|
||||||
themes: [],
|
themes: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
highlighter.loadTheme("dark-plus");
|
await highlighter.loadTheme("dark-plus");
|
||||||
|
|
||||||
function rehypeShiki() {
|
function rehypeShiki() {
|
||||||
return async (tree) => {
|
return async (tree) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import nextMDX from "@next/mdx";
|
|
||||||
|
|
||||||
import bundleAnalyzer from "@next/bundle-analyzer";
|
import bundleAnalyzer from "@next/bundle-analyzer";
|
||||||
|
import nextMDX from "@next/mdx";
|
||||||
import { recmaPlugins } from "./mdx/recma.mjs";
|
import { recmaPlugins } from "./mdx/recma.mjs";
|
||||||
import { rehypePlugins } from "./mdx/rehype.mjs";
|
import { rehypePlugins } from "./mdx/rehype.mjs";
|
||||||
import { remarkPlugins } from "./mdx/remark.mjs";
|
import { remarkPlugins } from "./mdx/remark.mjs";
|
||||||
|
|
@ -17,6 +16,11 @@ const withMDX = nextMDX({
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
pageExtensions: ["js", "jsx", "ts", "tsx", "mdx"],
|
pageExtensions: ["js", "jsx", "ts", "tsx", "mdx"],
|
||||||
output: "export",
|
output: "export",
|
||||||
|
images: {
|
||||||
|
domains: [
|
||||||
|
"api.microlink.io", // Microlink Image Preview
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const withBundleAnalyzer = bundleAnalyzer({
|
const withBundleAnalyzer = bundleAnalyzer({
|
||||||
|
|
|
||||||
60
package.json
60
package.json
|
|
@ -11,50 +11,56 @@
|
||||||
"uuid": "bun --print 'crypto.randomUUID()'"
|
"uuid": "bun --print 'crypto.randomUUID()'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@algolia/autocomplete-core": "^1.19.1",
|
"@algolia/autocomplete-core": "^1.19.4",
|
||||||
"@headlessui/react": "^2.2.3",
|
"@headlessui/react": "^2.2.9",
|
||||||
"@headlessui/tailwindcss": "^0.2.2",
|
"@headlessui/tailwindcss": "^0.2.2",
|
||||||
"@mdx-js/loader": "^3.1.0",
|
"@mdx-js/loader": "^3.1.0",
|
||||||
"@mdx-js/react": "^3.1.0",
|
"@mdx-js/react": "^3.1.0",
|
||||||
"@next/mdx": "^15.3.2",
|
"@next/mdx": "^15.4.10",
|
||||||
"@sindresorhus/slugify": "^2.2.1",
|
"@radix-ui/react-hover-card": "^1.1.15",
|
||||||
"@tailwindcss/postcss": "^4.1.6",
|
"@sindresorhus/slugify": "^3.0.0",
|
||||||
"@tailwindcss/typography": "^0.5.16",
|
"@tailwindcss/postcss": "^4.1.18",
|
||||||
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "^22.15.18",
|
"@types/node": "^25.0.3",
|
||||||
"@types/react": "^19.1.4",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.1.5",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@types/react-highlight-words": "^0.20.0",
|
"@types/react-highlight-words": "^0.20.1",
|
||||||
"acorn": "^8.14.1",
|
"acorn": "^8.15.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"flexsearch": "^0.8.166",
|
"flexsearch": "^0.8.212",
|
||||||
"framer-motion": "^12.11.3",
|
"framer-motion": "^12.23.26",
|
||||||
"mdast-util-to-string": "^4.0.0",
|
"mdast-util-to-string": "^4.0.0",
|
||||||
"mdx-annotations": "^0.1.4",
|
"mdx-annotations": "^0.1.4",
|
||||||
"next": "^15.3.2",
|
"next": "15.4.10",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"react": "^19.1.0",
|
"qss": "^3.0.0",
|
||||||
"react-dom": "^19.1.0",
|
"react": "^19.2.3",
|
||||||
|
"react-dom": "^19.2.3",
|
||||||
"react-highlight-words": "^0.21.0",
|
"react-highlight-words": "^0.21.0",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"remark-mdx": "^3.1.0",
|
"remark-mdx": "^3.1.1",
|
||||||
"shiki": "^3.4.1",
|
"shiki": "^3.20.0",
|
||||||
"simple-functional-loader": "^1.2.1",
|
"simple-functional-loader": "^1.2.1",
|
||||||
"tailwindcss": "^4.1.6",
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.9.3",
|
||||||
"unist-util-filter": "^5.0.1",
|
"unist-util-filter": "^5.0.1",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "^5.0.0",
|
||||||
"uwuifier": "^4.2.2",
|
"uwuifier": "^4.2.2",
|
||||||
"zustand": "^5.0.4"
|
"zustand": "^5.0.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.9.4",
|
"@biomejs/biome": "^2.3.10",
|
||||||
"@iconify-icon/react": "^3.0.0",
|
"@iconify-icon/react": "^3.0.3",
|
||||||
"@next/bundle-analyzer": "^15.3.2",
|
"@next/bundle-analyzer": "^15.5.4",
|
||||||
"@shikijs/transformers": "^3.4.1",
|
"@shikijs/transformers": "^3.20.0",
|
||||||
"sharp": "^0.34.1"
|
"sharp": "^0.34.5"
|
||||||
},
|
},
|
||||||
"trustedDependencies": ["@biomejs/biome", "sharp"]
|
"trustedDependencies": [
|
||||||
|
"@biomejs/biome",
|
||||||
|
"@tailwindcss/oxide",
|
||||||
|
"sharp"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
125
public/pl.js
125
public/pl.js
|
|
@ -1 +1,124 @@
|
||||||
!function(){"use strict";var l=window.location,i=window.document,t=i.currentScript,r=t.getAttribute("data-api")||new URL(t.src).origin+"/api/event",o=t.getAttribute("data-domain");function s(t,e){t&&console.warn("Ignoring Event: "+t),e&&e.callback&&e.callback()}function e(t,e){if(/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/.test(l.hostname)||"file:"===l.protocol)return s("localhost",e);if((window._phantom||window.__nightmare||window.navigator.webdriver||window.Cypress)&&!window.__plausible)return s(null,e);try{if("true"===window.localStorage.plausible_ignore)return s("localStorage flag",e)}catch(t){}var a={},n=(a.n=t,a.u=l.href,a.d=o,a.r=i.referrer||null,e&&e.meta&&(a.m=JSON.stringify(e.meta)),e&&e.props&&(a.p=e.props),new XMLHttpRequest);n.open("POST",r,!0),n.setRequestHeader("Content-Type","text/plain"),n.send(JSON.stringify(a)),n.onreadystatechange=function(){4===n.readyState&&e&&e.callback&&e.callback({status:n.status})}}var a=window.plausible&&window.plausible.q||[];window.plausible=e;for(var n,p=0;p<a.length;p++)e.apply(this,a[p]);function c(){n!==l.pathname&&(n=l.pathname,e("pageview"))}function u(){c()}var d,t=window.history;t.pushState&&(d=t.pushState,t.pushState=function(){d.apply(this,arguments),u()},window.addEventListener("popstate",u)),"prerender"===i.visibilityState?i.addEventListener("visibilitychange",function(){n||"visible"!==i.visibilityState||c()}):c();var f=1;function w(t){var e,a,n,i,r;function o(){n||(n=!0,window.location=a.href)}"auxclick"===t.type&&t.button!==f||((e=function(t){for(;t&&(void 0===t.tagName||!(e=t)||!e.tagName||"a"!==e.tagName.toLowerCase()||!t.href);)t=t.parentNode;var e;return t}(t.target))&&e.href&&e.href.split("?")[0],(r=e)&&r.href&&r.host&&r.host!==l.host&&(r=t,t={name:"Outbound Link: Click",props:{url:(a=e).href}},n=!1,!function(t,e){if(!t.defaultPrevented)return e=!e.target||e.target.match(/^_(self|parent|top)$/i),t=!(t.ctrlKey||t.metaKey||t.shiftKey)&&"click"===t.type,e&&t}(r,a)?(i={props:t.props},plausible(t.name,i)):(i={props:t.props,callback:o},plausible(t.name,i),setTimeout(o,5e3),r.preventDefault())))}i.addEventListener("click",w),i.addEventListener("auxclick",w)}();
|
!(function () {
|
||||||
|
var l = window.location,
|
||||||
|
i = window.document,
|
||||||
|
t = i.currentScript,
|
||||||
|
r = t.getAttribute("data-api") || new URL(t.src).origin + "/api/event",
|
||||||
|
o = t.getAttribute("data-domain");
|
||||||
|
function s(t, e) {
|
||||||
|
t && console.warn("Ignoring Event: " + t),
|
||||||
|
e && e.callback && e.callback();
|
||||||
|
}
|
||||||
|
function e(t, e) {
|
||||||
|
if (
|
||||||
|
/^localhost$|^127(\.[0-9]+){0,2}\.[0-9]+$|^\[::1?\]$/.test(
|
||||||
|
l.hostname,
|
||||||
|
) ||
|
||||||
|
"file:" === l.protocol
|
||||||
|
)
|
||||||
|
return s("localhost", e);
|
||||||
|
if (
|
||||||
|
(window._phantom ||
|
||||||
|
window.__nightmare ||
|
||||||
|
window.navigator.webdriver ||
|
||||||
|
window.Cypress) &&
|
||||||
|
!window.__plausible
|
||||||
|
)
|
||||||
|
return s(null, e);
|
||||||
|
try {
|
||||||
|
if ("true" === window.localStorage.plausible_ignore)
|
||||||
|
return s("localStorage flag", e);
|
||||||
|
} catch (t) {}
|
||||||
|
var a = {},
|
||||||
|
n =
|
||||||
|
((a.n = t),
|
||||||
|
(a.u = l.href),
|
||||||
|
(a.d = o),
|
||||||
|
(a.r = i.referrer || null),
|
||||||
|
e && e.meta && (a.m = JSON.stringify(e.meta)),
|
||||||
|
e && e.props && (a.p = e.props),
|
||||||
|
new XMLHttpRequest());
|
||||||
|
n.open("POST", r, !0),
|
||||||
|
n.setRequestHeader("Content-Type", "text/plain"),
|
||||||
|
n.send(JSON.stringify(a)),
|
||||||
|
(n.onreadystatechange = () => {
|
||||||
|
4 === n.readyState &&
|
||||||
|
e &&
|
||||||
|
e.callback &&
|
||||||
|
e.callback({ status: n.status });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var a = (window.plausible && window.plausible.q) || [];
|
||||||
|
window.plausible = e;
|
||||||
|
for (var n, p = 0; p < a.length; p++) e.apply(this, a[p]);
|
||||||
|
function c() {
|
||||||
|
n !== l.pathname && ((n = l.pathname), e("pageview"));
|
||||||
|
}
|
||||||
|
function u() {
|
||||||
|
c();
|
||||||
|
}
|
||||||
|
var d,
|
||||||
|
t = window.history;
|
||||||
|
t.pushState &&
|
||||||
|
((d = t.pushState),
|
||||||
|
(t.pushState = function () {
|
||||||
|
d.apply(this, arguments), u();
|
||||||
|
}),
|
||||||
|
window.addEventListener("popstate", u)),
|
||||||
|
"prerender" === i.visibilityState
|
||||||
|
? i.addEventListener("visibilitychange", () => {
|
||||||
|
n || "visible" !== i.visibilityState || c();
|
||||||
|
})
|
||||||
|
: c();
|
||||||
|
var f = 1;
|
||||||
|
function w(t) {
|
||||||
|
var e, a, n, i, r;
|
||||||
|
function o() {
|
||||||
|
n || ((n = !0), (window.location = a.href));
|
||||||
|
}
|
||||||
|
("auxclick" === t.type && t.button !== f) ||
|
||||||
|
((e = ((t) => {
|
||||||
|
for (
|
||||||
|
;
|
||||||
|
t &&
|
||||||
|
(void 0 === t.tagName ||
|
||||||
|
!(e = t) ||
|
||||||
|
!e.tagName ||
|
||||||
|
"a" !== e.tagName.toLowerCase() ||
|
||||||
|
!t.href);
|
||||||
|
)
|
||||||
|
t = t.parentNode;
|
||||||
|
var e;
|
||||||
|
return t;
|
||||||
|
})(t.target)) &&
|
||||||
|
e.href &&
|
||||||
|
e.href.split("?")[0],
|
||||||
|
(r = e) &&
|
||||||
|
r.href &&
|
||||||
|
r.host &&
|
||||||
|
r.host !== l.host &&
|
||||||
|
((r = t),
|
||||||
|
(t = {
|
||||||
|
name: "Outbound Link: Click",
|
||||||
|
props: { url: (a = e).href },
|
||||||
|
}),
|
||||||
|
(n = !1),
|
||||||
|
!((t, e) => {
|
||||||
|
if (!t.defaultPrevented)
|
||||||
|
return (
|
||||||
|
(e =
|
||||||
|
!e.target ||
|
||||||
|
e.target.match(/^_(self|parent|top)$/i)),
|
||||||
|
(t =
|
||||||
|
!(t.ctrlKey || t.metaKey || t.shiftKey) &&
|
||||||
|
"click" === t.type),
|
||||||
|
e && t
|
||||||
|
);
|
||||||
|
})(r, a)
|
||||||
|
? ((i = { props: t.props }), plausible(t.name, i))
|
||||||
|
: ((i = { props: t.props, callback: o }),
|
||||||
|
plausible(t.name, i),
|
||||||
|
setTimeout(o, 5e3),
|
||||||
|
r.preventDefault())));
|
||||||
|
}
|
||||||
|
i.addEventListener("click", w), i.addEventListener("auxclick", w);
|
||||||
|
})();
|
||||||
|
|
|
||||||
|
|
@ -143,12 +143,16 @@
|
||||||
.prose [class*="language-"] .has-focused .line:not(.focused) {
|
.prose [class*="language-"] .has-focused .line:not(.focused) {
|
||||||
filter: blur(0.095rem);
|
filter: blur(0.095rem);
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
transition: filter 0.35s, opacity 0.35s;
|
transition:
|
||||||
|
filter 0.35s,
|
||||||
|
opacity 0.35s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose [class*="language-"] .has-focused .line:not(.focused) {
|
.prose [class*="language-"] .has-focused .line:not(.focused) {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
transition: filter 0.35s, opacity 0.35s;
|
transition:
|
||||||
|
filter 0.35s,
|
||||||
|
opacity 0.35s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose [class*="language-"]:hover .has-focused .line:not(.focused) {
|
.prose [class*="language-"]:hover .has-focused .line:not(.focused) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue