diff --git a/app/api/basics/page.mdx b/app/api/basics/page.mdx new file mode 100644 index 0000000..78e6591 --- /dev/null +++ b/app/api/basics/page.mdx @@ -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. + + + 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. + + +## 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. + + + 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. + + +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 +``` \ No newline at end of file diff --git a/app/api/endpoints/page.mdx b/app/api/endpoints/page.mdx new file mode 100644 index 0000000..22d95b1 --- /dev/null +++ b/app/api/endpoints/page.mdx @@ -0,0 +1,238 @@ +export const metadata = { + title: "API Endpoints", + description: "Explains all endpoints in Versia's federation API.", +} + +# Endpoints + +## Well-known + + + 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` + + + + + + + + Must be `/.well-known/versia`. + + + Must be `GET`. + + + A small JSON object with a single attribute: + + - `versions`: Supported Versia Protocol versions. + - Versions marked as "Working Draft X" are represented as `0.X`. + + + + + + + ```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" + ] + } + ``` + + + + +## Instance metadata + + + This endpoint is exempt from the signature requirement. No signatures are required for requests or responses to it. + + + + + + + + Must be `/.versia/v0.6/instance`. + + + Must be `GET`. + + + Instance's metadata, as defined in the [Instance Metadata](/entities/instance-metadata) document. + + + + + + + ```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!!", + // ... + } + ``` + + + + +## Entity data + + + + + + 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`. + + + Must be `GET`. + + + Entity data as JSON, as defined in its [Entity](/entities) definition document. + + + + + + + ```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", + // ... + } + ``` + + + +## Entity collections + + + + + + 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`. + + + Must be `GET`. + + + Must be either a [Collection](/structures/collection) or a [URICollection](/structures/collection#uri-collection) as JSON. + + + + + + + ```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", + // ... + } + ``` + + + +### 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. + + + + + + Must be `/.versia/v0.6/inbox`. + + + Must be `POST`. + + + + + + + ```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", + ... + } + ``` + + + \ No newline at end of file diff --git a/app/changelog/page.mdx b/app/changelog/page.mdx index ac5a2fa..4147243 100644 --- a/app/changelog/page.mdx +++ b/app/changelog/page.mdx @@ -8,6 +8,27 @@ export const metadata = { 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 - Removed URI from [Report](/extensions/reports), and replaced `reason` with `tags`. diff --git a/app/entities/delete/page.mdx b/app/entities/delete/page.mdx index ba9b3f6..cf71d3f 100644 --- a/app/entities/delete/page.mdx +++ b/app/entities/delete/page.mdx @@ -5,32 +5,33 @@ export const metadata = { # 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 Implementations **must** ensure that the author of the `Delete` entity has the authorization to delete the target entity. 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. ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a 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). + + [Reference](/types#reference) to the `User` who is deleting the entity. Type of the entity being deleted. - - URI of the entity being deleted. + + [Reference](/types#reference) to the entity being deleted. @@ -40,11 +41,10 @@ Having the authorization is defined as: ```jsonc {{ title: 'Example Delete' }} { "type": "Delete", - "id": "9b3212b8-529c-435a-8798-09ebbc17ca74", "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": "https://example.com/notes/02e1e3b2-cb1f-4e4a-b82e-98866bee5de7" + "deleted": "02e1e3b2-cb1f-4e4a-b82e-98866bee5de7" } ``` diff --git a/app/entities/follow-accept/page.mdx b/app/entities/follow-accept/page.mdx index 103b4b0..1e7f0f5 100644 --- a/app/entities/follow-accept/page.mdx +++ b/app/entities/follow-accept/page.mdx @@ -11,17 +11,18 @@ export const metadata = { ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the `User` considered the 'followee', i.e. the user who is being followed. + + [Reference](/types#reference) to the `User` considered the 'followee', i.e. the user who is being followed. - - URI of the `User` considered the 'follower', i.e. the user who is trying to follow the author. + + [Reference](/types#reference) to the `User` considered the 'follower', i.e. the user who is trying to follow the author. @@ -31,10 +32,9 @@ export const metadata = { ```jsonc {{ title: 'Example FollowAccept' }} { "type": "FollowAccept", - "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", "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" } ``` diff --git a/app/entities/follow-reject/page.mdx b/app/entities/follow-reject/page.mdx index 7492789..abf9710 100644 --- a/app/entities/follow-reject/page.mdx +++ b/app/entities/follow-reject/page.mdx @@ -21,17 +21,18 @@ But it can also be used when Bob is already following Alice, in the case that: ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the `User` considered the 'followee', i.e. the user who is being followed. + + [Reference](/types#reference) to the `User` considered the 'followee', i.e. the user who is being followed. - - URI of the `User` considered the 'follower', i.e. the user who is trying to follow the author. + + [Reference](/types#reference) to the `User` considered the 'follower', i.e. the user who is trying to follow the author. @@ -41,10 +42,9 @@ But it can also be used when Bob is already following Alice, in the case that: ```jsonc {{ title: 'Example FollowReject' }} { "type": "FollowReject", - "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", "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" } ``` diff --git a/app/entities/follow/page.mdx b/app/entities/follow/page.mdx index 2b9e17f..72b8764 100644 --- a/app/entities/follow/page.mdx +++ b/app/entities/follow/page.mdx @@ -53,17 +53,18 @@ Once a follow relationship is established, the **followee**'s instance should se ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the `User` considered the 'follower'. + + [Reference](/types#reference) to the `User` considered the 'follower'. - - URI of the `User` that is being followed. + + [Reference](/types#reference) to the `User` that is being followed. @@ -73,10 +74,9 @@ Once a follow relationship is established, the **followee**'s instance should se ```jsonc {{ title: 'Example Follow' }} { "type": "Follow", - "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", "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" } ``` diff --git a/app/entities/instance-metadata/page.mdx b/app/entities/instance-metadata/page.mdx index 4232622..8fae58c 100644 --- a/app/entities/instance-metadata/page.mdx +++ b/app/entities/instance-metadata/page.mdx @@ -7,12 +7,6 @@ export const metadata = { 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 @@ -21,9 +15,6 @@ Check the entity's documentation page to see if it supports this (it will be not This entity does not have an ID. - - This entity does not have a URI. - Friendly name of the instance, for humans. @@ -57,11 +48,8 @@ Check the entity's documentation page to see if it supports this (it will be not Long description of the instance, for humans. Should be around 100-200 words. - - Hostname of the instance. Includes the port if it is not the default (i.e. `443` for HTTPS). - - - URI to the instance's shared inbox, if supported. + + Domain of the instance, used for federation. 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. - `key`: Instance public key, in [SPKI-encoded base64](/signatures#exporting-the-public-key). - - URI to [Collection](/structures/collection) of instance moderators. - - - This is for human consumption (such as moderator contact), not for any kind of protocol authorization. - - - - URI to [Collection](/structures/collection) of instance administrators. - - - This is for human consumption (such as admin contact), not for any kind of protocol authorization. - - Logo of the instance. Must be an image format (`image/*`). @@ -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.", - "host": "social.jimjams.com", - "shared_inbox": "https://social.jimjams.com/inbox", - "moderators": "https://social.jimjams.com/moderators", - "admins": "https://social.jimjams.com/admins", + "domain": "social.jimjams.com", "logo": { "image/png": { "content": "https://social.jimjams.com/files/logo.png" @@ -147,4 +118,13 @@ Check the entity's documentation page to see if it supports this (it will be not ``` - \ No newline at end of file + + +### 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) \ No newline at end of file diff --git a/app/entities/note/page.mdx b/app/entities/note/page.mdx index 2227f4c..91c717b 100644 --- a/app/entities/note/page.mdx +++ b/app/entities/note/page.mdx @@ -16,11 +16,11 @@ Notes represent a piece of content on a Versia instance. They can be posted by [ - + Media attachments to the note. May be any format. **Must** be remote. - - URI of the `User` considered the author of the note. + + [Reference](/types#reference) to the `User` considered the author of the note. 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 ``` - - 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. - The content of the note. Must be text format (`text/html`, `text/markdown`, etc). Must not be remote. @@ -72,8 +50,8 @@ Notes represent a piece of content on a Versia instance. They can be posted by [ } ``` - - 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. - `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`. - + Whether the note contains "sensitive content". This can be used with `subject` as a "content warning" feature. - - 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. - + 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 @@ -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. - - 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. - - 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. 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", "type": "Note", - "uri": "https://versia.social/objects/01902e09-0f8b-72de-8ee3-9afc0cf5eae1", "created_at": "2024-06-19T01:07:44.139Z", "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", "remote": true, "thumbhash": "1QcSHQRnh493V4dIh4eXh1h4kJUI", + "description": null, + "fps": null, + "duration": null, "height": 960, "size": 221275, "hash": { @@ -143,6 +123,12 @@ Notes represent a piece of content on a Versia instance. They can be posted by [ "text/plain": { "content": "https://cdn.lysand.org/68c02dd11c179ef4d170b05393f6e72133dd0ad733f40d41b42363d8784e8d5d/fire.txt", "remote": true, + "description": null, + "thumbhash": null, + "width": null, + "height": null, + "fps": null, + "duration": null "size": 8, "hash": { "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", - "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": { "text/html": { "content": "

In the next versia-fe update: account settings, finally!

" @@ -180,9 +159,21 @@ Notes represent a piece of content on a Versia instance. They can be posted by [ "group": "public", "is_sensitive": false, "mentions": [], - "subject": "Versia development" + "subject": "Versia development", + "previews": [], + "quotes": null, + "replies_to": null } ```
+ +### 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) \ No newline at end of file diff --git a/app/entities/page.mdx b/app/entities/page.mdx index b4bb253..3ffdcb4 100644 --- a/app/entities/page.mdx +++ b/app/entities/page.mdx @@ -6,36 +6,39 @@ export const metadata = { # 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. -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. - 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). Type of the entity. Custom types must follow [Extension Naming](/extensions#naming). - + Date and time when the entity was created. Must be an [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) timestamp. - Handling of dates that are valid but obviously incorrect (e.g. in the future) is left to the Implementation's discretion. - - - - URI of the entity. Should be unique and resolve to the entity. Must be an absolute URI. - - - [**Transient Entities**](/entities#transient-entities) do not require a URI. + 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. @@ -56,12 +59,11 @@ Any field in an entity not marked as `required` may be omitted or set to `null`. ```jsonc {{ 'title': 'Example 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_type": "Note", - "deleted": "https://bongo.social/notes/54059ce2-9332-46fa-bf6a-598b5493b81b", + "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", + "type": "pub.versia:likes/Like", + "created_at": "2021-01-01T00:00:00.000Z", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", + "liked": "otherexample.org:fmKZ763jzIU8" } ``` @@ -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", "type": "org.space:Zlorbs/Zlorb", "created_at": "2023-04-13T08:00:00Z", - "uri": "https://space.org/zlorbs/f0aacf0b-df7a-4ee5-a2ba-6c4acafd8642", "extensions": { // [!code focus:100] "org.space:zlorbs": { "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 -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. - -Implementations **must not** rely on other implementations to store transient entities in their database. - -## Serialization +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. -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). \ No newline at end of file +Implementations **must not** rely on other implementations to store transient entities in their database. \ No newline at end of file diff --git a/app/entities/unfollow/page.mdx b/app/entities/unfollow/page.mdx index a155516..d735321 100644 --- a/app/entities/unfollow/page.mdx +++ b/app/entities/unfollow/page.mdx @@ -26,17 +26,18 @@ Sometimes, [Users](/entities/user) want to unsubscribe from each other to stop s ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - 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 'follower', i.e. the user who is unsubscribing from the followee. - - URI of the `User` considered the 'followee', i.e. the user who is being unsubscribed from. + + [Reference](/types#reference) to the `User` considered the 'followee', i.e. the user who is being unsubscribed from. @@ -46,10 +47,9 @@ Sometimes, [Users](/entities/user) want to unsubscribe from each other to stop s ```jsonc {{ title: 'Example Unfollow' }} { "type": "Unfollow", - "id": "3e7e4750-afd4-4d99-a256-02f0710a0520", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", "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" } ``` diff --git a/app/entities/user/page.mdx b/app/entities/user/page.mdx index f3141d1..c5d6e1f 100644 --- a/app/entities/user/page.mdx +++ b/app/entities/user/page.mdx @@ -35,7 +35,7 @@ Usernames can be changed by the user, so it is recommended to use `id` for long- ### 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 @@ -52,7 +52,7 @@ Instance **must** be the host of the instance the user is on (hostname with opti Display name, as shown to other users. May contain emojis and any Unicode character. - + Custom key/value pairs. For example, metadata like socials or pronouns. Must be text format (`text/*`). ```typescript @@ -70,63 +70,11 @@ Instance **must** be the host of the instance the user is on (hostname with opti A header image for the user's profile. Also known as a cover photo or a banner. Must be an image format (`image/*`). - - 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)). - - - `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; - } - ``` - - - 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`. + + 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. - - User consent to be indexed by search engines. If `false`, the user's profile should not be indexed. Defaults to `true`. - - - 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. - - - 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. + + User consent to be indexed by search engines. If `false`, the user's profile should not be indexed. @@ -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", "type": "User", - "uri": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771", "created_at": "2024-04-09T01:38:51.743Z", "avatar": { // [!code focus:100] "image/png": { @@ -152,14 +99,6 @@ Instance **must** be the host of the instance the user is on (hostname with opti "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)", "extensions": { "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, - "inbox": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/inbox", "indexable": false, "manually_approves_followers": false, - "public_key": { - "actor": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771", - "algorithm": "ed25519", - "key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - }, "username": "aprl" } ``` + +### 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) \ No newline at end of file diff --git a/app/extensions/custom-emojis/page.mdx b/app/extensions/custom-emojis/page.mdx index f6d3a18..86c5bd3 100644 --- a/app/extensions/custom-emojis/page.mdx +++ b/app/extensions/custom-emojis/page.mdx @@ -15,7 +15,11 @@ The Custom Emojis extension adds support for adding personalized emojis to feder 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. @@ -34,7 +38,7 @@ The Custom Emojis extension adds support for adding personalized emojis to feder "image/webp": { "content": "https://cdn.example.com/emojis/happy_face.webp", "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", "type": "Note", - "uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd", "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": { "text/plain": { "content": "Hello, world :happy_face:!" } }, - "extensions": { // [!code focus:16] + ... + "extensions": { // [!code focus:23] "pub.versia:custom_emojis": { "emojis": [ { @@ -105,7 +105,7 @@ Custom Emojis can be added to any entity with text content. The extension ID is "image/webp": { "content": "https://cdn.example.com/emojis/happy_face.webp", "remote": true, - "description": "A happy emoji smiling.", + "description": "A happy emoji smiling." } } } diff --git a/app/extensions/delegation/page.mdx b/app/extensions/delegation/page.mdx new file mode 100644 index 0000000..3ec8480 --- /dev/null +++ b/app/extensions/delegation/page.mdx @@ -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. + + + 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. + + +## 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: + + + + + If this user performs actions on behalf on another user, **MUST** have a reference to that user. + + + If other users perform actions on behalf of this user, **MUST** have a list of references to all such users. + + + + + + + ```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" + ] + } + } + } + ``` + + + diff --git a/app/extensions/groups/page.mdx b/app/extensions/groups/page.mdx index 5a41f78..bbfb469 100644 --- a/app/extensions/groups/page.mdx +++ b/app/extensions/groups/page.mdx @@ -27,7 +27,7 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not Text only (`text/plain`, `text/html`, etc). - + Whether the group is open to all users or requires approval to join. @@ -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. - - URI of the group's members list. [URI Collection](/structures/collection#uri-collection) of [Users](/entities/user). - - - URI of the group's associated notes. [URI Collection](/structures/collection#uri-collection) of [Notes](/entities/note). - @@ -51,7 +45,6 @@ Refer to [Note](/entities/note#entity-definition)'s `group` property for how not { "type": "pub.versia:groups/Group", "id": "ed480922-b095-4f09-9da5-c995be8f5960", - "uri": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", "name": { "text/html": { "content": "The Woozy 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." } }, - "open": false, - "members": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960/members", + "open": false } ```
+### 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 [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. + + This entity is a [**Transient Entity**](/entities#transient-entities). + + Must be `pub.versia:groups/Subscribe`. - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the [User](/entities/user) subscribing to the group. + + [Reference](/types#reference) to the [User](/entities/user) subscribing to the group. - - URI of the group to subscribe to. + + [Reference](/types#reference) to the group to subscribe to. @@ -105,9 +107,8 @@ Indicates that a [User](/entities/user) wishes to subscribe to a group. ```jsonc {{ title: "Example GroupSubscribe" }} { "type": "pub.versia:groups/Subscribe", - "id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0", - "subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc", - "group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", + "subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc", + "group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960", "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. + + This entity is a [**Transient Entity**](/entities#transient-entities). + + Must be `pub.versia:groups/Unsubscribe`. - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the [User](/entities/user) unsubscribing from the group. + + [Reference](/types#reference) to the [User](/entities/user) unsubscribing from the group. - - URI of the group to unsubscribe from. + + [Reference](/types#reference) to the group to unsubscribe from. @@ -142,9 +144,8 @@ Indicates that a [User](/entities/user) wishes to unsubscribe from a group. ```jsonc {{ title: "Example GroupUnsubscribe" }} { "type": "pub.versia:groups/Unsubscribe", - "id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0", - "subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc", - "group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", + "subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc", + "group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960", "created_at": "2021-01-01T00:00:00Z" } ``` @@ -154,7 +155,11 @@ Indicates that a [User](/entities/user) wishes to unsubscribe from a group. ### 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. + + + This entity is a [**Transient Entity**](/entities#transient-entities). + @@ -162,14 +167,11 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use Must be `pub.versia:groups/SubscribeAccept`. - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the [User](/entities/user) subscribing to the group. + + [Reference](/types#reference) to the [User](/entities/user) subscribing to the group. - - URI of the group that accepted the subscription. + + [Reference](/types#reference) to the group that accepted the subscription. @@ -179,9 +181,8 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use ```jsonc {{ title: "Example GroupSubscribeAccept" }} { "type": "pub.versia:groups/SubscribeAccept", - "id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0", - "subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc", - "group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", + "subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc", + "group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960", "created_at": "2021-01-01T00:00:00Z" } ``` @@ -191,7 +192,11 @@ Indicates that a [Group](#entity-definition) has accepted a [User](/entities/use ### 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. + + + This entity is a [**Transient Entity**](/entities#transient-entities). + @@ -199,14 +204,11 @@ Indicates that a [Group](#entity-definition) has rejected a [User](/entities/use Must be `pub.versia:groups/SubscribeReject`. - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the [User](/entities/user) subscribing to the group. + + [Reference](/types#reference) to the [User](/entities/user) subscribing to the group. - - URI of the group that rejected the subscription. + + [Reference](/types#reference) to the group that rejected the subscription. @@ -216,9 +218,8 @@ Indicates that a [Group](#entity-definition) has rejected a [User](/entities/use ```jsonc {{ title: "Example GroupSubscribeReject" }} { "type": "pub.versia:groups/SubscribeReject", - "id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0", - "subscriber": "https://bob.social/users/e9277471-8aa1-4d40-a3d0-0878e818ccdc", - "group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", + "subscriber": "e9277471-8aa1-4d40-a3d0-0878e818ccdc", + "group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960", "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. -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). ### 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. + + + This entity is a [**Transient Entity**](/entities#transient-entities). + @@ -244,14 +249,11 @@ The `GroupFederate` entity allows a group to federate a note to all of its membe Must be `pub.versia:groups/Federate`. - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - - - URI of the note to federate. + + [Reference](/types#reference) to the note to federate. - - URI of the group federating the note. + + [Reference](/types#reference) to the group federating the note. @@ -261,9 +263,8 @@ The `GroupFederate` entity allows a group to federate a note to all of its membe ```jsonc {{ title: "Example GroupFederate" }} { "type": "pub.versia:groups/Federate", - "id": "9a7e9345-4e4a-4d5a-8301-4dbbfe777ca0", - "note": "https://example.com/notes/ed480922-b095-4f09-9da5-c995be8f5960", - "group": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", + "note": "c5aa65fa-0356-4029-b61c-6b237e5d1393", + "group": "example.com:ed480922-b095-4f09-9da5-c995be8f5960", "created_at": "2021-01-01T00:00:00Z" } ``` diff --git a/app/extensions/instance-messaging/page.mdx b/app/extensions/instance-messaging/page.mdx index 794d1a7..9a13a4b 100644 --- a/app/extensions/instance-messaging/page.mdx +++ b/app/extensions/instance-messaging/page.mdx @@ -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. -## Instance Metadata Extensions -This extension adds the following metadata to instances: +## Sending Messages - - - - - The endpoint to send federation debug messages to. +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. - ### 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. +Reasons: + - `username` must be alphanumeric. Found invalid character `@`. +``` - ```text {{ "title": "Helpful Message" }} - Validation failed for https://jane.org/users/nkGEd8eI98. - Reasons: - - `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" }} - Federation failed. - ``` - - - - - - - ```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", - }, - } - } - ``` - - - \ No newline at end of file +```text {{ "title": "Unhelpful Message" }} +Federation failed. +``` \ No newline at end of file diff --git a/app/extensions/interaction-controls/page.mdx b/app/extensions/interaction-controls/page.mdx index 96bbeea..f81bfcb 100644 --- a/app/extensions/interaction-controls/page.mdx +++ b/app/extensions/interaction-controls/page.mdx @@ -15,17 +15,13 @@ The entity defined in this document must be inserted in the `pub.versia:interact { "id": "456df8ed-daf1-4062-abab-491071c7b8dd", "type": "Note", - "uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd", "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": { "text/plain": { "content": "Hello, world :happy_face:!" } }, + ... "extensions": { // [!code focus:9] "pub.versia:interaction_controls": { "reply": { @@ -104,7 +100,7 @@ Extensions **may** choose to register their own interaction types (such as `pub. ### 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. diff --git a/app/extensions/likes/page.mdx b/app/extensions/likes/page.mdx index 403e6e7..546aa30 100644 --- a/app/extensions/likes/page.mdx +++ b/app/extensions/likes/page.mdx @@ -22,11 +22,11 @@ Likes are a way for users to show appreciation for a note, like Twitter's "heart Must be `pub.versia:likes/Like`. - - Creator of the Like. + + [Reference](/types#reference) to the creator of the Like. - - URI of the note being liked. Must link to a [Note](/entities/note). + + [Reference](/types#reference) to the note being liked. @@ -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", "type": "pub.versia:likes/Like", "created_at": "2021-01-01T00:00:00.000Z", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", - "uri": "https://example.com/likes/3e7e4750-afd4-4d99-a256-02f0710a0520", - "liked": "https://otherexample.org/notes/fmKZ763jzIU8" + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", + "liked": "otherexample.org:fmKZ763jzIU8" } ``` @@ -59,11 +58,11 @@ Dislikes are a way for users to show disapproval for a note, like YouTube's "dis Must be `pub.versia:likes/Dislike`. - - Creator of the Dislike. + + [Reference](/types#reference) to the creator of the Dislike. - - URI of the note being disliked. Must link to a [Note](/entities/note). + + [Reference](/types#reference) to the note being disliked. @@ -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", "type": "pub.versia:likes/Dislike", "created_at": "2021-01-01T00:00:00.000Z", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", - "uri": "https://example.com/dislikes/3e7e4750-afd4-4d99-a256-02f0710a0520", - "disliked": "https://otherexample.org/notes/fmKZ763jzIU8" + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", + "disliked": "otherexample.org: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: -- `likes`: A [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. - -```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" - } -} -``` +- `pub.versia:likes/Likes`: [URI Collection](/structures/collection#uri-collection) of all the notes the user has liked. +- `pub.versia:likes/Dislikes`: [URI Collection](/structures/collection#uri-collection) of all the notes the user has disliked. ## Note Collections 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. -- `dislikes`: A [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" - } -} -``` +- `pub.versia:likes/Likes`: [URI Collection](/structures/collection#uri-collection) of all the likes the note has received. +- `pub.versia:likes/Dislikes`: [URI Collection](/structures/collection#uri-collection) of all the dislikes the note has received. ## Interaction Types diff --git a/app/extensions/migration/page.mdx b/app/extensions/migration/page.mdx index b52376b..4b917ff 100644 --- a/app/extensions/migration/page.mdx +++ b/app/extensions/migration/page.mdx @@ -30,20 +30,21 @@ Migration happens in three steps: ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - Must be `pub.versia:migration/Migration`. - - URI of the [User](/entities/user) who is migrating. + + [Reference](/types#reference) to the [User](/entities/user) who is migrating. - - URI of the destination [User](/entities/user) on the new instance. + + [Reference](/types#reference) to the destination [User](/entities/user) on the new instance. @@ -52,11 +53,10 @@ Migration happens in three steps: ```json {{ title: "Example Entity" }} { - "id": "016f3de2-ad63-4e06-999e-1e6b41c981c5", "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", - "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 - - 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. - - 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. @@ -88,8 +88,8 @@ The following extensions to [User](/entities/user) are used by the migration ext // ... "extensions": { // [!code focus:100] "pub.versia:migration": { - "previous": "https://oldinstance.social/users/44df6e02-ef43-47e0-aff2-47041f3d09ed", - // "new": "https://newinstance.social/users/73e999a0-53d0-40a3-a5cc-be0408004726", + "previous": "oldinstance.social:44df6e02-ef43-47e0-aff2-47041f3d09ed", + // "new": "newinstance.social:73e999a0-53d0-40a3-a5cc-be0408004726", } } } diff --git a/app/extensions/page.mdx b/app/extensions/page.mdx index d3ba1f3..8dd3c67 100644 --- a/app/extensions/page.mdx +++ b/app/extensions/page.mdx @@ -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' }} -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. @@ -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: - 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" }} pub.versia:likes @@ -30,7 +30,7 @@ pub.versia:likes ### Custom entities 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" }} 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. - `key`: The extension name. - - `value`: Extension data. Can be any JSON-serializable data. - - Extension data can be any JSON-serializable data. + - `value`: Extension data. Can be any JSON object, following [Versia JSON rules](/json). @@ -61,10 +59,9 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)' { "type": "pub.versia:groups/Group", "id": "ed480922-b095-4f09-9da5-c995be8f5960", - "uri": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960", "name": null, "description": null, - "members": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960/members", + "open": true, "extensions": { // [!code focus:100] "com.example:gps": { "location": { @@ -87,12 +84,12 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)' - The extension type. [Must follow naming conventions](#naming). + The extension type, [following naming conventions](#naming). 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. @@ -102,8 +99,7 @@ Extensions can be found in two places: an [Entity](/entities#entity-definition)' { "type": "com.example:poll/Poll", "id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9", - "uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", "created_at": "2021-01-01T00:00:00.000Z", "question": "What is your favourite colour?", "options": [ diff --git a/app/extensions/polls/page.mdx b/app/extensions/polls/page.mdx index cb671a7..d07ef97 100644 --- a/app/extensions/polls/page.mdx +++ b/app/extensions/polls/page.mdx @@ -29,7 +29,7 @@ Note that there is no `question` field: the question should be included in the ` Whether the poll allows multiple votes to be cast for different options. - + RFC 3339 timestamp of when the poll ends and no more votes can be cast. If not present, the poll does not expire. @@ -41,19 +41,15 @@ Note that there is no `question` field: the question should be included in the ` { "id": "01902e09-0f8b-72de-8ee3-9afc0cf5eae1", "type": "Note", // [!code focus] - "uri": "https://versia.social/notes/01902e09-0f8b-72de-8ee3-9afc0cf5eae1", "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", - "collections": { - "replies": "https://versia.social/notes/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/replies", - "quotes": "https://versia.social/notes/01902e09-0f8b-72de-8ee3-9afc0cf5eae1/quotes" - }, "content": { "text/plain": { "content": "What is your favourite color?" } }, + ... "extensions": { // [!code focus:28] "pub.versia:polls": { "options": [ @@ -102,11 +98,11 @@ If a vote is cast to a poll that is closed, the vote should be rejected with a ` Must be `pub.versia:polls/Vote`. - - URI to the user who cast the vote. + + [Reference](/types#reference) of the user who cast the vote. - - 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. 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", "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", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3] - "poll": "https://example.com/notes/f08a124e-fe90-439e-8be4-15a428a72a19", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3] + "poll": "example.com:f08a124e-fe90-439e-8be4-15a428a72a19", "option": 1 } ``` diff --git a/app/extensions/reactions/page.mdx b/app/extensions/reactions/page.mdx index eaad613..110f569 100644 --- a/app/extensions/reactions/page.mdx +++ b/app/extensions/reactions/page.mdx @@ -19,11 +19,11 @@ User reactions are (like every other entity) federated to all followers, and can Must be `pub.versia:reactions/Reaction`. - - URI of the [User](/entities/user) that is reacting. + + [Reference](/types#reference) to the [User](/entities/user) that is reacting. - - URI of the [Note](/entities/note) attached to the reaction. + + [Reference](/types#reference) to the [Note](/entities/note) attached to the reaction. 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", "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", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3] - "object": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19", + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", // [!code focus:3] + "object": "example.com:f08a124e-fe90-439e-8be4-15a428a72a19", "content": "😀", } ``` @@ -52,20 +51,9 @@ User reactions are (like every other entity) federated to all followers, and can ## 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. - -```jsonc -{ - "type": "Note", - ... - "collections": { - ... - "pub.versia:reactions/Reactions": "https://example.com/publications/f08a124e-fe90-439e-8be4-15a428a72a19/reactions" - } -} -``` +- `pub.versia:reactions/Reactions`: [URI Collection](/structures/collection#uri-collection) of all the reactions to the note. ## Interaction Types diff --git a/app/extensions/reports/page.mdx b/app/extensions/reports/page.mdx index a1bf22e..d24b53d 100644 --- a/app/extensions/reports/page.mdx +++ b/app/extensions/reports/page.mdx @@ -11,20 +11,21 @@ When an instance receives a report, it *should* be reviewed by a moderator or ad ## Entity Definition + + This entity is a [**Transient Entity**](/entities#transient-entities). + + - - This is a [**Transient Entity**](/entities#transient-entities) and does not have a URI. - Must be `pub.versia:reports/Report`. - - 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. - - URIs of the content being reported. + + [References](/types#reference) to the content being reported. 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" }} { - "id": "6f3001a1-641b-4763-a9c4-a089852eec84", "type": "pub.versia:reports/Report", - "author": "https://example.com/users/6f3001a1-641b-4763-a9c4-a089852eec84", + "author": "6f3001a1-641b-4763-a9c4-a089852eec84", "reported": [ - "https://test.com/publications/46f936a3-9a1e-4b02-8cde-0902a89769fa", - "https://test.com/publications/213d7c56-fb9b-4646-a4d2-7d70aa7d106a" + "test.com:46f936a3-9a1e-4b02-8cde-0902a89769fa", + "test.com:213d7c56-fb9b-4646-a4d2-7d70aa7d106a" ], "tags": [ "spam", diff --git a/app/extensions/share/page.mdx b/app/extensions/share/page.mdx index fa38799..02b862b 100644 --- a/app/extensions/share/page.mdx +++ b/app/extensions/share/page.mdx @@ -21,11 +21,11 @@ When a user shares a note, the note's original author **must** receive the entit Must be `pub.versia:share/Share`. - - Creator of the Share. + + [Reference](/types#reference) to the creator of the Share. - - URI of the note being shared. Must link to a [Note](/entities/note). + + [Reference](/types#reference) to the note being shared. @@ -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", "type": "pub.versia:share/Share", "created_at": "2021-01-01T00:00:00.000Z", - "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe", - "uri": "https://example.com/shares/3e7e4750-afd4-4d99-a256-02f0710a0520", - "shared": "https://otherexample.org/notes/fmKZ763jzIU8" + "author": "6e0204a2-746c-4972-8602-c4f37fc63bbe", + "shared": "otherexample.org: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: -- `shares`: A [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" - } -} -``` +- `pub.versia:share/Shares`: [URI Collection](/structures/collection#uri-collection) of all the shares of the note. ## Interaction Types diff --git a/app/extensions/vanity/page.mdx b/app/extensions/vanity/page.mdx index 07e48d8..704bae7 100644 --- a/app/extensions/vanity/page.mdx +++ b/app/extensions/vanity/page.mdx @@ -42,13 +42,10 @@ All properties are optional. Audio format (e.g. `audio/mpeg`). - 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 - /* e.g. "he/him" */ - type ShortPronoun = string; - - interface LongPronoun { + interface Pronoun { subject: string; object: string; dependent_possessive: string; @@ -56,12 +53,11 @@ All properties are optional. reflexive: string; } - type Pronoun = ShortPronoun | LongPronoun; /* Example: en-US or fr */ type LanguageCode = string; ``` - + User's birthday. If year is left out or set to `0000`, implementations **SHOULD** not display the year. @@ -72,8 +68,8 @@ All properties are optional. User's timezone. Should be a valid [IANA timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) string. - - 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. @@ -91,31 +87,37 @@ All properties are optional. { "image/png": { "content": "https://cdn.example.com/ab5081cf-b11f-408f-92c2-7c246f290593/cat_ears.png", - "remote": true, + "remote": true } } ], "avatar_mask": { "image/png": { "content": "https://cdn.example.com/d8c42be1-d0f7-43ef-b4ab-5f614e1beba4/rounded_square.jpeg", - "remote": true, + "remote": true } }, "background": { "image/png": { "content": "https://cdn.example.com/6492ddcd-311e-4921-9567-41b497762b09/untitled-file-0019822.png", - "remote": true, + "remote": true } }, "audio": { "audio/mpeg": { "content": "https://cdn.example.com/4da2f0d4-4728-4819-83e4-d614e4c5bebc/michael-jackson-thriller.mp3", - "remote": true, + "remote": true } }, "pronouns": { "en-us": [ - "he/him", + { + "subject": "he", + "object": "him", + "dependent_possessive": "his", + "independent_possessive": "his", + "reflexive": "himself" + }, { "subject": "they", "object": "them", @@ -129,8 +131,8 @@ All properties are optional. "location": "+40.6894-074.0447/", "timezone": "America/New_York", "aliases": [ - "https://burger.social/accounts/349ee237-c672-41c1-aadc-677e185f795a", - "https://versia.social/users/f565ef02-035d-4974-ba5e-f62a8558331d" + "burger.social:349ee237-c672-41c1-aadc-677e185f795a", + "versia.social:f565ef02-035d-4974-ba5e-f62a8558331d" ] } } diff --git a/app/extensions/websockets/page.mdx b/app/extensions/websockets/page.mdx deleted file mode 100644 index ab29a30..0000000 --- a/app/extensions/websockets/page.mdx +++ /dev/null @@ -1,57 +0,0 @@ -export const metadata = { - title: 'WebSocket Extension', - description: - 'The WebSocket extension adds support for real-time communication between instances.', -} - -# WebSockets Extension - - - 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. - - -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. - - - - - - Same as the `Versia-Signature` header in HTTP requests. - - - Same as the `Versia-Signed-At` header in HTTP requests. - - - Same as the `Versia-Signed-By` header in HTTP requests. - - - Same as the request body in HTTP requests. Must be a string (stringified JSON), not JSON. - - - - - - - ```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\"}" - } - ``` - - - - -## Connection Establishment - -... \ No newline at end of file diff --git a/app/federation/delegation/page.mdx b/app/federation/delegation/page.mdx deleted file mode 100644 index 43d4e8c..0000000 --- a/app/federation/delegation/page.mdx +++ /dev/null @@ -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. \ No newline at end of file diff --git a/app/federation/discovery/page.mdx b/app/federation/discovery/page.mdx index a1baf1e..fe56937 100644 --- a/app/federation/discovery/page.mdx +++ b/app/federation/discovery/page.mdx @@ -24,7 +24,7 @@ Accept: application/jrd+json { "subject": "acct:george@versia.social", // [!code focus:6] "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" ], "links": [ @@ -35,8 +35,8 @@ Accept: application/jrd+json }, { // [!code focus:5] "rel": "self", - "type": "application/json", - "href": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771" + "type": "application/vnd.versia+json", + "href": "https://versia.social/.versia/v0.6/entities/User/018ec082-0ae1-761c-b2c5-22275a611771" }, { "rel": "http://webfinger.net/rel/avatar", @@ -49,18 +49,39 @@ Accept: application/jrd+json ## 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: -### Example +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. -To discover the metadata of the instance `versia.social`, an instance would make a `GET` request to `https://versia.social/.well-known/versia`. +### Example -This endpoint will return an [InstanceMetadata](/entities/instance-metadata) entity. +To discover the metadata of the instance `versia.social`, an instance would first make a `GET` request to `https://versia.social/.well-known/versia`. ```http {{ 'title': 'Example Request' }} GET /.well-known/versia HTTP/1.1 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' }} { @@ -72,7 +93,8 @@ Accept: application/json }, "compatibility": { "versions": [ - "0.5.0" + "0.5.0", + "0.6.0" ], "extensions": [ "pub.versia:reactions", @@ -80,7 +102,10 @@ Accept: application/json "pub.versia:reports" ] }, - "host": "versia.social", - "created_at": "2021-07-01T00:00:00Z" + "domain": "versia.social", + "created_at": "2021-07-01T00:00:00Z", + "description": null, + "logo": null, + "banner": null } ``` \ No newline at end of file diff --git a/app/federation/example/page.mdx b/app/federation/example/page.mdx index 0709a03..ad4893b 100644 --- a/app/federation/example/page.mdx +++ b/app/federation/example/page.mdx @@ -40,8 +40,8 @@ curl https://b.social/.well-known/webfinger?resource=acct:joe@b.social -H "Accep "links": [ { // [!code focus:5] "rel": "self", - "type": "application/json", - "href": "https://b.social/users/joe" + "type": "application/vnd.versia+json", + "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 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. ### 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. ```bash -curl https://b.social/users/joe \ - -H "Accept: application/json" \ +# The request is signed by a.social's instance private key +curl https://b.social/.versia/entities/User/joe \ + -H "Accept: application/vnd.versia+json" \ -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-Signed-By: https://a.social/users/alice" \ + -H "Versia-Signed-By: a.social" \ -H "Versia-Signed-At: 1729241687" ``` @@ -71,30 +71,30 @@ curl https://b.social/users/joe \ ```json { - "id": "bde22zi3ca8762", // [!code focus:10] + "id": "bde22zi3ca8762", // [!code focus:3] "type": "User", - "uri": "https://b.social/users/joe", "created_at": "2024-10-13T18:48:19Z", "avatar": { "image/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 } - }, - "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] + }, // [!code focus:3] "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", + "bio": null, + "header": null, + "fields": [], + "manually_approves_followers": false, + "indexable": true, "extensions": { "pub.versia:custom_emojis": { "emojis": [ @@ -103,7 +103,15 @@ curl https://b.social/users/joe \ "content": { "image/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] "type": "Note", - "uri": "https://a.social/notes/782addd9-c051-4eea-8ba4-23d561d0c5bb", "created_at": "2024-12-01T12:19:06Z", - "author": "https://a.social/users/alice", + "author": "alice", "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": { - "text/html": { - "content": "Hello, @joe@b.social! How are you doing today?", + "text/html": { // [!code focus:12] + "content": "Hello, @joe@b.social! How are you doing today?", "remote": false, + "description": null, + "size": null, + "hash": null, + "thumbhash": null, + "width": null, + "height": null, + "fps": null, + "duration": null }, "text/plain": { "content": "Hello, @joe@b.social! How are you doing today?", "remote": false, + "description": null, + "size": null, + "hash": null, + "thumbhash": null, + "width": null, + "height": null, + "fps": null, + "duration": null } }, "group": "public", "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`. ```bash -curl -X POST https://b.social/inbox \ - -H "Content-Type: application/json; charset=utf-8" \ +curl -X POST https://b.social/.versia/v0.6/inbox \ + -H "Content-Type: application/vnd.versia+json; charset=utf-8" \ -H "Accept: application/json" \ -H "User-Agent: CoolerServer/1.0 (https://coolerserver.com)" \ # The request is signed by Alice's private key -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" ``` diff --git a/app/federation/http/page.mdx b/app/federation/http/page.mdx index bb421ad..575d714 100644 --- a/app/federation/http/page.mdx +++ b/app/federation/http/page.mdx @@ -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. -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 @@ -16,32 +16,37 @@ ALL kinds of HTTP requests/responses between instances **MUST** include a [Signa - Must include `application/json`. + Must be `application/vnd.versia+json`, unless specified otherwise. Basic `application/json` is **not** allowed. - 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. - + See [Signatures](/signatures) for more information. - + See [Signatures](/signatures). - + See [Signatures](/signatures). - 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) + ``` ```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 User-Agent: CoolServer/1.0 (https://coolserver.com) Versia-Signature: /CjB2L9bcvRg+uP19B4/rqy7Ji9/cqMFPlL3GVCIndnQjYyOpBzJEAl9weDnXm7Jrqa3y6sBC+EYWKThO2r9Bw== - Versia-Signed-By: https://example.com/users/1 + Versia-Signed-By: example.com Versia-Signed-At: 1729241687 ``` @@ -49,9 +54,9 @@ ALL kinds of HTTP requests/responses between instances **MUST** include a [Signa ## 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. 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 - Must include `application/json; charset=utf-8`. + Must include `application/vnd.versia+json; charset=utf-8`, unless specified otherwise. - + See [Signatures](/signatures) for more information. - + See [Signatures](/signatures). - + See [Signatures](/signatures). @@ -79,9 +84,9 @@ IETF draft [draft-polli-ratelimit-headers-02](https://www.ietf.org/archive/id/dr ```http {{ 'title': 'Example Response' }} 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-Signed-By: https://example.com/users/1 + Versia-Signed-By: example.com Versia-Signed-At: 1729241717 ``` diff --git a/app/federation/page.mdx b/app/federation/page.mdx index 9364a26..13ca699 100644 --- a/app/federation/page.mdx +++ b/app/federation/page.mdx @@ -21,24 +21,30 @@ Federation is built on the [HyperText Transfer Protocol (HTTP)](https://tools.ie ## 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. + + See the [Inbox Endpoint](/api/endpoints#inbox) for more information on the inbox endpoint. + + +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: -> 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. -### 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 -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//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. + + + 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. + 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. \ No newline at end of file diff --git a/app/federation/validation/page.mdx b/app/federation/validation/page.mdx index 493b04b..2739f39 100644 --- a/app/federation/validation/page.mdx +++ b/app/federation/validation/page.mdx @@ -6,7 +6,7 @@ export const metadata = { # 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. 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: -- 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 presence of **all required headers**. - 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. - 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. - For example, a `size` field on a `ContentFormat` structure should be a positive integer, not a negative number or a floating-point number. @@ -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. -- 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). 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. diff --git a/app/introduction/page.mdx b/app/introduction/page.mdx index 6274e6b..4df6f95 100644 --- a/app/introduction/page.mdx +++ b/app/introduction/page.mdx @@ -3,7 +3,7 @@ import { HeroPattern } from '@/components/HeroPattern' export const metadata = { 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 = [ @@ -16,7 +16,7 @@ export const sections = [ # 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' }}

Thanks

diff --git a/app/philosophy/principles/page.mdx b/app/philosophy/principles/page.mdx index 0842424..7fba24e 100644 --- a/app/philosophy/principles/page.mdx +++ b/app/philosophy/principles/page.mdx @@ -28,6 +28,6 @@ Developer-facing features (e.g. shared inboxes, reply backfilling, etc.) should ## 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. \ No newline at end of file +If there is a need for branching, nesting should be avoided: logic branches should be as flat as possible. \ No newline at end of file diff --git a/app/providers.tsx b/app/providers.tsx index db08246..26a03a1 100644 --- a/app/providers.tsx +++ b/app/providers.tsx @@ -1,8 +1,8 @@ "use client"; -import { uwuifyDocument } from "@/lib/uwuify"; import { ThemeProvider, useTheme } from "next-themes"; import { type ReactNode, useEffect } from "react"; +import { uwuifyDocument } from "@/lib/uwuify"; function ThemeWatcher() { const { resolvedTheme, setTheme } = useTheme(); diff --git a/app/security/page.mdx b/app/security/page.mdx index 62cf1e6..4957a67 100644 --- a/app/security/page.mdx +++ b/app/security/page.mdx @@ -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. -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. 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 - The Web - 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). 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 diff --git a/app/signatures/page.mdx b/app/signatures/page.mdx index d3b700d..9c8ba31 100644 --- a/app/signatures/page.mdx +++ b/app/signatures/page.mdx @@ -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: - **`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-At`**: The current Unix timestamp, in seconds (no milliseconds), when the request was signed. Timezone must be UTC, like all Unix timestamps. +- **`Versia-Signed-By`**: [Domain](/api/basics#domain) of the instance authoring the request. +- **`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: -- **All POST 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`. +Signatures must be put on: +- **All `POST` requests**. +- **All `GET` requests**. +- **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 @@ -36,12 +36,12 @@ $0 $1 $2 $3 ``` Where: -- `$0` is the HTTP method (e.g. `GET`, `POST`) in lowercase. -- `$1` is the path of the request, in standard URI format (don't forget to URL-encode it). -- `$2` is the Unix timestamp when the request was signed, in UTC seconds. +- `$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 request pathname, URL-encoded. +- `$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) -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: ``` @@ -50,25 +50,25 @@ post /notes 1729243417 n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg= ### Verifying the Signature -To verify a signature, the instance must: +To verify a signature, the verifying instance must: - Recreate the string as described above. - Extract the signature provided in the `Versia-Signature` header. - Check that the `Versia-Signed-At` timestamp is within 5 minutes of the current time. -- Decode the signature from base64. -- Perform a signature verification using the user's public key. +- Decode the signature from base64 to the raw bytes. +- Perform a signature verification using the sender instance's public key. ### Example 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 { "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: ```typescript @@ -97,7 +97,7 @@ const digest = await crypto.subtle.digest( ); 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( "Ed25519", @@ -113,25 +113,25 @@ To send the request, Bob would use the following code: ```typescript 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-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", headers, 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 const method = request.method.toLowerCase(); const path = new URL(request.url).pathname; 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 if (Math.abs(Date.now() - timestamp) > 300_000) { @@ -160,12 +160,12 @@ if (!isVerified) { ## 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. - 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. ```typescript {{ title: "Example using TypeScript and the WebCrypto API" }} diff --git a/app/structures/collection/page.mdx b/app/structures/collection/page.mdx index 841b87a..e0e98ae 100644 --- a/app/structures/collection/page.mdx +++ b/app/structures/collection/page.mdx @@ -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' }} -Pages should be limited to a reasonable number of entities, such as 20 or 80. - As Collections are independent and not part of a larger entity (like [ContentFormat](/structures/content-format)), they should have a valid [Signature](/signatures). @@ -18,31 +16,12 @@ Pages should be limited to a reasonable number of entities, such as 20 or 80. - - 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). - - - URI to the first page of the collection. Query parameters are allowed. - - - 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`. + + [Reference](/types#reference) to the author of the collection. Usually the user who "owns" the collection. Total number of entities in the collection, across all pages. - - URI to the next page of the collection. Query parameters are allowed. - - If there is no next page, this should be `null`. - - - URI to the previous page of the collection. Query parameters are allowed. - - - If there is no previous page, this should be `null`. - Collection contents. Must be an array of entities. @@ -54,17 +33,14 @@ Pages should be limited to a reasonable number of entities, such as 20 or 80. ```jsonc {{ 'title': 'Example Collection' }} { "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, - "next": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/outbox?page=2", - "previous": null, "items": [ { "id": "456df8ed-daf1-4062-abab-491071c7b8dd", "type": "Note", "uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd", "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" @@ -89,32 +65,14 @@ URI Collections are identical to regular collections, but they contain only URIs - - 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). - - - URI to the first page of the collection. Query parameters are allowed. - - - 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`. + + [Reference](/types#reference) to the author of the collection. Usually the user who owns the collection. Total number of entities in the collection, across all pages. - - URI to the next page of the collection. Query parameters are allowed. - - If there is no next page, this should be `null`. - - - URI to the previous page of the collection. Query parameters are allowed. - - If there is no previous page, this should be `null`. - - - Collection contents. Must be an array of URIs. + + Collection contents. Must be an array of [References](/types#reference). @@ -123,15 +81,11 @@ URI Collections are identical to regular collections, but they contain only URIs ```jsonc {{ 'title': 'Example URI Collection' }} { - "author": "https://versia.social/users/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", + "author": "018ec082-0ae1-761c-b2c5-22275a611771", "total": 46, - "next": "https://versia.social/users/018ec082-0ae1-761c-b2c5-22275a611771/followers?page=2", - "previous": null, "items": [ - "https://versia.social/users/f8b0d4b4-d354-4798-bbc5-c2ba8acabfe3", - "https://social.bob.com/u/2B27E62snga763" + "versia.social:f8b0d4b4-d354-4798-bbc5-c2ba8acabfe3", + "social.bob.com:2B27E62snga763" ] } ``` diff --git a/app/types/page.mdx b/app/types/page.mdx index d35e6fa..044c310 100644 --- a/app/types/page.mdx +++ b/app/types/page.mdx @@ -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. + + + If the hostname is an IPv6 address, it must be enclosed in square brackets. + + For example: `[2001:db8::1]:3000`. + + +### 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 diff --git a/biome.json b/biome.json index 074db76..d33a222 100644 --- a/biome.json +++ b/biome.json @@ -1,30 +1,49 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "organizeImports": { - "enabled": true + "$schema": "https://biomejs.dev/schemas/2.3.10/schema.json", + "assist": { "actions": { "source": { "organizeImports": "on" } } }, + "css": { + "parser": { + "tailwindDirectives": true + } }, "linter": { "enabled": true, "rules": { - "all": true, + "suspicious": { + "noConsole": "off", + "noExplicitAny": "off", + "noDuplicateElseIf": "error", + "noDocumentCookie": "off", + "noReactSpecificProps": "off", + "noUnknownAtRules": "off" + }, + "performance": { + "noBarrelFile": "off", + "noNamespaceImport": "off", + "useTopLevelRegex": "off", + "noImgElement": "off" + }, "correctness": { - "noNodejsModules": "off", + "noUnknownFunction": "off", + "noUndeclaredVariables": "off", + "useHookAtTopLevel": "off", + "noUnusedVariables": "off", + "noUnusedImports": "off", + "noUndeclaredDependencies": "off", "useImportExtensions": "off", - "noUnknownFunction": "off" + "useJsxKeyInIterable": "off", + "useUniqueElementIds": "off" }, - "complexity": { - "noExcessiveCognitiveComplexity": "off" + "a11y": { + "noStaticElementInteractions": "off" }, - "suspicious": { - "noReactSpecificProps": "off" - }, - "performance": { - "useTopLevelRegex": "off" + "complexity": { + "noExcessiveCognitiveComplexity": "off", + "noImportantStyles": "off" }, "style": { "noDefaultExport": "off", "noParameterProperties": "off", - "noNamespaceImport": "off", "useFilenamingConvention": "off", "useNamingConvention": { "level": "warn", @@ -54,28 +73,22 @@ "PascalCase", "snake_case" ] - }, - { - "selector": { - "kind": "classMethod", - "scope": "any" - }, - "formats": ["camelCase", "PascalCase"] - }, - { - "selector": { - "kind": "functionParameter", - "scope": "any" - }, - "formats": ["snake_case", "camelCase"] } ] } - } + }, + "noParameterAssign": "error", + "useAsConstAssertion": "error", + "useDefaultParameterLast": "error", + "useEnumInitializers": "error", + "useSelfClosingElements": "error", + "useSingleVarDeclarator": "error", + "noUnusedTemplateLiteral": "error", + "useNumberNamespace": "error", + "noInferrableTypes": "error", + "noUselessElse": "error" }, - "nursery": { - "noDuplicateElseIf": "warn" - } + "nursery": {} } }, "formatter": { @@ -83,10 +96,27 @@ "indentStyle": "space", "indentWidth": 4 }, - "javascript": { - "globals": ["Bun"] + "overrides": [ + { + "includes": ["**/*.vue"], + "linter": { + "rules": { + "correctness": { + "noUnusedImports": "off" + }, + "style": { + "useImportType": "off" + } + } + } + } + ], + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true }, "files": { - "ignore": ["node_modules", ".next", ".output", "out", "public/pl.js"] + "includes": ["**", "!public"] } } diff --git a/bun.lock b/bun.lock index 1d48e42..a3c2f12 100644 --- a/bun.lock +++ b/bun.lock @@ -1,216 +1,228 @@ { "lockfileVersion": 1, + "configVersion": 1, "workspaces": { "": { "name": "@versia-pub/docs", "dependencies": { - "@algolia/autocomplete-core": "^1.19.1", - "@headlessui/react": "^2.2.3", + "@algolia/autocomplete-core": "^1.19.4", + "@headlessui/react": "^2.2.9", "@headlessui/tailwindcss": "^0.2.2", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/mdx": "^15.3.2", - "@sindresorhus/slugify": "^2.2.1", - "@tailwindcss/postcss": "^4.1.6", - "@tailwindcss/typography": "^0.5.16", + "@next/mdx": "^15.4.10", + "@radix-ui/react-hover-card": "^1.1.15", + "@sindresorhus/slugify": "^3.0.0", + "@tailwindcss/postcss": "^4.1.18", + "@tailwindcss/typography": "^0.5.19", "@types/mdx": "^2.0.13", - "@types/node": "^22.15.18", - "@types/react": "^19.1.4", - "@types/react-dom": "^19.1.5", - "@types/react-highlight-words": "^0.20.0", - "acorn": "^8.14.1", + "@types/node": "^25.0.3", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@types/react-highlight-words": "^0.20.1", + "acorn": "^8.15.0", "clsx": "^2.1.1", "fast-glob": "^3.3.3", - "flexsearch": "^0.8.166", - "framer-motion": "^12.11.3", + "flexsearch": "^0.8.212", + "framer-motion": "^12.23.26", "mdast-util-to-string": "^4.0.0", "mdx-annotations": "^0.1.4", - "next": "^15.3.2", + "next": "15.4.10", "next-themes": "^0.4.6", - "react": "^19.1.0", - "react-dom": "^19.1.0", + "qss": "^3.0.0", + "react": "^19.2.3", + "react-dom": "^19.2.3", "react-highlight-words": "^0.21.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", - "remark-mdx": "^3.1.0", - "shiki": "^3.4.1", + "remark-mdx": "^3.1.1", + "shiki": "^3.20.0", "simple-functional-loader": "^1.2.1", - "tailwindcss": "^4.1.6", - "typescript": "^5.8.3", + "tailwindcss": "^4.1.18", + "typescript": "^5.9.3", "unist-util-filter": "^5.0.1", "unist-util-visit": "^5.0.0", "uwuifier": "^4.2.2", - "zustand": "^5.0.4", + "zustand": "^5.0.9", }, "devDependencies": { - "@biomejs/biome": "^1.9.4", - "@iconify-icon/react": "^3.0.0", - "@next/bundle-analyzer": "^15.3.2", - "@shikijs/transformers": "^3.4.1", - "sharp": "^0.34.1", + "@biomejs/biome": "^2.3.10", + "@iconify-icon/react": "^3.0.3", + "@next/bundle-analyzer": "^15.5.4", + "@shikijs/transformers": "^3.20.0", + "sharp": "^0.34.5", }, }, }, "trustedDependencies": [ + "@tailwindcss/oxide", "sharp", "@biomejs/biome", ], "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=="], - "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + "@algolia/requester-node-http": ["@algolia/requester-node-http@5.46.1", "", { "dependencies": { "@algolia/client-common": "5.46.1" } }, "sha512-VwbhV1xvTGiek3d2pOS6vNBC4dtbNadyRT+i1niZpGhOJWz1XnfhxNboVbXPGAyMJYz7kDrolbDvEzIDT93uUA=="], - "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], - "@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/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/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="], + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M6xUjtCVnNGFfK7HMNKa593nb7fwNm43fq1Mt71kpLpb+4mE7odO8W/oWVDyBVO4ackhresy1ZYO7OJcVo/B7w=="], - "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="], + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-Vae7+V6t/Avr8tVbFNjnFSTKZogZHFYl7MMH62P/J1kZtr0tyRQ9Fe0onjqjS2Ek9lmNLmZc/VR5uSekh+p1fg=="], - "@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": ["@biomejs/cli-linux-arm64@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-hhPw2V3/EpHKsileVOFynuWiKRgFEV48cLe0eA+G2wO4SzlwEhLEB9LhlSrVeu2mtSn205W283LkX7Fh48CaxA=="], - "@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-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-B9DszIHkuKtOH2IFeeVkQmSMVUjss9KtHaNXquYYWCjH8IstNgXgx5B0aSBQNr6mn4RcKKRQZXn9Zu1rM3O0/A=="], - "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="], + "@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-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="], + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QTfHZQh62SDFdYc2nfmZFuTm5yYb4eO1zwfB+90YxUumRCR171tS1GoTX5OD0wrv4UsziMPmrePMtkTnNyYG3g=="], - "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="], + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-o7lYc9n+CfRbHvkjPhm8s9FgbKdYZu5HCcGVMItLjz93EhgJ8AM44W+QckDqLA9MKDNFrR8nPbO4b73VC5kGGQ=="], - "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="], + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.10", "", { "os": "win32", "cpu": "x64" }, "sha512-pHEFgq7dUEsKnqG9mx9bXihxGI49X+ar+UBrEIj3Wqj3UCZp1rNgV+OoyjFgcXsjCWpuEAF4VJdkZr3TrWdCbQ=="], "@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-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=="], - "@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=="], - "@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=="], - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + "@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=="], - "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], + "@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/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=="], + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - "@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=="], + "@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=="], - "@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/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/react": ["@mdx-js/react@3.1.0", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ=="], + "@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=="], - "@next/bundle-analyzer": ["@next/bundle-analyzer@15.3.2", "", { "dependencies": { "webpack-bundle-analyzer": "4.10.1" } }, "sha512-zY5O1PNKNxWEjaFX8gKzm77z2oL0cnj+m5aiqNBgay9LPLCDO13Cf+FJONeNq/nJjeXptwHFT9EMmTecF9U4Iw=="], + "@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=="], - "@next/env": ["@next/env@15.3.2", "", {}, "sha512-xURk++7P7qR9JG1jJtLzPzf0qEvqCN0A/T3DXf8IPMKo9/6FfjxtEffRJIIew/bIL4T3C2jLLqBor8B/zVlx6g=="], + "@next/bundle-analyzer": ["@next/bundle-analyzer@15.5.9", "", { "dependencies": { "webpack-bundle-analyzer": "4.10.1" } }, "sha512-lT1EBpFyGVN9u8M43f2jE78DsCu0A5KPA5OkF5PdIHrKDo4oTJ4lUQKciA9T2u9gccSXIPQcZb5TYkHF4f8iiw=="], - "@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/env": ["@next/env@15.4.10", "", {}, "sha512-knhmoJ0Vv7VRf6pZEPSnciUG1S4bIhWx+qTYBW/AjxEtlzsiNORPk8sFDCEvqLfmKuey56UB9FL1UdHEV3uBrg=="], - "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2DR6kY/OGcokbnCsjHpNeQblqCZ85/1j6njYSkzRdpLn5At7OkSdmk7WyAmB9G0k25+VgqVZ/u356OSoQZ3z0g=="], + "@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/swc-darwin-x64": ["@next/swc-darwin-x64@15.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-ro/fdqaZWL6k1S/5CLv1I0DaZfDVJkWNaUU3un8Lg6m0YENWlDulmIWzV96Iou2wEYyEsZq51mwV8+XQXqMp3w=="], + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.4.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Pf6zXp7yyQEn7sqMxur6+kYcywx5up1J849psyET7/8pG2gQTVMjU3NzgIt8SeEP5to3If/SaWmaA6H6ysBr1A=="], - "@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-darwin-x64": ["@next/swc-darwin-x64@15.4.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-xla6AOfz68a6kq3gRQccWEvFC/VRGJmA/QuSLENSO7CZX5WIEkSz7r1FdXUjtGCQ1c2M+ndUAH7opdfLK1PQbw=="], - "@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-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.4.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-y3fmp+1Px/SJD+5ntve5QLZnGLycsxsVPkTzAc3zUiXYSOlTPqT8ynfmt6tt4fSo1tAhDPmryXpYKEAcoAPDJw=="], - "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uRBo6THWei0chz+Y5j37qzx+BtoDRFIkDzZjlpCItBRXyMPIg079eIkOCl3aqr2tkxL4HFyJ4GHDes7W8HuAUg=="], + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.4.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-DX/L8VHzrr1CfwaVjBQr3GWCqNNFgyWJbeQ10Lx/phzbQo3JNAxUok1DZ8JHRGcL6PgMRgj6HylnLNndxn4Z6A=="], - "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-+uxFlPuCNx/T9PdMClOqeE8USKzj8tVz37KflT3Kdbx/LOlZBRI2yxuIcmx1mPNK8DwSOMNCr4ureSet7eyC0w=="], + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.4.8", "", { "os": "linux", "cpu": "x64" }, "sha512-9fLAAXKAL3xEIFdKdzG5rUSvSiZTLLTCc6JKq1z04DR4zY7DbAPcRvNm3K1inVhTiQCs19ZRAgUerHiVKMZZIA=="], - "@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-linux-x64-musl": ["@next/swc-linux-x64-musl@15.4.8", "", { "os": "linux", "cpu": "x64" }, "sha512-s45V7nfb5g7dbS7JK6XZDcapicVrMMvX2uYgOHP16QuKH/JA285oy6HcxlKqwUNaFY/UC6EvQ8QZUOo19cBKSA=="], - "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.3.2", "", { "os": "win32", "cpu": "x64" }, "sha512-aW5B8wOPioJ4mBdMDXkt5f3j8pUr9W8AnlX0Df35uRWNT1Y6RIybxjnSUe+PhM+M1bwgyY8PHLmXZC6zT1o5tA=="], + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.4.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-KjgeQyOAq7t/HzAJcWPGA8X+4WY03uSCZ2Ekk98S9OgCFsb6lfBE3dbUzUuEQAN2THbwYgFfxX2yFTCMm8Kehw=="], + + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.4.8", "", { "os": "win32", "cpu": "x64" }, "sha512-Exsmf/+42fWVnLMaZHzshukTBxZrSwuuLKFvqhGHJ+mC1AokqieLY/XzAl3jc/CqhXLqLY3RRjkKJ9YnLPcRWg=="], "@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=="], - "@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=="], - "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + "@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=="], - "@sindresorhus/slugify": ["@sindresorhus/slugify@2.2.1", "", { "dependencies": { "@sindresorhus/transliterate": "^1.0.0", "escape-string-regexp": "^5.0.0" } }, "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw=="], + "@shikijs/transformers": ["@shikijs/transformers@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/types": "3.20.0" } }, "sha512-PrHHMRr3Q5W1qB/42kJW6laqFyWdhrPF2hNR9qjOm1xcSiAO3hAHo7HaVyHE6pMyevmy3i51O8kuGGXC78uK3g=="], - "@sindresorhus/transliterate": ["@sindresorhus/transliterate@1.6.0", "", { "dependencies": { "escape-string-regexp": "^5.0.0" } }, "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ=="], + "@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="], + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + + "@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@2.2.0", "", {}, "sha512-aLtANYAx3qvFilasPhZke27+Cm7WawGGuGiOd2EAp0lg1NdWKfulslcql/Qi7lNQ9odkPjwRbwk9c4CYsTh+Rg=="], "@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/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=="], @@ -308,25 +356,25 @@ "@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=="], "@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-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=="], @@ -336,9 +384,7 @@ "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.30001715", "", {}, "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw=="], + "caniuse-lite": ["caniuse-lite@1.0.30001760", "", {}, "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw=="], "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=="], - "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], - "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], "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=="], "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=="], - "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=="], - "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=="], - "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=="], @@ -390,7 +426,7 @@ "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=="], @@ -420,9 +456,9 @@ "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=="], @@ -444,16 +480,14 @@ "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-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-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], @@ -468,43 +502,39 @@ "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=="], - "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-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.29.2", "", { "os": "win32", "cpu": "x64" }, "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA=="], - - "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=="], + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="], - "lodash.castarray": ["lodash.castarray@4.4.0", "", {}, "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q=="], + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="], - "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "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=="], "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=="], @@ -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-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=="], @@ -620,15 +650,9 @@ "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=="], - - "minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="], - - "mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="], + "motion-dom": ["motion-dom@12.23.23", "", { "dependencies": { "motion-utils": "^12.23.6" } }, "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA=="], - "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=="], + "motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="], "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=="], - "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=="], "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=="], @@ -652,29 +676,31 @@ "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=="], - "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=="], - "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=="], "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-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=="], @@ -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-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=="], @@ -698,45 +724,39 @@ "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=="], - "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-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=="], - "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=="], "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=="], - "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=="], - "tabbable": ["tabbable@6.2.0", "", {}, "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="], - - "tailwindcss": ["tailwindcss@4.1.6", "", {}, "sha512-j0cGLTreM6u4OWzBeLBpycK0WIh8w7kSwcUsQZoGLHZ7xDTdM69lN64AgoIEEwFi0tnhs4wSykUa5YWxAzgFYg=="], + "tabbable": ["tabbable@6.3.0", "", {}, "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="], - "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], + "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="], - "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=="], + "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], "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=="], - "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=="], "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=="], @@ -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-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=="], @@ -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-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=="], "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.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=="], + "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=="], "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.9.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw=="], + "@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/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=="], "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=="], "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=="], diff --git a/components/Code.tsx b/components/Code.tsx index 42fd46c..1d19628 100644 --- a/components/Code.tsx +++ b/components/Code.tsx @@ -5,9 +5,9 @@ import clsx from "clsx"; import { Children, type ComponentPropsWithoutRef, - type ReactNode, createContext, isValidElement, + type ReactNode, useContext, useEffect, useRef, @@ -144,8 +144,7 @@ function CodePanel({ label?: string; code?: string; }) { - // biome-ignore lint/suspicious/noExplicitAny: - const child = Children.only(children) as ReactNode & { props: any }; + const child = children as ReactNode & { props: any }; if (isValidElement(child)) { tag = child.props.tag ?? tag; @@ -207,8 +206,7 @@ function CodeGroupHeader({ > {getPanelTitle( isValidElement(child) - ? // biome-ignore lint/suspicious/noExplicitAny: - (child.props as any) + ? (child.props as any) : {}, )} @@ -326,7 +324,6 @@ export function CodeGroup({ }: ComponentPropsWithoutRef & { title: string }) { const languages = Children.map(children, (child) => - // biome-ignore lint/suspicious/noExplicitAny: getPanelTitle(isValidElement(child) ? (child.props as any) : {}), ) ?? []; const tabGroupProps = useTabGroupProps(languages); @@ -375,8 +372,8 @@ export function Code({ children, ...props }: ComponentPropsWithoutRef<"code">) { ); } return ( - // biome-ignore lint/security/noDangerouslySetInnerHtml: - // biome-ignore lint/style/useNamingConvention: + // biome-ignore lint/security/noDangerouslySetInnerHtml: HTML is trusted + // biome-ignore lint/style/useNamingConvention: Biome incorrectly tags this as bad naming ); } diff --git a/components/Feedback.tsx b/components/Feedback.tsx index 163dec2..b461175 100644 --- a/components/Feedback.tsx +++ b/components/Feedback.tsx @@ -59,7 +59,6 @@ const FeedbackForm = forwardRef< }); const FeedbackThanks = forwardRef>( - // biome-ignore lint/style/useNamingConvention: function FeedbackThanks(_props, ref) { return (
+
diff --git a/components/GridPattern.tsx b/components/GridPattern.tsx index 14fefc8..2369c91 100644 --- a/components/GridPattern.tsx +++ b/components/GridPattern.tsx @@ -37,7 +37,7 @@ export function GridPattern({ fill={`url(#${patternId})`} /> {squares && ( - // biome-ignore lint/a11y/noSvgWithoutTitle: + // biome-ignore lint/a11y/noSvgWithoutTitle: it's decoration

diff --git a/components/Header.tsx b/components/Header.tsx index b64138f..b552997 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -2,10 +2,10 @@ import clsx from "clsx"; import { motion, useScroll, useTransform } from "framer-motion"; import Link from "next/link"; import { - type CSSProperties, type ComponentRef, - type ReactNode, + type CSSProperties, forwardRef, + type ReactNode, } from "react"; import { Button } from "./Button"; @@ -13,8 +13,8 @@ import { Logo } from "./Logo"; import { MobileNavigation, useIsInsideMobileNavigation, + useMobileNavigationStore, } from "./MobileNavigation"; -import { useMobileNavigationStore } from "./MobileNavigation"; import { MobileSearch, Search } from "./Search"; import { ThemeToggle } from "./ThemeToggle"; @@ -95,7 +95,7 @@ export const Header = forwardRef, { className?: string }>(

- +
diff --git a/components/Layout.tsx b/components/Layout.tsx index b07de15..af02915 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -25,7 +25,7 @@ export function Layout({
diff --git a/components/Libraries.tsx b/components/Libraries.tsx index 24f98e0..3f94ef7 100644 --- a/components/Libraries.tsx +++ b/components/Libraries.tsx @@ -6,8 +6,8 @@ import { Heading } from "./Heading"; const libraries = [ { - href: "https://github.com/versia-pub/api/tree/main/federation", - name: "@versia/federation", + href: "https://github.com/versia-pub/server/tree/main/packages/sdk", + name: "@versia/sdk", description: "Fully-featured federation toolkit with validation, signatures, parsing, and more.", logo: logoTypescript, diff --git a/components/LinkPreview.tsx b/components/LinkPreview.tsx new file mode 100644 index 0000000..eb11c7c --- /dev/null +++ b/components/LinkPreview.tsx @@ -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, + ) => { + 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( +
+ +
, + document.body, + ) + : null} + { + setOpen(open); + }} + > + + {children} + + + + + + {isOpen && ( + + + {`Preview + + + )} + + + + + + ); +}; diff --git a/components/Logo.tsx b/components/Logo.tsx index 52bf0da..0da78d4 100644 --- a/components/Logo.tsx +++ b/components/Logo.tsx @@ -1,7 +1,7 @@ import clsx from "clsx"; import type { ComponentPropsWithoutRef } from "react"; // Uncomment this on dev branches -// import { Badge } from "./Metadata"; +import { Badge } from "./Metadata"; export function Logo(props: ComponentPropsWithoutRef<"div">) { return ( @@ -17,9 +17,9 @@ export function Logo(props: ComponentPropsWithoutRef<"div">) { alt="Logo" className="h-full rounded-xs" /> - - Versia Protocol {/* Dev */} - + {/* + Versia Protocol Dev + */}
); } diff --git a/components/MobileNavigation.tsx b/components/MobileNavigation.tsx index 56d9d4d..a2f994c 100644 --- a/components/MobileNavigation.tsx +++ b/components/MobileNavigation.tsx @@ -11,9 +11,9 @@ import { motion } from "framer-motion"; import { usePathname, useSearchParams } from "next/navigation"; import { type ComponentPropsWithoutRef, + createContext, type MouseEvent, Suspense, - createContext, useContext, useEffect, useRef, diff --git a/components/Navigation.tsx b/components/Navigation.tsx index 06c3c10..4d088f9 100644 --- a/components/Navigation.tsx +++ b/components/Navigation.tsx @@ -209,7 +209,6 @@ function NavigationGroup({ {link.href === pathname && sections.length > 0 && ( role="list" initial={{ opacity: 0 }} animate={{ @@ -250,6 +249,7 @@ export const navigation: NavGroup[] = [ { title: "Introduction", href: "/introduction" }, { title: "SDKs", href: "/sdks" }, { title: "Entities", href: "/entities" }, + { title: "JSON", href: "/json" }, { title: "Signatures", href: "/signatures" }, { title: "Security", href: "/security" }, { title: "Federation", href: "/federation" }, @@ -267,10 +267,16 @@ export const navigation: NavGroup[] = [ { title: "HTTP", href: "/federation/http" }, { title: "Validation", href: "/federation/validation" }, { title: "Discovery", href: "/federation/discovery" }, - { title: "Delegation", href: "/federation/delegation" }, { title: "Example", href: "/federation/example" }, ], }, + { + title: "API", + links: [ + { title: "Basics", href: "/api/basics" }, + { title: "Endpoints", href: "/api/endpoints" }, + ], + }, { title: "Structures", links: [ @@ -295,6 +301,7 @@ export const navigation: NavGroup[] = [ title: "Extensions", links: [ { title: "Custom Emojis", href: "/extensions/custom-emojis" }, + { title: "Delegation", href: "/extensions/delegation" }, { title: "Groups", href: "/extensions/groups" }, { title: "Instance Messaging", @@ -311,7 +318,6 @@ export const navigation: NavGroup[] = [ { title: "Reports", href: "/extensions/reports" }, { title: "Share", href: "/extensions/share" }, { title: "Vanity", href: "/extensions/vanity" }, - { title: "WebSockets", href: "/extensions/websockets" }, ], }, ]; @@ -334,7 +340,7 @@ export function Navigation(props: ComponentPropsWithoutRef<"nav">) { variant="filled" className="w-full" > - Working Draft 5 + Working Draft 6 diff --git a/components/Property.tsx b/components/Property.tsx index e45f14d..6524de3 100644 --- a/components/Property.tsx +++ b/components/Property.tsx @@ -1,7 +1,7 @@ "use client"; import Link from "next/link"; -import { type ReactNode, createContext, useContext } from "react"; +import { createContext, type ReactNode, useContext } from "react"; import { AnchorIcon } from "./Heading"; export const PropertyContext = createContext<{ @@ -13,7 +13,10 @@ export const PropertyContext = createContext<{ export function Properties({ children, name, -}: { children: ReactNode; name: string }) { +}: { + children: ReactNode; + name: string; +}) { return (
    diff --git a/components/Resources.tsx b/components/Resources.tsx index 0e3a64d..5810e98 100644 --- a/components/Resources.tsx +++ b/components/Resources.tsx @@ -1,5 +1,6 @@ "use client"; +import { Icon } from "@iconify-icon/react"; import { type MotionValue, motion, @@ -7,8 +8,6 @@ import { useMotionValue, } from "framer-motion"; import Link from "next/link"; - -import { Icon } from "@iconify-icon/react"; import type { ComponentPropsWithoutRef, MouseEvent } from "react"; import { GridPattern } from "./GridPattern"; import { Heading } from "./Heading"; diff --git a/components/Search.tsx b/components/Search.tsx index 34699f5..5f8acec 100644 --- a/components/Search.tsx +++ b/components/Search.tsx @@ -19,11 +19,11 @@ import { type ComponentPropsWithoutRef, type ComponentRef, Fragment, + forwardRef, type MouseEvent, type KeyboardEvent as ReactKeyboardEvent, Suspense, type SyntheticEvent, - forwardRef, useCallback, useEffect, useId, @@ -164,7 +164,6 @@ function LoadingIcon(props: ComponentPropsWithoutRef<"svg">) { function HighlightQuery({ text, query }: { text: string; query: string }) { return ( - // @ts-ignore export { Button } from "./Button"; -export { CodeGroup, Code as code, Pre as pre } from "./Code"; -export { Property, Properties } from "./Property"; +export { Code as code, CodeGroup, Pre as pre } from "./Code"; +export { Properties, Property } from "./Property"; export function wrapper({ children }: { children: ReactNode }) { return ( @@ -44,6 +43,37 @@ function InfoIcon(props: ComponentPropsWithoutRef<"svg">) { ); } +function WarningIcon(props: ComponentPropsWithoutRef<"svg">) { + return ( + + ); +} + export function Note({ children }: { children: ReactNode }) { return (
    @@ -55,6 +85,17 @@ export function Note({ children }: { children: ReactNode }) { ); } +export function Warning({ children }: { children: ReactNode }) { + return ( +
    + +
    + {children} +
    +
    + ); +} + export function Row({ children }: { children: ReactNode }) { return (
    diff --git a/mdx/rehype.mjs b/mdx/rehype.mjs index 7cf89f1..f40449c 100644 --- a/mdx/rehype.mjs +++ b/mdx/rehype.mjs @@ -12,7 +12,6 @@ import { visit } from "unist-util-visit"; function rehypeParseCodeBlocks() { return (tree) => { - // biome-ignore lint/style/useNamingConvention: visit(tree, "element", (node, _nodeIndex, parentNode) => { if (node.tagName === "code" && node.properties.className) { parentNode.properties.language = @@ -40,7 +39,7 @@ const highlighter = await createHighlighter({ themes: [], }); -highlighter.loadTheme("dark-plus"); +await highlighter.loadTheme("dark-plus"); function rehypeShiki() { return async (tree) => { diff --git a/next.config.mjs b/next.config.mjs index 14c5c0d..97832f6 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,6 +1,5 @@ -import nextMDX from "@next/mdx"; - import bundleAnalyzer from "@next/bundle-analyzer"; +import nextMDX from "@next/mdx"; import { recmaPlugins } from "./mdx/recma.mjs"; import { rehypePlugins } from "./mdx/rehype.mjs"; import { remarkPlugins } from "./mdx/remark.mjs"; @@ -17,6 +16,11 @@ const withMDX = nextMDX({ const nextConfig = { pageExtensions: ["js", "jsx", "ts", "tsx", "mdx"], output: "export", + images: { + domains: [ + "api.microlink.io", // Microlink Image Preview + ], + }, }; const withBundleAnalyzer = bundleAnalyzer({ diff --git a/package.json b/package.json index bf19321..358cbaa 100644 --- a/package.json +++ b/package.json @@ -11,50 +11,56 @@ "uuid": "bun --print 'crypto.randomUUID()'" }, "dependencies": { - "@algolia/autocomplete-core": "^1.19.1", - "@headlessui/react": "^2.2.3", + "@algolia/autocomplete-core": "^1.19.4", + "@headlessui/react": "^2.2.9", "@headlessui/tailwindcss": "^0.2.2", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/mdx": "^15.3.2", - "@sindresorhus/slugify": "^2.2.1", - "@tailwindcss/postcss": "^4.1.6", - "@tailwindcss/typography": "^0.5.16", + "@next/mdx": "^15.4.10", + "@radix-ui/react-hover-card": "^1.1.15", + "@sindresorhus/slugify": "^3.0.0", + "@tailwindcss/postcss": "^4.1.18", + "@tailwindcss/typography": "^0.5.19", "@types/mdx": "^2.0.13", - "@types/node": "^22.15.18", - "@types/react": "^19.1.4", - "@types/react-dom": "^19.1.5", - "@types/react-highlight-words": "^0.20.0", - "acorn": "^8.14.1", + "@types/node": "^25.0.3", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@types/react-highlight-words": "^0.20.1", + "acorn": "^8.15.0", "clsx": "^2.1.1", "fast-glob": "^3.3.3", - "flexsearch": "^0.8.166", - "framer-motion": "^12.11.3", + "flexsearch": "^0.8.212", + "framer-motion": "^12.23.26", "mdast-util-to-string": "^4.0.0", "mdx-annotations": "^0.1.4", - "next": "^15.3.2", + "next": "15.4.10", "next-themes": "^0.4.6", - "react": "^19.1.0", - "react-dom": "^19.1.0", + "qss": "^3.0.0", + "react": "^19.2.3", + "react-dom": "^19.2.3", "react-highlight-words": "^0.21.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", - "remark-mdx": "^3.1.0", - "shiki": "^3.4.1", + "remark-mdx": "^3.1.1", + "shiki": "^3.20.0", "simple-functional-loader": "^1.2.1", - "tailwindcss": "^4.1.6", - "typescript": "^5.8.3", + "tailwindcss": "^4.1.18", + "typescript": "^5.9.3", "unist-util-filter": "^5.0.1", "unist-util-visit": "^5.0.0", "uwuifier": "^4.2.2", - "zustand": "^5.0.4" + "zustand": "^5.0.9" }, "devDependencies": { - "@biomejs/biome": "^1.9.4", - "@iconify-icon/react": "^3.0.0", - "@next/bundle-analyzer": "^15.3.2", - "@shikijs/transformers": "^3.4.1", - "sharp": "^0.34.1" + "@biomejs/biome": "^2.3.10", + "@iconify-icon/react": "^3.0.3", + "@next/bundle-analyzer": "^15.5.4", + "@shikijs/transformers": "^3.20.0", + "sharp": "^0.34.5" }, - "trustedDependencies": ["@biomejs/biome", "sharp"] + "trustedDependencies": [ + "@biomejs/biome", + "@tailwindcss/oxide", + "sharp" + ] } diff --git a/public/pl.js b/public/pl.js index 193bbf9..4d2e22e 100644 --- a/public/pl.js +++ b/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 { + 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); +})(); diff --git a/styles/tailwind.css b/styles/tailwind.css index 0b0817e..f7ffae3 100644 --- a/styles/tailwind.css +++ b/styles/tailwind.css @@ -143,12 +143,16 @@ .prose [class*="language-"] .has-focused .line:not(.focused) { filter: blur(0.095rem); 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) { 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) {