CVE-2023-5571: Improper Input Validation (CWE-20)
value: Improper Input Validation in GitHub repository vriteio/vrite prior to 0.3.0.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
CVSS v3 base score: 7.5
Published: 2023-10-13T10:15Z
Repository: https://github.com/vriteio/vrite
Language: TypeScript
Files changed: .gitignore, apps/backend/api/src/api.ts, apps/backend/api/src/index.ts, apps/backend/app/src/app.ts, apps/backend/app/src/index.ts, apps/backend/assets/src/assets.ts, apps/backend/assets/src/index.ts, apps/backend/collaboration/src/extensions/git-sync.ts, apps/backend/collaboration/src/extensions/search-indexing.ts, apps/backend/collaboration/src/index.ts, apps/backend/collaboration/src/writing.ts, apps/backend/extensions/package.json, apps/backend/extensions/src/extensions.ts, apps/backend/extensions/src/index.ts, apps/backend/extensions/src/routes/dev/transformer.ts, apps/backend/extensions/src/routes/hashnode/transformer.ts, apps/backend/extensions/src/routes/index.ts, apps/backend/extensions/src/routes/mdx/index.ts, apps/backend/extensions/src/routes/mdx/input-transformer.ts, apps/backend/extensions/src/routes/mdx/output-transformer.ts, apps/backend/extensions/src/routes/medium/transformer.ts, apps/docs/.astro/types.d.ts, apps/docs/astro.config.mjs, apps/docs/package.json, apps/docs/src/components/content/card-grid.astro, apps/docs/src/components/content/card.astro, apps/docs/src/components/content/index.ts, apps/docs/src/components/content/info.astro, apps/docs/src/components/content/warning.astro, apps/docs/src/components/fragments/footer.tsx, apps/docs/src/components/fragments/header.tsx, apps/docs/src/components/fragments/index.ts, apps/docs/src/components/fragments/on-this-page.tsx, apps/docs/src/components/fragments/search-palette.tsx, apps/docs/src/components/fragments/side-bar.tsx, apps/docs/src/components/layouts/default.astro, apps/docs/src/components/layouts/menu.json, apps/docs/src/content/config.ts, apps/docs/src/content/docs/javascript-sdk/javascript-sdk.md, apps/docs/src/content/docs/self-hosting/configuration.md, apps/docs/src/content/docs/self-hosting/docker.md, apps/docs/src/content/docs/usage-guide/configuring-vrite.md, apps/docs/src/content/docs/usage-guide/content-editor.md, apps/docs/src/content/docs/usage-guide/getting-started.md, apps/docs/src/content/docs/usage-guide/kanban-dashboard.md, apps/docs/src/content/docs/usage-guide/metadata.md, apps/docs/src/content/docs/usage-guide/publishing.md, apps/docs/src/content/docs/usage-guide/vrite-extensions.md, apps/docs/src/content/recipes/test.mdx, apps/docs/src/env.d.ts, apps/docs/src/pages/[...slug].astro, apps/docs/src/styles/base.css, apps/docs/src/styles/styles.scss, apps/web/package.json, apps/web/public/sandbox.js, apps/web/src/assets/json/light-theme.json, apps/web/src/components/fragments/mini-code-editor.tsx, apps/web/src/context/appearance.tsx, apps/web/src/context/authenticated-user-data.tsx, apps/web/src/context/client.tsx, apps/web/src/context/extensions.tsx, apps/web/src/layout/toolbar/index.tsx, apps/web/src/lib/code-editor/format.ts, apps/web/src/lib/code-editor/suggest-language.ts, apps/web/src/lib/editor/editing.ts, apps/web/src/lib/editor/extensions/block-action-menu/component.tsx, apps/web/src/lib/editor/extensions/block-action-menu/plugin.tsx, apps/web/src/lib/editor/extensions/code-block/menu.tsx, apps/web/src/lib/editor/extensions/code-block/node.tsx, apps/web/src/lib/editor/extensions/code-block/view.tsx, apps/web/src/lib/editor/extensions/collab-cursor.tsx, apps/web/src/lib/editor/extensions/element-menu/component.tsx, apps/web/src/lib/editor/extensions/element-menu/editor.tsx, apps/web/src/lib/editor/extensions/element-menu/index.ts, apps/web/src/lib/editor/extensions/element-menu/plugin.tsx, apps/web/src/lib/editor/extensions/element/node.tsx, apps/web/src/lib/editor/extensions/embed/menu.tsx, apps/web/src/lib/editor/extensions/embed/view.tsx, apps/web/src/lib/editor/extensions/image/menu.tsx, apps/web/src/lib/editor/extensions/image/view.tsx, apps/web/src/lib/editor/extensions/index.ts, apps/web/src/lib/editor/extensions/slash-menu/component.tsx, apps/web/src/lib/monaco.ts, apps/web/src/styles/styles.css, apps/web/src/styles/styles.scss, apps/web/src/views/auth/error-messages.tsx, apps/web/src/views/conflict/index.tsx, apps/web/src/views/content-piece/sections/details/slug.tsx, apps/web/src/views/editor/editor.tsx, apps/web/src/views/editor/menus/bubble/block.tsx, apps/web/src/views/editor/menus/bubble/format.tsx, apps/web/src/views/editor/menus/bubble/index.tsx, apps/web/src/views/editor/menus/bubble/link.tsx, apps/web/src/views/editor/menus/bubble/table.tsx, apps/web/src/views/editor/menus/index.ts, apps/web/src/views/extensions/extension-card.tsx, apps/web/src/views/git/sync-view/index.tsx, apps/web/src/views/settings/api/configure-subsection.tsx, apps/web/src/views/settings/appearance.tsx, apps/web/src/views/settings/editor/index.tsx, apps/web/src/views/settings/editor/options.ts, apps/web/src/views/settings/transformers/index.tsx, apps/web/src/views/settings/webhooks/configure-webhook-subsection.tsx, apps/web/src/views/settings/webhooks/events.ts, apps/web/tsconfig.json, apps/web/vite.config.ts, package.json, packages/backend/src/database/comments.ts, packages/backend/src/database/index.ts, packages/backend/src/database/transformers.ts, packages/backend/src/database/users.ts, packages/backend/src/database/webhooks.ts, packages/backend/src/database/workspace-memberships.ts, packages/backend/src/database/workspace-settings.ts, packages/backend/src/env.ts, packages/backend/src/events/comment.ts, packages/backend/src/events/content-group.ts, packages/backend/src/events/content-piece.ts, packages/backend/src/events/extension.ts, packages/backend/src/events/git-data.ts, packages/backend/src/events/index.ts, packages/backend/src/events/role.ts, packages/backend/src/events/tag.ts, packages/backend/src/events/token.ts, packages/backend/src/events/transformer.ts, packages/backend/src/events/user-settings.ts, packages/backend/src/events/user.ts, packages/backend/src/events/variant.ts, packages/backend/src/events/webhook.ts, packages/backend/src/events/workspace-membership.ts, packages/backend/src/events/workspace-settings.ts, packages/backend/src/events/workspace.ts, packages/backend/src/index.ts, packages/backend/src/lib/auth.ts, packages/backend/src/lib/context.ts, packages/backend/src/lib/git-sync/github/index.ts, packages/backend/src/lib/git-sync/github/process-content.ts, packages/backend/src/lib/git-sync/hooks.ts, packages/backend/src/lib/git-sync/index.ts, packages/backend/src/lib/git-sync/process-content.ts, packages/backend/src/lib/git-sync/types.ts, packages/backend/src/lib/host-config.ts, packages/backend/src/lib/index.ts, packages/backend/src/lib/middleware.ts, packages/backend/src/lib/mongo.ts, packages/backend/src/lib/processing.ts, packages/backend/src/lib/session.ts, packages/backend/src/lib/trpc.ts, packages/backend/src/lib/webhooks.ts, packages/backend/src/plugins/database.ts, packages/backend/src/plugins/email.ts, packages/backend/src/plugins/git-sync.ts, packages/backend/src/plugins/host-config.ts, packages/backend/src/plugins/oauth.ts, packages/backend/src/plugins/pub-sub.ts, packages/backend/src/plugins/s3.ts, packages/backend/src/plugins/search.ts, packages/backend/src/plugins/session.ts, packages/backend/src/plugins/trpc.ts, packages/backend/src/routes/auth.ts, packages/backend/src/routes/comments.ts, packages/backend/src/routes/content-groups.ts, packages/backend/src/routes/content-pieces.ts, packages/backend/src/routes/extensions.ts, packages/backend/src/routes/git/github/index.ts, packages/backend/src/routes/git/github/pull.ts, packages/backend/src/routes/git/github/synced-pieces.ts, packages/backend/src/routes/git/index.ts, packages/backend/src/routes/git/process-records.ts, packages/backend/src/routes/index.ts, packages/backend/src/routes/roles.ts, packages/backend/src/routes/search.ts, packages/backend/src/routes/tags.ts, packages/backend/src/routes/tokens.ts, packages/backend/src/routes/transformers.ts, packages/backend/src/routes/user-settings.ts, packages/backend/src/routes/users.ts, packages/backend/src/routes/utils.ts, packages/backend/src/routes/variants.ts, packages/backend/src/routes/verification.ts, packages/backend/src/routes/webhooks.ts, packages/backend/src/routes/workspace-memberships.ts, packages/backend/src/routes/workspace-settings.ts, packages/backend/src/routes/workspaces.ts, packages/backend/src/server.ts, packages/components/src/primitives/input.tsx, packages/components/src/primitives/tooltip.tsx, packages/editor/src/code-block.ts, packages/editor/src/element.ts, packages/editor/src/embed.ts, packages/editor/src/image.ts, packages/editor/src/index.ts, packages/emails/src/render-email.tsx, packages/extensions/src/dev/spec.json, packages/extensions/src/hashnode/spec.json, packages/extensions/src/mdx/functions/configure.ts, packages/extensions/src/mdx/functions/uninstall.ts, packages/extensions/src/mdx/icon-dark.svg, packages/extensions/src/mdx/icon.svg, packages/extensions/src/mdx/spec.json, packages/extensions/src/medium/spec.json, packages/sdk/javascript/package.json, packages/sdk/javascript/src/api/client.ts, packages/sdk/javascript/src/api/index.ts, packages/sdk/javascript/src/api/request.ts, packages/sdk/javascript/src/transformers/content-walker.ts, packages/sdk/javascript/src/transformers/output-transformers.ts, pnpm-lock.yaml
Commit date: 2023-10-10 16:17:42 +0200
Commit message: Vrite v0.3 (#45)

- Replace wrapper with element;
- Add XML-like syntax for elements;
- Redesign editor block menus;
- Add MDX extension;
- Allow CORS API access;
- Restructure @vrite/backend;
Diff: diff --git a/.gitignore b/.gitignore
index f1bbf56..8e9a8e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,10 +24,11 @@ npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
 .pnpm-debug.log*
 
 # local env files
+docker.env
 .env
 .env.local
 .env.development.local
 .env.test.local
 .env.production.local
diff --git a/apps/backend/api/src/api.ts b/apps/backend/api/src/api.ts
index 36cf662..79c74c6 100644
--- a/apps/backend/api/src/api.ts
+++ b/apps/backend/api/src/api.ts
@@ -2,11 +2,11 @@ import { publicPlugin, appRouter, createContext } from "@vrite/backend";
 import rateLimitPlugin from "@fastify/rate-limit";
 import {
   createOpenApiNodeHttpHandler,
   CreateOpenApiNodeHttpHandlerOptions
 } from "trpc-openapi/dist/adapters/node-http/core";
-import corsPlugin from "@fastify/cors";
+import corsPlugin, { OriginFunction } from "@fastify/cors";
 import { OpenApiRouter } from "trpc-openapi";
 import { AnyRouter } from "@trpc/server";
 import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
 
 type CreateOpenApiFastifyPluginOptions<TRouter extends OpenApiRouter> =
@@ -53,40 +53,42 @@ const fastifyTRPCOpenApiPlugin = <TRouter extends AnyRouter>(
     }
   });
   done();
 };
 const apiService = publicPlugin(async (fastify) => {
+  const originCallback: OriginFunction = (origin, callback) => {
+    if (!origin || origin === "null") {
+      callback(null, true);
+
+      return;
+    }
+
+    const { hostname } = new URL(origin);
+    const appHostname = new URL(fastify.config.PUBLIC_APP_URL).hostname;
+
+    if (
+      hostname === "localhost" ||
+      hostname.endsWith(appHostname) ||
+      (fastify.config.VRITE_CLOUD && hostname.endsWith("swagger.io"))
+    ) {
+      callback(null, true);
+
+      return;
+    }
+
+    callback(new Error("Not allowed"), false);
+  };
+
   await fastify.register(rateLimitPlugin, {
     max: 500,
     timeWindow: "1 minute",
     redis: fastify.redis
   });
   await fastify.register(corsPlugin, {
+    origin: true,
     credentials: true,
-    methods: ["GET", "DELETE", "PUT", "POST"],
-    origin(origin, callback) {
-      if (!origin || origin === "null") {
-        callback(null, true);
-
-        return;
-      }
-
-      const { hostname } = new URL(origin);
-      const appHostname = new URL(fastify.config.PUBLIC_APP_URL).hostname;
-
-      if (
-        hostname === "localhost" ||
-        hostname.endsWith(appHostname) ||
-        (fastify.config.VRITE_CLOUD && hostname.endsWith("swagger.io"))
-      ) {
-        callback(null, true);
-
-        return;
-      }
-
-      callback(new Error("Not allowed"), false);
-    }
+    methods: ["GET", "DELETE", "PUT", "POST"]
   });
   await fastify.register(fastifyTRPCOpenApiPlugin, {
     basePath: "/",
     router: appRouter,
     createContext({ req, res }: { req: FastifyRequest; res: FastifyReply }) {
diff --git a/apps/backend/api/src/index.ts b/apps/backend/api/src/index.ts
index e3dab61..48f0092 100644
--- a/apps/backend/api/src/index.ts
+++ b/apps/backend/api/src/index.ts
@@ -1,19 +1,26 @@
 import { apiService } from "./api";
 import { generateOpenApiDocument } from "trpc-openapi";
 import { createServer, appRouter } from "@vrite/backend";
 
 (async () => {
-  const server = await createServer();
+  const server = await createServer({
+    database: true,
+    pubSub: true,
+    auth: true,
+    email: true,
+    gitSync: true,
+    search: true
+  });
 
   await server.register(apiService);
   server.get("/swagger.json", (req, res) => {
     res.send(
       generateOpenApiDocument(appRouter, {
         baseUrl: server.config.PUBLIC_API_URL,
         title: "Vrite API",
-        version: "0.2.0"
+        version: "0.3.0"
       })
     );
   });
 
   return server.listen({ host: server.config.HOST, port: server.config.PORT }, (err) => {
diff --git a/apps/backend/app/src/app.ts b/apps/backend/app/src/app.ts
index 6f9a290..eeb7717 100644
--- a/apps/backend/app/src/app.ts
+++ b/apps/backend/app/src/app.ts
@@ -1,23 +1,22 @@
-import { appRouter, errors, publicPlugin, trpcPlugin } from "@vrite/backend";
+import { errors, publicPlugin, trpcPlugin, processAuth } from "@vrite/backend";
 import staticPlugin from "@fastify/static";
 import websocketPlugin from "@fastify/websocket";
 import axios from "axios";
 import viewPlugin from "@fastify/view";
 import handlebars from "handlebars";
 import { FastifyReply } from "fastify";
-import { processAuth } from "@vrite/backend/src/lib/auth";
 import { nanoid } from "nanoid";
 import multipartPlugin from "@fastify/multipart";
 import mime from "mime-types";
 import sharp from "sharp";
 import { PutObjectCommand } from "@aws-sdk/client-s3";
 import path from "path";
 
 const appService = publicPlugin(async (fastify) => {
   const renderPage = async (reply: FastifyReply): Promise<void> => {
-    return reply.view("index.html", {
+    return reply.header("X-Frame-Options", "SAMEORIGIN").view("index.html", {
       PUBLIC_APP_URL: fastify.config.PUBLIC_APP_URL,
       PUBLIC_API_URL: fastify.config.PUBLIC_API_URL,
       PUBLIC_COLLAB_URL: fastify.config.PUBLIC_COLLAB_URL,
       PUBLIC_ASSETS_URL: fastify.config.PUBLIC_ASSETS_URL,
       PUBLIC_DISABLE_ANALYTICS: fastify.config.PUBLIC_DISABLE_ANALYTICS,
@@ -49,61 +48,10 @@ const appService = publicPlugin(async (fastify) => {
     return renderPage(reply);
   });
   fastify.setNotFoundHandler(async (_request, reply) => {
     return renderPage(reply);
   });
-  fastify.get<{ Querystring: { url: string } }>("/proxy*", async (request, reply) => {
-    const filterOutRegex =
-      /(localhost|\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?::\d{0,4})?\b)/;
-
-    if (request.headers.origin) {
-      reply.header("Access-Control-Allow-Origin", fastify.config.PUBLIC_APP_URL);
-      reply.header("Access-Control-Allow-Methods", "GET");
-      reply.header(
-        "Access-Control-Allow-Headers",
-        request.headers["access-control-request-headers"]
-      );
-    } else if (
-      fastify.config.NODE_ENV !== "development" &&
-      !fastify.config.PUBLIC_APP_URL.includes("localhost")
-    ) {
-      // Prevent proxy abuse in production
-      return reply.status(400).send("Invalid Origin");
-    }
-
-    if (
-      filterOutRegex.test(request.query.url) &&
-      !request.query.url.includes(fastify.config.PUBLIC_ASSETS_URL)
-    ) {
-      return reply.status(400).send("Invalid URL");
-    }
-
-    if (request.method === "OPTIONS") {
-      // CORS Preflight
-      reply.send();
-    } else {
-      const targetURL = request.query.url;
-
-      try {
-        const response = await axios.get(targetURL, {
-          responseType: "arraybuffer"
-        });
-
-        if (!`${response.headers["content-type"]}`.includes("image")) {
-          return reply.status(400).send("Invalid Content-Type");
-        }
-
-        reply.header("content-type", response.headers["content-type"]);
-        reply.send(Buffer.from(response.data, "binary"));
-      } catch (error) {
-        // eslint-disable-next-line no-console
-        console.error(error);
-
-        return reply.status(500).send("Could not fetch");
-      }
-    }
-  });
   fastify.post<{
     Body: Buffer;
   }>("/upload", async (req, res) => {
     if (req.headers.origin) {
       res.header("Access-Control-Allow-Origin", fastify.config.PUBLIC_APP_URL);
diff --git a/apps/backend/app/src/index.ts b/apps/backend/app/src/index.ts
index 7f400ee..00b9539 100644
--- a/apps/backend/app/src/index.ts
+++ b/apps/backend/app/src/index.ts
@@ -1,10 +1,18 @@
 import { appService } from "./app";
 import { createServer } from "@vrite/backend";
 
 (async () => {
-  const server = await createServer();
+  const server = await createServer({
+    database: true,
+    pubSub: true,
+    auth: true,
+    email: true,
+    gitSync: true,
+    search: true,
+    storage: true
+  });
 
   await server.register(appService);
   server.listen({ host: server.config.HOST, port: server.config.PORT }, (err) => {
     if (err) {
       server.log.error(err);
diff --git a/apps/backend/assets/src/api.ts b/apps/backend/assets/src/assets.ts
similarity index 94%
rename from apps/backend/assets/src/api.ts
rename to apps/backend/assets/src/assets.ts
index 6ea413e..9a87733 100644
--- a/apps/backend/assets/src/api.ts
+++ b/apps/backend/assets/src/assets.ts
@@ -44,11 +44,14 @@ const assetsService = publicPlugin(async (fastify) => {
     const sourceContentType = (sourceResponse.ContentType || "").toLowerCase();
     const sendSource = async (): Promise<void> => {
       await reply.header("Content-Type", sourceContentType).send(sourceAsset);
     };
 
-    reply.header("Access-Control-Allow-Origin", fastify.config.PUBLIC_APP_URL);
+    reply.header(
+      "Access-Control-Allow-Origin",
+      fastify.config.NODE_ENV === "development" ? "*" : fastify.config.PUBLIC_APP_URL
+    );
     reply.header("Access-Control-Allow-Methods", "GET");
 
     if (!sourceAsset) return reply.status(404).send();
 
     if (!Object.values(imageMimeTypes).includes(sourceContentType)) {
diff --git a/apps/backend/assets/src/index.ts b/apps/backend/assets/src/index.ts
index df04edc..4e8e485 100644
--- a/apps/backend/assets/src/index.ts
+++ b/apps/backend/assets/src/index.ts
@@ -1,10 +1,12 @@
-import { assetsService } from "./api";
+import { assetsService } from "./assets";
 import { createServer } from "@vrite/backend";
 
 (async () => {
-  const server = await createServer();
+  const server = await createServer({
+    storage: true
+  });
 
   await server.register(assetsService);
 
   return server.listen({ host: server.config.HOST, port: server.config.PORT }, (err) => {
     if (err) {
diff --git a/apps/backend/collaboration/src/extensions/git-sync.ts b/apps/backend/collaboration/src/extensions/git-sync.ts
index d34338e..bb3f844 100644
--- a/apps/backend/collaboration/src/extensions/git-sync.ts
+++ b/apps/backend/collaboration/src/extensions/git-sync.ts
@@ -1,29 +1,23 @@
 import { Extension, onChangePayload, onDisconnectPayload } from "@hocuspocus/server";
 import {
-  GitData,
-  ObjectId,
   createGenericOutputContentProcessor,
   docToJSON,
   getContentPiecesCollection,
   getGitDataCollection,
-  jsonToBuffer
+  jsonToBuffer,
+  publishGitDataEvent
 } from "@vrite/backend";
-import { createEventPublisher } from "@vrite/backend/src/lib/pub-sub";
 import { FastifyInstance } from "fastify";
+import { ObjectId } from "mongodb";
 import crypto from "node:crypto";
 
 interface Configuration {
   debounce: number | false | null;
   debounceMaxWait: number;
 }
 
-type GitDataEvent = {
-  action: "update";
-  data: Partial<GitData>;
-};
-
 class GitSync implements Extension {
   private configuration: Configuration = {
     debounce: 5000,
     debounceMaxWait: 20000
   };
@@ -34,14 +28,10 @@ class GitSync implements Extension {
 
   private contentPiecesCollection: ReturnType<typeof getContentPiecesCollection>;
 
   private debounced: Map<string, { timeout: NodeJS.Timeout; start: number }> = new Map();
 
-  private publishGitDataEvent = createEventPublisher<GitDataEvent>((workspaceId) => {
-    return `gitData:${workspaceId}`;
-  });
-
   public constructor(fastify: FastifyInstance, configuration?: Partial<Configuration>) {
     this.fastify = fastify;
     this.configuration = {
       ...this.configuration,
       ...configuration
@@ -119,11 +109,11 @@ class GitSync implements Extension {
         $set: {
           "records.$.currentHash": currentHash
         }
       }
     );
-    this.publishGitDataEvent({ fastify: this.fastify }, `${details.context.workspaceId}`, {
+    publishGitDataEvent({ fastify: this.fastify }, `${details.context.workspaceId}`, {
       action: "update",
       data: {
         records: gitData.records.map((record: any) => {
           if (record.contentPieceId.toString() === contentPieceId) {
             return {
diff --git a/apps/backend/collaboration/src/extensions/search-indexing.ts b/apps/backend/collaboration/src/extensions/search-indexing.ts
index 1ac46b3..63043d8 100644
--- a/apps/backend/collaboration/src/extensions/search-indexing.ts
+++ b/apps/backend/collaboration/src/extensions/search-indexing.ts
@@ -1,8 +1,9 @@
 import { Extension, onChangePayload, onDisconnectPayload } from "@hocuspocus/server";
-import { ObjectId, docToBuffer, getContentPiecesCollection } from "@vrite/backend";
+import { docToBuffer, getContentPiecesCollection } from "@vrite/backend";
 import { FastifyInstance } from "fastify";
+import { ObjectId } from "mongodb";
 
 interface Configuration {
   debounce: number | false | null;
   debounceMaxWait: number;
 }
diff --git a/apps/backend/collaboration/src/index.ts b/apps/backend/collaboration/src/index.ts
index 77b0a3b..f8e7d44 100644
--- a/apps/backend/collaboration/src/index.ts
+++ b/apps/backend/collaboration/src/index.ts
@@ -1,8 +1,13 @@
 import { writingPlugin } from "./writing";
 import { createServer } from "@vrite/backend";
 
 (async () => {
-  const server = await createServer();
+  const server = await createServer({
+    database: true,
+    auth: true,
+    pubSub: true,
+    search: true
+  });
 
   await server.register(writingPlugin);
 })();
diff --git a/apps/backend/collaboration/src/writing.ts b/apps/backend/collaboration/src/writing.ts
index fb4a3c8..405e943 100644
--- a/apps/backend/collaboration/src/writing.ts
+++ b/apps/backend/collaboration/src/writing.ts
@@ -1,12 +1,16 @@
-import { publicPlugin, getContentsCollection, getContentVariantsCollection } from "@vrite/backend";
+import {
+  publicPlugin,
+  getContentsCollection,
+  getContentVariantsCollection,
+  errors,
+  SessionData
+} from "@vrite/backend";
 import { Server } from "@hocuspocus/server";
 import { Database } from "@hocuspocus/extension-database";
 import { Redis } from "@hocuspocus/extension-redis";
 import { ObjectId, Binary } from "mongodb";
-import { SessionData } from "@vrite/backend/src/lib/session";
-import { unauthorized } from "@vrite/backend/src/lib/errors";
 import { SearchIndexing } from "#extensions/search-indexing";
 import { GitSync } from "#extensions/git-sync";
 
 const writingPlugin = publicPlugin(async (fastify) => {
   const contentsCollection = getContentsCollection(fastify.mongo.db!);
@@ -16,17 +20,17 @@ const writingPlugin = publicPlugin(async (fastify) => {
     address: fastify.config.HOST,
     async onAuthenticate(data) {
       const cookies = fastify.parseCookie(data.requestHeaders.cookie || "");
 
       if (!cookies.accessToken) {
-        throw unauthorized();
+        throw errors.unauthorized();
       }
 
       const token = fastify.unsignCookie(cookies.accessToken || "")?.value || "";
 
       if (!token) {
-        throw unauthorized();
+        throw errors.unauthorized();
       }
 
       const { sessionId } = fastify.jwt.verify<{ sessionId: string }>(token);
       const sessionCache = await fastify.redis.get(`session:${sessionId}`);
       const sessionData = JSON.parse(sessionCache || "{}") as SessionData;
diff --git a/apps/backend/extensions/package.json b/apps/backend/extensions/package.json
index da50d82..820886f 100644
--- a/apps/backend/extensions/package.json
+++ b/apps/backend/extensions/package.json
@@ -8,16 +8,38 @@
     "build": "scripts build-node src/index.ts",
     "start": "node ./dist/index.js"
   },
   "dependencies": {
     "@fastify/cors": "^8.3.0",
+    "@prettier/sync": "^0.3.0",
     "@trpc/server": "^10.35.0",
+    "@types/hast": "^3.0.1",
+    "@types/html-to-text": "^9.0.1",
+    "@types/js-yaml": "^4.0.6",
+    "@types/mdast": "^4.0.1",
     "@vrite/backend": "workspace:*",
     "@vrite/sdk": "workspace:*",
+    "dayjs": "^1.11.9",
     "fastify": "^4.20.0",
+    "hast-util-to-html": "^9.0.0",
+    "html-to-text": "^9.0.5",
+    "js-yaml": "^4.1.0",
+    "mdast-util-from-markdown": "^2.0.0",
+    "mdast-util-frontmatter": "^2.0.1",
+    "mdast-util-gfm": "^3.0.0",
+    "mdast-util-mdx": "^3.0.0",
+    "mdast-util-to-hast": "^13.0.2",
+    "micromark-extension-frontmatter": "^2.0.0",
+    "micromark-extension-gfm": "^3.0.0",
+    "micromark-extension-mdxjs": "^2.0.0",
     "openai": "^4.0.0",
-    "trpc-openapi": "^1.2.0"
+    "prettier": "^3.0.2",
+    "remark": "^15.0.1",
+    "remark-mdx": "^2.3.0",
+    "remark-parse": "^11.0.0",
+    "trpc-openapi": "^1.2.0",
+    "unist-util-visit": "^5.0.0"
   },
   "devDependencies": {
     "@vrite/scripts": "workspace:*"
   }
 }
diff --git a/apps/backend/extensions/src/extensions.ts b/apps/backend/extensions/src/extensions.ts
index 0496a24..be5a5c9 100644
--- a/apps/backend/extensions/src/extensions.ts
+++ b/apps/backend/extensions/src/extensions.ts
@@ -1,15 +1,15 @@
 import { extensionsRouter } from "./routes";
-import { publicPlugin, createContext } from "@vrite/backend";
+import { publicPlugin, createFastifyContext } from "@vrite/backend";
 import {
   createOpenApiNodeHttpHandler,
   CreateOpenApiNodeHttpHandlerOptions
 } from "trpc-openapi/dist/adapters/node-http/core";
-import corsPlugin from "@fastify/cors";
 import { OpenApiRouter } from "trpc-openapi";
 import { AnyRouter } from "@trpc/server";
 import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
+import corsPlugin from "@fastify/cors";
 
 type CreateOpenApiFastifyPluginOptions<TRouter extends OpenApiRouter> =
   CreateOpenApiNodeHttpHandlerOptions<TRouter, any, any> & {
     basePath?: `/${string}`;
   };
@@ -54,19 +54,19 @@ const fastifyTRPCOpenApiPlugin = <TRouter extends AnyRouter>(
   });
   done();
 };
 const extensionsService = publicPlugin(async (fastify) => {
   await fastify.register(corsPlugin, {
-    credentials: true,
     methods: ["GET", "DELETE", "PUT", "POST"],
+    credentials: true,
     origin: true
   });
   await fastify.register(fastifyTRPCOpenApiPlugin, {
     basePath: "/",
     router: extensionsRouter,
     createContext({ req, res }: { req: FastifyRequest; res: FastifyReply }) {
-      return createContext({ req, res }, fastify);
+      return createFastifyContext({ req, res }, fastify);
     }
   });
 });
 
 export { extensionsService };
diff --git a/apps/backend/extensions/src/index.ts b/apps/backend/extensions/src/index.ts
index 5ca3ad8..94aa2ca 100644
--- a/apps/backend/extensions/src/index.ts
+++ b/apps/backend/extensions/src/index.ts
@@ -1,10 +1,10 @@
 import { extensionsService } from "./extensions";
-import { createServer, z } from "@vrite/backend";
+import { createServer } from "@vrite/backend";
 
 (async () => {
-  const server = await createServer();
+  const server = await createServer({});
 
   await server.register(extensionsService);
 
   return server.listen({ host: server.config.HOST, port: server.config.PORT }, (err) => {
     if (err) {
diff --git a/apps/backend/extensions/src/routes/dev/transformer.ts b/apps/backend/extensions/src/routes/dev/transformer.ts
index e3b7b63..46773de 100644
--- a/apps/backend/extensions/src/routes/dev/transformer.ts
+++ b/apps/backend/extensions/src/routes/dev/transformer.ts
@@ -109,11 +109,11 @@ const devOutputTransformer = createOutputTransformer<string>((contentNode) => {
 
     return output;
   };
   const transformContentNode = (
     nodeWalker: JSONContentNodeWalker<
-      JSONContentNode["listItem" | "blockquote" | "doc" | "wrapper"]
+      JSONContentNode["listItem" | "blockquote" | "doc" | "element"]
     >
   ): string => {
     return nodeWalker.children
       .map((child) => {
         const nodeType = child.node.type;
@@ -148,13 +148,13 @@ const devOutputTransformer = createOutputTransformer<string>((contentNode) => {
             )}\n`;
           case "codeBlock":
             return `\n\`\`\`${child.node.attrs?.lang || ""}\n${transformTextNode(
               child as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
             )}\n\`\`\`\n`;
-          case "wrapper":
+          case "element":
             return `\n${transformContentNode(
-              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
+              child as JSONContentNodeWalker<JSONContentNode["element"]>
             )}\n`;
           case "blockquote":
             return `\n${transformContentNode(
               child as JSONContentNodeWalker<JSONContentNode["blockquote"]>
             )
diff --git a/apps/backend/extensions/src/routes/hashnode/transformer.ts b/apps/backend/extensions/src/routes/hashnode/transformer.ts
index 87125bb..736218d 100644
--- a/apps/backend/extensions/src/routes/hashnode/transformer.ts
+++ b/apps/backend/extensions/src/routes/hashnode/transformer.ts
@@ -109,11 +109,11 @@ const hashnodeOutputTransformer = createOutputTransformer<string>((contentNode)
 
     return output;
   };
   const transformContentNode = (
     nodeWalker: JSONContentNodeWalker<
-      JSONContentNode["listItem" | "blockquote" | "doc" | "wrapper"]
+      JSONContentNode["listItem" | "blockquote" | "doc" | "element"]
     >
   ): string => {
     return nodeWalker.children
       .map((child) => {
         const nodeType = child.node.type;
@@ -148,13 +148,13 @@ const hashnodeOutputTransformer = createOutputTransformer<string>((contentNode)
             )}\n`;
           case "codeBlock":
             return `\n\`\`\`${child.node.attrs?.lang || ""}\n${transformTextNode(
               child as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
             )}\n\`\`\`\n`;
-          case "wrapper":
+          case "element":
             return `\n${transformContentNode(
-              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
+              child as JSONContentNodeWalker<JSONContentNode["element"]>
             )}\n`;
           case "blockquote":
             return `\n${transformContentNode(
               child as JSONContentNodeWalker<JSONContentNode["blockquote"]>
             )
diff --git a/apps/backend/extensions/src/routes/index.ts b/apps/backend/extensions/src/routes/index.ts
index 749e6b2..2db5eef 100644
--- a/apps/backend/extensions/src/routes/index.ts
+++ b/apps/backend/extensions/src/routes/index.ts
@@ -1,16 +1,18 @@
 import { devRouter } from "./dev";
 import { hashnodeRouter } from "./hashnode";
 import { gptRouter } from "./gpt";
 import { mediumRouter } from "./medium";
+import { mdxRouter } from "./mdx";
 import { router } from "@vrite/backend";
 
 const extensionsRouter = router({
   dev: devRouter,
   hashnode: hashnodeRouter,
   medium: mediumRouter,
-  gpt: gptRouter
+  gpt: gptRouter,
+  mdx: mdxRouter
 });
 
 type Router = typeof extensionsRouter;
 
 export { extensionsRouter };
diff --git a/apps/backend/extensions/src/routes/mdx/index.ts b/apps/backend/extensions/src/routes/mdx/index.ts
new file mode 100644
index 0000000..5fc3648
--- /dev/null
+++ b/apps/backend/extensions/src/routes/mdx/index.ts
@@ -0,0 +1,62 @@
+import { mdxAsyncInputTransformer } from "./input-transformer";
+import { mdxAsyncOutputTransformer } from "./output-transformer";
+import { procedure, router, z } from "@vrite/backend";
+import { InputTransformer } from "@vrite/sdk/transformers";
+
+const basePath = "/mdx";
+const mdxRouter = router({
+  input: procedure
+    .meta({
+      openapi: {
+        method: "POST",
+        path: `${basePath}/input`
+      }
+    })
+    .input(z.object({ data: z.array(z.string()) }))
+    .output(
+      z.array(
+        z.object({
+          content: z.string(),
+          contentPiece: z.any()
+        })
+      )
+    )
+    .mutation(async ({ input }) => {
+      const output: Array<ReturnType<InputTransformer>> = [];
+
+      for await (const content of input.data) {
+        output.push(await mdxAsyncInputTransformer(content));
+      }
+
+      return output;
+    }),
+  output: procedure
+    .meta({
+      openapi: {
+        method: "POST",
+        path: `${basePath}/output`
+      }
+    })
+    .input(
+      z.object({
+        data: z.array(
+          z.object({
+            content: z.any(),
+            metadata: z.any()
+          })
+        )
+      })
+    )
+    .output(z.array(z.string()))
+    .mutation(async ({ ctx, input }) => {
+      const output: string[] = [];
+
+      for await (const { content, metadata } of input.data) {
+        output.push(await mdxAsyncOutputTransformer(content, metadata));
+      }
+
+      return output;
+    })
+});
+
+export { mdxRouter };
diff --git a/apps/backend/extensions/src/routes/mdx/input-transformer.ts b/apps/backend/extensions/src/routes/mdx/input-transformer.ts
new file mode 100644
index 0000000..5edc0a1
--- /dev/null
+++ b/apps/backend/extensions/src/routes/mdx/input-transformer.ts
@@ -0,0 +1,201 @@
+import { InputTransformer } from "@vrite/sdk/transformers";
+import { mdxjs } from "micromark-extension-mdxjs";
+import { fromMarkdown } from "mdast-util-from-markdown";
+import { MdxJsxAttribute, MdxJsxExpressionAttribute, mdxFromMarkdown } from "mdast-util-mdx";
+import { frontmatter } from "micromark-extension-frontmatter";
+import { frontmatterFromMarkdown } from "mdast-util-frontmatter";
+import { gfmFromMarkdown } from "mdast-util-gfm";
+import { gfm } from "micromark-extension-gfm";
+import { toHtml } from "hast-util-to-html";
+import { toHast, defaultHandlers } from "mdast-util-to-hast";
+import babelPlugin from "prettier/plugins/babel";
+import estreePlugin from "prettier/plugins/estree";
+import { format } from "prettier/standalone";
+import { load } from "js-yaml";
+import dayjs from "dayjs";
+import type { Plugin } from "prettier";
+import type { RootContentMap } from "mdast";
+import type { Element, Text } from "hast";
+
+const attributeProcessingPromises: Array<Promise<any>> = [];
+const processAttribute = async (value: string): Promise<any> => {
+  try {
+    const processedValue = await format(value, {
+      parser: "json-stringify",
+      plugins: [babelPlugin, estreePlugin as Plugin]
+    });
+
+    return JSON.parse(processedValue);
+  } catch (error) {
+    try {
+      return JSON.parse(value);
+    } catch (error) {
+      return value;
+    }
+  }
+};
+const attributesToJSON = async (
+  attributes: Array<MdxJsxAttribute | MdxJsxExpressionAttribute>
+): Promise<Record<string, any>> => {
+  const output: Record<string, any> = {};
+
+  for await (const attribute of attributes) {
+    if (attribute.type === "mdxJsxAttribute") {
+      if (typeof attribute.value === "string") {
+        output[attribute.name] = attribute.value;
+      } else if (attribute.value === null) {
+        output[attribute.name] = true;
+      } else if (attribute.value?.value) {
+        const value = await processAttribute(attribute.value.value);
+
+        output[attribute.name] = value;
+      }
+    }
+  }
+
+  return output;
+};
+const mdxAsyncInputTransformer = async (input: string): Promise<ReturnType<InputTransformer>> => {
+  const mdast = fromMarkdown(input, {
+    extensions: [gfm(), frontmatter(), mdxjs()],
+    mdastExtensions: [gfmFromMarkdown(), frontmatterFromMarkdown(), mdxFromMarkdown()]
+  });
+  const hast = toHast(mdast, {
+    handlers: {
+      mdxjsEsm(state, node: RootContentMap["mdxjsEsm"]) {
+        const result: Element = {
+          tagName: "div",
+          type: "element",
+          properties: {
+            "data-element": "true",
+            "data-type": "Import"
+          },
+          children: state.all({
+            children: [{ type: "code", lang: "mdx", value: node.value.trim() }],
+            type: "root"
+          })
+        };
+
+        state.patch(node, result);
+
+        return state.applyData(node, result);
+      },
+      paragraph(state, node: RootContentMap["paragraph"]) {
+        if (node.children.length === 1 && node.children[0].type === "image") {
+          return defaultHandlers.image(state, node.children[0]);
+        } else if (node.children.length === 1 && node.children[0].type === "mdxJsxTextElement") {
+          return state.all({ type: "root", children: [node.children[0]] })[0];
+        }
+
+        return defaultHandlers.paragraph(state, node);
+      },
+      code(state, node: RootContentMap["code"]) {
+        const result = defaultHandlers.code(state, { ...node, value: node.value.trim() });
+        const meta: string[] = [];
+
+        let title = "";
+
+        (node.meta || "").split(" ").forEach((item) => {
+          if (item.startsWith("title=")) {
+            const match = item.match(/title="(.+?)"/);
+
+            if (match) {
+              title = match[1] || title;
+            }
+          } else {
+            meta.push(item);
+          }
+        });
+
+        const codeElement = result.children[0] as Element;
+        const textElement = codeElement.children[0] as Text;
+
+        result.properties["data-title"] = title;
+        result.properties["data-meta"] = meta.join(" ");
+        textElement.value = textElement.value.trim();
+
+        return result;
+      },
+      list(state, node: RootContentMap["list"]) {
+        const result = defaultHandlers.list(state, node);
+        const className = `${result.properties.className || ""}`;
+
+        if (className.includes("contains-task-list")) {
+          result.properties.className = className.replace("contains-task-list", "").trim();
+          if (!result.properties.className) delete result.properties.className;
+
+          result.properties["data-type"] = "taskList";
+        }
+
+        return result;
+      },
+      mdxFlowExpression() {
+        return undefined;
+      },
+      mdxJsxTextElement(state, node: RootContentMap["mdxJsxTextElement"], parent) {
+        if (parent?.children.length === 1) {
+          return state.all({
+            type: "root",
+            children: [
+              {
+                type: "mdxJsxFlowElement",
+                name: node.name,
+                attributes: node.attributes,
+                children: [{ type: "paragraph", children: node.children }]
+              }
+            ]
+          })[0];
+        }
+
+        return undefined;
+      },
+      mdxTextExpression() {
+        return undefined;
+      },
+      mdxJsxFlowElement(state, node: RootContentMap["mdxJsxFlowElement"]) {
+        const result: Element = {
+          tagName: "div",
+          type: "element",
+          properties: {
+            "data-element": "true",
+            "data-type": node.name
+          },
+          children: state.all(node)
+        };
+        const promise = attributesToJSON(node.attributes).then((attributes) => {
+          result.properties["data-props"] = JSON.stringify(attributes);
+        });
+
+        attributeProcessingPromises.push(promise);
+        state.patch(node, result);
+
+        return state.applyData(node, result);
+      }
+    }
+  });
+  const frontmatterYAML = mdast.children.find(
+    (child) => child.type === "yaml"
+  ) as RootContentMap["yaml"];
+  const { canonicalLink, coverUrl, description, date, slug, title, ...customData } = (
+    frontmatterYAML ? load(frontmatterYAML.value) : {}
+  ) as Record<string, any>;
+
+  await Promise.all(attributeProcessingPromises);
+
+  const content = toHtml(hast);
+
+  return {
+    content,
+    contentPiece: {
+      ...(canonicalLink && { canonicalLink }),
+      ...(coverUrl && { coverUrl }),
+      ...(description && { description: `<p>${description}</p>` }),
+      ...(date && { date: dayjs(date).toISOString() }),
+      ...(slug && { slug }),
+      ...(title && { title }),
+      customData
+    }
+  };
+};
+
+export { mdxAsyncInputTransformer };
diff --git a/apps/backend/extensions/src/routes/mdx/output-transformer.ts b/apps/backend/extensions/src/routes/mdx/output-transformer.ts
new file mode 100644
index 0000000..71bf7f0
--- /dev/null
+++ b/apps/backend/extensions/src/routes/mdx/output-transformer.ts
@@ -0,0 +1,315 @@
+/* eslint-disable no-use-before-define */
+import {
+  createContentWalker,
+  JSONContentNodeWalker,
+  JSONContentNode,
+  GenericJSONContentNode
+} from "@vrite/sdk/transformers";
+import { format } from "prettier/standalone";
+import babelPlugin from "prettier/plugins/babel";
+import estreePlugin from "prettier/plugins/estree";
+import markdownPlugin from "prettier/plugins/markdown";
+import { ContentPiece } from "@vrite/sdk/api";
+import { convert as convertToText } from "html-to-text";
+import { dump } from "js-yaml";
+import dayjs from "dayjs";
+import type { Plugin } from "prettier";
+
+const processCode = async (code: string, hasContent?: boolean): Promise<string> => {
+  const codeTagClosed = code?.trim().replace(/>$/, "/>") || "";
+  const formattedCode = await format(codeTagClosed, {
+    parser: "babel-ts",
+    plugins: [babelPlugin, estreePlugin as Plugin],
+    printWidth: 60,
+    trailingComma: "none",
+    singleQuote: false
+  });
+
+  return formattedCode.replace(/ *?\/>;/gm, hasContent ? ">" : "/>").trim();
+};
+const mdxAsyncOutputTransformer = async (
+  contentNode: GenericJSONContentNode,
+  contentPiece?: Pick<
+    ContentPiece<Record<string, any>>,
+    | "date"
+    | "title"
+    | "description"
+    | "tags"
+    | "members"
+    | "slug"
+    | "filename"
+    | "coverUrl"
+    | "coverAlt"
+    | "customData"
+    | "canonicalLink"
+    | "coverWidth"
+  >
+): Promise<string> => {
+  const contentWalker = createContentWalker(contentNode);
+  const transformText = (textWalker: JSONContentNodeWalker<JSONContentNode["text"]>): string => {
+    let output = "";
+
+    if (textWalker.node.type === "text") {
+      output = textWalker.node.text;
+      textWalker.node.marks?.forEach((mark) => {
+        switch (mark.type) {
+          case "link":
+            output = `[${output}](${mark.attrs.href})`;
+            break;
+          case "bold":
+            output = `**${output}**`;
+            break;
+          case "code":
+            output = `\`${output}\``;
+            break;
+          case "italic":
+            output = `_${output}_`;
+            break;
+          case "strike":
+            output = `~~${output}~~`;
+            break;
+          default:
+            break;
+        }
+      });
+    }
+
+    return output;
+  };
+  const transformTextNode = (
+    paragraphWalker: JSONContentNodeWalker<JSONContentNode["paragraph" | "heading" | "codeBlock"]>
+  ): string => {
+    return `${paragraphWalker.children
+      .map((child) => {
+        if (child.node.type === "text") {
+          return transformText(child as JSONContentNodeWalker<JSONContentNode["text"]>);
+        }
+
+        return "\n";
+      })
+      .join("")}`;
+  };
+  const transformTable = (tableWalker: JSONContentNodeWalker<JSONContentNode["table"]>): string => {
+    let output = "";
+
+    tableWalker.children.forEach((tableRowWalker, rowIndex) => {
+      let isHeader = false;
+
+      const columns = tableRowWalker.children.map((tableCellWalker) => {
+        if (tableCellWalker.node.type === "tableHeader") {
+          isHeader = true;
+        }
+
+        return tableCellWalker.children.map(transformTextNode).join("\n");
+      });
+
+      if (rowIndex === tableWalker.children.length - 1) {
+        output += `| ${columns.map((row) => row.replace(/\n/g, " ")).join(" | ")} |`;
+      } else {
+        output += `| ${columns.map((row) => row.replace(/\n/g, " ")).join(" | ")} |\n`;
+      }
+
+      if (isHeader && rowIndex === 0) {
+        output += `| ${columns.map(() => "---").join(" | ")} |\n`;
+      }
+    });
+
+    return output;
+  };
+  const transformCodeBlock = (
+    codeBlockWalker: JSONContentNodeWalker<JSONContentNode["codeBlock"]>
+  ): string => {
+    const attrs = codeBlockWalker.node.attrs || {};
+
+    let openingTag = `${attrs?.lang || ""}`;
+
+    if (attrs?.title) {
+      openingTag += ` title="${attrs.title}"`;
+    }
+
+    if (attrs?.meta) {
+      openingTag += ` ${attrs.meta}`;
+    }
+
+    return `\`\`\`${openingTag}\n${transformTextNode(codeBlockWalker)}\n\`\`\``;
+  };
+  const transformElement = async (
+    elementWalker: JSONContentNodeWalker<JSONContentNode["element"]>
+  ): Promise<string> => {
+    const { attrs } = elementWalker.node;
+
+    if (attrs.type === "Import" && elementWalker.children[0]?.node?.type === "codeBlock") {
+      return `${transformTextNode(
+        elementWalker.children[0] as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
+      ).trim()}`;
+    }
+
+    const keyValueProps = Object.entries(attrs.props).map(([key, value]) => {
+      if (value === true) return key;
+
+      const useBrackets = typeof value !== "string" || value.includes("\n") || value.includes(`"`);
+
+      return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${useBrackets ? "}" : ""}`;
+    });
+    const openingTag = await processCode(
+      `<${attrs.type}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`,
+      elementWalker.children.length > 0
+    );
+
+    if (elementWalker.children.length > 0) {
+      return `${openingTag}\n${(
+        await transformContentNode(
+          elementWalker as JSONContentNodeWalker<JSONContentNode["element"]>
+        )
+      )
+        .split("\n")
+        .map((line) => `  ${line}`)
+        .join("\n")}\n</${attrs.type}>`;
+    }
+
+    return openingTag;
+  };
+  const transformContentNode = async (
+    nodeWalker: JSONContentNodeWalker<
+      JSONContentNode["listItem" | "taskItem" | "blockquote" | "doc" | "element"]
+    >
+  ): Promise<string> => {
+    const output: string[] = [];
+
+    for await (const child of nodeWalker.children) {
+      const processChildNode = async (): Promise<string> => {
+        const nodeType = child.node.type;
+        const previousSibling = child.previousSibling();
+        const isPreviousSiblingList = ["bulletList", "orderedList", "taskList"].includes(
+          previousSibling?.node.type || ""
+        );
+
+        switch (nodeType) {
+          case "paragraph":
+            return `\n${transformTextNode(
+              child as JSONContentNodeWalker<JSONContentNode["paragraph"]>
+            )}\n`;
+          case "bulletList":
+          case "orderedList":
+          case "taskList":
+            return `${isPreviousSiblingList ? "\n" : ""}${await transformList(
+              child as JSONContentNodeWalker<
+                JSONContentNode["bulletList" | "orderedList" | "taskList"]
+              >
+            )}\n`;
+          case "table":
+            return `\n${transformTable(
+              child as JSONContentNodeWalker<JSONContentNode["table"]>
+            )}\n`;
+          case "horizontalRule":
+            return "\n---\n";
+          case "image":
+            return `\n![${child.node.attrs?.alt || ""}](${child.node.attrs?.src || ""})\n`;
+          case "heading":
+            return `\n${"#".repeat(child.node.attrs?.level || 1)} ${transformTextNode(
+              child as JSONContentNodeWalker<JSONContentNode["heading"]>
+            )}\n`;
+          case "codeBlock":
+            return `\n${transformCodeBlock(
+              child as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
+            )}\n`;
+          case "element":
+            return `${child.node.attrs.type === "Import" ? "" : "\n"}${await transformElement(
+              child as JSONContentNodeWalker<JSONContentNode["element"]>
+            )}\n`;
+          case "blockquote":
+            return `\n${(
+              await transformContentNode(
+                child as JSONContentNodeWalker<JSONContentNode["blockquote"]>
+              )
+            )
+              .split("\n")
+              .map((line) => `> ${line}`)
+              .join("\n")}\n`;
+          default:
+            return "";
+        }
+      };
+
+      output.push(await processChildNode());
+    }
+
+    return output.join("").trim();
+  };
+  const transformList = async (
+    listWalker: JSONContentNodeWalker<JSONContentNode["bulletList" | "orderedList" | "taskList"]>
+  ): Promise<string> => {
+    const listItems: Array<{ content: string; node: JSONContentNode["listItem" | "taskItem"] }> =
+      [];
+
+    for await (const nodeWalker of listWalker.children) {
+      listItems.push({
+        content: await transformContentNode(nodeWalker),
+        node: nodeWalker.node
+      });
+    }
+
+    return listItems
+      .map(({ content, node }, index) => {
+        let prefix = "";
+        let indent = 0;
+
+        if (listWalker.node.type === "taskList" && node.type === "taskItem") {
+          prefix = `${node.attrs?.checked ? "- [x] " : "- [ ] "} `;
+          indent = 2;
+        }
+
+        if (listWalker.node.type === "orderedList") {
+          const start = listWalker.node.attrs?.start || 1;
+
+          prefix = `${start + index}. `;
+          indent = prefix.length;
+        }
+
+        if (listWalker.node.type === "bulletList") {
+          prefix = "- ";
+          indent = prefix.length;
+        }
+
+        return content
+          .split("\n")
+          .map((line, lineIndex) => {
+            if (lineIndex === 0) {
+              return `${prefix}${line}`;
+            }
+
+            return `${" ".repeat(indent)}${line}`;
+          })
+          .join("\n");
+      })
+      .join("\n");
+  };
+  const content = await transformContentNode(
+    contentWalker as JSONContentNodeWalker<JSONContentNode["doc"]>
+  );
+  const frontmatter = dump(
+    {
+      ...(contentPiece?.canonicalLink && { canonicalLink: contentPiece.canonicalLink }),
+      ...(contentPiece?.coverUrl && { coverUrl: contentPiece.coverUrl }),
+      ...(contentPiece?.description && {
+        description: convertToText(contentPiece.description, { wordwrap: false })
+      }),
+      ...(contentPiece?.date && { date: dayjs(contentPiece.date).format("YYYY-MM-DD") }),
+      ...(contentPiece?.slug && { slug: contentPiece.slug }),
+      ...(contentPiece?.title && { title: contentPiece.title }),
+      ...(contentPiece?.customData || {})
+    },
+    { skipInvalid: true, forceQuotes: true, quotingType: '"' }
+  );
+
+  return (
+    await format(
+      `${frontmatter ? "---" : ""}\n${frontmatter.trim()}\n${
+        frontmatter ? "---" : ""
+      }\n\n${content.trim()}`,
+      { plugins: [markdownPlugin], parser: "mdx" }
+    )
+  ).trim();
+};
+
+export { mdxAsyncOutputTransformer };
diff --git a/apps/backend/extensions/src/routes/medium/transformer.ts b/apps/backend/extensions/src/routes/medium/transformer.ts
index 2c24680..838b315 100644
--- a/apps/backend/extensions/src/routes/medium/transformer.ts
+++ b/apps/backend/extensions/src/routes/medium/transformer.ts
@@ -61,11 +61,11 @@ const mediumOutputTransformer = createOutputTransformer<string>((contentNode) =>
 
     return `**${content}**`;
   };
   const transformContentNode = (
     nodeWalker: JSONContentNodeWalker<
-      JSONContentNode["listItem" | "blockquote" | "doc" | "wrapper"]
+      JSONContentNode["listItem" | "blockquote" | "doc" | "element"]
     >
   ): string => {
     return nodeWalker.children
       .map((child) => {
         const nodeType = child.node.type;
@@ -96,13 +96,13 @@ const mediumOutputTransformer = createOutputTransformer<string>((contentNode) =>
             )}\n`;
           case "codeBlock":
             return `\n\`\`\`${child.node.attrs?.lang || ""}\n${transformTextNode(
               child as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
             )}\n\`\`\`\n`;
-          case "wrapper":
+          case "element":
             return `\n${transformContentNode(
-              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
+              child as JSONContentNodeWalker<JSONContentNode["element"]>
             )}\n`;
           case "blockquote":
             return `\n${transformContentNode(
               child as JSONContentNodeWalker<JSONContentNode["blockquote"]>
             )
diff --git a/apps/docs/.astro/types.d.ts b/apps/docs/.astro/types.d.ts
index 12c0923..1d7e9c5 100644
--- a/apps/docs/.astro/types.d.ts
+++ b/apps/docs/.astro/types.d.ts
@@ -1,5 +1,15 @@
+declare module 'astro:content' {
+	interface Render {
+		'.mdx': Promise<{
+			Content: import('astro').MarkdownInstance<{}>['Content'];
+			headings: import('astro').MarkdownHeading[];
+			remarkPluginFrontmatter: Record<string, any>;
+		}>;
+	}
+}
+
 declare module 'astro:content' {
 	interface Render {
 		'.md': Promise<{
 			Content: import('astro').MarkdownInstance<{}>['Content'];
 			headings: import('astro').MarkdownHeading[];
@@ -174,78 +184,87 @@ declare module 'astro:content' {
 
 	type ContentEntryMap = {
 		"docs": {
 "javascript-sdk/javascript-sdk.md": {
 	id: "javascript-sdk/javascript-sdk.md";
-  slug: "javascript-sdk/javascript-sdk";
+  slug: "javascript-sdk/introduction";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "self-hosting/configuration.md": {
 	id: "self-hosting/configuration.md";
   slug: "self-hosting/configuration";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "self-hosting/docker.md": {
 	id: "self-hosting/docker.md";
   slug: "self-hosting/docker";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/configuring-vrite.md": {
 	id: "usage-guide/configuring-vrite.md";
   slug: "usage-guide/configuring-vrite";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/content-editor.md": {
 	id: "usage-guide/content-editor.md";
-  slug: "usage-guide/content-editor";
+  slug: "/usage-guide/content-editor";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/getting-started.md": {
 	id: "usage-guide/getting-started.md";
-  slug: "usage-guide/getting-started";
+  slug: "/usage-guide/getting-started";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/kanban-dashboard.md": {
 	id: "usage-guide/kanban-dashboard.md";
-  slug: "usage-guide/kanban-dashboard";
+  slug: "/usage-guide/kanban-dashboard";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/metadata.md": {
 	id: "usage-guide/metadata.md";
-  slug: "usage-guide/metadata";
+  slug: "/usage-guide/metadata";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/publishing.md": {
 	id: "usage-guide/publishing.md";
-  slug: "usage-guide/publishing";
+  slug: "/usage-guide/publishing";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
 "usage-guide/vrite-extensions.md": {
 	id: "usage-guide/vrite-extensions.md";
-  slug: "usage-guide/vrite-extensions";
+  slug: "/usage-guide/vrite-extensions";
   body: string;
   collection: "docs";
-  data: any
+  data: InferEntrySchema<"docs">
 } & { render(): Render[".md"] };
+};
+"recipes": {
+"test.mdx": {
+	id: "test.mdx";
+  slug: "/recipes/content-pieces";
+  body: string;
+  collection: "recipes";
+  data: InferEntrySchema<"recipes">
+} & { render(): Render[".mdx"] };
 };
 
 	};
 
 	type DataEntryMap = {
diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs
index 528bb36..a52c498 100644
--- a/apps/docs/astro.config.mjs
+++ b/apps/docs/astro.config.mjs
@@ -1,26 +1,32 @@
 import { defineConfig } from "astro/config";
 import solidJs from "@astrojs/solid-js";
 import unocss from "unocss/astro";
 import robotsTxt from "astro-robots-txt";
+import mdx from "@astrojs/mdx";
+import autoImport from "astro-auto-import";
 
 export default defineConfig({
   markdown: {
     shikiConfig: {
       theme: "github-dark"
     }
   },
   integrations: [
+    autoImport({
+      imports: [{ "#components/content": ["Card", "CardGrid", "Warning", "Info"] }]
+    }),
     unocss({ injectReset: true }),
     solidJs(),
     robotsTxt({
       policy: [
         {
           userAgent: "*"
         }
       ]
-    })
+    }),
+    mdx()
   ],
   build: {
     redirects: false
   },
   site: "https://docs.vrite.io",
diff --git a/apps/docs/package.json b/apps/docs/package.json
index f09d9ca..fb6d44c 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -9,27 +9,35 @@
     "build": "astro build",
     "preview": "astro preview",
     "astro": "astro"
   },
   "dependencies": {
+    "@astrojs/mdx": "^1.1.1",
     "@astrojs/sitemap": "^3.0.0",
     "@astrojs/solid-js": "^3.0.1",
     "@mdi/js": "^7.2.96",
+    "@solid-primitives/scheduled": "^1.4.0",
     "@types/marked": "^5.0.1",
     "@unocss/reset": "^0.55.7",
     "@vrite/components": "workspace:*",
+    "@vrite/sdk": "workspace:*",
     "astro": "^3.1.0",
+    "astro-auto-import": "^0.3.1",
+    "astro-icon": "^0.8.1",
     "clsx": "^2.0.0",
     "curl-string": "^3.1.0",
     "marked": "^9.0.0",
     "mini-svg-data-uri": "^1.4.4",
     "nanoid": "^5.0.1",
     "plausible-tracker": "^0.3.8",
+    "seamless-scroll-polyfill": "^2.3.4",
     "shiki": "^0.14.4",
     "solid-js": "^1.7.11",
+    "tinykeys": "^2.1.0",
     "typescript": "^5.2.2",
     "unocss": "^0.55.7",
+    "url-slug": "^4.0.1",
     "vite": "^4.4.9"
   },
   "devDependencies": {
     "@astrojs/node": "^6.0.0",
     "astro-robots-txt": "^1.0.0",
diff --git a/apps/docs/src/components/content/card-grid.astro b/apps/docs/src/components/content/card-grid.astro
new file mode 100644
index 0000000..1183d9d
--- /dev/null
+++ b/apps/docs/src/components/content/card-grid.astro
@@ -0,0 +1,18 @@
+---
+import clsx from "clsx";
+interface Props {
+  cols?: 2 | 3 | 4;
+}
+
+const { props } = Astro;
+---
+
+<div
+  class={clsx("grid grid-reset-margin gap-2 my-4", {
+    "sm:grid-cols-2": !props.cols || props.cols === 2,
+    "sm:grid-cols-3": props.cols === 3,
+    "sm:grid-cols-4": props.cols === 4
+  })}
+>
+  <slot />
+</div>
diff --git a/apps/docs/src/components/content/card.astro b/apps/docs/src/components/content/card.astro
new file mode 100644
index 0000000..0b096e6
--- /dev/null
+++ b/apps/docs/src/components/content/card.astro
@@ -0,0 +1,44 @@
+---
+import { Card as BaseCard, Heading, IconButton } from "#components/primitives";
+import { Icon } from "astro-icon";
+import clsx from "clsx";
+
+interface Props {
+  icon: string;
+  label: string;
+  gradient?: boolean;
+  link: string;
+}
+
+const { props } = Astro;
+---
+
+<a href={props.link} class="not-prose cursor-pointer block my-4"
+  ><BaseCard
+    class={clsx(
+      "w-full flex flex-col m-0 p-0 gap-2 items-start h-full",
+      props.gradient ? "hover:bg-gradient-to-bl" : "!hover:bg-gray-200"
+    )}
+    color={props.gradient ? "primary" : "contrast"}
+  >
+    <div class="flex justify-center items-center pl-3 pr-4 pt-3 w-full">
+      <div class="pr-1 py-1">
+        <Icon
+          name={props.icon}
+          class={clsx("h-6 w-6", props.gradient ? "fill-current" : "fill-[url(#gradient)]")}
+        />
+      </div>
+      <Heading level={2} class="pl-1 flex-1">
+        {props.label}
+      </Heading>
+    </div>
+    <div
+      class={clsx(
+        "flex flex-col justify-center items-start gap-2 w-full px-4 pb-4",
+        props.gradient ? "" : "text-gray-500 dark:text-gray-400"
+      )}
+    >
+      <slot />
+    </div>
+  </BaseCard></a
+>
diff --git a/apps/docs/src/components/content/index.ts b/apps/docs/src/components/content/index.ts
new file mode 100644
index 0000000..0507253
--- /dev/null
+++ b/apps/docs/src/components/content/index.ts
@@ -0,0 +1,4 @@
+export { default as Card } from "./card.astro";
+export { default as CardGrid } from "./card-grid.astro";
+export { default as Warning } from "./warning.astro";
+export { default as Info } from "./info.astro";
diff --git a/apps/docs/src/components/content/info.astro b/apps/docs/src/components/content/info.astro
new file mode 100644
index 0000000..475e9db
--- /dev/null
+++ b/apps/docs/src/components/content/info.astro
@@ -0,0 +1,9 @@
+---
+import { Card, Icon } from "#components/primitives";
+import { mdiInformationSlabCircleOutline } from "@mdi/js";
+---
+
+<Card class="flex items-center justify-start mx-0 my-4" color="contrast">
+  <Icon path={mdiInformationSlabCircleOutline} class="w-6 h-6 mr-2 fill-[url(#gradient)]" />
+  <div class="flex-1 not-prose"><slot /></div>
+</Card>
diff --git a/apps/docs/src/components/content/warning.astro b/apps/docs/src/components/content/warning.astro
new file mode 100644
index 0000000..5c7fc9d
--- /dev/null
+++ b/apps/docs/src/components/content/warning.astro
@@ -0,0 +1,9 @@
+---
+import { Card, Icon } from "#components/primitives";
+import { mdiAlertCircleOutline } from "@mdi/js";
+---
+
+<Card class="flex items-center justify-start m-0 my-4" color="primary">
+  <Icon path={mdiAlertCircleOutline} class="w-6 h-6 mr-2" />
+  <div class="flex-1 not-prose"><slot /></div>
+</Card>
diff --git a/apps/docs/src/components/fragments/endpoint-card-sections.tsx b/apps/docs/src/components/fragments/endpoint-card-sections.tsx
deleted file mode 100644
index 64b0d95..0000000
--- a/apps/docs/src/components/fragments/endpoint-card-sections.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { ParentComponent, createSignal } from "solid-js";
-import { Button } from "#components/primitives";
-
-interface EndpointCardSectionsProps {
-  sections: Array<{ label: string; id: string }>;
-}
-
-const EndpointCardSections: ParentComponent<EndpointCardSectionsProps> = (props) => {
-  const [activeSection, setActiveSection] = createSignal(props.sections[0].id);
-
-  return (
-    <>
-      <div class="flex w-full gap-2">
-        {props.sections.map((section) => {
-          return (
-            <Button
-              variant={section.id === activeSection() ? "solid" : "text"}
-              text={section.id === activeSection() ? "base" : "soft"}
-              color="contrast"
-              class="py-1 m-0 text-xl font-semibold"
-              onClick={() => {
-                setActiveSection(section.id);
-              }}
-            >
-              {section.label}
-            </Button>
-          );
-        })}
-      </div>
-      <div data-active-section={activeSection()}>{props.children}</div>
-    </>
-  );
-};
-
-export { EndpointCardSections };
diff --git a/apps/docs/src/components/fragments/endpoint-card.astro b/apps/docs/src/components/fragments/endpoint-card.astro
deleted file mode 100644
index 8b5a211..0000000
--- a/apps/docs/src/components/fragments/endpoint-card.astro
+++ /dev/null
@@ -1,125 +0,0 @@
----
-import { Code } from "astro:components";
-import { Button, Card, IconButton } from "#components/primitives";
-import curlString from "curl-string";
-import { mdiAsterisk } from "@mdi/js";
-import { EndpointCardSections } from "./endpoint-card-sections";
-
-interface Props {
-    method: string;
-    endpoint: string;
-    parameters?: Array<{
-        name: string;
-        required?: boolean;
-        description?: string;
-        example?:string;
-        schema: { type: string; default?:string };
-    }>;
-    example?: Record<string, any>;
-    requestBody?: string;
-    response?: string;
-}
-
-const body = JSON.stringify( {}, null, 2);
-const sections: Array<{ label: string; id: string }> = [];
-
-if (Astro.props.parameters && Astro.props.parameters.length) {
-    sections.push({ label: "Parameters", id: "parameters" });
-}
-
-if (Astro.props.requestBody) {
-    sections.push({ label: "Body", id: "body" });
-}
-
-sections.push({ label: "Response", id: "response" });
-
-const queryString = new URLSearchParams(
-    (Astro.props.parameters||[]).map((parameter) => {
-        return [parameter.name, parameter.example]
-    }) as string[][]
-).toString();
-const url = `https://api.vrite.io${Astro.props.endpoint}${queryString ? `?${queryString}` : ""}`;
-const parsedBody = JSON.parse(body);
-const curl = curlString(
-    `"${url}"`,
-    {
-        method: Astro.props.method,
-        headers: {
-            Authorization: `Bearer ${"<YOUR-TOKEN>"}`,
-            ...(body === "{}"
-                ? {}
-                : {
-                      "Content-Type": "application/json"
-                  }),
-            Accept: "application/json"
-        },
-        ...(body === "{}"
-            ? {}
-            : {
-                  body: parsedBody
-              })
-    },
-    { colorJson: false, jsonIndentWidth: 4 }
-);
-const code = `${curl}\n`;
----
-
-<Card class="relative p-4 m-0 gap-2 flex flex-col text-gray-700 dark:text-gray-300 my-4 bg-gray-100 dark:bg-gray-900">
-    <div class="flex">
-        <Button badge class="m-0 font-mono font-semibold" size="large" color="contrast">
-            {Astro.props.method}
-            {" "}{Astro.props.endpoint}
-        </Button>
-    </div>
-    <div class="code-block-contrast">
-        <Code code={code} lang="shell" />
-    </div>
-    <EndpointCardSections client:load sections={sections}>
-        {
-            Astro.props.parameters && Astro.props.parameters.length ? (
-                <div class="flex flex-col gap-2 parameters-section">
-                    {(Astro.props.parameters || []).map((parameter) => {
-                        return (
-                            <Card class="m-0 bg-gray-50 dark:bg-gray-800">
-                                <div class="flex items-center">
-                                    <Button badge text="soft" class="m-0 font-mono font-semibold">
-                                        {parameter.name}
-                                    </Button>
-                                    <span class="!bg-transparent text-sm font-mono px-2 flex-1">
-                                        {parameter.schema.type}
-                                    </span>
-                                    {parameter.required && (
-                                        <IconButton
-                                            class="m-0"
-                                            path={mdiAsterisk}
-                                            color="primary"
-                                            badge
-                                            label="Required"
-                                        />
-                                    )}
-                                </div>
-                                {parameter.description && (
-                                    <p class="pl-1 m-0 mt-2">{parameter.description}</p>
-                                )}
-                            </Card>
-                        );
-                    })}
-                </div>
-            ): <></>
-        }
-        {
-            Astro.props.requestBody && (
-                <div class="code-block-contrast body-section">
-                    <Code code={Astro.props.requestBody} lang="typescript"  />
-                </div>
-            )
-        }
-        {
-            Astro.props.response && (
-                <div class="code-block-contrast response-section">
-                    <Code code={Astro.props.response} lang="typescript" />
-                </div>
-            )
-        }
-    </EndpointCardSections>
-</Card>
diff --git a/apps/docs/src/components/fragments/navigation.tsx b/apps/docs/src/components/fragments/footer.tsx
similarity index 80%
rename from apps/docs/src/components/fragments/navigation.tsx
rename to apps/docs/src/components/fragments/footer.tsx
index c9bf72c..7578c36 100644
--- a/apps/docs/src/components/fragments/navigation.tsx
+++ b/apps/docs/src/components/fragments/footer.tsx
@@ -1,21 +1,22 @@
 import { mdiChevronLeft, mdiChevronRight } from "@mdi/js";
 import { Component, Show } from "solid-js";
 import { IconButton } from "#components/primitives";
 
-interface NavigateProps {
-  nextEntry?: { label: string; link: string };
-  previousEntry?: { label: string; link: string };
+interface FooterProps {
+  nextEntry?: { label: string; link: string } | null;
+  previousEntry?: { label: string; link: string } | null;
 }
 
-const Navigation: Component<NavigateProps> = (props) => {
+const Footer: Component<FooterProps> = (props) => {
   return (
     <div class="flex flex-col lg:flex-row w-full gap-2 lg:gap-4 pt-16">
       <div class="flex-1">
         <Show when={props.previousEntry}>
           <IconButton
             label={props.previousEntry!.label}
+            text="soft"
             path={mdiChevronLeft}
             iconProps={{ class: "min-w-8" }}
             size="large"
             class="no-underline flex-1 m-0 justify-start"
             link={props.previousEntry!.link}
@@ -24,10 +25,11 @@ const Navigation: Component<NavigateProps> = (props) => {
       </div>
       <div class="flex-1">
         <Show when={props.nextEntry}>
           <IconButton
             label={<span class="pr-2">{props.nextEntry!.label}</span>}
+            text="soft"
             path={mdiChevronRight}
             iconProps={{ class: "min-w-8" }}
             size="large"
             class="flex-row-reverse no-underline m-0 justify-start"
             link={props.nextEntry!.link}
@@ -36,6 +38,6 @@ const Navigation: Component<NavigateProps> = (props) => {
       </div>
     </div>
   );
 };
 
-export { Navigation };
+export { Footer };
diff --git a/apps/docs/src/components/fragments/header.tsx b/apps/docs/src/components/fragments/header.tsx
index ced8faf..2d5e0e9 100644
--- a/apps/docs/src/components/fragments/header.tsx
+++ b/apps/docs/src/components/fragments/header.tsx
@@ -1,33 +1,103 @@
-import { mdiAppleKeyboardCommand, mdiMagnify } from "@mdi/js";
-import type { Component } from "solid-js";
-import { Icon, IconButton } from "#components/primitives";
-import { logoIcon } from "#assets/icons";
+import { SearchPaletteProvider, useSearchPalette } from "./search-palette";
+import { mdiAppleKeyboardCommand, mdiGithub, mdiMagnify } from "@mdi/js";
+import { For, type Component, Show } from "solid-js";
+import clsx from "clsx";
+import { Button, Icon, IconButton, Tooltip } from "#components/primitives";
+import { discordIcon, logoIcon } from "#assets/icons";
 
 const isAppleDevice = (): boolean => {
   const platform = typeof navigator === "object" ? navigator.platform : "";
   const appleDeviceRegex = /Mac|iPod|iPhone|iPad/;
 
   return appleDeviceRegex.test(platform);
 };
+const externalLinks = [
+  {
+    label: "GitHub",
+    icon: mdiGithub,
+    href: "https://github.com/vriteio/vrite"
+  },
+  {
+    label: "Discord",
+    icon: discordIcon,
+    href: "https://discord.gg/yYqDWyKnqE"
+  }
+];
 const Header: Component = () => {
+  const { opened, setOpened } = useSearchPalette();
+
   return (
-    <div class="top-0 bg-gray-50 dark:bg-gray-800 border-b-2 border-gray-200 dark:border-gray-700 left-0 z-50 items-center justify-center w-full flex py-2 px-4 md:px-3">
+    <div
+      class={clsx(
+        "top-0 gap-2 h-12 fixed bg-gray-50 dark:bg-gray-800 border-gray-200 dark:border-gray-700 border-b-2 right-0 z-1 items-center justify-center w-full flex py-2 px-4 md:px-8",
+        "!pr-[max(1rem,calc((100%-(1536px))/2))]"
+      )}
+    >
+      <div class="flex md:hidden items-center justify-start px-1">
+        <IconButton
+          path={logoIcon}
+          color="primary"
+          link="/"
+          class="bg-gradient-to-tr from-red-500 to-orange-500 m-0 mr-1"
+        />
+        <span class="flex-1 text-2xl font-extrabold text-gray-600 dark:text-gray-200">rite</span>
+      </div>
       <div class="flex-1" />
+      <For each={externalLinks}>
+        {(link) => {
+          return (
+            <a
+              class="flex justify-start items-center group cursor-pointer"
+              target="_blank"
+              href={link.href}
+            >
+              <Tooltip text={link.label} class="mt-1">
+                <IconButton
+                  path={link.icon}
+                  class="m-0 h-8 min-w-8"
+                  iconProps={{ class: "h-5 w-5" }}
+                  text="soft"
+                />
+              </Tooltip>
+            </a>
+          );
+        }}
+      </For>
       <IconButton
         path={mdiMagnify}
         label={
-          <div class="hidden xl:flex w-full items-center min-w-48">
-            <span class="pl-1 flex-1 text-start">Search</span>
-            <kbd class="bg-gray-300 dark:bg-gray-700 group-hover:bg-gray-200 dark:group-hover:bg-gray-800 flex justify-center items-center rounded-md px-1 h-5 text-sm">
-              {isAppleDevice() ? <Icon path={mdiAppleKeyboardCommand} class="h-3 w-3" /> : "Ctrl "}K
-            </kbd>
+          <div class="hidden md:flex w-full items-center">
+            <span class="pl-1 flex-1 text-start pr-3">Search</span>
+            <Show when={typeof window === "object"}>
+              <kbd class="bg-gray-300 dark:bg-gray-700 group-hover:bg-gray-200 dark:group-hover:bg-gray-800 flex justify-center items-center rounded-md px-1 h-5 text-sm">
+                {isAppleDevice() ? (
+                  <Icon path={mdiAppleKeyboardCommand} class="h-3 w-3" />
+                ) : (
+                  "Ctrl "
+                )}
+                K
+              </kbd>
+            </Show>
           </div>
         }
         text="soft"
-        class="@xl:min-w-48 justify-start m-0 group !hidden"
+        class="lg:min-w-48 justify-start m-0 group"
+        onClick={() => {
+          setOpened(!opened());
+        }}
       />
+      <Button color="primary" class="m-0" link="https://app.vrite.io">
+        Sign in
+      </Button>
     </div>
   );
 };
+const HeaderWrapper: Component = () => {
+  return (
+    <SearchPaletteProvider>
+      <Header />
+    </SearchPaletteProvider>
+  );
+};
 
-export { Header };
+export { HeaderWrapper as Header };
diff --git a/apps/docs/src/components/fragments/index.tsx b/apps/docs/src/components/fragments/index.ts
similarity index 69%
rename from apps/docs/src/components/fragments/index.tsx
rename to apps/docs/src/components/fragments/index.ts
index 6bfc94a..aa26b9a 100644
--- a/apps/docs/src/components/fragments/index.tsx
+++ b/apps/docs/src/components/fragments/index.ts
@@ -2,6 +2,8 @@ export * from "./analytics";
 export { default as BaseHead } from "./base-head.astro";
 export * from "./header";
 export * from "./side-bar";
 export * from "./on-this-page";
 export * from "./svg-defs";
-export * from "./navigation";
+export * from "./footer";
+export * from "./search-palette";
+export * from "./footer";
diff --git a/apps/docs/src/components/fragments/on-this-page.tsx b/apps/docs/src/components/fragments/on-this-page.tsx
index 8235ca6..df73834 100644
--- a/apps/docs/src/components/fragments/on-this-page.tsx
+++ b/apps/docs/src/components/fragments/on-this-page.tsx
@@ -1,8 +1,17 @@
-import { Component, For, onMount, onCleanup, createSignal, createMemo } from "solid-js";
+import {
+  Component,
+  For,
+  onMount,
+  onCleanup,
+  createSignal,
+  createMemo,
+  createEffect
+} from "solid-js";
 import { mdiListBox } from "@mdi/js";
 import clsx from "clsx";
+import { scroll } from "seamless-scroll-polyfill";
 import type { MarkdownHeading } from "astro";
 import { Button, IconButton } from "#components/primitives";
 
 interface OnThisPageProps {
   headings: MarkdownHeading[];
@@ -10,18 +19,46 @@ interface OnThisPageProps {
 
 const OnThisPage: Component<OnThisPageProps> = (props) => {
   const [activeHeading, setActiveHeading] = createSignal(props.headings[0]?.slug || "");
   const headings = createMemo(() => {
     return props.headings.filter((heading) => {
-      return heading.depth === 2;
+      return heading.depth === 2 || heading.depth === 3;
     });
   });
+  const scrollToActiveHeading = (smooth?: boolean): void => {
+    const heading = activeHeading();
+    const element = document.getElementById(heading);
+
+    if (!element) return;
+
+    const rect = element.getBoundingClientRect();
+    const y = rect.top + window.scrollY - 60;
+
+    scroll(window, {
+      top: y,
+      behavior: smooth === false ? "instant" : "smooth"
+    });
+  };
+  const handleClick = (event: MouseEvent): void => {
+    const target = event.target as HTMLElement;
+
+    if (target.matches("h2, h3")) {
+      const { id } = target;
+
+      if (id) {
+        setActiveHeading(id);
+        scrollToActiveHeading();
+        history.replaceState(null, "", `#${id}`);
+        navigator.clipboard.writeText(window.location.href);
+      }
+    }
+  };
 
   onMount(() => {
     if (!headings().length) return;
 
-    const observedElements: HTMLElement[] = [];
+    const hash = location.hash.slice(1);
     const setCurrent: IntersectionObserverCallback = (entries) => {
       for (const entry of entries) {
         if (entry.isIntersecting) {
           const { id } = entry.target;
 
@@ -57,21 +94,28 @@ const OnThisPage: Component<OnThisPageProps> = (props) => {
           .map((heading) => `#${heading.slug}`)
           .join(", ")
       )
       .forEach((h) => headingsObserver.observe(h));
     container?.addEventListener("scroll", handleScroll);
+    document.body.addEventListener("click", handleClick);
     onCleanup(() => {
       headingsObserver.disconnect();
       container?.removeEventListener("scroll", handleScroll);
+      document.body.removeEventListener("click", handleClick);
     });
+
+    if (hash) {
+      setActiveHeading(hash);
+      scrollToActiveHeading(false);
+    }
   });
 
   return (
     <>
       <div
         class={clsx(
-          "w-56 flex-col justify-start top-0 pt-16 fixed right-0 hidden xl:flex gap-2",
+          "w-56 flex-col justify-start top-0 pt-24 xl:fixed right-0 hidden xl:flex gap-2",
           "mr-[max(0px,calc((100%-(1536px))/2))]"
         )}
       >
         <IconButton
           text="soft"
@@ -87,17 +131,15 @@ const OnThisPage: Component<OnThisPageProps> = (props) => {
             return (
               <Button
                 variant="text"
                 text={activeHeading() === heading.slug ? "base" : "soft"}
                 color={activeHeading() === heading.slug ? "primary" : "base"}
-                class="text-start m-0"
+                class={clsx("text-start m-0", heading.depth === 3 && "ml-6")}
+                size={heading.depth === 2 ? "medium" : "small"}
                 onClick={() => {
-                  document.getElementById(heading.slug)?.scrollIntoView({
-                    block: "start",
-                    inline: "nearest"
-                  });
                   setActiveHeading(heading.slug);
+                  scrollToActiveHeading();
                 }}
               >
                 {heading.text}
               </Button>
             );
diff --git a/apps/docs/src/components/fragments/search-palette.tsx b/apps/docs/src/components/fragments/search-palette.tsx
new file mode 100644
index 0000000..f23cfe6
--- /dev/null
+++ b/apps/docs/src/components/fragments/search-palette.tsx
@@ -0,0 +1,502 @@
+import {
+  Accessor,
+  Component,
+  For,
+  Match,
+  ParentComponent,
+  Setter,
+  Show,
+  Switch,
+  createEffect,
+  createSignal,
+  on,
+  onCleanup,
+  useContext
+} from "solid-js";
+import {
+  mdiChevronRight,
+  mdiCreationOutline,
+  mdiFileDocumentOutline,
+  mdiHeadSnowflakeOutline,
+  mdiInformationOutline,
+  mdiKeyboardEsc,
+  mdiKeyboardReturn,
+  mdiMagnify,
+  mdiSwapVertical
+} from "@mdi/js";
+import clsx from "clsx";
+import { scrollIntoView } from "seamless-scroll-polyfill";
+import { createContext } from "solid-js";
+import { debounce } from "@solid-primitives/scheduled";
+import { convert as convertToSlug } from "url-slug";
+import { marked } from "marked";
+import { createClient, SearchResult } from "@vrite/sdk/api";
+import {
+  Button,
+  Card,
+  Icon,
+  IconButton,
+  Input,
+  Loader,
+  Overlay,
+  Tooltip
+} from "#components/primitives";
+
+interface SearchPaletteProps {
+  opened: boolean;
+  setOpened(opened: boolean): void;
+}
+interface SearchPaletteContextData {
+  opened: Accessor<boolean>;
+  setOpened: Setter<boolean>;
+}
+
+const SearchPaletteContext = createContext<SearchPaletteContextData>();
+const SearchPalette: Component<SearchPaletteProps> = (props) => {
+  const client = createClient({
+    token: import.meta.env.PUBLIC_VRITE_SEARCH_TOKEN
+  });
+  const [inputRef, setInputRef] = createSignal<HTMLInputElement | null>(null);
+  const [abortControllerRef, setAbortControllerRef] = createSignal<AbortController | null>(null);
+  const [mode, setMode] = createSignal<"search" | "ask">("search");
+  const [searchResults, setSearchResults] = createSignal<SearchResult[]>([]);
+  const [answer, setAnswer] = createSignal<string>("");
+  const [loading, setLoading] = createSignal(false);
+  const [mouseHoverEnabled, setMouseHoverEnabled] = createSignal(false);
+  const [selectedIndex, setSelectedIndex] = createSignal(0);
+  const [query, setQuery] = createSignal("");
+  const ask = async (): Promise<void> => {
+    let content = "";
+
+    client.useSignal(abortControllerRef()?.signal || null).ask({
+      query: query(),
+      onError(error) {
+        setLoading(false);
+        throw error;
+      },
+      onChunk(chunk) {
+        content += chunk;
+        setAnswer(marked.parse(content, { gfm: true }));
+      },
+      onEnd() {
+        setLoading(false);
+      }
+    });
+    setLoading(false);
+  };
+  const search = debounce(async () => {
+    setSearchResults([]);
+
+    if (abortControllerRef()) abortControllerRef()?.abort();
+
+    if (!query()) {
+      setLoading(false);
+      setSearchResults([]);
+
+      return;
+    }
+
+    setAbortControllerRef(new AbortController());
+
+    try {
+      const search = await client
+        .useSignal(abortControllerRef()?.signal || null)
+        .search({ query: query() });
+
+      setSearchResults(search);
+      setLoading(false);
+
+      return;
+    } catch (error) {
+      const trpcError = error as any;
+      const causeErrorName = trpcError.cause?.name?.toLowerCase() || "";
+
+      if (!causeErrorName.includes("aborterror") && abortControllerRef()?.signal.aborted) {
+        setLoading(false);
+      }
+    }
+  }, 150);
+  const scrollToSelectedResult = (smooth?: boolean): void => {
+    const selectedResultElement = document.querySelector("[data-selected=true]");
+
+    if (selectedResultElement) {
+      scrollIntoView(selectedResultElement, {
+        behavior: smooth ? "smooth" : "instant",
+        block: "center"
+      });
+    }
+  };
+  const goToContentPiece = (searchResult: SearchResult): void => {
+    // eslint-disable-next-line no-console
+    props.setOpened(false);
+
+    const { slug } = searchResult.contentPiece;
+    const [title, subHeading1, subHeading2] = searchResult.breadcrumb;
+
+    window.location.href = `/${slug.startsWith("/") ? slug.slice(1) : slug}#${convertToSlug(
+      subHeading2 || subHeading1
+    )}`;
+  };
+
+  createEffect(
+    on(
+      query,
+      () => {
+        if (mode() === "search") {
+          search.clear();
+          search();
+        }
+      },
+      { defer: true }
+    )
+  );
+  createEffect(
+    on(mode, () => {
+      setMouseHoverEnabled(false);
+      setSelectedIndex(0);
+      setLoading(false);
+      setAnswer("");
+      setSearchResults([]);
+      setQuery("");
+    })
+  );
+  createEffect(() => {
+    if (inputRef() && props.opened && mode()) {
+      setTimeout(() => {
+        inputRef()?.focus();
+      }, 300);
+    }
+  });
+  createEffect(() => {
+    import("tinykeys").then(({ createKeybindingsHandler }) => {
+      const keyShortcutHandler = createKeybindingsHandler({
+        "$mod+KeyK": (event) => {
+          props.setOpened(!props.opened);
+        },
+        "escape": (event) => {
+          if (!props.opened) return;
+
+          props.setOpened(false);
+        },
+        "ArrowUp": (event) => {
+          if (!props.opened) return;
+
+          setMouseHoverEnabled(false);
+          event.preventDefault();
+          event.stopPropagation();
+
+          if (selectedIndex() > 0) {
+            setSelectedIndex(selectedIndex() - 1);
+            scrollToSelectedResult();
+          } else if (mode() === "search") {
+            setSelectedIndex(searchResults().length - 1);
+            scrollToSelectedResult(true);
+          }
+        },
+        "ArrowDown": (event) => {
+          if (!props.opened) return;
+
+          setMouseHoverEnabled(false);
+          event.preventDefault();
+          event.stopPropagation();
+
+          if (mode() === "search" && selectedIndex() < searchResults().length - 1) {
+            setSelectedIndex(selectedIndex() + 1);
+            scrollToSelectedResult();
+          } else {
+            setSelectedIndex(0);
+            scrollToSelectedResult(true);
+          }
+        },
+        "Enter": (event) => {
+          if (!props.opened) return;
+
+          if (mode() === "search") {
+            goToContentPiece(searchResults()[selectedIndex()]);
+          }
+        }
+      });
+
+      window.addEventListener("keydown", keyShortcutHandler);
+      onCleanup(() => {
+        window.removeEventListener("keydown", keyShortcutHandler);
+      });
+    });
+  });
+
+  const getIcon = (): string => {
+    switch (mode()) {
+      case "search":
+        return mdiMagnify;
+      case "ask":
+        return mdiHeadSnowflakeOutline;
+    }
+  };
+  const getLabel = (): string => {
+    switch (mode()) {
+      case "ask":
+        return "Just ask";
+      case "search":
+      default:
+        return "Search";
+    }
+  };
+
+  return (
+    <Overlay
+      opened={props.opened}
+      class="items-start"
+      shadeClass="bg-opacity-50"
+      wrapperClass="mt-32"
+      onOverlayClick={() => {
+        props.setOpened(false);
+      }}
+    >
+      <Card
+        class="w-2xl max-w-[calc(100vw-2rem)] max-h-[calc(100vh-16rem)] flex flex-col p-0 overflow-hidden shadow-xl"
+        color="base"
+        onPointerMove={() => {
+          setMouseHoverEnabled(true);
+        }}
+      >
+        <div class="flex w-full justify-center items-center p-2 border-b-2 dark:border-gray-700">
+          <IconButton path={getIcon()} text="soft" variant="text" badge hover={false} class="m-0" />
+          <Input
+            value={query()}
+            setValue={(value) => {
+              if (mode() === "search") {
+                setLoading(true);
+              }
+
+              setQuery(value);
+            }}
+            ref={setInputRef}
+            tabIndex={0}
+            placeholder={getLabel()}
+            wrapperClass="flex-1 m-0"
+            class="m-0 bg-transparent"
+            onEnter={() => {
+              if (mode() === "ask") {
+                setLoading(true);
+                setAnswer("");
+                ask();
+              }
+            }}
+            onKeyDown={(event) => {
+              if (event.key === "Backspace" && !query()) {
+                setMode("search");
+              }
+            }}
+            adornment={() => (
+              <Show when={mode() === "search" || mode() === "ask"}>
+                <Tooltip text="Ask" side="left" class="-ml-1">
+                  <IconButton
+                    path={mdiCreationOutline}
+                    class="m-0"
+                    text={mode() === "ask" ? "base" : "soft"}
+                    color={mode() === "ask" ? "primary" : "base"}
+                    onClick={() => {
+                      setMode((mode) => (mode === "ask" ? "search" : "ask"));
+                    }}
+                    variant="text"
+                  />
+                </Tooltip>
+              </Show>
+            )}
+          />
+        </div>
+        <div class="relative overflow-hidden">
+          <div class="flex-1 flex flex-col overflow-auto  max-h-[calc(100vh-21.5rem)] scrollbar-sm">
+            <Switch>
+              <Match when={mode() === "search"}>
+                <Show
+                  when={!loading()}
+                  fallback={
+                    <div class="flex justify-center items-center p-4">
+                      <Loader />
+                    </div>
+                  }
+                >
+                  <For
+                    each={searchResults()}
+                    fallback={
+                      <span class="p-4 text-center text-gray-500 dark:text-gray-400">
+                        <Show when={query()} fallback="Type to search">
+                          No results
+                        </Show>
+                      </span>
+                    }
+                  >
+                    {(result, index) => {
+                      return (
+                        <Card
+                          class={clsx(
+                            "flex justify-start items-center py-2 px-3 m-0 rounded-none border-none",
+                            index() === selectedIndex() &&
+                              "bg-gray-300 dark:bg-gray-700 cursor-pointer",
+                            index() !== selectedIndex() && "bg-transparent"
+                          )}
+                          color="base"
+                          onClick={() => {
+                            goToContentPiece(result);
+                          }}
+                          onPointerEnter={() => {
+                            if (!mouseHoverEnabled()) return;
+
+                            setSelectedIndex(index());
+                          }}
+                        >
+                          <div class="flex w-full">
+                            <Icon
+                              path={mdiFileDocumentOutline}
+                              class="h-6 w-6 mr-2 justify-start items-center"
+                            />
+                            <div class="flex flex-col justify-start flex-1">
+                              <p class="flex items-center justify-start flex-wrap font-semibold">
+                                <For each={result.breadcrumb}>
+                                  {(breadcrumb, index) => {
+                                    return (
+                                      <>
+                                        <Show when={index()}>
+                                          <Icon
+                                            path={mdiChevronRight}
+                                            class="flex-inline h-5 w-5 text-gray-500 dark:text-gray-400"
+                                          />
+                                        </Show>
+                                        {breadcrumb}
+                                      </>
+                                    );
+                                  }}
+                                </For>
+                              </p>
+                              <p class="prose flex-1 text-sm clamp-2 whitespace-pre-wrap text-gray-500 dark:text-gray-400">
+                                {result.content}
+                              </p>
+                            </div>
+                          </div>
+                        </Card>
+                      );
+                    }}
+                  </For>
+                </Show>
+              </Match>
+              <Match when={mode() === "ask"}>
+                <Show
+                  when={answer()}
+                  fallback={
+                    <Show
+                      when={!loading()}
+                      fallback={
+                        <div class="flex justify-center items-center p-4">
+                          <Loader />
+                        </div>
+                      }
+                    >
+                      <span class="p-4 text-center text-gray-500 dark:text-gray-400">
+                        What do you want to know?
+                      </span>
+                    </Show>
+                  }
+                >
+                  <Card
+                    class={clsx(
+                      "flex flex-col items-center py-2 px-3 m-0 rounded-none border-none"
+                    )}
+                    color="base"
+                  >
+                    <div
+                      class="flex flex-col w-full prose whitespace-pre-wrap"
+                      innerHTML={answer()}
+                    />
+                    <Show when={!loading()}>
+                      <IconButton
+                        color="contrast"
+                        text="soft"
+                        size="small"
+                        badge
+                        class="mt-4"
+                        path={mdiInformationOutline}
+                        label="The information produced may be inaccurate."
+                      />
+                    </Show>
+                  </Card>
+                </Show>
+              </Match>
+            </Switch>
+          </div>
+        </div>
+        <div class="border-t-2 dark:border-gray-700 px-2 py-1 flex gap-2 bg-gray-100 dark:bg-gray-800">
+          <div class="hidden md:flex gap-2">
+            <IconButton
+              path={mdiSwapVertical}
+              hover={false}
+              badge
+              label="Select"
+              size="small"
+              variant="text"
+              text="soft"
+            />
+            <IconButton
+              path={mdiKeyboardReturn}
+              hover={false}
+              badge
+              label="Open"
+              size="small"
+              variant="text"
+              text="soft"
+            />
+            <IconButton
+              path={mdiKeyboardEsc}
+              hover={false}
+              badge
+              label="Close"
+              size="small"
+              variant="text"
+              text="soft"
+            />
+          </div>
+          <div class="flex-1" />
+          <Button
+            size="small"
+            variant="text"
+            color={mode() === "ask" ? "primary" : "base"}
+            text={mode() === "ask" ? "base" : "soft"}
+            onClick={() => {
+              setMode((mode) => (mode === "search" ? "ask" : "search"));
+            }}
+          >
+            Ask a question
+          </Button>
+        </div>
+      </Card>
+    </Overlay>
+  );
+};
+const SearchPaletteProvider: ParentComponent = (props) => {
+  const [opened, setOpened] = createSignal(false);
+
+  createEffect(() => {
+    if (opened()) {
+      document.body.style.overflow = "hidden";
+    } else {
+      document.body.style.overflow = "auto";
+    }
+  });
+
+  return (
+    <SearchPaletteContext.Provider
+      value={{
+        opened,
+        setOpened
+      }}
+    >
+      {props.children}
+      <SearchPalette opened={opened()} setOpened={setOpened} />
+    </SearchPaletteContext.Provider>
+  );
+};
+const useSearchPalette = (): SearchPaletteContextData => {
+  return useContext(SearchPaletteContext)!;
+};
+
+export { SearchPaletteProvider, useSearchPalette };
diff --git a/apps/docs/src/components/fragments/side-bar.tsx b/apps/docs/src/components/fragments/side-bar.tsx
index d906a35..60a5eeb 100644
--- a/apps/docs/src/components/fragments/side-bar.tsx
+++ b/apps/docs/src/components/fragments/side-bar.tsx
@@ -1,52 +1,42 @@
-import { mdiMenu, mdiClose, mdiGithub, mdiChevronDown, mdiCodeJson } from "@mdi/js";
+import { mdiMenu, mdiClose, mdiChevronDown } from "@mdi/js";
 import clsx from "clsx";
-import { Component, For, JSX, createSignal } from "solid-js";
+import { Component, For, JSX, createEffect, createSignal } from "solid-js";
 import { menuOpened, setMenuOpened } from "#lib/state";
 import { Card, Button, IconButton } from "#components/primitives";
-import { discordIcon } from "#assets/icons";
 import { logoIcon } from "#assets/icons/logo";
 
 interface SideBarProps {
-  menu: Array<{
+  currentSection: string;
+  sections: Array<{
     label: string;
-    menu: Array<{ label: string; link: string }>;
+    icon: string;
+    link: string;
+    id: string;
   }>;
+  menu: Record<
+    string,
+    Array<{
+      label: string;
+      menu: Array<{ label: string; link?: string; menu?: Array<{ label: string; link: string }> }>;
+    }>
+  >;
   currentPath: string;
 }
-
-const externalLinks = [
-  {
-    label: "GitHub",
-    icon: mdiGithub,
-    href: "https://github.com/vriteio/vrite"
-  },
-  {
-    label: "Discord",
-    icon: discordIcon,
-    href: "https://discord.gg/yYqDWyKnqE"
-  },
-  {
-    label: "Vrite Cloud",
-    icon: logoIcon,
-    href: "https://app.vrite.io"
-  },
-  {
-    label: "API Reference",
-    icon: mdiCodeJson,
-    href: "https://generator.swagger.io/?url=https://api.vrite.io/swagger.json#"
-  }
-];
-const SideBarNestedMenu: Component<{
-  menu: Array<{ label: string; link: string; menu?: Array<{ label: string; link: string }> }>;
+interface SideBarNestedMenuProps {
+  menu: Array<{ label: string; link?: string; menu?: Array<{ label: string; link: string }> }>;
   currentPath: string;
   children: JSX.Element;
-}> = (props) => {
+  openedByDefault?: boolean;
+}
+
+const SideBarNestedMenu: Component<SideBarNestedMenuProps> = (props) => {
   const [opened, setOpened] = createSignal(
-    props.menu.filter((item) => {
-      return props.currentPath.includes(item.link);
-    }).length > 0
+    props.openedByDefault ||
+      props.menu.filter((item) => {
+        return item.link && props.currentPath.includes(item.link);
+      }).length > 0
   );
 
   return (
     <div class="flex flex-col w-full">
       <div class="flex justify-center items-center">
@@ -85,11 +75,11 @@ const SideBarNestedMenu: Component<{
                   </SideBarNestedMenu>
                 );
               }
 
               const active = (): boolean => {
-                return props.currentPath.includes(item.link);
+                return Boolean(item.link && props.currentPath.includes(item.link));
               };
 
               return (
                 <Button
                   variant={active() ? "solid" : "text"}
@@ -107,19 +97,27 @@ const SideBarNestedMenu: Component<{
       </div>
     </div>
   );
 };
 const SideBar: Component<SideBarProps> = (props) => {
+  createEffect(() => {
+    if (menuOpened()) {
+      document.body.style.overflow = "hidden";
+    } else {
+      document.body.style.overflow = "auto";
+    }
+  });
+
   return (
     <>
       <div class={clsx("h-full fixed top-0 left-0 z-1", "pl-[max(0px,calc((100%-1536px)/2))]")}>
         <Card
           class={clsx(
             "top-0 h-full z-50 min-w-80 w-full md:max-w-80 m-0 bg-gray-100 dark:bg-gray-900",
             "flex-col gap-2 justify-start items-start border-0 md:border-r-2 rounded-none flex fixed md:relative",
             "transform md:transition-transform duration-300 ease-in-out scrollbar-sm-contrast overflow-auto",
-            menuOpened() ? "" : "translate-y-full md:translate-y-0"
+            menuOpened() ? "" : "translate-y-[100vh] md:translate-y-0"
           )}
         >
           <div class="flex items-center justify-start px-1 pb-4 pt-2">
             <IconButton
               path={logoIcon}
@@ -133,35 +131,39 @@ const SideBar: Component<SideBarProps> = (props) => {
             <span class="text-gray-500 dark:text-gray-400 font-semibold border-l-2 pl-2 ml-2 leading-8 border-gray-200 dark:border-gray-700">
               Documentation
             </span>
           </div>
           <div class="flex flex-col gap-2 pl-1 w-full py-4">
-            <For each={externalLinks}>
-              {(link) => {
+            <For each={props.sections}>
+              {(section) => {
                 return (
                   <a
                     class="flex justify-start items-center group w-full cursor-pointer"
-                    target="_blank"
-                    href={link.href}
+                    target={section.link.startsWith("http") ? "_blank" : "_self"}
+                    href={section.link}
                   >
                     <IconButton
-                      path={link.icon}
+                      path={section.icon}
                       class="m-0 group-hover:bg-gray-300 dark:group-hover:bg-gray-700 h-8 w-8"
                       iconProps={{ class: "h-5 w-5" }}
-                      color="contrast"
-                      text="soft"
+                      color={section.id === props.currentSection ? "primary" : "contrast"}
+                      text={section.id === props.currentSection ? "primary" : "soft"}
                     />
-                    <span class=" ml-2 text-gray-500 dark:text-gray-400">{link.label}</span>
+                    <span class=" ml-2 text-gray-500 dark:text-gray-400">{section.label}</span>
                   </a>
                 );
               }}
             </For>
           </div>
-          <For each={props.menu}>
+          <For each={props.menu[props.currentSection]}>
             {(menuItem) => {
               return (
-                <SideBarNestedMenu currentPath={props.currentPath} menu={menuItem.menu}>
+                <SideBarNestedMenu
+                  currentPath={props.currentPath}
+                  menu={menuItem.menu}
+                  openedByDefault
+                >
                   <Button
                     variant="text"
                     class="justify-start w-full font-bold m-0"
                     badge
                     hover={false}
diff --git a/apps/docs/src/components/layouts/default.astro b/apps/docs/src/components/layouts/default.astro
index 2b22099..cd10e3b 100644
--- a/apps/docs/src/components/layouts/default.astro
+++ b/apps/docs/src/components/layouts/default.astro
@@ -1,37 +1,109 @@
 ---
-import { Header, BaseHead, SideBar, SVGDefs, OnThisPage } from "#components/fragments";
+import { Header, BaseHead, SideBar, SVGDefs, OnThisPage, Footer } from "#components/fragments";
 import type { MarkdownHeading } from "astro";
 import menu from "./menu.json";
+import { Button } from "#components/primitives";
+import { mdiBookOpenBlankVariant, mdiConsoleLine, mdiTextBoxMultiple } from "@mdi/js";
 
 const image = "https://docs.vrite.io/meta-image.png";
 const title = "Vrite － developer content platform";
 const description =
   "Open-Source, collaborative developer content platform for documentation, technical blogs, and more.";
+const flattenMenu = (
+  menu: Array<{
+    label: string;
+    link?: string;
+    menu?: Array<{ label: string; link: string }>;
+  }>,
+  section: string,
+  labels: string[]
+): Array<{ label: string; link: string; section: string; labels: string[] }> => {
+  return menu.flatMap((item) => {
+    if (item.link) {
+      return [{ label: item.label, link: item.link, section, labels: [...labels, item.label] }];
+    }
+    if (item.menu) {
+      return flattenMenu(item.menu, section, [...labels, item.label]);
+    }
+    return [];
+  });
+};
+const sections = [
+  {
+    label: "Documentation",
+    link: "/usage-guide/getting-started",
+    icon: mdiBookOpenBlankVariant,
+    id: "docs"
+  },
+  {
+    label: "API reference",
+    link: "https://generator.swagger.io/?url=https://api.vrite.io/swagger.json",
+    icon: mdiConsoleLine,
+    id: "api"
+  }
+  /*{
+    label: "Recipes",
+    link: "/self-hosting/docker",
+    icon: mdiTextBoxMultiple,
+    id: "recipes"
+  }*/
+];
+const flatMenu = [
+  ...flattenMenu(menu.docs, "docs", []),
+  ...flattenMenu(menu.recipes, "recipes", [])
+];
+const currentEntry = flatMenu.find((item) => item.link === Astro.url.pathname);
+const nextEntry = currentEntry ? flatMenu[flatMenu.indexOf(currentEntry) + 1] : null;
+const prevEntry = currentEntry ? flatMenu[flatMenu.indexOf(currentEntry) - 1] : null;
 
 type Props = {
   headings: MarkdownHeading[];
   title: string;
+  description?: string;
 };
 ---
 
 <!DOCTYPE html>
 <html lang="en">
   <head>
-    <BaseHead description={description} title={title} image={image} />
+    <BaseHead
+      description={Astro.props.description || description}
+      title={Astro.props.title ? `${Astro.props.title} | Vrite Documentation` : title}
+      image={image}
+    />
   </head>
   <body class="overflow-x-hidden overscroll-none">
     <SVGDefs />
     <main class="flex flex-col items-center justify-center bg-gray-50 dark:bg-gray-800">
       <div class="flex-1 flex justify-center items-center flex-1 w-full max-w-screen-2xl relative">
-        <SideBar menu={menu} currentPath={Astro.url.pathname} client:load />
-        <div class="flex overflow-hidden w-full relative h-full">
-          <div class="flex-1 flex overflow-y-auto overflow-x-hidden justify-center" id="container">
+        <Header client:load />
+        <SideBar
+          menu={menu}
+          sections={sections}
+          currentSection={currentEntry?.section || "docs"}
+          currentPath={Astro.url.pathname}
+          client:load
+        />
+        <div class="flex overflow-hidden w-full relative h-full pt-12">
+          <div
+            class="flex-1 flex overflow-y-auto overflow-x-hidden justify-center min-h-[calc(100vh-3rem)]"
+            id="container"
+          >
             <div
-              class="flex-1 prose max-w-screen-md w-full text-lg px-4 pt-4 pb-24 h-fit xl:w-[calc(100%-15rem)]"
+              class="flex-1 prose max-w-screen-md w-full text-lg px-4 md:px-8 pt-4 pb-24 h-fit xl:w-[calc(100%-15rem)]"
             >
+              {
+                (currentEntry?.labels.length || 0) > 1 && (
+                  <Button badge color="primary" variant="text" class="m-0 pl-1 py-0" hover={false}>
+                    {currentEntry?.labels.at(-2)}
+                  </Button>
+                )
+              }
+              <h1>{Astro.props.title}</h1>
               <slot />
+              <Footer nextEntry={nextEntry} previousEntry={prevEntry} />
             </div>
             <OnThisPage headings={Astro.props.headings} client:load />
           </div>
         </div>
       </div>
diff --git a/apps/docs/src/components/layouts/menu.json b/apps/docs/src/components/layouts/menu.json
index 007ff5a..e86f860 100644
--- a/apps/docs/src/components/layouts/menu.json
+++ b/apps/docs/src/components/layouts/menu.json
@@ -1,53 +1,60 @@
-[
-  {
-    "label": "Usage Guide",
-    "menu": [
-      {
-        "label": "Getting Started",
-        "link": "/usage-guide/getting-started"
-      },
-      {
-        "label": "Managing Content with Kanban",
-        "link": "/usage-guide/kanban-dashboard"
-      },
-      {
-        "label": "Managing metadata",
-        "link": "/usage-guide/metadata"
-      },
-      {
-        "label": "Writing in the Vrite Editor",
-        "link": "/usage-guide/content-editor"
-      },
-      {
-        "label": "Configuring Vrite",
-        "link": "/usage-guide/configuring-vrite"
-      },
-      {
-        "label": "Publishing content",
-        "link": "/usage-guide/publishing"
-      }
-    ]
-  },
-  {
-    "label": "JavaScript SDK",
-    "menu": [
-      {
-        "label": "Introduction",
-        "link": "/javascript-sdk/javascript-sdk"
-      }
-    ]
-  },
-  {
-    "label": "Self-Hosting",
-    "menu": [
-      {
-        "label": "Docker",
-        "link": "/self-hosting/docker"
-      },
-      {
-        "label": "Configuration",
-        "link": "/self-hosting/configuration"
-      }
-    ]
-  }
-]
+{
+  "docs": [
+    {
+      "label": "Usage Guide",
+      "menu": [
+        {
+          "label": "Getting Started",
+          "link": "/usage-guide/getting-started"
+        },
+        {
+          "label": "Managing Content with Kanban",
+          "link": "/usage-guide/kanban-dashboard"
+        },
+        {
+          "label": "Managing metadata",
+          "link": "/usage-guide/metadata"
+        },
+        {
+          "label": "Writing in the Vrite Editor",
+          "link": "/usage-guide/content-editor"
+        },
+        {
+          "label": "Configuring Vrite",
+          "link": "/usage-guide/configuring-vrite"
+        },
+        {
+          "label": "Publishing content",
+          "link": "/usage-guide/publishing"
+        },
+        {
+          "label": "Vrite Extensions",
+          "link": "/usage-guide/vrite-extensions"
+        }
+      ]
+    },
+    {
+      "label": "JavaScript SDK",
+      "menu": [
+        {
+          "label": "Introduction",
+          "link": "/javascript-sdk/introduction"
+        }
+      ]
+    },
+    {
+      "label": "Self-Hosting",
+      "menu": [
+        {
+          "label": "Docker",
+          "link": "/self-hosting/docker"
+        },
+        {
+          "label": "Configuration",
+          "link": "/self-hosting/configuration"
+        }
+      ]
+    }
+  ],
+  "recipes": []
+}
diff --git a/apps/docs/src/content/config.ts b/apps/docs/src/content/config.ts
index f06eaa1..8a39dc6 100644
--- a/apps/docs/src/content/config.ts
+++ b/apps/docs/src/content/config.ts
@@ -1,10 +1,22 @@
 import { z, defineCollection } from "astro:content";
 
 const docsCollection = defineCollection({
-  type: "content"
+  type: "content",
+  schema: z.object({
+    title: z.string().optional(),
+    description: z.string().optional()
+  })
+});
+const recipesCollection = defineCollection({
+  type: "content",
+  schema: z.object({
+    title: z.string().optional(),
+    description: z.string().optional()
+  })
 });
 const collections = {
-  docs: docsCollection
+  docs: docsCollection,
+  recipes: recipesCollection
 };
 
 export { collections };
diff --git a/apps/docs/src/content/docs/javascript-sdk/javascript-sdk.md b/apps/docs/src/content/docs/javascript-sdk/javascript-sdk.md
index 3f357f4..46dafae 100644
--- a/apps/docs/src/content/docs/javascript-sdk/javascript-sdk.md
+++ b/apps/docs/src/content/docs/javascript-sdk/javascript-sdk.md
@@ -1,5 +1,10 @@
+---
+title: "Introduction"
+slug: "javascript-sdk/introduction"
+---
+
 [Vrite JavaScript SDK](https://github.com/vriteio/vrite/tree/main/packages/sdk/javascript) is a one-stop-shop when building any kind of Vrite-powered website or web app.
 
 Currently it includes the following parts:
 
 - **API client** — for easy access to Vrite API;
diff --git a/apps/docs/src/content/docs/self-hosting/configuration.md b/apps/docs/src/content/docs/self-hosting/configuration.md
index 087cbd9..5334f52 100644
--- a/apps/docs/src/content/docs/self-hosting/configuration.md
+++ b/apps/docs/src/content/docs/self-hosting/configuration.md
@@ -1,5 +1,10 @@
+---
+title: "Configuring Self-Hosted Vrite"
+slug: "self-hosting/configuration"
+---
+
 To properly host Vrite, you first have to configure a couple of environment variables. This guide aims to give you an overview of the available options.
 
 ## Security
 
 Providing a strong `SECRET` is important, as it’s the value used to encrypt JSON Web Tokens. You can generate one from the terminal with:
diff --git a/apps/docs/src/content/docs/self-hosting/docker.md b/apps/docs/src/content/docs/self-hosting/docker.md
index e2ac795..bd2d4b9 100644
--- a/apps/docs/src/content/docs/self-hosting/docker.md
+++ b/apps/docs/src/content/docs/self-hosting/docker.md
@@ -1,5 +1,10 @@
+---
+title: "Self-Hosting Vrite with Docker"
+slug: "self-hosting/docker"
+---
+
 Vrite aims to provide the best and most accessible technical writing experience. To do so, we provide both a ready, [easy-to-use “Vrite Cloud” instance](https://app.vrite.io/), as well as an option for you to **self-host Vrite** on your own servers.
 
 The recommended way to self-host Vrite is with [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) - both of which you need to have installed on your machine.
 
 Start by cloning the Vrite repository and preparing the `docker.env` file:
diff --git a/apps/docs/src/content/docs/usage-guide/configuring-vrite.md b/apps/docs/src/content/docs/usage-guide/configuring-vrite.md
index e356aa2..2c9314d 100644
--- a/apps/docs/src/content/docs/usage-guide/configuring-vrite.md
+++ b/apps/docs/src/content/docs/usage-guide/configuring-vrite.md
@@ -1,5 +1,10 @@
+---
+title: "Configuring Vrite"
+slug: "usage-guide/configuring-vrite"
+---
+
 Everything related to configuring Vrite can be done from the settings side panel. From managing API tokens to customizing the editing experience — all can be managed in the settings.
 
 It’s worth noting that there are 2 categories of settings in Vrite:
 
 - **Workspace-bound** — settings that are configured for the entire workspace. When configured, all the members of the workspace will see them in effect;
diff --git a/apps/docs/src/content/docs/usage-guide/content-editor.md b/apps/docs/src/content/docs/usage-guide/content-editor.md
index 790185c..2b52a79 100644
--- a/apps/docs/src/content/docs/usage-guide/content-editor.md
+++ b/apps/docs/src/content/docs/usage-guide/content-editor.md
@@ -1,5 +1,10 @@
+---
+title: "Writing in Vrite Editor"
+slug: "/usage-guide/content-editor"
+---
+
 The content editor is the core part of Vrite — this is where you can create your next technical masterpiece. And, thanks to all the features, formatting options, and content blocks Vrite supports - it should be a breeze!
 
 ## Editing Menus
 
 Editing menus are one of the most important parts of the Vrite editing experience. Implementing modern design and UX found in other state-of-the-art WYSIWYG editors, Vrite provides you with a set of easily-accessible menus that are right there when you need them!
diff --git a/apps/docs/src/content/docs/usage-guide/getting-started.md b/apps/docs/src/content/docs/usage-guide/getting-started.md
index 4f66e3a..e308cf7 100644
--- a/apps/docs/src/content/docs/usage-guide/getting-started.md
+++ b/apps/docs/src/content/docs/usage-guide/getting-started.md
@@ -1,5 +1,10 @@
+---
+title: "Getting Started"
+slug: "/usage-guide/getting-started"
+---
+
 **Vrite** (Public Beta) is a headless CMS, made with technical, programming-related content in mind. Combining great project management frameworks like Kanban with a state-of-the-art WYSIWYG editor and support for real-time collaboration, Vrite is a CMS unlike any other.
 
 ## Vrite’s Features
 
 Currently, while we’re working on fixing bugs and adding more features, Vrite is in **Public Beta**. That said, it already has a ton of features for your to try out, including:
diff --git a/apps/docs/src/content/docs/usage-guide/kanban-dashboard.md b/apps/docs/src/content/docs/usage-guide/kanban-dashboard.md
index 6c732d5..1cf9f25 100644
--- a/apps/docs/src/content/docs/usage-guide/kanban-dashboard.md
+++ b/apps/docs/src/content/docs/usage-guide/kanban-dashboard.md
@@ -1,5 +1,10 @@
+---
+title: "Managing Content in Kanban"
+slug: "/usage-guide/kanban-dashboard"
+---
+
 Managing content using traditional CMS tools is hard. Basic lists or tables just don’t cut it. It's especially difficult when working in teams or depending on a complex content production pipeline. You end up using many different tools, switching and copy-pasting between them, experiencing degraded UX, and losing time.
 
 That's why Vrite approaches content management differently — by implementing a **Kanban dashboard** many developers and project managers are familiar with and enjoy using.
 
 ## Kanban Dashboard
diff --git a/apps/docs/src/content/docs/usage-guide/metadata.md b/apps/docs/src/content/docs/usage-guide/metadata.md
index e092766..01c2a74 100644
--- a/apps/docs/src/content/docs/usage-guide/metadata.md
+++ b/apps/docs/src/content/docs/usage-guide/metadata.md
@@ -1,5 +1,10 @@
+---
+title: "Managing Metadata"
+slug: "/usage-guide/metadata"
+---
+
 After the actual content, **metadata** is probably some of the most important information you have to manage in your CMS. In Vrite, metadata — part of a content piece — can be managed from the **metadata side panel**.
 
 ## Metadata Side Panel
 
 ![Metadata side panel in Vrite](https://assets.vrite.io/6409e82d7dfc74cef7a72e0d/r1Q4gBmINQjJjrGZmyfMo.png)
diff --git a/apps/docs/src/content/docs/usage-guide/publishing.md b/apps/docs/src/content/docs/usage-guide/publishing.md
index af014e4..5d6bcb0 100644
--- a/apps/docs/src/content/docs/usage-guide/publishing.md
+++ b/apps/docs/src/content/docs/usage-guide/publishing.md
@@ -1,5 +1,10 @@
+---
+title: "Publishing Content"
+slug: "/usage-guide/publishing"
+---
+
 With Vrite’s unique features like Kanban-based content management, the actual publishing flow is quite unique. All you have to do to publish a piece can be just drag and drop.
 
 ## Dedicated Content Group
 
 The recommended approach is to create a **dedicated**, ideally **locked**, **content group** for publishing, with an easily-identifiable name e.g. _Published_. You can then move any content piece that's ready to be published, to this content group.
diff --git a/apps/docs/src/content/docs/usage-guide/vrite-extensions.md b/apps/docs/src/content/docs/usage-guide/vrite-extensions.md
index 079e3ba..bddc508 100644
--- a/apps/docs/src/content/docs/usage-guide/vrite-extensions.md
+++ b/apps/docs/src/content/docs/usage-guide/vrite-extensions.md
@@ -1,5 +1,10 @@
+---
+title: "Vrite Extensions"
+slug: "/usage-guide/vrite-extensions"
+---
+
 Vrite Extensions are meant to make Vrite both more customizable and easier to use. With direct access to Vrite API and the ability to extend Vrite’s UI, they have the ability to vastly improve your experience with Vrite.
 
 The Extensions specification and related APIs are in the early stages and we continue to stabilize and improve them. The goal is to create a platform that all users can build on. However, for now, only first-party extensions are available, which include:
 
 - **Hashnode** — automatically publishes and updates articles on [Hashnode](https://hashnode.com/);
diff --git a/apps/docs/src/content/recipes/test.mdx b/apps/docs/src/content/recipes/test.mdx
new file mode 100644
index 0000000..95cc8a6
--- /dev/null
+++ b/apps/docs/src/content/recipes/test.mdx
@@ -0,0 +1,6 @@
+---
+title: "Content Pieces API"
+slug: "/recipes/content-pieces"
+---
+
+Content
diff --git a/apps/docs/src/env.d.ts b/apps/docs/src/env.d.ts
index acef35f..9a6d3ac 100644
--- a/apps/docs/src/env.d.ts
+++ b/apps/docs/src/env.d.ts
@@ -1,2 +1,9 @@
 /// <reference path="../.astro/types.d.ts" />
 /// <reference types="astro/client" />
+interface ImportMetaEnv {
+  readonly PUBLIC_VRITE_SEARCH_TOKEN: string;
+}
+
+interface ImportMeta {
+  readonly env: ImportMetaEnv;
+}
diff --git a/apps/docs/src/pages/[...slug].astro b/apps/docs/src/pages/[...slug].astro
index 7b56d54..f1225f0 100644
--- a/apps/docs/src/pages/[...slug].astro
+++ b/apps/docs/src/pages/[...slug].astro
@@ -11,16 +11,23 @@ if (slug === undefined) {
 const { entry } = Astro.props;
 const { Content, headings } = await entry.render();
 
 export const prerender = true;
 export async function getStaticPaths() {
-  const blogEntries = await getCollection("docs");
-  return blogEntries.map((entry) => ({
-    params: { slug: entry.slug },
-    props: { entry }
-  }));
+  const docsEntries = await getCollection("docs");
+  const recipesEntries = await getCollection("recipes");
+  return [
+    ...docsEntries.map((entry) => ({
+      params: { slug: entry.slug },
+      props: { entry }
+    })),
+    ...recipesEntries.map((entry) => ({
+      params: { slug: entry.slug },
+      props: { entry }
+    }))
+  ];
 }
 ---
 
-<DefaultLayout headings={headings} title={entry.data.title}>
+<DefaultLayout headings={headings} title={entry.data.title} description={entry.data.description}>
   <Content />
 </DefaultLayout>
diff --git a/apps/docs/src/styles/base.css b/apps/docs/src/styles/base.css
index f37e054..232d91f 100644
--- a/apps/docs/src/styles/base.css
+++ b/apps/docs/src/styles/base.css
@@ -174,5 +174,33 @@ h2 {
 @media (prefers-color-scheme: dark) {
   .astro-code {
     scrollbar-color: #1e293b #0f172a;
   }
 }
+
+.clamp-1 {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  overflow-wrap: break-word;
+  -webkit-line-clamp: 1;
+  line-clamp: 1;
+  -webkit-box-orient: vertical;
+}
+.clamp-2 {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  overflow-wrap: break-word;
+  -webkit-line-clamp: 2;
+  line-clamp: 2;
+  -webkit-box-orient: vertical;
+}
+.clamp-3 {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  display: -webkit-box;
+  overflow-wrap: break-word;
+  -webkit-line-clamp: 3;
+  line-clamp: 3;
+  -webkit-box-orient: vertical;
+}
diff --git a/apps/docs/src/styles/styles.scss b/apps/docs/src/styles/styles.scss
index 485480f..1a75930 100644
--- a/apps/docs/src/styles/styles.scss
+++ b/apps/docs/src/styles/styles.scss
@@ -4,18 +4,27 @@
     background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"),
       linear-gradient(to top right, var(--un-gradient-stops));
     @apply border-transparent dark:border-transparent;
   }
 }
-
+.font-jetbrains {
+  font-family: "JetBrainsMonoVariable", monospace;
+}
 kbd {
   font-family: "JetBrainsMonoVariable", monospace;
 }
 #side-panel > div {
   height: 100%;
 }
-
+svg > path {
+  fill: inherit;
+}
+.grid-reset-margin {
+  & > * {
+    margin: 0;
+  }
+}
 .resize-cursor {
   cursor: ew-resize;
   cursor: col-resize;
 }
 .prose {
@@ -99,68 +108,27 @@ kbd {
     }
   }
 
   font-kerning: none;
   :where(h1, h2, h3, h4, h5, h6):not(:where(.not-prose, .not-prose *)) {
-    &::before,
-    &::before,
-    &::before,
-    &::before,
-    &::before,
-    &::before,
-    .open-slash-menu > button {
-      @apply font-bold dark:bg-gray-900 dark:border-gray-700;
-      position: absolute;
-      left: -2.5rem;
-      background: #f9fafb;
-      height: 2rem;
-      width: 2rem;
-      justify-content: center;
-      display: flex;
-      align-items: center;
-      color: #6b7280;
-      border-radius: 25%;
-      font-size: 1rem;
-      line-height: 1rem;
-      text-align: center;
-      top: 50%;
-      transform: translateY(-50%);
-      //border: 2px solid #e5e7eb;
-      @apply border-2;
-      opacity: 1;
-    }
+    @apply relative;
+    margin: 0 !important;
   }
-
-  h1,
-  h2,
-  h3,
-  h4,
-  h5,
-  h6,
-  .open-slash-menu {
-    @apply m-0 relative;
-    & > button {
-      @apply mt-4;
+  :where(h2, h3):not(:where(.not-prose, .not-prose *)) {
+    @apply hover:cursor-pointer;
+    &::before {
+      @apply hidden md:block absolute pr-6 -left-6 transform scale-90 text-gray-500 dark:text-gray-400 opacity-0;
+      content: "#";
     }
-  }
-  .open-slash-menu {
-    button {
-      font-size: 1.25em;
-      line-height: 1.25em;
-      font-weight: 600;
+    &:hover::before {
+      @apply opacity-100;
     }
   }
-  :where(h4):not(:where(.not-prose, .not-prose *)) {
-    line-height: 2.1rem;
-  }
-  :where(h5):not(:where(.not-prose, .not-prose *)) {
-    line-height: 2.1rem;
-  }
-  :where(h6):not(:where(.not-prose, .not-prose *)) {
-    font-size: 0.875em;
-    line-height: 2.1rem;
+  h3:not(:where(.not-prose, .not-prose *))::before {
+    @apply pr-5 -left-5;
   }
+
   :where(ul p, ol p):not(:where(.not-prose, .not-prose *)) {
     @apply m-0;
   }
   :where(ul:not([data-type="taskList"]) li > * + *, ol li > * + *):not(
       :where(.not-prose, .not-prose *)
diff --git a/apps/web/package.json b/apps/web/package.json
index 407ef26..f67730d 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -56,11 +56,11 @@
     "clsx": "^2.0.0",
     "dayjs": "^1.11.9",
     "dompurify": "^3.0.5",
     "marked": "^5.1.2",
     "minisearch": "^6.1.0",
-    "monaco-editor": "^0.40.0",
+    "monaco-editor": "^0.43.0",
     "nanoevents": "^8.0.0",
     "nanoid": "^4.0.2",
     "prettier": "^3.0.2",
     "seamless-scroll-polyfill": "^2.3.4",
     "solid-js": "^1.7.8",
diff --git a/apps/web/public/sandbox.js b/apps/web/public/sandbox.js
index d1b13c0..0ef3559 100644
--- a/apps/web/public/sandbox.js
+++ b/apps/web/public/sandbox.js
@@ -141,12 +141,12 @@
           }
           var REPLACER = 65533;
           var string = "";
           var bitsNeeded = this.bitsNeeded;
           var codePoint = this.codePoint;
-          for (var i2 = 0; i2 < octets.length; i2 += 1) {
-            var octet = octets[i2];
+          for (var i = 0; i < octets.length; i += 1) {
+            var octet = octets[i];
             if (bitsNeeded !== 0) {
               if (octet < 128 || octet > 191 || !valid(codePoint << 6 | octet & 63, bitsNeeded - 6, octetsCount(bitsNeeded, codePoint))) {
                 bitsNeeded = 0;
                 codePoint = REPLACER;
                 string += String.fromCharCode(codePoint);
@@ -415,12 +415,12 @@
           });
         }
         function HeadersPolyfill(all) {
           var map = /* @__PURE__ */ Object.create(null);
           var array = all.split("\r\n");
-          for (var i2 = 0; i2 < array.length; i2 += 1) {
-            var line = array[i2];
+          for (var i = 0; i < array.length; i += 1) {
+            var line = array[i];
             var parts = line.split(": ");
             var name = parts.shift();
             var value = parts.join(": ");
             map[toLowerCase(name)] = value;
           }
@@ -537,12 +537,12 @@
         EventTarget.prototype.dispatchEvent = function(event) {
           event.target = this;
           var typeListeners = this._listeners[event.type];
           if (typeListeners != void 0) {
             var length = typeListeners.length;
-            for (var i2 = 0; i2 < length; i2 += 1) {
-              var listener = typeListeners[i2];
+            for (var i = 0; i < length; i += 1) {
+              var listener = typeListeners[i];
               try {
                 if (typeof listener.handleEvent === "function") {
                   listener.handleEvent(event);
                 } else {
                   listener.call(this, event);
@@ -560,12 +560,12 @@
           if (typeListeners == void 0) {
             typeListeners = [];
             listeners[type] = typeListeners;
           }
           var found = false;
-          for (var i2 = 0; i2 < typeListeners.length; i2 += 1) {
-            if (typeListeners[i2] === listener) {
+          for (var i = 0; i < typeListeners.length; i += 1) {
+            if (typeListeners[i] === listener) {
               found = true;
             }
           }
           if (!found) {
             typeListeners.push(listener);
@@ -575,13 +575,13 @@
           type = String(type);
           var listeners = this._listeners;
           var typeListeners = listeners[type];
           if (typeListeners != void 0) {
             var filtered = [];
-            for (var i2 = 0; i2 < typeListeners.length; i2 += 1) {
-              if (typeListeners[i2] !== listener) {
-                filtered.push(typeListeners[i2]);
+            for (var i = 0; i < typeListeners.length; i += 1) {
+              if (typeListeners[i] !== listener) {
+                filtered.push(typeListeners[i]);
               }
             }
             if (filtered.length === 0) {
               delete listeners[type];
             } else {
@@ -720,14 +720,14 @@
             }
           };
           var onProgress = function(textChunk) {
             if (currentState === OPEN) {
               var n = -1;
-              for (var i2 = 0; i2 < textChunk.length; i2 += 1) {
-                var c = textChunk.charCodeAt(i2);
+              for (var i = 0; i < textChunk.length; i += 1) {
+                var c = textChunk.charCodeAt(i);
                 if (c === "\n".charCodeAt(0) || c === "\r".charCodeAt(0)) {
-                  n = i2;
+                  n = i;
                 }
               }
               var chunk = (n !== -1 ? textBuffer : "") + textChunk.slice(0, n + 1);
               textBuffer = (n === -1 ? textBuffer : "") + textChunk.slice(n + 1);
               if (textChunk !== "") {
@@ -877,12 +877,12 @@
             valueStart = 0;
             state = FIELD_START;
             var requestURL = url;
             if (url.slice(0, 5) !== "data:" && url.slice(0, 5) !== "blob:") {
               if (lastEventId !== "") {
-                var i2 = url.indexOf("?");
-                requestURL = i2 === -1 ? url : url.slice(0, i2 + 1) + url.slice(i2 + 1).replace(/(?:^|&)([^=&]*)(?:=[^&]*)?/g, function(p, paramName) {
+                var i = url.indexOf("?");
+                requestURL = i === -1 ? url : url.slice(0, i + 1) + url.slice(i + 1).replace(/(?:^|&)([^=&]*)(?:=[^&]*)?/g, function(p, paramName) {
                   return paramName === lastEventIdQueryParameterName ? "" : p;
                 });
                 requestURL += (url.indexOf("?") === -1 ? "?" : "&") + lastEventIdQueryParameterName + "=" + encodeURIComponent(lastEventId);
               }
             }
@@ -955,11 +955,11 @@
   // ../../node_modules/.pnpm/unfetch@4.2.0/node_modules/unfetch/dist/unfetch.js
   var require_unfetch = __commonJS({
     "../../node_modules/.pnpm/unfetch@4.2.0/node_modules/unfetch/dist/unfetch.js"(exports, module) {
       module.exports = function(e, n) {
         return n = n || {}, new Promise(function(t, r) {
-          var s = new XMLHttpRequest(), o = [], u2 = [], i2 = {}, a = function() {
+          var s = new XMLHttpRequest(), o = [], u2 = [], i = {}, a = function() {
             return { ok: 2 == (s.status / 100 | 0), statusText: s.statusText, status: s.status, url: s.responseURL, text: function() {
               return Promise.resolve(s.responseText);
             }, json: function() {
               return Promise.resolve(s.responseText).then(JSON.parse);
             }, blob: function() {
@@ -967,18 +967,18 @@
             }, clone: a, headers: { keys: function() {
               return o;
             }, entries: function() {
               return u2;
             }, get: function(e2) {
-              return i2[e2.toLowerCase()];
+              return i[e2.toLowerCase()];
             }, has: function(e2) {
-              return e2.toLowerCase() in i2;
+              return e2.toLowerCase() in i;
             } } };
           };
           for (var l2 in s.open(n.method || "get", e, true), s.onload = function() {
             s.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, function(e2, n2, t2) {
-              o.push(n2 = n2.toLowerCase()), u2.push([n2, t2]), i2[n2] = i2[n2] ? i2[n2] + "," + t2 : t2;
+              o.push(n2 = n2.toLowerCase()), u2.push([n2, t2]), i[n2] = i[n2] ? i[n2] + "," + t2 : t2;
             }), t(a());
           }, s.onerror = r, s.withCredentials = "include" == n.credentials, n.headers)
             s.setRequestHeader(l2, n.headers[l2]);
           s.send(n.body || null);
         });
@@ -994,78 +994,87 @@
   });
 
   // ../../packages/sdk/javascript/dist/api.mjs
   var api_exports = {};
   __export(api_exports, {
-    createClient: () => B
+    createClient: () => M
   });
-  var import_eventsource, i, w, $, U, f, g, L, d, S, D, O, E, R, C, x, m, I, h, j, v, k, q, l, A, u, z, B;
+  var import_eventsource, l, U, E, S, f, h, L, m, D, O, R, T, x, C, I, u, v, k, j, q, G, A, b, z, y, B, M;
   var init_api = __esm({
     "../../packages/sdk/javascript/dist/api.mjs"() {
       import_eventsource = __toESM(require_browser(), 1);
-      i = "/content-groups";
-      w = (t) => ({ get: (e) => t("GET", `${i}`, { params: e }), list: (e) => t("GET", `${i}/list`, { params: e }), create: (e) => t("POST", `${i}`, { body: e }), update: (e) => t("PUT", `${i}`, { body: e }), delete: (e) => t("DELETE", `${i}`, { params: e }) });
-      $ = "/content-pieces";
-      U = (t) => ({ get: (e) => t("GET", `${$}`, { params: e }), create: (e) => t("POST", `${$}`, { body: e }), update: (e) => t("PUT", `${$}`, { body: e }), delete: (e) => t("DELETE", `${$}`, { params: e }), list: (e) => t("GET", `${$}/list`, { params: e }) });
+      l = "/content-groups";
+      U = (t) => ({ get: (e) => t("GET", `${l}`, { params: e }), list: (e) => t("GET", `${l}/list`, { params: e }), create: (e) => t("POST", `${l}`, { body: e }), update: (e) => t("PUT", `${l}`, { body: e }), delete: (e) => t("DELETE", `${l}`, { params: e }) });
+      E = "/content-pieces";
+      S = (t) => ({ get: (e) => t("GET", `${E}`, { params: e }), create: (e) => t("POST", `${E}`, { body: e }), update: (e) => t("PUT", `${E}`, { body: e }), delete: (e) => t("DELETE", `${E}`, { params: e }), list: (e) => t("GET", `${E}/list`, { params: e }) });
       f = (t) => {
-        let e = t.baseURL || "https://api.vrite.io", n = t.extensionId || "", c = t.headers || {}, { token: s } = t;
-        return { sendRequest: async (a, p, r) => {
+        let e = t.baseURL || "https://api.vrite.io", c = t.extensionId || "", i = t.headers || {}, $ = null, { token: p } = t;
+        return { sendRequest: async (s, a, n) => {
           try {
-            const { default: o } = await Promise.resolve().then(() => __toESM(require_browser2(), 1)), y = await o(`${e}${p}/?${encodeURI(Object.entries(r?.params || {}).filter(([, b]) => b).map(([b, G]) => `${b}=${G}`).join("&"))}`, { headers: { Authorization: `Bearer ${s}`, Accept: "application/json", ...r?.body ? { "Content-Type": "application/json" } : {}, ...n ? { "X-Vrite-Extension-ID": n } : {}, ...c }, body: r?.body ? JSON.stringify(r.body) : null, method: a });
-            let T = null;
+            const { default: o } = await Promise.resolve().then(() => __toESM(require_browser2(), 1)), d = await o(`${e}${a}/?${encodeURI(Object.entries(n?.params || {}).filter(([, g]) => g).map(([g, w]) => `${g}=${w}`).join("&"))}`, { headers: { Authorization: `Bearer ${p}`, Accept: "application/json", ...n?.body ? { "Content-Type": "application/json" } : {}, ...c ? { "X-Vrite-Extension-ID": c } : {}, ...i }, body: n?.body ? JSON.stringify(n.body) : null, signal: $, method: s });
+            $ = null;
+            let r = null;
             try {
-              if (T = await y.json(), !T)
+              if (r = await d.json(), !r)
                 return;
             } catch {
               return;
             }
-            if (!y.ok)
-              throw T;
-            return T;
+            if (!d.ok)
+              throw r;
+            return r;
           } catch (o) {
             throw console.error(o), o;
           }
-        }, reconfigure: (a) => {
-          e = a.baseURL || e, s = a.token || s, n = a.extensionId || n, c = a.headers || c;
-        }, getConfig: () => ({ baseURL: e, token: s, extensionId: n, headers: c }) };
+        }, reconfigure: (s) => {
+          e = s.baseURL || e, p = s.token || p, c = s.extensionId || c, i = s.headers || i;
+        }, useSignal: (s) => {
+          $ = s;
+        }, getConfig: () => ({ baseURL: e, token: p, extensionId: c, headers: i }), getSignal: () => $ };
       };
-      g = "/user-settings";
-      L = (t) => ({ get: () => t("GET", `${g}`), update: (e) => t("PUT", `${g}`, { body: e }) });
-      d = "/tags";
-      S = (t) => ({ get: (e) => t("GET", `${d}`, { params: e }), update: (e) => t("PUT", `${d}`, { body: e }), create: (e) => t("PUT", `${d}`, { body: e }), delete: (e) => t("DELETE", `${d}`, { params: e }), list: (e) => t("GET", `${d}/list`, { params: e }) });
-      D = "/profile";
-      O = (t) => ({ get: () => t("GET", `${D}`) });
-      E = "/webhooks";
-      R = (t) => ({ get: (e) => t("GET", `${E}`, { params: e }), create: (e) => t("POST", `${E}`, { body: e }), update: (e) => t("PUT", `${E}`, { body: e }), delete: (e) => t("DELETE", `${E}`, { params: e }), list: (e) => t("GET", `${E}/list`, { params: e }) });
+      h = "/user-settings";
+      L = (t) => ({ get: () => t("GET", `${h}`), update: (e) => t("PUT", `${h}`, { body: e }) });
+      m = "/tags";
+      D = (t) => ({ get: (e) => t("GET", `${m}`, { params: e }), update: (e) => t("PUT", `${m}`, { body: e }), create: (e) => t("PUT", `${m}`, { body: e }), delete: (e) => t("DELETE", `${m}`, { params: e }), list: (e) => t("GET", `${m}/list`, { params: e }) });
+      O = "/profile";
+      R = (t) => ({ get: () => t("GET", `${O}`) });
+      T = "/webhooks";
+      x = (t) => ({ get: (e) => t("GET", `${T}`, { params: e }), create: (e) => t("POST", `${T}`, { body: e }), update: (e) => t("PUT", `${T}`, { body: e }), delete: (e) => t("DELETE", `${T}`, { params: e }), list: (e) => t("GET", `${T}/list`, { params: e }) });
       C = "/workspace";
-      x = (t) => ({ get: () => t("GET", `${C}`) });
-      m = "/roles";
-      I = (t) => ({ get: (e) => t("GET", `${m}`, { params: e }), create: (e) => t("POST", `${m}`, { body: e }), update: (e) => t("PUT", `${m}`, { body: e }), delete: (e) => t("DELETE", `${m}`, { params: e }), list: (e) => t("GET", `${m}/list`, { params: e }) });
-      h = "/workspace-settings";
-      j = (t) => ({ get: () => t("GET", `${h}`), update: (e) => t("PUT", `${h}`, { body: e }) });
-      v = (t) => ({ listMembers: (e) => t("GET", "/workspace-memberships/list-members", { params: e }), listWorkspaces: (e) => t("GET", "/workspace-memberships/list-workspaces", { params: e }), create: (e) => t("POST", "/workspace-memberships", { body: e }), update: (e) => t("PUT", "/workspace-memberships", { body: e }), delete: (e) => t("DELETE", "/workspace-memberships", { params: e }) });
-      k = "/extension";
-      q = (t) => ({ get: () => t("GET", `${k}`), updateContentPieceData: (e) => t("POST", `${k}/content-piece-data`, { body: e }) });
-      l = "/variants";
-      A = (t) => ({ create: (e) => t("POST", `${l}`, { body: e }), update: (e) => t("PUT", `${l}`, { body: e }), delete: (e) => t("DELETE", `${l}`, { params: e }), list: () => t("GET", `${l}/list`) });
-      u = "/transformers";
-      z = (t) => ({ create: (e) => t("POST", `${u}`, { body: e }), delete: (e) => t("DELETE", `${u}`, { params: e }), list: () => t("GET", `${u}/list`) });
-      B = (t) => {
-        const { sendRequest: e, reconfigure: n, getConfig: c } = f(t);
-        return { contentGroups: w(e), contentPieces: U(e), tags: S(e), profile: O(e), userSettings: L(e), webhooks: R(e), workspace: x(e), roles: I(e), workspaceSettings: j(e), workspaceMemberships: v(e), extension: q(e), variants: A(e), transformers: z(e), search(s) {
-          return e("GET", "/search", { params: s });
-        }, async ask(s) {
-          let a = "";
-          const p = new import_eventsource.default(`${c().baseURL}/search/ask?query=${encodeURIComponent(s.query)}`, { headers: { Authorization: `Bearer ${c().token}` } });
-          p.addEventListener("error", (r) => {
-            const o = r;
-            return o.message ? s.onError?.(o.message) : (p.close(), s.onEnd?.(a));
-          }), p.addEventListener("message", (r) => {
-            const o = decodeURIComponent(r.data);
-            a += o, s.onChunk?.(o, a);
-          });
-        }, reconfigure: n };
+      I = (t) => ({ get: () => t("GET", `${C}`) });
+      u = "/roles";
+      v = (t) => ({ get: (e) => t("GET", `${u}`, { params: e }), create: (e) => t("POST", `${u}`, { body: e }), update: (e) => t("PUT", `${u}`, { body: e }), delete: (e) => t("DELETE", `${u}`, { params: e }), list: (e) => t("GET", `${u}/list`, { params: e }) });
+      k = "/workspace-settings";
+      j = (t) => ({ get: () => t("GET", `${k}`), update: (e) => t("PUT", `${k}`, { body: e }) });
+      q = (t) => ({ listMembers: (e) => t("GET", "/workspace-memberships/list-members", { params: e }), listWorkspaces: (e) => t("GET", "/workspace-memberships/list-workspaces", { params: e }), create: (e) => t("POST", "/workspace-memberships", { body: e }), update: (e) => t("PUT", "/workspace-memberships", { body: e }), delete: (e) => t("DELETE", "/workspace-memberships", { params: e }) });
+      G = "/extension";
+      A = (t) => ({ get: () => t("GET", `${G}`), updateContentPieceData: (e) => t("POST", `${G}/content-piece-data`, { body: e }) });
+      b = "/variants";
+      z = (t) => ({ create: (e) => t("POST", `${b}`, { body: e }), update: (e) => t("PUT", `${b}`, { body: e }), delete: (e) => t("DELETE", `${b}`, { params: e }), list: () => t("GET", `${b}/list`) });
+      y = "/transformers";
+      B = (t) => ({ create: (e) => t("POST", `${y}`, { body: e }), delete: (e) => t("DELETE", `${y}`, { params: e }), list: () => t("GET", `${y}/list`) });
+      M = (t) => {
+        const { sendRequest: e, reconfigure: c, getConfig: i, getSignal: $, useSignal: p } = f(t), s = { contentGroups: U(e), contentPieces: S(e), tags: D(e), profile: R(e), userSettings: L(e), webhooks: x(e), workspace: I(e), roles: v(e), workspaceSettings: j(e), workspaceMemberships: q(e), extension: A(e), variants: z(e), transformers: B(e), search(a) {
+          return e("GET", "/search", { params: a });
+        }, async ask(a) {
+          let n = "";
+          const o = new import_eventsource.default(`${i().baseURL}/search/ask?query=${encodeURIComponent(a.query)}`, { headers: { Authorization: `Bearer ${i().token}` } });
+          o.addEventListener("error", (d) => {
+            const r = d;
+            return r.message ? a.onError?.(r.message) : (o.close(), a.onEnd?.(n));
+          }), o.addEventListener("message", (d) => {
+            const r = decodeURIComponent(d.data);
+            n += r, a.onChunk?.(r, n);
+          }), $()?.addEventListener("abort", () => {
+            o.close();
+          }), p(null);
+        }, useSignal(a) {
+          return p(a), s;
+        }, reconfigure(a) {
+          return c(a), s;
+        } };
+        return s;
       };
     }
   });
 
   // scripts/sandbox.ts
diff --git a/apps/web/src/assets/json/light-theme.json b/apps/web/src/assets/json/light-theme.json
index 52ce7f9..822af80 100644
--- a/apps/web/src/assets/json/light-theme.json
+++ b/apps/web/src/assets/json/light-theme.json
@@ -1,469 +1,37 @@
 {
-  "inherit": false,
-  "base": "vs-dark",
-  "colors": {
-    "focusBorder": "#2188ff",
-    "foreground": "#444d56",
-    "descriptionForeground": "#6a737d",
-    "errorForeground": "#cb2431",
-    "textLink.foreground": "#0366d6",
-    "textLink.activeForeground": "#005cc5",
-    "textBlockQuote.background": "#fafbfc",
-    "textBlockQuote.border": "#e1e4e8",
-    "textCodeBlock.background": "#f6f8fa",
-    "textPreformat.foreground": "#586069",
-    "textSeparator.foreground": "#d1d5da",
-    "button.background": "#159739",
-    "button.foreground": "#ffffff",
-    "button.hoverBackground": "#138934",
-    "checkbox.background": "#fafbfc",
-    "checkbox.border": "#d1d5da",
-    "dropdown.background": "#fafbfc",
-    "dropdown.border": "#e1e4e8",
-    "dropdown.foreground": "#2f363d",
-    "dropdown.listBackground": "#ffffff",
-    "input.background": "#fafbfc",
-    "input.border": "#e1e4e8",
-    "input.foreground": "#2f363d",
-    "input.placeholderForeground": "#959da5",
-    "badge.foreground": "#005cc5",
-    "badge.background": "#dbedff",
-    "progressBar.background": "#2188ff",
-    "titleBar.activeForeground": "#2f363d",
-    "titleBar.activeBackground": "#ffffff",
-    "titleBar.inactiveForeground": "#6a737d",
-    "titleBar.inactiveBackground": "#f6f8fa",
-    "titleBar.border": "#e1e4e8",
-    "activityBar.foreground": "#2f363d",
-    "activityBar.inactiveForeground": "#959da5",
-    "activityBar.background": "#ffffff",
-    "activityBarBadge.foreground": "#ffffff",
-    "activityBarBadge.background": "#2188ff",
-    "activityBar.activeBorder": "#f9826c",
-    "activityBar.border": "#e1e4e8",
-    "sideBar.foreground": "#586069",
-    "sideBar.background": "#f6f8fa",
-    "sideBar.border": "#e1e4e8",
-    "sideBarTitle.foreground": "#2f363d",
-    "sideBarSectionHeader.foreground": "#2f363d",
-    "sideBarSectionHeader.background": "#f6f8fa",
-    "sideBarSectionHeader.border": "#e1e4e8",
-    "list.hoverForeground": "#2f363d",
-    "list.inactiveSelectionForeground": "#2f363d",
-    "list.activeSelectionForeground": "#2f363d",
-    "list.hoverBackground": "#ebf0f4",
-    "list.inactiveSelectionBackground": "#e8eaed",
-    "list.activeSelectionBackground": "#e2e5e9",
-    "list.inactiveFocusBackground": "#dbedff",
-    "list.focusBackground": "#cce5ff",
-    "tree.indentGuidesStroke": "#e1e4e8",
-    "notificationCenterHeader.foreground": "#6a737d",
-    "notificationCenterHeader.background": "#e1e4e8",
-    "notifications.foreground": "#2f363d",
-    "notifications.background": "#fafbfc",
-    "notifications.border": "#e1e4e8",
-    "notificationsErrorIcon.foreground": "#d73a49",
-    "notificationsWarningIcon.foreground": "#e36209",
-    "notificationsInfoIcon.foreground": "#005cc5",
-    "pickerGroup.border": "#e1e4e8",
-    "pickerGroup.foreground": "#2f363d",
-    "quickInput.background": "#fafbfc",
-    "quickInput.foreground": "#2f363d",
-    "statusBar.foreground": "#586069",
-    "statusBar.background": "#ffffff",
-    "statusBar.border": "#e1e4e8",
-    "statusBar.noFolderBackground": "#ffffff",
-    "statusBar.debuggingBackground": "#f9826c",
-    "statusBar.debuggingForeground": "#ffffff",
-    "editorGroupHeader.tabsBackground": "#f6f8fa",
-    "editorGroupHeader.tabsBorder": "#e1e4e8",
-    "editorGroup.border": "#e1e4e8",
-    "tab.activeForeground": "#2f363d",
-    "tab.inactiveForeground": "#6a737d",
-    "tab.inactiveBackground": "#f6f8fa",
-    "tab.activeBackground": "#ffffff",
-    "tab.hoverBackground": "#ffffff",
-    "tab.unfocusedHoverBackground": "#ffffff",
-    "tab.border": "#e1e4e8",
-    "tab.unfocusedActiveBorderTop": "#e1e4e8",
-    "tab.activeBorder": "#ffffff",
-    "tab.unfocusedActiveBorder": "#ffffff",
-    "tab.activeBorderTop": "#f9826c",
-    "breadcrumb.foreground": "#6a737d",
-    "breadcrumb.focusForeground": "#2f363d",
-    "breadcrumb.activeSelectionForeground": "#586069",
-    "breadcrumbPicker.background": "#fafbfc",
-    "editor.foreground": "#24292e",
-    "editor.background": "#f9fafb",
-    "editorWidget.background": "#f3f4f6",
-    "editorWidget.border": "#e5e7eb",
-    "editor.foldBackground": "#fafbfc",
-    "editor.lineHighlightBackground": "#f6f8fa",
-    "editorLineNumber.foreground": "#1b1f234d",
-    "editorLineNumber.activeForeground": "#24292e",
-    "editorIndentGuide.background": "#eff2f6",
-    "editorIndentGuide.activeBackground": "#d7dbe0",
-    "editorWhitespace.foreground": "#d1d5da",
-    "editorCursor.foreground": "#044289",
-    "editor.findMatchBackground": "#ffdf5d",
-    "editor.findMatchHighlightBackground": "#ffdf5d66",
-    "editor.inactiveSelectionBackground": "#0366d611",
-    "editor.selectionBackground": "#0366d625",
-    "editor.selectionHighlightBackground": "#34d05840",
-    "editor.selectionHighlightBorder": "#34d05800",
-    "editor.wordHighlightBackground": "#34d05800",
-    "editor.wordHighlightStrongBackground": "#34d05800",
-    "editor.wordHighlightBorder": "#24943e99",
-    "editor.wordHighlightStrongBorder": "#24943e50",
-    "editorBracketMatch.background": "#34d05840",
-    "editorBracketMatch.border": "#34d05800",
-    "editorGutter.modifiedBackground": "#2188ff",
-    "editorGutter.addedBackground": "#28a745",
-    "editorGutter.deletedBackground": "#d73a49",
-    "diffEditor.insertedTextBackground": "#34d05822",
-    "diffEditor.removedTextBackground": "#d73a4922",
-    "scrollbar.shadow": "#6a737d33",
-    "scrollbarSlider.background": "#959da533",
-    "scrollbarSlider.hoverBackground": "#959da544",
-    "scrollbarSlider.activeBackground": "#959da588",
-    "editorOverviewRuler.border": "#ffffff",
-    "panel.background": "#f6f8fa",
-    "panel.border": "#e1e4e8",
-    "panelTitle.activeBorder": "#f9826c",
-    "panelTitle.activeForeground": "#2f363d",
-    "panelTitle.inactiveForeground": "#6a737d",
-    "panelInput.border": "#e1e4e8",
-    "terminal.foreground": "#586069",
-    "gitDecoration.addedResourceForeground": "#28a745",
-    "gitDecoration.modifiedResourceForeground": "#005cc5",
-    "gitDecoration.deletedResourceForeground": "#d73a49",
-    "gitDecoration.untrackedResourceForeground": "#28a745",
-    "gitDecoration.ignoredResourceForeground": "#959da5",
-    "gitDecoration.conflictingResourceForeground": "#e36209",
-    "gitDecoration.submoduleResourceForeground": "#959da5",
-    "debugToolBar.background": "#ffffff",
-    "editor.stackFrameHighlightBackground": "#fffbdd",
-    "editor.focusedStackFrameHighlightBackground": "#fff5b1",
-    "settings.headerForeground": "#2f363d",
-    "settings.modifiedItemIndicator": "#2188ff",
-    "welcomePage.buttonBackground": "#f6f8fa",
-    "welcomePage.buttonHoverBackground": "#e1e4e8"
-  },
+  "base": "vs",
+  "inherit": true,
   "rules": [
     {
-      "foreground": "#6a737d",
-      "token": "comment"
-    },
-    {
-      "foreground": "#6a737d",
-      "token": "punctuation.definition.comment"
-    },
-    {
-      "foreground": "#6a737d",
-      "token": "string.comment"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "constant"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "entity.name.constant"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "variable.other.constant"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "variable.language"
-    },
-    {
-      "foreground": "#6f42c1",
-      "token": "entity"
-    },
-    {
-      "foreground": "#6f42c1",
-      "token": "entity.name"
-    },
-    {
-      "foreground": "#24292e",
-      "token": "variable.parameter.function"
-    },
-    {
-      "foreground": "#22863a",
-      "token": "entity.name.tag"
-    },
-    {
-      "foreground": "#d73a49",
-      "token": "keyword"
-    },
-    {
-      "foreground": "#d73a49",
-      "token": "storage"
-    },
-    {
-      "foreground": "#d73a49",
-      "token": "storage.type"
-    },
-    {
-      "foreground": "#24292e",
-      "token": "storage.modifier.package"
-    },
-    {
-      "foreground": "#24292e",
-      "token": "storage.modifier.import"
-    },
-    {
-      "foreground": "#24292e",
-      "token": "storage.type.java"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "punctuation.definition.string"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string punctuation.section.embedded source"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "support"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "meta.property-name"
-    },
-    {
-      "foreground": "#e36209",
-      "token": "variable"
-    },
-    {
-      "foreground": "#24292e",
-      "token": "variable.other"
-    },
-    {
-      "fontStyle": "italic",
-      "foreground": "#b31d28",
-      "token": "invalid.broken"
-    },
-    {
-      "fontStyle": "italic",
-      "foreground": "#b31d28",
-      "token": "invalid.deprecated"
-    },
-    {
-      "fontStyle": "italic",
-      "foreground": "#b31d28",
-      "token": "invalid.illegal"
-    },
-    {
-      "fontStyle": "italic",
-      "foreground": "#b31d28",
-      "token": "invalid.unimplemented"
-    },
-    {
-      "fontStyle": "italic underline",
-      "background": "#d73a49",
-      "foreground": "#fafbfc",
-      "content": "^M",
-      "token": "carriage-return"
-    },
-    {
-      "foreground": "#b31d28",
-      "token": "message.error"
-    },
-    {
-      "foreground": "#24292e",
-      "token": "string source"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "string variable"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "source.regexp"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string.regexp"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string.regexp.character-class"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string.regexp constant.character.escape"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string.regexp source.ruby.embedded"
-    },
-    {
-      "foreground": "#032f62",
-      "token": "string.regexp string.regexp.arbitrary-repitition"
-    },
-    {
-      "fontStyle": "bold",
-      "foreground": "#22863a",
-      "token": "string.regexp constant.character.escape"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "support.constant"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "support.variable"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "meta.module-reference"
-    },
-    {
-      "foreground": "#e36209",
-      "token": "punctuation.definition.list.begin.markdown"
-    },
-    {
-      "fontStyle": "bold",
-      "foreground": "#005cc5",
-      "token": "markup.heading"
-    },
-    {
-      "fontStyle": "bold",
-      "foreground": "#005cc5",
-      "token": "markup.heading entity.name"
-    },
-    {
-      "foreground": "#22863a",
-      "token": "markup.quote"
-    },
-    {
-      "fontStyle": "italic",
-      "foreground": "#24292e",
-      "token": "markup.italic"
-    },
-    {
-      "fontStyle": "bold",
-      "foreground": "#24292e",
-      "token": "markup.bold"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "markup.raw"
-    },
-    {
-      "background": "#ffeef0",
-      "foreground": "#b31d28",
-      "token": "markup.deleted"
-    },
-    {
-      "background": "#ffeef0",
-      "foreground": "#b31d28",
-      "token": "meta.diff.header.from-file"
-    },
-    {
-      "background": "#ffeef0",
-      "foreground": "#b31d28",
-      "token": "punctuation.definition.deleted"
-    },
-    {
-      "background": "#f0fff4",
-      "foreground": "#22863a",
-      "token": "markup.inserted"
-    },
-    {
-      "background": "#f0fff4",
-      "foreground": "#22863a",
-      "token": "meta.diff.header.to-file"
-    },
-    {
-      "background": "#f0fff4",
-      "foreground": "#22863a",
-      "token": "punctuation.definition.inserted"
-    },
-    {
-      "background": "#ffebda",
-      "foreground": "#e36209",
-      "token": "markup.changed"
-    },
-    {
-      "background": "#ffebda",
-      "foreground": "#e36209",
-      "token": "punctuation.definition.changed"
-    },
-    {
-      "foreground": "#f6f8fa",
-      "background": "#005cc5",
-      "token": "markup.ignored"
-    },
-    {
-      "foreground": "#f6f8fa",
-      "background": "#005cc5",
-      "token": "markup.untracked"
-    },
-    {
-      "foreground": "#6f42c1",
-      "fontStyle": "bold",
-      "token": "meta.diff.range"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "meta.diff.header"
-    },
-    {
-      "fontStyle": "bold",
-      "foreground": "#005cc5",
-      "token": "meta.separator"
-    },
-    {
-      "foreground": "#005cc5",
-      "token": "meta.output"
-    },
-    {
-      "foreground": "#586069",
-      "token": "brackethighlighter.tag"
-    },
-    {
-      "foreground": "#586069",
-      "token": "brackethighlighter.curly"
-    },
-    {
-      "foreground": "#586069",
-      "token": "brackethighlighter.round"
-    },
-    {
-      "foreground": "#586069",
-      "token": "brackethighlighter.square"
-    },
-    {
-      "foreground": "#586069",
-      "token": "brackethighlighter.angle"
-    },
-    {
-      "foreground": "#586069",
-      "token": "brackethighlighter.quote"
-    },
-    {
-      "foreground": "#b31d28",
-      "token": "brackethighlighter.unmatched"
-    },
-    {
-      "foreground": "#032f62",
-      "fontStyle": "underline",
-      "token": "constant.other.reference.link"
-    },
-    {
-      "foreground": "#032f62",
-      "fontStyle": "underline",
-      "token": "string.other.link"
+      "token": "",
+      "settings": {
+        "foreground": "#000000",
+        "background": "#FFFFFF"
+      }
     }
   ],
-  "encodedTokensColors": []
+  "colors": {
+    "editor.background": "#f9fafb",
+    "editorWidget.background": "#f3f4f6",
+    "editor.foreground": "#000000",
+    "editor.inactiveSelectionBackground": "#E5EBF1",
+    "editorIndentGuide.background": "#D3D3D3",
+    "editorIndentGuide.activeBackground": "#939393",
+    "editor.selectionHighlightBackground": "#ADD6FF80",
+    "editorSuggestWidget.background": "#F3F3F3",
+    "activityBarBadge.background": "#007ACC",
+    "sideBarTitle.foreground": "#6F6F6F",
+    "list.hoverBackground": "#E8E8E8",
+    "input.placeholderForeground": "#767676",
+    "searchEditor.textInputBorder": "#CECECE",
+    "settings.textInputBorder": "#CECECE",
+    "settings.numberInputBorder": "#CECECE",
+    "statusBarItem.remoteForeground": "#FFF",
+    "statusBarItem.remoteBackground": "#16825D",
+    "sideBarSectionHeader.background": "#0000",
+    "sideBarSectionHeader.border": "#61616130",
+    "tab.lastPinnedBorder": "#61616130",
+    "notebook.cellBorderColor": "#E8E8E8",
+    "statusBarItem.errorBackground": "#c72e0f"
+  }
 }
diff --git a/apps/web/src/components/fragments/mini-code-editor.tsx b/apps/web/src/components/fragments/mini-code-editor.tsx
index b894f23..1185754 100644
--- a/apps/web/src/components/fragments/mini-code-editor.tsx
+++ b/apps/web/src/components/fragments/mini-code-editor.tsx
@@ -79,11 +79,10 @@ const MiniCodeEditor: Component<MiniCodeEditorProps> = (props) => {
         hover: { enabled: !props.readOnly },
         scrollBeyondLastLine: false,
         model: null,
         wordWrap: props.wrap ? "on" : "off",
         readOnly: typeof props.readOnly === "boolean" ? props.readOnly : false,
-        theme: "dark-contrast",
         scrollbar: {
           alwaysConsumeMouseWheel: false
         }
       });
 
@@ -138,15 +137,10 @@ const MiniCodeEditor: Component<MiniCodeEditorProps> = (props) => {
               );
             }
           }
         )
       );
-      createEffect(() => {
-        props.monaco.editor.setTheme(
-          `${codeEditorTheme()}${props.color === "contrast" ? "-contrast" : ""}`
-        );
-      });
       onCleanup(() => {
         codeEditor.getModel()?.dispose();
         codeEditor.dispose();
       });
     }
@@ -155,11 +149,12 @@ const MiniCodeEditor: Component<MiniCodeEditorProps> = (props) => {
   return (
     <div class={clsx("relative w-full", props.wrapperClass)}>
       <div
         ref={setEditorContainerRef}
         class={clsx(
-          "w-full bg-gray-100 border-2 not-prose dark:bg-gray-900 rounded-2xl dark:border-gray-700 rounded",
+          "w-full bg-gray-100 border-2 not-prose dark:bg-gray-900 rounded-2xl dark:border-gray-700 rounded-editor-2xl customized-editor box-content",
+          props.color === "contrast" && "customized-editor-contrast",
           props.class
         )}
       ></div>
       <Show when={props.onSave && props.code !== currentCode()}>
         <IconButton
diff --git a/apps/web/src/context/appearance.tsx b/apps/web/src/context/appearance.tsx
index 7e03eb5..c734adc 100644
--- a/apps/web/src/context/appearance.tsx
+++ b/apps/web/src/context/appearance.tsx
@@ -11,11 +11,11 @@ interface AppearanceContextData {
 }
 
 const AppearanceContext = createContext<AppearanceContextData>();
 const AppearanceProvider: ParentComponent = (props) => {
   const {
-    userSettings = () => ({ accentColor: "energy", codeEditorTheme: "dark", uiTheme: "auto" })
+    userSettings = () => ({ accentColor: "energy", codeEditorTheme: "auto", uiTheme: "auto" })
   } = useAuthenticatedUserData() || {};
   const prefersDark = createPrefersDark();
   const uiTheme = (): BaseTheme => {
     if (userSettings()?.uiTheme === "auto") {
       return prefersDark() ? "dark" : "light";
diff --git a/apps/web/src/context/authenticated-user-data.tsx b/apps/web/src/context/authenticated-user-data.tsx
index 3c53a32..bdd1f16 100644
--- a/apps/web/src/context/authenticated-user-data.tsx
+++ b/apps/web/src/context/authenticated-user-data.tsx
@@ -182,36 +182,10 @@ const AuthenticatedUserDataProvider: ParentComponent = (props) => {
           if (action === "update" && workspaceSettings()) {
             setWorkspaceSettings((workspaceSettings) => ({
               ...workspaceSettings!,
               ...data
             }));
-          } else if (action === "createWrapper") {
-            setWorkspaceSettings((workspaceSettings) => ({
-              ...workspaceSettings!,
-              wrappers: [...(workspaceSettings?.wrappers || []), data]
-            }));
-          } else if (action === "deleteWrapper") {
-            setWorkspaceSettings((workspaceSettings) => ({
-              ...workspaceSettings!,
-              wrappers: (workspaceSettings?.wrappers || []).filter(
-                (wrapper) => wrapper.key !== data.key
-              )
-            }));
-          } else if (action === "updateWrapper") {
-            setWorkspaceSettings((workspaceSettings) => ({
-              ...workspaceSettings!,
-              wrappers: (workspaceSettings?.wrappers || []).map((wrapper) => {
-                if (wrapper.key === data.key) {
-                  return {
-                    ...wrapper,
-                    ...data
-                  };
-                }
-
-                return wrapper;
-              })
-            }));
           }
         }
       });
       const tagsChanges = client.tags.changes.subscribe(undefined, {
         onData({ action, data }) {
diff --git a/apps/web/src/context/client.tsx b/apps/web/src/context/client.tsx
index 42ea4f7..b4a06f9 100644
--- a/apps/web/src/context/client.tsx
+++ b/apps/web/src/context/client.tsx
@@ -59,11 +59,11 @@ const refreshTokenLink = (closeConnection: () => void): TRPCLink<App.Router> =>
                 observer.error(error);
 
                 return;
               }
 
-              if (error.data?.code === "UNAUTHORIZED") {
+              if (error.data?.code === "UNAUTHORIZED" && window.location.pathname !== "/auth") {
                 attempt();
               } else {
                 observer.error(error);
               }
             },
diff --git a/apps/web/src/context/extensions.tsx b/apps/web/src/context/extensions.tsx
index c730098..cbe7468 100644
--- a/apps/web/src/context/extensions.tsx
+++ b/apps/web/src/context/extensions.tsx
@@ -34,11 +34,12 @@ interface ExtensionsContextData {
 
 const officialExtensions = {
   "dev": () => import("@vrite/extensions/dev.json"),
   "hashnode": () => import("@vrite/extensions/hashnode.json"),
   "medium": () => import("@vrite/extensions/medium.json"),
-  "gpt-3.5": () => import("@vrite/extensions/gpt-3.5.json")
+  "gpt-3.5": () => import("@vrite/extensions/gpt-3.5.json"),
+  "mdx": () => import("@vrite/extensions/mdx.json")
 };
 const isOfficialExtension = (id: string): boolean => {
   return id in officialExtensions;
 };
 const ExtensionsContext = createContext<ExtensionsContextData>();
diff --git a/apps/web/src/layout/toolbar/index.tsx b/apps/web/src/layout/toolbar/index.tsx
index 88d70b7..fd2c997 100644
--- a/apps/web/src/layout/toolbar/index.tsx
+++ b/apps/web/src/layout/toolbar/index.tsx
@@ -433,11 +433,11 @@ const Toolbar: Component<{ class?: string }> = (props) => {
   });
 
   return (
     <div
       class={clsx(
-        ":base-2: p-1 w-full flex items-center border-b-2 absolute h-12 border-gray-200 dark:border-gray-700 justify-end @container z-1",
+        ":base-2: p-1 w-full flex items-center border-b-2 absolute h-12 border-gray-200 dark:border-gray-700 justify-end @container z-10",
         props.class
       )}
     >
       <Dynamic component={view()} />
     </div>
diff --git a/apps/web/src/lib/code-editor/format.ts b/apps/web/src/lib/code-editor/format.ts
index 97e90f0..b95b1d1 100644
--- a/apps/web/src/lib/code-editor/format.ts
+++ b/apps/web/src/lib/code-editor/format.ts
@@ -2,19 +2,20 @@ import { format } from "prettier/standalone";
 import type { Options, Plugin } from "prettier";
 
 const languageParserMap = {
   javascript: "babel",
   typescript: "babel-ts",
-  json: "yaml",
+  json: "json-stringify",
   graphql: "graphql",
   html: "html",
   vue: "vue",
   markdown: "markdown",
   yaml: "yaml",
   css: "css",
   less: "less",
-  scss: "scss"
+  scss: "scss",
+  mdx: "mdx"
 } as const;
 
 type SupportedLanguages = keyof typeof languageParserMap;
 
 const isFormattable = (language: string): boolean => {
@@ -22,23 +23,24 @@ const isFormattable = (language: string): boolean => {
 };
 const loadParserPlugins = async (language: string): Promise<Plugin[] | null> => {
   switch (language as SupportedLanguages) {
     case "javascript":
     case "typescript":
+    case "json":
       return [
         await import("prettier/plugins/babel"),
         (await import("prettier/plugins/estree")) as Plugin
       ];
     case "graphql":
       return [await import("prettier/plugins/graphql")];
     case "html":
     case "vue":
       return [await import("prettier/plugins/html")];
     case "markdown":
+    case "mdx":
       return [await import("prettier/plugins/markdown")];
     case "yaml":
-    case "json":
       return [await import("prettier/plugins/yaml")];
     case "css":
     case "less":
     case "scss":
       return [await import("prettier/plugins/postcss")];
@@ -52,15 +54,11 @@ const formatCode = async (code: string, language: string, options?: Options): Pr
 
   if (parser && parserPlugins) {
     return format(code, {
       ...(options || {}),
       parser,
-      plugins: parserPlugins,
-      ...(language === "json" && {
-        trailingComma: "none",
-        singleQuote: false
-      })
+      plugins: parserPlugins
     });
   }
 
   return code;
 };
diff --git a/apps/web/src/lib/code-editor/suggest-language.ts b/apps/web/src/lib/code-editor/suggest-language.ts
index a559648..f59e73e 100644
--- a/apps/web/src/lib/code-editor/suggest-language.ts
+++ b/apps/web/src/lib/code-editor/suggest-language.ts
@@ -12,25 +12,26 @@ const getLanguageIds = (
     })
     .map((language) => {
       return { id: language.id };
     });
 };
-const useSuggestLanguage = (
-  languages: monaco.languages.ILanguageExtensionPoint[]
-): ((query: string) => string[]) => {
-  const languageIds = getLanguageIds(languages);
+const useSuggestLanguage = (): ((query: string) => string[]) => {
   const engine =
     searchEngine() ||
     new MiniSearch({
       fields: ["id"],
       searchOptions: {
         prefix: true
       }
     });
 
   if (!searchEngine()) {
-    engine.addAll(languageIds);
+    import("#lib/monaco").then(({ monaco }) => {
+      const languageIds = getLanguageIds(monaco.languages.getLanguages());
+
+      engine.addAll(languageIds);
+    });
     setSearchEngine(engine);
   }
 
   return (query: string) => {
     const suggestions = engine.autoSuggest(query, { prefix: true });
diff --git a/apps/web/src/lib/editor/editing.ts b/apps/web/src/lib/editor/editing.ts
index 23aa01d..6776219 100644
--- a/apps/web/src/lib/editor/editing.ts
+++ b/apps/web/src/lib/editor/editing.ts
@@ -1,6 +1,6 @@
-import { CodeBlock, Embed, Image, Wrapper } from "./extensions";
+import { CodeBlock, Embed, Image, Element } from "./extensions";
 import { SlashMenuItem } from "./extensions/slash-menu/component";
 import { Editor, Node as NodeExtension, Mark as MarkExtension } from "@tiptap/core";
 import { DOMOutputSpec, DOMSerializer, Mark, Node } from "@tiptap/pm/model";
 import {
   Heading,
@@ -116,11 +116,11 @@ const createExtensions = (
     taskList: TaskList,
     blockquote: Blockquote,
     codeBlock: CodeBlock.configure({ provider }),
     horizontalRule: HorizontalRule,
     image: Image,
-    wrapper: Wrapper,
+    element: Element,
     table: [Table, TableCell, TableHeader, TableRow]
   };
   const getHeadingLevels = (settings: App.WorkspaceSettings): Level[] => {
     return settings.blocks
       .filter((block) => block.startsWith("heading"))
@@ -283,17 +283,17 @@ const createBlockMenuOptions = (settings?: App.WorkspaceSettings): SlashMenuItem
       command({ editor, range }) {
         return editor.chain().focus().deleteRange(range).setHorizontalRule().run();
       }
     },
     {
-      label: "Wrapper",
+      label: "Element",
       group: "Blocks",
-      block: "wrapper",
+      block: "element",
       icon: mdiCubeOutline,
       ref: createRef<HTMLElement | null>(null),
       command({ editor, range }) {
-        return editor.chain().focus().deleteRange(range).setWrapper().run();
+        return editor.chain().focus().deleteRange(range).setElement().run();
       }
     },
     {
       label: "CodePen",
       icon: mdiCodepen,
diff --git a/apps/web/src/lib/editor/extensions/block-action-menu/component.tsx b/apps/web/src/lib/editor/extensions/block-action-menu/component.tsx
index f574db7..8bf1a62 100644
--- a/apps/web/src/lib/editor/extensions/block-action-menu/component.tsx
+++ b/apps/web/src/lib/editor/extensions/block-action-menu/component.tsx
@@ -123,11 +123,11 @@ const BlockActionMenu: Component<BlockActionMenuProps> = (props) => {
             <Dropdown
               placement="left-end"
               class={clsx(
                 blockAction.blocks.length !== 0 &&
                   !blockAction.blocks.some((block) => {
-                    return node()?.hasMarkup(props.state.editor.schema.nodes[block]);
+                    return node()?.type.name === props.state.editor.schema.nodes[block].name;
                   }) &&
                   "hidden"
               )}
               cardProps={{ class: "p-0 m-0 -ml-1 pr-1.5 p-3" }}
               overlayProps={{
diff --git a/apps/web/src/lib/editor/extensions/block-action-menu/plugin.tsx b/apps/web/src/lib/editor/extensions/block-action-menu/plugin.tsx
index aaf916d..4be8fd2 100644
--- a/apps/web/src/lib/editor/extensions/block-action-menu/plugin.tsx
+++ b/apps/web/src/lib/editor/extensions/block-action-menu/plugin.tsx
@@ -109,11 +109,11 @@ const BlockActionMenuPlugin = Extension.create({
       try {
         const p = findParentAtDepth(selection.$from, 1);
 
         rangeFrom = p.start - 1;
         rangeTo = p.start + p.node.nodeSize - 1;
-      } catch (e) {
+      } catch (error) {
         box.style.display = "none";
       }
     }
 
     component?.setState({
diff --git a/apps/web/src/lib/editor/extensions/code-block/menu.tsx b/apps/web/src/lib/editor/extensions/code-block/menu.tsx
index f26ed79..6500f21 100644
--- a/apps/web/src/lib/editor/extensions/code-block/menu.tsx
+++ b/apps/web/src/lib/editor/extensions/code-block/menu.tsx
@@ -1,59 +1,131 @@
 import { CodeBlockAttributes } from "./node";
-import { useSolidNodeView } from "@vrite/tiptap-solid";
-import { mdiCodeTagsCheck } from "@mdi/js";
+import { SolidNodeViewProps } from "@vrite/tiptap-solid";
+import { mdiCodeTags, mdiCodeTagsCheck, mdiFileOutline } from "@mdi/js";
 import { Component, createEffect, createMemo, createSignal, on, Show } from "solid-js";
-import type { monaco } from "#lib/monaco";
-import { IconButton, Input, Tooltip } from "#components/primitives";
+import { debounce } from "@solid-primitives/scheduled";
+import { Card, IconButton, Input, Tooltip } from "#components/primitives";
 import { useSuggestLanguage, isFormattable } from "#lib/code-editor";
+import { createRef } from "#lib/utils";
 
 interface CodeBlockMenuProps {
-  monaco: typeof monaco;
+  state: SolidNodeViewProps<CodeBlockAttributes>;
+  changeLanguage(lang: string | null): void;
   format(): void;
-  changeLanguage(languageId: string | null): void;
 }
 
 const CodeBlockMenu: Component<CodeBlockMenuProps> = (props) => {
-  const { state } = useSolidNodeView();
-  const attrs = (): CodeBlockAttributes => state().node.attrs;
+  const [mode, setMode] = createSignal<"title" | "lang">("lang");
+  const [menuRef, setMenuRef] = createRef<HTMLElement | null>(null);
+  const [left, setLeft] = createSignal(0);
   const [suggestions, setSuggestions] = createSignal<string[]>([]);
-  const suggestLanguage = useSuggestLanguage(props.monaco.languages.getLanguages());
-  const formattingAvailable = createMemo(() => {
-    return isFormattable(attrs().lang || "");
-  });
+  const attrs = (): CodeBlockAttributes => props.state.node.attrs;
+  const suggestLanguage = useSuggestLanguage();
+  const formattingAvailable = createMemo(() => isFormattable(attrs().lang?.split(" ")?.[0] || ""));
+  const updateAttribute = debounce((attributes: CodeBlockAttributes) => {
+    return props.state.updateAttributes(attributes);
+  }, 200);
+  const currentValue = (): string => {
+    if (mode() === "lang") {
+      return [attrs().lang, attrs().meta].filter(Boolean).join(" ");
+    }
+
+    return attrs().title || "";
+  };
 
   createEffect(
-    on(attrs, () => {
-      setSuggestions(suggestLanguage(attrs().lang || ""));
-      props.changeLanguage(attrs().lang || null);
+    on(attrs, (attrs) => {
+      setSuggestions(suggestLanguage(attrs.lang || ""));
+      props.changeLanguage(attrs.lang?.split(" ")?.[0] || null);
     })
   );
+  createEffect(
+    on(
+      () => props.state.selected,
+      () => {
+        const element = menuRef();
+
+        if (!element || !element.parentElement) return;
+
+        const { left, width } = element.parentElement.getBoundingClientRect();
+        const right = window.innerWidth - left - width;
+
+        setLeft(-Math.abs((right - left) / 2));
+      }
+    )
+  );
 
   return (
-    <div class="flex p-0 transition-shadow duration-200 border-0 rounded-xl">
-      <Input
-        wrapperClass="flex-1 max-w-full"
-        placeholder="Language"
-        value={attrs().lang || ""}
-        suggestions={suggestions()}
-        color="contrast"
-        disabled={!state().editor.isEditable}
-        setValue={(value) => {
-          state().updateAttributes({ lang: value });
-        }}
-      />
-      <Show when={state().editor.isEditable}>
-        <Tooltip text={formattingAvailable() ? "Format" : "Formatting unavailable"}>
+    <div
+      class="pointer-events-auto flex bg-gray-50 dark:bg-gray-900 !md:bg-transparent border-gray-200 dark:border-gray-700 border-y-2 md:border-0 backdrop-blur-sm md:gap-2 w-screen md:w-auto !md:left-unset relative md:rounded-2xl"
+      style={{ left: `${left()}px` }}
+      ref={setMenuRef}
+    >
+      <Card class="flex py-0 m-0 border-0 md:border-2 px-1 gap-1">
+        <Tooltip text="Title">
           <IconButton
-            path={mdiCodeTagsCheck}
-            color="contrast"
-            text="soft"
-            disabled={!formattingAvailable()}
-            onClick={props.format}
+            path={mdiFileOutline}
+            color={mode() === "title" ? "primary" : "contrast"}
+            text={mode() === "title" ? "primary" : "soft"}
+            variant={mode() === "title" ? "solid" : "text"}
+            class="m-0"
+            onClick={() => {
+              setMode("title");
+            }}
           ></IconButton>
         </Tooltip>
-      </Show>
+        <Tooltip text="Language">
+          <IconButton
+            path={mdiCodeTags}
+            color={mode() === "lang" ? "primary" : "contrast"}
+            text={mode() === "lang" ? "primary" : "soft"}
+            variant={mode() === "lang" ? "solid" : "text"}
+            class="m-0"
+            onClick={() => {
+              setMode("lang");
+            }}
+          ></IconButton>
+        </Tooltip>
+      </Card>
+      <Card class="flex m-0 border-0 md:border-2 p-1 gap-1 flex-1">
+        <Input
+          wrapperClass="flex-1 max-w-full md:w-72"
+          placeholder={mode() === "title" ? "Snippet title" : "Language meta"}
+          value={currentValue()}
+          suggestions={mode() === "lang" ? suggestions() : []}
+          suggestionsBoxClass="mt-3 mx-0 mb-0"
+          class="m-0 !bg-transparent text-lg"
+          color="contrast"
+          disabled={!props.state.editor.isEditable}
+          setValue={(value) => {
+            updateAttribute.clear();
+
+            if (mode() === "lang") {
+              const [lang, ...meta] = value.split(" ");
+
+              updateAttribute({ meta: meta.join(" "), lang });
+            } else {
+              updateAttribute({ title: value });
+            }
+          }}
+        />
+      </Card>
+      <Card class="flex m-0 border-0 md:border-2 p-1">
+        <Show when={props.state.editor.isEditable}>
+          <Tooltip text={formattingAvailable() ? "Format" : "Formatting unavailable"} class="mt-1">
+            <IconButton
+              path={mdiCodeTagsCheck}
+              color="contrast"
+              text="soft"
+              variant="text"
+              class="m-0"
+              disabled={!formattingAvailable()}
+              onClick={props.format}
+            ></IconButton>
+          </Tooltip>
+        </Show>
+      </Card>
     </div>
   );
 };
 
 export { CodeBlockMenu };
diff --git a/apps/web/src/lib/editor/extensions/code-block/node.tsx b/apps/web/src/lib/editor/extensions/code-block/node.tsx
index 22201a3..fc90824 100644
--- a/apps/web/src/lib/editor/extensions/code-block/node.tsx
+++ b/apps/web/src/lib/editor/extensions/code-block/node.tsx
@@ -73,11 +73,11 @@ const CodeBlock = BaseCodeBlock.extend<CodeBlockOptions>({
             setLoading(false);
           });
         });
 
         return (
-          <NodeViewWrapper class="my-5">
+          <NodeViewWrapper>
             <Show when={!loading()}>
               <CodeBlockView
                 monaco={monacoRef()!}
                 updatingRef={updatingRef}
                 codeEditorRef={codeEditorRef}
diff --git a/apps/web/src/lib/editor/extensions/code-block/view.tsx b/apps/web/src/lib/editor/extensions/code-block/view.tsx
index 12d28c9..3ccbde8 100644
--- a/apps/web/src/lib/editor/extensions/code-block/view.tsx
+++ b/apps/web/src/lib/editor/extensions/code-block/view.tsx
@@ -1,21 +1,15 @@
 import { CodeBlockAttributes, CodeBlockOptions } from "./node";
 import { CodeBlockMenu } from "./menu";
 import { useSolidNodeView } from "@vrite/tiptap-solid";
 import clsx from "clsx";
-import { Component, createEffect, createSignal, onMount } from "solid-js";
+import { Component, createEffect, createSignal, on, onMount } from "solid-js";
 import { nanoid } from "nanoid";
 import type { monaco } from "#lib/monaco";
 import { formatCode } from "#lib/code-editor";
-import { Card } from "#components/primitives";
 import { createRef, selectionClasses } from "#lib/utils";
-import {
-  useAppearance,
-  useAuthenticatedUserData,
-  useNotifications,
-  useLocalStorage
-} from "#context";
+import { useAppearance, useAuthenticatedUserData, useNotifications } from "#context";
 
 interface CodeBlockViewProps {
   monaco: typeof monaco;
   codeEditorRef(): monaco.editor.IStandaloneCodeEditor | null;
   updatingRef(): boolean | null;
@@ -49,10 +43,11 @@ const CodeBlockView: Component<CodeBlockViewProps> = (props) => {
   const [editorContainerRef, setEditorContainerRef] = createRef<HTMLElement | null>(null);
   const [decorationsRef, setDecorationsRef] = createRef<string[]>([]);
   const [codeEditor, setCodeEditor] = createSignal<monaco.editor.IStandaloneCodeEditor | null>(
     null
   );
+  const [codeEditorActive, setCodeEditorActive] = createSignal(false);
   const [currentModelValue, setCurrentModelValue] = createRef("");
   const selected = (): boolean => {
     return state().selected;
   };
   const format = async (): Promise<void> => {
@@ -63,11 +58,11 @@ const CodeBlockView: Component<CodeBlockViewProps> = (props) => {
         JSON.parse(workspaceSettings()?.prettierConfig || "{}")
       );
 
       notify({ text: "Formatting code", type: "loading", promise: formattingCode });
 
-      const formattedCode = await formattingCode;
+      const formattedCode = (await formattingCode).trim();
 
       props.setUpdatingRef(true);
 
       const { tr } = state().editor.state;
       const offset = state().getPos() + 1;
@@ -104,11 +99,11 @@ const CodeBlockView: Component<CodeBlockViewProps> = (props) => {
       props.monaco.editor.setModelLanguage(model, languageId || "");
     }
   };
   const updateEditorHeight = (monacoEditor: monaco.editor.IStandaloneCodeEditor): void => {
     const container = monacoEditor.getContainerDomNode();
-    const contentHeight = Math.max(200, monacoEditor.getContentHeight());
+    const contentHeight = Math.max(20, monacoEditor.getContentHeight());
     const editorContainer = editorContainerRef();
 
     if (editorContainer) {
       editorContainer.style.height = `${contentHeight}px`;
     }
@@ -127,11 +122,10 @@ const CodeBlockView: Component<CodeBlockViewProps> = (props) => {
       const codeEditor = props.monaco.editor.create(editorContainer, {
         automaticLayout: true,
         model: null,
         fontSize: 13,
         fontFamily: "JetBrainsMonoVariable",
-        theme: "dark",
         tabSize: 2,
         insertSpaces: true,
         readOnly: !state().editor.isEditable,
         scrollbar: {
           alwaysConsumeMouseWheel: false
@@ -191,10 +185,14 @@ const CodeBlockView: Component<CodeBlockViewProps> = (props) => {
         setCurrentModelValue(codeEditor.getModel()?.getValue() || "");
       });
       codeEditor.onDidContentSizeChange(() => updateEditorHeight(codeEditor));
       codeEditor.onDidBlurEditorText(() => {
         options().provider?.awareness?.setLocalStateField("vscSelection", null);
+        setCodeEditorActive(false);
+      });
+      codeEditor.onDidFocusEditorText(() => {
+        setCodeEditorActive(true);
       });
       codeEditor.onDidChangeCursorSelection(() => {
         const model = codeEditor.getModel();
         const sel = codeEditor.getSelection();
 
@@ -275,38 +273,43 @@ const CodeBlockView: Component<CodeBlockViewProps> = (props) => {
       createEffect(() => {
         props.monaco.editor.setTheme(codeEditorTheme());
       });
     }
   });
+  createEffect(
+    on(codeEditorActive, (active) => {
+      if (active) {
+        state().editor.commands.setNodeSelection(state().getPos());
+      }
+    })
+  );
 
   return (
     <div
       class={clsx(
-        "relative rounded-2xl not-prose text-base leading-4",
+        "relative rounded-2xl text-base leading-4 not-prose",
         selected() && "ring ring-primary ring-2"
       )}
       contentEditable={selected() ? false : undefined}
       draggable={false}
     >
       <div
         ref={setEditorContainerRef}
         spellcheck={false}
         class={clsx(
-          "w-full bg-gray-50 dark:bg-gray-900 h-72 not-prose rounded-t-2xl rounded",
-          codeEditorTheme() === "light" && "border-2 border-b-0 dark:border-0"
+          "bg-gray-50 dark:bg-gray-900 h-72 rounded-2xl rounded-editor-2xl border-2 border-gray-300 dark:border-gray-700 box-content customized-editor"
         )}
       />
-      <Card
+      <div
         class={clsx(
-          "m-0 rounded-t-none",
-          codeEditorTheme() === "dark" && "border-t-0 dark:border-0 dark:border-t-2",
-          codeEditorTheme() === "light" && "dark:border-t-0"
+          "absolute w-full justify-center items-center -bottom-14 z-1 pointer-events-none",
+          selected() ? "grid" : "hidden"
         )}
-        contentEditable={false}
       >
-        <CodeBlockMenu monaco={props.monaco} format={format} changeLanguage={changeLanguage} />
-      </Card>
+        <CodeBlockMenu changeLanguage={changeLanguage} format={format} state={state()} />
+      </div>
+      <div data-type="draggable-item" />
     </div>
   );
 };
 
 export { CodeBlockView };
diff --git a/apps/web/src/lib/editor/extensions/collab-cursor.tsx b/apps/web/src/lib/editor/extensions/collab-cursor.tsx
index c703835..9be8ad9 100644
--- a/apps/web/src/lib/editor/extensions/collab-cursor.tsx
+++ b/apps/web/src/lib/editor/extensions/collab-cursor.tsx
@@ -64,20 +64,32 @@ const CollabCursor = (provider: HocuspocusProvider): Extension => {
           w: number;
           top: number;
         }>(null);
 
         onMount(() => {
-          if (container.parentElement?.classList.contains("ProseMirror")) {
+          if (
+            container.parentElement?.classList.contains("ProseMirror") ||
+            container.parentElement?.classList.contains("content") ||
+            container.parentElement?.tagName === "TH" ||
+            container.parentElement?.tagName === "TD" ||
+            container.parentElement?.tagName === "LI" ||
+            container.parentElement?.tagName === "BLOCKQUOTE"
+          ) {
             const rect = container.previousElementSibling?.getBoundingClientRect();
-            const parentPos = document.getElementById("pm-container")?.getBoundingClientRect();
+
+            let parentPos = document.getElementById("pm-container")?.getBoundingClientRect();
+
+            if (container.parentElement?.classList.contains("content")) {
+              parentPos = container.parentElement?.getBoundingClientRect();
+            }
 
             if (!parentPos || !rect) return;
 
             setBlockSelection({
               h: rect.height,
               w: rect.width,
-              top: rect.top - parentPos.top - 20
+              top: rect.top - parentPos.top
             });
           }
         });
 
         return (
diff --git a/apps/web/src/lib/editor/extensions/element-menu/component.tsx b/apps/web/src/lib/editor/extensions/element-menu/component.tsx
new file mode 100644
index 0000000..6821f71
--- /dev/null
+++ b/apps/web/src/lib/editor/extensions/element-menu/component.tsx
@@ -0,0 +1,97 @@
+import { ElementMenuEditor } from "./editor";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { Component, Show, createEffect, createSignal } from "solid-js";
+import { Node as PMNode } from "@tiptap/pm/model";
+
+interface ElementMenuProps {
+  state: {
+    pos: number;
+    node: PMNode | null;
+    container: HTMLElement | null;
+    editor: SolidEditor;
+    active: boolean;
+  };
+}
+
+const ElementMenu: Component<ElementMenuProps> = (props) => {
+  const [attributes, setAttributes] = createSignal({ type: "", props: {} as Record<string, any> });
+
+  createEffect(() => {
+    setAttributes((attributes) => {
+      if (!props.state.node) {
+        return { type: "", props: {} };
+      }
+
+      const newAttributes = props.state.node.attrs;
+
+      if (
+        newAttributes.type !== attributes.type ||
+        JSON.stringify(newAttributes.props) !== JSON.stringify(attributes.props)
+      ) {
+        return { type: newAttributes.type, props: newAttributes.props };
+      }
+
+      return attributes;
+    });
+  });
+
+  return (
+    <Show when={props.state.editor.isEditable}>
+      <div class="flex">
+        <ElementMenuEditor
+          state={{
+            editor: props.state.editor,
+            type: attributes()?.type || "",
+            props: attributes()?.props || {},
+            active: props.state.active,
+            contentSize: props.state.node?.content.size || 0,
+
+            removeElement() {
+              props.state.editor.commands.command(({ tr, dispatch }) => {
+                if (!dispatch) return false;
+
+                const lastPos = props.state.pos;
+
+                if (typeof lastPos === "number" && props.state.node) {
+                  tr.delete(lastPos, lastPos + props.state.node.nodeSize);
+
+                  return true;
+                }
+
+                return false;
+              });
+            },
+            setElement(element) {
+              props.state.editor.commands.command(({ tr, dispatch }) => {
+                if (!dispatch) return false;
+
+                const lastPos = props.state.pos;
+
+                if (lastPos !== null) {
+                  tr.setNodeAttribute(lastPos, "type", element.type);
+                  tr.setNodeAttribute(lastPos, "props", element.props);
+
+                  if (element.content && !props.state.node?.content.size) {
+                    tr.replaceWith(
+                      lastPos + 1,
+                      lastPos + props.state.node!.content.size + 1,
+                      props.state.editor.schema.node("paragraph")
+                    );
+                  } else if (!element.content && props.state.node?.content.size) {
+                    tr.delete(lastPos + 1, lastPos + props.state.node!.content.size + 1);
+                  }
+
+                  return true;
+                }
+
+                return false;
+              });
+            }
+          }}
+        />
+      </div>
+    </Show>
+  );
+};
+
+export { ElementMenu };
diff --git a/apps/web/src/lib/editor/extensions/element-menu/editor.tsx b/apps/web/src/lib/editor/extensions/element-menu/editor.tsx
new file mode 100644
index 0000000..f7b3900
--- /dev/null
+++ b/apps/web/src/lib/editor/extensions/element-menu/editor.tsx
@@ -0,0 +1,303 @@
+import {
+  createEffect,
+  createMemo,
+  createRenderEffect,
+  createSignal,
+  lazy,
+  on,
+  onCleanup,
+  onMount
+} from "solid-js";
+import { createRef } from "@vrite/components/src/ref";
+import clsx from "clsx";
+import { nanoid } from "nanoid";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { scrollIntoView } from "seamless-scroll-polyfill";
+import { monaco } from "#lib/monaco";
+import { useAppearance } from "#context";
+import { formatCode } from "#lib/code-editor";
+
+interface ElementMenuEditorProps {
+  state: {
+    type: string;
+    active: boolean;
+    props: Record<string, any>;
+    editor: SolidEditor;
+    contentSize: number;
+    removeElement(): void;
+    setElement(element: { type: string; props: Record<string, any>; content: boolean }): void;
+  };
+}
+
+const codeEditorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
+  automaticLayout: true,
+  minimap: { enabled: false },
+  contextmenu: false,
+  fontSize: 17.5,
+  fontFamily: "JetBrainsMonoVariable",
+  scrollBeyondLastLine: false,
+  model: null,
+  wordWrap: "on",
+  theme: "dark",
+  suggestFontSize: 13,
+  codeLensFontSize: 13,
+  lineHeight: 26,
+  suggestLineHeight: 21,
+  overviewRulerBorder: false,
+  overviewRulerLanes: 0,
+  hideCursorInOverviewRuler: true,
+  lineNumbers: "off",
+  glyphMargin: false,
+  folding: false,
+  quickSuggestions: false,
+  lightbulb: { enabled: false },
+  hover: { enabled: false },
+  lineDecorationsWidth: 0,
+  lineNumbersMinChars: 0,
+  renderLineHighlightOnlyWhenFocus: true,
+  renderLineHighlight: "none",
+  scrollbar: {
+    vertical: "hidden",
+    horizontal: "hidden",
+    alwaysConsumeMouseWheel: false
+  }
+};
+const ElementMenuEditor = lazy(async () => {
+  const { monaco } = await import("#lib/monaco");
+
+  return {
+    default: (props: ElementMenuEditorProps) => {
+      const { codeEditorTheme = () => "dark" } = useAppearance() || {};
+      const [editorContainerRef, setEditorContainerRef] = createRef<HTMLElement | null>(null);
+      const [coords, setCoords] = createSignal({ x: 0, y: 0 });
+      const [visible, setVisible] = createSignal(true);
+      const type = createMemo(() => props.state.type);
+      const processCode = async (code: string): Promise<string> => {
+        const codeTagClosed = code?.trim().replace(/>$/, "/>") || "";
+        const formattedCode = await formatCode(codeTagClosed, "typescript", {
+          printWidth: 60,
+          trailingComma: "none",
+          singleQuote: false
+        });
+
+        return formattedCode.replace(/ *?\/>;/gm, props.state.contentSize ? ">" : "/>").trim();
+      };
+      const propsValue = createMemo((previous) => {
+        if (!previous || JSON.stringify(previous) !== JSON.stringify(props.state.props)) {
+          return props.state.props;
+        }
+
+        return previous;
+      });
+      const editorCode = createMemo(() => {
+        const keyValueProps = Object.entries(propsValue()).map(([key, value]) => {
+          if (value === true) return key;
+
+          const useBrackets =
+            typeof value !== "string" || value.includes("\n") || value.includes(`"`);
+
+          return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${
+            useBrackets ? "}" : ""
+          }`;
+        });
+
+        return `<${type()}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`;
+      });
+      const saveLastCoords = (event: MouseEvent): void => {
+        setCoords({ x: event.clientX, y: event.clientY });
+      };
+      const onSave = async (code: string): Promise<void> => {
+        const tagRegex = /^<(\w+?)(?:\s|\n|\/|>)/;
+        const attributeRegex =
+          /\s(\w+?)(?:=(?:(?:{((?:.|\n|\s)+?)})|(?:"((?:.|\n|\s)+?)")|(?:'((?:.|\n|\s)+?)')))?(?=(?:(?:\s|\n)+\w+=?)|(?:(?:\s|\n)*\/?>))/g;
+        const [, tag] = tagRegex.exec(code.trim()) || [];
+        const attributes: Record<string, any> = {};
+        const processAttributes = async (): Promise<void> => {
+          const match = attributeRegex.exec(code.trim());
+
+          if (!match) return;
+
+          const [, key] = match;
+          const value = (match[2] || match[3] || match[4] || "true").trim();
+
+          try {
+            const processedValue = await formatCode(value, "json", {
+              trailingComma: "none"
+            });
+
+            attributes[key] = JSON.parse(processedValue);
+          } catch (e) {
+            try {
+              attributes[key] = JSON.parse(value);
+            } catch (e) {
+              if (!props.state.props[key] || typeof props.state.props[key] === "string") {
+                attributes[key] = value;
+              } else {
+                attributes[key] = props.state.props[key];
+              }
+            }
+          }
+
+          await processAttributes();
+        };
+
+        await processAttributes();
+
+        if (tag && tag !== "undefined") {
+          props.state.setElement({
+            type: tag,
+            props: attributes,
+            content: !code.endsWith("/>")
+          });
+        } else {
+          props.state.removeElement();
+        }
+      };
+
+      onMount(() => {
+        const editorContainer = editorContainerRef()!;
+        const codeEditor = monaco.editor.create(editorContainer, codeEditorOptions);
+        const updateEditorHeight = (): void => {
+          const container = codeEditor.getContainerDomNode();
+          const contentHeight = Math.max(26, codeEditor.getContentHeight());
+
+          if (editorContainer) {
+            editorContainer.style.height = `${contentHeight}px`;
+          }
+
+          container.style.height = `${contentHeight}px`;
+          codeEditor.layout({
+            width: container.clientWidth,
+            height: contentHeight
+          });
+        };
+
+        codeEditor.onDidContentSizeChange(updateEditorHeight);
+        codeEditor.onDidChangeModelContent(() => {
+          const element = document.querySelector(".selected-element-tag") as HTMLElement;
+
+          if (element) {
+            element.textContent = codeEditor.getValue() || "";
+            element.style.height = `${codeEditor.getContentHeight()}px`;
+          }
+        });
+        codeEditor.onDidBlurEditorText(async () => {
+          const element = document.querySelector(".selected-element-tag") as HTMLElement;
+
+          if (element) {
+            element.textContent = await processCode(editorCode());
+          }
+
+          await onSave(codeEditor.getValue());
+        });
+        codeEditor.onKeyDown((event) => {
+          if (event.code === "Escape") {
+            props.state.editor.commands.focus();
+            event.preventDefault();
+            event.stopPropagation();
+          }
+        });
+        codeEditor.setModel(
+          monaco.editor.createModel(
+            editorCode(),
+            "javascript",
+            monaco.Uri.parse(`file:///${nanoid()}`)
+          )
+        );
+        createEffect(() => {
+          monaco.editor.setTheme(codeEditorTheme());
+        });
+        createEffect(
+          on(
+            () => props.state.active,
+            (active, _, prevElement) => {
+              const element: HTMLElement | null =
+                (prevElement as HTMLElement) ||
+                (document.querySelector(".selected-element-tag") as HTMLElement);
+
+              if (element) {
+                setTimeout(() => {
+                  if (active) {
+                    element.style.height = `${codeEditor.getContentHeight()}px`;
+
+                    return element;
+                  } else {
+                    element.style.height = "unset";
+
+                    return null;
+                  }
+                }, 0);
+              }
+
+              return element || null;
+            }
+          )
+        );
+        createEffect(
+          on(editorCode, async (code) => {
+            if (code === "<>") return codeEditor.setValue("");
+
+            const selection = codeEditor.getSelection();
+            const formattedCode = await processCode(code);
+
+            codeEditor.setValue(formattedCode);
+            if (selection) codeEditor.setSelection(selection);
+          })
+        );
+        createEffect(
+          on(type, (type, _previousType, handle) => {
+            if (typeof handle === "number") clearTimeout(handle);
+
+            if (type) {
+              return window.setTimeout(() => {
+                setVisible(true);
+
+                const { position } =
+                  codeEditor?.getTargetAtClientPoint(coords().x, coords().y) || {};
+
+                if (position) {
+                  codeEditor?.setSelection(monaco.Range.fromPositions(position, position));
+                }
+
+                scrollIntoView(editorContainer, { behavior: "smooth", block: "nearest" });
+                codeEditor?.focus();
+              }, 100);
+            }
+          })
+        );
+        onCleanup(() => {
+          codeEditor.getModel()?.dispose();
+          codeEditor.dispose();
+        });
+      });
+      createRenderEffect(
+        on(type, (type, previousType) => {
+          if (type !== previousType) setVisible(false);
+        })
+      );
+      window.addEventListener("pointerdown", saveLastCoords);
+      onCleanup(() => {
+        window.removeEventListener("pointerdown", saveLastCoords);
+      });
+
+      return (
+        <div
+          class={clsx(
+            "w-full flex items-center justify-start",
+            !visible() && "opacity-0 transition-opacity duration-200"
+          )}
+          contentEditable={false}
+        >
+          <div class="relative w-full">
+            <div
+              ref={setEditorContainerRef}
+              class="w-full not-prose customized-editor customized-editor-contrast customized-editor-show-keyboard-hidden"
+            ></div>
+          </div>
+        </div>
+      );
+    }
+  };
+});
+
+export { ElementMenuEditor };
diff --git a/apps/web/src/lib/editor/extensions/element-menu/index.ts b/apps/web/src/lib/editor/extensions/element-menu/index.ts
new file mode 100644
index 0000000..39b9a61
--- /dev/null
+++ b/apps/web/src/lib/editor/extensions/element-menu/index.ts
@@ -0,0 +1 @@
+export * from "./plugin";
diff --git a/apps/web/src/lib/editor/extensions/element-menu/plugin.tsx b/apps/web/src/lib/editor/extensions/element-menu/plugin.tsx
new file mode 100644
index 0000000..b88a9c6
--- /dev/null
+++ b/apps/web/src/lib/editor/extensions/element-menu/plugin.tsx
@@ -0,0 +1,105 @@
+import { ElementMenu } from "./component";
+import { Extension } from "@tiptap/core";
+import { SolidEditor, SolidRenderer } from "@vrite/tiptap-solid";
+import { CellSelection } from "@tiptap/pm/tables";
+import { createNanoEvents } from "nanoevents";
+import { NodeSelection } from "@tiptap/pm/state";
+import { Node as PMNode } from "@tiptap/pm/model";
+
+const emitter = createNanoEvents();
+const generalMenuContainer = document.createElement("div");
+
+let generalMenu: SolidRenderer<{
+  editor: SolidEditor;
+  pos: number;
+  node: PMNode | null;
+  container: HTMLElement | null;
+  active: boolean;
+}> | null = null;
+
+const handleUpdate = (editor: SolidEditor): void => {
+  const { selection } = editor.state;
+  const selectedNode = selection.$from.nodeAfter;
+  const isNodeSelection = selection instanceof NodeSelection;
+
+  if (!isNodeSelection || !selectedNode || selectedNode.type.name !== "element") {
+    generalMenuContainer.style.display = "none";
+    generalMenu?.setState((state) => ({ ...state, active: false }));
+
+    return;
+  }
+
+  const { view } = editor;
+  const node = view.nodeDOM(selection.$from.pos);
+
+  if (!node) return;
+
+  const blockParent = node as HTMLElement;
+  const parentPos = document.getElementById("pm-container")?.getBoundingClientRect();
+  const childPos = blockParent?.getBoundingClientRect();
+
+  if (!parentPos || !childPos) return;
+
+  const relativePos = {
+    top: childPos.top - parentPos.top,
+    right: childPos.right - parentPos.right,
+    bottom: childPos.bottom - parentPos.bottom,
+    left: childPos.left - parentPos.left
+  };
+
+  Object.assign(generalMenuContainer.style, {
+    width: `${Math.min(childPos?.width || parentPos.width, parentPos.width)}px`,
+    top: `${relativePos.top}px`,
+    left: `${relativePos.left}px`,
+    position: "absolute",
+    display: "block"
+  });
+  generalMenu?.setState(() => ({
+    pos: selection.$from.pos,
+    node: selectedNode,
+    container: blockParent,
+    editor,
+    active: true
+  }));
+};
+const ElementMenuPlugin = Extension.create({
+  name: "elementMenu",
+  onCreate() {
+    generalMenu = new SolidRenderer(ElementMenu, {
+      editor: this.editor as SolidEditor,
+      state: {
+        pos: 0,
+        node: null as PMNode | null,
+        container: null as HTMLElement | null,
+        editor: this.editor as SolidEditor,
+        active: false as boolean
+      }
+    });
+    generalMenuContainer.appendChild(generalMenu.element);
+    document.getElementById("pm-container")?.appendChild(generalMenuContainer);
+  },
+  onBlur() {
+    const menuActive = document.activeElement?.contains(generalMenuContainer);
+
+    if (!menuActive) {
+      generalMenuContainer.style.display = "none";
+      generalMenu?.setState((state) => ({ ...state, active: false }));
+    }
+  },
+  onFocus() {
+    const isCellSelection = this.editor.state.selection instanceof CellSelection;
+
+    if (this.editor.isActive("element") && !isCellSelection) {
+      generalMenuContainer.style.display = "block";
+      generalMenu?.setState((state) => ({ ...state, active: true }));
+    }
+  },
+  onUpdate() {
+    handleUpdate(this.editor as SolidEditor);
+  },
+  onSelectionUpdate() {
+    handleUpdate(this.editor as SolidEditor);
+  }
+});
+
+export { ElementMenuPlugin, emitter };
diff --git a/apps/web/src/lib/editor/extensions/wrapper/index.ts b/apps/web/src/lib/editor/extensions/element/index.ts
similarity index 100%
rename from apps/web/src/lib/editor/extensions/wrapper/index.ts
rename to apps/web/src/lib/editor/extensions/element/index.ts
diff --git a/apps/web/src/lib/editor/extensions/element/node.tsx b/apps/web/src/lib/editor/extensions/element/node.tsx
new file mode 100644
index 0000000..feffb76
--- /dev/null
+++ b/apps/web/src/lib/editor/extensions/element/node.tsx
@@ -0,0 +1,181 @@
+import { Element as BaseElement, ElementAttributes } from "@vrite/editor";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { NodeView } from "@tiptap/core";
+import { keymap } from "@tiptap/pm/keymap";
+import { Node } from "@tiptap/pm/model";
+import { EditorState } from "@tiptap/pm/state";
+import { Node as PMNode } from "@tiptap/pm/model";
+import { formatCode } from "#lib/code-editor";
+
+const getOpeningTag = async (node: PMNode): Promise<string> => {
+  const keyValueProps = Object.entries(node.attrs.props).map(([key, value]) => {
+    if (value === true) return key;
+
+    const useBrackets = typeof value !== "string" || value.includes("\n") || value.includes(`"`);
+
+    return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${useBrackets ? "}" : ""}`;
+  });
+  const c = `<${node.attrs.type}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`;
+  const codeTagClosed = c.trim().replace(/>$/, "/>") || "";
+  const formattedCode = await formatCode(codeTagClosed, "typescript", {
+    printWidth: 60,
+    trailingComma: "none",
+    singleQuote: false
+  });
+
+  return formattedCode.replace(/ *?\/>;/gm, node.content.size ? ">" : "/>").trim();
+};
+const getClosingTag = (node: PMNode): string => node.attrs.type;
+const Element = BaseElement.extend({
+  addProseMirrorPlugins() {
+    const handleDeleteElement = (state: EditorState): boolean => {
+      if (this.editor.isActive("element")) {
+        const currentDepth = state.selection.$from.depth;
+
+        let node: Node | null = null;
+        let pos: number | null = null;
+
+        for (let i = currentDepth; i >= 0; i--) {
+          const currentNode = state.selection.$from.node(i);
+
+          if (currentNode.type.name === "element") {
+            node = currentNode;
+            pos = i > 0 ? state.selection.$from.before(i) : 0;
+            break;
+          }
+        }
+
+        if (
+          node &&
+          !node.textContent &&
+          node.content.childCount === 1 &&
+          node.content.firstChild?.type.name === "paragraph" &&
+          typeof pos === "number"
+        ) {
+          this.editor
+            .chain()
+            .deleteRange({
+              from: pos,
+              to: pos + node.nodeSize
+            })
+            .focus()
+            .run();
+
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    return [
+      keymap({
+        Delete: handleDeleteElement,
+        Backspace: handleDeleteElement
+      })
+    ];
+  },
+  addNodeView() {
+    return (props) => {
+      let node = props.node as Node;
+
+      const editor = this.editor as SolidEditor;
+      const referenceView = new NodeView(() => {}, props);
+      const dom = document.createElement("div");
+      const contentContainer = document.createElement("div");
+      const content = document.createElement("div");
+      const code = document.createElement("code");
+      const bottomCode = document.createElement("code");
+      const bottomCodeStart = document.createElement("span");
+      const bottomCodeKey = document.createElement("span");
+      const bottomCodeEnd = document.createElement("span");
+      const handleCodeClick = (event: MouseEvent): void => {
+        if (typeof props.getPos === "function") {
+          editor.commands.setTextSelection(props.getPos());
+          editor.commands.setNodeSelection(props.getPos());
+        }
+
+        event.preventDefault();
+        event.stopPropagation();
+      };
+
+      getOpeningTag(props.node).then((openingTag) => (code.textContent = openingTag));
+      bottomCodeKey.textContent = getClosingTag(node);
+      contentContainer.setAttribute(
+        "class",
+        "px-3 w-full border-gray-300 dark:border-gray-700 border-l-2 ml-1 py-0 content"
+      );
+      dom.setAttribute("class", "flex flex-col justify-center items-center relative");
+      dom.setAttribute("data-element", "true");
+      content.setAttribute("class", "relative content");
+      contentContainer.append(content);
+      dom.append(code, contentContainer, bottomCode);
+      code.setAttribute(
+        "class",
+        "!whitespace-pre-wrap leading-[26px] min-h-6.5 block w-full !p-0 !bg-transparent !rounded-0 !text-gray-400 !dark:text-gray-400 cursor-pointer"
+      );
+      bottomCode.setAttribute(
+        "class",
+        "block w-full !p-0 leading-[26px] min-h-6.5 !rounded-0 !bg-transparent !text-gray-400 !dark:text-gray-400 cursor-pointer"
+      );
+      code.contentEditable = "false";
+      bottomCode.contentEditable = "false";
+      bottomCode.append(bottomCodeStart, bottomCodeKey, bottomCodeEnd);
+      bottomCodeStart.textContent = "</";
+      bottomCodeEnd.textContent = ">";
+      code.addEventListener("click", handleCodeClick);
+      bottomCode.addEventListener("click", handleCodeClick);
+
+      if (!node.content.size) {
+        bottomCode.classList.add("!hidden");
+      }
+
+      return {
+        dom,
+        contentDOM: content,
+        ignoreMutation(mutation: MutationRecord | { type: "selection"; target: Element }) {
+          if (mutation.type === "selection") {
+            return true;
+          }
+
+          return referenceView.ignoreMutation(mutation);
+        },
+        selectNode() {
+          contentContainer.classList.add("!border-primary");
+          code.classList.add("selected-element-tag");
+          bottomCode.classList.remove("!text-gray-400", "!dark:text-gray-400");
+          bottomCode.classList.add("!text-[#000000]", "!dark:text-[#DCDCDC]");
+          bottomCodeKey.classList.add("!text-[#008080]", "!dark:text-[#3dc9b0]");
+        },
+        deselectNode() {
+          contentContainer.classList.remove("!border-primary");
+          code.classList.remove("selected-element-tag");
+          bottomCode.classList.add("!text-gray-400", "!dark:text-gray-400");
+          bottomCode.classList.remove("!text-[#000000]", "!dark:text-[#DCDCDC]");
+          bottomCodeKey.classList.remove("!text-[#008080]", "!dark:text-[#3dc9b0]");
+        },
+        stopEvent(event) {
+          return referenceView.stopEvent(event);
+        },
+        update(newNode) {
+          if (newNode.type.name !== "element") return false;
+
+          node = newNode as Node;
+          getOpeningTag(node).then((openingTag) => (code.textContent = openingTag));
+          bottomCodeKey.textContent = getClosingTag(node);
+
+          if (node.content.size) {
+            bottomCode.classList.remove("!hidden");
+          } else {
+            bottomCode.classList.add("!hidden");
+          }
+
+          return true;
+        }
+      };
+    };
+  }
+});
+
+export { Element };
+export type { ElementAttributes };
diff --git a/apps/web/src/lib/editor/extensions/embed/menu.tsx b/apps/web/src/lib/editor/extensions/embed/menu.tsx
index 49c2f4c..7f3491f 100644
--- a/apps/web/src/lib/editor/extensions/embed/menu.tsx
+++ b/apps/web/src/lib/editor/extensions/embed/menu.tsx
@@ -1,11 +1,10 @@
 import { EmbedAttributes } from "./node";
 import { SolidNodeViewProps, Attrs } from "@vrite/tiptap-solid";
-import { Component } from "solid-js";
-import { mdiDotsGrid } from "@mdi/js";
-import { IconButton, Input, Tooltip } from "#components/primitives";
-import { EmbedType, getEmbedId, getEmbedSrc } from "#lib/utils";
+import { Component, createEffect, createSignal, on } from "solid-js";
+import { Card, Input } from "#components/primitives";
+import { EmbedType, createRef, getEmbedId, getEmbedSrc } from "#lib/utils";
 
 interface ImageMenuProps {
   state: SolidNodeViewProps<Attrs>;
 }
 
@@ -20,30 +19,54 @@ const getInputPlaceholder = (embedType?: EmbedType): string => {
     default:
       return "Embed URL";
   }
 };
 const EmbedMenu: Component<ImageMenuProps> = (props) => {
+  const [menuRef, setMenuRef] = createRef<HTMLElement | null>(null);
+  const [left, setLeft] = createSignal(0);
   const attrs = (): EmbedAttributes => props.state.node.attrs;
   const getSrc = (input: string): string => {
     return getEmbedSrc(
       getEmbedId(input, (attrs().embed as EmbedType) || "codepen"),
       (attrs().embed as EmbedType) || "codepen"
     );
   };
 
+  createEffect(
+    on(
+      () => props.state.selected,
+      () => {
+        const element = menuRef();
+
+        if (!element || !element.parentElement) return;
+
+        const { left, width } = element.parentElement.getBoundingClientRect();
+        const right = window.innerWidth - left - width;
+
+        setLeft(-Math.abs((right - left) / 2));
+      }
+    )
+  );
+
   return (
-    <div class="flex p-0 transition-shadow duration-200 border-0 rounded-xl">
-      <Input
-        wrapperClass="flex-1 max-w-full"
-        color="contrast"
-        placeholder={getInputPlaceholder(attrs().embed as EmbedType)}
-        value={attrs().input || ""}
-        disabled={!props.state.editor.isEditable}
-        setValue={(value) => {
-          props.state.updateAttributes({ input: value, src: getSrc(value) });
-        }}
-      />
+    <div
+      class="pointer-events-auto flex bg-gray-50 dark:bg-gray-900 !md:bg-transparent border-gray-200 dark:border-gray-700 border-y-2 md:border-0 backdrop-blur-sm md:gap-2 w-screen md:w-auto !md:left-unset relative md:rounded-2xl"
+      style={{ left: `${left()}px` }}
+      ref={setMenuRef}
+    >
+      <Card class="flex m-0 border-0 md:border-2 p-1">
+        <Input
+          wrapperClass="max-w-full min-w-unset md:w-96 flex-1"
+          class="w-full bg-transparent m-0 flex-1 text-lg"
+          placeholder={getInputPlaceholder(attrs().embed as EmbedType)}
+          value={attrs().input || ""}
+          disabled={!props.state.editor.isEditable}
+          setValue={(value) => {
+            props.state.updateAttributes({ input: value, src: getSrc(value) });
+          }}
+        />
+      </Card>
     </div>
   );
 };
 
 export { EmbedMenu };
diff --git a/apps/web/src/lib/editor/extensions/embed/view.tsx b/apps/web/src/lib/editor/extensions/embed/view.tsx
index 9ecc858..81ca390 100644
--- a/apps/web/src/lib/editor/extensions/embed/view.tsx
+++ b/apps/web/src/lib/editor/extensions/embed/view.tsx
@@ -2,11 +2,11 @@ import { EmbedAttributes } from "./node";
 import { EmbedMenu } from "./menu";
 import { NodeViewWrapper, useSolidNodeView } from "@vrite/tiptap-solid";
 import { Component, createSignal, Show } from "solid-js";
 import clsx from "clsx";
 import { mdiCodepen, mdiYoutube } from "@mdi/js";
-import { Card, Icon } from "#components/primitives";
+import { Icon } from "#components/primitives";
 import { codeSandboxIcon } from "#assets/icons";
 import { EmbedType } from "#lib/utils";
 
 const getPlaceholderIcon = (embedType?: EmbedType): string => {
   switch (embedType) {
@@ -29,18 +29,18 @@ const EmbedView: Component = () => {
   const attrs = (): EmbedAttributes => {
     return state().node.attrs;
   };
 
   return (
-    <NodeViewWrapper class="my-5">
+    <NodeViewWrapper>
       <div class={clsx("relative rounded-2xl", selected() && "ring ring-primary ring-2")}>
         <Show
           when={attrs().src}
           fallback={
             <div
               class={clsx(
-                "pt-[35%] w-full rounded-t-2xl bg-gradient-to-tr flex justify-center items-center relative"
+                "pt-[35%] w-full rounded-2xl bg-gradient-to-tr flex justify-center items-center relative border-2 border-gray-300 dark:border-gray-700"
               )}
             >
               <div class="absolute flex flex-col items-center justify-center font-bold text-white transform -translate-y-1/2 top-1/2">
                 <Icon
                   path={getPlaceholderIcon(state().node.attrs.embed as EmbedType)}
@@ -53,17 +53,22 @@ const EmbedView: Component = () => {
             </div>
           }
         >
           <iframe
             src={attrs().src || ""}
-            class="object-contain w-full m-0 transition-opacity duration-300 border-2 border-gray-200 dark:border-gray-700 aspect-video min-h-96 rounded-t-2xl"
+            class="object-contain w-full m-0 transition-opacity duration-300 border-2 border-gray-300 dark:border-gray-700 aspect-video min-h-96 rounded-2xl"
           />
         </Show>
-
-        <Card class="m-0 border-t-0 rounded-t-none">
+        <div
+          class={clsx(
+            "absolute w-full justify-center items-center -bottom-14 z-1 pointer-events-none",
+            selected() ? "grid" : "hidden"
+          )}
+        >
           <EmbedMenu state={state()} />
-        </Card>
+        </div>
+        <div data-type="draggable-item" />
       </div>
     </NodeViewWrapper>
   );
 };
 
diff --git a/apps/web/src/lib/editor/extensions/image/menu.tsx b/apps/web/src/lib/editor/extensions/image/menu.tsx
index f2bacf1..2c4c62a 100644
--- a/apps/web/src/lib/editor/extensions/image/menu.tsx
+++ b/apps/web/src/lib/editor/extensions/image/menu.tsx
@@ -1,89 +1,122 @@
 import { ImageAttributes, ImageOptions } from "./node";
 import { SolidNodeViewProps } from "@vrite/tiptap-solid";
 import { mdiLinkVariant, mdiText, mdiUpload } from "@mdi/js";
-import { Component, createSignal, Show } from "solid-js";
+import { Component, createEffect, createSignal, on, onMount } from "solid-js";
 import { nanoid } from "nanoid";
 import { debounce } from "@solid-primitives/scheduled";
-import { uploadFile as uploadFileUtil } from "#lib/utils";
-import { Button, IconButton, Input, Loader, Tooltip } from "#components/primitives";
+import clsx from "clsx";
+import { createRef, uploadFile as uploadFileUtil } from "#lib/utils";
+import { Card, IconButton, Input, Tooltip } from "#components/primitives";
 
 interface ImageMenuProps {
   state: SolidNodeViewProps<ImageAttributes>;
 }
 
 const ImageMenu: Component<ImageMenuProps> = (props) => {
   const { storage } = props.state.extension;
+  const [menuRef, setMenuRef] = createRef<HTMLElement | null>(null);
   const [inputMode, setInputMode] = createSignal<"alt" | "src">("src");
   const [uploading, setUploading] = createSignal(false);
+  const [left, setLeft] = createSignal(0);
   const attrs = (): ImageAttributes => props.state.node.attrs;
   const options = (): ImageOptions => props.state.extension.options;
+  const placeholder = (): string => {
+    if (inputMode() === "src") {
+      return options().cover ? "Cover image URL" : "Image URL";
+    }
+
+    return options().cover ? "Cover alt description" : "Alt description";
+  };
   const updateAttribute = debounce((attribute: "src" | "alt", value: string) => {
     return props.state.updateAttributes({ [attribute]: value });
   }, 200);
-  const inputId = nanoid();
   const uploadFile = async (file?: File | null): Promise<void> => {
     if (file && file.type.includes("image")) {
       setUploading(true);
 
       const uploadedUrl = await uploadFileUtil(file);
 
-      if (uploadedUrl) {
-        props.state.updateAttributes({ src: uploadedUrl });
-      }
+      if (uploadedUrl) props.state.updateAttributes({ src: uploadedUrl });
 
       setUploading(false);
     }
   };
-  const getPlaceholder = (): string => {
-    if (inputMode() === "src") {
-      return options().cover ? "Cover image URL" : "Image URL";
-    }
-
-    return options().cover ? "Cover alt description" : "Alt description";
-  };
+  const inputId = nanoid();
 
   if (storage.droppedFile()) {
     uploadFile(storage.droppedFile());
     storage.setDroppedFile(null);
   }
 
+  createEffect(
+    on(
+      () => props.state.selected,
+      () => {
+        const element = menuRef();
+
+        if (!element || !element.parentElement) return;
+
+        const { left, width } = element.parentElement.getBoundingClientRect();
+        const right = window.innerWidth - left - width;
+
+        setLeft(-Math.abs((right - left) / 2));
+      }
+    )
+  );
+
   return (
-    <div class="flex p-0 transition-shadow duration-200 border-0 rounded-xl">
-      <Tooltip text="Alt">
-        <IconButton
-          path={mdiText}
-          color={inputMode() === "alt" ? "primary" : "contrast"}
-          text={inputMode() === "alt" ? "primary" : "soft"}
-          onClick={() => {
-            setInputMode("alt");
+    <div
+      class={clsx(
+        "pointer-events-auto flex bg-gray-50 dark:bg-gray-900 border-gray-200 dark:border-gray-700 border-y-2 backdrop-blur-sm relative !md:left-unset",
+        options().cover && "w-full border-t-0",
+        !options().cover &&
+          "md:gap-2 w-screen md:w-auto md:border-0 md:rounded-2xl !md:bg-transparent"
+      )}
+      style={{ left: `${left()}px` }}
+      ref={setMenuRef}
+    >
+      <Card class={clsx("flex py-0 m-0 border-0  px-1 gap-1", !options().cover && "md:border-2")}>
+        <Tooltip text="Alt">
+          <IconButton
+            path={mdiText}
+            color={inputMode() === "alt" ? "primary" : "contrast"}
+            text={inputMode() === "alt" ? "primary" : "soft"}
+            variant={inputMode() === "alt" ? "solid" : "text"}
+            class="m-0"
+            onClick={() => {
+              setInputMode("alt");
+            }}
+          ></IconButton>
+        </Tooltip>
+        <Tooltip text="Image URL">
+          <IconButton
+            path={mdiLinkVariant}
+            color={inputMode() === "src" ? "primary" : "contrast"}
+            text={inputMode() === "src" ? "primary" : "soft"}
+            variant={inputMode() === "src" ? "solid" : "text"}
+            class="m-0"
+            onClick={() => {
+              setInputMode("src");
+            }}
+          ></IconButton>
+        </Tooltip>
+      </Card>
+      <Card class={clsx("p-1 m-0 border-0 flex-1", !options().cover && "md:border-2")}>
+        <Input
+          wrapperClass={clsx("max-w-full min-w-unset flex-1", !options().cover && "md:w-96 ")}
+          class="w-full bg-transparent m-0 flex-1 text-lg"
+          placeholder={placeholder()}
+          value={attrs()[inputMode()] || ""}
+          disabled={!props.state.editor.isEditable}
+          setValue={(value) => {
+            updateAttribute.clear();
+            updateAttribute(inputMode(), value);
           }}
-        ></IconButton>
-      </Tooltip>
-      <Tooltip text="Image URL">
-        <IconButton
-          path={mdiLinkVariant}
-          color={inputMode() === "src" ? "primary" : "contrast"}
-          text={inputMode() === "src" ? "primary" : "soft"}
-          onClick={() => {
-            setInputMode("src");
-          }}
-        ></IconButton>
-      </Tooltip>
-      <Input
-        color="contrast"
-        wrapperClass="flex-1 max-w-full min-w-unset"
-        class="w-full"
-        placeholder={getPlaceholder()}
-        value={attrs()[inputMode()] || ""}
-        disabled={!props.state.editor.isEditable}
-        setValue={(value) => {
-          updateAttribute.clear();
-          updateAttribute(inputMode(), value);
-        }}
-      />
-      <Show when={props.state.editor.isEditable}>
+        />
+      </Card>
+      <Card class={clsx("p-1 m-0 border-0", !options().cover && "md:border-2")}>
         <input
           type="file"
           hidden
           disabled={uploading()}
           id={inputId}
@@ -93,24 +126,23 @@ const ImageMenu: Component<ImageMenuProps> = (props) => {
             uploadFile(event.currentTarget.files?.item(0));
             event.currentTarget.value = "";
           }}
         />
         <label for={inputId} class="flex items-center justify-center">
-          <Tooltip text={uploading() ? "Uploading" : "Upload image"}>
-            <Show
-              when={!uploading()}
-              fallback={
-                <Button badge color="contrast" class="flex items-center justify-center w-8 h-8">
-                  <Loader class="w-6 h-6" />
-                </Button>
-              }
-            >
-              <IconButton path={mdiUpload} color="contrast" text="soft" badge></IconButton>
-            </Show>
+          <Tooltip text={uploading() ? "Uploading" : "Upload image"} class="mt-1">
+            <IconButton
+              loading={uploading()}
+              path={mdiUpload}
+              color="contrast"
+              class="m-0"
+              text="soft"
+              badge
+              variant="text"
+            ></IconButton>
           </Tooltip>
         </label>
-      </Show>
+      </Card>
     </div>
   );
 };
 
 export { ImageMenu };
diff --git a/apps/web/src/lib/editor/extensions/image/view.tsx b/apps/web/src/lib/editor/extensions/image/view.tsx
index ecae7b0..46a5061 100644
--- a/apps/web/src/lib/editor/extensions/image/view.tsx
+++ b/apps/web/src/lib/editor/extensions/image/view.tsx
@@ -4,18 +4,18 @@ import { NodeViewWrapper, useSolidNodeView } from "@vrite/tiptap-solid";
 import { Component, createEffect, createSignal, Show, on, onCleanup } from "solid-js";
 import clsx from "clsx";
 import { mdiAlertCircle, mdiImage } from "@mdi/js";
 import { debounce } from "@solid-primitives/scheduled";
 import { createRef, validateURL } from "#lib/utils";
-import { Card, Icon, Loader } from "#components/primitives";
+import { Icon, Loader } from "#components/primitives";
 
 const ImageView: Component = () => {
   const { state } = useSolidNodeView<ImageAttributes>();
   const [error, setError] = createSignal(false);
   const [loading, setLoading] = createSignal(false);
   const [objectURL, setObjectURL] = createSignal("");
-  const [currentSrc, setCurrentSrc] = createRef("");
+  const [currentSrc, setCurrentSrc] = createSignal("");
   const [imageContainerRef, setImageContainerRef] = createRef<HTMLElement | null>(null);
   const updateWidth = debounce((width: string) => state().updateAttributes({ width }), 250);
   const updateAspectRatio = debounce(
     (aspectRatio: string) => state().updateAttributes({ aspectRatio }),
     250
@@ -36,11 +36,11 @@ const ImageView: Component = () => {
     if (newWidth !== attrs().width && state().editor.isEditable) {
       updateWidth(newWidth);
     }
   });
   const removeImage = (): void => {
-    if (objectURL()) {
+    if (currentSrc()) {
       URL.revokeObjectURL(objectURL());
       setCurrentSrc("");
       setObjectURL("");
     }
   };
@@ -54,46 +54,25 @@ const ImageView: Component = () => {
       return;
     }
 
     removeImage();
 
-    try {
-      if (!src) {
-        setError(false);
-        setLoading(false);
-
-        return;
-      }
-
-      if (!validateURL(src)) {
-        setError(true);
-        setLoading(false);
-
-        return;
-      }
-
-      const response = await fetch(
-        src.startsWith(window.env.PUBLIC_ASSETS_URL) ? src : `/proxy?url=${encodeURIComponent(src)}`
-      );
-
-      if (!response.ok) {
-        setError(true);
-        setLoading(false);
-
-        return;
-      }
+    if (!src) {
+      setError(false);
+      setLoading(false);
 
-      const blob = await response.blob();
-      const objectURL = URL.createObjectURL(blob);
+      return;
+    }
 
-      setCurrentSrc(src);
-      setObjectURL(objectURL);
-    } catch (error) {
+    if (!validateURL(src)) {
       setError(true);
-    } finally {
       setLoading(false);
+
+      return;
     }
+
+    setCurrentSrc(src);
   }, 350);
   const handleNewImageContainer = (element: HTMLElement): void => {
     const imageContainer = imageContainerRef();
 
     if (imageContainer) {
@@ -131,98 +110,102 @@ const ImageView: Component = () => {
       }
     )
   );
 
   return (
-    <NodeViewWrapper class={clsx(!options().cover && "my-5")}>
+    <NodeViewWrapper>
       <div
         class={clsx(
           "relative rounded-2xl",
           !options().cover && selected() && "ring ring-primary ring-2"
         )}
       >
         <div
           class={clsx(
             "border-gray-200 dark:border-gray-700",
-            options().cover ? "border-b-2" : "border-2 rounded-t-2xl"
+            options().cover ? "border-b-2" : "border-2 rounded-2xl"
           )}
         >
-          <Show
-            when={objectURL()}
-            fallback={
-              <div
-                class={clsx(
-                  "w-full bg-gradient-to-tr flex justify-center items-center relative",
-                  options().cover ? "min-h-48" : "rounded-t-2xl"
-                )}
-                style={{
-                  "padding-top": getPaddingTop()
-                }}
-              >
-                <div class="absolute flex flex-col items-center justify-center font-bold text-white transform -translate-y-1/2 top-1/2">
-                  <Show when={!loading()} fallback={<Loader class="w-8 h-8" />}>
-                    <Show
-                      when={!error()}
-                      fallback={
-                        <>
-                          <Icon path={mdiAlertCircle} class="w-16 h-16" />
-                          <span class="absolute top-full">Error</span>
-                        </>
-                      }
-                    >
-                      <Icon path={mdiImage} class="w-16 h-16" />
-                    </Show>
-                  </Show>
-                </div>
-              </div>
-            }
+          <div
+            class={clsx(
+              "w-full border-gray-200 dark:border-gray-700 flex justify-center items-center overflow-hidden bg-gray-100 dark:bg-gray-800 relative",
+              !error() && !loading() && currentSrc() ? "" : "opacity-0 !absolute",
+              !options().cover && "rounded-2xl"
+            )}
           >
             <div
               class={clsx(
-                "w-full border-gray-200 dark:border-gray-700 flex justify-center items-center overflow-hidden bg-gray-100 dark:bg-gray-800 relative",
-                !options().cover && "rounded-t-2xl"
+                "overflow-hidden min-w-40 !h-full",
+                state().editor.isEditable && "resize"
+              )}
+              ref={handleNewImageContainer}
+              style={{ width: attrs().width }}
+            >
+              <img
+                alt={attrs().alt}
+                src={currentSrc()}
+                class={clsx("object-contain w-full m-0 transition-opacity duration-300")}
+                onLoad={(event) => {
+                  setError(false);
+                  setLoading(false);
+
+                  const image = event.currentTarget;
+                  const w = image.naturalWidth;
+                  const h = image.naturalHeight;
+                  const aspectRatio = w / h;
+
+                  updateAspectRatio.clear();
+                  updateAspectRatio(`${aspectRatio}`);
+                }}
+                onError={() => {
+                  if (!currentSrc()) return;
+
+                  setLoading(false);
+                  removeImage();
+                  setError(true);
+                }}
+              />
+            </div>
+          </div>
+          <Show when={loading() || !currentSrc()}>
+            <div
+              class={clsx(
+                "w-full bg-gradient-to-tr flex justify-center items-center relative",
+                options().cover ? "min-h-48" : "rounded-2xl"
               )}
+              style={{
+                "padding-top": getPaddingTop()
+              }}
             >
-              <div
-                class={clsx(
-                  "overflow-hidden min-w-40 !h-full",
-                  state().editor.isEditable && "resize"
-                )}
-                ref={handleNewImageContainer}
-                style={{ width: attrs().width }}
-              >
-                <img
-                  alt={attrs().alt}
-                  src={objectURL()}
-                  data-src={currentSrc()}
-                  class={clsx("object-contain w-full m-0 transition-opacity duration-300")}
-                  onLoad={(event) => {
-                    const image = event.currentTarget;
-                    const w = image.naturalWidth;
-                    const h = image.naturalHeight;
-                    const aspectRatio = w / h;
-
-                    updateAspectRatio.clear();
-                    updateAspectRatio(`${aspectRatio}`);
-                  }}
-                  onError={() => {
-                    removeImage();
-                    setError(true);
-                  }}
-                />
+              <div class="absolute flex flex-col items-center justify-center font-bold text-white transform -translate-y-1/2 top-1/2">
+                <Show when={!loading()} fallback={<Loader class="w-8 h-8" />}>
+                  <Show
+                    when={!error()}
+                    fallback={
+                      <>
+                        <Icon path={mdiAlertCircle} class="w-16 h-16" />
+                        <span class="absolute top-full">Error</span>
+                      </>
+                    }
+                  >
+                    <Icon path={mdiImage} class="w-16 h-16" />
+                  </Show>
+                </Show>
               </div>
             </div>
           </Show>
         </div>
-        <Card
+        <div
           class={clsx(
-            "m-0 border-0 border-b-2 rounded-t-none",
-            options().cover ? "rounded-none" : "border-x-2"
+            "w-full justify-center items-center z-1 pointer-events-none",
+            selected() ? "grid" : "hidden",
+            options().cover ? "!flex relative" : "absolute -bottom-14"
           )}
         >
           <ImageMenu state={state()} />
-        </Card>
+        </div>
+        <div data-type="draggable-item" />
       </div>
     </NodeViewWrapper>
   );
 };
 
diff --git a/apps/web/src/lib/editor/extensions/index.ts b/apps/web/src/lib/editor/extensions/index.ts
index f336025..2e718c8 100644
--- a/apps/web/src/lib/editor/extensions/index.ts
+++ b/apps/web/src/lib/editor/extensions/index.ts
@@ -10,7 +10,8 @@ export * from "./placeholder";
 export * from "./trailing-node";
 export * from "./block-action-menu";
 export * from "./comment-menu";
 export * from "./block-paste";
 export * from "./table-menu";
-export * from "./wrapper";
+export * from "./element";
 export * from "./auto-dir";
+export * from "./element-menu";
diff --git a/apps/web/src/lib/editor/extensions/slash-menu/component.tsx b/apps/web/src/lib/editor/extensions/slash-menu/component.tsx
index 2f8289b..78256aa 100644
--- a/apps/web/src/lib/editor/extensions/slash-menu/component.tsx
+++ b/apps/web/src/lib/editor/extensions/slash-menu/component.tsx
@@ -10,11 +10,11 @@ import { App } from "#context";
 
 interface SlashMenuItem {
   icon: string;
   label: string;
   group: string;
-  block?: App.WorkspaceSettings["blocks"][number] | "wrapper";
+  block?: App.WorkspaceSettings["blocks"][number];
   embed?: App.WorkspaceSettings["embeds"][number];
   ref: Ref<HTMLElement | null>;
   command(params: { editor: SolidEditor; range: Range }): void;
 }
 interface SlashMenuState extends SuggestionProps<SlashMenuItem> {
diff --git a/apps/web/src/lib/editor/extensions/wrapper/menu.tsx b/apps/web/src/lib/editor/extensions/wrapper/menu.tsx
deleted file mode 100644
index 77f4d21..0000000
--- a/apps/web/src/lib/editor/extensions/wrapper/menu.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-import { Component, createEffect, createSignal } from "solid-js";
-import { SearchableSelect } from "#components/fragments";
-import { App, useAuthenticatedUserData } from "#context";
-
-interface WrapperMenuProps {
-  state: {
-    key: string;
-    setKey(key: string): void;
-  };
-}
-
-const WrapperMenu: Component<WrapperMenuProps> = (props) => {
-  const { workspaceSettings } = useAuthenticatedUserData();
-  const selectedOption = (): App.Wrapper | null => {
-    return (
-      (workspaceSettings()?.wrappers || []).find((wrapper) => wrapper.key === props.state.key) ||
-      null
-    );
-  };
-
-  props.state.setKey(selectedOption()?.key || "");
-
-  return (
-    <div class="w-full flex items-center justify-start text-base" contentEditable={false}>
-      <div>
-        <SearchableSelect
-          extractId={(option) => option.key}
-          filterOption={(option, query) => option.label.toLowerCase().includes(query.toLowerCase())}
-          options={workspaceSettings()?.wrappers || []}
-          renderOption={(option) => <div class="text-start">{option.label}</div>}
-          selectOption={(option) => {
-            props.state.setKey(option?.key || "");
-          }}
-          selected={selectedOption()}
-          loading={false}
-          placeholder="Wrapper"
-          buttonProps={{
-            class: "bg-gray-100",
-            color: "base",
-            text: "soft"
-          }}
-        />
-      </div>
-    </div>
-  );
-};
-
-export { WrapperMenu };
diff --git a/apps/web/src/lib/editor/extensions/wrapper/node.tsx b/apps/web/src/lib/editor/extensions/wrapper/node.tsx
deleted file mode 100644
index 1ffec48..0000000
--- a/apps/web/src/lib/editor/extensions/wrapper/node.tsx
+++ /dev/null
@@ -1,133 +0,0 @@
-import { WrapperMenu } from "./menu";
-import { Wrapper as BaseWrapper, WrapperAttributes } from "@vrite/editor";
-import { SolidEditor, SolidRenderer } from "@vrite/tiptap-solid";
-import { NodeView } from "@tiptap/core";
-import { keymap } from "@tiptap/pm/keymap";
-import { Node } from "@tiptap/pm/model";
-import { EditorState } from "@tiptap/pm/state";
-
-const Wrapper = BaseWrapper.extend({
-  addProseMirrorPlugins() {
-    const handleDeleteWrapper = (state: EditorState): boolean => {
-      if (this.editor.isActive("wrapper")) {
-        const currentDepth = state.selection.$from.depth;
-
-        let node: Node | null = null;
-        let pos: number | null = null;
-
-        for (let i = currentDepth; i >= 0; i--) {
-          const currentNode = state.selection.$from.node(i);
-
-          if (currentNode.type.name === "wrapper") {
-            node = currentNode;
-            pos = i > 0 ? state.selection.$from.before(i) : 0;
-            break;
-          }
-        }
-
-        if (
-          node &&
-          !node.textContent &&
-          node.content.childCount === 1 &&
-          node.content.firstChild?.type.name === "paragraph" &&
-          typeof pos === "number"
-        ) {
-          this.editor
-            .chain()
-            .deleteRange({
-              from: pos,
-              to: pos + node.nodeSize
-            })
-            .focus()
-            .run();
-
-          return true;
-        }
-      }
-
-      return false;
-    };
-
-    return [
-      keymap({
-        Delete: handleDeleteWrapper,
-        Backspace: handleDeleteWrapper
-      })
-    ];
-  },
-  addNodeView() {
-    const editor = this.editor as SolidEditor;
-
-    return (props) => {
-      let node = props.node as Node;
-
-      const referenceView = new NodeView(() => {}, props);
-      const dom = document.createElement("div");
-      const content = document.createElement("div");
-      const menu = document.createElement("div");
-
-      dom.setAttribute(
-        "class",
-        "px-3 pt-3 my-5 rounded-3xl border-gray-300 bg-gray-300 bg-opacity-30 dark:border-gray-700 dark:bg-gray-700 dark:bg-opacity-40 border-2"
-      );
-      dom.setAttribute("data-wrapper", "true");
-      content.setAttribute("class", "relative content mb-3");
-      menu.setAttribute("class", "mb-5");
-      menu.contentEditable = "false";
-
-      const renderer = new SolidRenderer<{ key: string; setKey(value: string): void }>(
-        WrapperMenu,
-        {
-          editor: this.editor as SolidEditor,
-          state: {
-            key: node.attrs.key,
-            setKey: (key) => {
-              if (typeof props.getPos === "function") {
-                editor.view.dispatch(
-                  editor.view.state.tr.setNodeMarkup(props.getPos(), undefined, {
-                    key: key || null
-                  })
-                );
-              }
-            }
-          }
-        }
-      );
-
-      menu.append(renderer.element);
-      dom.append(menu, content);
-
-      return {
-        dom,
-        contentDOM: content,
-        ignoreMutation(mutation: MutationRecord | { type: "selection"; target: Element }) {
-          if (mutation.type === "selection") {
-            return false;
-          }
-
-          return referenceView.ignoreMutation(mutation);
-        },
-        stopEvent(event) {
-          return referenceView.stopEvent(event);
-        },
-        destroy() {
-          renderer.destroy();
-        },
-        update(newNode) {
-          if (newNode.type.name !== "wrapper") return false;
-
-          node = newNode as Node;
-          renderer.setState((state) => ({
-            ...state,
-            key: node.attrs.key
-          }));
-
-          return true;
-        }
-      };
-    };
-  }
-});
-
-export { Wrapper };
-export type { WrapperAttributes };
diff --git a/apps/web/src/lib/monaco.ts b/apps/web/src/lib/monaco.ts
index dc4bde9..f410391 100644
--- a/apps/web/src/lib/monaco.ts
+++ b/apps/web/src/lib/monaco.ts
@@ -12,33 +12,18 @@ declare global {
     MonacoEnvironment?: monaco.Environment;
   }
 }
 
 monaco.editor.defineTheme("dark", { ...darkTheme, base: "vs-dark" });
-monaco.editor.defineTheme("light", { ...lightTheme, base: "vs-dark" });
-monaco.editor.defineTheme("dark-contrast", {
-  ...darkTheme,
-  colors: {
-    ...darkTheme.colors,
-    "editor.background": "#1f2937",
-    "editorWidget.background": "#111827"
-  },
-  base: "vs-dark"
-});
-monaco.editor.defineTheme("light-contrast", {
-  ...lightTheme,
-  colors: {
-    ...lightTheme.colors,
-    "editor.background": "#f3f4f6",
-    "editorWidget.background": "#f9fafb"
-  },
-  base: "vs-dark"
-});
+monaco.editor.defineTheme("light", { ...lightTheme, base: "vs" });
 monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
   noSemanticValidation: true,
   noSyntaxValidation: true
 });
+monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
+  diagnosticCodesToIgnore: [17008, 1005]
+});
 monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
   noUnusedLocals: false
 });
 monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
   enableSchemaRequest: true,
diff --git a/apps/web/src/styles/styles.css b/apps/web/src/styles/styles.css
index 58d044d..cb7f2af 100644
--- a/apps/web/src/styles/styles.css
+++ b/apps/web/src/styles/styles.css
@@ -16,16 +16,18 @@
   -ms-overflow-style: none;
   scrollbar-width: none;
 }
 
 .ProseMirror-gapcursor {
-  width: 100%;
+  @apply !w-full !m-0;
 }
 .ProseMirror-gapcursor::after {
-  width: 100% !important;
-  top: -19px !important;
-  @apply !border-primary my-2;
+  @apply !border-primary !w-full !z-1 !my-0 !top-0;
+}
+div:not([data-element="true"]) + .ProseMirror-gapcursor:has(+ div)::after,
+div + .ProseMirror-gapcursor:has(+ div:not([data-element="true"]))::after {
+  @apply !my-2.5;
 }
 .ProseMirror-dropcursor {
   @apply text-primary;
 }
 
diff --git a/apps/web/src/styles/styles.scss b/apps/web/src/styles/styles.scss
index a99908e..47f6cbf 100644
--- a/apps/web/src/styles/styles.scss
+++ b/apps/web/src/styles/styles.scss
@@ -41,16 +41,12 @@ kbd {
 .resize-cursor {
   cursor: ew-resize;
   cursor: col-resize;
 }
 .prose-editor {
-  .ProseMirror:not(:where(.not-prose, .not-prose *)) {
-    > * + div:not(.tableWrapper) {
-      @apply mb-5;
-    }
-
-    padding-bottom: 8rem;
+  .ProseMirror {
+    @apply pb-48;
   }
   .tableWrapper {
     @apply overflow-auto pb-2 mb-3;
     &::-webkit-scrollbar {
       @apply w-2 h-2 rounded-lg bg-gray-100 dark:bg-gray-800;
@@ -70,15 +66,15 @@ kbd {
     tbody {
       width: 100%;
     }
 
     tr {
-      @apply border-2 border-gray-200 dark:border-gray-700;
+      @apply border-2 border-gray-300 dark:border-gray-700;
     }
     td,
     th {
-      @apply text-left font-500 border-2 border-gray-200 dark:border-gray-700 relative p-2 vertical-top;
+      @apply text-left font-500 border-2 border-gray-300 dark:border-gray-700 relative p-2 vertical-top;
       min-width: 100px;
       border-style: none solid solid none;
       word-break: break-all;
     }
     th {
@@ -208,14 +204,14 @@ kbd {
     @apply m-0;
   }
   :where(ul:not([data-type="taskList"]) li > * + *, ol li > * + *):not(
       :where(.not-prose, .not-prose *)
     ) {
-    @apply my-5;
+    // @apply my-5;
   }
   :where(li > ul, li > ol, li > div > ul, li > div > ol):not(:where(.not-prose, .not-prose *)) {
-    @apply m-0;
+    //@apply m-0;
   }
   :where(ul[data-type="taskList"]):not(:where(.not-prose, .not-prose *)) {
     padding-left: 0rem;
     li {
       padding-left: 0.5rem;
@@ -254,18 +250,41 @@ kbd {
 .prose {
   --un-prose-lists: #6b7280;
   --un-prose-hr: #6b7280;
   --un-prose-invert-lists: #9ca3af;
   --un-prose-invert-hr: #9ca3af;
-  --highlighted-thread: "G3JAKWBAsWA1xXnPcJ-Zu";
+  --highlighted-thread: "";
+  :where([aria-expanded="false"] > .ProseMirror, .content, blockquote, li) {
+    &
+      > :where(div, ul, ol, p, blockquote, hr):not(.ProseMirror-gapcursor)
+      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6):not([data-element="true"]),
+    &
+      > :where(div, ul, ol, p, blockquote, hr):not([data-element="true"], .ProseMirror-gapcursor)
+      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6),
+    &
+      > :where(div, ul, ol, p, blockquote, hr):not(.ProseMirror-gapcursor)
+      + .ProseMirror-gapcursor
+      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6):not([data-element="true"]),
+    &
+      > :where(div, ul, ol, p, blockquote, hr):not([data-element="true"], .ProseMirror-gapcursor)
+      + .ProseMirror-gapcursor
+      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6) {
+      @apply mt-5;
+    }
+  }
 
-  :where(div[data-wrapper="true"]) {
+  :where(div[data-element="true"]) {
     .content > :first-child,
-    .content > :first-child [data-node-view-wrapper="true"] {
+    .content > .ProseMirror-gapcursor:first-child + *,
+    .content > :first-child > div > [data-node-view-wrapper="true"],
+    .content > .ProseMirror-gapcursor:first-child + * > div > [data-node-view-wrapper="true"] {
       margin-top: 0 !important;
     }
-    .content > :last-child:not([data-wrapper="true"]) {
+    .content > :last-child,
+    .content > .ProseMirror-gapcursor:last-child + *,
+    .content > :last-child > div > [data-node-view-wrapper="true"],
+    .content > .ProseMirror-gapcursor:last-child + * > div > [data-node-view-wrapper="true"] {
       margin-bottom: 0 !important;
     }
   }
   :where(blockquote):not(:where(.not-prose, .not-prose *)) {
     @apply border-l-3 pl-5.5 border-solid border-gray-300 dark:border-gray-700 not-italic text-gray-500 dark:text-gray-400;
@@ -274,12 +293,11 @@ kbd {
     &::before,
     &::after {
       content: unset !important;
     }
     @apply bg-gray-200 text-gray-700 font-medium dark:bg-gray-900 dark:text-gray-300 py-1 px-2 rounded-lg;
-    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
-      "Courier New", monospace !important;
+    font-family: "JetBrainsMonoVariable", monospace !important;
   }
   :where(mark) {
     @apply text-gray-700;
   }
   :where(span[data-comment]) {
@@ -351,25 +369,12 @@ kbd {
   }
   :where(blockquote):not(:where(.not-prose, .not-prose *)) {
     margin: 0;
   }
 }
-.rounded {
-  .monaco-editor,
-  .monaco-editor > *:first-child {
-    @apply rounded-2xl;
-  }
-  .monaco-editor .editor-widget {
-    @apply overflow-hidden rounded-lg;
-  }
-  .monaco-editor .monaco-hover {
-    @apply rounded-lg;
-  }
-}
-
-.ProseMirror .rounded .monaco-editor,
-.ProseMirror .rounded .monaco-editor > *:first-child {
+.ProseMirror .monaco-editor,
+.ProseMirror .monaco-editor > *:first-child {
   @apply rounded-b-none;
 }
 .split-view[data-code-editor-theme="dark"] .monaco-diff-editor {
   .original .overflow-guard {
     @apply md:(border-r-1 border-gray-700);
@@ -385,5 +390,87 @@ kbd {
   }
   .modified .overflow-guard {
     @apply md:(border-l-1 border-gray-200);
   }
 }
+
+.monaco-editor .editor-widget {
+  @apply overflow-hidden;
+  border-radius: 0.5rem !important;
+}
+.monaco-editor .monaco-hover {
+  border-radius: 0.5rem !important;
+}
+.rounded-editor-2xl {
+  .monaco-editor,
+  .monaco-editor > *:first-child {
+    @apply rounded-2xl;
+  }
+}
+.rounded-editor-t-2xl {
+  .monaco-editor,
+  .monaco-editor > *:first-child {
+    border-top-left-radius: calc(1rem - 2px);
+    border-top-right-radius: calc(1rem - 2px);
+  }
+}
+
+.rounded-editor-lg {
+  .monaco-editor,
+  .monaco-editor > *:first-child {
+    @apply rounded-lg;
+  }
+}
+.customized-editor-show-keyboard-hidden {
+  [widgetid="editor.contrib.ShowKeyboardWidget"] {
+    display: none !important;
+  }
+}
+.customized-editor {
+  --customized-editor-background: #f9fafb;
+  --customized-editor-widget-background: #f3f4f6;
+  .mtk2 {
+    color: var(--customized-editor-background);
+  }
+  .monaco-editor {
+    .inputarea.ime-input {
+      background-color: var(--customized-editor-background);
+    }
+    .view-overlays .current-line {
+      background-color: var(--customized-editor-widget-background) !important;
+      @apply border-gray-300 border-0;
+    }
+    .view-overlays > *:last-child:first-child .current-line {
+      background-color: transparent !important;
+    }
+    --vscode-editor-background: var(--customized-editor-background);
+    --vscode-editorStickyScroll-background: var(--customized-editor-background);
+    --vscode-breadcrumb-background: var(--customized-editor-background);
+    --vscode-editorGutter-background: var(--customized-editor-background);
+    --vscode-editorMarkerNavigation-background: var(--customized-editor-background);
+
+    // Editor Widget
+    .find-widget {
+      background-color: var(--customized-editor-widget-background);
+    }
+    --vscode-editorWidget-background: var(--customized-editor-widget-background);
+    --vscode-quickInput-background: var(--customized-editor-widget-background);
+    --vscode-editorHoverWidget-background: var(--customized-editor-widget-background);
+    --vscode-listFilterWidget-background: var(--customized-editor-widget-background);
+    --vscode-checkbox-selectBackground: var(--customized-editor-widget-background);
+    --vscode-breadcrumbPicker-background: var(--customized-editor-widget-background);
+  }
+}
+.customized-editor-contrast {
+  --customized-editor-background: #f3f4f6;
+  --customized-editor-widget-background: #f9fafb;
+}
+.dark {
+  .customized-editor {
+    --customized-editor-background: #111827;
+    --customized-editor-widget-background: #1f2937;
+  }
+  .customized-editor-contrast {
+    --customized-editor-background: #1f2937;
+    --customized-editor-widget-background: #111827;
+  }
+}
diff --git a/apps/web/src/views/auth/error-messages.tsx b/apps/web/src/views/auth/error-messages.tsx
index 29c9584..c466752 100644
--- a/apps/web/src/views/auth/error-messages.tsx
+++ b/apps/web/src/views/auth/error-messages.tsx
@@ -1,9 +1,10 @@
 const errorMessages: Record<string, string> = {
   invalidEmail: "Incorrect email address",
   invalidCredentials: "Invalid credentials",
   emailNotVerified: "Email not verified",
+  magicLinkAlreadySent: "Wait 1 min before requesting a new magic link",
   totpTokenInvalid: "Invalid 2FA code",
   resourceNotFound: "User not found",
   alreadyExists: "User already exists"
 };
 const getErrorMessage = (reason: string): string => {
diff --git a/apps/web/src/views/conflict/index.tsx b/apps/web/src/views/conflict/index.tsx
index 03c3ee9..309f81a 100644
--- a/apps/web/src/views/conflict/index.tsx
+++ b/apps/web/src/views/conflict/index.tsx
@@ -127,11 +127,11 @@ const ConflictView: Component<{ monaco: typeof monaco }> = (props) => {
         ref={setContainerRef}
         class="flex-1 h-full w-full split-view"
         data-code-editor-theme={codeEditorTheme()}
       />
       <Show when={!conflictData() || currentContent.loading}>
-        <div class="h-full w-full absolute top-0 left-0 bg-gray-100 dark:bg-gray-800 flex justify-center items-center">
+        <div class="h-full w-full absolute top-0 left-0 bg-gray-100 dark:bg-gray-800 flex justify-center items-center z-12">
           <Show when={!conflictData()} fallback={<Loader />}>
             <span class="text-2xl font-semibold text-gray-500 dark:text-gray-400">
               Select a conflict to resolve
             </span>
           </Show>
diff --git a/apps/web/src/views/content-piece/sections/details/slug.tsx b/apps/web/src/views/content-piece/sections/details/slug.tsx
index 7a1c64a..80a68b0 100644
--- a/apps/web/src/views/content-piece/sections/details/slug.tsx
+++ b/apps/web/src/views/content-piece/sections/details/slug.tsx
@@ -29,11 +29,16 @@ const SlugInput: Component<SlugInputProps> = (props) => {
           disabled={props.editable === false}
           color="base"
           onChange={(event) => {
             const { value } = event.currentTarget;
 
-            props.setSlug(convertToSlug(value));
+            props.setSlug(
+              value
+                .split("/")
+                .map((slugPart) => convertToSlug(slugPart))
+                .join("/")
+            );
           }}
         />
       </Show>
     </div>
   );
diff --git a/apps/web/src/views/editor/editor.tsx b/apps/web/src/views/editor/editor.tsx
index d0482fd..46323d9 100644
--- a/apps/web/src/views/editor/editor.tsx
+++ b/apps/web/src/views/editor/editor.tsx
@@ -16,11 +16,11 @@ import { Typography } from "@tiptap/extension-typography";
 import { HocuspocusProvider } from "@hocuspocus/provider";
 import { CharacterCount } from "@tiptap/extension-character-count";
 import * as Y from "yjs";
 import { useLocation, useNavigate } from "@solidjs/router";
 import { CellSelection } from "@tiptap/pm/tables";
-import { AllSelection } from "@tiptap/pm/state";
+import { AllSelection, NodeSelection } from "@tiptap/pm/state";
 import clsx from "clsx";
 import { Instance } from "tippy.js";
 import { scrollIntoView } from "seamless-scroll-polyfill";
 import { Dropdown } from "#components/primitives";
 import {
@@ -35,10 +35,11 @@ import {
   createClipboardSerializer,
   createExtensions,
   createBlockMenuOptions,
   BlockPaste,
   TableMenuPlugin,
+  ElementMenuPlugin,
   CommentMenuPlugin,
   AutoDir
 } from "#lib/editor";
 import {
   App,
@@ -141,10 +142,11 @@ const Editor: Component<EditorProps> = (props) => {
       SlashMenuPlugin.configure({
         menuItems: workspaceSettings() ? createBlockMenuOptions(workspaceSettings()!) : []
       }),
       hostConfig.extensions && BlockActionMenuPlugin,
       TableMenuPlugin,
+      ElementMenuPlugin,
       CommentMenuPlugin,
       Collab.configure({
         document: ydoc
       }),
       CollabCursor(provider)
@@ -170,13 +172,14 @@ const Editor: Component<EditorProps> = (props) => {
     const from = Math.min(...ranges.map((range) => range.$from.pos));
     const to = Math.max(...ranges.map((range) => range.$to.pos));
     const { empty } = selection;
     const isAllSelection = selection instanceof AllSelection;
     const isCellSelection = selection instanceof CellSelection;
+    const isNodeSelection = selection instanceof NodeSelection;
     const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(state.selection);
 
-    if (!view.hasFocus() || isAllSelection) {
+    if ((!view.hasFocus() && !isNodeSelection) || isAllSelection) {
       setBubbleMenuOpened(false);
 
       return false;
     }
 
@@ -185,11 +188,12 @@ const Editor: Component<EditorProps> = (props) => {
 
       return true;
     }
 
     if (
-      ["image", "codeBlock", "embed", "horizontalRule"].some((name) => {
+      isNodeSelection &&
+      ["horizontalRule", "image", "codeBlock", "embed", "element"].some((name) => {
         return editor.isActive(name);
       })
     ) {
       setBubbleMenuOpened(false);
 
@@ -209,11 +213,14 @@ const Editor: Component<EditorProps> = (props) => {
   const shouldShowFloatingMenu = (editor: SolidEditor): boolean => {
     const { state, view } = editor;
     const { selection } = state;
     const { $anchor, empty } = selection;
     const isRootDepth =
-      $anchor.depth === 1 || ($anchor.depth === 2 && $anchor.node(1).type.name === "wrapper");
+      $anchor.depth === 1 ||
+      ["element", "blockquote", "listItem", "taskItem"].includes(
+        $anchor.node($anchor.depth - 1)?.type?.name
+      );
     const isEmptyTextBlock =
       $anchor.parent.isTextblock &&
       !$anchor.parent.type.spec.code &&
       $anchor.parent.type.name === "paragraph" &&
       !$anchor.parent.textContent;
@@ -272,10 +279,12 @@ const Editor: Component<EditorProps> = (props) => {
             tippyOptions={{
               duration: [300, 250],
               zIndex: 30,
               hideOnClick: false,
               interactive: true,
+              placement: "bottom",
+              popperOptions: { modifiers: [{ name: "flip", enabled: false }] },
               animation: breakpoints.md() ? "scale-subtle" : "shift-away-subtle",
               onHide() {
                 if (containerRef()?.contains(el)) return false;
               },
               onCreate(instance) {
diff --git a/apps/web/src/views/editor/menus/bubble-menu.tsx b/apps/web/src/views/editor/menus/bubble-menu.tsx
deleted file mode 100644
index ab9f81c..0000000
--- a/apps/web/src/views/editor/menus/bubble-menu.tsx
+++ /dev/null
@@ -1,441 +0,0 @@
-import { SolidEditor } from "@vrite/tiptap-solid";
-import {
-  mdiFormatBold,
-  mdiFormatItalic,
-  mdiFormatStrikethrough,
-  mdiCodeTags,
-  mdiLinkVariant,
-  mdiFormatColorHighlight,
-  mdiFormatSubscript,
-  mdiFormatSuperscript,
-  mdiCheck,
-  mdiDelete,
-  mdiTableColumnRemove,
-  mdiTableRowRemove,
-  mdiTableMergeCells,
-  mdiTableSplitCell,
-  mdiTableRemove,
-  mdiCommentOutline,
-  mdiTableHeadersEyeOff,
-  mdiPlus,
-  mdiKeyboardCloseOutline
-} from "@mdi/js";
-import { CellSelection } from "@tiptap/pm/tables";
-import { Component, createEffect, createSignal, For, Match, on, Show, Switch } from "solid-js";
-import { nanoid } from "nanoid";
-import clsx from "clsx";
-import { breakpoints, createRef, Ref } from "#lib/utils";
-import { Card, IconButton, Input, Tooltip } from "#components/primitives";
-import { App, useAuthenticatedUserData, useClient } from "#context";
-
-type BubbleMenuMode = "format" | "link" | "table" | "block";
-interface BubbleMenuProps {
-  editor: SolidEditor;
-  opened: boolean;
-  contentPieceId?: string;
-  class?: string;
-  mode?: BubbleMenuMode;
-  ref?: Ref<HTMLElement>[1];
-  blur?(): void;
-  setBlockMenuOpened?(opened: boolean): void;
-}
-
-const BubbleMenu: Component<BubbleMenuProps> = (props) => {
-  const [activeMarks, setActiveMarks] = createSignal<string[]>([]);
-  const { workspaceSettings = () => null } = useAuthenticatedUserData() || {};
-  const client = useClient();
-  const [mode, setMode] = createSignal<BubbleMenuMode>("format");
-  const [link, setLink] = createSignal("");
-  const [linkInputRef, setLinkInputRef] = createRef<HTMLInputElement | null>(null);
-  const commentMenuItem = {
-    icon: mdiCommentOutline,
-    mark: "comment",
-    label: "Comment",
-    async onClick() {
-      if (props.editor.isActive("comment")) {
-        props.editor.commands.unsetComment();
-      } else {
-        const threadFragment = nanoid();
-
-        props.editor.chain().setComment({ thread: threadFragment }).focus().run();
-
-        try {
-          await client.comments.createThread.mutate({
-            contentPieceId: props.contentPieceId || "",
-            fragment: threadFragment
-          });
-        } catch (error) {
-          props.editor.commands.unsetComment();
-        }
-      }
-    }
-  };
-  const closeKeyboardItem = {
-    icon: mdiKeyboardCloseOutline,
-    label: "Close keyboard",
-    async onClick() {
-      props.blur?.();
-    }
-  };
-  const menus = (
-    [
-      {
-        icon: mdiFormatBold,
-        mark: "bold",
-        label: "Bold"
-      },
-      {
-        icon: mdiFormatItalic,
-        mark: "italic",
-        label: "Italic"
-      },
-      {
-        icon: mdiFormatStrikethrough,
-        mark: "strike",
-        label: "Strike"
-      },
-      {
-        icon: mdiCodeTags,
-        mark: "code",
-        label: "Code"
-      },
-      {
-        icon: mdiLinkVariant,
-        mark: "link",
-        label: "Link",
-        onClick() {
-          setMode("link");
-        }
-      },
-      { icon: mdiFormatColorHighlight, mark: "highlight", label: "Highlight" },
-      { icon: mdiFormatSubscript, mark: "subscript", label: "Subscript" },
-      { icon: mdiFormatSuperscript, mark: "superscript", label: "Superscript" },
-      ...(props.contentPieceId && breakpoints.md() ? [commentMenuItem] : []),
-      ...(breakpoints.md() ? [] : [closeKeyboardItem])
-    ] as Array<{ icon: string; mark?: string; label: string; onClick?(): void }>
-  ).filter(({ mark }) => {
-    if (!mark || mark === "comment") return true;
-
-    if (!workspaceSettings()) {
-      return true;
-    }
-
-    return workspaceSettings()!.marks.includes(mark as App.WorkspaceSettings["marks"][number]);
-  });
-  const tableMenus = [
-    {
-      icon: mdiTableHeadersEyeOff,
-      label: "Toggle header cell off",
-      show() {
-        const { selection } = props.editor.state;
-
-        if (selection instanceof CellSelection) {
-          const tableNode = selection.$anchorCell.node(1);
-          const rowNode = selection.$anchorCell.node(2);
-
-          if (tableNode.child(0) === rowNode) {
-            return false;
-          }
-
-          return selection.$anchorCell.nodeAfter?.type.name === "tableHeader";
-        }
-
-        return false;
-      },
-      onClick() {
-        props.editor.chain().toggleHeaderCell().focus().run();
-      }
-    },
-    {
-      icon: mdiTableMergeCells,
-      label: "Merge cells",
-      show() {
-        const { selection } = props.editor.state;
-
-        if (selection instanceof CellSelection) {
-          return selection.$anchorCell.pos !== selection.$headCell.pos;
-        }
-
-        return false;
-      },
-      onClick() {
-        props.editor.chain().mergeCells().run();
-      }
-    },
-    {
-      icon: mdiTableSplitCell,
-      label: "Split cell",
-      show() {
-        const { selection } = props.editor.state;
-
-        if (
-          selection instanceof CellSelection &&
-          selection.$anchorCell.pos === selection.$headCell.pos
-        ) {
-          return (
-            selection.$anchorCell.nodeAfter?.attrs.colspan > 1 ||
-            selection.$anchorCell.nodeAfter?.attrs.rowspan > 1
-          );
-        }
-
-        return false;
-      },
-      onClick() {
-        props.editor.chain().splitCell().run();
-      }
-    },
-    {
-      icon: mdiTableColumnRemove,
-      label: "Delete column(s)",
-      show() {
-        const { selection } = props.editor.state;
-
-        if (selection instanceof CellSelection) {
-          const tableNode = selection.$anchorCell.node(1);
-
-          let isSingleColumn = false;
-
-          tableNode.content.forEach((rowNode) => {
-            isSingleColumn = rowNode.childCount === 1;
-          });
-
-          return !isSingleColumn;
-        }
-
-        return true;
-      },
-      onClick() {
-        props.editor.chain().deleteColumn().focus().run();
-      }
-    },
-    {
-      icon: mdiTableRowRemove,
-      label: "Delete row(s)",
-
-      show() {
-        const { selection } = props.editor.state;
-
-        if (selection instanceof CellSelection) {
-          const tableNode = selection.$anchorCell.node(1);
-
-          if (tableNode.content.childCount === 1) {
-            return false;
-          }
-        }
-
-        return true;
-      },
-      onClick() {
-        props.editor.chain().deleteRow().focus().run();
-      }
-    },
-    {
-      icon: mdiTableRemove,
-      label: "Delete table",
-
-      show() {
-        const { selection } = props.editor.state;
-
-        if (selection instanceof CellSelection) {
-          const tableNode = selection.$anchorCell.node(1);
-
-          if (tableNode.childCount === 1) return true;
-
-          let isSingleColumn = false;
-
-          tableNode.content.forEach((rowNode) => {
-            isSingleColumn = rowNode.childCount === 1;
-          });
-
-          return isSingleColumn;
-        }
-
-        return false;
-      },
-      onClick() {
-        props.editor.chain().deleteTable().focus().run();
-      }
-    }
-  ];
-  const marks = menus.map((menu) => menu.mark);
-  const saveLink = (): void => {
-    props.editor.chain().unsetCode().setLink({ href: link() }).focus().run();
-    setMode("format");
-  };
-
-  props.editor.on("update", () => {
-    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
-  });
-  props.editor.on("selectionUpdate", () => {
-    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
-
-    if (props.editor.state.selection instanceof CellSelection) {
-      setMode("table");
-    } else if (!props.editor.state.selection.empty) {
-      setMode("format");
-    }
-  });
-  createEffect(
-    on(mode, (mode) => {
-      if (mode === "link") {
-        setLink(props.editor.getAttributes("link").href || "");
-        setTimeout(() => {
-          const linkInput = linkInputRef();
-
-          linkInput?.focus();
-        }, 300);
-      } else {
-        setLink("");
-      }
-    })
-  );
-  createEffect(
-    on(
-      () => props.mode,
-      (mode) => {
-        setMode((currentMode) => mode || currentMode);
-      }
-    )
-  );
-  createEffect(
-    on(
-      () => props.opened,
-      (opened) => {
-        if (!opened) {
-          setLink("");
-          setTimeout(() => {
-            setMode("format");
-          }, 300);
-        }
-      }
-    )
-  );
-
-  return (
-    <Card
-      class={clsx(
-        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial",
-        props.class
-      )}
-      ref={props.ref}
-    >
-      <Switch>
-        <Match when={mode() === "block"}>
-          <IconButton
-            path={mdiPlus}
-            text="soft"
-            variant="text"
-            label="Insert block"
-            onClick={(event) => {
-              props.setBlockMenuOpened?.(true);
-              event.preventDefault();
-              event.stopPropagation();
-            }}
-          />
-          <IconButton
-            path={mdiKeyboardCloseOutline}
-            text="soft"
-            variant="text"
-            onClick={(event) => {
-              props.blur?.();
-              event.preventDefault();
-              event.stopPropagation();
-            }}
-          />
-        </Match>
-        <Match when={mode() === "table"}>
-          <For
-            each={tableMenus}
-            fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
-          >
-            {(menuItem) => {
-              return (
-                <Show when={!menuItem.show || menuItem.show()}>
-                  <Tooltip text={menuItem.label} side="bottom" wrapperClass="snap-start">
-                    <IconButton
-                      path={menuItem.icon}
-                      text="soft"
-                      variant="text"
-                      color="base"
-                      onClick={(event) => {
-                        menuItem.onClick();
-                        event.preventDefault();
-                        event.stopPropagation();
-                      }}
-                    />
-                  </Tooltip>
-                </Show>
-              );
-            }}
-          </For>
-        </Match>
-        <Match when={mode() === "format"}>
-          <div class="flex">
-            <For
-              each={menus}
-              fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
-            >
-              {(menu) => {
-                const active = (): boolean => {
-                  return Boolean(menu.mark && activeMarks().includes(menu.mark));
-                };
-
-                return (
-                  <Tooltip text={menu.label} side="bottom" wrapperClass="snap-start">
-                    <IconButton
-                      path={menu.icon}
-                      text={active() ? "primary" : "soft"}
-                      variant={active() ? "solid" : "text"}
-                      color={active() ? "primary" : "base"}
-                      onClick={(event) => {
-                        const chain = props.editor.chain();
-
-                        if (menu.onClick) {
-                          menu.onClick();
-                        } else if (menu.mark) {
-                          if (menu.mark !== "code") {
-                            chain.unsetCode();
-                          }
-
-                          chain.toggleMark(menu.mark).focus().run();
-                        }
-
-                        event.preventDefault();
-                        event.stopPropagation();
-                      }}
-                    />
-                  </Tooltip>
-                );
-              }}
-            </For>
-          </div>
-        </Match>
-        <Match when={mode() === "link"}>
-          <Input
-            ref={setLinkInputRef}
-            value={link()}
-            placeholder="Paste a link..."
-            wrapperClass="w-full md:w-auto"
-            setValue={(value) => {
-              setLink(value);
-            }}
-            onEnter={saveLink}
-            class="py-0 my-0 bg-transparent"
-          />
-          <IconButton path={mdiCheck} text="soft" variant="text" onClick={saveLink} />
-          <IconButton
-            path={mdiDelete}
-            text="soft"
-            variant="text"
-            onClick={() => {
-              props.editor.chain().unsetLink().focus().run();
-              setMode("format");
-            }}
-          />
-        </Match>
-      </Switch>
-    </Card>
-  );
-};
-
-export { BubbleMenu };
diff --git a/apps/web/src/views/editor/menus/bubble/block.tsx b/apps/web/src/views/editor/menus/bubble/block.tsx
new file mode 100644
index 0000000..eebad17
--- /dev/null
+++ b/apps/web/src/views/editor/menus/bubble/block.tsx
@@ -0,0 +1,48 @@
+import { mdiPlus, mdiKeyboardCloseOutline } from "@mdi/js";
+import clsx from "clsx";
+import { Component } from "solid-js";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { Card, IconButton } from "#components/primitives";
+
+const BlockMenu: Component<{
+  class?: string;
+  mode: string;
+  opened: boolean;
+  editor: SolidEditor;
+  blur?(): void;
+  setMode(mode: string): void;
+  setBlockMenuOpened?(opened: boolean): void;
+}> = (props) => {
+  return (
+    <Card
+      class={clsx(
+        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
+        props.class
+      )}
+    >
+      <IconButton
+        path={mdiPlus}
+        text="soft"
+        variant="text"
+        label="Insert block"
+        onClick={(event) => {
+          props.setBlockMenuOpened?.(true);
+          event.preventDefault();
+          event.stopPropagation();
+        }}
+      />
+      <IconButton
+        path={mdiKeyboardCloseOutline}
+        text="soft"
+        variant="text"
+        onClick={(event) => {
+          props.blur?.();
+          event.preventDefault();
+          event.stopPropagation();
+        }}
+      />
+    </Card>
+  );
+};
+
+export { BlockMenu };
diff --git a/apps/web/src/views/editor/menus/bubble/format.tsx b/apps/web/src/views/editor/menus/bubble/format.tsx
new file mode 100644
index 0000000..1f3e054
--- /dev/null
+++ b/apps/web/src/views/editor/menus/bubble/format.tsx
@@ -0,0 +1,165 @@
+import clsx from "clsx";
+import { Component, For, createSignal } from "solid-js";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import {
+  mdiFormatBold,
+  mdiFormatItalic,
+  mdiFormatStrikethrough,
+  mdiCodeTags,
+  mdiLinkVariant,
+  mdiFormatColorHighlight,
+  mdiFormatSubscript,
+  mdiFormatSuperscript,
+  mdiKeyboardCloseOutline,
+  mdiCommentOutline
+} from "@mdi/js";
+import { nanoid } from "nanoid";
+import { Card, IconButton, Tooltip } from "#components/primitives";
+import { App, useAuthenticatedUserData, useClient } from "#context";
+import { breakpoints } from "#lib/utils";
+
+const FormatMenu: Component<{
+  class?: string;
+  mode: string;
+  opened: boolean;
+  editor: SolidEditor;
+  contentPieceId?: string;
+  blur?(): void;
+  setMode(mode: string): void;
+}> = (props) => {
+  const [activeMarks, setActiveMarks] = createSignal<string[]>([]);
+  const { workspaceSettings = () => null } = useAuthenticatedUserData() || {};
+  const client = useClient();
+  const commentMenuItem = {
+    icon: mdiCommentOutline,
+    mark: "comment",
+    label: "Comment",
+    async onClick() {
+      if (props.editor.isActive("comment")) {
+        props.editor.commands.unsetComment();
+      } else {
+        const threadFragment = nanoid();
+
+        props.editor.chain().setComment({ thread: threadFragment }).focus().run();
+
+        try {
+          await client.comments.createThread.mutate({
+            contentPieceId: props.contentPieceId || "",
+            fragment: threadFragment
+          });
+        } catch (error) {
+          props.editor.commands.unsetComment();
+        }
+      }
+    }
+  };
+  const closeKeyboardItem = {
+    icon: mdiKeyboardCloseOutline,
+    label: "Close keyboard",
+    async onClick() {
+      props.editor.commands.blur?.();
+    }
+  };
+  const menus = (
+    [
+      {
+        icon: mdiFormatBold,
+        mark: "bold",
+        label: "Bold"
+      },
+      {
+        icon: mdiFormatItalic,
+        mark: "italic",
+        label: "Italic"
+      },
+      {
+        icon: mdiFormatStrikethrough,
+        mark: "strike",
+        label: "Strike"
+      },
+      {
+        icon: mdiCodeTags,
+        mark: "code",
+        label: "Code"
+      },
+      {
+        icon: mdiLinkVariant,
+        mark: "link",
+        label: "Link",
+        onClick() {
+          props.setMode("link");
+        }
+      },
+      { icon: mdiFormatColorHighlight, mark: "highlight", label: "Highlight" },
+      { icon: mdiFormatSubscript, mark: "subscript", label: "Subscript" },
+      { icon: mdiFormatSuperscript, mark: "superscript", label: "Superscript" },
+      ...(props.contentPieceId && breakpoints.md() ? [commentMenuItem] : []),
+      ...(breakpoints.md() ? [] : [closeKeyboardItem])
+    ] as Array<{ icon: string; mark?: string; label: string; onClick?(): void }>
+  ).filter(({ mark }) => {
+    if (!mark || mark === "comment") return true;
+
+    if (!workspaceSettings()) {
+      return true;
+    }
+
+    return workspaceSettings()!.marks.includes(mark as App.WorkspaceSettings["marks"][number]);
+  });
+  const marks = menus.map((menu) => menu.mark);
+
+  props.editor.on("update", () => {
+    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
+  });
+  props.editor.on("selectionUpdate", () => {
+    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
+  });
+
+  return (
+    <Card
+      class={clsx(
+        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
+        props.class
+      )}
+    >
+      <For
+        each={menus}
+        fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
+      >
+        {(menu) => {
+          const active = (): boolean => {
+            return Boolean(menu.mark && activeMarks().includes(menu.mark));
+          };
+
+          return (
+            <Tooltip text={menu.label} side="bottom" wrapperClass="snap-start">
+              <IconButton
+                path={menu.icon}
+                text={active() ? "primary" : "soft"}
+                variant={active() ? "solid" : "text"}
+                color={active() ? "primary" : "base"}
+                onClick={(event) => {
+                  const chain = props.editor.chain();
+
+                  if (menu.onClick) {
+                    menu.onClick();
+                  } else if (menu.mark) {
+                    if (menu.mark !== "code") {
+                      chain.unsetCode();
+                    }
+
+                    chain.toggleMark(menu.mark).focus().run();
+                  }
+
+                  event.preventDefault();
+                  event.stopPropagation();
+                }}
+              />
+            </Tooltip>
+          );
+        }}
+      </For>
+    </Card>
+  );
+};
+
+export { FormatMenu };
diff --git a/apps/web/src/views/editor/menus/bubble/index.tsx b/apps/web/src/views/editor/menus/bubble/index.tsx
new file mode 100644
index 0000000..6118707
--- /dev/null
+++ b/apps/web/src/views/editor/menus/bubble/index.tsx
@@ -0,0 +1,101 @@
+import { LinkMenu } from "./link";
+import { FormatMenu } from "./format";
+import { TableMenu } from "./table";
+import { BlockMenu } from "./block";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { CellSelection } from "@tiptap/pm/tables";
+import { Component, createEffect, createSignal, Match, on, Switch } from "solid-js";
+import { Ref } from "#lib/utils";
+
+type BubbleMenuMode = "format" | "link" | "table" | "block";
+interface BubbleMenuProps {
+  editor: SolidEditor;
+  opened: boolean;
+  contentPieceId?: string;
+  class?: string;
+  mode?: BubbleMenuMode;
+  ref?: Ref<HTMLElement>[1];
+  blur?(): void;
+  setBlockMenuOpened?(opened: boolean): void;
+}
+
+const BubbleMenu: Component<BubbleMenuProps> = (props) => {
+  const [mode, setMode] = createSignal<BubbleMenuMode>("format");
+
+  props.editor.on("selectionUpdate", ({ editor }) => {
+    const { selection } = editor.state;
+
+    if (props.editor.state.selection instanceof CellSelection) {
+      setMode("table");
+    } else if (!props.editor.state.selection.empty) {
+      setMode("format");
+    }
+  });
+  createEffect(
+    on(
+      () => props.mode,
+      (mode) => {
+        setMode((currentMode) => mode || currentMode);
+      }
+    )
+  );
+  createEffect(
+    on(
+      () => props.opened,
+      (opened) => {
+        if (!opened) {
+          setTimeout(() => {
+            setMode("format");
+          }, 300);
+        }
+      }
+    )
+  );
+
+  return (
+    <Switch>
+      <Match when={mode() === "block"}>
+        <BlockMenu
+          editor={props.editor}
+          mode={mode()}
+          opened={props.opened}
+          setMode={setMode}
+          setBlockMenuOpened={props.setBlockMenuOpened}
+          blur={props.blur}
+          class={props.class}
+        />
+      </Match>
+      <Match when={mode() === "table"}>
+        <TableMenu
+          editor={props.editor}
+          mode={mode()}
+          opened={props.opened}
+          setMode={setMode}
+          class={props.class}
+        />
+      </Match>
+      <Match when={mode() === "format"}>
+        <FormatMenu
+          editor={props.editor}
+          mode={mode()}
+          opened={props.opened}
+          setMode={setMode}
+          class={props.class}
+          contentPieceId={props.contentPieceId}
+          blur={props.blur}
+        />
+      </Match>
+      <Match when={mode() === "link"}>
+        <LinkMenu
+          editor={props.editor}
+          mode={mode()}
+          opened={props.opened}
+          setMode={setMode}
+          class={props.class}
+        />
+      </Match>
+    </Switch>
+  );
+};
+
+export { BubbleMenu };
diff --git a/apps/web/src/views/editor/menus/bubble/link.tsx b/apps/web/src/views/editor/menus/bubble/link.tsx
new file mode 100644
index 0000000..84d681e
--- /dev/null
+++ b/apps/web/src/views/editor/menus/bubble/link.tsx
@@ -0,0 +1,82 @@
+import { mdiCheck, mdiDelete } from "@mdi/js";
+import clsx from "clsx";
+import { Component, createEffect, createSignal, on } from "solid-js";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { Card, Input, IconButton } from "#components/primitives";
+import { createRef } from "#lib/utils";
+
+const LinkMenu: Component<{
+  class?: string;
+  mode: string;
+  opened: boolean;
+  editor: SolidEditor;
+  setMode(mode: string): void;
+}> = (props) => {
+  const [link, setLink] = createSignal("");
+  const [linkInputRef, setLinkInputRef] = createRef<HTMLInputElement | null>(null);
+  const saveLink = (): void => {
+    props.editor.chain().unsetCode().setLink({ href: link() }).focus().run();
+    props.setMode("format");
+  };
+
+  createEffect(
+    on(
+      () => props.opened,
+      (opened) => {
+        if (!opened) {
+          setLink("");
+        }
+      }
+    )
+  );
+  createEffect(
+    on(
+      () => props.mode,
+      (mode) => {
+        if (mode === "link") {
+          setLink(props.editor.getAttributes("link").href || "");
+          setTimeout(() => {
+            const linkInput = linkInputRef();
+
+            linkInput?.focus();
+          }, 300);
+        } else {
+          setLink("");
+        }
+      }
+    )
+  );
+
+  return (
+    <Card
+      class={clsx(
+        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
+        props.class
+      )}
+    >
+      <Input
+        ref={setLinkInputRef}
+        value={link()}
+        placeholder="Paste a link..."
+        wrapperClass="w-full md:w-auto"
+        setValue={(value) => {
+          setLink(value);
+        }}
+        onEnter={saveLink}
+        class="py-0 my-0 bg-transparent"
+      />
+      <IconButton path={mdiCheck} text="soft" variant="text" onClick={saveLink} />
+      <IconButton
+        path={mdiDelete}
+        text="soft"
+        variant="text"
+        onClick={() => {
+          props.editor.chain().unsetLink().focus().run();
+          props.setMode("format");
+        }}
+      />
+    </Card>
+  );
+};
+
+export { LinkMenu };
diff --git a/apps/web/src/views/editor/menus/bubble/table.tsx b/apps/web/src/views/editor/menus/bubble/table.tsx
new file mode 100644
index 0000000..a80c615
--- /dev/null
+++ b/apps/web/src/views/editor/menus/bubble/table.tsx
@@ -0,0 +1,194 @@
+import {
+  mdiTableColumnRemove,
+  mdiTableHeadersEyeOff,
+  mdiTableMergeCells,
+  mdiTableRemove,
+  mdiTableRowRemove,
+  mdiTableSplitCell
+} from "@mdi/js";
+import clsx from "clsx";
+import { Component, For, Show, createEffect, on } from "solid-js";
+import { SolidEditor } from "@vrite/tiptap-solid";
+import { CellSelection } from "@tiptap/pm/tables";
+import { Card, IconButton, Tooltip } from "#components/primitives";
+import { createRef } from "#lib/utils";
+
+const TableMenu: Component<{
+  class?: string;
+  mode: string;
+  opened: boolean;
+  editor: SolidEditor;
+  setMode(mode: string): void;
+}> = (props) => {
+  const tableMenus = [
+    {
+      icon: mdiTableHeadersEyeOff,
+      label: "Toggle header cell off",
+      show() {
+        const { selection } = props.editor.state;
+
+        if (selection instanceof CellSelection) {
+          const tableNode = selection.$anchorCell.node(1);
+          const rowNode = selection.$anchorCell.node(2);
+
+          if (tableNode.child(0) === rowNode) {
+            return false;
+          }
+
+          return selection.$anchorCell.nodeAfter?.type.name === "tableHeader";
+        }
+
+        return false;
+      },
+      onClick() {
+        props.editor.chain().toggleHeaderCell().focus().run();
+      }
+    },
+    {
+      icon: mdiTableMergeCells,
+      label: "Merge cells",
+      show() {
+        const { selection } = props.editor.state;
+
+        if (selection instanceof CellSelection) {
+          return selection.$anchorCell.pos !== selection.$headCell.pos;
+        }
+
+        return false;
+      },
+      onClick() {
+        props.editor.chain().mergeCells().run();
+      }
+    },
+    {
+      icon: mdiTableSplitCell,
+      label: "Split cell",
+      show() {
+        const { selection } = props.editor.state;
+
+        if (
+          selection instanceof CellSelection &&
+          selection.$anchorCell.pos === selection.$headCell.pos
+        ) {
+          return (
+            selection.$anchorCell.nodeAfter?.attrs.colspan > 1 ||
+            selection.$anchorCell.nodeAfter?.attrs.rowspan > 1
+          );
+        }
+
+        return false;
+      },
+      onClick() {
+        props.editor.chain().splitCell().run();
+      }
+    },
+    {
+      icon: mdiTableColumnRemove,
+      label: "Delete column(s)",
+      show() {
+        const { selection } = props.editor.state;
+
+        if (selection instanceof CellSelection) {
+          const tableNode = selection.$anchorCell.node(1);
+
+          let isSingleColumn = false;
+
+          tableNode.content.forEach((rowNode) => {
+            isSingleColumn = rowNode.childCount === 1;
+          });
+
+          return !isSingleColumn;
+        }
+
+        return true;
+      },
+      onClick() {
+        props.editor.chain().deleteColumn().focus().run();
+      }
+    },
+    {
+      icon: mdiTableRowRemove,
+      label: "Delete row(s)",
+
+      show() {
+        const { selection } = props.editor.state;
+
+        if (selection instanceof CellSelection) {
+          const tableNode = selection.$anchorCell.node(1);
+
+          if (tableNode.content.childCount === 1) {
+            return false;
+          }
+        }
+
+        return true;
+      },
+      onClick() {
+        props.editor.chain().deleteRow().focus().run();
+      }
+    },
+    {
+      icon: mdiTableRemove,
+      label: "Delete table",
+
+      show() {
+        const { selection } = props.editor.state;
+
+        if (selection instanceof CellSelection) {
+          const tableNode = selection.$anchorCell.node(1);
+
+          if (tableNode.childCount === 1) return true;
+
+          let isSingleColumn = false;
+
+          tableNode.content.forEach((rowNode) => {
+            isSingleColumn = rowNode.childCount === 1;
+          });
+
+          return isSingleColumn;
+        }
+
+        return false;
+      },
+      onClick() {
+        props.editor.chain().deleteTable().focus().run();
+      }
+    }
+  ];
+
+  return (
+    <Card
+      class={clsx(
+        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
+        props.class
+      )}
+    >
+      <For
+        each={tableMenus}
+        fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
+      >
+        {(menuItem) => {
+          return (
+            <Show when={!menuItem.show || menuItem.show()}>
+              <Tooltip text={menuItem.label} side="bottom" wrapperClass="snap-start">
+                <IconButton
+                  path={menuItem.icon}
+                  text="soft"
+                  variant="text"
+                  color="base"
+                  onClick={(event) => {
+                    menuItem.onClick();
+                    event.preventDefault();
+                    event.stopPropagation();
+                  }}
+                />
+              </Tooltip>
+            </Show>
+          );
+        }}
+      </For>
+    </Card>
+  );
+};
+
+export { TableMenu };
diff --git a/apps/web/src/views/editor/menus/comment-threads-menu.tsx b/apps/web/src/views/editor/menus/comment-threads/index.tsx
similarity index 100%
rename from apps/web/src/views/editor/menus/comment-threads-menu.tsx
rename to apps/web/src/views/editor/menus/comment-threads/index.tsx
diff --git a/apps/web/src/views/editor/menus/export-menu.tsx b/apps/web/src/views/editor/menus/export/index.tsx
similarity index 100%
rename from apps/web/src/views/editor/menus/export-menu.tsx
rename to apps/web/src/views/editor/menus/export/index.tsx
diff --git a/apps/web/src/views/editor/menus/floating-menu.tsx b/apps/web/src/views/editor/menus/floating/index.tsx
similarity index 100%
rename from apps/web/src/views/editor/menus/floating-menu.tsx
rename to apps/web/src/views/editor/menus/floating/index.tsx
diff --git a/apps/web/src/views/editor/menus/index.ts b/apps/web/src/views/editor/menus/index.ts
index 4e853cf..185895e 100644
--- a/apps/web/src/views/editor/menus/index.ts
+++ b/apps/web/src/views/editor/menus/index.ts
@@ -1,6 +1,6 @@
-export * from "./bubble-menu";
-export * from "./export-menu";
-export * from "./floating-menu";
-export * from "./link-preview-menu";
-export * from "./stats-menu";
-export * from "./comment-threads-menu";
+export * from "./bubble";
+export * from "./comment-threads";
+export * from "./export";
+export * from "./floating";
+export * from "./link-preview";
+export * from "./stats";
diff --git a/apps/web/src/views/editor/menus/link-preview-menu.tsx b/apps/web/src/views/editor/menus/link-preview/index.tsx
similarity index 100%
rename from apps/web/src/views/editor/menus/link-preview-menu.tsx
rename to apps/web/src/views/editor/menus/link-preview/index.tsx
diff --git a/apps/web/src/views/editor/menus/stats-menu.tsx b/apps/web/src/views/editor/menus/stats/index.tsx
similarity index 100%
rename from apps/web/src/views/editor/menus/stats-menu.tsx
rename to apps/web/src/views/editor/menus/stats/index.tsx
diff --git a/apps/web/src/views/extensions/extension-card.tsx b/apps/web/src/views/extensions/extension-card.tsx
index f1d6edf..d7f7a82 100644
--- a/apps/web/src/views/extensions/extension-card.tsx
+++ b/apps/web/src/views/extensions/extension-card.tsx
@@ -1,19 +1,20 @@
 import { ExtensionIcon } from "./extension-icon";
 import { mdiTune, mdiDownloadOutline } from "@mdi/js";
 import { Component, Show } from "solid-js";
-import { ExtensionDetails, hasPermission, useClient } from "#context";
+import { ExtensionDetails, hasPermission, useClient, useExtensions } from "#context";
 import { Card, Heading, IconButton } from "#components/primitives";
 
 interface ExtensionCardProps {
   extension: ExtensionDetails;
   installed?: boolean;
   setOpenedExtension(extension: ExtensionDetails): void;
 }
 
 const ExtensionCard: Component<ExtensionCardProps> = (props) => {
   const client = useClient();
+  const { callFunction } = useExtensions();
 
   return (
     <Card class="m-0 gap-1 flex flex-col justify-center items-center" color="contrast">
       <div class="flex items-start justify-start w-full">
         <ExtensionIcon spec={props.extension.spec} />
@@ -39,10 +40,22 @@ const ExtensionCard: Component<ExtensionCardProps> = (props) => {
                     name: props.extension.spec.name,
                     displayName: props.extension.spec.displayName,
                     permissions: props.extension.spec.permissions || []
                   }
                 });
+                const onConfigureCallback = props.extension.spec.lifecycle?.["on:configure"];
+
+                if (onConfigureCallback) {
+                  await callFunction(props.extension.spec, onConfigureCallback, {
+                    extensionId: id,
+                    token,
+                    context: () => ({
+                      config: {},
+                      spec: props.extension.spec
+                    })
+                  });
+                }
 
                 props.setOpenedExtension({ ...props.extension, config: {}, id, token });
               }
             }}
             class="m-0 my-1"
diff --git a/apps/web/src/views/git/sync-view/index.tsx b/apps/web/src/views/git/sync-view/index.tsx
index 88f4448..343990e 100644
--- a/apps/web/src/views/git/sync-view/index.tsx
+++ b/apps/web/src/views/git/sync-view/index.tsx
@@ -45,10 +45,11 @@ const extractFileName = (path: string): { fileName: string; directory: string }
   const directory = pathParts.filter(Boolean).join("/");
 
   return { fileName, directory };
 };
 const InitialSyncCard: Component = () => {
+  const { notify } = useNotifications();
   const [loading, setLoading] = createSignal(false);
   const client = useClient();
 
   return (
     <TitledCard icon={mdiSync} label="Sync">
@@ -68,11 +69,18 @@ const InitialSyncCard: Component = () => {
           color="primary"
           class="m-0 w-full"
           loading={loading()}
           onClick={async () => {
             setLoading(true);
-            await client.git.github.initialSync.mutate();
+
+            try {
+              await client.git.github.initialSync.mutate();
+              notify({ text: "Latest content pulled", type: "success" });
+            } catch (error) {
+              notify({ text: "Couldn't pull content", type: "error" });
+            }
+
             setLoading(false);
           }}
         >
           Sync now
         </Button>
@@ -106,10 +114,11 @@ const CommitCard: Component<{ changedRecords: App.GitRecord[] }> = (props) => {
               try {
                 const { status } = await client.git.github.commit.mutate({ message: message() });
 
                 if (status === "committed") {
                   notify({ text: "Changes committed", type: "success" });
+                  setMessage("");
                 } else {
                   notify({
                     text: "Pull required before committing changes",
                     type: "error"
                   });
diff --git a/apps/web/src/views/settings/api/configure-subsection.tsx b/apps/web/src/views/settings/api/configure-subsection.tsx
index fadde91..8790ad4 100644
--- a/apps/web/src/views/settings/api/configure-subsection.tsx
+++ b/apps/web/src/views/settings/api/configure-subsection.tsx
@@ -1,8 +1,8 @@
 import { ConfigureTokenAction } from "./configure-action";
 import { mdiInformation, mdiKeyChain } from "@mdi/js";
-import { Component, For, Show, createEffect, createResource } from "solid-js";
+import { Component, For, Show, createEffect, createMemo, createResource, on } from "solid-js";
 import { createStore } from "solid-js/store";
 import { InputField, TitledCard } from "#components/fragments";
 import { Select, Heading, Loader } from "#components/primitives";
 import { useClient, App } from "#context";
 
diff --git a/apps/web/src/views/settings/appearance.tsx b/apps/web/src/views/settings/appearance.tsx
index 2d07e2d..befb04a 100644
--- a/apps/web/src/views/settings/appearance.tsx
+++ b/apps/web/src/views/settings/appearance.tsx
@@ -48,26 +48,18 @@ const AppearanceSection: Component = () => {
   const { userSettings } = useAuthenticatedUserData();
   const accentColors: App.AccentColor[] = ["energy", "neon", "sublime", "sunrise", "flow"];
 
   return (
     <div class="flex justify-center flex-col items-start w-full gap-5">
-      <TitledCard icon={mdiThemeLightDark} label="UI theme">
+      <TitledCard icon={mdiThemeLightDark} label="Theme">
         <ThemePicker
           theme={userSettings()?.uiTheme || "auto"}
           setTheme={async (theme) => {
             await client.userSettings.update.mutate({ uiTheme: theme });
           }}
         />
       </TitledCard>
-      <TitledCard label="Code editor theme" icon={mdiCodeTags}>
-        <ThemePicker
-          theme={userSettings()?.codeEditorTheme || "dark"}
-          setTheme={async (theme) => {
-            await client.userSettings.update.mutate({ codeEditorTheme: theme });
-          }}
-        />
-      </TitledCard>
       <TitledCard label="Accent color" icon={mdiPaletteSwatch}>
         <div class="grid grid-cols-3 @lg:grid-cols-5 gap-4 w-full group/container">
           <For each={accentColors}>
             {(accentColor) => {
               const active = (): boolean => {
diff --git a/apps/web/src/views/settings/editor/configure-wrapper-subsection.tsx b/apps/web/src/views/settings/editor/configure-wrapper-subsection.tsx
deleted file mode 100644
index b7b4ae4..0000000
--- a/apps/web/src/views/settings/editor/configure-wrapper-subsection.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { mdiCheck, mdiInformation } from "@mdi/js";
-import { Component, createEffect, createMemo, createSignal } from "solid-js";
-import { createStore } from "solid-js/store";
-import { InputField, TitledCard } from "#components/fragments";
-import { Button, IconButton, Tooltip } from "#components/primitives";
-import { useClient, App, useNotifications } from "#context";
-import { validateKey } from "#lib/utils";
-
-interface ConfigureWrapperSubSectionProps {
-  setActionComponent(component: Component<{}> | null): void;
-  onWrapperConfigured(): void;
-}
-
-const ConfigureWrapperSubSection: Component<ConfigureWrapperSubSectionProps> = (props) => {
-  const client = useClient();
-  const { notify } = useNotifications();
-  const [loading, setLoading] = createSignal(false);
-  const [wrapperData, setWrapperData] = createStore<App.Wrapper>({
-    key: "",
-    label: ""
-  });
-  const filled = createMemo(() => {
-    return Boolean(wrapperData.label && validateKey(wrapperData.key));
-  });
-  const onClick = async (): Promise<void> => {
-    try {
-      setLoading(true);
-      await client.workspaceSettings.createWrapper.mutate(wrapperData);
-      notify({ text: "New Wrapper created", type: "success" });
-      props.onWrapperConfigured();
-      setLoading(false);
-    } catch (error) {
-      notify({ text: "Failed to create new Wrapper", type: "error" });
-      setLoading(false);
-    }
-  };
-
-  createEffect(() => {
-    setWrapperData("key", wrapperData.label.toLowerCase().replace(/\s|-/g, "_").slice(0, 20));
-  });
-  props.setActionComponent(() => {
-    return (
-      <>
-        <Button
-          color="primary"
-          class="m-0 hidden @md:flex"
-          loading={loading()}
-          disabled={!filled()}
-          onClick={onClick}
-        >
-          Create Wrapper
-        </Button>
-        <Tooltip text="Create Wrapper" wrapperClass="flex @md:hidden" class="mt-1" fixed>
-          <IconButton
-            color="primary"
-            path={mdiCheck}
-            class="m-0"
-            loading={loading()}
-            disabled={!filled()}
-            onClick={onClick}
-          />
-        </Tooltip>
-      </>
-    );
-  });
-
-  return (
-    <>
-      <TitledCard icon={mdiInformation} label="Details">
-        <InputField
-          label="Wrapper label"
-          color="contrast"
-          placeholder="Label"
-          type="text"
-          value={wrapperData.label}
-          inputProps={{ maxLength: 50 }}
-          setValue={(value) => setWrapperData("label", value)}
-        >
-          Descriptive label for the wrapper.
-        </InputField>
-        <InputField
-          label="Wrapper key"
-          color="contrast"
-          placeholder="wrapper_key"
-          type="text"
-          value={wrapperData.key}
-          inputProps={{ maxLength: 20 }}
-          setValue={(value) => setWrapperData("key", value)}
-        >
-          Key identifying the Wrapper in JSON content. Has to be unique, and can only contain
-          letters, numbers and underscores.
-        </InputField>
-      </TitledCard>
-    </>
-  );
-};
-
-export { ConfigureWrapperSubSection };
diff --git a/apps/web/src/views/settings/editor/index.tsx b/apps/web/src/views/settings/editor/index.tsx
index 443c926..e8a723c 100644
--- a/apps/web/src/views/settings/editor/index.tsx
+++ b/apps/web/src/views/settings/editor/index.tsx
@@ -1,7 +1,6 @@
 import { marks, blocks, embeds } from "./options";
-import { ConfigureWrapperSubSection } from "./configure-wrapper-subsection";
 import { SettingsSectionComponent } from "../view";
 import {
   mdiApplicationBrackets,
   mdiCodeTagsCheck,
   mdiCube,
@@ -22,78 +21,17 @@ import {
   useAuthenticatedUserData,
   useClient,
   useNotifications
 } from "#context";
 
-const WrapperDetails: Component<{
-  wrapper: App.Wrapper;
-  onEdit?(): void;
-  onDelete?(): void;
-}> = (props) => {
-  const [loading, setLoading] = createSignal(false);
-  const { notify } = useNotifications();
-  const client = useClient();
-
-  return (
-    <Card class="flex flex-col gap-0 w-full m-0" color="contrast">
-      <div class="flex items-start justify-center gap-2 w-full">
-        <Heading level={3} class="break-anywhere flex-1">
-          {props.wrapper.label || "[No name]"}
-        </Heading>
-        <Show
-          when={!props.wrapper.extension}
-          fallback={
-            <Tooltip text="Extension" class="mt-1">
-              <IconButton path={mdiPuzzle} text="soft" class="m-0" badge />
-            </Tooltip>
-          }
-        >
-          <Show when={hasPermission("manageWorkspace")}>
-            <Tooltip text="Delete" class="mt-1">
-              <IconButton
-                path={mdiTrashCan}
-                text="soft"
-                class="m-0"
-                loading={loading()}
-                onClick={async () => {
-                  try {
-                    setLoading(true);
-                    await client.workspaceSettings.deleteWrapper.mutate({
-                      key: props.wrapper.key
-                    });
-                    setLoading(false);
-                    props.onDelete?.();
-                    notify({
-                      text: "Wrapper deleted",
-                      type: "success"
-                    });
-                  } catch (error) {
-                    setLoading(false);
-                    notify({
-                      text: "Failed to delete wrapper",
-                      type: "error"
-                    });
-                  }
-                }}
-              />
-            </Tooltip>
-          </Show>
-        </Show>
-      </div>
-    </Card>
-  );
-};
 const EditorSection: SettingsSectionComponent = (props) => {
   const { notify } = useNotifications();
-  const [openedSubsection, setOpenedSubsection] = createSignal<"none" | "configure-wrapper">(
-    "none"
-  );
+  const [openedSubsection, setOpenedSubsection] = createSignal<"none">("none");
   const { workspaceSettings } = useAuthenticatedUserData();
   const [enabledMarks, setEnabledMarks] = createSignal<App.WorkspaceSettings["marks"]>([]);
   const [enabledBlocks, setEnabledBlocks] = createSignal<App.WorkspaceSettings["blocks"]>([]);
   const [enabledEmbeds, setEnabledEmbeds] = createSignal<App.WorkspaceSettings["embeds"]>([]);
-  const [wrappers, setWrappers] = createSignal<App.WorkspaceSettings["wrappers"]>([]);
   const [prettierConfig, setPrettierConfig] =
     createSignal<App.WorkspaceSettings["prettierConfig"]>("");
   const client = useClient();
   const updateMarks = debounce(() => {
     client.workspaceSettings.update.mutate({
@@ -108,27 +46,16 @@ const EditorSection: SettingsSectionComponent = (props) => {
   const updateEmbeds = debounce(() => {
     client.workspaceSettings.update.mutate({
       embeds: enabledEmbeds()
     });
   }, 350);
-  const handleNewWrapper = (): void => {
-    setOpenedSubsection("configure-wrapper");
-    props.setSubSection({
-      label: "New wrapper",
-      icon: mdiCube,
-      goBack() {
-        setOpenedSubsection("none");
-      }
-    });
-  };
 
   createEffect(() => {
     setEnabledMarks(workspaceSettings()?.marks || []);
     setEnabledBlocks(workspaceSettings()?.blocks || []);
     setEnabledEmbeds(workspaceSettings()?.embeds || []);
     setPrettierConfig(workspaceSettings()?.prettierConfig || "");
-    setWrappers(workspaceSettings()?.wrappers || []);
   });
   createEffect(
     on(openedSubsection, (openedSubsection) => {
       if (openedSubsection === "none") {
         setOpenedSubsection("none");
@@ -272,56 +199,19 @@ const EditorSection: SettingsSectionComponent = (props) => {
                 );
               }}
             </For>
           </div>
         </TitledCard>
-        <Show when={enabledBlocks().includes("wrapper")}>
-          <TitledCard
-            label="Wrappers"
-            icon={mdiCube}
-            action={
-              <Show when={hasPermission("manageWorkspace")}>
-                <>
-                  <Button color="primary" class="m-0 hidden @md:flex" onClick={handleNewWrapper}>
-                    New Wrapper
-                  </Button>
-                  <Tooltip text="New Wrapper" wrapperClass="flex @md:hidden" class="mt-1" fixed>
-                    <IconButton
-                      path={mdiPlus}
-                      class="m-0"
-                      color="primary"
-                      onClick={handleNewWrapper}
-                    />
-                  </Tooltip>
-                </>
-              </Show>
-            }
-          >
-            <div class="flex flex-col gap-2 w-full">
-              <For
-                each={wrappers()}
-                fallback={
-                  <p class="px-2 w-full text-start text-gray-500 dark:text-gray-400">
-                    No wrappers found
-                  </p>
-                }
-              >
-                {(wrapper) => {
-                  return <WrapperDetails wrapper={wrapper} />;
-                }}
-              </For>
-            </div>
-          </TitledCard>
-        </Show>
         <TitledCard label="Prettier config" icon={mdiCodeTagsCheck}>
           <p class="prose text-gray-500 dark:text-gray-400">
             Customize your Prettier config for consistent code formatting for all users of the
             workspace
           </p>
           <MiniCodeEditor
             minHeight={200}
             fileName="prettierrc.json"
+            color="contrast"
             code={JSON.stringify(JSON.parse(workspaceSettings()?.prettierConfig || "{}"), null, 2)}
             onSave={async (value) => {
               try {
                 setPrettierConfig(JSON.stringify(JSON.parse(value)));
                 await client.workspaceSettings.update.mutate({
@@ -339,18 +229,10 @@ const EditorSection: SettingsSectionComponent = (props) => {
               }
             }}
           />
         </TitledCard>
       </Match>
-      <Match when={openedSubsection() === "configure-wrapper"}>
-        <ConfigureWrapperSubSection
-          setActionComponent={props.setActionComponent}
-          onWrapperConfigured={() => {
-            setOpenedSubsection("none");
-          }}
-        />
-      </Match>
     </Switch>
   );
 };
 
 export { EditorSection };
diff --git a/apps/web/src/views/settings/editor/options.ts b/apps/web/src/views/settings/editor/options.ts
index 65e3578..85bbfa2 100644
--- a/apps/web/src/views/settings/editor/options.ts
+++ b/apps/web/src/views/settings/editor/options.ts
@@ -94,11 +94,11 @@ const blocks: Record<
     { label: "Blockquote", icon: mdiFormatQuoteClose, value: "blockquote" },
     { label: "Code Block", icon: mdiCodeTags, value: "codeBlock" },
     { label: "Image", icon: mdiImage, value: "image" },
     { label: "Table", icon: mdiTable, value: "table" },
     { label: "Horizontal Rule", icon: mdiMinus, value: "horizontalRule" },
-    { label: "Wrapper", icon: mdiCubeOutline, value: "wrapper" }
+    { label: "Element", icon: mdiCubeOutline, value: "element" }
   ]
 };
 const embeds: Array<{
   icon: string;
   label: string;
diff --git a/apps/web/src/views/settings/transformers/index.tsx b/apps/web/src/views/settings/transformers/index.tsx
index 640ba2d..eebc478 100644
--- a/apps/web/src/views/settings/transformers/index.tsx
+++ b/apps/web/src/views/settings/transformers/index.tsx
@@ -8,30 +8,30 @@ import {
   createEffect,
   createSignal,
   on,
   onCleanup
 } from "solid-js";
-import { mdiFormatListBulleted, mdiPlusCircle, mdiTrashCan, mdiTune } from "@mdi/js";
+import { mdiFormatListBulleted, mdiPlusCircle, mdiPuzzle, mdiTrashCan, mdiTune } from "@mdi/js";
 import { createStore } from "solid-js/store";
 import { TitledCard } from "#components/fragments";
 import { App, hasPermission, useClient, useNotifications } from "#context";
 import { Button, Card, Heading, IconButton, Loader, Tooltip } from "#components/primitives";
 
 interface TransformerDetailsProps {
-  transformer: App.Transformer & { inUse?: boolean };
+  transformer: App.Transformer & { inUse?: boolean; extension?: boolean };
   onEdit?(): void;
   onDelete?(): void;
 }
 
 const useTransformers = (): {
   loading: Accessor<boolean>;
-  transformers(): Array<App.Transformer & { inUse?: boolean }>;
+  transformers(): Array<App.Transformer & { inUse?: boolean; extension?: boolean }>;
 } => {
   const client = useClient();
   const [loading, setLoading] = createSignal(false);
   const [state, setState] = createStore<{
-    transformers: Array<App.Transformer>;
+    transformers: Array<App.Transformer & { inUse?: boolean; extension?: boolean }>;
   }>({
     transformers: []
   });
   const loadData = async (): Promise<void> => {
     setLoading(true);
@@ -70,29 +70,38 @@ const TransformerDetails: Component<TransformerDetailsProps> = (props) => {
   return (
     <Card color="contrast" class="relative flex m-0 w-full gap-1 justify-center items-start">
       <Heading level={2} class="break-anywhere flex-1">
         {props.transformer.label}
       </Heading>
-      <Show when={hasPermission("manageWorkspace")}>
-        <div class="flex gap-2">
-          <Tooltip text="Delete" class="mt-1" enabled={!props.transformer.inUse}>
-            <IconButton
-              path={mdiTrashCan}
-              loading={loading()}
-              disabled={props.transformer.inUse}
-              class="m-0"
-              text="soft"
-              onClick={async () => {
-                setLoading(true);
-                await client.transformers.delete.mutate({ id: props.transformer.id });
-                setLoading(false);
-                props.onDelete?.();
-                notify({ text: "Transformer deleted", type: "success" });
-              }}
-            />
+      <Show
+        when={!props.transformer.extension}
+        fallback={
+          <Tooltip text="Extension" class="mt-1">
+            <IconButton path={mdiPuzzle} text="soft" class="m-0" badge />
           </Tooltip>
-        </div>
+        }
+      >
+        <Show when={hasPermission("manageWorkspace")}>
+          <div class="flex gap-2">
+            <Tooltip text="Delete" class="mt-1" enabled={!props.transformer.inUse}>
+              <IconButton
+                path={mdiTrashCan}
+                loading={loading()}
+                disabled={props.transformer.inUse}
+                class="m-0"
+                text="soft"
+                onClick={async () => {
+                  setLoading(true);
+                  await client.transformers.delete.mutate({ id: props.transformer.id });
+                  setLoading(false);
+                  props.onDelete?.();
+                  notify({ text: "Transformer deleted", type: "success" });
+                }}
+              />
+            </Tooltip>
+          </div>
+        </Show>
       </Show>
     </Card>
   );
 };
 const TransformersSection: SettingsSectionComponent = (props) => {
diff --git a/apps/web/src/views/settings/webhooks/configure-webhook-subsection.tsx b/apps/web/src/views/settings/webhooks/configure-webhook-subsection.tsx
index 099c94b..d60002d 100644
--- a/apps/web/src/views/settings/webhooks/configure-webhook-subsection.tsx
+++ b/apps/web/src/views/settings/webhooks/configure-webhook-subsection.tsx
@@ -17,11 +17,11 @@ const ConfigureWebhookSubsection: Component<ConfigureWebhookSubsectionProps> = (
   const client = useClient();
   const { notify } = useNotifications();
   const [loading, setLoading] = createSignal(false);
   const [webhookData, setWebhookData] = createStore<Omit<App.Webhook, "id">>({
     description: "",
-    event: "" as App.WebhookEvent,
+    event: "" as App.WebhookEventName,
     name: "",
     url: ""
   });
   const [editedWebhookData] = createResource(() => {
     if (!props.editedWebhookId) return null;
@@ -147,11 +147,11 @@ const ConfigureWebhookSubsection: Component<ConfigureWebhookSubsectionProps> = (
           color="contrast"
           type="select"
           options={webhookEvents}
           value={webhookData.event || ""}
           setValue={(value) => {
-            setWebhookData("event", value as App.WebhookEvent);
+            setWebhookData("event", value as App.WebhookEventName);
           }}
         >
           Event for which the Webhook should be called
         </InputField>
         <Show when={webhookData.event.startsWith("contentPiece")}>
diff --git a/apps/web/src/views/settings/webhooks/events.ts b/apps/web/src/views/settings/webhooks/events.ts
index b14fcac..b3dcac1 100644
--- a/apps/web/src/views/settings/webhooks/events.ts
+++ b/apps/web/src/views/settings/webhooks/events.ts
@@ -1,8 +1,8 @@
 import { App } from "#context";
 
-const webhookEvents: Array<{ label: string; value: App.WebhookEvent }> = [
+const webhookEvents: Array<{ label: string; value: App.WebhookEventName }> = [
   { label: "Content piece updated", value: "contentPieceUpdated" },
   { label: "New content piece added", value: "contentPieceAdded" },
   { label: "Content piece removed", value: "contentPieceRemoved" },
   { label: "New content group added", value: "contentGroupAdded" },
   { label: "Content group removed", value: "contentGroupRemoved" },
diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json
index ed70de8..e71ea18 100644
--- a/apps/web/tsconfig.json
+++ b/apps/web/tsconfig.json
@@ -7,11 +7,11 @@
     "allowSyntheticDefaultImports": true,
     "esModuleInterop": true,
     "resolveJsonModule": true,
     "jsx": "preserve",
     "jsxImportSource": "solid-js",
-    "types": ["vite/client", "mdx", "@vrite/extensions"],
+    "types": ["vite/client", "@vrite/extensions"],
     "baseUrl": ".",
     "paths": {
       "#*": ["./src/*", "../../packages/backend/src/*"]
     }
   }
diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts
index 8c36e89..a6f2b27 100644
--- a/apps/web/vite.config.ts
+++ b/apps/web/vite.config.ts
@@ -4,10 +4,11 @@ import tsconfigPaths from "vite-tsconfig-paths";
 import unocss from "unocss/vite";
 
 export default defineConfig(async ({ mode }) => {
   const plugins: PluginOption[] = [tsconfigPaths(), unocss(), solidPlugin()];
   const env = loadEnv(mode, process.cwd(), "PUBLIC_");
+  const proxyTarget = env.PUBLIC_APP_URL;
 
   if (mode === "development") {
     // Only transform index.html in dev mode - in production Handlebars will do this
     plugins.push({
       name: "html-transform",
@@ -23,18 +24,17 @@ export default defineConfig(async ({ mode }) => {
     logLevel: "info",
     envPrefix: "PUBLIC_",
     server: {
       proxy: {
         "/api": {
-          target: "http://localhost:3333",
+          target: proxyTarget,
           ws: true
         },
-        "/session": { target: "http://localhost:3333", ws: true },
-        "/login": { target: "http://localhost:3333", ws: true },
-        "/github": { target: "http://localhost:3333", ws: true },
-        "/proxy": { target: "http://localhost:3333", ws: true },
-        "/upload": { target: "http://localhost:3333", ws: true }
+        "/session": { target: proxyTarget, ws: true },
+        "/login": { target: proxyTarget, ws: true },
+        "/github": { target: proxyTarget, ws: true },
+        "/upload": { target: proxyTarget, ws: true }
       }
     },
     build: {
       minify: "terser",
       target: "esnext"
diff --git a/package.json b/package.json
index 5409d3d..a4a47fd 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
 {
   "name": "vrite",
-  "version": "0.2.1",
+  "version": "0.3.0",
   "license": "AGPL-3.0-only",
   "private": true,
   "workspaces": [
     "apps/*",
     "packages/*"
diff --git a/packages/backend/src/database/comments.ts b/packages/backend/src/database/comments.ts
index cae11ff..5471f8f 100644
--- a/packages/backend/src/database/comments.ts
+++ b/packages/backend/src/database/comments.ts
@@ -1,9 +1,9 @@
-import { Collection, Db, ObjectId } from "mongodb";
-import { UnderscoreID, zodId } from "#lib/mongo";
 import { Profile, profile } from "./users";
+import { Collection, Db, ObjectId } from "mongodb";
 import { z } from "zod";
+import { UnderscoreID, zodId } from "#lib/mongo";
 
 const comment = z.object({
   id: zodId(),
   memberId: zodId(),
   threadId: zodId(),
diff --git a/packages/backend/src/database/index.ts b/packages/backend/src/database/index.ts
index 942ad0a..358aa2e 100644
--- a/packages/backend/src/database/index.ts
+++ b/packages/backend/src/database/index.ts
@@ -15,8 +15,7 @@ export * from "./comments";
 export * from "./content-piece-variants";
 export * from "./content-variants";
 export * from "./variants";
 export * from "./content-groups";
 export * from "./git-data";
-export * from "./versions";
 export * from "./variants";
 export * from "./transformers";
diff --git a/packages/backend/src/database/transformers.ts b/packages/backend/src/database/transformers.ts
index b4ba1a8..a6137fa 100644
--- a/packages/backend/src/database/transformers.ts
+++ b/packages/backend/src/database/transformers.ts
@@ -14,10 +14,11 @@ interface Transformer<ID extends string | ObjectId = string>
   extends Omit<z.infer<typeof transformer>, "id"> {
   id: ID;
 }
 interface FullTransformer<ID extends string | ObjectId = string> extends Transformer<ID> {
   workspaceId: ID;
+  extensionId?: ID;
 }
 
 const getTransformersCollection = (db: Db): Collection<UnderscoreID<FullTransformer<ObjectId>>> => {
   return db.collection("transformers");
 };
diff --git a/packages/backend/src/database/users.ts b/packages/backend/src/database/users.ts
index 9fadc04..469547d 100644
--- a/packages/backend/src/database/users.ts
+++ b/packages/backend/src/database/users.ts
@@ -3,11 +3,11 @@ import { z } from "zod";
 import { UnderscoreID, zodId } from "#lib/mongo";
 
 const user = z.object({
   id: zodId(),
   username: z.string().min(1).max(20),
-  email: z.string().email(),
+  email: z.string().email().max(320),
   external: z
     .object({
       github: z
         .object({
           id: z.string()
diff --git a/packages/backend/src/database/versions.ts b/packages/backend/src/database/versions.ts
deleted file mode 100644
index be82d75..0000000
--- a/packages/backend/src/database/versions.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { ContentPiece, contentPiece } from "./content-pieces";
-import { ContentPieceVariant, contentPieceVariant } from "./content-piece-variants";
-import { Binary, Collection, Db, ObjectId } from "mongodb";
-import { z } from "zod";
-import { UnderscoreID, zodId } from "#lib/mongo";
-
-const version = z.object({
-  id: zodId(),
-  name: z.string(),
-  date: z.string(),
-  content: z.any().optional(),
-  contentPiece: contentPieceVariant.omit({ variantId: true, contentPieceId: true, id: true }),
-  contentPieceId: zodId(),
-  variantId: zodId().optional()
-});
-
-interface Version<ID extends string | ObjectId = string>
-  extends Omit<
-    z.infer<typeof version>,
-    "id" | "date" | "contentPieceId" | "variantId" | "content" | "contentPiece"
-  > {
-  date: ID extends string ? string : Date;
-  content?: Binary;
-  contentPiece: Omit<ContentPieceVariant<ID>, "id" | "variantId" | "contentPieceId">;
-  contentPieceId: ID;
-  variantId?: ID;
-  id: ID;
-}
-interface FullVersion<ID extends string | ObjectId = string> extends Version<ID> {
-  workspaceId: ID;
-}
-
-const getVersionsCollection = (db: Db): Collection<UnderscoreID<FullVersion<ObjectId>>> => {
-  return db.collection("contents");
-};
-
-export { getVersionsCollection, version };
-export type { Version, FullVersion };
diff --git a/packages/backend/src/database/webhooks.ts b/packages/backend/src/database/webhooks.ts
index 59767b5..d9c38f9 100644
--- a/packages/backend/src/database/webhooks.ts
+++ b/packages/backend/src/database/webhooks.ts
@@ -11,24 +11,24 @@ const contentGroupEvents = [
   "contentGroupAdded",
   "contentGroupRemoved",
   "contentGroupMoved"
 ] as const;
 const memberEvents = ["memberInvited", "memberAdded", "memberRemoved"] as const;
-const webhookEvent = z.enum([...contentPieceEvents, ...contentGroupEvents, ...memberEvents]);
+const webhookEventName = z.enum([...contentPieceEvents, ...contentGroupEvents, ...memberEvents]);
 const webhookMetadata = z.object({
   contentGroupId: zodId()
 });
 const webhook = z.object({
   id: zodId(),
   url: z.string(),
   name: z.string().min(1).max(50),
   description: z.string().optional(),
   metadata: webhookMetadata.optional(),
-  event: webhookEvent
+  event: webhookEventName
 });
 
-type WebhookEvent = z.infer<typeof webhookEvent>;
+type WebhookEventName = z.infer<typeof webhookEventName>;
 type WebhookMetadata<ID extends string | ObjectId = string> = {
   contentGroupId: ID;
 };
 
 interface Webhook<ID extends string | ObjectId = string>
@@ -45,12 +45,12 @@ const getWebhooksCollection = (db: Db): Collection<UnderscoreID<FullWebhook<Obje
   return db.collection("webhooks");
 };
 
 export {
   webhook,
-  webhookEvent,
+  webhookEventName,
   getWebhooksCollection,
   contentPieceEvents,
   contentGroupEvents,
   memberEvents
 };
-export type { WebhookEvent, Webhook, FullWebhook };
+export type { WebhookEventName, Webhook, FullWebhook };
diff --git a/packages/backend/src/database/workspace-memberships.ts b/packages/backend/src/database/workspace-memberships.ts
index e6bdc7b..8fdaaa5 100644
--- a/packages/backend/src/database/workspace-memberships.ts
+++ b/packages/backend/src/database/workspace-memberships.ts
@@ -4,11 +4,11 @@ import { UnderscoreID, zodId } from "#lib/mongo";
 
 const workspaceMembership = z.object({
   id: zodId(),
   userId: zodId().optional(),
   roleId: zodId(),
-  email: z.string().email().optional(),
+  email: z.string().email().max(320).optional(),
   name: z.string().max(50).optional()
 });
 const workspaceInviteCodeDetails = z.object({
   inviteVerificationCode: z.string().optional(),
   inviteVerificationCodeSalt: z.string().optional(),
diff --git a/packages/backend/src/database/workspace-settings.ts b/packages/backend/src/database/workspace-settings.ts
index c6df31d..4d5ea9f 100644
--- a/packages/backend/src/database/workspace-settings.ts
+++ b/packages/backend/src/database/workspace-settings.ts
@@ -31,19 +31,10 @@ const metadataSettings = z
   .object({
     canonicalLinkPattern: z.string(),
     enabledFields: z.array(metadataField).optional()
   })
   .partial();
-const wrapper = z.object({
-  label: z.string().min(1).max(50),
-  key: z
-    .string()
-    .min(1)
-    .max(20)
-    .regex(/^[a-z0-9_]*$/),
-  extension: z.boolean().optional()
-});
 const marks = [
   "bold",
   "italic",
   "strike",
   "code",
@@ -65,28 +56,25 @@ const blocks = [
   "blockquote",
   "codeBlock",
   "horizontalRule",
   "image",
   "table",
-  "wrapper"
+  "element"
 ] as const;
 const embeds = ["codepen", "codesandbox", "youtube"] as const;
 const workspaceSettings = z.object({
   id: zodId(),
   prettierConfig: z.string(),
   metadata: metadataSettings.optional(),
   marks: z.array(z.enum(marks)),
   blocks: z.array(z.enum(blocks)),
-  embeds: z.array(z.enum(embeds)),
-  wrappers: z.array(wrapper).optional()
+  embeds: z.array(z.enum(embeds))
 });
 
-interface Wrapper extends z.infer<typeof wrapper> {}
 interface WorkspaceSettings<ID extends string | ObjectId = string>
-  extends Omit<z.infer<typeof workspaceSettings>, "id" | "wrappers"> {
+  extends Omit<z.infer<typeof workspaceSettings>, "id"> {
   id: ID;
-  wrappers?: Wrapper[];
 }
 interface FullWorkspaceSettings<ID extends string | ObjectId = string>
   extends WorkspaceSettings<ID> {
   workspaceId: ID;
 }
@@ -105,9 +93,8 @@ export {
   marks,
   blocks,
   embeds,
   workspaceSettings,
   metadataSettings,
-  wrapper,
   getWorkspaceSettingsCollection
 };
-export type { MetadataField, MetadataSettings, WorkspaceSettings, FullWorkspaceSettings, Wrapper };
+export type { MetadataField, MetadataSettings, WorkspaceSettings, FullWorkspaceSettings };
diff --git a/packages/backend/src/env.ts b/packages/backend/src/env.ts
index 58bb051..ccd111f 100644
--- a/packages/backend/src/env.ts
+++ b/packages/backend/src/env.ts
@@ -1,6 +1,6 @@
-import { optional, z } from "zod";
+import { z } from "zod";
 
 const envSchema = z.object({
   NODE_ENV: z.string(),
   SECRET: z.string(),
   PORT: z.number(),
diff --git a/packages/backend/src/events/comment.ts b/packages/backend/src/events/comment.ts
new file mode 100644
index 0000000..3db7f94
--- /dev/null
+++ b/packages/backend/src/events/comment.ts
@@ -0,0 +1,34 @@
+import { Observable } from "@trpc/server/observable";
+import { Comment, CommentThread, CommentMember } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type CommentEvent =
+  | { action: "createThread"; data: CommentThread }
+  | { action: "resolveThread"; data: Pick<CommentThread, "id" | "fragment" | "resolved"> }
+  | { action: "deleteThread"; data: Pick<CommentThread, "id" | "fragment"> }
+  | {
+      action: "createComment";
+      data: Omit<Comment, "memberId"> & { member: CommentMember | null };
+    }
+  | {
+      action: "updateComment";
+      data: Pick<Comment, "id" | "content">;
+    }
+  | {
+      action: "deleteComment";
+      data: Pick<Comment, "id">;
+    };
+
+const publishCommentEvent = createEventPublisher<CommentEvent>((contentPieceId) => {
+  return `comments:${contentPieceId}`;
+});
+const subscribeToCommentEvents = (
+  ctx: Context,
+  contentPieceId: string
+): Observable<CommentEvent, unknown> => {
+  return createEventSubscription<CommentEvent>(ctx, `comments:${contentPieceId}`);
+};
+
+export { publishCommentEvent, subscribeToCommentEvents };
+export type { CommentEvent };
diff --git a/packages/backend/src/events/content-group.ts b/packages/backend/src/events/content-group.ts
new file mode 100644
index 0000000..e0ac202
--- /dev/null
+++ b/packages/backend/src/events/content-group.ts
@@ -0,0 +1,30 @@
+import { Observable } from "@trpc/server/observable";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { ContentGroup } from "#database";
+
+type ContentGroupEvent =
+  | {
+      action: "create";
+      data: ContentGroup;
+    }
+  | {
+      action: "update";
+      data: Partial<ContentGroup> & { id: string };
+    }
+  | { action: "delete"; data: { id: string } }
+  | { action: "move"; data: ContentGroup }
+  | { action: "reorder"; data: { id: string; index: number } };
+
+const publishContentGroupEvent = createEventPublisher<ContentGroupEvent>(
+  (workspaceId) => `contentGroups:${workspaceId}`
+);
+const subscribeToContentGroupEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<ContentGroupEvent, unknown> => {
+  return createEventSubscription<ContentGroupEvent>(ctx, `contentGroups:${workspaceId}`);
+};
+
+export { publishContentGroupEvent, subscribeToContentGroupEvents };
+export type { ContentGroupEvent };
diff --git a/packages/backend/src/events/content-piece.ts b/packages/backend/src/events/content-piece.ts
new file mode 100644
index 0000000..8a03e17
--- /dev/null
+++ b/packages/backend/src/events/content-piece.ts
@@ -0,0 +1,36 @@
+import { Observable } from "@trpc/server/observable";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { FullContentPieceWithAdditionalData } from "#database";
+
+type ContentPieceEvent =
+  | { action: "delete"; userId: string; data: { id: string } }
+  | { action: "create"; userId: string; data: FullContentPieceWithAdditionalData }
+  | {
+      action: "update";
+      userId: string;
+      variantId?: string;
+      data: Partial<FullContentPieceWithAdditionalData> & { id: string };
+    }
+  | {
+      action: "move";
+      userId: string;
+      data: {
+        contentPiece: FullContentPieceWithAdditionalData;
+        nextReferenceId?: string;
+        previousReferenceId?: string;
+      };
+    };
+
+const publishContentPieceEvent = createEventPublisher<ContentPieceEvent>((contentGroupId) => {
+  return `contentPieces:${contentGroupId}`;
+});
+const subscribeToContentPieceEvents = (
+  ctx: Context,
+  contentGroupId: string
+): Observable<ContentPieceEvent, unknown> => {
+  return createEventSubscription<ContentPieceEvent>(ctx, `contentPieces:${contentGroupId}`);
+};
+
+export { publishContentPieceEvent, subscribeToContentPieceEvents };
+export type { ContentPieceEvent };
diff --git a/packages/backend/src/events/extension.ts b/packages/backend/src/events/extension.ts
new file mode 100644
index 0000000..1f7702f
--- /dev/null
+++ b/packages/backend/src/events/extension.ts
@@ -0,0 +1,22 @@
+import { Observable } from "@trpc/server/observable";
+import { ContextObject, Extension } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type ExtensionEvent =
+  | { action: "delete"; data: { id: string } }
+  | { action: "create"; data: Extension & { id: string } }
+  | { action: "update"; data: { id: string; config: ContextObject } };
+
+const publishExtensionEvent = createEventPublisher<ExtensionEvent>((workspaceId) => {
+  return `extensions:${workspaceId}`;
+});
+const subscribeToExtensionEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<ExtensionEvent, unknown> => {
+  return createEventSubscription<ExtensionEvent>(ctx, `extensions:${workspaceId}`);
+};
+
+export { publishExtensionEvent, subscribeToExtensionEvents };
+export type { ExtensionEvent };
diff --git a/packages/backend/src/events/git-data.ts b/packages/backend/src/events/git-data.ts
new file mode 100644
index 0000000..dea3729
--- /dev/null
+++ b/packages/backend/src/events/git-data.ts
@@ -0,0 +1,31 @@
+import { Observable } from "@trpc/server/observable";
+import { GitData } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type GitDataEvent =
+  | {
+      action: "configure";
+      data: GitData;
+    }
+  | {
+      action: "update";
+      data: Partial<GitData>;
+    }
+  | {
+      action: "reset";
+      data: {};
+    };
+
+const publishGitDataEvent = createEventPublisher<GitDataEvent>((workspaceId) => {
+  return `gitData:${workspaceId}`;
+});
+const subscribeToGitDataEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<GitDataEvent, unknown> => {
+  return createEventSubscription<GitDataEvent>(ctx, `gitData:${workspaceId}`);
+};
+
+export { publishGitDataEvent, subscribeToGitDataEvents };
+export type { GitDataEvent };
diff --git a/packages/backend/src/events/index.ts b/packages/backend/src/events/index.ts
new file mode 100644
index 0000000..6dbfab6
--- /dev/null
+++ b/packages/backend/src/events/index.ts
@@ -0,0 +1,16 @@
+export * from "./comment";
+export * from "./content-group";
+export * from "./content-piece";
+export * from "./extension";
+export * from "./tag";
+export * from "./token";
+export * from "./transformer";
+export * from "./user-settings";
+export * from "./user";
+export * from "./variant";
+export * from "./workspace-membership";
+export * from "./webhook";
+export * from "./workspace-settings";
+export * from "./workspace";
+export * from "./git-data";
+export * from "./role";
diff --git a/packages/backend/src/events/role.ts b/packages/backend/src/events/role.ts
new file mode 100644
index 0000000..5d00351
--- /dev/null
+++ b/packages/backend/src/events/role.ts
@@ -0,0 +1,23 @@
+import { Observable } from "@trpc/server/observable";
+import { Role } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type RoleEvent =
+  | {
+      action: "create";
+      data: Role;
+    }
+  | { action: "update"; data: Partial<Role> & { id: string } }
+  | { action: "delete"; data: { id: string; newRole: Role } };
+
+const publishRoleEvent = createEventPublisher((workspaceId) => `roles:${workspaceId}`);
+const subscribeToRoleEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<RoleEvent, unknown> => {
+  return createEventSubscription<RoleEvent>(ctx, `roles:${workspaceId}`);
+};
+
+export { publishRoleEvent, subscribeToRoleEvents };
+export type { RoleEvent };
diff --git a/packages/backend/src/events/tag.ts b/packages/backend/src/events/tag.ts
new file mode 100644
index 0000000..e9c5742
--- /dev/null
+++ b/packages/backend/src/events/tag.ts
@@ -0,0 +1,20 @@
+import { Observable } from "@trpc/server/observable";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { Tag } from "#database";
+
+type TagEvent =
+  | { action: "create"; data: Tag }
+  | { action: "update"; data: Partial<Tag> & { id: string } }
+  | {
+      action: "delete";
+      data: { id: string };
+    };
+
+const publishTagEvent = createEventPublisher<TagEvent>((workspaceId) => `tags:${workspaceId}`);
+const subscribeToTagEvents = (ctx: Context, workspaceId: string): Observable<TagEvent, unknown> => {
+  return createEventSubscription<TagEvent>(ctx, `tags:${workspaceId}`);
+};
+
+export { publishTagEvent, subscribeToTagEvents };
+export type { TagEvent };
diff --git a/packages/backend/src/events/token.ts b/packages/backend/src/events/token.ts
new file mode 100644
index 0000000..5c67fe2
--- /dev/null
+++ b/packages/backend/src/events/token.ts
@@ -0,0 +1,25 @@
+import { Observable } from "@trpc/server/observable";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { Token } from "#database";
+
+type TokenEvent =
+  | {
+      action: "create";
+      data: Token;
+    }
+  | { action: "update"; data: Partial<Token> & { id: string } }
+  | { action: "delete"; data: { id: string } };
+
+const publishTokenEvent = createEventPublisher<TokenEvent>(
+  (workspaceId) => `tokens:${workspaceId}`
+);
+const subscribeToTokenEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<TokenEvent, unknown> => {
+  return createEventSubscription<TokenEvent>(ctx, `tokens:${workspaceId}`);
+};
+
+export { publishTokenEvent, subscribeToTokenEvents };
+export type { TokenEvent };
diff --git a/packages/backend/src/events/transformer.ts b/packages/backend/src/events/transformer.ts
new file mode 100644
index 0000000..8f6ad00
--- /dev/null
+++ b/packages/backend/src/events/transformer.ts
@@ -0,0 +1,27 @@
+import { Observable } from "@trpc/server/observable";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { Transformer } from "#database";
+
+type TransformerEvent =
+  | {
+      action: "create";
+      data: Transformer & { id: string };
+    }
+  | {
+      action: "delete";
+      data: { id: string };
+    };
+
+const publishTransformerEvent = createEventPublisher<TransformerEvent>(
+  (workspaceId) => `transformers:${workspaceId}`
+);
+const subscribeToTransformerEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<TransformerEvent, unknown> => {
+  return createEventSubscription<TransformerEvent>(ctx, `transformers:${workspaceId}`);
+};
+
+export { publishTransformerEvent, subscribeToTransformerEvents };
+export type { TransformerEvent };
diff --git a/packages/backend/src/events/user-settings.ts b/packages/backend/src/events/user-settings.ts
new file mode 100644
index 0000000..47b0564
--- /dev/null
+++ b/packages/backend/src/events/user-settings.ts
@@ -0,0 +1,19 @@
+import { Observable } from "@trpc/server/observable";
+import { AppearanceSettings } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type UserSettingsEvent = { action: "update"; data: Partial<AppearanceSettings> };
+
+const publishUserSettingsEvent = createEventPublisher<UserSettingsEvent>(
+  (userId) => `userSettings:${userId}`
+);
+const subscribeToUserSettingsEvents = (
+  ctx: Context,
+  userId: string
+): Observable<UserSettingsEvent, unknown> => {
+  return createEventSubscription<UserSettingsEvent>(ctx, `userSettings:${userId}`);
+};
+
+export { publishUserSettingsEvent, subscribeToUserSettingsEvents };
+export type { UserSettingsEvent };
diff --git a/packages/backend/src/events/user.ts b/packages/backend/src/events/user.ts
new file mode 100644
index 0000000..10432cd
--- /dev/null
+++ b/packages/backend/src/events/user.ts
@@ -0,0 +1,17 @@
+import { Observable } from "@trpc/server/observable";
+import { VerificationDetails, Profile } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type UserEvent = {
+  action: "update";
+  data: Partial<Profile> & { id: string } & Partial<VerificationDetails>;
+};
+
+const publishUserEvent = createEventPublisher<UserEvent>((userId: string) => `user:${userId}`);
+const subscribeToUserEvents = (ctx: Context, userId: string): Observable<UserEvent, unknown> => {
+  return createEventSubscription<UserEvent>(ctx, `user:${userId}`);
+};
+
+export { publishUserEvent, subscribeToUserEvents };
+export type { UserEvent };
diff --git a/packages/backend/src/events/variant.ts b/packages/backend/src/events/variant.ts
new file mode 100644
index 0000000..40713eb
--- /dev/null
+++ b/packages/backend/src/events/variant.ts
@@ -0,0 +1,31 @@
+import { Observable } from "@trpc/server/observable";
+import { Variant } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type VariantEvent =
+  | {
+      action: "create";
+      data: Variant & { id: string };
+    }
+  | {
+      action: "update";
+      data: Partial<Variant> & { id: string };
+    }
+  | {
+      action: "delete";
+      data: { id: string };
+    };
+
+const publishVariantEvent = createEventPublisher<VariantEvent>(
+  (workspaceId) => `variants:${workspaceId}`
+);
+const subscribeToVariantEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<VariantEvent, unknown> => {
+  return createEventSubscription<VariantEvent>(ctx, `variants:${workspaceId}`);
+};
+
+export { publishVariantEvent, subscribeToVariantEvents };
+export type { VariantEvent };
diff --git a/packages/backend/src/events/webhook.ts b/packages/backend/src/events/webhook.ts
new file mode 100644
index 0000000..97d3de8
--- /dev/null
+++ b/packages/backend/src/events/webhook.ts
@@ -0,0 +1,31 @@
+import { Observable } from "@trpc/server/observable";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { Webhook } from "#database";
+
+type WebhookEvent =
+  | {
+      action: "create";
+      data: Webhook & { id: string };
+    }
+  | {
+      action: "update";
+      data: Partial<Webhook> & { id: string };
+    }
+  | {
+      action: "delete";
+      data: { id: string };
+    };
+
+const publishWebhookEvent = createEventPublisher<WebhookEvent>((workspaceId) => {
+  return `webhooks:${workspaceId}`;
+});
+const subscribeToWebhookEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<WebhookEvent, unknown> => {
+  return createEventSubscription<WebhookEvent>(ctx, `webhooks:${workspaceId}`);
+};
+
+export { publishWebhookEvent, subscribeToWebhookEvents };
+export type { WebhookEvent };
diff --git a/packages/backend/src/events/workspace-membership.ts b/packages/backend/src/events/workspace-membership.ts
new file mode 100644
index 0000000..d547b45
--- /dev/null
+++ b/packages/backend/src/events/workspace-membership.ts
@@ -0,0 +1,41 @@
+import { Observable } from "@trpc/server/observable";
+import { Role, WorkspaceMembership } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type WorkspaceMembershipEvent =
+  | { action: "create"; data: { id: string; pendingInvite: boolean } & WorkspaceMembership }
+  | {
+      action: "update";
+      data: {
+        id: string;
+        userId: string;
+        role?: Role;
+        pendingInvite?: boolean;
+        profile?: {
+          fullName?: string;
+          username?: string;
+          avatar?: string;
+        };
+      } & Partial<WorkspaceMembership>;
+    }
+  | {
+      action: "delete";
+      data: { id: string; userId: string };
+    };
+
+const publishWorkspaceMembershipEvent = createEventPublisher<WorkspaceMembershipEvent>(
+  (workspaceId: string) => `workspaceMemberships:${workspaceId}`
+);
+const subscribeToWorkspaceMembershipEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<WorkspaceMembershipEvent, unknown> => {
+  return createEventSubscription<WorkspaceMembershipEvent>(
+    ctx,
+    `workspaceMemberships:${workspaceId}`
+  );
+};
+
+export { publishWorkspaceMembershipEvent, subscribeToWorkspaceMembershipEvents };
+export type { WorkspaceMembershipEvent };
diff --git a/packages/backend/src/events/workspace-settings.ts b/packages/backend/src/events/workspace-settings.ts
new file mode 100644
index 0000000..0f3cafe
--- /dev/null
+++ b/packages/backend/src/events/workspace-settings.ts
@@ -0,0 +1,24 @@
+import { Observable } from "@trpc/server/observable";
+import { WorkspaceSettings } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type WorkspaceSettingsEvent = {
+  action: "update";
+  data: Partial<Omit<WorkspaceSettings, "id">>;
+};
+
+const publishWorkspaceSettingsEvent = createEventPublisher<WorkspaceSettingsEvent>(
+  (workspaceId) => {
+    return `workspaceSettings:${workspaceId}`;
+  }
+);
+const subscribeToWorkspaceSettingsEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<WorkspaceSettingsEvent, unknown> => {
+  return createEventSubscription<WorkspaceSettingsEvent>(ctx, `workspaceSettings:${workspaceId}`);
+};
+
+export { publishWorkspaceSettingsEvent, subscribeToWorkspaceSettingsEvents };
+export type { WorkspaceSettingsEvent };
diff --git a/packages/backend/src/events/workspace.ts b/packages/backend/src/events/workspace.ts
new file mode 100644
index 0000000..71e2d39
--- /dev/null
+++ b/packages/backend/src/events/workspace.ts
@@ -0,0 +1,21 @@
+import { Observable } from "@trpc/server/observable";
+import { Workspace } from "#database";
+import { Context } from "#lib/context";
+import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+
+type WorkspaceEvent =
+  | { action: "update"; data: Partial<Workspace> & { id: string } }
+  | { action: "delete"; data: { id: string } };
+
+const publishWorkspaceEvent = createEventPublisher<WorkspaceEvent>((workspaceId) => {
+  return `workspace:${workspaceId}`;
+});
+const subscribeToWorkspaceEvents = (
+  ctx: Context,
+  workspaceId: string
+): Observable<WorkspaceEvent, unknown> => {
+  return createEventSubscription<WorkspaceEvent>(ctx, `workspace:${workspaceId}`);
+};
+
+export { publishWorkspaceEvent, subscribeToWorkspaceEvents };
+export type { WorkspaceEvent };
diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts
index 2fc03de..3831da5 100644
--- a/packages/backend/src/index.ts
+++ b/packages/backend/src/index.ts
@@ -1,5 +1,6 @@
-export * from "./server";
 export * from "./lib";
 export * from "./plugins";
-export * from "./routes";
 export * from "./database";
+export * from "./events";
+export * from "./routes";
+export * from "./server";
diff --git a/packages/backend/src/lib/auth.ts b/packages/backend/src/lib/auth.ts
index c79e430..4d44b07 100644
--- a/packages/backend/src/lib/auth.ts
+++ b/packages/backend/src/lib/auth.ts
@@ -1,9 +1,9 @@
 import { Context } from "./context";
 import { SessionData, getSessionId } from "./session";
 import { verifyValue } from "./hash";
-import { TokenPermission, getTokensCollection } from "#database/tokens";
+import { TokenPermission, getTokensCollection } from "#database";
 
 interface TokenData {
   permissions: TokenPermission[];
   userId: string;
   workspaceId: string;
diff --git a/packages/backend/src/lib/context.ts b/packages/backend/src/lib/context.ts
index a1ebde0..34ef61b 100644
--- a/packages/backend/src/lib/context.ts
+++ b/packages/backend/src/lib/context.ts
@@ -1,26 +1,37 @@
 import { CreateFastifyContextOptions } from "@trpc/server/adapters/fastify";
 import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
 import { Db } from "mongodb";
 
-interface Context {
+interface FastifyContext {
   fastify: FastifyInstance;
   req: FastifyRequest;
   res: FastifyReply;
+}
+interface Context extends FastifyContext {
   db: Db;
 }
 
+const createFastifyContext = (
+  { req, res }: CreateFastifyContextOptions,
+  fastify: FastifyInstance
+): FastifyContext => {
+  return { req, res, fastify };
+};
 const createContext = (
   { req, res }: CreateFastifyContextOptions,
   fastify: FastifyInstance
 ): Context => {
   const { db } = fastify.mongo;
 
   if (!db) {
     throw new Error("Database not connected");
   }
 
-  return { req, res, db, fastify };
+  return {
+    ...createFastifyContext({ req, res }, fastify),
+    db
+  };
 };
 
-export { createContext };
-export type { Context };
+export { createContext, createFastifyContext };
+export type { FastifyContext, Context };
diff --git a/packages/backend/src/lib/git-sync/github/index.ts b/packages/backend/src/lib/git-sync/github/index.ts
new file mode 100644
index 0000000..5077d2a
--- /dev/null
+++ b/packages/backend/src/lib/git-sync/github/index.ts
@@ -0,0 +1,4 @@
+export {
+  createInputContentProcessor as createInputContentProcessorGitHub,
+  createOutputContentProcessor as createOutputContentProcessorGitHub
+} from "./process-content";
diff --git a/packages/backend/src/routes/git/github/process-content.ts b/packages/backend/src/lib/git-sync/github/process-content.ts
similarity index 74%
rename from packages/backend/src/routes/git/github/process-content.ts
rename to packages/backend/src/lib/git-sync/github/process-content.ts
index acde403..6593bb4 100644
--- a/packages/backend/src/routes/git/github/process-content.ts
+++ b/packages/backend/src/lib/git-sync/github/process-content.ts
@@ -1,50 +1,28 @@
+import { AuthenticatedContext } from "../../middleware";
+import { UnderscoreID } from "../../mongo";
+import { jsonToBuffer, htmlToJSON, bufferToJSON } from "../../processing";
+import { InputContentProcessor, OutputContentProcessor } from "../types";
 import {
   GenericJSONContentNode,
   gfmInputTransformer,
   gfmOutputTransformer,
   InputTransformer,
   OutputTransformer
 } from "@vrite/sdk/transformers";
-import { ObjectId, Binary } from "mongodb";
-import { convert as convertToSlug } from "url-slug";
+import { ObjectId } from "mongodb";
 import * as prettier from "prettier/standalone";
 import markdownPlugin from "prettier/plugins/markdown";
 import htmlPlugin from "prettier/plugins/html";
 import axios from "axios";
 import crypto from "node:crypto";
 import {
-  FullContentPiece,
-  FullContents,
   FullGitData,
   getTransformersCollection,
   getWorkspaceSettingsCollection,
   Transformer
 } from "#database";
-import { UnderscoreID, jsonToBuffer, htmlToJSON, bufferToJSON, AuthenticatedContext } from "#lib";
-
-interface ProcessInputResult {
-  buffer: Buffer;
-  contentHash: string;
-  metadata: Partial<
-    Pick<FullContentPiece, keyof NonNullable<ReturnType<InputTransformer>["contentPiece"]>>
-  >;
-}
-interface OutputContentProcessorInput {
-  buffer: Buffer;
-  contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
-}
-
-interface InputContentProcessor {
-  process(inputContent: string): Promise<ProcessInputResult>;
-  processBatch(inputContent: string[]): Promise<ProcessInputResult[]>;
-}
-
-interface OutputContentProcessor {
-  process(input: OutputContentProcessorInput): Promise<string>;
-  processBatch(input: OutputContentProcessorInput[]): Promise<string[]>;
-}
 
 const extensionParserMap = {
   mdx: "mdx",
   html: "html",
   md: "markdown"
@@ -254,60 +232,7 @@ const createOutputContentProcessor = async (
 
       return output;
     }
   };
 };
-const createSyncedPieces = async (
-  inputs: Array<{
-    path: string;
-    content: string;
-    workspaceId: ObjectId;
-    contentGroupId: ObjectId;
-    order: string;
-  }>,
-  inputContentProcessor: InputContentProcessor
-): Promise<
-  Array<{
-    contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
-    content: UnderscoreID<FullContents<ObjectId>>;
-    contentHash: string;
-  }>
-> => {
-  const inputContentProcessorOutput = await inputContentProcessor.processBatch(
-    inputs.map((input) => input.content)
-  );
-
-  return inputs.map((input, index) => {
-    const filename = input.path.split("/").pop() || "";
-    const { buffer, contentHash, metadata } = inputContentProcessorOutput[index];
-    const { members, tags, date, ...inputMetadata } = metadata;
-    const contentPiece: UnderscoreID<FullContentPiece<ObjectId>> = {
-      _id: new ObjectId(),
-      workspaceId: input.workspaceId,
-      contentGroupId: input.contentGroupId,
-      order: input.order,
-      members: [],
-      slug: convertToSlug(filename),
-      tags: [],
-      title: filename,
-      filename,
-      ...inputMetadata,
-      ...(date && { date: new Date(date) }),
-      ...(members && { members: members.map((memberId) => new ObjectId(memberId)) }),
-      ...(tags && { tags: tags.map((tagId) => new ObjectId(tagId)) })
-    };
-    const content = {
-      _id: new ObjectId(),
-      contentPieceId: contentPiece._id,
-      content: new Binary(buffer)
-    };
-
-    return {
-      contentPiece,
-      contentHash,
-      content
-    };
-  });
-};
 
-export { createSyncedPieces, createInputContentProcessor, createOutputContentProcessor };
-export type { OutputContentProcessorInput, OutputContentProcessor, InputContentProcessor };
+export { createInputContentProcessor, createOutputContentProcessor };
diff --git a/packages/backend/src/lib/git-sync-hooks.ts b/packages/backend/src/lib/git-sync/hooks.ts
similarity index 95%
rename from packages/backend/src/lib/git-sync-hooks.ts
rename to packages/backend/src/lib/git-sync/hooks.ts
index b6bd2c3..bfb9dab 100644
--- a/packages/backend/src/lib/git-sync-hooks.ts
+++ b/packages/backend/src/lib/git-sync/hooks.ts
@@ -1,9 +1,12 @@
 /* eslint-disable sonarjs/no-identical-functions */
-import { AuthenticatedContext } from "./middleware";
-import { ObjectId, UnderscoreID } from "./mongo";
-import { jsonToBuffer } from "./processing";
+import { createGenericOutputContentProcessor } from "./process-content";
+import { OutputContentProcessor } from "./types";
+import { AuthenticatedContext } from "../middleware";
+import { UnderscoreID } from "../mongo";
+import { jsonToBuffer } from "../processing";
+import { ObjectId } from "mongodb";
 import crypto from "node:crypto";
 import {
   FullContentGroup,
   FullContentPiece,
   FullGitData,
@@ -12,15 +15,11 @@ import {
   getContentGroupsCollection,
   getContentPiecesCollection,
   getContentsCollection,
   getGitDataCollection
 } from "#database";
-import {
-  OutputContentProcessor,
-  createOutputContentProcessor as createOutputContentProcessorGitHub
-} from "#routes/git/github/process-content";
-import { publishGitDataEvent } from "#routes/git/events";
+import { publishGitDataEvent } from "#events";
 
 type GitSyncHookEvent =
   | "contentPieceUpdated"
   | "contentPieceRemoved"
   | "contentPieceCreated"
@@ -72,27 +71,10 @@ type GitSyncHookHandler<E extends GitSyncHookEvent> = (
     outputContentProcessor: OutputContentProcessor;
   },
   data: GitSyncHookEventData[E]
 ) => Promise<GitSyncHookData>;
 
-const createGenericOutputContentProcessor = async (
-  ctx: AuthenticatedContext,
-  gitData: UnderscoreID<FullGitData<ObjectId>>
-): Promise<OutputContentProcessor> => {
-  if (gitData.provider === "github") {
-    return await createOutputContentProcessorGitHub(ctx, gitData);
-  }
-
-  return {
-    process() {
-      return Promise.resolve("");
-    },
-    processBatch(input) {
-      return Promise.resolve(input.map(() => ""));
-    }
-  };
-};
 const handleContentGroupMoved: GitSyncHookHandler<"contentGroupMoved"> = async (
   { ctx, directories, records, outputContentProcessor },
   data
 ) => {
   const contentGroupsCollection = getContentGroupsCollection(ctx.db);
diff --git a/packages/backend/src/lib/git-sync/index.ts b/packages/backend/src/lib/git-sync/index.ts
new file mode 100644
index 0000000..7bb1f06
--- /dev/null
+++ b/packages/backend/src/lib/git-sync/index.ts
@@ -0,0 +1,4 @@
+export * from "./hooks";
+export * from "./process-content";
+export * from "./github";
+export * from "./types";
diff --git a/packages/backend/src/routes/git/process-content.ts b/packages/backend/src/lib/git-sync/process-content.ts
similarity index 86%
rename from packages/backend/src/routes/git/process-content.ts
rename to packages/backend/src/lib/git-sync/process-content.ts
index fed48bf..ee8475d 100644
--- a/packages/backend/src/routes/git/process-content.ts
+++ b/packages/backend/src/lib/git-sync/process-content.ts
@@ -1,11 +1,7 @@
-import {
-  OutputContentProcessor,
-  InputContentProcessor,
-  createOutputContentProcessor as createOutputContentProcessorGitHub,
-  createInputContentProcessor as createInputContentProcessorGitHub
-} from "./github";
+import { createOutputContentProcessorGitHub, createInputContentProcessorGitHub } from "./github";
+import { InputContentProcessor, OutputContentProcessor } from "./types";
 import { ObjectId } from "mongodb";
 import { FullGitData } from "#database";
 import { AuthenticatedContext, UnderscoreID } from "#lib";
 
 const createGenericOutputContentProcessor = async (
diff --git a/packages/backend/src/lib/git-sync/types.ts b/packages/backend/src/lib/git-sync/types.ts
new file mode 100644
index 0000000..3a906bf
--- /dev/null
+++ b/packages/backend/src/lib/git-sync/types.ts
@@ -0,0 +1,28 @@
+import { InputTransformer } from "@vrite/sdk/transformers";
+import { ObjectId } from "mongodb";
+import { FullContentPiece } from "#database";
+import { UnderscoreID } from "#lib/mongo";
+
+interface ProcessInputResult {
+  buffer: Buffer;
+  contentHash: string;
+  metadata: Partial<
+    Pick<FullContentPiece, keyof NonNullable<ReturnType<InputTransformer>["contentPiece"]>>
+  >;
+}
+interface OutputContentProcessorInput {
+  buffer: Buffer;
+  contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
+}
+
+interface InputContentProcessor {
+  process(inputContent: string): Promise<ProcessInputResult>;
+  processBatch(inputContent: string[]): Promise<ProcessInputResult[]>;
+}
+
+interface OutputContentProcessor {
+  process(input: OutputContentProcessorInput): Promise<string>;
+  processBatch(input: OutputContentProcessorInput[]): Promise<string[]>;
+}
+
+export type { InputContentProcessor, OutputContentProcessor, OutputContentProcessorInput };
diff --git a/packages/backend/src/lib/host-config.ts b/packages/backend/src/lib/host-config.ts
new file mode 100644
index 0000000..718bd59
--- /dev/null
+++ b/packages/backend/src/lib/host-config.ts
@@ -0,0 +1,16 @@
+import { z } from "zod";
+
+const hostConfig = z.object({
+  githubOAuth: z.boolean(),
+  githubApp: z.boolean(),
+  sendgrid: z.boolean(),
+  smtp: z.boolean(),
+  search: z.boolean(),
+  aiSearch: z.boolean(),
+  extensions: z.boolean()
+});
+
+interface HostConfig extends z.infer<typeof hostConfig> {}
+
+export { hostConfig };
+export type { HostConfig };
diff --git a/packages/backend/src/lib/index.ts b/packages/backend/src/lib/index.ts
index 553b548..bf6133a 100644
--- a/packages/backend/src/lib/index.ts
+++ b/packages/backend/src/lib/index.ts
@@ -1,9 +1,16 @@
-export * from "./utils";
+export * from "./auth";
+export * from "./context";
+export * as errors from "./errors";
+export * from "./git-sync";
+export * from "./hash";
+export * from "./middleware";
 export * from "./mongo";
 export * from "./plugin";
 export * from "./processing";
-export * from "./hash";
+export * from "./pub-sub";
+export * from "./session";
 export * from "./trpc";
-export * from "./middleware";
-export * from "./git-sync-hooks";
-export * as errors from "./errors";
+export * from "./utils";
+export * from "./webhooks";
+export * from "./workspace";
+export * from "./host-config";
diff --git a/packages/backend/src/lib/middleware.ts b/packages/backend/src/lib/middleware.ts
index 7cd7b1d..97a3a88 100644
--- a/packages/backend/src/lib/middleware.ts
+++ b/packages/backend/src/lib/middleware.ts
@@ -1,10 +1,11 @@
 import { processAuth } from "./auth";
 import { Context } from "./context";
+import * as errors from "./errors";
+import { HostConfig } from "./host-config";
+import { Meta, middleware } from "./trpc";
 import { ObjectId } from "mongodb";
-import { Meta, middleware } from "#lib/trpc";
-import * as errors from "#lib/errors";
 
 interface AuthMiddlewareContextExtension<W extends true | false = true> {
   auth: {
     userId: ObjectId;
     workspaceId: W extends true ? ObjectId : never;
@@ -67,11 +68,11 @@ const isAuthenticatedUser = middleware(async ({ ctx, next, meta }) => {
   return next({ ctx: authContextExtension });
 });
 const isEnabled = middleware(async ({ ctx, next, meta }) => {
   const requiredConfig = meta?.requiredConfig || [];
 
-  if (requiredConfig.some((property) => !ctx.fastify.hostConfig[property])) {
+  if (requiredConfig.some((property) => !ctx.fastify.hostConfig[property as keyof HostConfig])) {
     throw errors.serverError();
   }
 
   return next();
 });
diff --git a/packages/backend/src/lib/mongo.ts b/packages/backend/src/lib/mongo.ts
index 1872397..1ffe408 100644
--- a/packages/backend/src/lib/mongo.ts
+++ b/packages/backend/src/lib/mongo.ts
@@ -1,9 +1,8 @@
 import { z } from "zod";
-import { ObjectId, Db, Collection } from "mongodb";
 
 type UnderscoreID<T extends Record<string, any>> = Omit<T, "id"> & { _id: T["id"] };
 
 const zodId = (): z.ZodString => z.string().regex(/^[a-f\d]{24}$/i, "invalid id");
 
-export { zodId, ObjectId };
-export type { UnderscoreID, Db, Collection };
+export { zodId };
+export type { UnderscoreID };
diff --git a/packages/backend/src/lib/processing.ts b/packages/backend/src/lib/processing.ts
index 45f44ec..6345b3f 100644
--- a/packages/backend/src/lib/processing.ts
+++ b/packages/backend/src/lib/processing.ts
@@ -28,11 +28,11 @@ import {
   Comment,
   Table,
   TableCell,
   TableHeader,
   TableRow,
-  Wrapper
+  Element
 } from "@vrite/editor";
 
 type Attrs = Record<string, string | number | boolean>;
 interface DocJSON {
   type: string;
@@ -72,11 +72,11 @@ const htmlToJSON = (html: string): DocJSON => {
     Heading,
     BulletList,
     OrderedList,
     TaskList,
     Blockquote,
-    Wrapper,
+    Element,
     CodeBlock,
     HorizontalRule,
     Image,
     Embed,
     TaskItem,
@@ -105,11 +105,11 @@ const jsonToBuffer = (json: DocJSON): Buffer => {
     Heading,
     BulletList,
     OrderedList,
     TaskList,
     Blockquote,
-    Wrapper,
+    Element,
     CodeBlock,
     HorizontalRule,
     Image,
     Embed,
     TaskItem,
diff --git a/packages/backend/src/lib/session.ts b/packages/backend/src/lib/session.ts
index 4307a80..4976e54 100644
--- a/packages/backend/src/lib/session.ts
+++ b/packages/backend/src/lib/session.ts
@@ -1,13 +1,18 @@
 import { Context } from "./context";
 import { UnderscoreID } from "./mongo";
+import * as errors from "./errors";
 import { nanoid } from "nanoid";
 import { ObjectId } from "mongodb";
-import { getUserSettingsCollection } from "#database/user-settings";
-import { getWorkspaceMembershipsCollection } from "#database/workspace-memberships";
-import { BaseRoleType, FullRole, Permission, getRolesCollection } from "#database/roles";
-import * as errors from "#lib/errors";
+import {
+  BaseRoleType,
+  FullRole,
+  Permission,
+  getRolesCollection,
+  getUserSettingsCollection,
+  getWorkspaceMembershipsCollection
+} from "#database";
 
 declare module "node:net" {
   interface Socket {
     sessionId?: string;
   }
diff --git a/packages/backend/src/lib/trpc.ts b/packages/backend/src/lib/trpc.ts
index 6291be3..bb085ad 100644
--- a/packages/backend/src/lib/trpc.ts
+++ b/packages/backend/src/lib/trpc.ts
@@ -1,11 +1,11 @@
 import { Context } from "./context";
 import { CustomError } from "./errors";
+import { HostConfig } from "./host-config";
 import { initTRPC } from "@trpc/server";
 import { OpenApiMeta } from "trpc-openapi";
 import { TokenPermission, Permission } from "#database";
-import { HostConfig } from "#plugins/host-config";
 
 type Meta = OpenApiMeta & {
   permissions?: { session?: Permission[]; token?: TokenPermission[] };
   requiredConfig?: Array<keyof HostConfig>;
 };
diff --git a/packages/backend/src/lib/webhooks.ts b/packages/backend/src/lib/webhooks.ts
index a959f9e..3bb0295 100644
--- a/packages/backend/src/lib/webhooks.ts
+++ b/packages/backend/src/lib/webhooks.ts
@@ -1,12 +1,18 @@
 import { AuthenticatedContext } from "./middleware";
+import { zodId } from "./mongo";
 import axios from "axios";
 import { z } from "zod";
-import { ObjectId, zodId } from "#lib/mongo";
-import { WebhookEvent, getWebhooksCollection } from "#database/webhooks";
-import { contentGroup, contentPiece, getContentGroupsCollection } from "#database";
-import { workspaceMembership } from "#database/workspace-memberships";
+import { ObjectId } from "mongodb";
+import {
+  WebhookEvent,
+  getWebhooksCollection,
+  contentGroup,
+  contentPiece,
+  getContentGroupsCollection,
+  workspaceMembership
+} from "#database";
 
 const webhookPayload = z.union([
   contentPiece.extend({ slug: z.string(), locked: z.boolean().optional() }),
   contentGroup,
   workspaceMembership.extend({ id: zodId() })
@@ -54,12 +60,11 @@ const runWebhooks = async (
             "X-Vrite-Extension-ID": `${webhook.extensionId}`
           }
         })
       });
     } catch (error) {
-      // eslint-disable-next-line no-console
-      console.error("Failed to run webhook", error);
+      ctx.fastify.log.error("Failed to run webhook", error);
     }
   }
 };
 
 export { runWebhooks };
diff --git a/packages/backend/src/plugins/database.ts b/packages/backend/src/plugins/database.ts
index 0821905..dba7c76 100644
--- a/packages/backend/src/plugins/database.ts
+++ b/packages/backend/src/plugins/database.ts
@@ -1,18 +1,18 @@
-import { publicPlugin } from "#lib/plugin";
-import { getContentPiecesCollection } from "#database/content-pieces";
-import { getRolesCollection } from "#database/roles";
-import { getTagsCollection } from "#database/tags";
-import { getTokensCollection } from "#database/tokens";
-import { getUserSettingsCollection } from "#database/user-settings";
-import { getWebhooksCollection } from "#database/webhooks";
-import { getWorkspaceSettingsCollection } from "#database/workspace-settings";
-import { getContentsCollection } from "#database/contents";
-import { getUsersCollection } from "#database/users";
-import { getCommentThreadsCollection } from "#database/comment-threads";
-import { getCommentsCollection } from "#database/comments";
+import { publicPlugin } from "#lib";
 import {
+  getUserSettingsCollection,
+  getWebhooksCollection,
+  getWorkspaceSettingsCollection,
+  getContentsCollection,
+  getUsersCollection,
+  getCommentThreadsCollection,
+  getCommentsCollection,
+  getContentPiecesCollection,
+  getRolesCollection,
+  getTagsCollection,
+  getTokensCollection,
   getContentGroupsCollection,
   getContentPieceVariantsCollection,
   getContentVariantsCollection,
   getVariantsCollection
 } from "#database";
diff --git a/packages/backend/src/plugins/email.ts b/packages/backend/src/plugins/email.ts
index 2612561..b6dd5a4 100644
--- a/packages/backend/src/plugins/email.ts
+++ b/packages/backend/src/plugins/email.ts
@@ -1,14 +1,12 @@
-import { publicPlugin } from "../lib/plugin";
 import { EmailService, FastifyInstance } from "fastify";
 import { MailService } from "@sendgrid/mail";
 import { ObjectId } from "mongodb";
 import { EmailTemplate, getSubject, renderEmail } from "@vrite/emails";
 import * as nodemailer from "nodemailer";
-import { getWorkspacesCollection } from "#database/workspaces";
-import { getUsersCollection } from "#database/users";
-import * as errors from "#lib/errors";
+import { getWorkspacesCollection, getUsersCollection } from "#database";
+import { errors, publicPlugin } from "#lib";
 
 type EmailSender = (email: {
   to: string;
   template: EmailTemplate;
   data: Record<string, string>;
@@ -75,12 +73,11 @@ const createEmailSender = (fastify: FastifyInstance): EmailSender => {
           subject: getSubject(email.template),
           html: renderEmail(email.template, email.data),
           text: renderEmail(email.template, email.data, true)
         });
       } catch (error) {
-        // eslint-disable-next-line no-console
-        console.error(error);
+        fastify.log.error(error);
 
         throw errors.serverError();
       }
     };
   }
@@ -107,21 +104,20 @@ const createEmailSender = (fastify: FastifyInstance): EmailSender => {
           subject: getSubject(email.template),
           html: renderEmail(email.template, email.data),
           text: renderEmail(email.template, email.data, true)
         });
       } catch (error) {
-        // eslint-disable-next-line no-console
-        console.error(error);
+        fastify.log.error(error);
 
         throw errors.serverError();
       }
     };
   }
 
   return async () => {
     // eslint-disable-next-line no-console
-    console.error("No email service configured");
+    fastify.log.error("No email service configured");
 
     throw errors.serverError();
   };
 };
 const mailPlugin = publicPlugin(async (fastify) => {
diff --git a/packages/backend/src/plugins/git-sync.ts b/packages/backend/src/plugins/git-sync.ts
index bd0d291..4fbe93a 100644
--- a/packages/backend/src/plugins/git-sync.ts
+++ b/packages/backend/src/plugins/git-sync.ts
@@ -1,8 +1,8 @@
 import { App } from "octokit";
 import { FastifyInstance } from "fastify";
-import { publicPlugin } from "#lib/plugin";
+import { publicPlugin } from "#lib";
 
 declare module "fastify" {
   interface FastifyInstance {
     github: App;
   }
diff --git a/packages/backend/src/plugins/host-config.ts b/packages/backend/src/plugins/host-config.ts
index e1e817d..00c0c9d 100644
--- a/packages/backend/src/plugins/host-config.ts
+++ b/packages/backend/src/plugins/host-config.ts
@@ -1,19 +1,6 @@
-import { publicPlugin } from "../lib/plugin";
-import { z } from "zod";
-
-const hostConfig = z.object({
-  githubOAuth: z.boolean(),
-  githubApp: z.boolean(),
-  sendgrid: z.boolean(),
-  smtp: z.boolean(),
-  search: z.boolean(),
-  aiSearch: z.boolean(),
-  extensions: z.boolean()
-});
-
-interface HostConfig extends z.infer<typeof hostConfig> {}
+import { HostConfig, publicPlugin } from "#lib";
 
 declare module "fastify" {
   interface FastifyInstance {
     hostConfig: HostConfig;
   }
@@ -42,7 +29,6 @@ const hostConfigPlugin = publicPlugin(async (fastify) => {
   };
 
   fastify.decorate("hostConfig", hostConfig);
 });
 
-export { hostConfigPlugin, hostConfig };
-export type { HostConfig };
+export { hostConfigPlugin };
diff --git a/packages/backend/src/plugins/oauth.ts b/packages/backend/src/plugins/oauth.ts
index 8761b3d..d852787 100644
--- a/packages/backend/src/plugins/oauth.ts
+++ b/packages/backend/src/plugins/oauth.ts
@@ -1,15 +1,11 @@
 import axios from "axios";
 import fastifyOAuth2, { FastifyOAuth2Options, OAuth2Namespace } from "@fastify/oauth2";
 import { ObjectId } from "mongodb";
 import { FastifyInstance } from "fastify";
-import { publicPlugin } from "#lib/plugin";
-import { generateSalt } from "#lib/hash";
-import { createSession } from "#lib/session";
-import { createWorkspace } from "#lib/workspace";
-import { getUsersCollection } from "#database/users";
-import { getUserSettingsCollection } from "#database";
+import { publicPlugin, generateSalt, createSession, createWorkspace } from "#lib";
+import { getUserSettingsCollection, getUsersCollection } from "#database";
 
 declare module "fastify" {
   interface FastifyInstance {
     githubOAuth2: OAuth2Namespace;
   }
@@ -80,22 +76,21 @@ const registerGitHubOAuth = (fastify: FastifyInstance): void => {
         });
 
         await userSettingsCollection.insertOne({
           _id: new ObjectId(),
           userId: newUser._id,
-          codeEditorTheme: "dark",
+          codeEditorTheme: "auto",
           uiTheme: "auto",
           accentColor: "energy",
           currentWorkspaceId: workspaceId
         });
         await createSession({ req, res, db, fastify }, `${newUser._id}`);
       }
 
       return res.redirect("/");
     } catch (error) {
-      // eslint-disable-next-line no-console
-      console.error(error);
+      fastify.log.error(error);
 
       return res.redirect("/auth");
     }
   });
   fastify.register(fastifyOAuth2, oAuthConfig.github);
diff --git a/packages/backend/src/plugins/pub-sub.ts b/packages/backend/src/plugins/pub-sub.ts
index a3eb54a..5d1b8a4 100644
--- a/packages/backend/src/plugins/pub-sub.ts
+++ b/packages/backend/src/plugins/pub-sub.ts
@@ -1,7 +1,7 @@
-import { publicPlugin } from "../lib/plugin";
 import type { PubSubMessage, PubSubPlugin } from "fastify";
+import { publicPlugin } from "#lib";
 
 declare module "fastify" {
   interface PubSubMessage {
     action: string;
     userId?: string;
diff --git a/packages/backend/src/plugins/s3.ts b/packages/backend/src/plugins/s3.ts
index 8319038..a9148e9 100644
--- a/packages/backend/src/plugins/s3.ts
+++ b/packages/backend/src/plugins/s3.ts
@@ -1,12 +1,7 @@
-import { publicPlugin } from "../lib/plugin";
-import {
-  S3Client,
-  CreateBucketCommand,
-  PutBucketCorsCommand,
-  HeadBucketCommand
-} from "@aws-sdk/client-s3";
+import { S3Client, CreateBucketCommand, HeadBucketCommand } from "@aws-sdk/client-s3";
+import { publicPlugin } from "#lib";
 
 declare module "fastify" {
   interface FastifyInstance {
     s3: S3Client;
   }
diff --git a/packages/backend/src/plugins/search.ts b/packages/backend/src/plugins/search.ts
index cc049fc..b57253e 100644
--- a/packages/backend/src/plugins/search.ts
+++ b/packages/backend/src/plugins/search.ts
@@ -8,11 +8,12 @@ import {
 } from "@vrite/sdk/transformers";
 import { FastifyInstance, SearchService } from "fastify";
 import { OpenAI } from "openai";
 import { Stream } from "openai/streaming";
 import { ChatCompletionChunk } from "openai/resources/chat";
-import { Db, ObjectId, UnderscoreID, bufferToJSON, publicPlugin } from "#lib";
+import { Db, ObjectId } from "mongodb";
+import { UnderscoreID, bufferToJSON, publicPlugin } from "#lib";
 import { FullContentPiece, getContentVariantsCollection, getContentsCollection } from "#database";
 
 interface RawSearchResult {
   data: {
     Get: {
diff --git a/packages/backend/src/plugins/session.ts b/packages/backend/src/plugins/session.ts
index e533a60..7f5c58f 100644
--- a/packages/backend/src/plugins/session.ts
+++ b/packages/backend/src/plugins/session.ts
@@ -1,18 +1,17 @@
-import { appRouter } from "../routes";
 import { getHTTPStatusCodeFromError } from "@trpc/server/http";
-import { publicPlugin } from "#lib/plugin";
-import { CustomError } from "#lib/errors";
+import { appRouter } from "#routes";
+import { publicPlugin, errors } from "#lib";
 
 const sessionPlugin = publicPlugin(async (fastify) => {
   fastify.post("/session/refresh", async (req, res) => {
     const caller = appRouter.createCaller({ db: fastify.mongo.db!, fastify, req, res });
 
     try {
       await caller.auth.refreshToken();
     } catch (e) {
-      const error = e as CustomError;
+      const error = e as errors.CustomError;
       const httpStatusCode = getHTTPStatusCodeFromError(error);
 
       res
         .status(httpStatusCode)
         .send({ error: { message: error.message, cause: error.causeData } });
@@ -24,11 +23,11 @@ const sessionPlugin = publicPlugin(async (fastify) => {
     const caller = appRouter.createCaller({ db: fastify.mongo.db!, fastify, req, res });
 
     try {
       await caller.auth.logout();
     } catch (e) {
-      const error = e as CustomError;
+      const error = e as errors.CustomError;
       const httpStatusCode = getHTTPStatusCodeFromError(error);
 
       res
         .status(httpStatusCode)
         .send({ error: { message: error.message, cause: error.causeData } });
diff --git a/packages/backend/src/plugins/trpc.ts b/packages/backend/src/plugins/trpc.ts
index a2eeadd..5c80c76 100644
--- a/packages/backend/src/plugins/trpc.ts
+++ b/packages/backend/src/plugins/trpc.ts
@@ -1,10 +1,9 @@
-import { publicPlugin } from "../lib/plugin";
-import { createContext } from "../lib/context";
-import { appRouter } from "../routes";
 import { fastifyTRPCPlugin } from "@trpc/server/adapters/fastify";
 import { FastifyReply, FastifyRequest } from "fastify";
+import { appRouter } from "#routes";
+import { publicPlugin, createContext } from "#lib";
 
 const trpcPlugin = publicPlugin(async (fastify) => {
   await fastify.register(fastifyTRPCPlugin, {
     prefix: "/api/v1",
     useWSS: true,
diff --git a/packages/backend/src/routes/auth.ts b/packages/backend/src/routes/auth.ts
index 42801d9..ef5193b 100644
--- a/packages/backend/src/routes/auth.ts
+++ b/packages/backend/src/routes/auth.ts
@@ -1,24 +1,27 @@
 import { ObjectId } from "mongodb";
 import { nanoid } from "nanoid";
 import { z } from "zod";
 import * as OTPAuth from "otpauth";
-import { FullUser, getUsersCollection } from "#database/users";
-import { UnderscoreID } from "#lib/mongo";
-import { generateSalt, hashValue, verifyValue } from "#lib/hash";
-import { procedure, router } from "#lib/trpc";
+import { FullUser, getUsersCollection, getUserSettingsCollection } from "#database";
 import {
+  UnderscoreID,
+  generateSalt,
+  processAuth,
+  errors,
+  isAuthenticated,
+  isAuthenticatedUser,
+  hashValue,
+  verifyValue,
   createSession,
   deleteSession,
   getSessionId,
   refreshSession,
-  updateSession
-} from "#lib/session";
-import { processAuth } from "#lib/auth";
-import * as errors from "#lib/errors";
-import { isAuthenticated, isAuthenticatedUser } from "#lib/middleware";
-import { getUserSettingsCollection } from "#database";
+  updateSession,
+  procedure,
+  router
+} from "#lib";
 
 const totpConfig = {
   issuer: "Vrite",
   algorithm: "SHA512",
   digits: 6,
@@ -50,13 +53,17 @@ const authRouter = router({
       return Boolean(auth);
     }),
   register: procedure
     .input(
       z.object({
-        email: z.string().email(),
+        email: z.string().email().max(320),
         username: z.string().regex(/^[a-z0-9_]*$/),
-        password: z.string().regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/),
+        password: z
+          .string()
+          .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/)
+          .min(8)
+          .max(128),
         redirect: z.string().optional()
       })
     )
     .output(z.void())
     .mutation(async ({ input, ctx }) => {
@@ -92,11 +99,11 @@ const authRouter = router({
       });
     }),
   sendMagicLink: procedure
     .input(
       z.object({
-        email: z.string().email(),
+        email: z.string().email().max(320),
         totpToken: z.string().optional(),
         redirect: z.string().optional()
       })
     )
     .output(z.void())
@@ -108,10 +115,16 @@ const authRouter = router({
 
       if (user.emailVerificationCode) {
         throw errors.unauthorized("emailNotVerified");
       }
 
+      const magicLinkSent = await ctx.fastify.redis.get(`user:${user._id}:magicLinkSent`);
+
+      if (magicLinkSent === "true") {
+        throw errors.unauthorized("magicLinkAlreadySent");
+      }
+
       if (user.totpSecret) {
         verifyTotp(user, input.totpToken);
       }
 
       const magicLinkCode = nanoid();
@@ -126,20 +139,21 @@ const authRouter = router({
         `user:${user._id}:magicLinkRedirect`,
         input.redirect || "/",
         "EX",
         60 * 30
       );
+      await ctx.fastify.redis.set(`user:${user._id}:magicLinkSent`, "true", "EX", 60);
       await ctx.fastify.email.sendMagicLink(user.email, {
         code: magicLinkCode,
         userId: `${user._id}`
       });
     }),
   login: procedure
     .input(
       z.object({
-        email: z.string().email(),
-        password: z.string(),
+        email: z.string().email().max(320),
+        password: z.string().min(8).max(128),
         totpToken: z.string().optional()
       })
     )
     .output(z.void())
     .mutation(async ({ input, ctx }) => {
diff --git a/packages/backend/src/routes/comments.ts b/packages/backend/src/routes/comments.ts
index 0f99636..c0b058b 100644
--- a/packages/backend/src/routes/comments.ts
+++ b/packages/backend/src/routes/comments.ts
@@ -1,42 +1,21 @@
 import { Db, ObjectId } from "mongodb";
 import { z } from "zod";
-import { UnderscoreID, zodId } from "#lib/mongo";
-import { isAuthenticated } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { UnderscoreID, zodId, isAuthenticated, procedure, router, errors } from "#lib";
 import {
   CommentThread,
   commentThread,
   getCommentThreadsCollection,
   comment,
   getCommentsCollection,
   Comment,
   commentMember,
   CommentWithAdditionalData,
   getWorkspaceMembershipsCollection,
-  getUsersCollection,
-  CommentMember
+  getUsersCollection
 } from "#database";
-
-type CommentEvent =
-  | { action: "createThread"; data: CommentThread }
-  | { action: "resolveThread"; data: Pick<CommentThread, "id" | "fragment" | "resolved"> }
-  | { action: "deleteThread"; data: Pick<CommentThread, "id" | "fragment"> }
-  | {
-      action: "createComment";
-      data: Omit<Comment, "memberId"> & { member: CommentMember | null };
-    }
-  | {
-      action: "updateComment";
-      data: Pick<Comment, "id" | "content">;
-    }
-  | {
-      action: "deleteComment";
-      data: Pick<Comment, "id">;
-    };
+import { publishCommentEvent, subscribeToCommentEvents } from "#events";
 
 const fetchCommentsMembers = async (
   db: Db,
   comments: Array<UnderscoreID<Comment<ObjectId>>>
 ): Promise<Array<CommentWithAdditionalData>> => {
@@ -97,13 +76,10 @@ const fetchThreadsFirstComments = async (
   const comments = await commentsCollection.find({ _id: { $in: commentIds } }).toArray();
 
   return fetchCommentsMembers(db, comments);
 };
 const authenticatedProcedure = procedure.use(isAuthenticated);
-const publishEvent = createEventPublisher<CommentEvent>((contentPieceId) => {
-  return `comments:${contentPieceId}`;
-});
 const commentsRouter = router({
   getThread: authenticatedProcedure
     .input(z.object({ fragment: z.string() }))
     .output(commentThread.omit({ comments: true }))
     .query(async ({ ctx, input }) => {
@@ -214,11 +190,11 @@ const commentsRouter = router({
         fragment: input.fragment,
         resolved: false
       };
 
       await commentThreadsCollection.insertOne(thread);
-      publishEvent(ctx, `${input.contentPieceId}`, {
+      publishCommentEvent(ctx, `${input.contentPieceId}`, {
         action: "createThread",
         data: {
           ...thread,
           contentPieceId: `${thread.contentPieceId}`,
           date: thread.date.toISOString(),
@@ -247,11 +223,11 @@ const commentsRouter = router({
         },
         {
           $set: { resolved: true }
         }
       );
-      publishEvent(ctx, `${existingThread.contentPieceId}`, {
+      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
         action: "resolveThread",
         data: {
           id: `${existingThread._id}`,
           fragment: existingThread.fragment,
           resolved: true
@@ -287,11 +263,11 @@ const commentsRouter = router({
         },
         {
           $push: { comments: comment._id }
         }
       );
-      publishEvent(ctx, `${existingThread.contentPieceId}`, {
+      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
         action: "createComment",
         data: (await fetchCommentsMembers(ctx.db, [comment]))[0]
       });
 
       return { id: `${comment._id}` };
@@ -318,11 +294,11 @@ const commentsRouter = router({
 
       await commentsCollection.updateOne(
         { _id: existingComment._id },
         { $set: { content: input.content } }
       );
-      publishEvent(ctx, `${existingThread.contentPieceId}`, {
+      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
         action: "updateComment",
         data: {
           content: input.content,
           id: `${existingComment._id}`
         }
@@ -351,11 +327,11 @@ const commentsRouter = router({
       await commentsCollection.deleteOne({ _id: existingComment._id });
       await commentThreadsCollection.updateOne(
         { _id: existingThread._id },
         { $pull: { comments: existingComment._id } }
       );
-      publishEvent(ctx, `${existingThread.contentPieceId}`, {
+      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
         action: "deleteComment",
         data: {
           id: `${existingComment._id}`
         }
       });
@@ -373,21 +349,21 @@ const commentsRouter = router({
 
       if (!existingThread) throw errors.notFound("commentThread");
 
       await commentThreadsCollection.deleteOne({ _id: existingThread._id });
       await commentsCollection.deleteMany({ threadId: existingThread._id });
-      publishEvent(ctx, `${existingThread.contentPieceId}`, {
+      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
         action: "deleteThread",
         data: {
           id: `${existingThread._id}`,
           fragment: existingThread.fragment
         }
       });
     }),
   changes: authenticatedProcedure
     .input(z.object({ contentPieceId: zodId() }))
     .subscription(({ ctx, input }) => {
-      return createEventSubscription<CommentEvent>(ctx, `comments:${input.contentPieceId}`);
+      return subscribeToCommentEvents(ctx, input.contentPieceId);
     })
 });
 
 export { commentsRouter };
diff --git a/packages/backend/src/routes/content-groups.ts b/packages/backend/src/routes/content-groups.ts
index 1bc760e..eb31785 100644
--- a/packages/backend/src/routes/content-groups.ts
+++ b/packages/backend/src/routes/content-groups.ts
@@ -1,13 +1,7 @@
 import { ObjectId } from "mongodb";
 import { z } from "zod";
-import { procedure, router } from "#lib/trpc";
-import { isAuthenticated } from "#lib/middleware";
-import { UnderscoreID, zodId } from "#lib/mongo";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { runWebhooks } from "#lib/webhooks";
 import {
   ContentGroup,
   contentGroup,
   getContentsCollection,
   getContentPiecesCollection,
@@ -15,28 +9,22 @@ import {
   getContentPieceVariantsCollection,
   getContentVariantsCollection,
   getWorkspacesCollection,
   FullContentGroup
 } from "#database";
-import { runGitSyncHook } from "#lib";
-
-type ContentGroupEvent =
-  | {
-      action: "create";
-      data: ContentGroup;
-    }
-  | {
-      action: "update";
-      data: Partial<ContentGroup> & { id: string };
-    }
-  | { action: "delete"; data: { id: string } }
-  | { action: "move"; data: ContentGroup }
-  | { action: "reorder"; data: { id: string; index: number } };
-
-const publishEvent = createEventPublisher<ContentGroupEvent>(
-  (workspaceId) => `contentGroups:${workspaceId}`
-);
+import {
+  runGitSyncHook,
+  runWebhooks,
+  errors,
+  UnderscoreID,
+  zodId,
+  isAuthenticated,
+  procedure,
+  router
+} from "#lib";
+import { subscribeToContentGroupEvents, publishContentGroupEvent } from "#events";
+
 const basePath = "/content-groups";
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const rearrangeContentGroups = (
   contentGroups: Array<UnderscoreID<FullContentGroup<ObjectId>>>,
   ids: ObjectId[]
@@ -177,11 +165,14 @@ const contentGroupsRouter = router({
       runGitSyncHook(ctx, "contentGroupUpdated", {
         contentGroup,
         ancestor: "ancestor" in input ? input.ancestor : undefined,
         name: "name" in input ? input.name : undefined
       });
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "update", data: { id, ...update } });
+      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
+        action: "update",
+        data: { id, ...update }
+      });
     }),
   create: authenticatedProcedure
     .meta({
       openapi: { method: "POST", path: basePath, protect: true },
       permissions: { session: ["manageDashboard"], token: ["contentGroups:write"] }
@@ -229,11 +220,11 @@ const contentGroupsRouter = router({
           { $push: { contentGroups: contentGroup._id } }
         );
       }
 
       await contentGroupsCollection.insertOne(contentGroup);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: {
           id: `${contentGroup._id}`,
           ancestors: contentGroup.ancestors.map((id) => `${id}`),
           descendants: contentGroup.descendants.map((id) => `${id}`),
@@ -326,11 +317,11 @@ const contentGroupsRouter = router({
         ...contentGroup,
         ancestors: contentGroup.ancestors.map((id) => `${id}`),
         descendants: contentGroup.descendants.map((id) => `${id}`),
         id: `${contentGroup._id}`
       });
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: input
       });
       ctx.fastify.search.deleteContent({
         contentPieceId: contentPieceIds,
@@ -502,11 +493,11 @@ const contentGroupsRouter = router({
 
       runGitSyncHook(ctx, "contentGroupMoved", {
         ancestor: input.ancestor,
         contentGroup
       });
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "move",
         data: {
           id: input.id,
           ancestors: ancestors.map((id) => `${id}`),
           descendants: contentGroup.descendants.map((id) => `${id}`),
@@ -581,16 +572,16 @@ const contentGroupsRouter = router({
           { _id: ctx.auth.workspaceId },
           { $set: { contentGroups: newContentGroups } }
         );
       }
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "reorder",
         data: input
       });
     }),
   changes: authenticatedProcedure.subscription(async ({ ctx }) => {
-    return createEventSubscription<ContentGroupEvent>(ctx, `contentGroups:${ctx.auth.workspaceId}`);
+    return subscribeToContentGroupEvents(ctx, `${ctx.auth.workspaceId}`);
   })
 });
 
-export { contentGroupsRouter, publishEvent as publishContentGroupEvent };
+export { contentGroupsRouter };
diff --git a/packages/backend/src/routes/content-pieces.ts b/packages/backend/src/routes/content-pieces.ts
index ccb024b..c44bd9f 100644
--- a/packages/backend/src/routes/content-pieces.ts
+++ b/packages/backend/src/routes/content-pieces.ts
@@ -1,63 +1,49 @@
 import { Binary, Db, ObjectId } from "mongodb";
 import { z } from "zod";
 import { LexoRank } from "lexorank";
 import { convert as convertToSlug } from "url-slug";
 import { convert as convertToText } from "html-to-text";
-import { stringToRegex } from "#lib/utils";
-import { UnderscoreID, zodId } from "#lib/mongo";
-import { bufferToJSON, DocJSON, htmlToJSON, jsonToBuffer } from "#lib/processing";
-import { isAuthenticated } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
 import {
   contentPiece,
   ContentPiece,
   ContentPieceMember,
   contentPieceMember,
   FullContentPiece,
-  FullContentPieceWithAdditionalData,
-  getContentPiecesCollection
-} from "#database/content-pieces";
-import { Tag, getTagsCollection, tag } from "#database/tags";
-import * as errors from "#lib/errors";
-import { getContentsCollection } from "#database/contents";
-import { runWebhooks } from "#lib/webhooks";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+  getContentPiecesCollection,
+  Tag,
+  getTagsCollection,
+  tag,
+  getContentsCollection
+} from "#database";
+import {
+  runWebhooks,
+  errors,
+  runGitSyncHook,
+  procedure,
+  router,
+  isAuthenticated,
+  bufferToJSON,
+  DocJSON,
+  htmlToJSON,
+  jsonToBuffer,
+  UnderscoreID,
+  zodId,
+  stringToRegex
+} from "#lib";
 import {
   FullContentPieceVariant,
   getContentGroupsCollection,
   getContentPieceVariantsCollection,
   getContentVariantsCollection,
   getUsersCollection,
   getVariantsCollection,
   getWorkspaceMembershipsCollection,
   getWorkspaceSettingsCollection
 } from "#database";
-import { runGitSyncHook } from "#lib";
-
-type ContentPieceEvent =
-  | { action: "delete"; userId: string; data: { id: string } }
-  | { action: "create"; userId: string; data: FullContentPieceWithAdditionalData }
-  | {
-      action: "update";
-      userId: string;
-      variantId?: string;
-      data: Partial<FullContentPieceWithAdditionalData> & { id: string };
-    }
-  | {
-      action: "move";
-      userId: string;
-      data: {
-        contentPiece: FullContentPieceWithAdditionalData;
-        nextReferenceId?: string;
-        previousReferenceId?: string;
-      };
-    };
+import { publishContentPieceEvent, subscribeToContentPieceEvents } from "#events";
 
-const publishEvent = createEventPublisher<ContentPieceEvent>((contentGroupId) => {
-  return `contentPieces:${contentGroupId}`;
-});
 const webhookPayload = (
   contentPiece: UnderscoreID<FullContentPiece<ObjectId>>
 ): ContentPiece & { id: string; locked?: boolean } => {
   return {
     ...contentPiece,
@@ -149,25 +135,25 @@ const mergeVariantData = (
 
   return { ...contentPiece, ...mergedVariantData };
 };
 const getVariantDetails = async (
   db: Db,
-  variantIdOrName?: string
-): Promise<{ variantId: ObjectId | null; variantName: string | null }> => {
+  variantIdOrKey?: string
+): Promise<{ variantId: ObjectId | null; variantKey: string | null }> => {
   const variantsCollection = getVariantsCollection(db);
 
-  if (!variantIdOrName) return { variantId: null, variantName: null };
+  if (!variantIdOrKey) return { variantId: null, variantKey: null };
 
-  const isId = ObjectId.isValid(variantIdOrName);
+  const isId = ObjectId.isValid(variantIdOrKey);
   const variant = await variantsCollection.findOne({
-    ...(isId && { _id: new ObjectId(variantIdOrName) }),
-    ...(!isId && { name: variantIdOrName })
+    ...(isId && { _id: new ObjectId(variantIdOrKey) }),
+    ...(!isId && { key: variantIdOrKey })
   });
 
   if (!variant) throw errors.notFound("variant");
 
-  return { variantId: variant._id || null, variantName: variant.name || null };
+  return { variantId: variant._id || null, variantKey: variant.key || null };
 };
 const getCanonicalLinkFromPattern = (
   pattern: string,
   data: { slug: string; variant?: string | null }
 ): string => {
@@ -227,11 +213,11 @@ const contentPiecesRouter = router({
       const contentPiecesCollection = getContentPiecesCollection(ctx.db);
       const contentPieceVariantsCollection = getContentPieceVariantsCollection(ctx.db);
       const workspaceSettings = await workspaceSettingsCollection.findOne({
         workspaceId: ctx.auth.workspaceId
       });
-      const { variantId, variantName } = await getVariantDetails(ctx.db, input.variant);
+      const { variantId, variantKey } = await getVariantDetails(ctx.db, input.variant);
       const baseContentPiece = await contentPiecesCollection.findOne({
         _id: new ObjectId(input.id)
       });
 
       if (!baseContentPiece) throw errors.notFound("contentPiece");
@@ -294,11 +280,11 @@ const contentPiecesRouter = router({
         ...contentPiece,
         ...(workspaceSettings?.metadata?.canonicalLinkPattern &&
           typeof contentPiece.canonicalLink !== "string" && {
             canonicalLink: getCanonicalLinkFromPattern(
               workspaceSettings.metadata.canonicalLinkPattern,
-              { slug: contentPiece.slug, variant: variantName }
+              { slug: contentPiece.slug, variant: variantKey }
             )
           }),
         id: `${contentPiece._id}`,
         description: getDescription(),
         contentGroupId: `${contentPiece.contentGroupId}`,
@@ -351,11 +337,11 @@ const contentPiecesRouter = router({
       const contentPieceVariantsCollection = getContentPieceVariantsCollection(ctx.db);
       const workspaceSettings = await workspaceSettingsCollection.findOne({
         workspaceId: ctx.auth.workspaceId
       });
       const contentGroupId = new ObjectId(input.contentGroupId);
-      const { variantId, variantName } = await getVariantDetails(ctx.db, input.variant);
+      const { variantId, variantKey } = await getVariantDetails(ctx.db, input.variant);
       const cursor = contentPiecesCollection
         .find({
           workspaceId: ctx.auth.workspaceId,
           contentGroupId,
           ...(input.tagId ? { tags: new ObjectId(input.tagId) } : {}),
@@ -403,11 +389,11 @@ const contentPiecesRouter = router({
             ...contentPiece,
             ...(workspaceSettings?.metadata?.canonicalLinkPattern &&
               typeof contentPiece.canonicalLink !== "string" && {
                 canonicalLink: getCanonicalLinkFromPattern(
                   workspaceSettings.metadata.canonicalLinkPattern,
-                  { slug: contentPiece.slug, variant: variantName }
+                  { slug: contentPiece.slug, variant: variantKey }
                 )
               }),
             id: `${contentPiece._id}`,
             contentGroupId: `${contentPiece.contentGroupId}`,
             workspaceId: `${contentPiece.workspaceId}`,
@@ -498,11 +484,11 @@ const contentPiecesRouter = router({
       runWebhooks(ctx, "contentPieceAdded", webhookPayload(contentPiece));
 
       const tags = await fetchContentPieceTags(ctx.db, contentPiece);
       const members = await fetchContentPieceMembers(ctx.db, contentPiece);
 
-      publishEvent(ctx, `${contentPiece.contentGroupId}`, {
+      publishContentPieceEvent(ctx, `${contentPiece.contentGroupId}`, {
         action: "create",
         userId: `${ctx.auth.userId}`,
         data: {
           ...contentPiece,
           ...(workspaceSettings?.metadata?.canonicalLinkPattern &&
@@ -571,11 +557,11 @@ const contentPiecesRouter = router({
       const contentVariantsCollection = getContentVariantsCollection(ctx.db);
       const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);
       const workspaceSettings = await workspaceSettingsCollection.findOne({
         workspaceId: ctx.auth.workspaceId
       });
-      const { variantId, variantName } = await getVariantDetails(ctx.db, variant);
+      const { variantId, variantKey } = await getVariantDetails(ctx.db, variant);
       const baseContentPiece = await contentPiecesCollection.findOne({
         _id: new ObjectId(id)
       });
 
       if (!baseContentPiece) throw errors.notFound("contentPiece");
@@ -607,11 +593,18 @@ const contentPiecesRouter = router({
       const contentPieceUpdates: Partial<UnderscoreID<FullContentPiece<ObjectId>>> = {
         ...update
       };
 
       if (typeof update.slug !== "undefined") {
-        contentPieceUpdates.slug = convertToSlug(update.slug || update.title || contentPiece.title);
+        if (update.slug) {
+          contentPieceUpdates.slug = update.slug
+            .split("/")
+            .map((slugPart) => convertToSlug(slugPart))
+            .join("/");
+        } else {
+          contentPieceUpdates.slug = convertToSlug(update.title || contentPiece.title);
+        }
       } else if (convertToSlug(contentPiece.title) === contentPiece.slug) {
         contentPieceUpdates.slug = convertToSlug(update.title || contentPiece.title);
       }
 
       if (updatedTags) contentPieceUpdates.tags = updatedTags.map((tag) => new ObjectId(tag));
@@ -699,20 +692,20 @@ const contentPiecesRouter = router({
       }
 
       const tags = await fetchContentPieceTags(ctx.db, newContentPiece);
       const members = await fetchContentPieceMembers(ctx.db, newContentPiece);
 
-      publishEvent(ctx, `${newContentPiece.contentGroupId}`, {
+      publishContentPieceEvent(ctx, `${newContentPiece.contentGroupId}`, {
         action: "update",
         userId: `${ctx.auth.userId}`,
         data: {
           ...newContentPiece,
           ...(workspaceSettings?.metadata?.canonicalLinkPattern &&
             typeof newContentPiece.canonicalLink !== "string" && {
               canonicalLink: getCanonicalLinkFromPattern(
                 workspaceSettings.metadata.canonicalLinkPattern,
-                { slug: newContentPiece.slug, variant: variantName }
+                { slug: newContentPiece.slug, variant: variantKey }
               )
             }),
           id: `${newContentPiece._id}`,
           contentGroupId: `${newContentPiece.contentGroupId}`,
           workspaceId: `${newContentPiece.workspaceId}`,
@@ -756,11 +749,11 @@ const contentPiecesRouter = router({
       await contentVariantsCollection.deleteMany({
         contentPieceId: contentPiece._id
       });
       runGitSyncHook(ctx, "contentPieceRemoved", { contentPiece });
       runWebhooks(ctx, "contentPieceRemoved", webhookPayload(contentPiece));
-      publishEvent(ctx, `${contentPiece.contentGroupId}`, {
+      publishContentPieceEvent(ctx, `${contentPiece.contentGroupId}`, {
         action: "delete",
         userId: `${ctx.auth.userId}`,
         data: { id: input.id }
       });
       ctx.fastify.search.deleteContent({
@@ -860,11 +853,11 @@ const contentPiecesRouter = router({
 
       runGitSyncHook(ctx, "contentPieceMoved", {
         contentPiece,
         contentGroupId: input.contentGroupId
       });
-      publishEvent(
+      publishContentPieceEvent(
         ctx,
         [
           `${contentPiece.contentGroupId}`,
           ...(update.contentGroupId ? [`${update.contentGroupId}`] : [])
         ],
@@ -913,14 +906,10 @@ const contentPiecesRouter = router({
       }
     }),
   changes: authenticatedProcedure
     .input(z.object({ contentGroupId: zodId() }))
     .subscription(async ({ ctx, input }) => {
-      return createEventSubscription<ContentPieceEvent>(
-        ctx,
-        `contentPieces:${input.contentGroupId}`
-      );
+      return subscribeToContentPieceEvents(ctx, input.contentGroupId);
     })
 });
 
 export { contentPiecesRouter, fetchContentPieceTags };
-export type { ContentPieceEvent };
diff --git a/packages/backend/src/routes/extensions.ts b/packages/backend/src/routes/extensions.ts
index c1a3947..37ee531 100644
--- a/packages/backend/src/routes/extensions.ts
+++ b/packages/backend/src/routes/extensions.ts
@@ -1,40 +1,20 @@
 import { createToken } from "./tokens";
 import { z } from "zod";
 import { ObjectId } from "mongodb";
-import { isAuthenticated, isEnabled } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
 import {
-  Extension,
   extension,
   contextObject,
   getExtensionsCollection,
-  ContextObject,
   tokenPermission,
   getTokensCollection,
-  getContentPiecesCollection,
-  FullContentPieceWithAdditionalData
+  getContentPiecesCollection
 } from "#database";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import * as errors from "#lib/errors";
-import { zodId } from "#lib";
+import { zodId, errors, procedure, router, isAuthenticated, isEnabled } from "#lib";
+import { publishExtensionEvent, subscribeToExtensionEvents } from "#events/extension";
+import { publishContentPieceEvent } from "#events";
 
-type ExtensionEvent =
-  | { action: "delete"; data: { id: string } }
-  | { action: "create"; data: Extension & { id: string } }
-  | { action: "update"; data: { id: string; config: ContextObject } };
-
-const publishEvent = createEventPublisher<ExtensionEvent>((workspaceId) => {
-  return `extensions:${workspaceId}`;
-});
-const publishContentPieceEvent = createEventPublisher<{
-  action: "update";
-  userId: string;
-  data: Partial<FullContentPieceWithAdditionalData> & { id: string };
-}>((contentGroupId) => {
-  return `contentPieces:${contentGroupId}`;
-});
 const authenticatedProcedure = procedure.use(isAuthenticated).use(isEnabled);
 const basePath = "/extension";
 const extensionsRouter = router({
   get: authenticatedProcedure
     .meta({
@@ -167,11 +147,11 @@ const extensionsRouter = router({
         ...extension,
         id: `${_id}`
       }));
     }),
   changes: authenticatedProcedure.input(z.void()).subscription(({ ctx }) => {
-    return createEventSubscription<ExtensionEvent>(ctx, `extensions:${ctx.auth.workspaceId}`);
+    return subscribeToExtensionEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   install: authenticatedProcedure
     .meta({
       permissions: { session: ["manageExtensions"] },
       requiredConfig: ["extensions"]
@@ -218,11 +198,11 @@ const extensionsRouter = router({
         config: {},
         name: input.extension.name,
         workspaceId: ctx.auth.workspaceId,
         token: value
       });
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishExtensionEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: {
           config: {},
           name: input.extension.name,
           token: value,
@@ -257,11 +237,11 @@ const extensionsRouter = router({
 
       if (!matchedCount) {
         throw errors.notFound("extension");
       }
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishExtensionEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: {
           id: input.id,
           config: input.config
         }
@@ -286,11 +266,11 @@ const extensionsRouter = router({
       }
 
       await tokensCollection.deleteOne({
         extensionId: new ObjectId(input.id)
       });
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishExtensionEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: { id: input.id }
       });
     })
 });
diff --git a/packages/backend/src/routes/git/events.ts b/packages/backend/src/routes/git/events.ts
deleted file mode 100644
index 4b7f24e..0000000
--- a/packages/backend/src/routes/git/events.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { GitData } from "#database";
-import { createEventPublisher } from "#lib/pub-sub";
-
-type GitDataEvent =
-  | {
-      action: "configure";
-      data: GitData;
-    }
-  | {
-      action: "update";
-      data: Partial<GitData>;
-    }
-  | {
-      action: "reset";
-      data: {};
-    };
-
-const publishGitDataEvent = createEventPublisher<GitDataEvent>((workspaceId) => {
-  return `gitData:${workspaceId}`;
-});
-
-export { publishGitDataEvent };
-export type { GitDataEvent };
diff --git a/packages/backend/src/routes/git/github/index.ts b/packages/backend/src/routes/git/github/index.ts
index edea101..25943ee 100644
--- a/packages/backend/src/routes/git/github/index.ts
+++ b/packages/backend/src/routes/git/github/index.ts
@@ -1,30 +1,30 @@
-import {
-  createSyncedPieces,
-  createInputContentProcessor,
-  createOutputContentProcessor,
-  OutputContentProcessorInput,
-  OutputContentProcessor,
-  InputContentProcessor
-} from "./process-content";
 import {
   commitChanges,
   getCommitsSince,
   getFilesChangedInCommit,
   getLastCommit,
   getDirectory
 } from "./requests";
 import { processPulledRecords } from "./pull";
-import { publishGitDataEvent } from "../events";
+import { createSyncedPieces } from "./synced-pieces";
 import { z } from "zod";
 import { LexoRank } from "lexorank";
-import { Binary } from "mongodb";
+import { Binary, ObjectId } from "mongodb";
 import { minimatch } from "minimatch";
 import crypto from "node:crypto";
-import { AuthenticatedContext, isAuthenticated, isEnabled } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
+import {
+  createInputContentProcessorGitHub,
+  createOutputContentProcessorGitHub,
+  OutputContentProcessorInput,
+  AuthenticatedContext,
+  isAuthenticated,
+  isEnabled,
+  procedure,
+  router,
+  errors
+} from "#lib";
 import {
   FullContentGroup,
   FullContentPiece,
   FullContents,
   FullGitData,
@@ -37,13 +37,16 @@ import {
   getGitDataCollection,
   getWorkspaceSettingsCollection,
   getWorkspacesCollection,
   githubData
 } from "#database";
-import { ObjectId, UnderscoreID, zodId } from "#lib";
-import { publishContentGroupEvent } from "#routes/content-groups";
-import { publishWorkspaceSettingsEvent } from "#routes/workspace-settings";
+import { UnderscoreID, zodId } from "#lib";
+import {
+  publishContentGroupEvent,
+  publishGitDataEvent,
+  publishWorkspaceSettingsEvent
+} from "#events";
 
 const authenticatedProcedure = procedure.use(isAuthenticated).use(isEnabled);
 const enableFilenameMetadata = async (ctx: AuthenticatedContext): Promise<void> => {
   const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);
   const workspaceSettings = await workspaceSettingsCollection.findOne({
@@ -136,11 +139,11 @@ const githubRouter = router({
       const octokit = await ctx.fastify.github.getInstallationOctokit(
         gitData?.github.installationId
       );
       const { baseDirectory } = gitData.github;
       const basePath = baseDirectory.startsWith("/") ? baseDirectory.slice(1) : baseDirectory;
-      const inputContentProcessor = await createInputContentProcessor(ctx, gitData);
+      const inputContentProcessor = await createInputContentProcessorGitHub(ctx, gitData);
       const syncDirectory = async (
         path: string,
         ancestors: ObjectId[]
       ): Promise<UnderscoreID<FullContentGroup<ObjectId>>> => {
         const syncedPath = path.startsWith("/") ? path.slice(1) : path;
@@ -413,11 +416,11 @@ const githubRouter = router({
         gitData,
         ctx
       );
 
       if (conflicts.length && !input.force) {
-        const outputContentProcessor = await createOutputContentProcessor(ctx, gitData);
+        const outputContentProcessor = await createOutputContentProcessorGitHub(ctx, gitData);
         const contentPieceIds = conflicts.map((conflict) => conflict.contentPieceId);
         const contentPieces = await contentPiecesCollection
           .find({ _id: { $in: contentPieceIds } })
           .toArray();
         const contents = await contentsCollection
@@ -495,11 +498,11 @@ const githubRouter = router({
       const contentPiecesCollection = getContentPiecesCollection(ctx.db);
       const gitData = await gitDataCollection.findOne({ workspaceId: ctx.auth.workspaceId });
 
       if (!gitData?.github) throw errors.notFound("githubData");
 
-      const outputContentProcessor = await createOutputContentProcessor(ctx, gitData);
+      const outputContentProcessor = await createOutputContentProcessorGitHub(ctx, gitData);
       const changedRecords = gitData.records.filter((record) => {
         return record.currentHash !== record.syncedHash;
       });
       const octokit = await ctx.fastify.github.getInstallationOctokit(
         gitData?.github.installationId
@@ -618,11 +621,11 @@ const githubRouter = router({
       const contentPiecesCollection = getContentPiecesCollection(ctx.db);
       const gitData = await gitDataCollection.findOne({ workspaceId: ctx.auth.workspaceId });
 
       if (!gitData?.github) throw errors.notFound("githubData");
 
-      const outputContentProcessor = await createOutputContentProcessor(ctx, gitData);
+      const outputContentProcessor = await createOutputContentProcessorGitHub(ctx, gitData);
       const contentPiece = await contentPiecesCollection.findOne({
         _id: new ObjectId(input.contentPieceId)
       });
 
       if (!contentPiece) throw errors.notFound("contentPiece");
@@ -661,11 +664,11 @@ const githubRouter = router({
       const contentsCollection = getContentsCollection(ctx.db);
       const gitData = await gitDataCollection.findOne({ workspaceId: ctx.auth.workspaceId });
 
       if (!gitData?.github) throw errors.notFound("githubData");
 
-      const inputContentProcessor = await createInputContentProcessor(ctx, gitData);
+      const inputContentProcessor = await createInputContentProcessorGitHub(ctx, gitData);
       const { buffer, metadata, contentHash } = await inputContentProcessor.process(input.content);
       const { date, members, tags, ...restMetadata } = metadata;
 
       await contentsCollection.updateOne(
         {
@@ -720,7 +723,6 @@ const githubRouter = router({
         }
       });
     })
 });
 
-export { githubRouter, createInputContentProcessor, createOutputContentProcessor };
-export type { OutputContentProcessor, InputContentProcessor };
+export { githubRouter };
diff --git a/packages/backend/src/routes/git/github/pull.ts b/packages/backend/src/routes/git/github/pull.ts
index 0538dd3..ce12de3 100644
--- a/packages/backend/src/routes/git/github/pull.ts
+++ b/packages/backend/src/routes/git/github/pull.ts
@@ -1,8 +1,9 @@
-import { createSyncedPieces, createInputContentProcessor } from "./process-content";
+import { createSyncedPieces } from "./synced-pieces";
 import { LexoRank } from "lexorank";
 import { ObjectId, Binary } from "mongodb";
+import { createInputContentProcessorGitHub } from "#lib";
 import {
   FullGitData,
   getContentGroupsCollection,
   getContentPiecesCollection,
   getContentsCollection,
@@ -61,11 +62,11 @@ const processPulledRecords = async (
     path: string;
     contentPieceId: ObjectId;
     pulledContent: string;
     pulledHash: string;
   }> = [];
-  const inputContentProcessor = await createInputContentProcessor(ctx, gitData);
+  const inputContentProcessor = await createInputContentProcessorGitHub(ctx, gitData);
   const createDirectory = async (
     path: string
   ): Promise<UnderscoreID<FullContentGroup<ObjectId>>> => {
     const directories = path.split("/");
     const parentDirectory = directories.slice(0, -1).join("/");
diff --git a/packages/backend/src/routes/git/github/synced-pieces.ts b/packages/backend/src/routes/git/github/synced-pieces.ts
new file mode 100644
index 0000000..1d29af4
--- /dev/null
+++ b/packages/backend/src/routes/git/github/synced-pieces.ts
@@ -0,0 +1,59 @@
+import { ObjectId, Binary } from "mongodb";
+import { convert as convertToSlug } from "url-slug";
+import { FullContentPiece, FullContents } from "#database";
+import { InputContentProcessor, UnderscoreID } from "#lib";
+
+const createSyncedPieces = async (
+  inputs: Array<{
+    path: string;
+    content: string;
+    workspaceId: ObjectId;
+    contentGroupId: ObjectId;
+    order: string;
+  }>,
+  inputContentProcessor: InputContentProcessor
+): Promise<
+  Array<{
+    contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
+    content: UnderscoreID<FullContents<ObjectId>>;
+    contentHash: string;
+  }>
+> => {
+  const inputContentProcessorOutput = await inputContentProcessor.processBatch(
+    inputs.map((input) => input.content)
+  );
+
+  return inputs.map((input, index) => {
+    const filename = input.path.split("/").pop() || "";
+    const { buffer, contentHash, metadata } = inputContentProcessorOutput[index];
+    const { members, tags, date, ...inputMetadata } = metadata;
+    const contentPiece: UnderscoreID<FullContentPiece<ObjectId>> = {
+      _id: new ObjectId(),
+      workspaceId: input.workspaceId,
+      contentGroupId: input.contentGroupId,
+      order: input.order,
+      members: [],
+      slug: convertToSlug(filename),
+      tags: [],
+      title: filename,
+      filename,
+      ...inputMetadata,
+      ...(date && { date: new Date(date) }),
+      ...(members && { members: members.map((memberId) => new ObjectId(memberId)) }),
+      ...(tags && { tags: tags.map((tagId) => new ObjectId(tagId)) })
+    };
+    const content = {
+      _id: new ObjectId(),
+      contentPieceId: contentPiece._id,
+      content: new Binary(buffer)
+    };
+
+    return {
+      contentPiece,
+      contentHash,
+      content
+    };
+  });
+};
+
+export { createSyncedPieces };
diff --git a/packages/backend/src/routes/git/index.ts b/packages/backend/src/routes/git/index.ts
index 34f1983..71f5458 100644
--- a/packages/backend/src/routes/git/index.ts
+++ b/packages/backend/src/routes/git/index.ts
@@ -1,17 +1,11 @@
 import { githubRouter } from "./github";
-import { GitDataEvent, publishGitDataEvent } from "./events";
 import { processRecords } from "./process-records";
-import {
-  createGenericInputContentProcessor,
-  createGenericOutputContentProcessor
-} from "./process-content";
 import { z } from "zod";
-import { procedure, router } from "#lib/trpc";
+import { publishGitDataEvent, subscribeToGitDataEvents } from "#events";
+import { procedure, router, errors, isAuthenticated } from "#lib";
 import { getGitDataCollection, gitData } from "#database";
-import { errors, isAuthenticated } from "#lib";
-import { createEventSubscription } from "#lib/pub-sub";
 
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const gitRouter = router({
   github: githubRouter,
   config: authenticatedProcedure
@@ -57,10 +51,10 @@ const gitRouter = router({
       if (!deletedCount) throw errors.notFound("gitData");
 
       publishGitDataEvent(ctx, `${ctx.auth.workspaceId}`, { action: "reset", data: {} });
     }),
   changes: authenticatedProcedure.input(z.void()).subscription(async ({ ctx }) => {
-    return createEventSubscription<GitDataEvent>(ctx, `gitData:${ctx.auth.workspaceId}`);
+    return subscribeToGitDataEvents(ctx, `${ctx.auth.workspaceId}`);
   })
 });
 
-export { gitRouter, createGenericInputContentProcessor, createGenericOutputContentProcessor };
+export { gitRouter };
diff --git a/packages/backend/src/routes/git/process-records.ts b/packages/backend/src/routes/git/process-records.ts
index 38f5ad5..ee065f1 100644
--- a/packages/backend/src/routes/git/process-records.ts
+++ b/packages/backend/src/routes/git/process-records.ts
@@ -1,8 +1,9 @@
 import { minimatch } from "minimatch";
+import { ObjectId } from "mongodb";
 import { FullGitData, GitRecord } from "#database";
-import { ObjectId, UnderscoreID } from "#lib";
+import { UnderscoreID } from "#lib";
 
 type RecordsProcessor = (gitData: UnderscoreID<FullGitData<ObjectId>>) => GitRecord<ObjectId>[];
 
 const processRecordsGitHub: RecordsProcessor = (gitData) => {
   if (!gitData.github) return [];
diff --git a/packages/backend/src/routes/index.ts b/packages/backend/src/routes/index.ts
index af90405..752e54e 100644
--- a/packages/backend/src/routes/index.ts
+++ b/packages/backend/src/routes/index.ts
@@ -13,20 +13,16 @@ import { verificationRouter } from "./verification";
 import { authRouter } from "./auth";
 import { contentGroupsRouter } from "./content-groups";
 import { extensionsRouter } from "./extensions";
 import { commentsRouter } from "./comments";
 import { variantsRouter } from "./variants";
-import {
-  createGenericInputContentProcessor,
-  createGenericOutputContentProcessor,
-  gitRouter
-} from "./git";
+import { gitRouter } from "./git";
 import { searchRouter } from "./search";
 import { transformersRouter } from "./transformers";
 import type { TRPCClientError } from "@trpc/client";
-import { Context, createContext } from "#lib/context";
-import { router } from "#lib/trpc";
+import { Context, createContext } from "#lib";
+import { router } from "#lib";
 
 const appRouter = router({
   auth: authRouter,
   users: usersRouter,
   utils: utilsRouter,
@@ -52,13 +48,8 @@ const appRouter = router({
 type Router = typeof appRouter;
 type ClientError = TRPCClientError<Router> & {
   data: TRPCClientError<Router>["data"] & { cause?: { code: string } & Record<string, string> };
 };
 
-export {
-  appRouter,
-  createContext,
-  createGenericInputContentProcessor,
-  createGenericOutputContentProcessor
-};
+export { appRouter, createContext };
 export type * from "#database";
 export type { ClientError, Router, PreviewData, HostConfig, Context };
diff --git a/packages/backend/src/routes/roles.ts b/packages/backend/src/routes/roles.ts
index b18e92b..7a82dfd 100644
--- a/packages/backend/src/routes/roles.ts
+++ b/packages/backend/src/routes/roles.ts
@@ -1,31 +1,17 @@
 import { z } from "zod";
 import { ObjectId } from "mongodb";
-import { procedure, router } from "#lib/trpc";
-import { isAuthenticated } from "#lib/middleware";
-import { zodId } from "#lib/mongo";
 import {
-  Role,
   baseRoleType,
   getRolesCollection,
   role,
   getWorkspaceMembershipsCollection,
   getUsersCollection
 } from "#database";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { updateSessionRole } from "#lib/session";
-
-type RoleEvent =
-  | {
-      action: "create";
-      data: Role;
-    }
-  | { action: "update"; data: Partial<Role> & { id: string } }
-  | { action: "delete"; data: { id: string; newRole: Role } };
-
-const publishEvent = createEventPublisher((workspaceId) => `roles:${workspaceId}`);
+import { zodId, isAuthenticated, procedure, router, updateSessionRole, errors } from "#lib";
+import { publishRoleEvent, subscribeToRoleEvents } from "#events";
+
 const basePath = "/roles";
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const rolesRouter = router({
   list: authenticatedProcedure
     .meta({
@@ -61,11 +47,11 @@ const rolesRouter = router({
         id: `${_id}`,
         ...role
       }));
     }),
   changes: authenticatedProcedure.input(z.void()).subscription(({ ctx }) => {
-    return createEventSubscription<RoleEvent>(ctx, `roles:${ctx.auth.workspaceId}`);
+    return subscribeToRoleEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   get: authenticatedProcedure
     .meta({
       openapi: { method: "GET", path: basePath, protect: true },
       permissions: { token: ["roles:read"] }
@@ -134,11 +120,11 @@ const rolesRouter = router({
             permissions: input.permissions
           }
         }
       );
       updateSessionRole(ctx, input.id);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishRoleEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: {
           ...input
         }
       });
@@ -159,11 +145,11 @@ const rolesRouter = router({
         description: input.description,
         permissions: input.permissions
       };
 
       await rolesCollection.insertOne(role);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishRoleEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: {
           ...input,
           id: `${role._id}`
         }
@@ -209,11 +195,11 @@ const rolesRouter = router({
           $set: {
             roleId: viewerRole?._id
           }
         }
       );
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishRoleEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: {
           id: input.id,
           newRole: {
             permissions: viewerRole.permissions,
diff --git a/packages/backend/src/routes/search.ts b/packages/backend/src/routes/search.ts
index 85a27eb..e243024 100644
--- a/packages/backend/src/routes/search.ts
+++ b/packages/backend/src/routes/search.ts
@@ -1,9 +1,9 @@
 import { z } from "zod";
-import { isAuthenticated, isEnabled } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import { errors, zodId } from "#lib";
+import { ObjectId } from "mongodb";
+import { errors, zodId, procedure, router, isAuthenticated, isEnabled } from "#lib";
+import { contentPiece, getContentPiecesCollection } from "#database";
 
 const authenticatedProcedure = procedure.use(isAuthenticated).use(isEnabled);
 const basePath = "/search";
 const searchRouter = router({
   search: authenticatedProcedure
@@ -22,25 +22,51 @@ const searchRouter = router({
     )
     .output(
       z.array(
         z.object({
           contentPieceId: z.string(),
+          contentPiece,
           breadcrumb: z.array(z.string()),
           content: z.string()
         })
       )
     )
     .query(async ({ ctx, input }) => {
+      const contentPiecesCollection = getContentPiecesCollection(ctx.db);
       const results = await ctx.fastify.search.search({
         query: input.query,
         workspaceId: ctx.auth.workspaceId,
         limit: input.limit || 8,
         variantId: input.variantId,
         contentPieceId: input.contentPieceId
       });
+      const processedResults = results.data.Get.Content.map(({ _additional, ...result }) => result);
+      const contentPieces = await contentPiecesCollection
+        .find({
+          _id: { $in: processedResults.map(({ contentPieceId }) => new ObjectId(contentPieceId)) }
+        })
+        .toArray();
+
+      return processedResults.map(({ contentPieceId, content, breadcrumb }) => {
+        const { _id, date, contentGroupId, tags, members, ...contentPiece } = contentPieces.find(
+          ({ _id }) => _id.toString() === contentPieceId
+        )!;
 
-      return results.data.Get.Content.map(({ _additional, ...result }) => result);
+        return {
+          contentPieceId,
+          breadcrumb,
+          content,
+          contentPiece: {
+            id: `${_id}`,
+            contentGroupId: `${contentGroupId}`,
+            ...contentPiece,
+            ...(date && { date: date.toISOString() }),
+            ...(tags && { tags: tags.map((tagId) => `${tagId}`) }),
+            ...(members && { members: members.map((members) => `${members}`) })
+          }
+        };
+      });
     }),
   ask: authenticatedProcedure
     .meta({
       openapi: { method: "GET", path: `${basePath}/ask`, protect: true },
       requiredConfig: ["aiSearch"],
diff --git a/packages/backend/src/routes/tags.ts b/packages/backend/src/routes/tags.ts
index 4fe6cd3..8219fa1 100644
--- a/packages/backend/src/routes/tags.ts
+++ b/packages/backend/src/routes/tags.ts
@@ -1,26 +1,13 @@
 import { ObjectId } from "mongodb";
 import { z } from "zod";
-import { zodId } from "#lib/mongo";
-import { stringToRegex } from "#lib/utils";
-import { isAuthenticated } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { ExtendedTag, Tag, getTagsCollection, tag, getContentPiecesCollection } from "#database";
-
-type TagEvent =
-  | { action: "create"; data: Tag }
-  | { action: "update"; data: Partial<Tag> & { id: string } }
-  | {
-      action: "delete";
-      data: { id: string };
-    };
+import { stringToRegex, isAuthenticated, procedure, router, errors, zodId } from "#lib";
+import { ExtendedTag, getTagsCollection, tag, getContentPiecesCollection } from "#database";
+import { publishTagEvent, subscribeToTagEvents } from "#events";
 
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/tags";
-const publishEvent = createEventPublisher<TagEvent>((workspaceId) => `tags:${workspaceId}`);
 const tagsRouter = router({
   get: authenticatedProcedure
     .meta({
       openapi: { method: "GET", path: basePath, protect: true },
       permissions: { token: ["tags:read"] }
@@ -70,11 +57,11 @@ const tagsRouter = router({
         }
       );
 
       if (!matchedCount) throw errors.notFound("tag");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTagEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: input
       });
     }),
   create: authenticatedProcedure
@@ -92,11 +79,11 @@ const tagsRouter = router({
         workspaceId: ctx.auth.workspaceId,
         value: (input.label || "").toLowerCase().replace(/\s/g, "_")
       };
 
       await tagsCollection.insertOne(tag);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTagEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: {
           ...input,
           id: `${tag._id}`
         }
@@ -158,11 +145,11 @@ const tagsRouter = router({
           $pull: {
             tags: tagId
           }
         }
       );
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTagEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: { id: input.id }
       });
     }),
   search: authenticatedProcedure
@@ -186,10 +173,10 @@ const tagsRouter = router({
       return tags.map((tag) => {
         return { ...tag, id: `${tag._id}` };
       });
     }),
   changes: authenticatedProcedure.input(z.void()).subscription(({ ctx }) => {
-    return createEventSubscription<TagEvent>(ctx, `tags:${ctx.auth.workspaceId}`);
+    return subscribeToTagEvents(ctx, `${ctx.auth.workspaceId}`);
   })
 });
 
 export { tagsRouter };
diff --git a/packages/backend/src/routes/tokens.ts b/packages/backend/src/routes/tokens.ts
index fa93ec3..beb16e6 100644
--- a/packages/backend/src/routes/tokens.ts
+++ b/packages/backend/src/routes/tokens.ts
@@ -1,25 +1,22 @@
 import { z } from "zod";
 import { ObjectId } from "mongodb";
 import { nanoid } from "nanoid";
-import { procedure, router } from "#lib/trpc";
-import { AuthenticatedContext, isAuthenticated } from "#lib/middleware";
-import { generateSalt, hashValue } from "#lib/hash";
-import { UnderscoreID, zodId } from "#lib/mongo";
-import { Token, FullToken, getTokensCollection, token } from "#database/tokens";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-
-type TokenEvent =
-  | {
-      action: "create";
-      data: Token;
-    }
-  | { action: "update"; data: Partial<Token> & { id: string } }
-  | { action: "delete"; data: { id: string } };
-
-const publishEvent = createEventPublisher<TokenEvent>((workspaceId) => `tokens:${workspaceId}`);
+import {
+  AuthenticatedContext,
+  isAuthenticated,
+  procedure,
+  router,
+  UnderscoreID,
+  zodId,
+  errors,
+  generateSalt,
+  hashValue
+} from "#lib";
+import { Token, FullToken, getTokensCollection, token } from "#database";
+import { publishTokenEvent, subscribeToTokenEvents } from "#events";
+
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const createToken = async (
   input: Omit<Token, "id">,
   ctx: AuthenticatedContext,
   extensionId?: ObjectId
@@ -73,11 +70,11 @@ const tokensRouter = router({
       const tokensCollection = getTokensCollection(ctx.db);
       const { deletedCount } = await tokensCollection.deleteOne({ _id: new ObjectId(input.id) });
 
       if (deletedCount === 0) throw errors.notFound("token");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTokenEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: {
           id: input.id
         }
       });
@@ -123,11 +120,11 @@ const tokensRouter = router({
     .input(token.omit({ id: true }))
     .output(z.object({ value: z.string(), id: zodId() }))
     .mutation(async ({ ctx, input }) => {
       const { token, value } = await createToken(input, ctx);
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTokenEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: {
           id: `${token._id}`,
           name: token.name || "",
           description: token.description || "",
@@ -159,20 +156,20 @@ const tokensRouter = router({
         }
       );
 
       if (matchedCount === 0) throw errors.notFound("token");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTokenEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: {
           id,
           ...update
         }
       });
     }),
   changes: authenticatedProcedure.input(z.void()).subscription(({ ctx }) => {
-    return createEventSubscription<TokenEvent>(ctx, `tokens:${ctx.auth.workspaceId}`);
+    return subscribeToTokenEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   regenerate: authenticatedProcedure
     .meta({
       permissions: { session: ["manageTokens"] }
     })
diff --git a/packages/backend/src/routes/transformers.ts b/packages/backend/src/routes/transformers.ts
index 5627307..ef60471 100644
--- a/packages/backend/src/routes/transformers.ts
+++ b/packages/backend/src/routes/transformers.ts
@@ -1,27 +1,11 @@
 import { z } from "zod";
-import { isAuthenticated } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { Transformer, getGitDataCollection, transformer } from "#database";
-import { ObjectId, zodId } from "#lib/mongo";
-import { getTransformersCollection } from "#database/transformers";
+import { ObjectId } from "mongodb";
+import { getGitDataCollection, transformer, getTransformersCollection } from "#database";
+import { zodId, errors, procedure, router, isAuthenticated } from "#lib";
+import { publishTransformerEvent, subscribeToTransformerEvents } from "#events";
 
-type TransformersEvent =
-  | {
-      action: "create";
-      data: Transformer & { id: string };
-    }
-  | {
-      action: "delete";
-      data: { id: string };
-    };
-
-const publishEvent = createEventPublisher<TransformersEvent>(
-  (workspaceId) => `transformers:${workspaceId}`
-);
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/transformers";
 const transformersRouter = router({
   create: authenticatedProcedure
     .meta({
@@ -29,19 +13,21 @@ const transformersRouter = router({
       permissions: { session: ["manageWorkspace"], token: ["workspace:write"] }
     })
     .input(transformer.omit({ id: true }))
     .output(z.object({ id: zodId() }))
     .mutation(async ({ ctx, input }) => {
+      const extensionId = ctx.req.headers["x-vrite-extension-id"] as string | undefined;
       const transformersCollection = getTransformersCollection(ctx.db);
       const transformer = {
         _id: new ObjectId(),
         workspaceId: ctx.auth.workspaceId,
+        ...(extensionId && { extensionId: new ObjectId(extensionId) }),
         ...input
       };
 
       await transformersCollection.insertOne(transformer);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishTransformerEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: { ...input, id: `${transformer._id}` }
       });
 
       return { id: `${transformer._id}` };
@@ -69,19 +55,26 @@ const transformersRouter = router({
         workspaceId: ctx.auth.workspaceId
       });
 
       if (!deletedCount) throw errors.notFound("transformer");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
+      publishTransformerEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
     }),
   list: authenticatedProcedure
     .meta({
       openapi: { method: "GET", path: `${basePath}/list`, protect: true },
       permissions: { token: ["workspace:read"] }
     })
     .input(z.void())
-    .output(z.array(transformer.extend({ inUse: z.boolean().optional() })))
+    .output(
+      z.array(
+        transformer.extend({
+          inUse: z.boolean().optional(),
+          extension: z.boolean().optional()
+        })
+      )
+    )
     .query(async ({ ctx }) => {
       const gitDataCollection = getGitDataCollection(ctx.db);
       const transformersCollection = getTransformersCollection(ctx.db);
       const gitData = await gitDataCollection.findOne({
         workspaceId: ctx.auth.workspaceId
@@ -91,22 +84,22 @@ const transformersRouter = router({
           workspaceId: ctx.auth.workspaceId
         })
         .sort("_id", -1)
         .toArray();
 
-      return transformers.map(({ _id, workspaceId, ...transformerData }) => {
+      return transformers.map(({ _id, workspaceId, extensionId, ...transformerData }) => {
         return {
           id: `${_id}`,
           workspaceId: `${workspaceId}`,
           inUse: gitData?.github?.transformer === `${_id}`,
+          ...(extensionId && { extension: true }),
           ...transformerData
         };
       });
     }),
 
   changes: authenticatedProcedure.input(z.void()).subscription(async ({ ctx }) => {
-    return createEventSubscription<TransformersEvent>(ctx, `transformers:${ctx.auth.workspaceId}`);
+    return subscribeToTransformerEvents(ctx, `${ctx.auth.workspaceId}`);
   })
 });
 
 export { transformersRouter };
-export type { TransformersEvent };
diff --git a/packages/backend/src/routes/user-settings.ts b/packages/backend/src/routes/user-settings.ts
index 77aa527..52f79b9 100644
--- a/packages/backend/src/routes/user-settings.ts
+++ b/packages/backend/src/routes/user-settings.ts
@@ -1,43 +1,39 @@
 import { z } from "zod";
-import { isAuthenticated, isAuthenticatedUser } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
 import {
   getWorkspacesCollection,
   getWorkspaceMembershipsCollection,
-  AppearanceSettings,
   appearanceSettings,
   getUserSettingsCollection
 } from "#database";
-import { zodId } from "#lib";
+import { zodId, errors, procedure, router, isAuthenticated, isAuthenticatedUser } from "#lib";
+import { publishUserSettingsEvent, subscribeToUserSettingsEvents } from "#events";
 
-type UserSettingsEvent = { action: "update"; data: Partial<AppearanceSettings> };
-
-const publishEvent = createEventPublisher<UserSettingsEvent>((userId) => `userSettings:${userId}`);
 const authenticatedUserProcedure = procedure.use(isAuthenticatedUser);
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/user-settings";
 const userSettingsRouter = router({
   update: authenticatedUserProcedure
     .meta({
       openapi: { method: "PUT", path: basePath, protect: true },
       permissions: { token: ["userSettings:write"] }
     })
-    .input(appearanceSettings.partial())
+    .input(appearanceSettings.omit({ codeEditorTheme: true }).partial())
     .output(z.void())
     .mutation(async ({ ctx, input }) => {
       const userSettingsCollection = getUserSettingsCollection(ctx.db);
       const { matchedCount } = await userSettingsCollection.updateOne(
         { userId: ctx.auth.userId },
         { $set: { ...input } }
       );
 
       if (!matchedCount) throw errors.notFound("userSettings");
 
-      publishEvent(ctx, `${ctx.auth.userId}`, { action: "update", data: input });
+      publishUserSettingsEvent(ctx, `${ctx.auth.userId}`, {
+        action: "update",
+        data: { ...input, ...(input.uiTheme ? { codeEditorTheme: input.uiTheme } : {}) }
+      });
     }),
   get: authenticatedUserProcedure
     .meta({
       openapi: { method: "GET", path: basePath, protect: true },
       permissions: { token: ["userSettings:read"] }
@@ -51,11 +47,11 @@ const userSettingsRouter = router({
       });
 
       if (!userSettings) throw errors.notFound("userSettings");
 
       return {
-        codeEditorTheme: userSettings.codeEditorTheme,
+        codeEditorTheme: userSettings.uiTheme,
         uiTheme: userSettings.uiTheme,
         accentColor: userSettings.accentColor
       };
     }),
 
@@ -79,11 +75,10 @@ const userSettingsRouter = router({
       if (!workspaceMembership) throw errors.notFound("workspaceMembership");
 
       return `${ctx.auth.workspaceId}`;
     }),
   changes: authenticatedUserProcedure.input(z.void()).subscription(async ({ ctx }) => {
-    return createEventSubscription<UserSettingsEvent>(ctx, `userSettings:${ctx.auth.userId}`);
+    return subscribeToUserSettingsEvents(ctx, `${ctx.auth.userId}`);
   })
 });
 
 export { userSettingsRouter };
-export type { UserSettingsEvent };
diff --git a/packages/backend/src/routes/users.ts b/packages/backend/src/routes/users.ts
index 7cf7a12..47ec646 100644
--- a/packages/backend/src/routes/users.ts
+++ b/packages/backend/src/routes/users.ts
@@ -1,35 +1,17 @@
 import { z } from "zod";
 import { ObjectId } from "mongodb";
 import { nanoid } from "nanoid";
-import { hashValue } from "#lib/hash";
-import { isAuthenticated } from "#lib/middleware";
-import { UnderscoreID } from "#lib/mongo";
-import { procedure, router } from "#lib/trpc";
-import {
-  FullUser,
-  Profile,
-  VerificationDetails,
-  getUsersCollection,
-  profile,
-  verificationDetails
-} from "#database/users";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { stringToRegex } from "#lib/utils";
+import { procedure, router, errors, UnderscoreID, isAuthenticated, hashValue } from "#lib";
+import { FullUser, getUsersCollection, profile, verificationDetails } from "#database/users";
+import { publishUserEvent, subscribeToUserEvents } from "#events";
 
-type UserEvent = {
-  action: "update";
-  data: Partial<Profile> & { id: string } & Partial<VerificationDetails>;
-};
-
-const publishEvent = createEventPublisher<UserEvent>((userId: string) => `user:${userId}`);
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/profile";
 const usersRouter = router({
   changes: authenticatedProcedure.input(z.void()).subscription(async ({ ctx }) => {
-    return createEventSubscription<UserEvent>(ctx, `user:${ctx.auth.userId}`);
+    return subscribeToUserEvents(ctx, `${ctx.auth.userId}`);
   }),
   get: authenticatedProcedure
     .meta({
       openapi: { method: "GET", path: `${basePath}`, protect: true },
       permissions: { token: ["profile:read"] }
@@ -116,11 +98,11 @@ const usersRouter = router({
         { _id: ctx.auth.userId },
         {
           $set: update
         }
       );
-      publishEvent(ctx, `${ctx.auth.userId}`, {
+      publishUserEvent(ctx, `${ctx.auth.userId}`, {
         action: "update",
         data: {
           id: `${user._id}`,
           ...input,
           newEmailChangeInVerification: updatedEmail,
diff --git a/packages/backend/src/routes/utils.ts b/packages/backend/src/routes/utils.ts
index 768a4f1..ce362c3 100644
--- a/packages/backend/src/routes/utils.ts
+++ b/packages/backend/src/routes/utils.ts
@@ -1,16 +1,15 @@
 import { z } from "zod";
 import ogs from "open-graph-scraper";
-import { PutObjectCommand } from "@aws-sdk/client-s3";
-import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
-import { nanoid } from "nanoid";
-import mime from "mime-types";
-import { extractPreviewDataFromOpenGraph } from "#lib/utils";
-import { isAuthenticated } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import { hostConfig, HostConfig } from "#plugins/host-config";
+import {
+  procedure,
+  router,
+  errors,
+  extractPreviewDataFromOpenGraph,
+  hostConfig,
+  HostConfig
+} from "#lib";
 
 const previewData = z
   .object({
     image: z.string(),
     icon: z.string(),
@@ -20,11 +19,10 @@ const previewData = z
   })
   .partial();
 
 interface PreviewData extends z.infer<typeof previewData> {}
 
-const authenticatedProcedure = procedure.use(isAuthenticated);
 const utilsRouter = router({
   hostConfig: procedure.output(hostConfig).query(({ ctx }) => {
     return ctx.fastify.hostConfig;
   }),
   openGraph: procedure
diff --git a/packages/backend/src/routes/variants.ts b/packages/backend/src/routes/variants.ts
index 41a34b8..77f6bc2 100644
--- a/packages/backend/src/routes/variants.ts
+++ b/packages/backend/src/routes/variants.ts
@@ -1,36 +1,16 @@
 import { z } from "zod";
-import { isAuthenticated } from "#lib/middleware";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { ObjectId } from "mongodb";
 import {
-  Variant,
   getContentPieceVariantsCollection,
   getContentVariantsCollection,
   getVariantsCollection,
   variant
 } from "#database";
-import { ObjectId, zodId } from "#lib/mongo";
+import { zodId, errors, procedure, router, isAuthenticated } from "#lib";
+import { publishVariantEvent, subscribeToVariantEvents } from "#events";
 
-type VariantsEvent =
-  | {
-      action: "create";
-      data: Variant & { id: string };
-    }
-  | {
-      action: "update";
-      data: Partial<Variant> & { id: string };
-    }
-  | {
-      action: "delete";
-      data: { id: string };
-    };
-
-const publishEvent = createEventPublisher<VariantsEvent>(
-  (workspaceId) => `variants:${workspaceId}`
-);
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/variants";
 const variantsRouter = router({
   create: authenticatedProcedure
     .meta({
@@ -46,11 +26,11 @@ const variantsRouter = router({
         workspaceId: ctx.auth.workspaceId,
         ...input
       };
 
       await variantsCollection.insertOne(variant);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishVariantEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: { ...input, id: `${variant._id}` }
       });
 
       return { id: `${variant._id}` };
@@ -70,11 +50,11 @@ const variantsRouter = router({
         { $set: update }
       );
 
       if (!matchedCount) throw errors.notFound("variant");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "update", data: input });
+      publishVariantEvent(ctx, `${ctx.auth.workspaceId}`, { action: "update", data: input });
     }),
   delete: authenticatedProcedure
     .meta({
       openapi: { method: "DELETE", path: basePath, protect: true },
       permissions: { session: ["manageVariants"], token: ["variants:write"] }
@@ -99,11 +79,11 @@ const variantsRouter = router({
         variantId
       });
 
       if (!deletedCount) throw errors.notFound("variant");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
+      publishVariantEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
       ctx.fastify.search.deleteContent({ variantId, workspaceId: ctx.auth.workspaceId });
     }),
   list: authenticatedProcedure
     .meta({
       openapi: { method: "GET", path: `${basePath}/list`, protect: true },
@@ -129,11 +109,10 @@ const variantsRouter = router({
         };
       });
     }),
 
   changes: authenticatedProcedure.input(z.void()).subscription(async ({ ctx }) => {
-    return createEventSubscription<VariantsEvent>(ctx, `variants:${ctx.auth.workspaceId}`);
+    return subscribeToVariantEvents(ctx, `${ctx.auth.workspaceId}`);
   })
 });
 
 export { variantsRouter };
-export type { VariantsEvent };
diff --git a/packages/backend/src/routes/verification.ts b/packages/backend/src/routes/verification.ts
index a8be104..b6001e4 100644
--- a/packages/backend/src/routes/verification.ts
+++ b/packages/backend/src/routes/verification.ts
@@ -1,46 +1,24 @@
 import { z } from "zod";
 import { ObjectId } from "mongodb";
-import { VerificationDetails, getUsersCollection } from "#database/users";
-import { procedure, router } from "#lib/trpc";
-import { createWorkspace } from "#lib/workspace";
-import * as errors from "#lib/errors";
-import { createSession } from "#lib/session";
-import { isAuthenticatedUser } from "#lib/middleware";
-import { verifyValue } from "#lib";
 import {
-  WorkspaceMembership,
+  getUsersCollection,
+  getUserSettingsCollection,
   getWorkspaceMembershipsCollection
-} from "#database/workspace-memberships";
-import { runWebhooks } from "#lib/webhooks";
-import { createEventPublisher } from "#lib/pub-sub";
-import { getUserSettingsCollection } from "#database";
-
-type VerifyUserEvent = {
-  action: "update";
-  data: { id: string } & Partial<VerificationDetails & { email: string }>;
-};
-type VerifyWorkspaceInviteEvent = {
-  action: "update";
-  data: {
-    id: string;
-    userId: string;
-    pendingInvite?: boolean;
-    profile?: {
-      fullName?: string;
-      username?: string;
-      avatar?: string;
-    };
-  } & Partial<WorkspaceMembership>;
-};
+} from "#database";
+import {
+  runWebhooks,
+  verifyValue,
+  isAuthenticatedUser,
+  createSession,
+  errors,
+  createWorkspace,
+  procedure,
+  router
+} from "#lib";
+import { publishUserEvent, publishWorkspaceMembershipEvent } from "#events";
 
-const publishUserEvent = createEventPublisher<VerifyUserEvent>(
-  (userId: string) => `user:${userId}`
-);
-const publishWorkspaceMembershipEvent = createEventPublisher<VerifyWorkspaceInviteEvent>(
-  (workspaceId: string) => `workspaceMemberships:${workspaceId}`
-);
 const authenticatedUserProcedure = procedure.use(isAuthenticatedUser);
 const verificationRouter = router({
   verifyMagicLink: procedure
     .input(
       z.object({
@@ -106,19 +84,19 @@ const verificationRouter = router({
         const workspaceId = await createWorkspace(user, ctx.fastify, { defaultContent: true });
 
         await userSettingsCollection.insertOne({
           _id: new ObjectId(),
           userId: user._id,
-          codeEditorTheme: "dark",
+          codeEditorTheme: "auto",
           uiTheme: "auto",
           accentColor: "energy",
           currentWorkspaceId: workspaceId
         });
         await createSession(ctx, `${user._id}`);
       } catch (error) {
         // eslint-disable-next-line no-console
-        console.error(error);
+        ctx.fastify.log.error(error);
       }
 
       return "/";
     }),
   verifyWorkspaceInvite: authenticatedUserProcedure
diff --git a/packages/backend/src/routes/versions.ts b/packages/backend/src/routes/versions.ts
deleted file mode 100644
index 5903d14..0000000
--- a/packages/backend/src/routes/versions.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-import { Db, ObjectId } from "mongodb";
-import { z } from "zod";
-import { isAuthenticated } from "#lib/middleware";
-import { UnderscoreID } from "#lib/mongo";
-import { procedure, router } from "#lib/trpc";
-import * as errors from "#lib/errors";
-import {
-  FullVersion,
-  getContentPieceVariantsCollection,
-  getContentPiecesCollection,
-  getContentVariantsCollection,
-  getContentsCollection,
-  getVersionsCollection,
-  version
-} from "#database";
-
-const authenticatedProcedure = procedure.use(isAuthenticated);
-const basePath = "/versions";
-const createVersion = async (
-  db: Db,
-  data: Pick<FullVersion<ObjectId>, "name" | "contentPieceId" | "variantId" | "workspaceId">
-): Promise<ObjectId> => {
-  const versionsCollection = getVersionsCollection(db);
-  const contentPiecesCollection = getContentPiecesCollection(db);
-  const contentsCollection = getContentsCollection(db);
-  const contentPieceVariantsCollection = getContentPieceVariantsCollection(db);
-  const contentVariantsCollection = getContentVariantsCollection(db);
-
-  let contentPiece = await contentPiecesCollection.findOne({
-    _id: data.contentPieceId,
-    workspaceId: data.workspaceId
-  });
-
-  if (!contentPiece) throw errors.notFound("contentPiece");
-
-  let content = await contentsCollection.findOne({
-    contentPieceId: contentPiece._id
-  });
-
-  if (!content) throw errors.notFound("content");
-
-  if (data.variantId) {
-    const contentPieceVariant = await contentPieceVariantsCollection.findOne({
-      contentPieceId: contentPiece._id,
-      variantId: data.variantId,
-      workspaceId: data.workspaceId
-    });
-
-    if (!contentPieceVariant) throw errors.notFound("contentPieceVariant");
-
-    const contentVariant = await contentVariantsCollection.findOne({
-      contentPieceId: contentPiece._id,
-      variantId: data.variantId
-    });
-
-    if (!contentVariant) throw errors.notFound("contentVariant");
-
-    contentPiece = { ...contentPiece, ...contentPieceVariant };
-    content = { ...content, ...contentVariant };
-  }
-
-  const version: UnderscoreID<FullVersion<ObjectId>> = {
-    _id: new ObjectId(),
-    name: data.name,
-    date: new Date(),
-    content: content.content,
-    contentPiece: {
-      members: contentPiece.members,
-      tags: contentPiece.tags,
-      title: contentPiece.title,
-      description: contentPiece.description,
-      slug: contentPiece.slug,
-      canonicalLink: contentPiece.canonicalLink,
-      coverAlt: contentPiece.coverAlt,
-      coverUrl: contentPiece.coverUrl,
-      customData: contentPiece.customData,
-      date: contentPiece.date
-    },
-    contentPieceId: contentPiece._id,
-    variantId: data.variantId,
-    workspaceId: data.workspaceId
-  };
-
-  await versionsCollection.insertOne(version);
-
-  return version._id;
-};
-const versionsRouter = router({
-  create: authenticatedProcedure
-    .input(version.pick({ name: true, contentPieceId: true, variantId: true }))
-    .output(version.pick({ id: true }))
-    .mutation(async ({ ctx, input }) => {
-      const versionId = await createVersion(ctx.db, {
-        name: input.name,
-        contentPieceId: new ObjectId(input.contentPieceId),
-        variantId: new ObjectId(input.variantId),
-        workspaceId: ctx.auth.workspaceId
-      });
-
-      return { id: `${versionId}` };
-    }),
-  delete: authenticatedProcedure
-    .input(
-      version.pick({
-        id: true
-      })
-    )
-    .output(z.void())
-    .mutation(async ({ ctx, input }) => {
-      const versionsCollection = getVersionsCollection(ctx.db);
-      const { deletedCount } = await versionsCollection.deleteOne({
-        _id: new ObjectId(input.id),
-        workspaceId: ctx.auth.workspaceId
-      });
-
-      if (!deletedCount) throw errors.notFound("version");
-    }),
-  restore: authenticatedProcedure
-    .input(
-      version.pick({
-        id: true
-      })
-    )
-    .output(z.void())
-    .mutation(async ({ ctx, input }) => {
-      const versionsCollection = getVersionsCollection(ctx.db);
-      const contentPiecesCollection = getContentPiecesCollection(ctx.db);
-      const contentsCollection = getContentsCollection(ctx.db);
-      const contentPieceVariantsCollection = getContentPieceVariantsCollection(ctx.db);
-      const contentVariantsCollection = getContentVariantsCollection(ctx.db);
-      const version = await versionsCollection.findOne({
-        _id: new ObjectId(input.id),
-        workspaceId: ctx.auth.workspaceId
-      });
-
-      if (!version) throw errors.notFound("version");
-
-      if (version.variantId) {
-        const contentPieceVariantUpdateResult = await contentPieceVariantsCollection.updateOne(
-          {
-            contentPieceId: version.contentPieceId,
-            variantId: version.variantId,
-            workspaceId: ctx.auth.workspaceId
-          },
-          {
-            $set: version.contentPiece
-          }
-        );
-
-        if (!contentPieceVariantUpdateResult.matchedCount) {
-          throw errors.notFound("contentPieceVariant");
-        }
-
-        const contentVariantUpdateResult = await contentVariantsCollection.updateOne(
-          {
-            contentPieceId: version.contentPieceId,
-            variantId: version.variantId
-          },
-          {
-            $set: {
-              content: version.content
-            }
-          }
-        );
-
-        if (!contentVariantUpdateResult.matchedCount) throw errors.notFound("contentVariant");
-
-        return;
-      }
-
-      const contentPieceUpdateResult = await contentPiecesCollection.updateOne(
-        {
-          _id: version.contentPieceId,
-          workspaceId: ctx.auth.workspaceId
-        },
-        { $set: version.contentPiece }
-      );
-
-      if (!contentPieceUpdateResult.matchedCount) throw errors.notFound("contentPiece");
-
-      const contentUpdateResult = await contentsCollection.updateOne(
-        {
-          contentPieceId: version.contentPieceId
-        },
-        { $set: { content: version.content } }
-      );
-
-      if (!contentUpdateResult.matchedCount) throw errors.notFound("content");
-    })
-});
-
-export { versionsRouter, createVersion };
diff --git a/packages/backend/src/routes/webhooks.ts b/packages/backend/src/routes/webhooks.ts
index 7f737f9..d85c350 100644
--- a/packages/backend/src/routes/webhooks.ts
+++ b/packages/backend/src/routes/webhooks.ts
@@ -1,31 +1,11 @@
 import { ObjectId } from "mongodb";
 import { z } from "zod";
-import { procedure, router } from "#lib/trpc";
-import { isAuthenticated } from "#lib/middleware";
-import { UnderscoreID, zodId } from "#lib/mongo";
-import { FullWebhook, Webhook, getWebhooksCollection, webhook } from "#database/webhooks";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-
-type WebhookEvent =
-  | {
-      action: "create";
-      data: Webhook & { id: string };
-    }
-  | {
-      action: "update";
-      data: Partial<Webhook> & { id: string };
-    }
-  | {
-      action: "delete";
-      data: { id: string };
-    };
-
-const publishEvent = createEventPublisher<WebhookEvent>((workspaceId) => {
-  return `webhooks:${workspaceId}`;
-});
+import { FullWebhook, Webhook, getWebhooksCollection, webhook } from "#database";
+import { errors, isAuthenticated, UnderscoreID, zodId, procedure, router } from "#lib";
+import { publishWebhookEvent, subscribeToWebhookEvents } from "#events";
+
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/webhooks";
 const webhooksRouter = router({
   list: authenticatedProcedure
     .meta({
@@ -141,19 +121,19 @@ const webhooksRouter = router({
           contentGroupId: new ObjectId(metadata.contentGroupId)
         };
       } else if (webhook.event.startsWith("contentPiece")) throw errors.serverError();
 
       await webhooksCollection.insertOne(webhook);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWebhookEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: { ...input, id: `${webhook._id}` }
       });
 
       return { id: `${webhook._id}` };
     }),
   changes: authenticatedProcedure.input(z.void()).subscription(({ ctx }) => {
-    return createEventSubscription<WebhookEvent>(ctx, `webhooks:${ctx.auth.workspaceId}`);
+    return subscribeToWebhookEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   update: authenticatedProcedure
     .meta({
       openapi: { method: "PUT", path: basePath, protect: true },
       permissions: { session: ["manageWebhooks"], token: ["webhooks:write"] }
@@ -187,11 +167,11 @@ const webhooksRouter = router({
         }
       );
 
       if (!matchedCount) throw errors.notFound("webhook");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWebhookEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: input
       });
     }),
   delete: authenticatedProcedure
@@ -208,11 +188,11 @@ const webhooksRouter = router({
         workspaceId: ctx.auth.workspaceId
       });
 
       if (!deletedCount) throw errors.notFound("webhook");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWebhookEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: input
       });
     })
 });
diff --git a/packages/backend/src/routes/workspace-memberships.ts b/packages/backend/src/routes/workspace-memberships.ts
index d8ec5ed..d3178f8 100644
--- a/packages/backend/src/routes/workspace-memberships.ts
+++ b/packages/backend/src/routes/workspace-memberships.ts
@@ -1,55 +1,35 @@
-import { procedure, router } from "../lib/trpc";
-import { AuthenticatedContext, isAuthenticated, isAuthenticatedUser } from "../lib/middleware";
-import { UnderscoreID, generateSalt, hashValue, stringToRegex, zodId } from "../lib";
 import { ObjectId } from "mongodb";
 import { z } from "zod";
 import { nanoid } from "nanoid";
 import {
+  contentPieceMember,
   FullWorkspaceMembership,
-  WorkspaceMembership,
   getWorkspaceMembershipsCollection,
-  workspaceMembership
-} from "#database/workspace-memberships";
-import * as errors from "#lib/errors";
-import { getWorkspacesCollection, workspace } from "#database/workspaces";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { runWebhooks } from "#lib/webhooks";
-import {
-  Role,
-  contentPieceMember,
+  workspaceMembership,
   getRolesCollection,
   getUsersCollection,
-  profile,
-  role
+  getWorkspacesCollection,
+  workspace
 } from "#database";
-import { updateSessionUser } from "#lib/session";
-
-type WorkspaceMembershipEvent =
-  | { action: "create"; data: { id: string; pendingInvite: boolean } & WorkspaceMembership }
-  | {
-      action: "update";
-      data: {
-        id: string;
-        userId: string;
-        role?: Role;
-        pendingInvite?: boolean;
-        profile?: {
-          fullName?: string;
-          username?: string;
-          avatar?: string;
-        };
-      } & Partial<WorkspaceMembership>;
-    }
-  | {
-      action: "delete";
-      data: { id: string; userId: string };
-    };
-
-const publishEvent = createEventPublisher<WorkspaceMembershipEvent>(
-  (workspaceId) => `workspaceMemberships:${workspaceId}`
-);
+import {
+  AuthenticatedContext,
+  isAuthenticated,
+  procedure,
+  router,
+  isAuthenticatedUser,
+  updateSessionUser,
+  runWebhooks,
+  errors,
+  UnderscoreID,
+  generateSalt,
+  hashValue,
+  stringToRegex,
+  zodId
+} from "#lib";
+import { publishWorkspaceMembershipEvent, subscribeToWorkspaceMembershipEvents } from "#events";
+
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const authenticatedUserProcedure = procedure.use(isAuthenticatedUser);
 const basePath = "/workspace-memberships";
 const removeMemberFromWorkspace = async (ctx: AuthenticatedContext, id?: string): Promise<void> => {
   const workspaceMembershipsCollection = getWorkspaceMembershipsCollection(ctx.db);
@@ -81,11 +61,11 @@ const removeMemberFromWorkspace = async (ctx: AuthenticatedContext, id?: string)
 
   await workspaceMembershipsCollection.deleteOne({
     _id: workspaceMembership._id
   });
   await updateSessionUser(ctx, `${workspaceMembership.userId}`);
-  publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+  publishWorkspaceMembershipEvent(ctx, `${ctx.auth.workspaceId}`, {
     action: "delete",
     data: { id: `${workspaceMembership._id}`, userId: `${workspaceMembership.userId}` }
   });
   runWebhooks(ctx, "memberRemoved", {
     ...workspaceMembership,
@@ -148,11 +128,11 @@ const workspaceMembershipsRouter = router({
             roleId: new ObjectId(input.roleId)
           }
         }
       );
       await updateSessionUser(ctx, `${membership.userId}`);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWorkspaceMembershipEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: {
           id: input.id,
           userId: `${membership.userId}`,
           roleId: `${role._id}`,
@@ -330,11 +310,11 @@ const workspaceMembershipsRouter = router({
       openapi: { method: "POST", path: basePath, protect: true },
       permissions: { session: ["manageWorkspace"], token: ["workspaceMemberships:write"] }
     })
     .input(
       z.object({
-        email: z.string().email(),
+        email: z.string().email().max(320),
         name: z.string(),
         roleId: zodId()
       })
     )
     .output(z.void())
@@ -366,25 +346,22 @@ const workspaceMembershipsRouter = router({
         workspaceId: `${ctx.auth.workspaceId}`,
         senderUserId: `${ctx.auth.userId}`,
         inviteeName: input.name,
         membershipId: `${workspaceMembership._id}`
       });
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWorkspaceMembershipEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "create",
         data: {
           ...input,
           id: `${workspaceMembership._id}`,
           pendingInvite: true
         }
       });
       runWebhooks(ctx, "memberInvited", { ...input, id: `${workspaceMembership._id}` });
     }),
   changes: authenticatedProcedure.subscription(({ ctx }) => {
-    return createEventSubscription<WorkspaceMembershipEvent>(
-      ctx,
-      `workspaceMemberships:${ctx.auth.workspaceId}`
-    );
+    return subscribeToWorkspaceMembershipEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   delete: authenticatedProcedure
     .meta({
       openapi: { method: "DELETE", path: basePath, protect: true },
       permissions: { session: ["manageWorkspace"], token: ["workspaceMemberships:write"] }
diff --git a/packages/backend/src/routes/workspace-settings.ts b/packages/backend/src/routes/workspace-settings.ts
index 51cc01b..67b0627 100644
--- a/packages/backend/src/routes/workspace-settings.ts
+++ b/packages/backend/src/routes/workspace-settings.ts
@@ -1,39 +1,17 @@
-import { procedure, router } from "../lib/trpc";
-import { isAuthenticated } from "../lib/middleware";
 import { z } from "zod";
 import zodToJsonSchema from "zod-to-json-schema";
 import { ObjectId } from "mongodb";
 import {
   FullWorkspaceSettings,
-  WorkspaceSettings,
-  wrapper,
   getWorkspaceSettingsCollection,
   prettierConfig,
-  workspaceSettings,
-  Wrapper
+  workspaceSettings
 } from "#database/workspace-settings";
-import * as errors from "#lib/errors";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
+import { errors, isAuthenticated, procedure, router } from "#lib";
+import { subscribeToWorkspaceSettingsEvents, publishWorkspaceSettingsEvent } from "#events";
 
-type WorkspaceSettingsEvent =
-  | {
-      action: "update";
-      data: Partial<Omit<WorkspaceSettings, "id">>;
-    }
-  | {
-      action: "createWrapper";
-      data: Wrapper;
-    }
-  | {
-      action: "deleteWrapper";
-      data: Pick<Wrapper, "key">;
-    };
-
-const publishEvent = createEventPublisher<WorkspaceSettingsEvent>((workspaceId) => {
-  return `workspaceSettings:${workspaceId}`;
-});
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const basePath = "/workspace-settings";
 const workspaceSettingsRouter = router({
   get: authenticatedProcedure
     .meta({
@@ -56,121 +34,25 @@ const workspaceSettingsRouter = router({
         id: `${workspaceSettings._id}`,
         prettierConfig: workspaceSettings.prettierConfig,
         metadata: workspaceSettings.metadata,
         marks: workspaceSettings.marks,
         blocks: workspaceSettings.blocks,
-        embeds: workspaceSettings.embeds,
-        wrappers: workspaceSettings.wrappers || []
-      };
-    }),
-  createWrapper: authenticatedProcedure
-    .meta({
-      openapi: { method: "POST", path: `${basePath}/wrapper`, protect: true },
-      permissions: { session: ["manageWorkspace"], token: ["workspace:write"] }
-    })
-    .input(wrapper)
-    .output(z.object({ key: wrapper.shape.key }))
-    .mutation(async ({ input, ctx }) => {
-      const extensionId = ctx.req.headers["x-vrite-extension-id"] as string | undefined;
-      const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);
-      const workspaceSettings = await workspaceSettingsCollection.findOne({
-        workspaceId: ctx.auth.workspaceId
-      });
-
-      if (!workspaceSettings) throw errors.notFound("workspaceSettings");
-
-      const sameKeyWrapperIndex =
-        workspaceSettings.wrappers?.findIndex((wrapper) => wrapper.key === input.key) || -1;
-
-      if (sameKeyWrapperIndex >= 0) {
-        await workspaceSettingsCollection.updateOne(
-          {
-            workspaceId: ctx.auth.workspaceId
-          },
-          {
-            $set: {
-              wrappers: (workspaceSettings.wrappers || []).map((item, index) => {
-                if (index === sameKeyWrapperIndex) {
-                  return {
-                    ...item,
-                    ...input,
-                    ...(extensionId && { extension: item.extension || true })
-                  };
-                }
-
-                return item;
-              })
-            }
-          }
-        );
-      } else {
-        await workspaceSettingsCollection.updateOne(
-          {
-            workspaceId: ctx.auth.workspaceId
-          },
-          {
-            $push: {
-              wrappers: {
-                ...input,
-                ...(extensionId && { extension: true })
-              }
-            }
-          }
-        );
-      }
-
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
-        action: "createWrapper",
-        data: input
-      });
-
-      return {
-        key: input.key
+        embeds: workspaceSettings.embeds
       };
     }),
-  deleteWrapper: authenticatedProcedure
-    .meta({
-      openapi: { method: "DELETE", path: `${basePath}/wrapper`, protect: true },
-      permissions: { session: ["manageWorkspace"], token: ["workspace:write"] }
-    })
-    .input(wrapper.pick({ key: true }))
-    .output(z.void())
-    .mutation(async ({ input, ctx }) => {
-      const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);
-
-      await workspaceSettingsCollection.updateOne(
-        {
-          workspaceId: ctx.auth.workspaceId
-        },
-        {
-          $pull: {
-            wrappers: {
-              key: input.key
-            }
-          }
-        }
-      );
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
-        action: "deleteWrapper",
-        data: input
-      });
-    }),
   changes: authenticatedProcedure.input(z.void()).subscription(({ ctx }) => {
-    return createEventSubscription<WorkspaceSettingsEvent>(
-      ctx,
-      `workspaceSettings:${ctx.auth.workspaceId}`
-    );
+    return subscribeToWorkspaceSettingsEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   update: authenticatedProcedure
     .meta({
       openapi: { method: "PUT", path: basePath, protect: true },
       permissions: { session: ["manageWorkspace"], token: ["workspace:write"] }
     })
     .input(
       workspaceSettings
         .partial()
-        .omit({ id: true, prettierConfig: true, wrappers: true })
+        .omit({ id: true, prettierConfig: true })
         .extend({ prettierConfig: z.string().optional() })
     )
     .output(z.void())
     .mutation(async ({ ctx, input }) => {
       const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);
@@ -194,11 +76,11 @@ const workspaceSettingsRouter = router({
         }
       );
 
       if (!matchedCount) throw errors.notFound("workspaceSettings");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWorkspaceSettingsEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: input
       });
     }),
   prettierSchema: procedure
@@ -208,6 +90,6 @@ const workspaceSettingsRouter = router({
     .query(() => {
       return zodToJsonSchema(prettierConfig);
     })
 });
 
-export { workspaceSettingsRouter, publishEvent as publishWorkspaceSettingsEvent };
+export { workspaceSettingsRouter };
diff --git a/packages/backend/src/routes/workspaces.ts b/packages/backend/src/routes/workspaces.ts
index 48b9f46..779a79d 100644
--- a/packages/backend/src/routes/workspaces.ts
+++ b/packages/backend/src/routes/workspaces.ts
@@ -1,22 +1,18 @@
-import { procedure, router } from "../lib/trpc";
-import { isAuthenticated, isAuthenticatedUser } from "../lib/middleware";
-import { zodId } from "../lib";
 import { z } from "zod";
-import * as errors from "#lib/errors";
-import { Workspace, getWorkspacesCollection, workspace } from "#database/workspaces";
-import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
-import { createWorkspace, deleteWorkspace } from "#lib/workspace";
-import { getUsersCollection } from "#database";
+import {
+  errors,
+  createWorkspace,
+  deleteWorkspace,
+  isAuthenticated,
+  isAuthenticatedUser,
+  procedure,
+  router
+} from "#lib";
+import { getWorkspacesCollection, workspace, getUsersCollection } from "#database";
+import { subscribeToWorkspaceEvents, publishWorkspaceEvent } from "#events";
 
-type WorkspaceEvent =
-  | { action: "update"; data: Partial<Workspace> & { id: string } }
-  | { action: "delete"; data: { id: string } };
-
-const publishEvent = createEventPublisher<WorkspaceEvent>((workspaceId) => {
-  return `workspace:${workspaceId}`;
-});
 const authenticatedProcedure = procedure.use(isAuthenticated);
 const authenticatedUserProcedure = procedure.use(isAuthenticatedUser);
 const basePath = "/workspace";
 const workspacesRouter = router({
   get: authenticatedProcedure
@@ -40,11 +36,11 @@ const workspacesRouter = router({
         logo: workspace.logo,
         description: workspace.description
       };
     }),
   changes: authenticatedProcedure.subscription(({ ctx }) => {
-    return createEventSubscription<WorkspaceEvent>(ctx, `workspace:${ctx.auth.workspaceId}`);
+    return subscribeToWorkspaceEvents(ctx, `${ctx.auth.workspaceId}`);
   }),
   update: authenticatedProcedure
     .meta({
       permissions: { session: ["manageWorkspace"] }
     })
@@ -59,11 +55,11 @@ const workspacesRouter = router({
         }
       );
 
       if (!matchedCount) throw errors.notFound("workspace");
 
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWorkspaceEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "update",
         data: input
       });
     }),
   create: authenticatedUserProcedure
@@ -92,11 +88,11 @@ const workspacesRouter = router({
     })
     .input(z.void())
     .output(z.void())
     .mutation(async ({ ctx }) => {
       await deleteWorkspace(ctx.auth.workspaceId, ctx.fastify);
-      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
+      publishWorkspaceEvent(ctx, `${ctx.auth.workspaceId}`, {
         action: "delete",
         data: {
           id: `${ctx.auth.workspaceId}`
         }
       });
diff --git a/packages/backend/src/server.ts b/packages/backend/src/server.ts
index 9ecfccd..d00bb37 100644
--- a/packages/backend/src/server.ts
+++ b/packages/backend/src/server.ts
@@ -1,58 +1,94 @@
-import { OAuthPlugin } from "./plugins/oauth";
-import { s3Plugin } from "./plugins/s3";
-import { mailPlugin } from "./plugins/email";
-import { sessionPlugin } from "./plugins/session";
-import { pubSubPlugin } from "./plugins/pub-sub";
 import { envSchema } from "./env";
-import { databasePlugin } from "./plugins/database";
 import createFastify, { FastifyInstance } from "fastify";
 import envPlugin from "@fastify/env";
 import mongoPlugin from "@fastify/mongodb";
 import redisPlugin from "@fastify/redis";
 import jwtPlugin from "@fastify/jwt";
 import cookiePlugin from "@fastify/cookie";
 import zodToJsonSchema from "zod-to-json-schema";
-import { ZodRawShape } from "zod";
-import { gitSyncPlugin, hostConfigPlugin, searchPlugin } from "#plugins";
+import {
+  gitSyncPlugin,
+  hostConfigPlugin,
+  searchPlugin,
+  databasePlugin,
+  pubSubPlugin,
+  sessionPlugin,
+  mailPlugin,
+  s3Plugin,
+  OAuthPlugin
+} from "#plugins";
 
-const createServer = async (envSchemaExtension?: ZodRawShape): Promise<FastifyInstance> => {
+const createServer = async (
+  pluginOptions: Partial<{
+    database: boolean;
+    pubSub: boolean;
+    storage: boolean;
+    auth: boolean;
+    email: boolean;
+    gitSync: boolean;
+    search: boolean;
+  }>
+): Promise<FastifyInstance> => {
   const server = createFastify({
     maxParamLength: 5000,
     logger: false
   });
 
   // Env
   await server
     .register(envPlugin, {
       dotenv: true,
-      schema: zodToJsonSchema(envSchema.extend(envSchemaExtension || {}))
+      schema: zodToJsonSchema(envSchema)
     })
     .register(hostConfigPlugin);
+
   // Data
-  await server
-    .register(mongoPlugin, {
+  if (pluginOptions.database) {
+    await server.register(mongoPlugin, {
       forceClose: true,
       url: server.config.MONGO_URL
-    })
-    .register(redisPlugin, { url: server.config.REDIS_URL })
-    .register(redisPlugin, { url: server.config.REDIS_URL, namespace: "sub" });
-  await server.register(databasePlugin).register(pubSubPlugin).register(s3Plugin);
+    });
+    await server.register(databasePlugin);
+  }
+
+  if (pluginOptions.pubSub) {
+    await server
+      .register(redisPlugin, { url: server.config.REDIS_URL })
+      .register(redisPlugin, { url: server.config.REDIS_URL, namespace: "sub" });
+    await server.register(pubSubPlugin);
+  }
+
+  if (pluginOptions.storage) {
+    await server.register(s3Plugin);
+  }
+
   // Auth
-  await server
-    .register(cookiePlugin, { secret: server.config.SECRET })
-    .register(jwtPlugin, {
-      secret: server.config.SECRET,
-      cookie: { cookieName: "accessToken", signed: true }
-    })
-    .register(sessionPlugin)
-    .register(OAuthPlugin);
+  if (pluginOptions.auth) {
+    await server
+      .register(cookiePlugin, { secret: server.config.SECRET })
+      .register(jwtPlugin, {
+        secret: server.config.SECRET,
+        cookie: { cookieName: "accessToken", signed: true }
+      })
+      .register(sessionPlugin)
+      .register(OAuthPlugin);
+  }
+
   // Email
-  await server.register(mailPlugin);
+  if (pluginOptions.email) {
+    await server.register(mailPlugin);
+  }
+
   // GitHub sync
-  await server.register(gitSyncPlugin);
-  await server.register(searchPlugin);
+  if (pluginOptions.gitSync) {
+    await server.register(gitSyncPlugin);
+  }
+
+  if (pluginOptions.search) {
+    await server.register(searchPlugin);
+  }
 
   return server;
 };
 
 export { createServer };
diff --git a/packages/components/src/primitives/input.tsx b/packages/components/src/primitives/input.tsx
index 1bca6dd..92f3de1 100644
--- a/packages/components/src/primitives/input.tsx
+++ b/packages/components/src/primitives/input.tsx
@@ -25,10 +25,11 @@ interface InputProps extends JSX.InputHTMLAttributes<HTMLInputElement> {
   value: string;
   wrapperClass?: string;
   suggestions?: string[];
   textarea?: boolean;
   autoResize?: boolean;
+  suggestionsBoxClass?: string;
   ref?: Ref<HTMLInputElement>[1];
   color?: keyof typeof inputColors;
   adornment?(): JSX.Element;
   setValue?(value: string): void;
   onEnter?(event: KeyboardEvent): void;
@@ -203,11 +204,12 @@ const Input: Component<InputProps> = (props) => {
         {(adornment) => <Dynamic component={adornment} />}
       </Show>
       <Show when={suggestions().length > 0 && focused()}>
         <Card
           class={clsx(
-            `:base-2: absolute z-50 flex flex-col p-1 overflow-hidden transition-all duration-300 transform shadow-2xl w-full`
+            `:base-2: absolute z-50 flex flex-col p-1 overflow-hidden transition-all duration-300 transform shadow-2xl w-full`,
+            props.suggestionsBoxClass
           )}
           ref={setBoxRef}
         >
           <div class="flex flex-col w-full h-full overflow-auto scrollbar-sm">
             <For each={suggestions()}>
diff --git a/packages/components/src/primitives/tooltip.tsx b/packages/components/src/primitives/tooltip.tsx
index b6365bf..7a1e1c8 100644
--- a/packages/components/src/primitives/tooltip.tsx
+++ b/packages/components/src/primitives/tooltip.tsx
@@ -74,11 +74,14 @@ const Tooltip: Component<TooltipProps> = (props) => {
     } else {
       setVisible(false);
     }
   };
 
-  document.body.addEventListener("pointermove", onPointerMove);
+  if (typeof document !== "undefined") {
+    document.body.addEventListener("pointermove", onPointerMove);
+  }
+
   controller.onPositionUpdate(updatePosition);
   onMount(() => {
     const referenceElement = referenceRef();
     const floatingElement = floatingRef();
 
@@ -116,11 +119,14 @@ const Tooltip: Component<TooltipProps> = (props) => {
       }
     })
   );
   onCleanup(() => {
     cleanupRef()?.();
-    document.body.removeEventListener("pointermove", onPointerMove);
+
+    if (typeof document !== "undefined") {
+      document.body.removeEventListener("pointermove", onPointerMove);
+    }
   });
 
   return (
     <div
       class={clsx(`:base: relative flex flex-col items-center justify-center`, props.wrapperClass)}
diff --git a/packages/editor/src/code-block.ts b/packages/editor/src/code-block.ts
index 9049dd9..b3669d2 100644
--- a/packages/editor/src/code-block.ts
+++ b/packages/editor/src/code-block.ts
@@ -1,10 +1,12 @@
 import { nodeInputRule } from "./node-input-rule";
 import { Node, mergeAttributes } from "@tiptap/core";
 
 interface CodeBlockAttributes {
   lang?: string;
+  title?: string;
+  meta?: string;
 }
 interface CodeBlockOptions {
   inline: boolean;
   HTMLAttributes: CodeBlockAttributes;
 }
@@ -19,23 +21,16 @@ declare module "@tiptap/core" {
   }
 }
 
 const CodeBlock = Node.create<CodeBlockOptions>({
   name: "codeBlock",
-
   content: "text*",
-
   marks: "",
-
   group: "block",
-
   code: true,
-
   atom: true,
-
   isolating: true,
-
   addOptions() {
     return {
       inline: false,
       HTMLAttributes: {}
     };
@@ -57,10 +52,22 @@ const CodeBlock = Node.create<CodeBlockOptions>({
           }
 
           return language.toLowerCase();
         },
         rendered: false
+      },
+      title: {
+        default: null,
+        parseHTML: (element) => {
+          return element.getAttribute("data-title");
+        }
+      },
+      meta: {
+        default: null,
+        parseHTML: (element) => {
+          return element.getAttribute("data-meta");
+        }
       }
     };
   },
   parseHTML() {
     return [
@@ -75,11 +82,13 @@ const CodeBlock = Node.create<CodeBlockOptions>({
       "pre",
       mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
       [
         "code",
         {
-          class: node.attrs.lang ? `language-${node.attrs.lang}` : null
+          "class": node.attrs.lang ? `language-${node.attrs.lang}` : null,
+          "data-title": node.attrs.title,
+          "data-meta": node.attrs.meta
         },
         0
       ]
     ];
   },
diff --git a/packages/editor/src/element.ts b/packages/editor/src/element.ts
new file mode 100644
index 0000000..f091c22
--- /dev/null
+++ b/packages/editor/src/element.ts
@@ -0,0 +1,117 @@
+import { ExtendedRegExpMatchArray, Node, mergeAttributes, wrappingInputRule } from "@tiptap/core";
+import { nodeInputRule } from "#node-input-rule";
+
+interface ElementAttributes {
+  type?: string;
+  props: Record<string, unknown>;
+}
+
+declare module "@tiptap/core" {
+  interface Commands<ReturnType> {
+    Element: {
+      setElement: (attrs?: ElementAttributes) => ReturnType;
+      toggleElement: (attrs?: ElementAttributes) => ReturnType;
+      unsetElement: () => ReturnType;
+    };
+  }
+}
+
+const Element = Node.create({
+  name: "element",
+  content: "block*",
+  group: "block",
+  isolating: true,
+  defining: true,
+  selectable: true,
+  addAttributes() {
+    return {
+      props: {
+        default: {},
+        parseHTML: (element) => {
+          return JSON.parse(element.getAttribute("data-props") || "{}");
+        }
+      },
+      type: {
+        default: "Element",
+        parseHTML: (element) => {
+          return element.getAttribute("data-type");
+        }
+      }
+    };
+  },
+  parseHTML() {
+    return [
+      {
+        tag: "div[data-element=true]"
+      }
+    ];
+  },
+  renderHTML({ node, HTMLAttributes }) {
+    return [
+      "div",
+      mergeAttributes(HTMLAttributes, {
+        "data-element": "true",
+        "data-type": node.attrs.type,
+        "data-props": JSON.stringify(node.attrs.props)
+      }),
+      0
+    ];
+  },
+  addCommands() {
+    return {
+      setElement: (attrs) => {
+        return ({ commands }) => {
+          return commands.insertContent({
+            type: this.name,
+            attrs: {
+              type: "Element",
+              props: {},
+              ...attrs
+            }
+            // content: [{ type: "paragraph" }]
+          });
+        };
+      },
+      toggleElement: (attrs) => {
+        return ({ commands }) => {
+          return commands.toggleWrap(this.name, attrs);
+        };
+      },
+      unsetElement: () => {
+        return ({ commands }) => {
+          return commands.lift(this.name);
+        };
+      }
+    };
+  },
+  addInputRules() {
+    const getAttributes = (input: ExtendedRegExpMatchArray): Record<string, any> => {
+      const [code] = input;
+      const tagRegex = /^<(\w+?)(?:\s|\n|\/|>)/;
+      const [, tag] = tagRegex.exec(code.trim()) || [];
+
+      if (tag && tag !== "undefined") {
+        return { type: tag, props: {} };
+      }
+
+      return {};
+    };
+
+    return [
+      nodeInputRule({
+        find: /^<.*?.+?\/>$/,
+        type: this.type,
+        getAttributes
+      }),
+      wrappingInputRule({
+        find: /^<.*?.+?>$/,
+        type: this.type,
+        joinPredicate: () => false,
+        getAttributes
+      })
+    ];
+  }
+});
+
+export { Element };
+export type { ElementAttributes };
diff --git a/packages/editor/src/embed.ts b/packages/editor/src/embed.ts
index e209d40..6c7d3ef 100644
--- a/packages/editor/src/embed.ts
+++ b/packages/editor/src/embed.ts
@@ -20,10 +20,11 @@ const Embed = Node.create({
   name: "embed",
   atom: true,
   selectable: true,
   inline: false,
   group: "block",
+  draggable: true,
   addAttributes() {
     return {
       embed: {
         default: null
       },
diff --git a/packages/editor/src/image.ts b/packages/editor/src/image.ts
index d6a1017..b5a6a40 100644
--- a/packages/editor/src/image.ts
+++ b/packages/editor/src/image.ts
@@ -23,10 +23,11 @@ declare module "@tiptap/core" {
   }
 }
 
 const Image = Node.create<ImageOptions>({
   name: "image",
+  draggable: true,
   addOptions() {
     return {
       inline: false,
       cover: false,
       HTMLAttributes: {}
diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts
index 23f0c92..0ffaba5 100644
--- a/packages/editor/src/index.ts
+++ b/packages/editor/src/index.ts
@@ -1,7 +1,7 @@
 export * from "./code-block";
-export * from "./wrapper";
+export * from "./element";
 export * from "./task-item";
 export * from "./list-item";
 export * from "./embed";
 export * from "./image";
 export * from "./document";
diff --git a/packages/editor/src/wrapper.ts b/packages/editor/src/wrapper.ts
deleted file mode 100644
index 14d3e02..0000000
--- a/packages/editor/src/wrapper.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { nodeInputRule } from "./node-input-rule";
-import { Node, mergeAttributes, wrappingInputRule } from "@tiptap/core";
-
-interface WrapperAttributes {
-  name?: string;
-}
-interface WrapperOptions {
-  HTMLAttributes: WrapperAttributes;
-}
-
-declare module "@tiptap/core" {
-  interface Commands<ReturnType> {
-    wrapper: {
-      setWrapper: (attrs?: WrapperAttributes) => ReturnType;
-      toggleWrapper: (attrs?: WrapperAttributes) => ReturnType;
-      unsetWrapper: () => ReturnType;
-    };
-  }
-}
-
-const Wrapper = Node.create<WrapperOptions>({
-  name: "wrapper",
-  content: "block+",
-  group: "block",
-  isolating: true,
-  defining: true,
-  addOptions() {
-    return {
-      HTMLAttributes: {}
-    };
-  },
-  addAttributes() {
-    return {
-      key: {
-        default: null,
-        parseHTML: (element) => {
-          return element.getAttribute("data-key");
-        }
-      }
-    };
-  },
-  parseHTML() {
-    return [
-      {
-        tag: "div[data-wrapper=true]"
-      }
-    ];
-  },
-  renderHTML({ node, HTMLAttributes }) {
-    return [
-      "div",
-      mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
-        "data-wrapper": "true",
-        "data-key": node.attrs.key
-      }),
-      0
-    ];
-  },
-  addCommands() {
-    return {
-      setWrapper: (attrs) => {
-        return ({ commands }) => {
-          return commands.wrapIn(this.name, attrs);
-        };
-      },
-      toggleWrapper: (attrs) => {
-        return ({ commands }) => {
-          return commands.toggleWrap(this.name, attrs);
-        };
-      },
-      unsetWrapper: () => {
-        return ({ commands }) => {
-          return commands.lift(this.name);
-        };
-      }
-    };
-  },
-  addInputRules() {
-    return [
-      wrappingInputRule({
-        find: /(^:::(.*?)\s$)/,
-        type: this.type,
-        getAttributes: (match) => {
-          const [, , key] = match;
-
-          return { key: key.trim() };
-        }
-      })
-    ];
-  }
-});
-
-export { Wrapper };
-export type { WrapperAttributes, WrapperOptions };
diff --git a/packages/emails/src/render-email.tsx b/packages/emails/src/render-email.tsx
index 9d0f334..aed024a 100644
--- a/packages/emails/src/render-email.tsx
+++ b/packages/emails/src/render-email.tsx
@@ -4,26 +4,26 @@ import { VerifyEmail } from "../emails/verify-email";
 import { VerifyPasswordChange } from "../emails/verify-password-change";
 import { WorkspaceInvite } from "../emails/workspace-invite";
 import { render } from "@react-email/render";
 import * as React from "react";
 
-type RenderEmail = typeof renderEmail;
-
 const templateMap = {
   "magic-link": MagicLink,
   "verify-email-change": VerifyEmailChange,
   "verify-email": VerifyEmail,
   "verify-password-change": VerifyPasswordChange,
   "workspace-invite": WorkspaceInvite
 };
-const renderEmail = (<T extends keyof typeof templateMap>(
+const renderEmail = <T extends keyof typeof templateMap>(
   template: T,
   props: Record<string, string>,
   plainText?: boolean
 ): string => {
   const Template = templateMap[template] as React.FC<Record<string, string>>;
 
   return render(<Template {...props} />, { plainText });
-}) as (test: string) => string;
+};
+
+type RenderEmail = typeof renderEmail;
 
 export { renderEmail };
 export type { RenderEmail };
diff --git a/packages/extensions/src/dev/spec.json b/packages/extensions/src/dev/spec.json
index ef6137d..2e2caa3 100644
--- a/packages/extensions/src/dev/spec.json
+++ b/packages/extensions/src/dev/spec.json
@@ -2,11 +2,10 @@
   "name": "dev",
   "displayName": "Dev.to",
   "description": "Automatically publish and update articles on Dev.to",
   "permissions": ["contentGroups:read", "contentPieces:read", "webhooks:read", "webhooks:write"],
   "lifecycle": {
-    "on:install": "install",
     "on:uninstall": "uninstall",
     "on:configure": "configure",
     "on:initConfigurationView": "initConfigurationView",
     "on:initContentPieceView": "initContentPieceView"
   },
diff --git a/packages/extensions/src/hashnode/spec.json b/packages/extensions/src/hashnode/spec.json
index 6fc7227..f9e4377 100644
--- a/packages/extensions/src/hashnode/spec.json
+++ b/packages/extensions/src/hashnode/spec.json
@@ -2,11 +2,10 @@
   "name": "hashnode",
   "displayName": "Hashnode",
   "description": "Automatically publish and update articles on Hashnode",
   "permissions": ["contentGroups:read", "contentPieces:read", "webhooks:read", "webhooks:write"],
   "lifecycle": {
-    "on:install": "install",
     "on:uninstall": "uninstall",
     "on:configure": "configure",
     "on:initConfigurationView": "initConfigurationView",
     "on:initContentPieceView": "initContentPieceView"
   },
diff --git a/packages/extensions/src/mdx/functions/configure.ts b/packages/extensions/src/mdx/functions/configure.ts
new file mode 100644
index 0000000..771a327
--- /dev/null
+++ b/packages/extensions/src/mdx/functions/configure.ts
@@ -0,0 +1,23 @@
+import { ExtensionBaseContext } from "@vrite/extensions";
+
+const configure = async (context: ExtensionBaseContext): Promise<void> => {
+  const transformers = await context.client.transformers.list();
+  const mdxTransformer = transformers.find((transformer) => {
+    return (
+      transformer.label === "MDX" &&
+      transformer.input === "https://extensions.vrite.io/mdx/input" &&
+      transformer.output === "https://extensions.vrite.io/mdx/output"
+    );
+  });
+
+  if (!mdxTransformer) {
+    await context.client.transformers.create({
+      input: "https://extensions.vrite.io/mdx/input",
+      output: "https://extensions.vrite.io/mdx/output",
+      maxBatchSize: 100,
+      label: "MDX"
+    });
+  }
+};
+
+export default configure;
diff --git a/packages/extensions/src/mdx/functions/uninstall.ts b/packages/extensions/src/mdx/functions/uninstall.ts
new file mode 100644
index 0000000..6d83212
--- /dev/null
+++ b/packages/extensions/src/mdx/functions/uninstall.ts
@@ -0,0 +1,23 @@
+import { ExtensionGeneralContext } from "@vrite/extensions";
+
+const uninstall = async (context: ExtensionGeneralContext): Promise<void> => {
+  const transformers = await context.client.transformers.list();
+
+  if (transformers.length > 0) {
+    const mdxTransformer = transformers.find((transformer) => {
+      return (
+        transformer.label === "MDX" &&
+        transformer.input === "https://extensions.vrite.io/mdx/input" &&
+        transformer.output === "https://extensions.vrite.io/mdx/output"
+      );
+    });
+
+    if (mdxTransformer) {
+      await context.client.transformers.delete({
+        id: mdxTransformer?.id
+      });
+    }
+  }
+};
+
+export default uninstall;
diff --git a/packages/extensions/src/mdx/icon-dark.svg b/packages/extensions/src/mdx/icon-dark.svg
new file mode 100644
index 0000000..c58d08f
--- /dev/null
+++ b/packages/extensions/src/mdx/icon-dark.svg
@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+    <path
+        d="M20.3,16.5l-3.9,3.9-4-3.9,1.1-1.1,2.1,2.1V11.8h1.5v5.8l2.1-2.1ZM3.5,15.7l2.7,2.7L9,15.7v4.4h1.5V12L6.2,16.3,2,12v8.1H3.5Z"
+        style="fill:#d2d2d2" />
+    <path d="M28.8,20l-3.1-3.1L22.6,20l-1-1.1,3.1-3.1-3.2-3.2,1.1-1,3.1,3.2,3.2-3.2,1.1,1-3.2,3.2,3.1,3.1Z"
+        style="fill:#f9ac00" />
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/src/mdx/icon.svg b/packages/extensions/src/mdx/icon.svg
new file mode 100644
index 0000000..2aca8df
--- /dev/null
+++ b/packages/extensions/src/mdx/icon.svg
@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+    <path
+        d="M20.3,16.5l-3.9,3.9-4-3.9,1.1-1.1,2.1,2.1V11.8h1.5v5.8l2.1-2.1ZM3.5,15.7l2.7,2.7L9,15.7v4.4h1.5V12L6.2,16.3,2,12v8.1H3.5Z"
+        style="fill:#00000" />
+    <path d="M28.8,20l-3.1-3.1L22.6,20l-1-1.1,3.1-3.1-3.2-3.2,1.1-1,3.1,3.2,3.2-3.2,1.1,1-3.2,3.2,3.1,3.1Z"
+        style="fill:#f9ac00" />
+</svg>
\ No newline at end of file
diff --git a/packages/extensions/src/mdx/spec.json b/packages/extensions/src/mdx/spec.json
new file mode 100644
index 0000000..803b6d5
--- /dev/null
+++ b/packages/extensions/src/mdx/spec.json
@@ -0,0 +1,10 @@
+{
+  "name": "mdx",
+  "displayName": "MDX",
+  "description": "Adds MDX transformers to Git sync",
+  "permissions": ["workspace:write", "workspace:read"],
+  "lifecycle": {
+    "on:uninstall": "uninstall",
+    "on:configure": "configure"
+  }
+}
diff --git a/packages/extensions/src/medium/spec.json b/packages/extensions/src/medium/spec.json
index 87eb242..ad158a2 100644
--- a/packages/extensions/src/medium/spec.json
+++ b/packages/extensions/src/medium/spec.json
@@ -2,11 +2,10 @@
   "name": "medium",
   "displayName": "Medium",
   "description": "Automatically publish articles to Medium",
   "permissions": ["contentGroups:read", "contentPieces:read", "webhooks:read", "webhooks:write"],
   "lifecycle": {
-    "on:install": "install",
     "on:uninstall": "uninstall",
     "on:configure": "configure",
     "on:initConfigurationView": "initConfigurationView",
     "on:initContentPieceView": "initContentPieceView"
   },
diff --git a/packages/sdk/javascript/package.json b/packages/sdk/javascript/package.json
index 9085479..5deeb1c 100644
--- a/packages/sdk/javascript/package.json
+++ b/packages/sdk/javascript/package.json
@@ -1,8 +1,8 @@
 {
   "name": "@vrite/sdk",
-  "version": "0.2.0",
+  "version": "0.3.0",
   "private": false,
   "description": "JavaScript SDK and API client for Vrite - headless CMS for technical content",
   "license": "MIT",
   "type": "module",
   "scripts": {
diff --git a/packages/sdk/javascript/src/api/client.ts b/packages/sdk/javascript/src/api/client.ts
index 2121058..1dc3af4 100644
--- a/packages/sdk/javascript/src/api/client.ts
+++ b/packages/sdk/javascript/src/api/client.ts
@@ -1,7 +1,11 @@
 import { createContentGroupsEndpoints, ContentGroupsEndpoints } from "./content-groups";
-import { ContentPiecesEndpoints, createContentPiecesEndpoints } from "./content-pieces";
+import {
+  ContentPiece,
+  ContentPiecesEndpoints,
+  createContentPiecesEndpoints
+} from "./content-pieces";
 import { APIFetcherConfig, createAPIFetcher } from "./request";
 import { UserSettingsEndpoints, createUserSettingsEndpoints } from "./user-settings";
 import { TagsEndpoints, createTagsEndpoints } from "./tags";
 import { ProfileEndpoints, createProfileEndpoints } from "./profile";
 import { WebhooksEndpoints, createWebhooksEndpoints } from "./webhooks";
@@ -15,10 +19,16 @@ import {
 import { ExtensionEndpoints, createExtensionEndpoints } from "./extension";
 import { VariantsEndpoints, createVariantsEndpoints } from "./variants";
 import { TransformersEndpoints, createTransformersEndpoints } from "./transformers";
 import PolyfilledEventSource from "@sanity/eventsource";
 
+interface SearchResult {
+  contentPieceId: string;
+  contentPiece: Omit<ContentPiece, "locked" | "content" | "coverWidth">;
+  breadcrumb: string[];
+  content: string;
+}
 interface ClientConfig extends APIFetcherConfig {}
 interface Client {
   contentGroups: ContentGroupsEndpoints;
   contentPieces: ContentPiecesEndpoints;
   tags: TagsEndpoints;
@@ -34,31 +44,25 @@ interface Client {
   transformers: TransformersEndpoints;
   search(input: {
     query: string;
     limit?: number;
     variantId?: string;
-    contentPieceID?: string;
-  }): Promise<
-    Array<{
-      contentPieceId: string;
-      breadcrumb: string[];
-      content: string;
-    }>
-  >;
+    contentPieceId?: string;
+  }): Promise<SearchResult[]>;
   ask(input: {
     query: string;
     onChunk?(chunk: string, content: string): void;
     onEnd?(content: string): void;
     onError?(error: string): void;
   }): void;
-  reconfigure(config: ClientConfig): void;
+  useSignal(signal: AbortSignal | null): Client;
+  reconfigure(config: ClientConfig): Client;
 }
 
 const createClient = (config: ClientConfig): Client => {
-  const { sendRequest, reconfigure, getConfig } = createAPIFetcher(config);
-
-  return {
+  const { sendRequest, reconfigure, getConfig, getSignal, useSignal } = createAPIFetcher(config);
+  const client: Client = {
     contentGroups: createContentGroupsEndpoints(sendRequest),
     contentPieces: createContentPiecesEndpoints(sendRequest),
     tags: createTagsEndpoints(sendRequest),
     profile: createProfileEndpoints(sendRequest),
     userSettings: createUserSettingsEndpoints(sendRequest),
@@ -100,12 +104,27 @@ const createClient = (config: ClientConfig): Client => {
         const chunk = decodeURIComponent(event.data);
 
         content += chunk;
         input.onChunk?.(chunk, content);
       });
+      getSignal()?.addEventListener("abort", () => {
+        source.close();
+      });
+      useSignal(null);
     },
-    reconfigure
+    useSignal(signal) {
+      useSignal(signal);
+
+      return client;
+    },
+    reconfigure(config) {
+      reconfigure(config);
+
+      return client;
+    }
   };
+
+  return client;
 };
 
 export { createClient };
-export type { Client };
+export type { Client, SearchResult };
diff --git a/packages/sdk/javascript/src/api/index.ts b/packages/sdk/javascript/src/api/index.ts
index b487d3f..3020ef9 100644
--- a/packages/sdk/javascript/src/api/index.ts
+++ b/packages/sdk/javascript/src/api/index.ts
@@ -1,7 +1,7 @@
 export { createClient } from "./client";
-export type { Client } from "./client";
+export type { Client, SearchResult } from "./client";
 export type { ContentGroup } from "./content-groups";
 export type {
   ContentPiece,
   ContentPieceWithAdditionalData,
   JSONContent,
diff --git a/packages/sdk/javascript/src/api/request.ts b/packages/sdk/javascript/src/api/request.ts
index d3049d3..1e4bfdc 100644
--- a/packages/sdk/javascript/src/api/request.ts
+++ b/packages/sdk/javascript/src/api/request.ts
@@ -17,17 +17,20 @@ type PaginationParams = {
   page?: number;
 };
 interface APIFetcher {
   sendRequest: SendRequest;
   reconfigure: (config: APIFetcherConfig) => void;
+  useSignal: (signal: AbortSignal | null) => void;
   getConfig: () => Required<APIFetcherConfig>;
+  getSignal: () => AbortSignal | null;
 }
 
 const createAPIFetcher = (config: APIFetcherConfig): APIFetcher => {
   let baseURL = config.baseURL || "https://api.vrite.io";
   let extensionId = config.extensionId || "";
   let headers = config.headers || {};
+  let signal: AbortSignal | null = null;
   let { token } = config;
 
   const sendRequest: SendRequest = async (method, path, options) => {
     try {
       const { default: fetch } = await import("isomorphic-unfetch");
@@ -47,14 +50,17 @@ const createAPIFetcher = (config: APIFetcherConfig): APIFetcher => {
             ...(options?.body ? { "Content-Type": "application/json" } : {}),
             ...(extensionId ? { "X-Vrite-Extension-ID": extensionId } : {}),
             ...headers
           },
           body: options?.body ? JSON.stringify(options.body) : null,
+          signal,
           method
         }
       );
 
+      signal = null;
+
       let json = null;
 
       try {
         json = await response.json();
 
@@ -79,19 +85,25 @@ const createAPIFetcher = (config: APIFetcherConfig): APIFetcher => {
     baseURL = config.baseURL || baseURL;
     token = config.token || token;
     extensionId = config.extensionId || extensionId;
     headers = config.headers || headers;
   };
+  const useSignal = (newSignal: AbortSignal | null): void => {
+    signal = newSignal;
+  };
   const getConfig = (): Required<APIFetcherConfig> => {
     return {
       baseURL,
       token,
       extensionId,
       headers
     };
   };
+  const getSignal = (): AbortSignal | null => {
+    return signal;
+  };
 
-  return { sendRequest, reconfigure, getConfig };
+  return { sendRequest, reconfigure, useSignal, getConfig, getSignal };
 };
 
 export { createAPIFetcher };
 export type { SendRequest, APIFetcherConfig, PaginationParams };
diff --git a/packages/sdk/javascript/src/transformers/content-walker.ts b/packages/sdk/javascript/src/transformers/content-walker.ts
index a0f679e..c9869a4 100644
--- a/packages/sdk/javascript/src/transformers/content-walker.ts
+++ b/packages/sdk/javascript/src/transformers/content-walker.ts
@@ -83,31 +83,32 @@ type BlockquoteNode = {
   type: "blockquote";
   content?: Array<
     | ParagraphNode
     | HeadingNode
     | BlockquoteNode
-    | WrapperNode
+    | ElementNode
     | ImageNode
     | CodeBlockNode
     | EmbedNode
     | BulletListNode
     | OrderedListNode
     | TaskListNode
     | HorizontalRuleNode
     | TableNode
   >;
 };
-type WrapperNode = {
-  type: "wrapper";
-  attrs?: {
-    key?: string;
+type ElementNode = {
+  type: "element";
+  attrs: {
+    type: string;
+    props: Record<string, any>;
   };
   content?: Array<
     | ParagraphNode
     | HeadingNode
     | BlockquoteNode
-    | WrapperNode
+    | ElementNode
     | ImageNode
     | CodeBlockNode
     | EmbedNode
     | BulletListNode
     | OrderedListNode
@@ -124,11 +125,13 @@ type ImageNode = {
   };
 };
 type CodeBlockNode = {
   type: "codeBlock";
   attrs?: {
-    lang: string;
+    lang?: string;
+    meta?: string;
+    title?: string;
   };
   content: TextNode[];
 };
 type EmbedNode = {
   type: "embed";
@@ -217,11 +220,11 @@ type DocNode = {
   type: "doc";
   content: Array<
     | ParagraphNode
     | HeadingNode
     | BlockquoteNode
-    | WrapperNode
+    | ElementNode
     | ImageNode
     | CodeBlockNode
     | EmbedNode
     | BulletListNode
     | OrderedListNode
@@ -235,11 +238,11 @@ type JSONContentNode = {
   text: TextNode;
   hardBreak: HardBreakNode;
   paragraph: ParagraphNode;
   heading: HeadingNode;
   blockquote: BlockquoteNode;
-  wrapper: WrapperNode;
+  element: ElementNode;
   image: ImageNode;
   codeBlock: CodeBlockNode;
   embed: EmbedNode;
   bulletList: BulletListNode;
   orderedList: OrderedListNode;
diff --git a/packages/sdk/javascript/src/transformers/output-transformers.ts b/packages/sdk/javascript/src/transformers/output-transformers.ts
index c4a8a77..a764967 100644
--- a/packages/sdk/javascript/src/transformers/output-transformers.ts
+++ b/packages/sdk/javascript/src/transformers/output-transformers.ts
@@ -109,11 +109,11 @@ const gfmOutputTransformer = createOutputTransformer<string>((contentNode) => {
 
     return output;
   };
   const transformContentNode = (
     nodeWalker: JSONContentNodeWalker<
-      JSONContentNode["listItem" | "taskItem" | "blockquote" | "doc" | "wrapper"]
+      JSONContentNode["listItem" | "taskItem" | "blockquote" | "doc" | "element"]
     >
   ): string => {
     return nodeWalker.children
       .map((child) => {
         const nodeType = child.node.type;
@@ -149,13 +149,13 @@ const gfmOutputTransformer = createOutputTransformer<string>((contentNode) => {
             )}\n`;
           case "codeBlock":
             return `\n\`\`\`${child.node.attrs?.lang || ""}\n${transformTextNode(
               child as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
             )}\n\`\`\`\n`;
-          case "wrapper":
+          case "element":
             return `\n${transformContentNode(
-              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
+              child as JSONContentNodeWalker<JSONContentNode["element"]>
             )}\n`;
           case "blockquote":
             return `\n${transformContentNode(
               child as JSONContentNodeWalker<JSONContentNode["blockquote"]>
             )
@@ -323,14 +323,14 @@ const htmlOutputTransformer = createOutputTransformer<string>((contentNode) => {
           type: "checkbox",
           checked: nodeWalker.node.attrs.checked
         })} />${(nodeWalker as JSONContentNodeWalker<JSONContentNode["taskItem"]>).children
           .map(transformContentNode)
           .join("")}</label></li>`;
-      case "wrapper":
+      case "element":
         return `<div ${stringifyAttributes({
-          "data-key": nodeWalker.node.attrs?.key
-        })}>${(nodeWalker as JSONContentNodeWalker<JSONContentNode["wrapper"]>).children
+          "data-type": nodeWalker.node.attrs?.type
+        })}>${(nodeWalker as JSONContentNodeWalker<JSONContentNode["element"]>).children
           .map(transformContentNode)
           .join("")}</div>`;
       case "blockquote":
         return `<blockquote>${(
           nodeWalker as JSONContentNodeWalker<JSONContentNode["blockquote"]>
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f938a75..c7892cc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,29 +8,29 @@ importers:
         specifier: ^7.2.1
         version: 7.2.1
     devDependencies:
       '@typescript-eslint/eslint-plugin':
         specifier: ^6.2.0
-        version: 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.1.6)
+        version: 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.2.2)
       '@typescript-eslint/parser':
         specifier: ^6.2.0
-        version: 6.2.0(eslint@8.45.0)(typescript@5.1.6)
+        version: 6.2.0(eslint@8.45.0)(typescript@5.2.2)
       eslint:
         specifier: ^8.45.0
         version: 8.45.0
       eslint-config-prettier:
         specifier: ^8.8.0
         version: 8.8.0(eslint@8.45.0)
       eslint-config-xtrict:
         specifier: ^3.0.1
-        version: 3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.1.6)
+        version: 3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.2.2)
       eslint-plugin-import:
         specifier: ^2.27.5
         version: 2.27.5(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)
       eslint-plugin-solid:
         specifier: ^0.12.1
-        version: 0.12.1(eslint@8.45.0)(typescript@5.1.6)
+        version: 0.12.1(eslint@8.45.0)(typescript@5.2.2)
       prettier:
         specifier: ^3.0.2
         version: 3.0.2
       prettier-plugin-astro:
         specifier: ^0.11.0
@@ -38,11 +38,11 @@ importers:
       turbo:
         specifier: ^1.10.11
         version: 1.10.11
       typescript:
         specifier: ^5.1.6
-        version: 5.1.6
+        version: 5.2.2
 
   apps/backend/api:
     dependencies:
       '@fastify/cors':
         specifier: ^8.3.0
@@ -59,11 +59,11 @@ importers:
       fastify:
         specifier: ^4.20.0
         version: 4.20.0
       trpc-openapi:
         specifier: ^1.2.0
-        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.2)
+        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.4)
     devDependencies:
       '@vrite/scripts':
         specifier: workspace:*
         version: link:../../../packages/scripts
 
@@ -136,11 +136,11 @@ importers:
       sharp:
         specifier: ^0.32.5
         version: 0.32.5
       trpc-openapi:
         specifier: ^1.2.0
-        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.2)
+        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.4)
     devDependencies:
       '@vrite/scripts':
         specifier: workspace:*
         version: link:../../../packages/scripts
 
@@ -181,56 +181,137 @@ importers:
   apps/backend/extensions:
     dependencies:
       '@fastify/cors':
         specifier: ^8.3.0
         version: 8.3.0
+      '@prettier/sync':
+        specifier: ^0.3.0
+        version: 0.3.0(prettier@3.0.2)
       '@trpc/server':
         specifier: ^10.35.0
         version: 10.35.0
+      '@types/hast':
+        specifier: ^3.0.1
+        version: 3.0.1
+      '@types/html-to-text':
+        specifier: ^9.0.1
+        version: 9.0.1
+      '@types/js-yaml':
+        specifier: ^4.0.6
+        version: 4.0.6
+      '@types/mdast':
+        specifier: ^4.0.1
+        version: 4.0.1
       '@vrite/backend':
         specifier: workspace:*
         version: link:../../../packages/backend
       '@vrite/sdk':
         specifier: workspace:*
         version: link:../../../packages/sdk/javascript
+      dayjs:
+        specifier: ^1.11.9
+        version: 1.11.9
       fastify:
         specifier: ^4.20.0
         version: 4.20.0
+      hast-util-to-html:
+        specifier: ^9.0.0
+        version: 9.0.0
+      html-to-text:
+        specifier: ^9.0.5
+        version: 9.0.5
+      js-yaml:
+        specifier: ^4.1.0
+        version: 4.1.0
+      mdast-util-from-markdown:
+        specifier: ^2.0.0
+        version: 2.0.0
+      mdast-util-frontmatter:
+        specifier: ^2.0.1
+        version: 2.0.1
+      mdast-util-gfm:
+        specifier: ^3.0.0
+        version: 3.0.0
+      mdast-util-mdx:
+        specifier: ^3.0.0
+        version: 3.0.0
+      mdast-util-to-hast:
+        specifier: ^13.0.2
+        version: 13.0.2
+      micromark-extension-frontmatter:
+        specifier: ^2.0.0
+        version: 2.0.0
+      micromark-extension-gfm:
+        specifier: ^3.0.0
+        version: 3.0.0
+      micromark-extension-mdxjs:
+        specifier: ^2.0.0
+        version: 2.0.0
       openai:
         specifier: ^4.0.0
         version: 4.0.0
+      prettier:
+        specifier: ^3.0.2
+        version: 3.0.2
+      remark:
+        specifier: ^15.0.1
+        version: 15.0.1
+      remark-mdx:
+        specifier: ^2.3.0
+        version: 2.3.0
+      remark-parse:
+        specifier: ^11.0.0
+        version: 11.0.0
       trpc-openapi:
         specifier: ^1.2.0
-        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.2)
+        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.4)
+      unist-util-visit:
+        specifier: ^5.0.0
+        version: 5.0.0
     devDependencies:
       '@vrite/scripts':
         specifier: workspace:*
         version: link:../../../packages/scripts
 
   apps/docs:
     dependencies:
+      '@astrojs/mdx':
+        specifier: ^1.1.1
+        version: 1.1.1(astro@3.1.0)
       '@astrojs/sitemap':
         specifier: ^3.0.0
         version: 3.0.0
       '@astrojs/solid-js':
         specifier: ^3.0.1
         version: 3.0.1(solid-js@1.7.11)(vite@4.4.9)
       '@mdi/js':
         specifier: ^7.2.96
         version: 7.2.96
+      '@solid-primitives/scheduled':
+        specifier: ^1.4.0
+        version: 1.4.0(solid-js@1.7.11)
       '@types/marked':
         specifier: ^5.0.1
         version: 5.0.1
       '@unocss/reset':
         specifier: ^0.55.7
         version: 0.55.7
       '@vrite/components':
         specifier: workspace:*
         version: link:../../packages/components
+      '@vrite/sdk':
+        specifier: workspace:*
+        version: link:../../packages/sdk/javascript
       astro:
         specifier: ^3.1.0
         version: 3.1.0(sass@1.64.1)
+      astro-auto-import:
+        specifier: ^0.3.1
+        version: 0.3.1(astro@3.1.0)
+      astro-icon:
+        specifier: ^0.8.1
+        version: 0.8.1
       clsx:
         specifier: ^2.0.0
         version: 2.0.0
       curl-string:
         specifier: ^3.1.0
@@ -245,25 +326,34 @@ importers:
         specifier: ^5.0.1
         version: 5.0.1
       plausible-tracker:
         specifier: ^0.3.8
         version: 0.3.8
+      seamless-scroll-polyfill:
+        specifier: ^2.3.4
+        version: 2.3.4
       shiki:
         specifier: ^0.14.4
         version: 0.14.4
       solid-js:
         specifier: ^1.7.11
         version: 1.7.11
+      tinykeys:
+        specifier: ^2.1.0
+        version: 2.1.0
       typescript:
         specifier: ^5.2.2
         version: 5.2.2
       unocss:
         specifier: ^0.55.7
-        version: 0.55.7(postcss@8.4.29)(vite@4.4.9)
+        version: 0.55.7(postcss@8.4.31)(vite@4.4.9)
+      url-slug:
+        specifier: ^4.0.1
+        version: 4.0.1
       vite:
         specifier: ^4.4.9
-        version: 4.4.9(sass@1.64.1)
+        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
     devDependencies:
       '@astrojs/node':
         specifier: ^6.0.0
         version: 6.0.0(astro@3.1.0)
       astro-robots-txt:
@@ -281,11 +371,11 @@ importers:
       '@astrojs/sitemap':
         specifier: ^2.0.2
         version: 2.0.2
       '@astrojs/solid-js':
         specifier: ^2.2.1
-        version: 2.2.1(@babel/core@7.22.15)(solid-js@1.7.11)(vite@4.4.9)
+        version: 2.2.1(@babel/core@7.23.0)(solid-js@1.7.11)(vite@4.4.9)
       '@fontsource/nunito':
         specifier: ^5.0.8
         version: 5.0.8
       '@mdi/js':
         specifier: ^7.2.96
@@ -332,14 +422,14 @@ importers:
       typescript:
         specifier: ^5.2.2
         version: 5.2.2
       unocss:
         specifier: ^0.55.7
-        version: 0.55.7(postcss@8.4.29)(vite@4.4.9)
+        version: 0.55.7(postcss@8.4.31)(vite@4.4.9)
       vite:
         specifier: ^4.4.9
-        version: 4.4.9(sass@1.64.1)
+        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
     devDependencies:
       astro-robots-txt:
         specifier: ^0.4.1
         version: 0.4.1
 
@@ -357,32 +447,32 @@ importers:
       '@microsoft/fetch-event-source':
         specifier: ^2.0.1
         version: 2.0.1
       '@motionone/solid':
         specifier: ^10.16.2
-        version: 10.16.2(solid-js@1.7.8)
+        version: 10.16.2(solid-js@1.7.11)
       '@octokit/rest':
         specifier: ^20.0.1
         version: 20.0.1
       '@solid-primitives/active-element':
         specifier: ^2.0.15
-        version: 2.0.15(solid-js@1.7.8)
+        version: 2.0.15(solid-js@1.7.11)
       '@solid-primitives/connectivity':
         specifier: ^0.3.15
-        version: 0.3.15(solid-js@1.7.8)
+        version: 0.3.15(solid-js@1.7.11)
       '@solid-primitives/media':
         specifier: ^2.2.3
-        version: 2.2.3(solid-js@1.7.8)
+        version: 2.2.3(solid-js@1.7.11)
       '@solid-primitives/memo':
         specifier: ^1.3.2
-        version: 1.3.2(solid-js@1.7.8)
+        version: 1.3.2(solid-js@1.7.11)
       '@solid-primitives/scheduled':
         specifier: ^1.4.0
-        version: 1.4.0(solid-js@1.7.8)
+        version: 1.4.0(solid-js@1.7.11)
       '@solidjs/router':
         specifier: ^0.8.2
-        version: 0.8.2(solid-js@1.7.8)
+        version: 0.8.2(solid-js@1.7.11)
       '@tiptap/core':
         specifier: 2.1.8
         version: 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/extension-character-count':
         specifier: ^2.1.8
@@ -450,11 +540,11 @@ importers:
       '@vrite/sdk':
         specifier: workspace:*
         version: link:../../packages/sdk/javascript
       '@vrite/tiptap-solid':
         specifier: 1.0.0
-        version: 1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.8)
+        version: 1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.11)
       clsx:
         specifier: ^2.0.0
         version: 2.0.0
       dayjs:
         specifier: ^1.11.9
@@ -467,12 +557,12 @@ importers:
         version: 5.1.2
       minisearch:
         specifier: ^6.1.0
         version: 6.1.0
       monaco-editor:
-        specifier: ^0.40.0
-        version: 0.40.0
+        specifier: ^0.43.0
+        version: 0.43.0
       nanoevents:
         specifier: ^8.0.0
         version: 8.0.0
       nanoid:
         specifier: ^4.0.2
@@ -483,11 +573,11 @@ importers:
       seamless-scroll-polyfill:
         specifier: ^2.3.4
         version: 2.3.4
       solid-js:
         specifier: ^1.7.8
-        version: 1.7.8
+        version: 1.7.11
       sortablejs:
         specifier: ^1.15.0
         version: 1.15.0
       tinykeys:
         specifier: ^2.1.0
@@ -498,11 +588,11 @@ importers:
       url-slug:
         specifier: ^4.0.1
         version: 4.0.1
       y-prosemirror:
         specifier: ^1.2.1
-        version: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
+        version: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
       yjs:
         specifier: ^13.6.7
         version: 13.6.7
     devDependencies:
       '@types/node':
@@ -517,23 +607,23 @@ importers:
       terser:
         specifier: ^5.19.2
         version: 5.19.2
       typescript:
         specifier: ^5.1.6
-        version: 5.1.6
+        version: 5.2.2
       unocss:
         specifier: ^0.55.7
-        version: 0.55.7(postcss@8.4.29)(vite@4.4.7)
+        version: 0.55.7(postcss@8.4.31)(vite@4.4.9)
       vite:
         specifier: ^4.4.7
-        version: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
+        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
       vite-plugin-solid:
         specifier: ^2.7.0
-        version: 2.7.0(solid-js@1.7.8)(vite@4.4.7)
+        version: 2.7.0(solid-js@1.7.11)(vite@4.4.9)
       vite-tsconfig-paths:
         specifier: ^4.2.0
-        version: 4.2.0(typescript@5.1.6)(vite@4.4.7)
+        version: 4.2.0(typescript@5.2.2)(vite@4.4.9)
 
   packages/backend:
     dependencies:
       '@aws-sdk/client-s3':
         specifier: ^3.374.0
@@ -577,11 +667,11 @@ importers:
       '@octokit/types':
         specifier: ^11.1.0
         version: 11.1.0
       '@qdrant/qdrant-js':
         specifier: ^1.4.0
-        version: 1.4.0(typescript@5.1.6)
+        version: 1.4.0(typescript@5.2.2)
       '@sendgrid/mail':
         specifier: ^7.7.0
         version: 7.7.0
       '@tiptap/html':
         specifier: ^2.1.8
@@ -667,17 +757,17 @@ importers:
       trpc-openapi:
         specifier: ^1.2.0
         version: 1.2.0(@trpc/server@10.35.0)(zod@3.21.4)
       typescript:
         specifier: ^5.1.6
-        version: 5.1.6
+        version: 5.2.2
       url-slug:
         specifier: ^4.0.1
         version: 4.0.1
       weaviate-ts-client:
         specifier: ^1.4.0
-        version: 1.4.0(graphql@16.7.1)
+        version: 1.4.0(graphql@16.8.1)
       yjs:
         specifier: ^13.6.7
         version: 13.6.7
       zod:
         specifier: ^3.21.4
@@ -698,20 +788,20 @@ importers:
       '@mdi/js':
         specifier: ^7.2.96
         version: 7.2.96
       '@solid-primitives/active-element':
         specifier: ^2.0.15
-        version: 2.0.15(solid-js@1.7.8)
+        version: 2.0.15(solid-js@1.7.11)
       '@solid-primitives/media':
         specifier: ^2.2.3
-        version: 2.2.3(solid-js@1.7.8)
+        version: 2.2.3(solid-js@1.7.11)
       clsx:
         specifier: ^2.0.0
         version: 2.0.0
       solid-js:
         specifier: ^1.7.8
-        version: 1.7.8
+        version: 1.7.11
 
   packages/editor:
     dependencies:
       '@floating-ui/dom':
         specifier: ^1.4.5
@@ -737,11 +827,11 @@ importers:
       '@tiptap/extension-code':
         specifier: ^2.1.8
         version: 2.1.8(@tiptap/core@2.1.8)
       '@tiptap/extension-code-block-lowlight':
         specifier: ^2.1.8
-        version: 2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.0.3)(@tiptap/pm@2.1.8)
+        version: 2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.1.11)(@tiptap/pm@2.1.8)
       '@tiptap/extension-collaboration':
         specifier: ^2.1.8
         version: 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(y-prosemirror@1.0.20)
       '@tiptap/extension-collaboration-cursor':
         specifier: ^2.1.8
@@ -827,11 +917,11 @@ importers:
       clsx:
         specifier: ^2.0.0
         version: 2.0.0
       solid-js:
         specifier: ^1.7.8
-        version: 1.7.8
+        version: 1.7.11
       url-slug:
         specifier: ^4.0.1
         version: 4.0.1
 
   packages/emails:
@@ -904,17 +994,17 @@ importers:
         specifier: ^5.1.2
         version: 5.1.2
     devDependencies:
       astro:
         specifier: ^2.9.2
-        version: 2.9.2
+        version: 2.10.15
       unbuild:
         specifier: ^1.2.1
         version: 1.2.1
       vite:
         specifier: ^4.4.7
-        version: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
+        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
 
 packages:
 
   /@aashutoshrathi/word-wrap@1.2.6:
     resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
@@ -924,59 +1014,50 @@ packages:
   /@ampproject/remapping@2.2.1:
     resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
     engines: {node: '>=6.0.0'}
     dependencies:
       '@jridgewell/gen-mapping': 0.3.3
-      '@jridgewell/trace-mapping': 0.3.18
+      '@jridgewell/trace-mapping': 0.3.19
 
   /@antfu/install-pkg@0.1.1:
     resolution: {integrity: sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==}
     dependencies:
       execa: 5.1.1
       find-up: 5.0.0
 
   /@antfu/utils@0.7.6:
     resolution: {integrity: sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==}
 
-  /@astrojs/compiler@1.6.2:
-    resolution: {integrity: sha512-2grH0lSm/Su88ZUd1kF0OdR/CT4ClWKvCwVz4yDdpgLgpzXhs1LdO2V58YfSqnx/z+G5EBWv6yEkp3tDG3GQYQ==}
-    dev: true
-
   /@astrojs/compiler@1.8.2:
     resolution: {integrity: sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==}
 
-  /@astrojs/compiler@2.1.0:
-    resolution: {integrity: sha512-Mp+qrNhly+27bL/Zq8lGeUY+YrdoU0eDfIlAeGIPrzt0PnI/jGpvPUdCaugv4zbCrDkOUScFfcbeEiYumrdJnw==}
-
-  /@astrojs/internal-helpers@0.1.1:
-    resolution: {integrity: sha512-+LySbvFbjv2nO2m/e78suleQOGEru4Cnx73VsZbrQgB2u7A4ddsQg3P2T0zC0e10jgcT+c6nNlKeLpa6nRhQIg==}
-    dev: true
+  /@astrojs/compiler@2.2.0:
+    resolution: {integrity: sha512-JvmckEJgg8uXUw8Rs6VZDvN7LcweCHOdcxsCXpC+4KMDC9FaB5t9EH/NooSE+hu/rnACEhsXA3FKmf9wnhb7hA==}
 
   /@astrojs/internal-helpers@0.1.2:
     resolution: {integrity: sha512-YXLk1CUDdC9P5bjFZcGjz+cE/ZDceXObDTXn/GCID4r8LjThuexxi+dlJqukmUpkSItzQqgzfWnrPLxSFPejdA==}
-    dev: false
 
   /@astrojs/internal-helpers@0.2.0:
     resolution: {integrity: sha512-NQ4ppp1CM0HNkKbJNM4saVSfmUYzGlRalF6wx7F6T/MYHYSWGuojY89/oFTy4t8VlOGUCUijlsVNNeziWaUo5g==}
 
   /@astrojs/language-server@1.0.8:
     resolution: {integrity: sha512-gssRxLGb8XnvKpqSzrDW5jdzdFnXD7eBXVkPCkkt2hv7Qzb+SAzv6hVgMok3jDCxpR1aeB+XNd9Qszj2h29iog==}
     hasBin: true
     dependencies:
       '@astrojs/compiler': 1.8.2
-      '@jridgewell/trace-mapping': 0.3.18
-      '@vscode/emmet-helper': 2.8.9
+      '@jridgewell/trace-mapping': 0.3.19
+      '@vscode/emmet-helper': 2.9.2
       events: 3.3.0
       prettier: 2.8.8
       prettier-plugin-astro: 0.9.1
-      vscode-css-languageservice: 6.2.6
-      vscode-html-languageservice: 5.0.6
+      vscode-css-languageservice: 6.2.9
+      vscode-html-languageservice: 5.1.0
       vscode-languageserver: 8.1.0
-      vscode-languageserver-protocol: 3.17.3
-      vscode-languageserver-textdocument: 1.0.8
-      vscode-languageserver-types: 3.17.3
-      vscode-uri: 3.0.7
+      vscode-languageserver-protocol: 3.17.5
+      vscode-languageserver-textdocument: 1.0.11
+      vscode-languageserver-types: 3.17.5
+      vscode-uri: 3.0.8
 
   /@astrojs/markdown-remark@2.2.1(astro@2.10.15):
     resolution: {integrity: sha512-VF0HRv4GpC1XEMLnsKf6jth7JSmlt9qpqP0josQgA2eSpCIAC/Et+y94mgdBIZVBYH/yFnMoIxgKVe93xfO2GA==}
     peerDependencies:
       astro: ^2.5.0
@@ -995,21 +1076,21 @@ packages:
       unified: 10.1.2
       unist-util-visit: 4.1.2
       vfile: 5.3.7
     transitivePeerDependencies:
       - supports-color
-    dev: false
 
-  /@astrojs/markdown-remark@2.2.1(astro@2.9.2):
-    resolution: {integrity: sha512-VF0HRv4GpC1XEMLnsKf6jth7JSmlt9qpqP0josQgA2eSpCIAC/Et+y94mgdBIZVBYH/yFnMoIxgKVe93xfO2GA==}
+  /@astrojs/markdown-remark@3.2.0(astro@3.1.0):
+    resolution: {integrity: sha512-jigyLfefUZPKgVmmraCkVpdUuFH1R3SrpgQO13axsgwLDBgkggaQpNR5Ag4O9PDualeBtbdt30aYSfvnBKx9Hg==}
     peerDependencies:
-      astro: ^2.5.0
+      astro: ^3.1.0
     dependencies:
-      '@astrojs/prism': 2.1.2
-      astro: 2.9.2
-      github-slugger: 1.5.0
-      import-meta-resolve: 2.2.2
+      '@astrojs/prism': 3.0.0
+      astro: 3.1.0(sass@1.64.1)
+      github-slugger: 2.0.0
+      import-meta-resolve: 3.0.0
+      mdast-util-definitions: 6.0.0
       rehype-raw: 6.1.1
       rehype-stringify: 9.0.4
       remark-gfm: 3.0.1
       remark-parse: 10.0.2
       remark-rehype: 10.1.0
@@ -1018,16 +1099,15 @@ packages:
       unified: 10.1.2
       unist-util-visit: 4.1.2
       vfile: 5.3.7
     transitivePeerDependencies:
       - supports-color
-    dev: true
 
-  /@astrojs/markdown-remark@3.2.0(astro@3.1.0):
-    resolution: {integrity: sha512-jigyLfefUZPKgVmmraCkVpdUuFH1R3SrpgQO13axsgwLDBgkggaQpNR5Ag4O9PDualeBtbdt30aYSfvnBKx9Hg==}
+  /@astrojs/markdown-remark@3.2.1(astro@3.1.0):
+    resolution: {integrity: sha512-Z4YNMRtgFZeHhB29uCZl0B9MbMZddW9ZKCNucapoysbvygbDFF1gGtqpVnf+Lyv3rUBHwM/J5qWB2MSZuTuz1g==}
     peerDependencies:
-      astro: ^3.1.0
+      astro: ^3.2.3
     dependencies:
       '@astrojs/prism': 3.0.0
       astro: 3.1.0(sass@1.64.1)
       github-slugger: 2.0.0
       import-meta-resolve: 3.0.0
@@ -1042,10 +1122,37 @@ packages:
       unified: 10.1.2
       unist-util-visit: 4.1.2
       vfile: 5.3.7
     transitivePeerDependencies:
       - supports-color
+    dev: false
+
+  /@astrojs/mdx@1.1.1(astro@3.1.0):
+    resolution: {integrity: sha512-3dfL12ZqI6NCjx0iVOYVSyljlVgsxds5mOhe78xoCVjyqSpZZsxzz4Dt5WfGxDon2nc2bD6XGiZ2PIy8fmX6NQ==}
+    engines: {node: '>=18.14.1'}
+    peerDependencies:
+      astro: ^3.2.3
+    dependencies:
+      '@astrojs/markdown-remark': 3.2.1(astro@3.1.0)
+      '@mdx-js/mdx': 2.3.0
+      acorn: 8.10.0
+      astro: 3.1.0(sass@1.64.1)
+      es-module-lexer: 1.3.1
+      estree-util-visit: 1.2.1
+      github-slugger: 2.0.0
+      gray-matter: 4.0.3
+      hast-util-to-html: 8.0.4
+      kleur: 4.1.5
+      rehype-raw: 6.1.1
+      remark-gfm: 3.0.1
+      remark-smartypants: 2.0.0
+      source-map: 0.7.4
+      unist-util-visit: 4.1.2
+      vfile: 5.3.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
 
   /@astrojs/node@6.0.0(astro@3.1.0):
     resolution: {integrity: sha512-06x5UBt+g0EIUpOdtCdnTxRJhOTLxUnjzmGwIHp9RNBlIEpzd/dJs6pwvfiM2zuPolTLI53T8VOsdw3EMh2V+w==}
     peerDependencies:
       astro: ^3.0.0
@@ -1071,27 +1178,27 @@ packages:
 
   /@astrojs/sitemap@2.0.2:
     resolution: {integrity: sha512-dFWtdFwN8kxDiqIxF8T8ODqsUr6hG+EQlFEqm+3oQkhAkucF9QkYLM5Q72mEbYytkL4jvKyHbW1u10T5sWBZew==}
     dependencies:
       sitemap: 7.1.1
-      zod: 3.22.2
+      zod: 3.21.4
     dev: false
 
   /@astrojs/sitemap@3.0.0:
     resolution: {integrity: sha512-qm7npHuUW4q3OOmulqhJ1g69jEQu0Sdc6P8NbOzqIoosj/L+3v4i8dtKBnp6n1UQ4Sx8H8Vdi3Z/On7i9/ZJhw==}
     dependencies:
       sitemap: 7.1.1
       zod: 3.21.1
     dev: false
 
-  /@astrojs/solid-js@2.2.1(@babel/core@7.22.15)(solid-js@1.7.11)(vite@4.4.9):
+  /@astrojs/solid-js@2.2.1(@babel/core@7.23.0)(solid-js@1.7.11)(vite@4.4.9):
     resolution: {integrity: sha512-LJRKX1raHePOWE5lL7OjYvtap/S4fQoZLPB0pVw6RKUJtCeRIYD44x5DxFk52dFCkjnlVuWFlQkvtefT8kotcQ==}
     engines: {node: '>=16.12.0'}
     peerDependencies:
       solid-js: ^1.4.3
     dependencies:
-      babel-preset-solid: 1.7.7(@babel/core@7.22.15)
+      babel-preset-solid: 1.7.12(@babel/core@7.23.0)
       solid-js: 1.7.11
       vitefu: 0.2.4(vite@4.4.9)
     transitivePeerDependencies:
       - '@babel/core'
       - vite
@@ -1112,40 +1219,40 @@ packages:
 
   /@astrojs/telemetry@2.1.1:
     resolution: {integrity: sha512-4pRhyeQr0MLB5PKYgkdu+YE8sSpMbHL8dUuslBWBIdgcYjtD1SufPMBI8pgXJ+xlwrQJHKKfK2X1KonHYuOS9A==}
     engines: {node: '>=16.12.0'}
     dependencies:
-      ci-info: 3.8.0
+      ci-info: 3.9.0
       debug: 4.3.4
       dlv: 1.1.3
       dset: 3.1.2
       is-docker: 3.0.0
       is-wsl: 2.2.0
-      undici: 5.23.0
+      undici: 5.25.4
       which-pm-runs: 1.1.0
     transitivePeerDependencies:
       - supports-color
 
   /@astrojs/telemetry@3.0.1:
     resolution: {integrity: sha512-7zJMuikRDQ0LLLivteu0+y4pqdgznrChFiRrY3qmKlOEkLWD1T3u1a5M970lvpErP7Vgh4P298JBPjv8LTj+sw==}
     engines: {node: '>=18.14.1'}
     dependencies:
-      ci-info: 3.8.0
+      ci-info: 3.9.0
       debug: 4.3.4
       dlv: 1.1.3
       dset: 3.1.2
       is-docker: 3.0.0
-      is-wsl: 3.0.0
-      undici: 5.23.0
+      is-wsl: 3.1.0
+      undici: 5.25.4
       which-pm-runs: 1.1.0
     transitivePeerDependencies:
       - supports-color
 
   /@astrojs/webapi@2.2.0:
     resolution: {integrity: sha512-mHAOApWyjqSe5AQMOUD9rsZJqbMQqe3Wosb1a40JV6Okvyxj1G6GTlthwYadWCymq/lbgwh0PLiY8Fr4eFxtuQ==}
     dependencies:
-      undici: 5.23.0
+      undici: 5.25.4
 
   /@aws-crypto/crc32@3.0.0:
     resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==}
     dependencies:
       '@aws-crypto/util': 3.0.0
@@ -1269,11 +1376,11 @@ packages:
       '@smithy/util-retry': 1.1.0
       '@smithy/util-stream': 1.1.0
       '@smithy/util-utf8': 1.1.0
       '@smithy/util-waiter': 1.1.0
       fast-xml-parser: 4.2.5
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - '@aws-sdk/signature-v4-crt'
       - aws-crt
     dev: false
 
@@ -1311,11 +1418,11 @@ packages:
       '@smithy/util-body-length-node': 1.1.0
       '@smithy/util-defaults-mode-browser': 1.1.0
       '@smithy/util-defaults-mode-node': 1.1.0
       '@smithy/util-retry': 1.1.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/client-sso@3.370.0:
@@ -1352,11 +1459,11 @@ packages:
       '@smithy/util-body-length-node': 1.1.0
       '@smithy/util-defaults-mode-browser': 1.1.0
       '@smithy/util-defaults-mode-node': 1.1.0
       '@smithy/util-retry': 1.1.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/client-sts@3.370.0:
@@ -1397,11 +1504,11 @@ packages:
       '@smithy/util-defaults-mode-browser': 1.1.0
       '@smithy/util-defaults-mode-node': 1.1.0
       '@smithy/util-retry': 1.1.0
       '@smithy/util-utf8': 1.1.0
       fast-xml-parser: 4.2.5
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/credential-provider-env@3.370.0:
@@ -1409,11 +1516,11 @@ packages:
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/property-provider': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/credential-provider-ini@3.370.0:
     resolution: {integrity: sha512-eJyapFKa4NrC9RfTgxlXnXfS9InG/QMEUPPVL+VhG7YS6nKqetC1digOYgivnEeu+XSKE0DJ7uZuXujN2Y7VAQ==}
     engines: {node: '>=14.0.0'}
@@ -1425,11 +1532,11 @@ packages:
       '@aws-sdk/types': 3.370.0
       '@smithy/credential-provider-imds': 1.1.0
       '@smithy/property-provider': 1.2.0
       '@smithy/shared-ini-file-loader': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/credential-provider-node@3.370.0:
@@ -1444,11 +1551,11 @@ packages:
       '@aws-sdk/types': 3.370.0
       '@smithy/credential-provider-imds': 1.1.0
       '@smithy/property-provider': 1.2.0
       '@smithy/shared-ini-file-loader': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/credential-provider-process@3.370.0:
@@ -1457,11 +1564,11 @@ packages:
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/property-provider': 1.2.0
       '@smithy/shared-ini-file-loader': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/credential-provider-sso@3.370.0:
     resolution: {integrity: sha512-PFroYm5hcPSfC/jkZnCI34QFL3I7WVKveVk6/F3fud/cnP8hp6YjA9NiTNbqdFSzsyoiN/+e5fZgNKih8vVPTA==}
     engines: {node: '>=14.0.0'}
@@ -1470,11 +1577,11 @@ packages:
       '@aws-sdk/token-providers': 3.370.0
       '@aws-sdk/types': 3.370.0
       '@smithy/property-provider': 1.2.0
       '@smithy/shared-ini-file-loader': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/credential-provider-web-identity@3.370.0:
@@ -1482,20 +1589,20 @@ packages:
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/property-provider': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/hash-stream-node@3.374.0:
     resolution: {integrity: sha512-Ta7YEFcgc+d4Rt7foV/fbgnXP8IgMAb+JVzZVYcHTwQf836+PdjGfKbamYkh8cM2xE47hzZqPe+BacCjePqH7g==}
     engines: {node: '>=14.0.0'}
     deprecated: This package has moved to @smithy/hash-stream-node
     dependencies:
       '@smithy/hash-stream-node': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-bucket-endpoint@3.370.0:
     resolution: {integrity: sha512-B36+fOeJVO0D9cjR92Ob6Ki2FTzyTQ/uKk8w+xtur6W6zYVOPU4IQNpNZvN3Ykt4jitR2uUnVSlBb3sXHHhdFA==}
     engines: {node: '>=14.0.0'}
@@ -1503,21 +1610,21 @@ packages:
       '@aws-sdk/types': 3.370.0
       '@aws-sdk/util-arn-parser': 3.310.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
       '@smithy/util-config-provider': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-expect-continue@3.370.0:
     resolution: {integrity: sha512-OlFIpXa53obLryHyrqedE2Cp8lp2k+1Vjd++hlZFDFJncRlWZMxoXSyl6shQPqhIiGnNW4vt7tG5xE4jg4NAvw==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-flexible-checksums@3.374.0:
     resolution: {integrity: sha512-NVXqMiYrEvpbAK0jTOy791dkJAz+JQkIX8lgl/BgnNXvXFDP2wOW5JT830LX27bMhs/yzt1nJSLvgnSCuhOKtg==}
     engines: {node: '>=14.0.0'}
@@ -1527,70 +1634,70 @@ packages:
       '@aws-sdk/types': 3.370.0
       '@smithy/is-array-buffer': 1.1.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-host-header@3.370.0:
     resolution: {integrity: sha512-CPXOm/TnOFC7KyXcJglICC7OiA7Kj6mT3ChvEijr56TFOueNHvJdV4aNIFEQy0vGHOWtY12qOWLNto/wYR1BAQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-location-constraint@3.370.0:
     resolution: {integrity: sha512-NlDZEbBOF1IN7svUTcjbLodkUctt9zsfDI8+DqNlklRs5lsPb91WYvahOfjFO/EvACixa+a5d3cCumMCaIq4Cw==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-logger@3.370.0:
     resolution: {integrity: sha512-cQMq9SaZ/ORmTJPCT6VzMML7OxFdQzNkhMAgKpTDl+tdPWynlHF29E5xGoSzROnThHlQPCjogU0NZ8AxI0SWPA==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-recursion-detection@3.370.0:
     resolution: {integrity: sha512-L7ZF/w0lAAY/GK1khT8VdoU0XB7nWHk51rl/ecAg64J70dHnMOAg8n+5FZ9fBu/xH1FwUlHOkwlodJOgzLJjtg==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-sdk-s3@3.370.0:
     resolution: {integrity: sha512-DPYXtveWBDS5MzSHWTThg2KkLaOzZkCgPejjEuw3yl4ljsHawDs/ZIVCtmWXlBIS2lLCaBMpCV+t9psuJ/6/zQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@aws-sdk/util-arn-parser': 3.310.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-sdk-sts@3.370.0:
     resolution: {integrity: sha512-ykbsoVy0AJtVbuhAlTAMcaz/tCE3pT8nAp0L7CQQxSoanRCvOux7au0KwMIQVhxgnYid4dWVF6d00SkqU5MXRA==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/middleware-signing': 3.370.0
       '@aws-sdk/types': 3.370.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-signing@3.370.0:
     resolution: {integrity: sha512-Dwr/RTCWOXdm394wCwICGT2VNOTMRe4IGPsBRJAsM24pm+EEqQzSS3Xu/U/zF4exuxqpMta4wec4QpSarPNTxA==}
     engines: {node: '>=14.0.0'}
@@ -1599,31 +1706,31 @@ packages:
       '@smithy/property-provider': 1.2.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/signature-v4': 1.1.0
       '@smithy/types': 1.2.0
       '@smithy/util-middleware': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-ssec@3.370.0:
     resolution: {integrity: sha512-NIosfLS7mxCNdGYnuy76W9qP3f3YWVTusUA+uv+s6rnwG+Z2UheXCf1wpnJKzxORA8pioSP7ylZ8w2A0reCgYQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/middleware-user-agent@3.370.0:
     resolution: {integrity: sha512-2+3SB6MtMAq1+gVXhw0Y3ONXuljorh6ijnxgTpv+uQnBW5jHCUiAS8WDYiDEm7i9euJPbvJfM8WUrSMDMU6Cog==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@aws-sdk/util-endpoints': 3.370.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/s3-request-presigner@3.375.0:
     resolution: {integrity: sha512-C6hAM7Vl7DjO5Txs+9infZlEqelVH3piCu+GPox+x2IiELOdQ/PeaOcHnmaejNyAwF/oS0OYbRmdCI04bUYQ8Q==}
     engines: {node: '>=14.0.0'}
@@ -1633,11 +1740,11 @@ packages:
       '@aws-sdk/util-format-url': 3.370.0
       '@smithy/middleware-endpoint': 1.1.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/smithy-client': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - '@aws-sdk/signature-v4-crt'
     dev: false
 
   /@aws-sdk/signature-v4-multi-region@3.370.0:
@@ -1651,11 +1758,11 @@ packages:
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/signature-v4': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/token-providers@3.370.0:
     resolution: {integrity: sha512-EyR2ZYr+lJeRiZU2/eLR+mlYU9RXLQvNyGFSAekJKgN13Rpq/h0syzXVFLP/RSod/oZenh/fhVZ2HwlZxuGBtQ==}
     engines: {node: '>=14.0.0'}
@@ -1663,62 +1770,62 @@ packages:
       '@aws-sdk/client-sso-oidc': 3.370.0
       '@aws-sdk/types': 3.370.0
       '@smithy/property-provider': 1.2.0
       '@smithy/shared-ini-file-loader': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     transitivePeerDependencies:
       - aws-crt
     dev: false
 
   /@aws-sdk/types@3.370.0:
     resolution: {integrity: sha512-8PGMKklSkRKjunFhzM2y5Jm0H2TBu7YRNISdYzXLUHKSP9zlMEYagseKVdmox0zKHf1LXVNuSlUV2b6SRrieCQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-arn-parser@3.310.0:
     resolution: {integrity: sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-endpoints@3.370.0:
     resolution: {integrity: sha512-5ltVAnM79nRlywwzZN5i8Jp4tk245OCGkKwwXbnDU+gq7zT3CIOsct1wNZvmpfZEPGt/bv7/NyRcjP+7XNsX/g==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-format-url@3.370.0:
     resolution: {integrity: sha512-6ik8UTT5hNlMnATrqWiQWnIZ0EFW8wVsRGyYUYw/geB3lQ+WAWflpJg+gZiJnc5EY4R0aOzRVm02W8EUeH8f5g==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/querystring-builder': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-locate-window@3.310.0:
     resolution: {integrity: sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-user-agent-browser@3.370.0:
     resolution: {integrity: sha512-028LxYZMQ0DANKhW+AKFQslkScZUeYlPmSphrCIXgdIItRZh6ZJHGzE7J/jDsEntZOrZJsjI4z0zZ5W2idj04w==}
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/types': 1.2.0
       bowser: 2.11.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-user-agent-node@3.370.0:
     resolution: {integrity: sha512-33vxZUp8vxTT/DGYIR3PivQm07sSRGWI+4fCv63Rt7Q++fO24E0kQtmVAlikRY810I10poD6rwILVtITtFSzkg==}
     engines: {node: '>=14.0.0'}
@@ -1729,583 +1836,374 @@ packages:
         optional: true
     dependencies:
       '@aws-sdk/types': 3.370.0
       '@smithy/node-config-provider': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/util-utf8-browser@3.259.0:
     resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@aws-sdk/xml-builder@3.310.0:
     resolution: {integrity: sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@babel/code-frame@7.22.13:
     resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/highlight': 7.22.13
+      '@babel/highlight': 7.22.20
       chalk: 2.4.2
 
-  /@babel/code-frame@7.22.5:
-    resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/highlight': 7.22.13
-
-  /@babel/compat-data@7.22.9:
-    resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==}
+  /@babel/compat-data@7.22.20:
+    resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==}
     engines: {node: '>=6.9.0'}
 
-  /@babel/core@7.22.15:
-    resolution: {integrity: sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==}
+  /@babel/core@7.23.0:
+    resolution: {integrity: sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@ampproject/remapping': 2.2.1
       '@babel/code-frame': 7.22.13
-      '@babel/generator': 7.22.15
+      '@babel/generator': 7.23.0
       '@babel/helper-compilation-targets': 7.22.15
-      '@babel/helper-module-transforms': 7.22.15(@babel/core@7.22.15)
-      '@babel/helpers': 7.22.15
-      '@babel/parser': 7.22.16
+      '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0)
+      '@babel/helpers': 7.23.1
+      '@babel/parser': 7.23.0
       '@babel/template': 7.22.15
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-      convert-source-map: 1.9.0
-      debug: 4.3.4
-      gensync: 1.0.0-beta.2
-      json5: 2.2.3
-      semver: 6.3.1
-    transitivePeerDependencies:
-      - supports-color
-
-  /@babel/core@7.22.5:
-    resolution: {integrity: sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@ampproject/remapping': 2.2.1
-      '@babel/code-frame': 7.22.5
-      '@babel/generator': 7.22.5
-      '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.5)
-      '@babel/helper-module-transforms': 7.22.5
-      '@babel/helpers': 7.22.5
-      '@babel/parser': 7.22.5
-      '@babel/template': 7.22.5
-      '@babel/traverse': 7.22.5
-      '@babel/types': 7.22.5
-      convert-source-map: 1.9.0
+      '@babel/traverse': 7.23.0
+      '@babel/types': 7.23.0
+      convert-source-map: 2.0.0
       debug: 4.3.4
       gensync: 1.0.0-beta.2
       json5: 2.2.3
       semver: 6.3.1
     transitivePeerDependencies:
       - supports-color
 
-  /@babel/eslint-parser@7.22.5(@babel/core@7.22.5)(eslint@8.45.0):
-    resolution: {integrity: sha512-C69RWYNYtrgIRE5CmTd77ZiLDXqgBipahJc/jHP3sLcAGj6AJzxNIuKNpVnICqbyK7X3pFUfEvL++rvtbQpZkQ==}
+  /@babel/eslint-parser@7.22.15(@babel/core@7.23.0)(eslint@8.45.0):
+    resolution: {integrity: sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==}
     engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0}
     peerDependencies:
-      '@babel/core': '>=7.11.0'
+      '@babel/core': ^7.11.0
       eslint: ^7.5.0 || ^8.0.0
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1
       eslint: 8.45.0
       eslint-visitor-keys: 2.1.0
       semver: 6.3.1
     dev: true
 
-  /@babel/generator@7.22.15:
-    resolution: {integrity: sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/types': 7.22.15
-      '@jridgewell/gen-mapping': 0.3.3
-      '@jridgewell/trace-mapping': 0.3.18
-      jsesc: 2.5.2
-
-  /@babel/generator@7.22.5:
-    resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==}
+  /@babel/generator@7.23.0:
+    resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
       '@jridgewell/gen-mapping': 0.3.3
-      '@jridgewell/trace-mapping': 0.3.18
+      '@jridgewell/trace-mapping': 0.3.19
       jsesc: 2.5.2
 
   /@babel/helper-annotate-as-pure@7.22.5:
     resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-compilation-targets@7.22.15:
     resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/compat-data': 7.22.9
-      '@babel/helper-validator-option': 7.22.15
-      browserslist: 4.21.10
-      lru-cache: 5.1.1
-      semver: 6.3.1
-
-  /@babel/helper-compilation-targets@7.22.5(@babel/core@7.22.5):
-    resolution: {integrity: sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0
-    dependencies:
-      '@babel/compat-data': 7.22.9
-      '@babel/core': 7.22.5
+      '@babel/compat-data': 7.22.20
       '@babel/helper-validator-option': 7.22.15
-      browserslist: 4.21.10
+      browserslist: 4.22.1
       lru-cache: 5.1.1
       semver: 6.3.1
 
-  /@babel/helper-create-class-features-plugin@7.22.5(@babel/core@7.22.5):
-    resolution: {integrity: sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==}
+  /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.0):
+    resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-annotate-as-pure': 7.22.5
-      '@babel/helper-environment-visitor': 7.22.5
-      '@babel/helper-function-name': 7.22.5
-      '@babel/helper-member-expression-to-functions': 7.22.5
+      '@babel/helper-environment-visitor': 7.22.20
+      '@babel/helper-function-name': 7.23.0
+      '@babel/helper-member-expression-to-functions': 7.23.0
       '@babel/helper-optimise-call-expression': 7.22.5
-      '@babel/helper-replace-supers': 7.22.5
+      '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.0)
       '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
-      '@babel/helper-split-export-declaration': 7.22.5
+      '@babel/helper-split-export-declaration': 7.22.6
       semver: 6.3.1
-    transitivePeerDependencies:
-      - supports-color
 
-  /@babel/helper-environment-visitor@7.22.5:
-    resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==}
+  /@babel/helper-environment-visitor@7.22.20:
+    resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
     engines: {node: '>=6.9.0'}
 
-  /@babel/helper-function-name@7.22.5:
-    resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
+  /@babel/helper-function-name@7.23.0:
+    resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/template': 7.22.5
-      '@babel/types': 7.22.15
+      '@babel/template': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-hoist-variables@7.22.5:
     resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
-  /@babel/helper-member-expression-to-functions@7.22.5:
-    resolution: {integrity: sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==}
+  /@babel/helper-member-expression-to-functions@7.23.0:
+    resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-module-imports@7.18.6:
     resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-module-imports@7.22.15:
     resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
-
-  /@babel/helper-module-imports@7.22.5:
-    resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
-  /@babel/helper-module-transforms@7.22.15(@babel/core@7.22.15):
-    resolution: {integrity: sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==}
+  /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.0):
+    resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0
     dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-environment-visitor': 7.22.5
-      '@babel/helper-module-imports': 7.22.15
-      '@babel/helper-simple-access': 7.22.5
-      '@babel/helper-split-export-declaration': 7.22.6
-      '@babel/helper-validator-identifier': 7.22.15
-
-  /@babel/helper-module-transforms@7.22.5:
-    resolution: {integrity: sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/helper-environment-visitor': 7.22.5
+      '@babel/core': 7.23.0
+      '@babel/helper-environment-visitor': 7.22.20
       '@babel/helper-module-imports': 7.22.15
       '@babel/helper-simple-access': 7.22.5
       '@babel/helper-split-export-declaration': 7.22.6
-      '@babel/helper-validator-identifier': 7.22.15
-      '@babel/template': 7.22.15
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-validator-identifier': 7.22.20
 
   /@babel/helper-optimise-call-expression@7.22.5:
     resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-plugin-utils@7.22.5:
     resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
     engines: {node: '>=6.9.0'}
 
-  /@babel/helper-replace-supers@7.22.5:
-    resolution: {integrity: sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==}
+  /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.0):
+    resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==}
     engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0
     dependencies:
-      '@babel/helper-environment-visitor': 7.22.5
-      '@babel/helper-member-expression-to-functions': 7.22.5
+      '@babel/core': 7.23.0
+      '@babel/helper-environment-visitor': 7.22.20
+      '@babel/helper-member-expression-to-functions': 7.23.0
       '@babel/helper-optimise-call-expression': 7.22.5
-      '@babel/template': 7.22.15
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-    transitivePeerDependencies:
-      - supports-color
 
   /@babel/helper-simple-access@7.22.5:
     resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-skip-transparent-expression-wrappers@7.22.5:
     resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
-
-  /@babel/helper-split-export-declaration@7.22.5:
-    resolution: {integrity: sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-split-export-declaration@7.22.6:
     resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@babel/helper-string-parser@7.22.5:
     resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==}
     engines: {node: '>=6.9.0'}
 
-  /@babel/helper-validator-identifier@7.22.15:
-    resolution: {integrity: sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==}
-    engines: {node: '>=6.9.0'}
-
-  /@babel/helper-validator-identifier@7.22.5:
-    resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
+  /@babel/helper-validator-identifier@7.22.20:
+    resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
     engines: {node: '>=6.9.0'}
 
   /@babel/helper-validator-option@7.22.15:
     resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==}
     engines: {node: '>=6.9.0'}
 
-  /@babel/helper-validator-option@7.22.5:
-    resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==}
-    engines: {node: '>=6.9.0'}
-
-  /@babel/helpers@7.22.15:
-    resolution: {integrity: sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==}
+  /@babel/helpers@7.23.1:
+    resolution: {integrity: sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/template': 7.22.15
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-    transitivePeerDependencies:
-      - supports-color
-
-  /@babel/helpers@7.22.5:
-    resolution: {integrity: sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/template': 7.22.5
-      '@babel/traverse': 7.22.5
-      '@babel/types': 7.22.15
+      '@babel/traverse': 7.23.0
+      '@babel/types': 7.23.0
     transitivePeerDependencies:
       - supports-color
 
-  /@babel/highlight@7.22.13:
-    resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==}
+  /@babel/highlight@7.22.20:
+    resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/helper-validator-identifier': 7.22.15
+      '@babel/helper-validator-identifier': 7.22.20
       chalk: 2.4.2
       js-tokens: 4.0.0
 
-  /@babel/parser@7.22.16:
-    resolution: {integrity: sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==}
+  /@babel/parser@7.23.0:
+    resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==}
     engines: {node: '>=6.0.0'}
     hasBin: true
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
-  /@babel/parser@7.22.5:
-    resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==}
-    engines: {node: '>=6.0.0'}
-    hasBin: true
-    dependencies:
-      '@babel/types': 7.22.15
-
-  /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.15):
-    resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-plugin-utils': 7.22.5
-      '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.15)
-    dev: false
-
-  /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.15):
-    resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-plugin-utils': 7.22.5
-    dev: false
-
-  /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.15):
-    resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-plugin-utils': 7.22.5
-    dev: false
-
-  /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.15):
-    resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-plugin-utils': 7.22.5
-
-  /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.5):
+  /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.0):
     resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-plugin-utils': 7.22.5
 
-  /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.5):
+  /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.23.0):
     resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.22.5
-      '@babel/helper-plugin-utils': 7.22.5
-
-  /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.15):
-    resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-module-transforms': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-plugin-utils': 7.22.5
-      '@babel/helper-simple-access': 7.22.5
-    transitivePeerDependencies:
-      - supports-color
-    dev: false
 
-  /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.5):
-    resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==}
+  /@babel/plugin-transform-modules-commonjs@7.23.0(@babel/core@7.23.0):
+    resolution: {integrity: sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.22.5
-      '@babel/helper-module-transforms': 7.22.5
+      '@babel/core': 7.23.0
+      '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0)
       '@babel/helper-plugin-utils': 7.22.5
       '@babel/helper-simple-access': 7.22.5
-    transitivePeerDependencies:
-      - supports-color
-
-  /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.15):
-    resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==}
-    engines: {node: '>=6.9.0'}
-    peerDependencies:
-      '@babel/core': ^7.0.0-0
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-annotate-as-pure': 7.22.5
-      '@babel/helper-module-imports': 7.22.15
-      '@babel/helper-plugin-utils': 7.22.5
-      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.15)
-      '@babel/types': 7.22.15
 
-  /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.5):
-    resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==}
+  /@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.0):
+    resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-annotate-as-pure': 7.22.5
       '@babel/helper-module-imports': 7.22.15
       '@babel/helper-plugin-utils': 7.22.5
-      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5)
-      '@babel/types': 7.22.15
-    dev: true
+      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0)
+      '@babel/types': 7.23.0
 
-  /@babel/plugin-transform-typescript@7.22.5(@babel/core@7.22.5):
-    resolution: {integrity: sha512-SMubA9S7Cb5sGSFFUlqxyClTA9zWJ8qGQrppNUm05LtFuN1ELRFNndkix4zUJrC9F+YivWwa1dHMSyo0e0N9dA==}
+  /@babel/plugin-transform-typescript@7.22.15(@babel/core@7.23.0):
+    resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-annotate-as-pure': 7.22.5
-      '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.5)
+      '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0)
       '@babel/helper-plugin-utils': 7.22.5
-      '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.5)
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.0)
 
-  /@babel/preset-typescript@7.22.5(@babel/core@7.22.5):
-    resolution: {integrity: sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==}
+  /@babel/preset-typescript@7.23.0(@babel/core@7.23.0):
+    resolution: {integrity: sha512-6P6VVa/NM/VlAYj5s2Aq/gdVg8FSENCg3wlZ6Qau9AcPaoF5LbN1nyGlR9DTRIw9PpxI94e+ReydsJHcjwAweg==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0-0
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-plugin-utils': 7.22.5
-      '@babel/helper-validator-option': 7.22.5
-      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5)
-      '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.5)
-      '@babel/plugin-transform-typescript': 7.22.5(@babel/core@7.22.5)
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/helper-validator-option': 7.22.15
+      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0)
+      '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.23.0)
+      '@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.23.0)
 
-  /@babel/runtime@7.22.5:
-    resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==}
+  /@babel/runtime@7.23.1:
+    resolution: {integrity: sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      regenerator-runtime: 0.13.11
+      regenerator-runtime: 0.14.0
     dev: false
 
-  /@babel/standalone@7.22.5:
-    resolution: {integrity: sha512-6Lwhzral4YDEbIM3dBC8/w0BMDvOosGBGaJWSORLkerx8byawkmwwzXKUB0jGlI1Zp90+cK2uyTl62UPtLbUjQ==}
+  /@babel/standalone@7.23.1:
+    resolution: {integrity: sha512-a4muOYz1qUaSoybuUKwK90mRG4sf5rBeUbuzpuGLzG32ZDE/Y2YEebHDODFJN+BtyOKi19hrLfq2qbNyKMx0TA==}
     engines: {node: '>=6.9.0'}
     dev: true
 
   /@babel/template@7.22.15:
     resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/code-frame': 7.22.13
-      '@babel/parser': 7.22.16
-      '@babel/types': 7.22.15
-
-  /@babel/template@7.22.5:
-    resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/code-frame': 7.22.5
-      '@babel/parser': 7.22.5
-      '@babel/types': 7.22.15
-
-  /@babel/traverse@7.22.15:
-    resolution: {integrity: sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/code-frame': 7.22.13
-      '@babel/generator': 7.22.15
-      '@babel/helper-environment-visitor': 7.22.5
-      '@babel/helper-function-name': 7.22.5
-      '@babel/helper-hoist-variables': 7.22.5
-      '@babel/helper-split-export-declaration': 7.22.6
-      '@babel/parser': 7.22.16
-      '@babel/types': 7.22.15
-      debug: 4.3.4
-      globals: 11.12.0
-    transitivePeerDependencies:
-      - supports-color
+      '@babel/parser': 7.23.0
+      '@babel/types': 7.23.0
 
-  /@babel/traverse@7.22.5:
-    resolution: {integrity: sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==}
+  /@babel/traverse@7.23.0:
+    resolution: {integrity: sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/code-frame': 7.22.13
-      '@babel/generator': 7.22.15
-      '@babel/helper-environment-visitor': 7.22.5
-      '@babel/helper-function-name': 7.22.5
+      '@babel/generator': 7.23.0
+      '@babel/helper-environment-visitor': 7.22.20
+      '@babel/helper-function-name': 7.23.0
       '@babel/helper-hoist-variables': 7.22.5
       '@babel/helper-split-export-declaration': 7.22.6
-      '@babel/parser': 7.22.16
-      '@babel/types': 7.22.15
+      '@babel/parser': 7.23.0
+      '@babel/types': 7.23.0
       debug: 4.3.4
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
 
-  /@babel/types@7.22.15:
-    resolution: {integrity: sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==}
-    engines: {node: '>=6.9.0'}
-    dependencies:
-      '@babel/helper-string-parser': 7.22.5
-      '@babel/helper-validator-identifier': 7.22.15
-      to-fast-properties: 2.0.0
-
-  /@babel/types@7.22.5:
-    resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==}
+  /@babel/types@7.23.0:
+    resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/helper-string-parser': 7.22.5
-      '@babel/helper-validator-identifier': 7.22.5
+      '@babel/helper-validator-identifier': 7.22.20
       to-fast-properties: 2.0.0
 
-  /@bufbuild/connect-node@0.9.1(@bufbuild/protobuf@1.3.0):
+  /@bufbuild/connect-node@0.9.1(@bufbuild/protobuf@1.3.3):
     resolution: {integrity: sha512-kUMB6QQh8S19LsvweDg057WN3Gbg+zIqSHnRcXh9CBYSN7GWd9dgJPQSgalJFJngjFSW2qnnOmnUkxMyZiWBOw==}
     engines: {node: '>=16.0.0'}
+    deprecated: Connect has moved to its own org @connectrpc and has a stable v1. Run `npx @connectrpc/connect-migrate@latest` to update. See https://github.com/connectrpc/connect-es/releases/tag/v0.13.1 for details.
     peerDependencies:
       '@bufbuild/protobuf': ^1.2.0
     dependencies:
-      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.0)
-      '@bufbuild/protobuf': 1.3.0
-      headers-polyfill: 3.1.2
+      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.3)
+      '@bufbuild/protobuf': 1.3.3
+      headers-polyfill: 3.3.0
     dev: false
 
-  /@bufbuild/connect@0.9.1(@bufbuild/protobuf@1.3.0):
+  /@bufbuild/connect@0.9.1(@bufbuild/protobuf@1.3.3):
     resolution: {integrity: sha512-4O/PSMLWd3oQkwBuJBGBzFtPsnFC5dTRPGHFNFODna9wZJ6r45ccsOWsA4qXBL7gW2EKw93zRa0KVuge2dCOQQ==}
+    deprecated: Connect has moved to its own org @connectrpc and has a stable v1. Run `npx @connectrpc/connect-migrate@latest` to update. See https://github.com/connectrpc/connect-es/releases/tag/v0.13.1 for details.
     peerDependencies:
       '@bufbuild/protobuf': ^1.2.0
     dependencies:
-      '@bufbuild/protobuf': 1.3.0
+      '@bufbuild/protobuf': 1.3.3
     dev: false
 
-  /@bufbuild/protobuf@1.3.0:
-    resolution: {integrity: sha512-G372ods0pLt46yxVRsnP/e2btVPuuzArcMPFpIDeIwiGPuuglEs9y75iG0HMvZgncsj5TvbYRWqbVyOe3PLCWQ==}
+  /@bufbuild/protobuf@1.3.3:
+    resolution: {integrity: sha512-AoHSiIpTFF97SQgmQni4c+Tyr0CDhkaRaR2qGEJTEbauqQwLRpLrd9yVv//wVHOSxr/b4FJcL54VchhY6710xA==}
     dev: false
 
   /@commander-js/extra-typings@9.4.1(commander@9.4.1):
     resolution: {integrity: sha512-v0BqORYamk1koxDon6femDGLWSL7P78vYTyOU5nFaALnmNALL+ktgdHvWbxzzBBJIKS7kv3XvM/DqNwiLcgFTA==}
     peerDependencies:
@@ -2350,12 +2248,12 @@ packages:
     cpu: [arm64]
     os: [android]
     requiresBuild: true
     optional: true
 
-  /@esbuild/android-arm64@0.19.3:
-    resolution: {integrity: sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==}
+  /@esbuild/android-arm64@0.19.4:
+    resolution: {integrity: sha512-mRsi2vJsk4Bx/AFsNBqOH2fqedxn5L/moT58xgg51DjX1la64Z3Npicut2VbhvDFO26qjWtPMsVxCd80YTFVeg==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [android]
     requiresBuild: true
     optional: true
@@ -2392,12 +2290,12 @@ packages:
     cpu: [arm]
     os: [android]
     requiresBuild: true
     optional: true
 
-  /@esbuild/android-arm@0.19.3:
-    resolution: {integrity: sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==}
+  /@esbuild/android-arm@0.19.4:
+    resolution: {integrity: sha512-uBIbiYMeSsy2U0XQoOGVVcpIktjLMEKa7ryz2RLr7L/vTnANNEsPVAh4xOv7ondGz6ac1zVb0F8Jx20rQikffQ==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [android]
     requiresBuild: true
     optional: true
@@ -2425,12 +2323,12 @@ packages:
     cpu: [x64]
     os: [android]
     requiresBuild: true
     optional: true
 
-  /@esbuild/android-x64@0.19.3:
-    resolution: {integrity: sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==}
+  /@esbuild/android-x64@0.19.4:
+    resolution: {integrity: sha512-4iPufZ1TMOD3oBlGFqHXBpa3KFT46aLl6Vy7gwed0ZSYgHaZ/mihbYb4t7Z9etjkC9Al3ZYIoOaHrU60gcMy7g==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [android]
     requiresBuild: true
     optional: true
@@ -2458,12 +2356,12 @@ packages:
     cpu: [arm64]
     os: [darwin]
     requiresBuild: true
     optional: true
 
-  /@esbuild/darwin-arm64@0.19.3:
-    resolution: {integrity: sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==}
+  /@esbuild/darwin-arm64@0.19.4:
+    resolution: {integrity: sha512-Lviw8EzxsVQKpbS+rSt6/6zjn9ashUZ7Tbuvc2YENgRl0yZTktGlachZ9KMJUsVjZEGFVu336kl5lBgDN6PmpA==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [darwin]
     requiresBuild: true
     optional: true
@@ -2491,12 +2389,12 @@ packages:
     cpu: [x64]
     os: [darwin]
     requiresBuild: true
     optional: true
 
-  /@esbuild/darwin-x64@0.19.3:
-    resolution: {integrity: sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==}
+  /@esbuild/darwin-x64@0.19.4:
+    resolution: {integrity: sha512-YHbSFlLgDwglFn0lAO3Zsdrife9jcQXQhgRp77YiTDja23FrC2uwnhXMNkAucthsf+Psr7sTwYEryxz6FPAVqw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [darwin]
     requiresBuild: true
     optional: true
@@ -2524,12 +2422,12 @@ packages:
     cpu: [arm64]
     os: [freebsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/freebsd-arm64@0.19.3:
-    resolution: {integrity: sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==}
+  /@esbuild/freebsd-arm64@0.19.4:
+    resolution: {integrity: sha512-vz59ijyrTG22Hshaj620e5yhs2dU1WJy723ofc+KUgxVCM6zxQESmWdMuVmUzxtGqtj5heHyB44PjV/HKsEmuQ==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [freebsd]
     requiresBuild: true
     optional: true
@@ -2557,12 +2455,12 @@ packages:
     cpu: [x64]
     os: [freebsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/freebsd-x64@0.19.3:
-    resolution: {integrity: sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==}
+  /@esbuild/freebsd-x64@0.19.4:
+    resolution: {integrity: sha512-3sRbQ6W5kAiVQRBWREGJNd1YE7OgzS0AmOGjDmX/qZZecq8NFlQsQH0IfXjjmD0XtUYqr64e0EKNFjMUlPL3Cw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [freebsd]
     requiresBuild: true
     optional: true
@@ -2590,12 +2488,12 @@ packages:
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-arm64@0.19.3:
-    resolution: {integrity: sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==}
+  /@esbuild/linux-arm64@0.19.4:
+    resolution: {integrity: sha512-ZWmWORaPbsPwmyu7eIEATFlaqm0QGt+joRE9sKcnVUG3oBbr/KYdNE2TnkzdQwX6EDRdg/x8Q4EZQTXoClUqqA==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2623,12 +2521,12 @@ packages:
     cpu: [arm]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-arm@0.19.3:
-    resolution: {integrity: sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==}
+  /@esbuild/linux-arm@0.19.4:
+    resolution: {integrity: sha512-z/4ArqOo9EImzTi4b6Vq+pthLnepFzJ92BnofU1jgNlcVb+UqynVFdoXMCFreTK7FdhqAzH0vmdwW5373Hm9pg==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2656,12 +2554,12 @@ packages:
     cpu: [ia32]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-ia32@0.19.3:
-    resolution: {integrity: sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==}
+  /@esbuild/linux-ia32@0.19.4:
+    resolution: {integrity: sha512-EGc4vYM7i1GRUIMqRZNCTzJh25MHePYsnQfKDexD8uPTCm9mK56NIL04LUfX2aaJ+C9vyEp2fJ7jbqFEYgO9lQ==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2698,12 +2596,12 @@ packages:
     cpu: [loong64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-loong64@0.19.3:
-    resolution: {integrity: sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==}
+  /@esbuild/linux-loong64@0.19.4:
+    resolution: {integrity: sha512-WVhIKO26kmm8lPmNrUikxSpXcgd6HDog0cx12BUfA2PkmURHSgx9G6vA19lrlQOMw+UjMZ+l3PpbtzffCxFDRg==}
     engines: {node: '>=12'}
     cpu: [loong64]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2731,12 +2629,12 @@ packages:
     cpu: [mips64el]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-mips64el@0.19.3:
-    resolution: {integrity: sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==}
+  /@esbuild/linux-mips64el@0.19.4:
+    resolution: {integrity: sha512-keYY+Hlj5w86hNp5JJPuZNbvW4jql7c1eXdBUHIJGTeN/+0QFutU3GrS+c27L+NTmzi73yhtojHk+lr2+502Mw==}
     engines: {node: '>=12'}
     cpu: [mips64el]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2764,12 +2662,12 @@ packages:
     cpu: [ppc64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-ppc64@0.19.3:
-    resolution: {integrity: sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==}
+  /@esbuild/linux-ppc64@0.19.4:
+    resolution: {integrity: sha512-tQ92n0WMXyEsCH4m32S21fND8VxNiVazUbU4IUGVXQpWiaAxOBvtOtbEt3cXIV3GEBydYsY8pyeRMJx9kn3rvw==}
     engines: {node: '>=12'}
     cpu: [ppc64]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2797,12 +2695,12 @@ packages:
     cpu: [riscv64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-riscv64@0.19.3:
-    resolution: {integrity: sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==}
+  /@esbuild/linux-riscv64@0.19.4:
+    resolution: {integrity: sha512-tRRBey6fG9tqGH6V75xH3lFPpj9E8BH+N+zjSUCnFOX93kEzqS0WdyJHkta/mmJHn7MBaa++9P4ARiU4ykjhig==}
     engines: {node: '>=12'}
     cpu: [riscv64]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2830,12 +2728,12 @@ packages:
     cpu: [s390x]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-s390x@0.19.3:
-    resolution: {integrity: sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==}
+  /@esbuild/linux-s390x@0.19.4:
+    resolution: {integrity: sha512-152aLpQqKZYhThiJ+uAM4PcuLCAOxDsCekIbnGzPKVBRUDlgaaAfaUl5NYkB1hgY6WN4sPkejxKlANgVcGl9Qg==}
     engines: {node: '>=12'}
     cpu: [s390x]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2863,12 +2761,12 @@ packages:
     cpu: [x64]
     os: [linux]
     requiresBuild: true
     optional: true
 
-  /@esbuild/linux-x64@0.19.3:
-    resolution: {integrity: sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==}
+  /@esbuild/linux-x64@0.19.4:
+    resolution: {integrity: sha512-Mi4aNA3rz1BNFtB7aGadMD0MavmzuuXNTaYL6/uiYIs08U7YMPETpgNn5oue3ICr+inKwItOwSsJDYkrE9ekVg==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [linux]
     requiresBuild: true
     optional: true
@@ -2896,12 +2794,12 @@ packages:
     cpu: [x64]
     os: [netbsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/netbsd-x64@0.19.3:
-    resolution: {integrity: sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==}
+  /@esbuild/netbsd-x64@0.19.4:
+    resolution: {integrity: sha512-9+Wxx1i5N/CYo505CTT7T+ix4lVzEdz0uCoYGxM5JDVlP2YdDC1Bdz+Khv6IbqmisT0Si928eAxbmGkcbiuM/A==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [netbsd]
     requiresBuild: true
     optional: true
@@ -2929,12 +2827,12 @@ packages:
     cpu: [x64]
     os: [openbsd]
     requiresBuild: true
     optional: true
 
-  /@esbuild/openbsd-x64@0.19.3:
-    resolution: {integrity: sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==}
+  /@esbuild/openbsd-x64@0.19.4:
+    resolution: {integrity: sha512-MFsHleM5/rWRW9EivFssop+OulYVUoVcqkyOkjiynKBCGBj9Lihl7kh9IzrreDyXa4sNkquei5/DTP4uCk25xw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [openbsd]
     requiresBuild: true
     optional: true
@@ -2962,12 +2860,12 @@ packages:
     cpu: [x64]
     os: [sunos]
     requiresBuild: true
     optional: true
 
-  /@esbuild/sunos-x64@0.19.3:
-    resolution: {integrity: sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==}
+  /@esbuild/sunos-x64@0.19.4:
+    resolution: {integrity: sha512-6Xq8SpK46yLvrGxjp6HftkDwPP49puU4OF0hEL4dTxqCbfx09LyrbUj/D7tmIRMj5D5FCUPksBbxyQhp8tmHzw==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [sunos]
     requiresBuild: true
     optional: true
@@ -2995,12 +2893,12 @@ packages:
     cpu: [arm64]
     os: [win32]
     requiresBuild: true
     optional: true
 
-  /@esbuild/win32-arm64@0.19.3:
-    resolution: {integrity: sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==}
+  /@esbuild/win32-arm64@0.19.4:
+    resolution: {integrity: sha512-PkIl7Jq4mP6ke7QKwyg4fD4Xvn8PXisagV/+HntWoDEdmerB2LTukRZg728Yd1Fj+LuEX75t/hKXE2Ppk8Hh1w==}
     engines: {node: '>=12'}
     cpu: [arm64]
     os: [win32]
     requiresBuild: true
     optional: true
@@ -3028,12 +2926,12 @@ packages:
     cpu: [ia32]
     os: [win32]
     requiresBuild: true
     optional: true
 
-  /@esbuild/win32-ia32@0.19.3:
-    resolution: {integrity: sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==}
+  /@esbuild/win32-ia32@0.19.4:
+    resolution: {integrity: sha512-ga676Hnvw7/ycdKB53qPusvsKdwrWzEyJ+AtItHGoARszIqvjffTwaaW3b2L6l90i7MO9i+dlAW415INuRhSGg==}
     engines: {node: '>=12'}
     cpu: [ia32]
     os: [win32]
     requiresBuild: true
     optional: true
@@ -3061,12 +2959,12 @@ packages:
     cpu: [x64]
     os: [win32]
     requiresBuild: true
     optional: true
 
-  /@esbuild/win32-x64@0.19.3:
-    resolution: {integrity: sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==}
+  /@esbuild/win32-x64@0.19.4:
+    resolution: {integrity: sha512-HP0GDNla1T3ZL8Ko/SHAS2GgtjOg+VmWnnYLhuTksr++EnduYB0f3Y2LzHsUwb2iQ13JGoY6G3R8h6Du/WG6uA==}
     engines: {node: '>=12'}
     cpu: [x64]
     os: [win32]
     requiresBuild: true
     optional: true
@@ -3076,26 +2974,26 @@ packages:
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     peerDependencies:
       eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
     dependencies:
       eslint: 8.45.0
-      eslint-visitor-keys: 3.4.1
+      eslint-visitor-keys: 3.4.3
     dev: true
 
-  /@eslint-community/regexpp@4.6.1:
-    resolution: {integrity: sha512-O7x6dMstWLn2ktjcoiNLDkAGG2EjveHL+Vvc+n0fXumkJYAcSqcVYKtwDU+hDZ0uDUsnUagSYaZrOLAYE8un1A==}
+  /@eslint-community/regexpp@4.9.1:
+    resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==}
     engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
     dev: true
 
-  /@eslint/eslintrc@2.1.0:
-    resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==}
+  /@eslint/eslintrc@2.1.2:
+    resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dependencies:
       ajv: 6.12.6
       debug: 4.3.4
       espree: 9.6.1
-      globals: 13.20.0
+      globals: 13.23.0
       ignore: 5.2.4
       import-fresh: 3.3.0
       js-yaml: 4.1.0
       minimatch: 3.1.2
       strip-json-comments: 3.1.1
@@ -3126,21 +3024,25 @@ packages:
     engines: {node: '>=14'}
     dependencies:
       text-decoding: 1.0.0
     dev: false
 
+  /@fastify/busboy@2.0.0:
+    resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==}
+    engines: {node: '>=14'}
+
   /@fastify/cookie@8.3.0:
     resolution: {integrity: sha512-P9hY9GO11L20TnZ33XN3i0bt+3x0zaT7S0ohAzWO950E9PB2xnNhLYzPFJIGFi5AVN0yr5+/iZhWxeYvR6KCzg==}
     dependencies:
       cookie: 0.5.0
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
     dev: false
 
   /@fastify/cors@8.3.0:
     resolution: {integrity: sha512-oj9xkka2Tg0MrwuKhsSUumcAkfp2YCnKxmFEusi01pjk1YrdDsuSYTHXEelWNW+ilSy/ApZq0c2SvhKrLX0H1g==}
     dependencies:
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       mnemonist: 0.39.5
     dev: false
 
   /@fastify/deepmerge@1.3.0:
     resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==}
@@ -3148,37 +3050,37 @@ packages:
 
   /@fastify/env@4.2.0:
     resolution: {integrity: sha512-sj1ehQZPD6tty+6bhzZw1uS2K2s6eOB46maJ2fE+AuTYxdHKVVW/AHXqCYGu3nH9kgzdXsheu3/148ZoBeoQOw==}
     dependencies:
       env-schema: 5.2.0
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
     dev: false
 
-  /@fastify/error@3.2.1:
-    resolution: {integrity: sha512-scZVbcpPNWw/yyFmzzO7cf1daTeJp53spN2n7dBTHZd+cV7791fcWJCPP1Tfhdbre+8vDiCyQyqqXfQnYMntYQ==}
+  /@fastify/error@3.4.0:
+    resolution: {integrity: sha512-e/mafFwbK3MNqxUcFBLgHhgxsF8UT1m8aj0dAlqEa2nJEgPsRtpHTZ3ObgrgkZ2M1eJHPTwgyUl/tXkvabsZdQ==}
     dev: false
 
   /@fastify/fast-json-stringify-compiler@4.3.0:
     resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==}
     dependencies:
-      fast-json-stringify: 5.7.0
+      fast-json-stringify: 5.8.0
     dev: false
 
   /@fastify/jwt@7.2.0:
     resolution: {integrity: sha512-ONKobJVfFKaqUU3OEWHnkV0HVyJFfa+kzj8gEODEskhIXcf0Y8Trzsjca/Rl54VOsa5QnSgkZEXUpvChd3eUdQ==}
     dependencies:
-      '@fastify/error': 3.2.1
+      '@fastify/error': 3.4.0
       '@lukeed/ms': 2.0.1
-      fast-jwt: 3.1.1
-      fastify-plugin: 4.5.0
+      fast-jwt: 3.3.1
+      fastify-plugin: 4.5.1
       steed: 1.1.3
     dev: false
 
   /@fastify/mongodb@7.0.0:
     resolution: {integrity: sha512-NbneaY3iA+ZcWJWYObXVd+1tbBRqdA021h/hpyccd/dRMrvaKlGheVdmtGJFsHYw7lsJkTV+bciFrwi97JMYfg==}
     dependencies:
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       mongodb: 5.7.0
     transitivePeerDependencies:
       - '@aws-sdk/credential-providers'
       - '@mongodb-js/zstd'
       - kerberos
@@ -3189,43 +3091,43 @@ packages:
   /@fastify/multipart@7.7.3:
     resolution: {integrity: sha512-MG4Gd9FNEXc8qx0OgqoXM10EGO/dN/0iVQ8SrpFMU3d6F6KUfcqD2ZyoQhkm9LWrbiMgdHv5a43x78lASdn5GA==}
     dependencies:
       '@fastify/busboy': 1.2.1
       '@fastify/deepmerge': 1.3.0
-      '@fastify/error': 3.2.1
-      '@fastify/swagger': 8.10.0
-      '@fastify/swagger-ui': 1.9.3
+      '@fastify/error': 3.4.0
+      '@fastify/swagger': 8.11.0
+      '@fastify/swagger-ui': 1.10.0
       end-of-stream: 1.4.4
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       secure-json-parse: 2.7.0
       stream-wormhole: 1.1.0
     transitivePeerDependencies:
       - supports-color
     dev: false
 
   /@fastify/oauth2@7.2.1:
     resolution: {integrity: sha512-7a4tE4rL4BHqJiJsXVT6oHrAG9xzQx1kEs41yLCBsJ6CRy6PbBNs+q3iOt12gIY8OrfTAdvknxi1uTLgn08ggg==}
     dependencies:
       '@fastify/cookie': 8.3.0
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       simple-oauth2: 5.0.0
     transitivePeerDependencies:
       - supports-color
     dev: false
 
   /@fastify/rate-limit@8.0.3:
     resolution: {integrity: sha512-7wbSKXGKKLI1VkpW2XvS7SFg4n4/uzYt0YA5O2pfCcM6PYaBSV3VhSKGJ9/hJceCSH+zNEDRrWpufqxbcDkTZg==}
     dependencies:
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       ms: 2.1.3
-      tiny-lru: 11.0.1
+      tiny-lru: 11.2.2
     dev: false
 
   /@fastify/redis@6.1.1:
     resolution: {integrity: sha512-NZpHK+d3uJJ+w1iHx5n1woFvrHhhG52XjM9byWvU81KSsQpO0N/OikgQvz83frLV7UD4UQtTUgPvVbLxW0X81w==}
     dependencies:
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       ioredis: 5.3.2
     transitivePeerDependencies:
       - supports-color
     dev: false
 
@@ -3243,30 +3145,30 @@ packages:
     resolution: {integrity: sha512-UoaMvIHSBLCZBYOVZwFRYqX2ufUhd7FFMYGDeSf0Z+D8jhYtwljjmuQGuanUP8kS4y/ZEV1a8mfLha3zNwsnnQ==}
     dependencies:
       '@fastify/accept-negotiator': 1.1.0
       '@fastify/send': 2.1.0
       content-disposition: 0.5.4
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       glob: 8.1.0
       p-limit: 3.1.0
-      readable-stream: 4.4.0
+      readable-stream: 4.4.2
     dev: false
 
-  /@fastify/swagger-ui@1.9.3:
-    resolution: {integrity: sha512-YYqce4CydjDIEry6Zo4JLjVPe5rjS8iGnk3fHiIQnth9sFSLeyG0U1DCH+IyYmLddNDg1uWJOuErlVqnu/jI3w==}
+  /@fastify/swagger-ui@1.10.0:
+    resolution: {integrity: sha512-vps8KRDQ8JWQGG9Dh6fCOzAc81Y5a6RnCU/Sumyw3n7+HXJSYExnLLgv4aS9eRFSODtQ8kzZJ//IxAbf0nZ+sQ==}
     dependencies:
       '@fastify/static': 6.10.2
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       openapi-types: 12.1.3
       rfdc: 1.3.0
       yaml: 2.3.2
     dev: false
 
-  /@fastify/swagger@8.10.0:
-    resolution: {integrity: sha512-0o6nd0qWpJbVSv/vbK4bzHSYe7l+PTGPqrQVwWIXVGd7CvXr585SBx+h8EgrMOY80bcOnGreqnjYFOV0osGP5A==}
+  /@fastify/swagger@8.11.0:
+    resolution: {integrity: sha512-K8hAWr3wTBUojjJfNUy0TAl766ga2O/L5mWVbBZ6MImOOB3GYUgqNXC4MKrOejt8Y4Ps4cdKjkgzWLcUtg8SFg==}
     dependencies:
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       json-schema-resolver: 2.0.0
       openapi-types: 12.1.3
       rfdc: 1.3.0
       yaml: 2.3.2
     transitivePeerDependencies:
@@ -3274,44 +3176,50 @@ packages:
     dev: false
 
   /@fastify/view@8.0.0:
     resolution: {integrity: sha512-XfAffgqRj+AtEtkZeAAkMwTtu32Ve6xWkhxWQ9JOwXm2qQM6Fj+xphxnLvqpvQ0hJAYFYGiTOpB5ZS2VI5u00Q==}
     dependencies:
-      fastify-plugin: 4.5.0
+      fastify-plugin: 4.5.1
       hashlru: 2.3.0
     dev: false
 
   /@fastify/websocket@8.2.0:
     resolution: {integrity: sha512-B4tlHFBKCX7tenEG9aUcQEpksW2e0+dgRTaH/05+cro1Xsq1+kSj+9IB9Gep7a0KbHZGrat+zBsOas6lRs5dFQ==}
     dependencies:
-      fastify-plugin: 4.5.0
-      ws: 8.13.0
+      fastify-plugin: 4.5.1
+      ws: 8.14.2
     transitivePeerDependencies:
       - bufferutil
       - utf-8-validate
     dev: false
 
-  /@floating-ui/core@1.3.1:
-    resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
+  /@floating-ui/core@1.5.0:
+    resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==}
+    dependencies:
+      '@floating-ui/utils': 0.1.6
     dev: false
 
   /@floating-ui/dom@1.4.5:
     resolution: {integrity: sha512-96KnRWkRnuBSSFbj0sFGwwOUd8EkiecINVl0O9wiZlZ64EkpyAOG3Xc2vKKNJmru0Z7RqWNymA+6b8OZqjgyyw==}
     dependencies:
-      '@floating-ui/core': 1.3.1
+      '@floating-ui/core': 1.5.0
+    dev: false
+
+  /@floating-ui/utils@0.1.6:
+    resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==}
     dev: false
 
   /@fontsource/nunito@5.0.8:
     resolution: {integrity: sha512-Sb5uROR+aiS6T0CshbDAkjHmLXyWkWXCkDnx4K8fbRFPfmLpw6vKCu4iwb0+RuJDX519o98H/Qouk6p1umkFEQ==}
     dev: false
 
-  /@graphql-typed-document-node/core@3.2.0(graphql@16.7.1):
+  /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1):
     resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==}
     peerDependencies:
       graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
     dependencies:
-      graphql: 16.7.1
+      graphql: 16.8.1
     dev: false
 
   /@hapi/boom@10.0.1:
     resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==}
     dependencies:
@@ -3346,14 +3254,14 @@ packages:
       '@hapi/boom': 10.0.1
       '@hapi/bourne': 3.0.0
       '@hapi/hoek': 11.0.2
     dev: false
 
-  /@hocuspocus/common@2.5.0:
-    resolution: {integrity: sha512-TpnQAb1Rtff1trwURFWaUEYZwqykaIGo6NNnMr6ZISdDZFWNHMAMUmy7dwJDS9ECnEtcjXhpPxXeLV+MVQXVnw==}
+  /@hocuspocus/common@2.6.1:
+    resolution: {integrity: sha512-s6//HV4D8Oav3uFHZKWcKtKaKPd6j2hidmplFKufgh1dSKeZ6psiNv9SzB3GUYPva7Vw81dWbJ2U8fkOYNqHzg==}
     dependencies:
-      lib0: 0.2.78
+      lib0: 0.2.86
     dev: false
 
   /@hocuspocus/extension-database@2.5.0(y-protocols@1.0.5)(yjs@13.6.7):
     resolution: {integrity: sha512-O8SM9+ynoslYikLnOJAdJKvjDdhg6vgdHTJzPzETmsD7e8wbrPaQCLU9DKZOJ+zMdI5rFd+UdSclPOfxVxalGw==}
     peerDependencies:
@@ -3376,11 +3284,11 @@ packages:
       '@hocuspocus/server': 2.5.0(y-protocols@1.0.5)(yjs@13.6.7)
       ioredis: 4.28.5
       kleur: 4.1.5
       lodash.debounce: 4.0.8
       redlock: 4.2.0
-      uuid: 9.0.0
+      uuid: 9.0.1
       y-protocols: 1.0.5
       yjs: 13.6.7
     transitivePeerDependencies:
       - bufferutil
       - supports-color
@@ -3391,13 +3299,13 @@ packages:
     resolution: {integrity: sha512-Du/q0kcVhaSQiKPBha19f+mnFOl4sFybARRWsGp4JIoDG+Vt3r73ZqjalIJmp9h4mBr2tGtS5zK/oQ/Vrv5/Bw==}
     peerDependencies:
       y-protocols: ^1.0.5
       yjs: ^13.6.4
     dependencies:
-      '@hocuspocus/common': 2.5.0
+      '@hocuspocus/common': 2.6.1
       '@lifeomic/attempt': 3.0.3
-      lib0: 0.2.78
+      lib0: 0.2.86
       ws: 7.5.9
       y-protocols: 1.0.5
       yjs: 13.6.7
     transitivePeerDependencies:
       - bufferutil
@@ -3408,16 +3316,16 @@ packages:
     resolution: {integrity: sha512-7oopepZIdkU2XxJouVZSdsFTg2VaqwfM1so87VEY+b7DER68BS+rVb8Eimz9WER9ZLLyg5DK+t797rnXJX/1cQ==}
     peerDependencies:
       y-protocols: ^1.0.5
       yjs: ^13.6.4
     dependencies:
-      '@hocuspocus/common': 2.5.0
+      '@hocuspocus/common': 2.6.1
       async-lock: 1.4.0
       kleur: 4.1.5
-      lib0: 0.2.78
-      uuid: 9.0.0
-      ws: 8.13.0
+      lib0: 0.2.86
+      uuid: 9.0.1
+      ws: 8.14.2
       y-protocols: 1.0.5
       yjs: 13.6.7
     transitivePeerDependencies:
       - bufferutil
       - utf-8-validate
@@ -3430,17 +3338,17 @@ packages:
       y-prosemirror: ^1.0.15
       yjs: ^13.6.4
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
-      '@tiptap/starter-kit': 2.0.3(@tiptap/pm@2.1.8)
-      y-prosemirror: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
+      '@tiptap/starter-kit': 2.1.11(@tiptap/pm@2.1.8)
+      y-prosemirror: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
       yjs: 13.6.7
     dev: false
 
-  /@humanwhocodes/config-array@0.11.10:
-    resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
+  /@humanwhocodes/config-array@0.11.11:
+    resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==}
     engines: {node: '>=10.10.0'}
     dependencies:
       '@humanwhocodes/object-schema': 1.2.1
       debug: 4.3.4
       minimatch: 3.1.2
@@ -3458,12 +3366,12 @@ packages:
     dev: true
 
   /@iconify/types@2.0.0:
     resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
 
-  /@iconify/utils@2.1.9:
-    resolution: {integrity: sha512-mo+A4n3MwLlWlg1SoSO+Dt6pOPWKElk9sSJ6ZpuzbB9OcjxN8RUWxU3ulPwB1nglErWKRam2x4BAohbYF7FiFA==}
+  /@iconify/utils@2.1.11:
+    resolution: {integrity: sha512-M/w3PkN8zQYXi8N6qK/KhnYMfEbbb6Sk8RZVn8g+Pmmu5ybw177RpsaGwpziyHeUsu4etrexYSWq3rwnIqzYCg==}
     dependencies:
       '@antfu/install-pkg': 0.1.1
       '@antfu/utils': 0.7.6
       '@iconify/types': 2.0.0
       debug: 4.3.4
@@ -3496,99 +3404,47 @@ packages:
     resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
     engines: {node: '>=6.0.0'}
     dependencies:
       '@jridgewell/set-array': 1.1.2
       '@jridgewell/sourcemap-codec': 1.4.15
-      '@jridgewell/trace-mapping': 0.3.18
+      '@jridgewell/trace-mapping': 0.3.19
 
-  /@jridgewell/resolve-uri@3.1.0:
-    resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
+  /@jridgewell/resolve-uri@3.1.1:
+    resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
     engines: {node: '>=6.0.0'}
 
   /@jridgewell/set-array@1.1.2:
     resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
     engines: {node: '>=6.0.0'}
 
-  /@jridgewell/source-map@0.3.3:
-    resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==}
+  /@jridgewell/source-map@0.3.5:
+    resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
     dependencies:
       '@jridgewell/gen-mapping': 0.3.3
-      '@jridgewell/trace-mapping': 0.3.18
-    dev: true
-
-  /@jridgewell/sourcemap-codec@1.4.14:
-    resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
+      '@jridgewell/trace-mapping': 0.3.19
 
   /@jridgewell/sourcemap-codec@1.4.15:
     resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
 
-  /@jridgewell/trace-mapping@0.3.18:
-    resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==}
+  /@jridgewell/trace-mapping@0.3.19:
+    resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
     dependencies:
-      '@jridgewell/resolve-uri': 3.1.0
-      '@jridgewell/sourcemap-codec': 1.4.14
+      '@jridgewell/resolve-uri': 3.1.1
+      '@jridgewell/sourcemap-codec': 1.4.15
 
   /@lifeomic/attempt@3.0.3:
     resolution: {integrity: sha512-GlM2AbzrErd/TmLL3E8hAHmb5Q7VhDJp35vIbyPVA5Rz55LZuRr8pwL3qrwwkVNo05gMX1J44gURKb4MHQZo7w==}
     dev: false
 
-  /@linaria/core@4.2.9:
-    resolution: {integrity: sha512-ELcu37VNVOT/PU0L6WDIN+aLzNFyJrqoBYT0CucGOCAmODbojUMCv8oJYRbWzA3N34w1t199dN4UFdfRWFG2rg==}
-    engines: {node: ^12.16.0 || >=13.7.0}
-    dependencies:
-      '@linaria/logger': 4.0.0
-      '@linaria/tags': 4.3.5
-      '@linaria/utils': 4.3.4
-    transitivePeerDependencies:
-      - supports-color
+  /@lukeed/ms@2.0.1:
+    resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==}
+    engines: {node: '>=8'}
     dev: false
 
-  /@linaria/logger@4.0.0:
-    resolution: {integrity: sha512-YnBq0JlDWMEkTOK+tMo5yEVR0f5V//6qMLToGcLhTyM9g9i+IDFn51Z+5q2hLk7RdG4NBPgbcCXYi2w4RKsPeg==}
-    engines: {node: ^12.16.0 || >=13.7.0}
-    dependencies:
-      debug: 4.3.4
-      picocolors: 1.0.0
-    transitivePeerDependencies:
-      - supports-color
-    dev: false
-
-  /@linaria/tags@4.3.5:
-    resolution: {integrity: sha512-PgaIi8Vv89YOjc6rpKL/uPg2w4k0rAwAYxcqeXqzKqsEAste5rgB8xp1/KUOG0oAOkPd3MRL6Duj+m0ZwJ3g+g==}
-    engines: {node: ^12.16.0 || >=13.7.0}
-    dependencies:
-      '@babel/generator': 7.22.15
-      '@linaria/logger': 4.0.0
-      '@linaria/utils': 4.3.4
-    transitivePeerDependencies:
-      - supports-color
-    dev: false
-
-  /@linaria/utils@4.3.4:
-    resolution: {integrity: sha512-vt6WJG54n+KANaqxOfzIIU7aSfFHEWFbnGLsgxL7nASHqO0zezrNA2y2Rrp80zSeTW+wSpbmDM4uJyC9UW1qoA==}
-    engines: {node: ^12.16.0 || >=13.7.0}
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.22.15)
-      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.15)
-      '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.15)
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-      '@linaria/logger': 4.0.0
-      babel-merge: 3.0.0(@babel/core@7.22.15)
-    transitivePeerDependencies:
-      - supports-color
-    dev: false
-
-  /@lukeed/ms@2.0.1:
-    resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==}
-    engines: {node: '>=8'}
-    dev: false
-
-  /@manypkg/find-root@2.1.0:
-    resolution: {integrity: sha512-NEYRVlZCJYhRTqQURhv+WBpDcvmsp/M423Wcdvggv8lYJYD4GtqnTMLrQaTjA10fYt/PIc3tSdwV+wxJnWqPfQ==}
-    engines: {node: '>=14.18.0'}
+  /@manypkg/find-root@2.1.0:
+    resolution: {integrity: sha512-NEYRVlZCJYhRTqQURhv+WBpDcvmsp/M423Wcdvggv8lYJYD4GtqnTMLrQaTjA10fYt/PIc3tSdwV+wxJnWqPfQ==}
+    engines: {node: '>=14.18.0'}
     dependencies:
       '@manypkg/tools': 1.1.0
       '@types/node': 12.20.55
       find-up: 4.1.0
       fs-extra: 8.1.0
@@ -3606,72 +3462,96 @@ packages:
 
   /@mdi/js@7.2.96:
     resolution: {integrity: sha512-paR9M9ZT7rKbh2boksNUynuSZMHhqRYnEZOm/KrZTjQ4/FzyhjLHuvw/8XYzP+E7fS4+/Ms/82EN1pl/OFsiIA==}
     dev: false
 
+  /@mdx-js/mdx@2.3.0:
+    resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/mdx': 2.0.8
+      estree-util-build-jsx: 2.2.2
+      estree-util-is-identifier-name: 2.1.0
+      estree-util-to-js: 1.2.0
+      estree-walker: 3.0.3
+      hast-util-to-estree: 2.3.3
+      markdown-extensions: 1.1.1
+      periscopic: 3.1.0
+      remark-mdx: 2.3.0
+      remark-parse: 10.0.2
+      remark-rehype: 10.1.0
+      unified: 10.1.2
+      unist-util-position-from-estree: 1.1.2
+      unist-util-stringify-position: 3.0.3
+      unist-util-visit: 4.1.2
+      vfile: 5.3.7
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /@microsoft/fetch-event-source@2.0.1:
     resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==}
     dev: false
 
-  /@motionone/animation@10.15.1:
-    resolution: {integrity: sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==}
+  /@motionone/animation@10.16.3:
+    resolution: {integrity: sha512-QUGWpLbMFLhyqKlngjZhjtxM8IqiJQjLK0DF+XOF6od9nhSvlaeEpOY/UMCRVcZn/9Tr2rZO22EkuCIjYdI74g==}
     dependencies:
-      '@motionone/easing': 10.15.1
-      '@motionone/types': 10.15.1
-      '@motionone/utils': 10.15.1
-      tslib: 2.5.3
+      '@motionone/easing': 10.16.3
+      '@motionone/types': 10.16.3
+      '@motionone/utils': 10.16.3
+      tslib: 2.6.2
     dev: false
 
-  /@motionone/dom@10.16.2:
-    resolution: {integrity: sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg==}
+  /@motionone/dom@10.16.4:
+    resolution: {integrity: sha512-HPHlVo/030qpRj9R8fgY50KTN4Ko30moWRTA3L3imrsRBmob93cTYmodln49HYFbQm01lFF7X523OkKY0DX6UA==}
     dependencies:
-      '@motionone/animation': 10.15.1
-      '@motionone/generators': 10.15.1
-      '@motionone/types': 10.15.1
-      '@motionone/utils': 10.15.1
+      '@motionone/animation': 10.16.3
+      '@motionone/generators': 10.16.4
+      '@motionone/types': 10.16.3
+      '@motionone/utils': 10.16.3
       hey-listen: 1.0.8
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
-  /@motionone/easing@10.15.1:
-    resolution: {integrity: sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==}
+  /@motionone/easing@10.16.3:
+    resolution: {integrity: sha512-HWTMZbTmZojzwEuKT/xCdvoMPXjYSyQvuVM6jmM0yoGU6BWzsmYMeB4bn38UFf618fJCNtP9XeC/zxtKWfbr0w==}
     dependencies:
-      '@motionone/utils': 10.15.1
-      tslib: 2.5.3
+      '@motionone/utils': 10.16.3
+      tslib: 2.6.2
     dev: false
 
-  /@motionone/generators@10.15.1:
-    resolution: {integrity: sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==}
+  /@motionone/generators@10.16.4:
+    resolution: {integrity: sha512-geFZ3w0Rm0ZXXpctWsSf3REGywmLLujEjxPYpBR0j+ymYwof0xbV6S5kGqqsDKgyWKVWpUInqQYvQfL6fRbXeg==}
     dependencies:
-      '@motionone/types': 10.15.1
-      '@motionone/utils': 10.15.1
-      tslib: 2.5.3
+      '@motionone/types': 10.16.3
+      '@motionone/utils': 10.16.3
+      tslib: 2.6.2
     dev: false
 
-  /@motionone/solid@10.16.2(solid-js@1.7.8):
+  /@motionone/solid@10.16.2(solid-js@1.7.11):
     resolution: {integrity: sha512-0bl1KRDWc6BRcKXzRZR2KdRzIIN86SfSe8mcfKPwHYQDzdOEohRcYUsDaYlwWuwU07VCngOHZEPgFCofDJ80zw==}
     peerDependencies:
       solid-js: ^1.5.0
     dependencies:
-      '@motionone/dom': 10.16.2
-      '@motionone/utils': 10.15.1
-      '@solid-primitives/props': 3.1.6(solid-js@1.7.8)
-      '@solid-primitives/refs': 1.0.4(solid-js@1.7.8)
-      '@solid-primitives/transition-group': 1.0.2(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@motionone/dom': 10.16.4
+      '@motionone/utils': 10.16.3
+      '@solid-primitives/props': 3.1.8(solid-js@1.7.11)
+      '@solid-primitives/refs': 1.0.5(solid-js@1.7.11)
+      '@solid-primitives/transition-group': 1.0.3(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@motionone/types@10.15.1:
-    resolution: {integrity: sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==}
+  /@motionone/types@10.16.3:
+    resolution: {integrity: sha512-W4jkEGFifDq73DlaZs3HUfamV2t1wM35zN/zX7Q79LfZ2sc6C0R1baUHZmqc/K5F3vSw3PavgQ6HyHLd/MXcWg==}
     dev: false
 
-  /@motionone/utils@10.15.1:
-    resolution: {integrity: sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==}
+  /@motionone/utils@10.16.3:
+    resolution: {integrity: sha512-WNWDksJIxQkaI9p9Z9z0+K27xdqISGNFy1SsWVGaiedTHq0iaT6iZujby8fT/ZnZxj1EOaxJtSfUPCFNU5CRoA==}
     dependencies:
-      '@motionone/types': 10.15.1
+      '@motionone/types': 10.16.3
       hey-listen: 1.0.8
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1:
     resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==}
     dependencies:
@@ -3694,69 +3574,69 @@ packages:
     engines: {node: '>= 8'}
     dependencies:
       '@nodelib/fs.scandir': 2.1.5
       fastq: 1.15.0
 
-  /@octokit/app@14.0.0:
-    resolution: {integrity: sha512-g/zDXttroZ9Se08shK0d0d/j0cgSA+h4WV7qGUevNEM0piNBkIlfb4Fm6bSwCNAZhNf72mBgERmYOoxicPkqdw==}
+  /@octokit/app@14.0.1:
+    resolution: {integrity: sha512-4opdXcWBVhzd6FOxlaxDKXXqi9Vz2hsDSWQGNo49HbYFAX11UqMpksMjEdfvHy0x19Pse8Nvn+R6inNb/V398w==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/auth-app': 6.0.0
-      '@octokit/auth-unauthenticated': 5.0.0
-      '@octokit/core': 5.0.0
+      '@octokit/auth-app': 6.0.1
+      '@octokit/auth-unauthenticated': 5.0.1
+      '@octokit/core': 5.0.1
       '@octokit/oauth-app': 6.0.0
-      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
-      '@octokit/types': 11.1.0
+      '@octokit/plugin-paginate-rest': 9.0.0(@octokit/core@5.0.1)
+      '@octokit/types': 12.0.0
       '@octokit/webhooks': 12.0.3
     dev: false
 
-  /@octokit/auth-app@6.0.0:
-    resolution: {integrity: sha512-OKct7Rukf3g9DjpzcpdacQsdmd6oPrJ7fZND22JkjzhDvfhttUOnmh+qPS4kHhaNNyTxqSThnfrUWvkqNLd1nw==}
+  /@octokit/auth-app@6.0.1:
+    resolution: {integrity: sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/auth-oauth-app': 7.0.0
-      '@octokit/auth-oauth-user': 4.0.0
-      '@octokit/request': 8.1.1
-      '@octokit/request-error': 5.0.0
-      '@octokit/types': 11.1.0
+      '@octokit/auth-oauth-app': 7.0.1
+      '@octokit/auth-oauth-user': 4.0.1
+      '@octokit/request': 8.1.3
+      '@octokit/request-error': 5.0.1
+      '@octokit/types': 12.0.0
       deprecation: 2.3.1
-      lru-cache: 10.0.0
+      lru-cache: 10.0.1
       universal-github-app-jwt: 1.1.1
       universal-user-agent: 6.0.0
     dev: false
 
-  /@octokit/auth-oauth-app@7.0.0:
-    resolution: {integrity: sha512-8JvJEXGoEqrbzLwt3SwIUvkDd+1wrM8up0KawvDIElB8rbxPbvWppGO0SLKAWSJ0q8ILcVq+mWck6pDcZ3a9KA==}
+  /@octokit/auth-oauth-app@7.0.1:
+    resolution: {integrity: sha512-RE0KK0DCjCHXHlQBoubwlLijXEKfhMhKm9gO56xYvFmP1QTMb+vvwRPmQLLx0V+5AvV9N9I3lr1WyTzwL3rMDg==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/auth-oauth-device': 6.0.0
-      '@octokit/auth-oauth-user': 4.0.0
-      '@octokit/request': 8.1.1
-      '@octokit/types': 11.1.0
+      '@octokit/auth-oauth-device': 6.0.1
+      '@octokit/auth-oauth-user': 4.0.1
+      '@octokit/request': 8.1.3
+      '@octokit/types': 12.0.0
       '@types/btoa-lite': 1.0.0
       btoa-lite: 1.0.0
       universal-user-agent: 6.0.0
     dev: false
 
-  /@octokit/auth-oauth-device@6.0.0:
-    resolution: {integrity: sha512-Zgf/LKhwWk54rJaTGYVYtbKgUty+ouil6VQeRd+pCw7Gd0ECoSWaZuHK6uDGC/HtnWHjpSWFhzxPauDoHcNRtg==}
+  /@octokit/auth-oauth-device@6.0.1:
+    resolution: {integrity: sha512-yxU0rkL65QkjbqQedgVx3gmW7YM5fF+r5uaSj9tM/cQGVqloXcqP2xK90eTyYvl29arFVCW8Vz4H/t47mL0ELw==}
     engines: {node: '>= 18'}
     dependencies:
       '@octokit/oauth-methods': 4.0.0
-      '@octokit/request': 8.1.1
-      '@octokit/types': 11.1.0
+      '@octokit/request': 8.1.3
+      '@octokit/types': 12.0.0
       universal-user-agent: 6.0.0
     dev: false
 
-  /@octokit/auth-oauth-user@4.0.0:
-    resolution: {integrity: sha512-VOm5aIkVGHaOhIvsF/4YmSjoYDzzrKbbYkdSEO0KqHK7I8SlO3ZndSikQ1fBlNPUEH0ve2BOTxLrVvI1qBf9/Q==}
+  /@octokit/auth-oauth-user@4.0.1:
+    resolution: {integrity: sha512-N94wWW09d0hleCnrO5wt5MxekatqEJ4zf+1vSe8MKMrhZ7gAXKFOKrDEZW2INltvBWJCyDUELgGRv8gfErH1Iw==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/auth-oauth-device': 6.0.0
+      '@octokit/auth-oauth-device': 6.0.1
       '@octokit/oauth-methods': 4.0.0
-      '@octokit/request': 8.1.1
-      '@octokit/types': 11.1.0
+      '@octokit/request': 8.1.3
+      '@octokit/types': 12.0.0
       btoa-lite: 1.0.0
       universal-user-agent: 6.0.0
     dev: false
 
   /@octokit/auth-token@3.0.4:
@@ -3767,16 +3647,16 @@ packages:
   /@octokit/auth-token@4.0.0:
     resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==}
     engines: {node: '>= 18'}
     dev: false
 
-  /@octokit/auth-unauthenticated@5.0.0:
-    resolution: {integrity: sha512-AjOI6FNB2dweJ85p6rf7D4EhE4y6VBcwYfX/7KJkR5Q9fD9ET6NABAjajUTSNFfCxmNIaQgISggZ3pkgwtTqsA==}
+  /@octokit/auth-unauthenticated@5.0.1:
+    resolution: {integrity: sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/request-error': 5.0.0
-      '@octokit/types': 11.1.0
+      '@octokit/request-error': 5.0.1
+      '@octokit/types': 12.0.0
     dev: false
 
   /@octokit/core@4.2.4:
     resolution: {integrity: sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==}
     engines: {node: '>= 14'}
@@ -3790,19 +3670,19 @@ packages:
       universal-user-agent: 6.0.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
-  /@octokit/core@5.0.0:
-    resolution: {integrity: sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==}
+  /@octokit/core@5.0.1:
+    resolution: {integrity: sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==}
     engines: {node: '>= 18'}
     dependencies:
       '@octokit/auth-token': 4.0.0
-      '@octokit/graphql': 7.0.1
-      '@octokit/request': 8.1.1
-      '@octokit/request-error': 5.0.0
-      '@octokit/types': 11.1.0
+      '@octokit/graphql': 7.0.2
+      '@octokit/request': 8.1.3
+      '@octokit/request-error': 5.0.1
+      '@octokit/types': 12.0.0
       before-after-hook: 2.2.3
       universal-user-agent: 6.0.0
     dev: false
 
   /@octokit/endpoint@7.0.6:
@@ -3812,15 +3692,15 @@ packages:
       '@octokit/types': 9.3.2
       is-plain-object: 5.0.0
       universal-user-agent: 6.0.0
     dev: false
 
-  /@octokit/endpoint@9.0.0:
-    resolution: {integrity: sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==}
+  /@octokit/endpoint@9.0.1:
+    resolution: {integrity: sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/types': 11.1.0
+      '@octokit/types': 12.0.0
       is-plain-object: 5.0.0
       universal-user-agent: 6.0.0
     dev: false
 
   /@octokit/graphql@5.0.6:
@@ -3832,30 +3712,30 @@ packages:
       universal-user-agent: 6.0.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
-  /@octokit/graphql@7.0.1:
-    resolution: {integrity: sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==}
+  /@octokit/graphql@7.0.2:
+    resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/request': 8.1.1
-      '@octokit/types': 11.1.0
+      '@octokit/request': 8.1.3
+      '@octokit/types': 12.0.0
       universal-user-agent: 6.0.0
     dev: false
 
   /@octokit/oauth-app@6.0.0:
     resolution: {integrity: sha512-bNMkS+vJ6oz2hCyraT9ZfTpAQ8dZNqJJQVNaKjPLx4ue5RZiFdU1YWXguOPR8AaSHS+lKe+lR3abn2siGd+zow==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/auth-oauth-app': 7.0.0
-      '@octokit/auth-oauth-user': 4.0.0
-      '@octokit/auth-unauthenticated': 5.0.0
-      '@octokit/core': 5.0.0
+      '@octokit/auth-oauth-app': 7.0.1
+      '@octokit/auth-oauth-user': 4.0.1
+      '@octokit/auth-unauthenticated': 5.0.1
+      '@octokit/core': 5.0.1
       '@octokit/oauth-authorization-url': 6.0.2
       '@octokit/oauth-methods': 4.0.0
-      '@types/aws-lambda': 8.10.119
+      '@types/aws-lambda': 8.10.124
       universal-user-agent: 6.0.0
     dev: false
 
   /@octokit/oauth-authorization-url@6.0.2:
     resolution: {integrity: sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==}
@@ -3865,18 +3745,22 @@ packages:
   /@octokit/oauth-methods@4.0.0:
     resolution: {integrity: sha512-dqy7BZLfLbi3/8X8xPKUKZclMEK9vN3fK5WF3ortRvtplQTszFvdAGbTo71gGLO+4ZxspNiLjnqdd64Chklf7w==}
     engines: {node: '>= 18'}
     dependencies:
       '@octokit/oauth-authorization-url': 6.0.2
-      '@octokit/request': 8.1.1
-      '@octokit/request-error': 5.0.0
+      '@octokit/request': 8.1.3
+      '@octokit/request-error': 5.0.1
       '@octokit/types': 11.1.0
       btoa-lite: 1.0.0
     dev: false
 
-  /@octokit/openapi-types@18.0.0:
-    resolution: {integrity: sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==}
+  /@octokit/openapi-types@18.1.1:
+    resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==}
+    dev: false
+
+  /@octokit/openapi-types@19.0.0:
+    resolution: {integrity: sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==}
     dev: false
 
   /@octokit/plugin-paginate-rest@6.1.2(@octokit/core@4.2.4):
     resolution: {integrity: sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==}
     engines: {node: '>= 14'}
@@ -3886,35 +3770,45 @@ packages:
       '@octokit/core': 4.2.4
       '@octokit/tsconfig': 1.0.2
       '@octokit/types': 9.3.2
     dev: false
 
-  /@octokit/plugin-paginate-rest@8.0.0(@octokit/core@5.0.0):
+  /@octokit/plugin-paginate-rest@8.0.0(@octokit/core@5.0.1):
     resolution: {integrity: sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==}
     engines: {node: '>= 18'}
     peerDependencies:
       '@octokit/core': '>=5'
     dependencies:
-      '@octokit/core': 5.0.0
+      '@octokit/core': 5.0.1
       '@octokit/types': 11.1.0
     dev: false
 
+  /@octokit/plugin-paginate-rest@9.0.0(@octokit/core@5.0.1):
+    resolution: {integrity: sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==}
+    engines: {node: '>= 18'}
+    peerDependencies:
+      '@octokit/core': '>=5'
+    dependencies:
+      '@octokit/core': 5.0.1
+      '@octokit/types': 12.0.0
+    dev: false
+
   /@octokit/plugin-request-log@1.0.4(@octokit/core@4.2.4):
     resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==}
     peerDependencies:
       '@octokit/core': '>=3'
     dependencies:
       '@octokit/core': 4.2.4
     dev: false
 
-  /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.0):
+  /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.1):
     resolution: {integrity: sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==}
     engines: {node: '>= 18'}
     peerDependencies:
       '@octokit/core': '>=5'
     dependencies:
-      '@octokit/core': 5.0.0
+      '@octokit/core': 5.0.1
     dev: false
 
   /@octokit/plugin-rest-endpoint-methods@7.2.3(@octokit/core@4.2.4):
     resolution: {integrity: sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==}
     engines: {node: '>= 14'}
@@ -3923,39 +3817,39 @@ packages:
     dependencies:
       '@octokit/core': 4.2.4
       '@octokit/types': 10.0.0
     dev: false
 
-  /@octokit/plugin-rest-endpoint-methods@9.0.0(@octokit/core@5.0.0):
+  /@octokit/plugin-rest-endpoint-methods@9.0.0(@octokit/core@5.0.1):
     resolution: {integrity: sha512-KquMF/VB1IkKNiVnzJKspY5mFgGyLd7HzdJfVEGTJFzqu9BRFNWt+nwTCMuUiWc72gLQhRWYubTwOkQj+w/1PA==}
     engines: {node: '>= 18'}
     peerDependencies:
       '@octokit/core': '>=5'
     dependencies:
-      '@octokit/core': 5.0.0
+      '@octokit/core': 5.0.1
       '@octokit/types': 11.1.0
     dev: false
 
-  /@octokit/plugin-retry@6.0.0(@octokit/core@5.0.0):
-    resolution: {integrity: sha512-a1/A4A+PB1QoAHQfLJxGHhLfSAT03bR1jJz3GgQJZvty2ozawFWs93MiBQXO7SL2YbO7CIq0Goj4qLOBj8JeMQ==}
+  /@octokit/plugin-retry@6.0.1(@octokit/core@5.0.1):
+    resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==}
     engines: {node: '>= 18'}
     peerDependencies:
       '@octokit/core': '>=5'
     dependencies:
-      '@octokit/core': 5.0.0
-      '@octokit/request-error': 5.0.0
-      '@octokit/types': 11.1.0
+      '@octokit/core': 5.0.1
+      '@octokit/request-error': 5.0.1
+      '@octokit/types': 12.0.0
       bottleneck: 2.19.5
     dev: false
 
-  /@octokit/plugin-throttling@7.0.0(@octokit/core@5.0.0):
+  /@octokit/plugin-throttling@7.0.0(@octokit/core@5.0.1):
     resolution: {integrity: sha512-KL2k/d0uANc8XqP5S64YcNFCudR3F5AaKO39XWdUtlJIjT9Ni79ekWJ6Kj5xvAw87udkOMEPcVf9xEge2+ahew==}
     engines: {node: '>= 18'}
     peerDependencies:
       '@octokit/core': ^5.0.0
     dependencies:
-      '@octokit/core': 5.0.0
+      '@octokit/core': 5.0.1
       '@octokit/types': 11.1.0
       bottleneck: 2.19.5
     dev: false
 
   /@octokit/request-error@3.0.3:
@@ -3965,15 +3859,15 @@ packages:
       '@octokit/types': 9.3.2
       deprecation: 2.3.1
       once: 1.4.0
     dev: false
 
-  /@octokit/request-error@5.0.0:
-    resolution: {integrity: sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==}
+  /@octokit/request-error@5.0.1:
+    resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/types': 11.1.0
+      '@octokit/types': 12.0.0
       deprecation: 2.3.1
       once: 1.4.0
     dev: false
 
   /@octokit/request@6.2.8:
@@ -3982,23 +3876,23 @@ packages:
     dependencies:
       '@octokit/endpoint': 7.0.6
       '@octokit/request-error': 3.0.3
       '@octokit/types': 9.3.2
       is-plain-object: 5.0.0
-      node-fetch: 2.6.12
+      node-fetch: 2.7.0
       universal-user-agent: 6.0.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
-  /@octokit/request@8.1.1:
-    resolution: {integrity: sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==}
+  /@octokit/request@8.1.3:
+    resolution: {integrity: sha512-iUvXP4QmysS8kyE/a4AGwR0A+tHDVxgW6TmPd2ci8/Xc8KjlBtTKSDpZlUT5Y4S4Nu+eM8LvbOYjVAp/sz3Gpg==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/endpoint': 9.0.0
-      '@octokit/request-error': 5.0.0
-      '@octokit/types': 11.1.0
+      '@octokit/endpoint': 9.0.1
+      '@octokit/request-error': 5.0.1
+      '@octokit/types': 12.0.0
       is-plain-object: 5.0.0
       universal-user-agent: 6.0.0
     dev: false
 
   /@octokit/rest@19.0.7:
@@ -4015,36 +3909,42 @@ packages:
 
   /@octokit/rest@20.0.1:
     resolution: {integrity: sha512-wROV21RwHQIMNb2Dgd4+pY+dVy1Dwmp85pBrgr6YRRDYRBu9Gb+D73f4Bl2EukZSj5hInq2Tui9o7gAQpc2k2Q==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/core': 5.0.0
-      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
-      '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.0)
-      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.0)
+      '@octokit/core': 5.0.1
+      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.1)
+      '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.1)
+      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.1)
     dev: false
 
   /@octokit/tsconfig@1.0.2:
     resolution: {integrity: sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==}
     dev: false
 
   /@octokit/types@10.0.0:
     resolution: {integrity: sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==}
     dependencies:
-      '@octokit/openapi-types': 18.0.0
+      '@octokit/openapi-types': 18.1.1
     dev: false
 
   /@octokit/types@11.1.0:
     resolution: {integrity: sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==}
     dependencies:
-      '@octokit/openapi-types': 18.0.0
+      '@octokit/openapi-types': 18.1.1
+    dev: false
+
+  /@octokit/types@12.0.0:
+    resolution: {integrity: sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==}
+    dependencies:
+      '@octokit/openapi-types': 19.0.0
     dev: false
 
   /@octokit/types@9.3.2:
     resolution: {integrity: sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==}
     dependencies:
-      '@octokit/openapi-types': 18.0.0
+      '@octokit/openapi-types': 18.1.1
     dev: false
 
   /@octokit/webhooks-methods@4.0.0:
     resolution: {integrity: sha512-M8mwmTXp+VeolOS/kfRvsDdW+IO0qJ8kYodM/sAysk093q6ApgmBXwK1ZlUvAwXVrp/YVHp6aArj4auAxUAOFw==}
     engines: {node: '>= 18'}
@@ -4056,11 +3956,11 @@ packages:
 
   /@octokit/webhooks@12.0.3:
     resolution: {integrity: sha512-8iG+/yza7hwz1RrQ7i7uGpK2/tuItZxZq1aTmeg2TNp2xTUB8F8lZF/FcZvyyAxT8tpDMF74TjFGCDACkf1kAQ==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/request-error': 5.0.0
+      '@octokit/request-error': 5.0.1
       '@octokit/webhooks-methods': 4.0.0
       '@octokit/webhooks-types': 7.1.0
       aggregate-error: 3.1.0
     dev: false
 
@@ -4073,28 +3973,36 @@ packages:
     engines: {node: '>=14'}
     requiresBuild: true
     dev: false
     optional: true
 
-  /@pkgr/utils@2.4.1:
-    resolution: {integrity: sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==}
+  /@pkgr/utils@2.4.2:
+    resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==}
     engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
     dependencies:
       cross-spawn: 7.0.3
       fast-glob: 3.3.1
       is-glob: 4.0.3
       open: 9.1.0
       picocolors: 1.0.0
-      tslib: 2.5.3
+      tslib: 2.6.2
 
-  /@polka/url@1.0.0-next.21:
-    resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
+  /@polka/url@1.0.0-next.23:
+    resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==}
 
   /@popperjs/core@2.11.8:
     resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
     dev: false
 
+  /@prettier/sync@0.3.0(prettier@3.0.2):
+    resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==}
+    peerDependencies:
+      prettier: ^3.0.0
+    dependencies:
+      prettier: 3.0.2
+    dev: false
+
   /@proload/core@0.3.3:
     resolution: {integrity: sha512-7dAFWsIK84C90AMl24+N/ProHKm4iw0akcnoKjRvbfHifJZBLhaDsDus1QJmhG12lXj4e/uB/8mB/0aduCW+NQ==}
     dependencies:
       deepmerge: 4.3.1
       escalade: 3.1.1
@@ -4107,65 +4015,65 @@ packages:
     dependencies:
       '@proload/core': 0.3.3
       tsm: 2.3.0
     dev: true
 
-  /@qdrant/js-client-grpc@1.4.0(typescript@5.1.6):
+  /@qdrant/js-client-grpc@1.4.0(typescript@5.2.2):
     resolution: {integrity: sha512-Ue30STJz6pHrlvSbox3+7vqU/tSZUywQWeqahDP0TvyxtaOtV1D4nsFkshk5kMpWzPNircNglA7gNdQlnVPxVw==}
     engines: {node: '>=18.0.0', pnpm: '>=8'}
     peerDependencies:
       typescript: '>=4.1'
     dependencies:
-      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.0)
-      '@bufbuild/connect-node': 0.9.1(@bufbuild/protobuf@1.3.0)
-      '@bufbuild/protobuf': 1.3.0
-      typescript: 5.1.6
+      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.3)
+      '@bufbuild/connect-node': 0.9.1(@bufbuild/protobuf@1.3.3)
+      '@bufbuild/protobuf': 1.3.3
+      typescript: 5.2.2
     dev: false
 
-  /@qdrant/js-client-rest@1.4.0(typescript@5.1.6):
+  /@qdrant/js-client-rest@1.4.0(typescript@5.2.2):
     resolution: {integrity: sha512-I3pCKnaVdqiVpZ9+XtEjCx7IQSJnerXffD/g8mj/fZsOOJH3IFM+nF2izOfVIByufAArW+drGcAPrxHedba99w==}
     engines: {node: '>=18.0.0', pnpm: '>=8'}
     peerDependencies:
       typescript: '>=4.1'
     dependencies:
       '@qdrant/openapi-typescript-fetch': 1.2.1
       '@sevinf/maybe': 0.5.0
-      typescript: 5.1.6
-      undici: 5.22.1
+      typescript: 5.2.2
+      undici: 5.25.4
     dev: false
 
   /@qdrant/openapi-typescript-fetch@1.2.1:
     resolution: {integrity: sha512-oiBJRN1ME7orFZocgE25jrM3knIF/OKJfMsZPBbtMMKfgNVYfps0MokGvSJkBmecj6bf8QoLXWIGlIoaTM4Zmw==}
     engines: {node: '>=12.0.0', pnpm: '>=8'}
     dev: false
 
-  /@qdrant/qdrant-js@1.4.0(typescript@5.1.6):
+  /@qdrant/qdrant-js@1.4.0(typescript@5.2.2):
     resolution: {integrity: sha512-3bqyvmclwCYSQyvp6X2rwTVeXE/3wXp2Y2DUsVWg/uY0FO6jdCKYjqqMmu1wR9UpmLpaFrLqVVPt+nEntTiuAg==}
     engines: {node: '>=18.0.0', pnpm: '>=8'}
     peerDependencies:
       typescript: '>=4.1'
     dependencies:
-      '@qdrant/js-client-grpc': 1.4.0(typescript@5.1.6)
-      '@qdrant/js-client-rest': 1.4.0(typescript@5.1.6)
-      typescript: 5.1.6
+      '@qdrant/js-client-grpc': 1.4.0(typescript@5.2.2)
+      '@qdrant/js-client-rest': 1.4.0(typescript@5.2.2)
+      typescript: 5.2.2
     dev: false
 
   /@radix-ui/react-compose-refs@1.0.0(react@18.2.0):
     resolution: {integrity: sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA==}
     peerDependencies:
       react: ^16.8 || ^17.0 || ^18.0
     dependencies:
-      '@babel/runtime': 7.22.5
+      '@babel/runtime': 7.23.1
       react: 18.2.0
     dev: false
 
   /@radix-ui/react-slot@1.0.0(react@18.2.0):
     resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==}
     peerDependencies:
       react: ^16.8 || ^17.0 || ^18.0
     dependencies:
-      '@babel/runtime': 7.22.5
+      '@babel/runtime': 7.23.1
       '@radix-ui/react-compose-refs': 1.0.0(react@18.2.0)
       react: 18.2.0
     dev: false
 
   /@react-email/body@0.0.2:
@@ -4324,148 +4232,127 @@ packages:
     engines: {node: '>=16.0.0'}
     dependencies:
       react: 18.2.0
     dev: false
 
-  /@remirror/core-constants@2.0.1:
-    resolution: {integrity: sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==}
-    dependencies:
-      '@babel/runtime': 7.22.5
+  /@remirror/core-constants@2.0.2:
+    resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==}
     dev: false
 
-  /@remirror/core-helpers@2.0.3:
-    resolution: {integrity: sha512-LqIPF4stGG69l9qu/FFicv9d9B+YaItzgDMC5A0CEvDQfKkGD3BfabLmfpnuWbsc06oKGdTduilgWcALLZoYLg==}
+  /@remirror/core-helpers@3.0.0:
+    resolution: {integrity: sha512-tusEgQJIqg4qKj6HSBUFcyRnWnziw3neh4T9wOmsPGHFC3w9kl5KSrDb9UAgE8uX6y32FnS7vJ955mWOl3n50A==}
     dependencies:
-      '@babel/runtime': 7.22.5
-      '@linaria/core': 4.2.9
-      '@remirror/core-constants': 2.0.1
+      '@remirror/core-constants': 2.0.2
       '@remirror/types': 1.0.1
-      '@types/object.omit': 3.0.0
+      '@types/object.omit': 3.0.1
       '@types/object.pick': 1.3.2
       '@types/throttle-debounce': 2.1.0
       case-anything: 2.1.13
       dash-get: 1.0.2
       deepmerge: 4.3.1
       fast-deep-equal: 3.1.3
       make-error: 1.3.6
       object.omit: 3.0.0
       object.pick: 1.3.0
       throttle-debounce: 3.0.1
-    transitivePeerDependencies:
-      - supports-color
     dev: false
 
   /@remirror/types@1.0.1:
     resolution: {integrity: sha512-VlZQxwGnt1jtQ18D6JqdIF+uFZo525WEqrfp9BOc3COPpK4+AWCgdnAWL+ho6imWcoINlGjR/+3b6y5C1vBVEA==}
     dependencies:
       type-fest: 2.19.0
     dev: false
 
-  /@rollup/plugin-alias@5.0.0(rollup@3.26.2):
-    resolution: {integrity: sha512-l9hY5chSCjuFRPsnRm16twWBiSApl2uYFLsepQYwtBuAxNMQ/1dJqADld40P0Jkqm65GRTLy/AC6hnpVebtLsA==}
+  /@rollup/plugin-alias@5.0.1(rollup@3.29.4):
+    resolution: {integrity: sha512-JObvbWdOHoMy9W7SU0lvGhDtWq9PllP5mjpAy+TUslZG/WzOId9u80Hsqq1vCUn9pFJ0cxpdcnAv+QzU2zFH3Q==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
-      rollup: ^1.20.0||^2.0.0||^3.0.0
+      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
     peerDependenciesMeta:
       rollup:
         optional: true
     dependencies:
-      rollup: 3.26.2
+      rollup: 3.29.4
       slash: 4.0.0
     dev: true
 
-  /@rollup/plugin-commonjs@24.1.0(rollup@3.26.2):
+  /@rollup/plugin-commonjs@24.1.0(rollup@3.29.4):
     resolution: {integrity: sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
       rollup: ^2.68.0||^3.0.0
     peerDependenciesMeta:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       commondir: 1.0.1
       estree-walker: 2.0.2
       glob: 8.1.0
       is-reference: 1.2.1
       magic-string: 0.27.0
-      rollup: 3.26.2
+      rollup: 3.29.4
     dev: true
 
-  /@rollup/plugin-json@6.0.0(rollup@3.26.2):
-    resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==}
+  /@rollup/plugin-json@6.0.1(rollup@3.29.4):
+    resolution: {integrity: sha512-RgVfl5hWMkxN1h/uZj8FVESvPuBJ/uf6ly6GTj0GONnkfoBN5KC0MSz+PN2OLDgYXMhtG0mWpTrkiOjoxAIevw==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
-      rollup: ^1.20.0||^2.0.0||^3.0.0
+      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
     peerDependenciesMeta:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
-      rollup: 3.26.2
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
+      rollup: 3.29.4
     dev: true
 
-  /@rollup/plugin-node-resolve@15.1.0(rollup@3.26.2):
-    resolution: {integrity: sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==}
+  /@rollup/plugin-node-resolve@15.2.2(rollup@3.29.4):
+    resolution: {integrity: sha512-f64bU4OKqV0yihtxFemmuf0oj37pToCFMISCA+sJbbIAl5wcpbRO9XgWNWb1tDiWQJUcPxo6V0l59hcuZOQ3kw==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
-      rollup: ^2.78.0||^3.0.0
+      rollup: ^2.78.0||^3.0.0||^4.0.0
     peerDependenciesMeta:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       '@types/resolve': 1.20.2
       deepmerge: 4.3.1
       is-builtin-module: 3.2.1
       is-module: 1.0.0
-      resolve: 1.22.2
-      rollup: 3.26.2
+      resolve: 1.22.6
+      rollup: 3.29.4
     dev: true
 
-  /@rollup/plugin-replace@5.0.2(rollup@3.26.2):
-    resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==}
+  /@rollup/plugin-replace@5.0.3(rollup@3.29.4):
+    resolution: {integrity: sha512-je7fu05B800IrMlWjb2wzJcdXzHYW46iTipfChnBDbIbDXhASZs27W1B58T2Yf45jZtJUONegpbce+9Ut2Ti/Q==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
-      rollup: ^1.20.0||^2.0.0||^3.0.0
+      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
     peerDependenciesMeta:
       rollup:
         optional: true
     dependencies:
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       magic-string: 0.27.0
-      rollup: 3.26.2
-    dev: true
-
-  /@rollup/pluginutils@5.0.2(rollup@3.26.2):
-    resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
-    engines: {node: '>=14.0.0'}
-    peerDependencies:
-      rollup: ^1.20.0||^2.0.0||^3.0.0
-    peerDependenciesMeta:
-      rollup:
-        optional: true
-    dependencies:
-      '@types/estree': 1.0.1
-      estree-walker: 2.0.2
-      picomatch: 2.3.1
-      rollup: 3.26.2
+      rollup: 3.29.4
     dev: true
 
-  /@rollup/pluginutils@5.0.4(rollup@3.26.2):
-    resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
+  /@rollup/pluginutils@5.0.5(rollup@3.29.4):
+    resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==}
     engines: {node: '>=14.0.0'}
     peerDependencies:
-      rollup: ^1.20.0||^2.0.0||^3.0.0
+      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
     peerDependenciesMeta:
       rollup:
         optional: true
     dependencies:
-      '@types/estree': 1.0.1
+      '@types/estree': 1.0.2
       estree-walker: 2.0.2
       picomatch: 2.3.1
-      rollup: 3.26.2
+      rollup: 3.29.4
 
   /@sanity/eventsource@5.0.0:
     resolution: {integrity: sha512-0ewT+BDzfiamHwitUfRcwsl/RREHjWv6VNZvQ8Q4OnnNKXfEEGXbWmqzof0okOTkp4XELgyliht4Qj28o9AU2g==}
     dependencies:
       '@types/event-source-polyfill': 1.0.1
@@ -4536,169 +4423,169 @@ packages:
   /@smithy/abort-controller@1.1.0:
     resolution: {integrity: sha512-5imgGUlZL4dW4YWdMYAKLmal9ny/tlenM81QZY7xYyb76z9Z/QOg7oM5Ak9HQl8QfFTlGVWwcMXl+54jroRgEQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/chunked-blob-reader-native@1.1.0:
     resolution: {integrity: sha512-RCJRL4+T54deVRYxuQT4lRsVPO60mqbfm7Mc5cyo9KeKsVpHTjtSKsMDP7ancRnzh9WLb6zeUJ/KWZ7K9Pvozw==}
     dependencies:
       '@smithy/util-base64': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/chunked-blob-reader@1.1.0:
     resolution: {integrity: sha512-yU3BNPaWxWqV5z64vJ2sanu0j9BPzD1bxVm8Ab9MZ9AZc2lZQgoYOlPgKrrG2adRXpXddxFGuoJGgmNL8bIvgw==}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/config-resolver@1.1.0:
     resolution: {integrity: sha512-7WD9eZHp46BxAjNGHJLmxhhyeiNWkBdVStd7SUJPUZqQGeIO/REtIrcIfKUfdiHTQ9jyu2SYoqvzqqaFc6987w==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
       '@smithy/util-config-provider': 1.1.0
       '@smithy/util-middleware': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/credential-provider-imds@1.1.0:
     resolution: {integrity: sha512-kUMOdEu3RP6ozH0Ga8OeMP8gSkBsK1UqZZKyPLFnpZHrtZuHSSt7M7gsHYB/bYQBZAo3o7qrGmRty3BubYtYxQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/node-config-provider': 1.1.0
       '@smithy/property-provider': 1.2.0
       '@smithy/types': 1.2.0
       '@smithy/url-parser': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/eventstream-codec@1.1.0:
     resolution: {integrity: sha512-3tEbUb8t8an226jKB6V/Q2XU/J53lCwCzULuBPEaF4JjSh+FlCMp7TmogE/Aij5J9DwlsZ4VAD/IRDuQ/0ZtMw==}
     dependencies:
       '@aws-crypto/crc32': 3.0.0
       '@smithy/types': 1.2.0
       '@smithy/util-hex-encoding': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/eventstream-serde-browser@1.1.0:
     resolution: {integrity: sha512-qUov6SYlcCeubwTQgaSBuNO0J31UdwgGRSZvmHhc3CCYOywoVSsA5vahcNuhoZDzZkhWTpol3Pm7+6OUuHF0aA==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/eventstream-serde-universal': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/eventstream-serde-config-resolver@1.1.0:
     resolution: {integrity: sha512-vtPnp8FJkrNibWZCXvJN6rijTAEAzrmEKNfCUJOHAeBScY25hc6NjYlEJfdSmhW1qaA179oXeqHobcUNzvFkmw==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/eventstream-serde-node@1.1.0:
     resolution: {integrity: sha512-r8kUOPsJMolBGi/eU2gKfw5spfAhQjJXLe4bjjTzkapsqL654JZ+8G9iS1TprYUcCoCHDbwnH1of3kjrYKk7CQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/eventstream-serde-universal': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/eventstream-serde-universal@1.1.0:
     resolution: {integrity: sha512-8nQttgdbefJbLfz7Mao0FtkdRUlc92fCiHV3vClAl1N/qetm/I6Lsu5mLt9CzG7TGFkFb5t3qzAV2FaeAqF+ag==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/eventstream-codec': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/fetch-http-handler@1.1.0:
     resolution: {integrity: sha512-N22C9R44u5WGlcY+Wuv8EXmCAq62wWwriRAuoczMEwAIjPbvHSthyPSLqI4S7kAST1j6niWg8kwpeJ3ReAv3xg==}
     dependencies:
       '@smithy/protocol-http': 1.2.0
       '@smithy/querystring-builder': 1.1.0
       '@smithy/types': 1.2.0
       '@smithy/util-base64': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/hash-blob-browser@1.1.0:
     resolution: {integrity: sha512-9dt+piziVY0rZQanHav5ud2VgVHL4+RMnsT9QZolgNFZcj9io5fkK+G946gxx1gCslG+40UO0vIvoaE1OGlmNw==}
     dependencies:
       '@smithy/chunked-blob-reader': 1.1.0
       '@smithy/chunked-blob-reader-native': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/hash-node@1.1.0:
     resolution: {integrity: sha512-yiNKDGMzrQjnpnbLfkYKo+HwIxmBAsv0AI++QIJwvhfkLpUTBylelkv6oo78/YqZZS6h+bGfl0gILJsKE2wAKQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
       '@smithy/util-buffer-from': 1.1.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/hash-stream-node@1.1.0:
     resolution: {integrity: sha512-+kpru9xjxnNUvDBmbiRULWD3dV+YQLb1GtSE7rfG1WntkWUxB4mZ4VLW1qM38uMOS+LEQxGN/JP+ewfB16K4dQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/invalid-dependency@1.1.0:
     resolution: {integrity: sha512-h2rXn68ClTwzPXYzEUNkz+0B/A0Hz8YdFNTiEwlxkwzkETGKMxmsrQGFXwYm3jd736R5vkXcClXz1ddKrsaBEQ==}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/is-array-buffer@1.1.0:
     resolution: {integrity: sha512-twpQ/n+3OWZJ7Z+xu43MJErmhB/WO/mMTnqR6PwWQShvSJ/emx5d1N59LQZk6ZpTAeuRWrc+eHhkzTp9NFjNRQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/md5-js@1.1.0:
     resolution: {integrity: sha512-ftB+GrB/AgF+NlaoVMc3wlXZxsAcenrq2inrc6FfwM2tXUmU2Oc1W3qVW7rIDNqR6GmvXkAIxlnp6P2QkwlkNw==}
     dependencies:
       '@smithy/types': 1.2.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/middleware-content-length@1.1.0:
     resolution: {integrity: sha512-iNxwhZ7Xc5+LjeDElEOi/Nh8fFsc9Dw9+5w7h7/GLFIU0RgAwBJuJtcP1vNTOwzW4B3hG+gRu8sQLqA9OEaTwA==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/protocol-http': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/middleware-endpoint@1.1.0:
     resolution: {integrity: sha512-PvpazNjVpxX2ICrzoFYCpFnjB39DKCpZds8lRpAB3p6HGrx6QHBaNvOzVhJGBf0jcAbfCdc5/W0n9z8VWaSSww==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/middleware-serde': 1.1.0
       '@smithy/types': 1.2.0
       '@smithy/url-parser': 1.1.0
       '@smithy/util-middleware': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/middleware-retry@1.1.0:
     resolution: {integrity: sha512-lINKYxIvT+W20YFOtHBKeGm7npuJg0/YCoShttU7fVpsmU+a2rdb9zrJn1MHqWfUL6DhTAWGa0tH2O7l4XrDcw==}
     engines: {node: '>=14.0.0'}
@@ -4706,81 +4593,81 @@ packages:
       '@smithy/protocol-http': 1.2.0
       '@smithy/service-error-classification': 1.1.0
       '@smithy/types': 1.2.0
       '@smithy/util-middleware': 1.1.0
       '@smithy/util-retry': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
       uuid: 8.3.2
     dev: false
 
   /@smithy/middleware-serde@1.1.0:
     resolution: {integrity: sha512-RiBMxhxuO9VTjHsjJvhzViyceoLhU6gtrnJGpAXY43wE49IstXIGEQz8MT50/hOq5EumX16FCpup0r5DVyfqNQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/middleware-stack@1.1.0:
     resolution: {integrity: sha512-XynYiIvXNea2BbLcppvpNK0zu8o2woJqgnmxqYTn4FWagH/Hr2QIk8LOsUz7BIJ4tooFhmx8urHKCdlPbbPDCA==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/node-config-provider@1.1.0:
     resolution: {integrity: sha512-2G4TlzUnmTrUY26VKTonQqydwb+gtM/mcl+TqDP8CnWtJKVL8ElPpKgLGScP04bPIRY9x2/10lDdoaRXDqPuCw==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/property-provider': 1.2.0
       '@smithy/shared-ini-file-loader': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/node-http-handler@1.1.0:
     resolution: {integrity: sha512-d3kRriEgaIiGXLziAM8bjnaLn1fthCJeTLZIwEIpzQqe6yPX0a+yQoLCTyjb2fvdLwkMoG4p7THIIB5cj5lkbg==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/abort-controller': 1.1.0
       '@smithy/protocol-http': 1.2.0
       '@smithy/querystring-builder': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/property-provider@1.2.0:
     resolution: {integrity: sha512-qlJd9gT751i4T0t/hJAyNGfESfi08Fek8QiLcysoKPgR05qHhG0OYhlaCJHhpXy4ECW0lHyjvFM1smrCLIXVfw==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/protocol-http@1.2.0:
     resolution: {integrity: sha512-GfGfruksi3nXdFok5RhgtOnWe5f6BndzYfmEXISD+5gAGdayFGpjWu5pIqIweTudMtse20bGbc+7MFZXT1Tb8Q==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/querystring-builder@1.1.0:
     resolution: {integrity: sha512-gDEi4LxIGLbdfjrjiY45QNbuDmpkwh9DX4xzrR2AzjjXpxwGyfSpbJaYhXARw9p17VH0h9UewnNQXNwaQyYMDA==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
       '@smithy/util-uri-escape': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/querystring-parser@1.1.0:
     resolution: {integrity: sha512-Lm/FZu2qW3XX+kZ4WPwr+7aAeHf1Lm84UjNkKyBu16XbmEV7ukfhXni2aIwS2rcVf8Yv5E7wchGGpOFldj9V4Q==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/service-error-classification@1.1.0:
     resolution: {integrity: sha512-OCTEeJ1igatd5kFrS2VDlYbainNNpf7Lj1siFOxnRWqYOP9oNvC5HOJBd3t+Z8MbrmehBtuDJ2QqeBsfeiNkww==}
     engines: {node: '>=14.0.0'}
@@ -4789,11 +4676,11 @@ packages:
   /@smithy/shared-ini-file-loader@1.1.0:
     resolution: {integrity: sha512-S/v33zvCWzFyGZGlsEF0XsZtNNR281UhR7byk3nRfsgw5lGpg51rK/zjMgulM+h6NSuXaFILaYrw1I1v4kMcuA==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/signature-v4@1.1.0:
     resolution: {integrity: sha512-fDo3m7YqXBs7neciOePPd/X9LPm5QLlDMdIC4m1H6dgNLnXfLMFNIxEfPyohGA8VW9Wn4X8lygnPSGxDZSmp0Q==}
     engines: {node: '>=14.0.0'}
@@ -4803,82 +4690,82 @@ packages:
       '@smithy/types': 1.2.0
       '@smithy/util-hex-encoding': 1.1.0
       '@smithy/util-middleware': 1.1.0
       '@smithy/util-uri-escape': 1.1.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/smithy-client@1.1.0:
     resolution: {integrity: sha512-j32SGgVhv2G9nBTmel9u3OXux8KG20ssxuFakJrEeDug3kqbl1qrGzVLCe+Eib402UDtA0Sp1a4NZ2SEXDBxag==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/middleware-stack': 1.1.0
       '@smithy/types': 1.2.0
       '@smithy/util-stream': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/types@1.2.0:
     resolution: {integrity: sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/url-parser@1.1.0:
     resolution: {integrity: sha512-tpvi761kzboiLNGEWczuybMPCJh6WHB3cz9gWAG95mSyaKXmmX8ZcMxoV+irZfxDqLwZVJ22XTumu32S7Ow8aQ==}
     dependencies:
       '@smithy/querystring-parser': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-base64@1.1.0:
     resolution: {integrity: sha512-FpYmDmVbOXAxqvoVCwqehUN0zXS+lN8V7VS9O7I8MKeVHdSTsZzlwiMEvGoyTNOXWn8luF4CTDYgNHnZViR30g==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/util-buffer-from': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-body-length-browser@1.1.0:
     resolution: {integrity: sha512-cep3ioRxzRZ2Jbp3Kly7gy6iNVefYXiT6ETt8W01RQr3uwi1YMkrbU1p3lMR4KhX/91Nrk6UOgX1RH+oIt48RQ==}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-body-length-node@1.1.0:
     resolution: {integrity: sha512-fRHRjkUuT5em4HZoshySXmB1n3HAU7IS232s+qU4TicexhyGJpXMK/2+c56ePOIa1FOK2tV1Q3J/7Mae35QVSw==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-buffer-from@1.1.0:
     resolution: {integrity: sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/is-array-buffer': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-config-provider@1.1.0:
     resolution: {integrity: sha512-rQ47YpNmF6Is4I9GiE3T3+0xQ+r7RKRKbmHYyGSbyep/0cSf9kteKcI0ssJTvveJ1K4QvwrxXj1tEFp/G2UqxQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-defaults-mode-browser@1.1.0:
     resolution: {integrity: sha512-0bWhs1e412bfC5gwPCMe8Zbz0J8UoZ/meEQdo6MYj8Ne+c+QZ+KxVjx0a1dFYOclvM33SslL9dP0odn8kfblkg==}
     engines: {node: '>= 10.0.0'}
     dependencies:
       '@smithy/property-provider': 1.2.0
       '@smithy/types': 1.2.0
       bowser: 2.11.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-defaults-mode-node@1.1.0:
     resolution: {integrity: sha512-440e25TUH2b+TeK5CwsjYFrI9ShVOgA31CoxCKiv4ncSK4ZM68XW5opYxQmzMbRWARGEMu2XEUeBmOgMU2RLsw==}
     engines: {node: '>= 10.0.0'}
@@ -4886,33 +4773,33 @@ packages:
       '@smithy/config-resolver': 1.1.0
       '@smithy/credential-provider-imds': 1.1.0
       '@smithy/node-config-provider': 1.1.0
       '@smithy/property-provider': 1.2.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-hex-encoding@1.1.0:
     resolution: {integrity: sha512-7UtIE9eH0u41zpB60Jzr0oNCQ3hMJUabMcKRUVjmyHTXiWDE4vjSqN6qlih7rCNeKGbioS7f/y2Jgym4QZcKFg==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-middleware@1.1.0:
     resolution: {integrity: sha512-6hhckcBqVgjWAqLy2vqlPZ3rfxLDhFWEmM7oLh2POGvsi7j0tHkbN7w4DFhuBExVJAbJ/qqxqZdRY6Fu7/OezQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-retry@1.1.0:
     resolution: {integrity: sha512-ygQW5HBqYXpR3ua09UciS0sL7UGJzGiktrKkOuEJwARoUuzz40yaEGU6xd9Gs7KBmAaFC8gMfnghHtwZ2nyBCQ==}
     engines: {node: '>= 14.0.0'}
     dependencies:
       '@smithy/service-error-classification': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-stream@1.1.0:
     resolution: {integrity: sha512-w3lsdGsntaLQIrwDWJkIFKrFscgZXwU/oxsse09aSTNv5TckPhDeYea3LhsDrU5MGAG3vprhVZAKr33S45coVA==}
     engines: {node: '>=14.0.0'}
@@ -4922,173 +4809,197 @@ packages:
       '@smithy/types': 1.2.0
       '@smithy/util-base64': 1.1.0
       '@smithy/util-buffer-from': 1.1.0
       '@smithy/util-hex-encoding': 1.1.0
       '@smithy/util-utf8': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-uri-escape@1.1.0:
     resolution: {integrity: sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w==}
     engines: {node: '>=14.0.0'}
     dependencies:
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-utf8@1.1.0:
     resolution: {integrity: sha512-p/MYV+JmqmPyjdgyN2UxAeYDj9cBqCjp0C/NsTWnnjoZUVqoeZ6IrW915L9CAKWVECgv9lVQGc4u/yz26/bI1A==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/util-buffer-from': 1.1.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
   /@smithy/util-waiter@1.1.0:
     resolution: {integrity: sha512-S6FNIB3UJT+5Efd/0DeziO5Rs82QAMODHW4v2V3oNRrwaBigY/7Yx3SiLudZuF9WpVsV08Ih3BjIH34nzZiinQ==}
     engines: {node: '>=14.0.0'}
     dependencies:
       '@smithy/abort-controller': 1.1.0
       '@smithy/types': 1.2.0
-      tslib: 2.5.3
+      tslib: 2.6.2
     dev: false
 
-  /@solid-primitives/active-element@2.0.15(solid-js@1.7.8):
+  /@solid-primitives/active-element@2.0.15(solid-js@1.7.11):
     resolution: {integrity: sha512-ShHOjC59Ng6QIMvKjWs8XpIksGmP93dZC0AmagCXEbWzkqQieAaiyCkEezuXOK3tiVke0HItRByv90eBn9QPXA==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/event-listener': 2.2.13(solid-js@1.7.8)
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/event-listener': 2.3.0(solid-js@1.7.11)
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/connectivity@0.3.15(solid-js@1.7.8):
+  /@solid-primitives/connectivity@0.3.15(solid-js@1.7.11):
     resolution: {integrity: sha512-BN1Be+rYg7rtw6h2pGzwiiyE5ObrrMRzjOUOnWPujHwWRFbdsnrhfpGVvqYvmzDEVXwCfNJMyhCxHmg/h8M2cw==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/event-listener': 2.2.13(solid-js@1.7.8)
-      '@solid-primitives/rootless': 1.4.1(solid-js@1.7.8)
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/event-listener': 2.3.0(solid-js@1.7.11)
+      '@solid-primitives/rootless': 1.4.2(solid-js@1.7.11)
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/event-listener@2.2.13(solid-js@1.7.8):
-    resolution: {integrity: sha512-8GtVEq0ECZoa5Klo1jjfGPfwg0zVJ8TNnNkWu8FqRkh0CkhbhCVJAKwjleem9K/qL6zUDfJihLjhqGBTBbb+8w==}
+  /@solid-primitives/event-listener@2.3.0(solid-js@1.7.11):
+    resolution: {integrity: sha512-0DS7DQZvCExWSpurVZC9/wjI8RmkhuOtWOy6Pp1Woq9ElMT9/bfjNpkwXsOwisLpcTqh9eUs17kp7jtpWcC20w==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/media@2.2.3(solid-js@1.7.8):
+  /@solid-primitives/media@2.2.3(solid-js@1.7.11):
     resolution: {integrity: sha512-xhKaTJjH6e65OL706/hA38WWitafbJCm/Zpv7qAn4cy/cgxZ39Cl0bPdYzZhUlkJvTt8YVT0IBcOBLKlJVaPRg==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/event-listener': 2.2.13(solid-js@1.7.8)
-      '@solid-primitives/rootless': 1.4.1(solid-js@1.7.8)
-      '@solid-primitives/static-store': 0.0.4(solid-js@1.7.8)
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/event-listener': 2.3.0(solid-js@1.7.11)
+      '@solid-primitives/rootless': 1.4.2(solid-js@1.7.11)
+      '@solid-primitives/static-store': 0.0.4(solid-js@1.7.11)
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/memo@1.3.2(solid-js@1.7.8):
+  /@solid-primitives/memo@1.3.2(solid-js@1.7.11):
     resolution: {integrity: sha512-HhQ+tjX9XxGIQQhejLmJCmrIj1jTEkPbSGoIAjC2nCIU9wE0DuNpupluNuh0HL7yfldMWqwXFOWG5+OKUB29nQ==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/scheduled': 1.4.0(solid-js@1.7.8)
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/scheduled': 1.4.0(solid-js@1.7.11)
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/props@3.1.6(solid-js@1.7.8):
-    resolution: {integrity: sha512-ChtvXBDxASR+zZgH0ysoBstbVJdqJk6LITb78CScgHd+Uc8C6eaHKLmhNeuVCd36FGAuyj9vylDHe2GhmFlecA==}
+  /@solid-primitives/props@3.1.8(solid-js@1.7.11):
+    resolution: {integrity: sha512-38ERNFhl87emUDPRlYvCmlbvEcK2mOJB38SU22YS2QXFDK7TQf/7P46XZacs7oODc/fckhfZTitht71FMEDe2g==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/refs@1.0.4(solid-js@1.7.8):
-    resolution: {integrity: sha512-BxZKkct0OIyADWIoA9UITm+3G5Xb3IkOa0nZd40SgOK5DtMqpXFIEPUkJ/woPB90WqlM9UvvuiJHUyAjMeAmCw==}
+  /@solid-primitives/refs@1.0.5(solid-js@1.7.11):
+    resolution: {integrity: sha512-5hmYmYbm6rs43nMHHozyyUngGA7P7q2WtlaCLJEfmlUJf67GWI1PZmqAiol6m9F37XSMZRuvZLoQ7HA/0q3GYg==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/rootless@1.4.1(solid-js@1.7.8):
-    resolution: {integrity: sha512-h7VBUk8usD76Eh1a4wT17PcGtIRxGPlLuJ4Mf7roCNu46W5cc9DAoz8M6XebuZWVKeUkML/JuPMZQSV0mLo2Fw==}
+  /@solid-primitives/rootless@1.4.2(solid-js@1.7.11):
+    resolution: {integrity: sha512-ynI/2aEOPyc14IKCX6yDBqnsAYCoLbaP9V/jejEWMVKOT2ZdV2ZxdftaLimOpWPpvjyti5DUJIGTOfLaNb7jlg==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/scheduled@1.4.0(solid-js@1.7.8):
+  /@solid-primitives/scheduled@1.4.0(solid-js@1.7.11):
     resolution: {integrity: sha512-j4xMdsvluO8xv+M62gSUrUEKiqT0qlymM9PhXiqIzpnRNm5rrP+bHpG0BDhqkNe6fDEDb+W1L7OCmiG+qveBvQ==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      solid-js: 1.7.8
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/static-store@0.0.4(solid-js@1.7.8):
+  /@solid-primitives/static-store@0.0.4(solid-js@1.7.11):
     resolution: {integrity: sha512-NcLtDNA6H+Z9LmqaUe4SKfMx0YbszIMXEqfV15cB34t5XyEeOM5TihYwsVJ/dpkmpHYzflm0SwAL+P9uwyzvWQ==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
-      solid-js: 1.7.8
+      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/transition-group@1.0.2(solid-js@1.7.8):
-    resolution: {integrity: sha512-+o3J7TnU0/Sok+LKA0z0wvhim88dpd2eFBk8/05adE6wVypVlME8sKqTMO+xRv8HoT4Kq3sczmvwV07FKg2n+g==}
+  /@solid-primitives/transition-group@1.0.3(solid-js@1.7.11):
+    resolution: {integrity: sha512-TnFADZhx9sibdoW5gxkU1QmLabzV2H2OBKYGS2aR5IC61Q/+7v8wlxOJEevxXNbPiRo6qlE3STLU3L9XS8hDbA==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      solid-js: 1.7.8
+      solid-js: 1.7.11
     dev: false
 
-  /@solid-primitives/utils@6.2.0(solid-js@1.7.8):
-    resolution: {integrity: sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==}
+  /@solid-primitives/utils@6.2.1(solid-js@1.7.11):
+    resolution: {integrity: sha512-TsecNzxiO5bLfzqb4OOuzfUmdOROcssuGqgh5rXMMaasoFZ3GoveUgdY1wcf17frMJM7kCNGNuK34EjErneZkg==}
     peerDependencies:
       solid-js: ^1.6.12
     dependencies:
-      solid-js: 1.7.8
+      solid-js: 1.7.11
     dev: false
 
-  /@solidjs/router@0.8.2(solid-js@1.7.8):
+  /@solidjs/router@0.8.2(solid-js@1.7.11):
     resolution: {integrity: sha512-gUKW+LZqxtX6y/Aw6JKyy4gQ9E7dLqp513oB9pSYJR1HM5c56Pf7eijzyXX+b3WuXig18Cxqah4tMtF0YGu80w==}
     peerDependencies:
       solid-js: ^1.5.3
     dependencies:
-      solid-js: 1.7.8
+      solid-js: 1.7.11
+    dev: false
+
+  /@tiptap/core@2.1.11(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-1W2DdjpPwfphHgQ3Qm4s5wzCnEjiXm1TeZ+6/zBl89yKURXgv8Mw1JGdj/NcImQjtDcsNn97MscACK3GKbEJBA==}
+    peerDependencies:
+      '@tiptap/pm': ^2.0.0
+    dependencies:
+      '@tiptap/pm': 2.1.8
     dev: false
 
   /@tiptap/core@2.1.8(@tiptap/pm@2.1.8):
     resolution: {integrity: sha512-QTGgqki7hkonLJ93gWqCUkD6cCAQ3rEX9gbMLwzfnegIZ+/BKLQYKYCozsEMZnMPXgdRrKuyRBOL+RH+IolMeA==}
     peerDependencies:
       '@tiptap/pm': ^2.0.0
     dependencies:
       '@tiptap/pm': 2.1.8
     dev: false
 
+  /@tiptap/extension-blockquote@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-IEVe3goA0rgp1G8Wm733BSRJiy71Vh2fmTCyZKWmc2A6GREVSy1X3fCvAo6pMENRObhjIoaBQUCE3p4iJYOxqg==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-blockquote@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-NhTE90ZDb/BbtkgeNjwLYPYMryAfCXCM+Zpk8AMsVODZ+bDy+lsqpnDw7uRxUK3guLMnqKgSe2eTaXqx7AKE+A==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-bold@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-vhdkBtvd029ufOYt2ug49Gz+RLKSczO/CCqKYBqBmpIpsifyK7M6jkgamvAQg3c/vYk0LNcKiL2dp0Jp7L+5Gw==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-bold@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-rDdmir78a0JTiV+vrycGh3yS1ZzRF1bRvBt4jr7Rne0LOl03kc7Wm936ommiL3McWUpZZV37ZpCm5JfE8rQb+w==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5104,10 +5015,18 @@ packages:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
       tippy.js: 6.3.7
     dev: false
 
+  /@tiptap/extension-bullet-list@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-SOOVH2aSmdMtjWL7TTLbN72xbAFz2G5jifT4UCXb7Qx6LsyhNCyDCu0ukOW8rSosGoSdmBXxAsD9sBJ1jEOmZw==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-bullet-list@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-VWj3XZMwJQVb7e4ZM0N+o6o+905lyMMS4C35yw/sxN5CDw4TJpQMSPSAmBVNtK469XUdlGOxeLc/+Q00aU+S8A==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5122,32 +5041,50 @@ packages:
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
     dev: false
 
-  /@tiptap/extension-code-block-lowlight@2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.0.3)(@tiptap/pm@2.1.8):
+  /@tiptap/extension-code-block-lowlight@2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.1.11)(@tiptap/pm@2.1.8):
     resolution: {integrity: sha512-qiUIh8JRfvd2rhDKFjHCxBp+nRy3HedovQoVFX9YEnBbg6so+I1nLE2Eck4t3KhBVfVRBrxBKZPLVb83zQ0s4w==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       '@tiptap/extension-code-block': ^2.0.0
       '@tiptap/pm': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
-      '@tiptap/extension-code-block': 2.0.3(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
+      '@tiptap/extension-code-block': 2.1.11(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
+      '@tiptap/pm': 2.1.8
+    dev: false
+
+  /@tiptap/extension-code-block@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-QhmhCCWqg/5qLXpZ3sl2A0rqJqV8zMOegcxUFaqcJMOqNbsuHcRgc9C+1hWSVLbCmstB7M6sgF02QpTBOkYHxg==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+      '@tiptap/pm': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
     dev: false
 
-  /@tiptap/extension-code-block@2.0.3(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
-    resolution: {integrity: sha512-F4xMy18EwgpyY9f5Te7UuF7UwxRLptOtCq1p2c2DfxBvHDWhAjQqVqcW/sq/I/WuED7FwCnPLyyAasPiVPkLPw==}
+  /@tiptap/extension-code-block@2.1.11(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-QhmhCCWqg/5qLXpZ3sl2A0rqJqV8zMOegcxUFaqcJMOqNbsuHcRgc9C+1hWSVLbCmstB7M6sgF02QpTBOkYHxg==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       '@tiptap/pm': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
     dev: false
 
+  /@tiptap/extension-code@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-G0UEbMFunujy/F86yHN0/dumPLbwTis9C+6IQv1XRPNsV28U0MgxBhlPcJUgyO5lwuleePDxiBVcRv2XrysgKw==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-code@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-dQL8aUYzSEkES5P4sBYZ6SiCMnFK1cUKKGruaRV1TJyFu/ClZ8Y+BKS2GCCMcyH0tKjqsibYsNFBWz9/Q5gjEg==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5159,21 +5096,21 @@ packages:
     peerDependencies:
       '@tiptap/core': ^2.0.0
       y-prosemirror: 1.0.20
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
-      y-prosemirror: 1.0.20(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
+      y-prosemirror: 1.0.20(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
     dev: false
 
   /@tiptap/extension-collaboration-cursor@2.1.8(@tiptap/core@2.1.8)(y-prosemirror@1.2.1):
     resolution: {integrity: sha512-GptV9d9v7vRS/JzekraQuFwwuyYnE2fhFiewV1DHJe/wbvK99HCxFTpBHK74TfXfzhzogGjGNLeJG4YL/Npeng==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       y-prosemirror: 1.0.20
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
-      y-prosemirror: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
+      y-prosemirror: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
     dev: false
 
   /@tiptap/extension-collaboration@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(y-prosemirror@1.0.20):
     resolution: {integrity: sha512-aTx5wPg8KPxdJCuruCFzilsns1ha9Gh03WwO8k1Wj+5kV1OmoxW3VsuneLN2/0OB2eKX66xEmWJHnThF8Mk5qA==}
     peerDependencies:
@@ -5181,11 +5118,11 @@ packages:
       '@tiptap/pm': ^2.0.0
       y-prosemirror: 1.0.20
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
-      y-prosemirror: 1.0.20(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
+      y-prosemirror: 1.0.20(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
     dev: false
 
   /@tiptap/extension-collaboration@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(y-prosemirror@1.2.1):
     resolution: {integrity: sha512-aTx5wPg8KPxdJCuruCFzilsns1ha9Gh03WwO8k1Wj+5kV1OmoxW3VsuneLN2/0OB2eKX66xEmWJHnThF8Mk5qA==}
     peerDependencies:
@@ -5193,21 +5130,39 @@ packages:
       '@tiptap/pm': ^2.0.0
       y-prosemirror: 1.0.20
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
-      y-prosemirror: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
+      y-prosemirror: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
+    dev: false
+
+  /@tiptap/extension-document@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-L/iLuqxvJep33ycCFNrnUhdR0VtcZyeNnqB+ZvVHzEwLoRud+LBy44lpEdBrAFsvRm3DG14m/FGYL+TfaD0vxA==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
     dev: false
 
   /@tiptap/extension-document@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-mLPZqd5QUv3FKo+5zOaf7dGqZPci7Myr92U1Y6Vw0V+hCRC9Emm3I/xssQYGsWXmXQuyNJ5WRlpXgag3Ae+CkA==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-dropcursor@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-MiJepRpHlu93aInOMW8NeRCvm9VE5rL0MA9TONY/IspJFGFIqonc/01J6t33JQa3Xh/x3xAfis4nKa/UazeVJw==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+      '@tiptap/pm': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+      '@tiptap/pm': 2.1.8
+    dev: false
+
   /@tiptap/extension-dropcursor@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
     resolution: {integrity: sha512-KilbUHApYya2Q6brq5qW+B+pPkb6lvgnjRfuFuv6doM/v+lfEdozUE1Ma8C19UXtzl7BmPDut9HRMDL17Pqwyg==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       '@tiptap/pm': ^2.0.0
@@ -5225,54 +5180,92 @@ packages:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
       tippy.js: 6.3.7
     dev: false
 
+  /@tiptap/extension-gapcursor@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-P/xjyhSOVyop5XXbNtRPgrooQrSlpYblwR67ClI9FAC7uQliuOwi5VcndmEItjWWSe85kJa2IHjOS7mLYvJe8A==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+      '@tiptap/pm': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+      '@tiptap/pm': 2.1.8
+    dev: false
+
   /@tiptap/extension-gapcursor@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
     resolution: {integrity: sha512-0EQgV/kF2dg2dOpw0fTbwwNaubwS8QNhEPPbnXQP8xqZpupuia+DKKgC+ttzbE9XhS4Sv1fGib52Sr7MMIduhA==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       '@tiptap/pm': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
     dev: false
 
+  /@tiptap/extension-hard-break@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-qhiPe6FA0b6PPb/ITlgSnY0l9tEVmXZ9e7eSjvks12ORfqL/dofSCLtChHWvhZxugzo92xejG2hXLi6lyOLbkg==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-hard-break@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-K86FTizvZu7779Gz2XigW1IxAjZXduyZ7w0ipwe+5QBa/Lh6Vfl9wa8TgV1lFAkC2VATsAa3aa36llMIDBgeew==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
-  /@tiptap/extension-heading@2.0.3(@tiptap/core@2.1.8):
-    resolution: {integrity: sha512-f0IEv5ms6aCzL80WeZ1qLCXTkRVwbpRr1qAETjg3gG4eoJN18+lZNOJYpyZy3P92C5KwF2T3Av00eFyVLIbb8Q==}
+  /@tiptap/extension-heading@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-QBtl0S1aDFB+F1wvTrS5iGdNUEeXp+WuTddj+L2f5EP4KqG2x7sj7e7ENMy20g/l8tbKwzd3AZZydvClH4Ybbw==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
-      '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
     dev: false
 
   /@tiptap/extension-highlight@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-OCXtFWCbwsgOHq7IP4Qr02EfjwYeRRcuL1ipv0LojGtMcvnkw7OLhQZ8oocrqi4/6QCOtPLSGlcqrQ6pmN7jww==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-history@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-88dovV2O9icmBn0IvaArFFeS6X5ts6BxZPu5VbGML8KBL8iAu+Og7RXEPdOy5e13K0K4V21fDpO3n7KdvNOAYQ==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+      '@tiptap/pm': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+      '@tiptap/pm': 2.1.8
+    dev: false
+
   /@tiptap/extension-history@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
     resolution: {integrity: sha512-Cyq4YsmosfgHGlaf2wiiU8VaLweUMG8LHuhZ5A2RAoriy3G09Bqgn6eqLmho8KoU1VgvffXTVBaYKxz9gVgu3w==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       '@tiptap/pm': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
     dev: false
 
+  /@tiptap/extension-horizontal-rule@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-uvHPa2YCKnDhtSBSZB3lk5U4H3wRKP0DNvVx4Y2F7MdQianVzcyOd1pZYO9BQs+lUB1aZots6doE69Zqz3mU2Q==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+      '@tiptap/pm': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+      '@tiptap/pm': 2.1.8
+    dev: false
+
   /@tiptap/extension-horizontal-rule@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
     resolution: {integrity: sha512-qUNz8p/p3gth0ueYFkmMdVRcRVmtCwQGJsHWwbx23XrF/a7AJ0FSdiW0sk8YD6Dbw+i1cB3cnRyO+qq9XuWdqw==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
       '@tiptap/pm': ^2.0.0
@@ -5287,10 +5280,18 @@ packages:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-italic@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-QmDsHtnBBit/1KtQpBPxjSPjDC1mVKtoNTgsEwMWK6YAkCKOKPj7oPEqqjaNZIRMKPPzE5XCsfBoS3jtVmo+6A==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-italic@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-cR6kSoMraA/dCdwmus8A09WAwpxiZiGG+B0OqsludGF+MdZLilhoGyXDbTeO3aKoKccfqxZGk1YKK13C/gRM1Q==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5306,26 +5307,50 @@ packages:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
       linkifyjs: 4.1.1
     dev: false
 
+  /@tiptap/extension-list-item@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-YhwHaPGhffsFsg/zjCu1G24//j/BTRDRZbZXmMwp77m1yEqPULcWyoWrI+gUzetQxJRD/ruAucqjLtoLLfICmQ==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-list-item@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-fiYVRhHvcXMcVuuiXBx/0AFWwGoKzs9784VSuVUeSSzSuH6vOchM1kZCH+v6acs7vltFKNDrluyEiwGIz1b8qA==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-ordered-list@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-/tghfEJ5U7WFbF8xyOqRJks8KxP/lRjnroMXMglaushSMx8PYPo1dZDB/dJZw7ksy47MAaKJfKlx3gyN2CPXBQ==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-ordered-list@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-qTVSWTlSjFNRwPNmWmfe9TsW9XL3LQCNJsfaBxtVZfhDN9rhoIZ6rPTBO7f2TTiPK1+uyLTvK+znWYvU9RtD5A==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-paragraph@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-gXMgJ2CU3X4yh1wKnb8RdbDmhITB76pH6DX0uWprmEgvzNMN3Qw+h5uBD9lgxg1WVghbCmkG9mY9J4PPbPTLxw==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-paragraph@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-ZuwvwKaG5GeoYRgeh96PToLk2TjxsLiZKnLN6rkUCsW6aLoseK7/8/7vm3dP2N9dAUN35ESw0/pRk2Q/VK1/+g==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5340,10 +5365,18 @@ packages:
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
     dev: false
 
+  /@tiptap/extension-strike@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-UnjeSVgu3bDuyjjUdWsUErRCoQKAHCzH/pAiqTEPEEdFYgZFQPBpcJICRVdlYjRmI2ZKh6d0TMUS55m7ckmwmQ==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-strike@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-JGPiGudEZAKTiOirua9gtDG+HILHEx4CGODW5PDBMA1xYDfyo7ZJk5xgfJWZ1SOo7YviF26HSY4KKV9ThINq2Q==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5416,10 +5449,18 @@ packages:
       '@tiptap/core': ^2.0.0
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
     dev: false
 
+  /@tiptap/extension-text@2.1.11(@tiptap/core@2.1.11):
+    resolution: {integrity: sha512-Iey0EXYv9079+lbHMvZtLc6XcYfKrq++msEXuFFNHxvL0i/XzndhGf+qlDhLROLgEtDiiTqzOBBwFCGlFjbDow==}
+    peerDependencies:
+      '@tiptap/core': ^2.0.0
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+    dev: false
+
   /@tiptap/extension-text@2.1.8(@tiptap/core@2.1.8):
     resolution: {integrity: sha512-ha7oTtUdcJdTVLr8CrxbNMucbAmOBCi83MLxdKZclVf1VpdIVpE3NTojfH2mnZCVMvtPhj4PILQp2hGO95SFig==}
     peerDependencies:
       '@tiptap/core': ^2.0.0
     dependencies:
@@ -5454,46 +5495,44 @@ packages:
       prosemirror-dropcursor: 1.8.1
       prosemirror-gapcursor: 1.3.2
       prosemirror-history: 1.3.2
       prosemirror-inputrules: 1.2.1
       prosemirror-keymap: 1.2.2
-      prosemirror-markdown: 1.11.0
-      prosemirror-menu: 1.2.2
-      prosemirror-model: 1.19.2
+      prosemirror-markdown: 1.11.2
+      prosemirror-menu: 1.2.4
+      prosemirror-model: 1.19.3
       prosemirror-schema-basic: 1.2.2
       prosemirror-schema-list: 1.3.0
       prosemirror-state: 1.4.3
-      prosemirror-tables: 1.3.3
-      prosemirror-trailing-node: 2.0.4(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)
-      prosemirror-transform: 1.7.3
-      prosemirror-view: 1.31.4
-    transitivePeerDependencies:
-      - supports-color
-    dev: false
-
-  /@tiptap/starter-kit@2.0.3(@tiptap/pm@2.1.8):
-    resolution: {integrity: sha512-t4WG4w93zTpL2VxhVyJJvl3kdLF001ZrhpOuEiZqEMBMUMbM56Uiigv1CnUQpTFrjDAh3IM8hkqzAh20TYw2iQ==}
-    dependencies:
-      '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
-      '@tiptap/extension-blockquote': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-bold': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-bullet-list': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-code': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-code-block': 2.0.3(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
-      '@tiptap/extension-document': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-dropcursor': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
-      '@tiptap/extension-gapcursor': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
-      '@tiptap/extension-hard-break': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-heading': 2.0.3(@tiptap/core@2.1.8)
-      '@tiptap/extension-history': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
-      '@tiptap/extension-horizontal-rule': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
-      '@tiptap/extension-italic': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-list-item': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-ordered-list': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-paragraph': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-strike': 2.1.8(@tiptap/core@2.1.8)
-      '@tiptap/extension-text': 2.1.8(@tiptap/core@2.1.8)
+      prosemirror-tables: 1.3.4
+      prosemirror-trailing-node: 2.0.7(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)
+      prosemirror-transform: 1.8.0
+      prosemirror-view: 1.32.0
+    dev: false
+
+  /@tiptap/starter-kit@2.1.11(@tiptap/pm@2.1.8):
+    resolution: {integrity: sha512-kZXwuo9yxrs1ASxluRKjXThjdcy90d7owJxnJWD7SyEwXaXYc4h+Ar1M9rP3jieCDBuRTtCgvAOKbVbhnRJ2jg==}
+    dependencies:
+      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
+      '@tiptap/extension-blockquote': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-bold': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-bullet-list': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-code': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-code-block': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
+      '@tiptap/extension-document': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-dropcursor': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
+      '@tiptap/extension-gapcursor': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
+      '@tiptap/extension-hard-break': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-heading': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-history': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
+      '@tiptap/extension-horizontal-rule': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
+      '@tiptap/extension-italic': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-list-item': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-ordered-list': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-paragraph': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-strike': 2.1.11(@tiptap/core@2.1.11)
+      '@tiptap/extension-text': 2.1.11(@tiptap/core@2.1.11)
     transitivePeerDependencies:
       - '@tiptap/pm'
     dev: false
 
   /@tiptap/suggestion@2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
@@ -5520,330 +5559,364 @@ packages:
 
   /@trpc/server@10.35.0:
     resolution: {integrity: sha512-UntbE9gG+kB2nEwuJ0hw7AmQuRWw67voKaVBPBA7Ow6+aGZc00gva7015Ey5BT7Qf1wq7xJMLUdgw4QiVU+VpQ==}
     dev: false
 
-  /@types/aws-lambda@8.10.119:
-    resolution: {integrity: sha512-Vqm22aZrCvCd6I5g1SvpW151jfqwTzEZ7XJ3yZ6xaZG31nUEOEyzzVImjRcsN8Wi/QyPxId/x8GTtgIbsy8kEw==}
+  /@trysound/sax@0.2.0:
+    resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
+    engines: {node: '>=10.13.0'}
+    dev: false
+
+  /@types/acorn@4.0.6:
+    resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
+    dependencies:
+      '@types/estree': 1.0.2
+    dev: false
+
+  /@types/aws-lambda@8.10.124:
+    resolution: {integrity: sha512-PHqK0SuAkFS3tZjceqRXecxxrWIN3VqTicuialtK2wZmvBy7H9WGc3u3+wOgaZB7N8SpSXDpWk9qa7eorpTStg==}
     dev: false
 
-  /@types/babel__core@7.20.1:
-    resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==}
+  /@types/babel__core@7.20.2:
+    resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==}
     dependencies:
-      '@babel/parser': 7.22.16
-      '@babel/types': 7.22.15
-      '@types/babel__generator': 7.6.4
-      '@types/babel__template': 7.4.1
-      '@types/babel__traverse': 7.20.1
+      '@babel/parser': 7.23.0
+      '@babel/types': 7.23.0
+      '@types/babel__generator': 7.6.5
+      '@types/babel__template': 7.4.2
+      '@types/babel__traverse': 7.20.2
 
-  /@types/babel__generator@7.6.4:
-    resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==}
+  /@types/babel__generator@7.6.5:
+    resolution: {integrity: sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
-  /@types/babel__template@7.4.1:
-    resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==}
+  /@types/babel__template@7.4.2:
+    resolution: {integrity: sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==}
     dependencies:
-      '@babel/parser': 7.22.5
-      '@babel/types': 7.22.15
+      '@babel/parser': 7.23.0
+      '@babel/types': 7.23.0
 
-  /@types/babel__traverse@7.20.1:
-    resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==}
+  /@types/babel__traverse@7.20.2:
+    resolution: {integrity: sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==}
     dependencies:
-      '@babel/types': 7.22.15
+      '@babel/types': 7.23.0
 
   /@types/btoa-lite@1.0.0:
     resolution: {integrity: sha512-wJsiX1tosQ+J5+bY5LrSahHxr2wT+uME5UDwdN1kg4frt40euqA+wzECkmq4t5QbveHiJepfdThgQrPw6KiSlg==}
     dev: false
 
-  /@types/debug@4.1.8:
-    resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
+  /@types/debug@4.1.9:
+    resolution: {integrity: sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==}
     dependencies:
-      '@types/ms': 0.7.31
+      '@types/ms': 0.7.32
 
-  /@types/dom-view-transitions@1.0.1:
-    resolution: {integrity: sha512-A9S1ijj/4MX06I1W/6on8lhaYyq1Ir7gaOvfllW1o4RzVWW88HAeqX0pUx9VgOLnNpdiGeUW2CTkg18p5LWIrA==}
+  /@types/dom-view-transitions@1.0.2:
+    resolution: {integrity: sha512-+ctRyzGMOZB5AbvhpTv37OWkP9N3Xxfac7bhS7AcuRMmO03SHxm5/5kWCPtcatx2gW+NhFMdl7l1DqJvvPVtwg==}
 
   /@types/dompurify@3.0.2:
     resolution: {integrity: sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==}
     dependencies:
-      '@types/trusted-types': 2.0.3
+      '@types/trusted-types': 2.0.4
     dev: false
 
   /@types/eslint-visitor-keys@1.0.0:
     resolution: {integrity: sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==}
     dev: true
 
-  /@types/estree@1.0.1:
-    resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
+  /@types/estree-jsx@1.0.1:
+    resolution: {integrity: sha512-sHyakZlAezNFxmYRo0fopDZW+XvK6ipeZkkp5EAOLjdPfZp8VjZBJ67vSRI99RSCAoqXVmXOHS4fnWoxpuGQtQ==}
+    dependencies:
+      '@types/estree': 1.0.2
+    dev: false
+
+  /@types/estree@1.0.2:
+    resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==}
 
   /@types/event-source-polyfill@1.0.1:
     resolution: {integrity: sha512-dls8b0lUgJ/miRApF0efboQ9QZnAm7ofTO6P1ILu8bRPxUFKDxVwFf8+TeuuErmNui6blpltyr7+eV72dbQXlQ==}
     dev: false
 
   /@types/eventsource@1.1.11:
     resolution: {integrity: sha512-L7wLDZlWm5mROzv87W0ofIYeQP5K2UhoFnnUyEWLKM6UBb0ZNRgAqp98qE5DkgfBXdWfc2kYmw9KZm4NLjRbsw==}
     dev: false
 
-  /@types/hast@2.3.4:
-    resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==}
+  /@types/hast@2.3.6:
+    resolution: {integrity: sha512-47rJE80oqPmFdVDCD7IheXBrVdwuBgsYwoczFvKmwfo2Mzsnt+V9OONsYauFmICb6lQPpCuXYJWejBNs4pDJRg==}
+    dependencies:
+      '@types/unist': 2.0.8
+
+  /@types/hast@3.0.1:
+    resolution: {integrity: sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 3.0.0
+    dev: false
 
   /@types/html-to-text@9.0.1:
     resolution: {integrity: sha512-sHu702QGb0SP2F0Zt+CxdCmGZIZ0gEaaCjqOh/V4iba1wTxPVntEPOM/vHm5bel08TILhB3+OxUTkDJWnr/zHQ==}
     dev: false
 
-  /@types/json-schema@7.0.12:
-    resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
+  /@types/js-yaml@4.0.6:
+    resolution: {integrity: sha512-ACTuifTSIIbyksx2HTon3aFtCKWcID7/h3XEmRpDYdMCXxPbl+m9GteOJeaAkiAta/NJaSFuA7ahZ0NkwajDSw==}
+    dev: false
+
+  /@types/json-schema@7.0.13:
+    resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==}
     dev: true
 
   /@types/json5@0.0.29:
     resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
     dev: true
 
   /@types/json5@0.0.30:
     resolution: {integrity: sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA==}
 
-  /@types/jsonwebtoken@9.0.2:
-    resolution: {integrity: sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==}
+  /@types/jsonwebtoken@9.0.3:
+    resolution: {integrity: sha512-b0jGiOgHtZ2jqdPgPnP6WLCXZk1T8p06A/vPGzUvxpFGgKMbjXJDjC5m52ErqBnIuWZFgGoIJyRdeG5AyreJjA==}
     dependencies:
       '@types/node': 20.4.5
     dev: false
 
   /@types/marked@5.0.1:
     resolution: {integrity: sha512-Y3pAUzHKh605fN6fvASsz5FDSWbZcs/65Q6xYRmnIP9ZIYz27T4IOmXfH9gWJV1dpi7f1e7z7nBGUTx/a0ptpA==}
     dev: false
 
-  /@types/mdast@3.0.11:
-    resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
+  /@types/mdast@3.0.13:
+    resolution: {integrity: sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
 
-  /@types/mdast@4.0.0:
-    resolution: {integrity: sha512-YLeG8CujC9adtj/kuDzq1N4tCDYKoZ5l/bnjq8d74+t/3q/tHquJOJKUQXJrLCflOHpKjXgcI/a929gpmLOEng==}
+  /@types/mdast@4.0.1:
+    resolution: {integrity: sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==}
     dependencies:
       '@types/unist': 3.0.0
 
+  /@types/mdx@2.0.8:
+    resolution: {integrity: sha512-r7/zWe+f9x+zjXqGxf821qz++ld8tp6Z4jUS6qmPZUXH6tfh4riXOhAqb12tWGWAevCFtMt1goLWkQMqIJKpsA==}
+    dev: false
+
   /@types/mime-types@2.1.1:
     resolution: {integrity: sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==}
     dev: false
 
-  /@types/ms@0.7.31:
-    resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
+  /@types/ms@0.7.32:
+    resolution: {integrity: sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==}
 
-  /@types/nlcst@1.0.0:
-    resolution: {integrity: sha512-3TGCfOcy8R8mMQ4CNSNOe3PG66HttvjcLzCoOpvXvDtfWOTi+uT/rxeOKm/qEwbM4SNe1O/PjdiBK2YcTjU4OQ==}
+  /@types/nlcst@1.0.2:
+    resolution: {integrity: sha512-ykxL/GDDUhqikjU0LIywZvEwb1NTYXTEWf+XgMSS2o6IXIakafPccxZmxgZcvJPZ3yFl2kdL1gJZz3U3iZF3QA==}
     dependencies:
-      '@types/unist': 3.0.0
+      '@types/unist': 2.0.8
 
-  /@types/node-fetch@2.6.4:
-    resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==}
+  /@types/node-fetch@2.6.6:
+    resolution: {integrity: sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==}
     dependencies:
       '@types/node': 20.4.5
-      form-data: 3.0.1
+      form-data: 4.0.0
     dev: false
 
   /@types/node@12.20.55:
     resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
     dev: false
 
   /@types/node@17.0.45:
     resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==}
     dev: false
 
-  /@types/node@18.17.5:
-    resolution: {integrity: sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==}
+  /@types/node@18.18.4:
+    resolution: {integrity: sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ==}
     dev: false
 
   /@types/node@20.4.4:
     resolution: {integrity: sha512-CukZhumInROvLq3+b5gLev+vgpsIqC2D0deQr/yS1WnxvmYLlJXZpaQrQiseMY+6xusl79E04UjWoqyr+t1/Ew==}
-    dev: true
 
   /@types/node@20.4.5:
     resolution: {integrity: sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==}
 
   /@types/nodemailer@6.4.9:
     resolution: {integrity: sha512-XYG8Gv+sHjaOtUpiuytahMy2mM3rectgroNbs6R3djZEKmPNiIJwe9KqOJBGzKKnNZNKvnuvmugBgpq3w/S0ig==}
     dependencies:
       '@types/node': 20.4.5
     dev: false
 
-  /@types/normalize-package-data@2.4.1:
-    resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
+  /@types/normalize-package-data@2.4.2:
+    resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==}
 
-  /@types/object.omit@3.0.0:
-    resolution: {integrity: sha512-I27IoPpH250TUzc9FzXd0P1BV/BMJuzqD3jOz98ehf9dQqGkxlq+hO1bIqZGWqCg5bVOy0g4AUVJtnxe0klDmw==}
+  /@types/object.omit@3.0.1:
+    resolution: {integrity: sha512-24XD34UeRWw505TsMNBrQ4bES2s8IxiFC59mmNUFhTz9IX2hAtA7gQ8wVww1i17QmhBYILg5iqYP2y7aqA3pwQ==}
     dev: false
 
   /@types/object.pick@1.3.2:
     resolution: {integrity: sha512-sn7L+qQ6RLPdXRoiaE7bZ/Ek+o4uICma/lBFPyJEKDTPTBP1W8u0c4baj3EiS4DiqLs+Hk+KUGvMVJtAw3ePJg==}
     dev: false
 
   /@types/parse5@6.0.3:
     resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
 
-  /@types/prop-types@15.7.5:
-    resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
+  /@types/prop-types@15.7.8:
+    resolution: {integrity: sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==}
     dev: false
 
   /@types/react@18.2.21:
     resolution: {integrity: sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==}
     dependencies:
-      '@types/prop-types': 15.7.5
-      '@types/scheduler': 0.16.3
+      '@types/prop-types': 15.7.8
+      '@types/scheduler': 0.16.4
       csstype: 3.1.2
     dev: false
 
   /@types/resolve@1.20.2:
     resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
+    dev: true
 
-  /@types/sax@1.2.4:
-    resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==}
+  /@types/resolve@1.20.3:
+    resolution: {integrity: sha512-NH5oErHOtHZYcjCtg69t26aXEk4BN2zLWqf7wnDZ+dpe0iR7Rds1SPGEItl3fca21oOe0n3OCnZ4W7jBxu7FOw==}
+
+  /@types/sax@1.2.5:
+    resolution: {integrity: sha512-9jWta97bBVC027/MShr3gLab8gPhKy4l6qpb+UJLF5pDm3501NvA7uvqVCW+REFtx00oTi6Cq9JzLwgq6evVgw==}
     dependencies:
       '@types/node': 20.4.5
     dev: false
 
-  /@types/scheduler@0.16.3:
-    resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
+  /@types/scheduler@0.16.4:
+    resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==}
     dev: false
 
-  /@types/semver@7.5.0:
-    resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
+  /@types/semver@7.5.3:
+    resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==}
     dev: true
 
   /@types/sortablejs@1.15.1:
     resolution: {integrity: sha512-g/JwBNToh6oCTAwNS8UGVmjO7NLDKsejVhvE4x1eWiPTC3uCuNsa/TD4ssvX3du+MLiM+SHPNDuijp8y76JzLQ==}
     dev: false
 
   /@types/throttle-debounce@2.1.0:
     resolution: {integrity: sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==}
     dev: false
 
-  /@types/trusted-types@2.0.3:
-    resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
+  /@types/trusted-types@2.0.4:
+    resolution: {integrity: sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==}
     dev: false
 
-  /@types/unist@2.0.6:
-    resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
+  /@types/unist@2.0.8:
+    resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==}
 
   /@types/unist@3.0.0:
     resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==}
 
-  /@types/webidl-conversions@7.0.0:
-    resolution: {integrity: sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==}
+  /@types/webidl-conversions@7.0.1:
+    resolution: {integrity: sha512-8hKOnOan+Uu+NgMaCouhg3cT9x5fFZ92Jwf+uDLXLu/MFRbXxlWwGeQY7KVHkeSft6RvY+tdxklUBuyY9eIEKg==}
     dev: false
 
   /@types/whatwg-url@8.2.2:
     resolution: {integrity: sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==}
     dependencies:
       '@types/node': 20.4.5
-      '@types/webidl-conversions': 7.0.0
+      '@types/webidl-conversions': 7.0.1
     dev: false
 
   /@types/ws@8.5.5:
     resolution: {integrity: sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==}
     dependencies:
       '@types/node': 20.4.5
     dev: false
 
-  /@types/yargs-parser@21.0.0:
-    resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==}
+  /@types/yargs-parser@21.0.1:
+    resolution: {integrity: sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==}
 
-  /@typescript-eslint/eslint-plugin@3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/eslint-plugin@3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
       '@typescript-eslint/parser': ^3.0.0
       eslint: ^5.0.0 || ^6.0.0 || ^7.0.0
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
-      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
+      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
       debug: 4.3.4
       eslint: 8.45.0
       functional-red-black-tree: 1.0.1
       regexpp: 3.2.0
       semver: 7.5.4
-      tsutils: 3.21.0(typescript@5.1.6)
-      typescript: 5.1.6
+      tsutils: 3.21.0(typescript@5.2.2)
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/eslint-plugin@6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/eslint-plugin@6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-rClGrMuyS/3j0ETa1Ui7s6GkLhfZGKZL3ZrChLeAiACBE/tRc1wq8SNZESUuluxhLj9FkUefRs2l6bCIArWBiQ==}
     engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
       '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
       eslint: ^7.0.0 || ^8.0.0
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@eslint-community/regexpp': 4.6.1
-      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
+      '@eslint-community/regexpp': 4.9.1
+      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
       '@typescript-eslint/scope-manager': 6.2.0
-      '@typescript-eslint/type-utils': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
-      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/type-utils': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
+      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
       '@typescript-eslint/visitor-keys': 6.2.0
       debug: 4.3.4
       eslint: 8.45.0
       graphemer: 1.4.0
       ignore: 5.2.4
       natural-compare: 1.4.0
       natural-compare-lite: 1.4.0
       semver: 7.5.4
-      ts-api-utils: 1.0.1(typescript@5.1.6)
-      typescript: 5.1.6
+      ts-api-utils: 1.0.3(typescript@5.2.2)
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/experimental-utils@3.10.1(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/experimental-utils@3.10.1(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
       eslint: '*'
     dependencies:
-      '@types/json-schema': 7.0.12
+      '@types/json-schema': 7.0.13
       '@typescript-eslint/types': 3.10.1
-      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.1.6)
+      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.2.2)
       eslint: 8.45.0
       eslint-scope: 5.1.1
       eslint-utils: 2.1.0
     transitivePeerDependencies:
       - supports-color
       - typescript
     dev: true
 
-  /@typescript-eslint/parser@3.10.1(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/parser@3.10.1(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
       eslint: ^5.0.0 || ^6.0.0 || ^7.0.0
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
       '@types/eslint-visitor-keys': 1.0.0
-      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
       '@typescript-eslint/types': 3.10.1
-      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.1.6)
+      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.2.2)
       eslint: 8.45.0
       eslint-visitor-keys: 1.3.0
-      typescript: 5.1.6
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/parser@6.2.0(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/parser@6.2.0(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==}
     engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
       eslint: ^7.0.0 || ^8.0.0
       typescript: '*'
@@ -5851,71 +5924,71 @@ packages:
       typescript:
         optional: true
     dependencies:
       '@typescript-eslint/scope-manager': 6.2.0
       '@typescript-eslint/types': 6.2.0
-      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6)
+      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.2.2)
       '@typescript-eslint/visitor-keys': 6.2.0
       debug: 4.3.4
       eslint: 8.45.0
-      typescript: 5.1.6
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/scope-manager@5.59.11:
-    resolution: {integrity: sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==}
+  /@typescript-eslint/scope-manager@5.62.0:
+    resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dependencies:
-      '@typescript-eslint/types': 5.59.11
-      '@typescript-eslint/visitor-keys': 5.59.11
+      '@typescript-eslint/types': 5.62.0
+      '@typescript-eslint/visitor-keys': 5.62.0
     dev: true
 
   /@typescript-eslint/scope-manager@6.2.0:
     resolution: {integrity: sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==}
     engines: {node: ^16.0.0 || >=18.0.0}
     dependencies:
       '@typescript-eslint/types': 6.2.0
       '@typescript-eslint/visitor-keys': 6.2.0
     dev: true
 
-  /@typescript-eslint/type-utils@6.2.0(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/type-utils@6.2.0(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-DnGZuNU2JN3AYwddYIqrVkYW0uUQdv0AY+kz2M25euVNlujcN2u+rJgfJsBFlUEzBB6OQkUqSZPyuTLf2bP5mw==}
     engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
       eslint: ^7.0.0 || ^8.0.0
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6)
-      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.2.2)
+      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
       debug: 4.3.4
       eslint: 8.45.0
-      ts-api-utils: 1.0.1(typescript@5.1.6)
-      typescript: 5.1.6
+      ts-api-utils: 1.0.3(typescript@5.2.2)
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
   /@typescript-eslint/types@3.10.1:
     resolution: {integrity: sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==}
     engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
     dev: true
 
-  /@typescript-eslint/types@5.59.11:
-    resolution: {integrity: sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==}
+  /@typescript-eslint/types@5.62.0:
+    resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dev: true
 
   /@typescript-eslint/types@6.2.0:
     resolution: {integrity: sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==}
     engines: {node: ^16.0.0 || >=18.0.0}
     dev: true
 
-  /@typescript-eslint/typescript-estree@3.10.1(typescript@5.1.6):
+  /@typescript-eslint/typescript-estree@3.10.1(typescript@5.2.2):
     resolution: {integrity: sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==}
     engines: {node: ^10.12.0 || >=12.0.0}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
@@ -5927,38 +6000,38 @@ packages:
       debug: 4.3.4
       glob: 7.2.3
       is-glob: 4.0.3
       lodash: 4.17.21
       semver: 7.5.4
-      tsutils: 3.21.0(typescript@5.1.6)
-      typescript: 5.1.6
+      tsutils: 3.21.0(typescript@5.2.2)
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/typescript-estree@5.59.11(typescript@5.1.6):
-    resolution: {integrity: sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA==}
+  /@typescript-eslint/typescript-estree@5.62.0(typescript@5.2.2):
+    resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@typescript-eslint/types': 5.59.11
-      '@typescript-eslint/visitor-keys': 5.59.11
+      '@typescript-eslint/types': 5.62.0
+      '@typescript-eslint/visitor-keys': 5.62.0
       debug: 4.3.4
       globby: 11.1.0
       is-glob: 4.0.3
       semver: 7.5.4
-      tsutils: 3.21.0(typescript@5.1.6)
-      typescript: 5.1.6
+      tsutils: 3.21.0(typescript@5.2.2)
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/typescript-estree@6.2.0(typescript@5.1.6):
+  /@typescript-eslint/typescript-estree@6.2.0(typescript@5.2.2):
     resolution: {integrity: sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==}
     engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
@@ -5969,48 +6042,48 @@ packages:
       '@typescript-eslint/visitor-keys': 6.2.0
       debug: 4.3.4
       globby: 11.1.0
       is-glob: 4.0.3
       semver: 7.5.4
-      ts-api-utils: 1.0.1(typescript@5.1.6)
-      typescript: 5.1.6
+      ts-api-utils: 1.0.3(typescript@5.2.2)
+      typescript: 5.2.2
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@typescript-eslint/utils@5.59.11(eslint@8.45.0)(typescript@5.1.6):
-    resolution: {integrity: sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg==}
+  /@typescript-eslint/utils@5.62.0(eslint@8.45.0)(typescript@5.2.2):
+    resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     peerDependencies:
       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
     dependencies:
       '@eslint-community/eslint-utils': 4.4.0(eslint@8.45.0)
-      '@types/json-schema': 7.0.12
-      '@types/semver': 7.5.0
-      '@typescript-eslint/scope-manager': 5.59.11
-      '@typescript-eslint/types': 5.59.11
-      '@typescript-eslint/typescript-estree': 5.59.11(typescript@5.1.6)
+      '@types/json-schema': 7.0.13
+      '@types/semver': 7.5.3
+      '@typescript-eslint/scope-manager': 5.62.0
+      '@typescript-eslint/types': 5.62.0
+      '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2)
       eslint: 8.45.0
       eslint-scope: 5.1.1
       semver: 7.5.4
     transitivePeerDependencies:
       - supports-color
       - typescript
     dev: true
 
-  /@typescript-eslint/utils@6.2.0(eslint@8.45.0)(typescript@5.1.6):
+  /@typescript-eslint/utils@6.2.0(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-RCFrC1lXiX1qEZN8LmLrxYRhOkElEsPKTVSNout8DMzf8PeWoQG7Rxz2SadpJa3VSh5oYKGwt7j7X/VRg+Y3OQ==}
     engines: {node: ^16.0.0 || >=18.0.0}
     peerDependencies:
       eslint: ^7.0.0 || ^8.0.0
     dependencies:
       '@eslint-community/eslint-utils': 4.4.0(eslint@8.45.0)
-      '@types/json-schema': 7.0.12
-      '@types/semver': 7.5.0
+      '@types/json-schema': 7.0.13
+      '@types/semver': 7.5.3
       '@typescript-eslint/scope-manager': 6.2.0
       '@typescript-eslint/types': 6.2.0
-      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6)
+      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.2.2)
       eslint: 8.45.0
       semver: 7.5.4
     transitivePeerDependencies:
       - supports-color
       - typescript
@@ -6021,41 +6094,29 @@ packages:
     engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
     dependencies:
       eslint-visitor-keys: 1.3.0
     dev: true
 
-  /@typescript-eslint/visitor-keys@5.59.11:
-    resolution: {integrity: sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==}
+  /@typescript-eslint/visitor-keys@5.62.0:
+    resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dependencies:
-      '@typescript-eslint/types': 5.59.11
-      eslint-visitor-keys: 3.4.1
+      '@typescript-eslint/types': 5.62.0
+      eslint-visitor-keys: 3.4.3
     dev: true
 
   /@typescript-eslint/visitor-keys@6.2.0:
     resolution: {integrity: sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==}
     engines: {node: ^16.0.0 || >=18.0.0}
     dependencies:
       '@typescript-eslint/types': 6.2.0
-      eslint-visitor-keys: 3.4.1
+      eslint-visitor-keys: 3.4.3
     dev: true
 
-  /@unocss/astro@0.55.7(vite@4.4.7):
-    resolution: {integrity: sha512-mw8r14ArxUQBVCCisAJlF/WsZb650iBsduD/lXMk56N/nQ3MMArCcn62kcAxgZSb5tfIOQGQu/tbR8hEcD8y2g==}
-    peerDependencies:
-      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
-    peerDependenciesMeta:
-      vite:
-        optional: true
-    dependencies:
-      '@unocss/core': 0.55.7
-      '@unocss/reset': 0.55.7
-      '@unocss/vite': 0.55.7(vite@4.4.7)
-      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
-    transitivePeerDependencies:
-      - rollup
-    dev: true
+  /@ungap/structured-clone@1.2.0:
+    resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+    dev: false
 
   /@unocss/astro@0.55.7(vite@4.4.9):
     resolution: {integrity: sha512-mw8r14ArxUQBVCCisAJlF/WsZb650iBsduD/lXMk56N/nQ3MMArCcn62kcAxgZSb5tfIOQGQu/tbR8hEcD8y2g==}
     peerDependencies:
       vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
@@ -6064,42 +6125,41 @@ packages:
         optional: true
     dependencies:
       '@unocss/core': 0.55.7
       '@unocss/reset': 0.55.7
       '@unocss/vite': 0.55.7(vite@4.4.9)
-      vite: 4.4.9(sass@1.64.1)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
     transitivePeerDependencies:
       - rollup
-    dev: false
 
   /@unocss/cli@0.55.7:
     resolution: {integrity: sha512-ZHX2SR2WQbKfcmgOOHjBLB3V57Ct76Zb76YULzBj2EVX43lX/YDCVG87n6ePDY7rOcjCAthjrFQYCLV5KVLKHg==}
     engines: {node: '>=14'}
     hasBin: true
     dependencies:
       '@ampproject/remapping': 2.2.1
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       '@unocss/config': 0.55.7
       '@unocss/core': 0.55.7
       '@unocss/preset-uno': 0.55.7
       cac: 6.7.14
       chokidar: 3.5.3
       colorette: 2.0.20
       consola: 3.2.3
       fast-glob: 3.3.1
-      magic-string: 0.30.3
+      magic-string: 0.30.4
       pathe: 1.1.1
       perfect-debounce: 1.0.0
     transitivePeerDependencies:
       - rollup
 
   /@unocss/config@0.55.7:
     resolution: {integrity: sha512-+X6rPScyFEWbkZyCyM+HfoJhJNN+CEl2n2izWkm0kuDj3w9fY9B3f/0dsk+jmx/gJEI5Y797q9zspNMNDib1AA==}
     engines: {node: '>=14'}
     dependencies:
       '@unocss/core': 0.55.7
-      unconfig: 0.3.10
+      unconfig: 0.3.11
 
   /@unocss/core@0.55.7:
     resolution: {integrity: sha512-c+bWe844Xjlwc1EPwHj0+n3LpntJG7ELPbEOOxNIG+CQdcEX0l1G0rkM8+nKstJ9WJmgpf1HdJQLVMF62HXvhw==}
 
   /@unocss/extractor-arbitrary-variants@0.55.7:
@@ -6111,32 +6171,32 @@ packages:
     resolution: {integrity: sha512-N0mjZozDDyqx8Mh6C/ZlMTlDzGiq22sXY/hPRX55Cf44WZI4W/ZWajqAAp42B+lw2MN0k1FYEMIAwn9n+xgq/g==}
     dependencies:
       gzip-size: 6.0.0
       sirv: 2.0.3
 
-  /@unocss/postcss@0.55.7(postcss@8.4.29):
+  /@unocss/postcss@0.55.7(postcss@8.4.31):
     resolution: {integrity: sha512-53Z/yv/CNdlTqKZQ9gpYRoLZSuzQ28J0SDrGCdzwjLcvHG/FD7/x1S7yxE7cUp/4sjvLL15HSzkWq8vNy6SkwQ==}
     engines: {node: '>=14'}
     peerDependencies:
       postcss: ^8.4.21
     dependencies:
       '@unocss/config': 0.55.7
       '@unocss/core': 0.55.7
       css-tree: 2.3.1
       fast-glob: 3.3.1
-      magic-string: 0.30.3
-      postcss: 8.4.29
+      magic-string: 0.30.4
+      postcss: 8.4.31
 
   /@unocss/preset-attributify@0.55.7:
     resolution: {integrity: sha512-L1sNw3DyM4mymIm4DBTTTOllk8LmhYlWMgDlaAW2MYWygjqDCsp99wRKT2175Ya5xHYBA6XetMoBryZD23qJYQ==}
     dependencies:
       '@unocss/core': 0.55.7
 
   /@unocss/preset-icons@0.55.7:
     resolution: {integrity: sha512-JXLOHkyEKKAjLTqjAxYfhwln05WXilGg3jctkZWKpMNawPaonrGt3kZT12YMuMmOryxk7UcyKB0dtYc+p3QYvw==}
     dependencies:
-      '@iconify/utils': 2.1.9
+      '@iconify/utils': 2.1.11
       '@unocss/core': 0.55.7
       ofetch: 1.3.3
     transitivePeerDependencies:
       - supports-color
 
@@ -6206,76 +6266,55 @@ packages:
   /@unocss/transformer-variant-group@0.55.7:
     resolution: {integrity: sha512-uLyZ08XXVriUDenZCTGA3xGgMD3B9GVr6mSz002pDlLpQDi8FcMQTOGg8X4ViCGzS3l03S/+r+JY7kJTpMFa9w==}
     dependencies:
       '@unocss/core': 0.55.7
 
-  /@unocss/vite@0.55.7(vite@4.4.7):
+  /@unocss/vite@0.55.7(vite@4.4.9):
     resolution: {integrity: sha512-xmdyDnt9Ag4o7DGl22/P6MaB+HSjWOQw9qYYzIefSv3SVUvn3cEhIX/PCWqFp8Kts2HyvAoJLbZmygSf1XdZNQ==}
     peerDependencies:
       vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
     dependencies:
       '@ampproject/remapping': 2.2.1
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       '@unocss/config': 0.55.7
       '@unocss/core': 0.55.7
       '@unocss/inspector': 0.55.7
       '@unocss/scope': 0.55.7
       '@unocss/transformer-directives': 0.55.7
       chokidar: 3.5.3
       fast-glob: 3.3.1
-      magic-string: 0.30.3
-      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
+      magic-string: 0.30.4
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
     transitivePeerDependencies:
       - rollup
-    dev: true
 
-  /@unocss/vite@0.55.7(vite@4.4.9):
-    resolution: {integrity: sha512-xmdyDnt9Ag4o7DGl22/P6MaB+HSjWOQw9qYYzIefSv3SVUvn3cEhIX/PCWqFp8Kts2HyvAoJLbZmygSf1XdZNQ==}
+  /@vrite/tiptap-solid@1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.11):
+    resolution: {integrity: sha512-eSv3kr8VAjyZ8aVEfhzIGe/LLDAcdBS0GEcWr+Eaab3tM6N11PIhI/1vlufU02uAF0JFY4yx/NA1jvGLU8jEWw==}
     peerDependencies:
-      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
-    dependencies:
-      '@ampproject/remapping': 2.2.1
-      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
-      '@unocss/config': 0.55.7
-      '@unocss/core': 0.55.7
-      '@unocss/inspector': 0.55.7
-      '@unocss/scope': 0.55.7
-      '@unocss/transformer-directives': 0.55.7
-      chokidar: 3.5.3
-      fast-glob: 3.3.1
-      magic-string: 0.30.3
-      vite: 4.4.9(sass@1.64.1)
-    transitivePeerDependencies:
-      - rollup
-    dev: false
-
-  /@vrite/tiptap-solid@1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.8):
-    resolution: {integrity: sha512-eSv3kr8VAjyZ8aVEfhzIGe/LLDAcdBS0GEcWr+Eaab3tM6N11PIhI/1vlufU02uAF0JFY4yx/NA1jvGLU8jEWw==}
-    peerDependencies:
-      '@tiptap/core': 2.1.8
-      '@tiptap/pm': 2.1.8
-      solid-js: ^1.7.11
+      '@tiptap/core': 2.1.8
+      '@tiptap/pm': 2.1.8
+      solid-js: ^1.7.11
     dependencies:
       '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
       '@tiptap/extension-bubble-menu': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
       '@tiptap/extension-floating-menu': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
       '@tiptap/pm': 2.1.8
       nanoid: 4.0.2
-      solid-js: 1.7.8
+      solid-js: 1.7.11
     dev: false
 
-  /@vscode/emmet-helper@2.8.9:
-    resolution: {integrity: sha512-ygpVStaePHt9aI9zk4NNJWI/NsRaeDSW1vQsZVmtpVRVCOdwYlsc3BfB/eppUu1OucT0x3OHDAzKcxnitjcSXQ==}
+  /@vscode/emmet-helper@2.9.2:
+    resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==}
     dependencies:
-      emmet: 2.4.4
+      emmet: 2.4.6
       jsonc-parser: 2.3.1
-      vscode-languageserver-textdocument: 1.0.8
-      vscode-languageserver-types: 3.17.3
+      vscode-languageserver-textdocument: 1.0.11
+      vscode-languageserver-types: 3.17.5
       vscode-uri: 2.1.2
 
-  /@vscode/l10n@0.0.14:
-    resolution: {integrity: sha512-/yrv59IEnmh655z1oeDnGcvMYwnEzNzHLgeYcQCkhYX0xBvYWrAuefoiLcPBUkMpJsb46bqQ6Yv4pwTTQ4d3Qg==}
+  /@vscode/l10n@0.0.16:
+    resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==}
 
   /abbrev@1.1.1:
     resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
     dev: false
 
@@ -6302,11 +6341,10 @@ packages:
     resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
     peerDependencies:
       acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
     dependencies:
       acorn: 8.10.0
-    dev: true
 
   /acorn-node@1.8.2:
     resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==}
     dependencies:
       acorn: 7.4.1
@@ -6385,12 +6423,12 @@ packages:
 
   /ansi-regex@6.0.1:
     resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
     engines: {node: '>=12'}
 
-  /ansi-sequence-parser@1.1.0:
-    resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==}
+  /ansi-sequence-parser@1.1.1:
+    resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==}
 
   /ansi-styles@3.2.1:
     resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
     engines: {node: '>=4'}
     dependencies:
@@ -6434,17 +6472,17 @@ packages:
     dependencies:
       call-bind: 1.0.2
       is-array-buffer: 3.0.2
     dev: true
 
-  /array-includes@3.1.6:
-    resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==}
+  /array-includes@3.1.7:
+    resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
       get-intrinsic: 1.2.1
       is-string: 1.0.7
     dev: true
 
   /array-iterate@2.0.1:
@@ -6452,39 +6490,76 @@ packages:
 
   /array-union@2.1.0:
     resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
     engines: {node: '>=8'}
 
-  /array.prototype.flat@1.3.1:
-    resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==}
+  /array.prototype.flat@1.3.2:
+    resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
       es-shim-unscopables: 1.0.0
     dev: true
 
-  /array.prototype.flatmap@1.3.1:
-    resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==}
+  /array.prototype.flatmap@1.3.2:
+    resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
       es-shim-unscopables: 1.0.0
     dev: true
 
+  /arraybuffer.prototype.slice@1.0.2:
+    resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      array-buffer-byte-length: 1.0.0
+      call-bind: 1.0.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
+      get-intrinsic: 1.2.1
+      is-array-buffer: 3.0.2
+      is-shared-array-buffer: 1.0.2
+    dev: true
+
   /asn1.js@5.4.1:
     resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==}
     dependencies:
       bn.js: 4.12.0
       inherits: 2.0.4
       minimalistic-assert: 1.0.1
       safer-buffer: 2.1.2
     dev: false
 
+  /astring@1.8.6:
+    resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
+    hasBin: true
+    dev: false
+
+  /astro-auto-import@0.3.1(astro@3.1.0):
+    resolution: {integrity: sha512-4kXZMlZFiq3dqT6fcfPbCjHTABQ279eKbIqZAb6qktBhGlmHwpHr1spOUFj/RQFilaWVgfjzOBmuZnoydZb5Vg==}
+    engines: {node: '>=16.0.0'}
+    peerDependencies:
+      astro: ^2.0.0 || ^3.0.0-beta
+    dependencies:
+      '@types/node': 18.18.4
+      acorn: 8.10.0
+      astro: 3.1.0(sass@1.64.1)
+    dev: false
+
+  /astro-icon@0.8.1:
+    resolution: {integrity: sha512-APk+fbFnoyGdIVSPFrdrOW9YBK96/1fYuVe7ULTGW92+z00RKB8GfLJiUvzNVXUAX2rZJCFmruGVF4rrhcTYsg==}
+    dependencies:
+      node-fetch: 3.3.2
+      resolve-pkg: 2.0.0
+      svgo: 2.8.0
+    dev: false
+
   /astro-robots-txt@0.4.1:
     resolution: {integrity: sha512-YujWFocCHcOA+sDlaiqVsUH7eeHDOn9WrtsyT7KPW3JOHn1dZB1KwoshsPGTJiZ0PeeAqPcHOz+M9xjzc/tjsQ==}
     dependencies:
       '@proload/core': 0.3.3
       '@proload/plugin-tsm': 0.2.1(@proload/core@0.3.3)
@@ -6495,11 +6570,11 @@ packages:
 
   /astro-robots-txt@1.0.0:
     resolution: {integrity: sha512-6JQSLid4gMhoWjOm85UHLkgrw0+hHIjnJVIUqxjU2D6feKlVyYukMNYjH44ZDZBK1P8hNxd33PgWlHzCASvedA==}
     dependencies:
       valid-filename: 4.0.0
-      zod: 3.22.2
+      zod: 3.22.4
     dev: true
 
   /astro@2.10.15:
     resolution: {integrity: sha512-7jgkCZexxOX541g2kKHGOcDDUVKYc+sGi87GtLOkbWwTsKqEIp9GU0o7DpKe1rhItm9VVEiHz4uxvMh3wGmJdA==}
     engines: {node: '>=16.12.0', npm: '>=6.14.0'}
@@ -6514,40 +6589,40 @@ packages:
       '@astrojs/internal-helpers': 0.1.2
       '@astrojs/language-server': 1.0.8
       '@astrojs/markdown-remark': 2.2.1(astro@2.10.15)
       '@astrojs/telemetry': 2.1.1
       '@astrojs/webapi': 2.2.0
-      '@babel/core': 7.22.15
-      '@babel/generator': 7.22.15
-      '@babel/parser': 7.22.16
-      '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.15)
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-      '@types/babel__core': 7.20.1
-      '@types/dom-view-transitions': 1.0.1
-      '@types/yargs-parser': 21.0.0
+      '@babel/core': 7.23.0
+      '@babel/generator': 7.23.0
+      '@babel/parser': 7.23.0
+      '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.0)
+      '@babel/traverse': 7.23.0
+      '@babel/types': 7.23.0
+      '@types/babel__core': 7.20.2
+      '@types/dom-view-transitions': 1.0.2
+      '@types/yargs-parser': 21.0.1
       acorn: 8.10.0
       boxen: 6.2.1
       chokidar: 3.5.3
-      ci-info: 3.8.0
+      ci-info: 3.9.0
       common-ancestor-path: 1.0.1
       cookie: 0.5.0
       debug: 4.3.4
       devalue: 4.3.2
       diff: 5.1.0
-      es-module-lexer: 1.3.0
+      es-module-lexer: 1.3.1
       esbuild: 0.17.19
       estree-walker: 3.0.0
       execa: 6.1.0
       fast-glob: 3.3.1
       github-slugger: 2.0.0
       gray-matter: 4.0.3
       html-escaper: 3.0.3
       http-cache-semantics: 4.1.1
       js-yaml: 4.1.0
       kleur: 4.1.5
-      magic-string: 0.30.3
+      magic-string: 0.30.4
       mime: 3.0.0
       network-information-types: 0.1.1(typescript@5.2.2)
       ora: 6.3.1
       p-limit: 4.0.0
       path-to-regexp: 6.2.1
@@ -6561,162 +6636,82 @@ packages:
       strip-ansi: 7.1.0
       tsconfig-resolver: 3.0.1
       typescript: 5.2.2
       unist-util-visit: 4.1.2
       vfile: 5.3.7
-      vite: 4.4.9(sass@1.64.1)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
       vitefu: 0.2.4(vite@4.4.9)
       which-pm: 2.1.1
       yargs-parser: 21.1.1
-      zod: 3.22.2
-    transitivePeerDependencies:
-      - '@types/node'
-      - less
-      - lightningcss
-      - sass
-      - stylus
-      - sugarss
-      - supports-color
-      - terser
-    dev: false
-
-  /astro@2.9.2:
-    resolution: {integrity: sha512-ejdGM9SbK58AvJS8lbkre/d5CoW8JftqaRxc9rGqzpiZQ8iU8gfdFmi3Hzkcvd2HrGvYYsJku88pM6tkBPniJQ==}
-    engines: {node: '>=16.12.0', npm: '>=6.14.0'}
-    hasBin: true
-    peerDependencies:
-      sharp: '>=0.31.0'
-    peerDependenciesMeta:
-      sharp:
-        optional: true
-    dependencies:
-      '@astrojs/compiler': 1.6.2
-      '@astrojs/internal-helpers': 0.1.1
-      '@astrojs/language-server': 1.0.8
-      '@astrojs/markdown-remark': 2.2.1(astro@2.9.2)
-      '@astrojs/telemetry': 2.1.1
-      '@astrojs/webapi': 2.2.0
-      '@babel/core': 7.22.5
-      '@babel/generator': 7.22.5
-      '@babel/parser': 7.22.5
-      '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.5)
-      '@babel/traverse': 7.22.5
-      '@babel/types': 7.22.5
-      '@types/babel__core': 7.20.1
-      '@types/dom-view-transitions': 1.0.1
-      '@types/yargs-parser': 21.0.0
-      acorn: 8.10.0
-      boxen: 6.2.1
-      chokidar: 3.5.3
-      ci-info: 3.8.0
-      common-ancestor-path: 1.0.1
-      cookie: 0.5.0
-      debug: 4.3.4
-      deepmerge-ts: 4.3.0
-      devalue: 4.3.2
-      diff: 5.1.0
-      es-module-lexer: 1.3.0
-      esbuild: 0.17.19
-      estree-walker: 3.0.0
-      execa: 6.1.0
-      fast-glob: 3.3.1
-      github-slugger: 2.0.0
-      gray-matter: 4.0.3
-      html-escaper: 3.0.3
-      js-yaml: 4.1.0
-      kleur: 4.1.5
-      magic-string: 0.27.0
-      mime: 3.0.0
-      network-information-types: 0.1.1(typescript@5.2.2)
-      ora: 6.3.1
-      p-limit: 4.0.0
-      path-to-regexp: 6.2.1
-      preferred-pm: 3.0.3
-      prompts: 2.4.2
-      rehype: 12.0.1
-      semver: 7.5.4
-      server-destroy: 1.0.1
-      shiki: 0.14.4
-      string-width: 5.1.2
-      strip-ansi: 7.1.0
-      tsconfig-resolver: 3.0.1
-      typescript: 5.2.2
-      unist-util-visit: 4.1.2
-      vfile: 5.3.7
-      vite: 4.4.9(sass@1.64.1)
-      vitefu: 0.2.4(vite@4.4.9)
-      which-pm: 2.0.0
-      yargs-parser: 21.1.1
       zod: 3.21.4
     transitivePeerDependencies:
       - '@types/node'
       - less
       - lightningcss
       - sass
       - stylus
       - sugarss
       - supports-color
       - terser
-    dev: true
 
   /astro@3.1.0(sass@1.64.1):
     resolution: {integrity: sha512-hVPZg9uDafqJbDwOwtcujwhJ6Qp3BCaIj1cvablTYI0jdYrZSvcybhIMTf8NhzK5smvZy2Bv9eEDYXLpiLDrRQ==}
     engines: {node: '>=18.14.1', npm: '>=6.14.0'}
     hasBin: true
     dependencies:
-      '@astrojs/compiler': 2.1.0
+      '@astrojs/compiler': 2.2.0
       '@astrojs/internal-helpers': 0.2.0
       '@astrojs/markdown-remark': 3.2.0(astro@3.1.0)
       '@astrojs/telemetry': 3.0.1
-      '@babel/core': 7.22.15
-      '@babel/generator': 7.22.15
-      '@babel/parser': 7.22.16
-      '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.15)
-      '@babel/traverse': 7.22.15
-      '@babel/types': 7.22.15
-      '@types/babel__core': 7.20.1
+      '@babel/core': 7.23.0
+      '@babel/generator': 7.23.0
+      '@babel/parser': 7.23.0
+      '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.0)
+      '@babel/traverse': 7.23.0
+      '@babel/types': 7.23.0
+      '@types/babel__core': 7.20.2
       acorn: 8.10.0
       boxen: 7.1.1
       chokidar: 3.5.3
-      ci-info: 3.8.0
+      ci-info: 3.9.0
       clsx: 2.0.0
       common-ancestor-path: 1.0.1
       cookie: 0.5.0
       debug: 4.3.4
       devalue: 4.3.2
       diff: 5.1.0
-      es-module-lexer: 1.3.0
-      esbuild: 0.19.3
+      es-module-lexer: 1.3.1
+      esbuild: 0.19.4
       estree-walker: 3.0.3
       execa: 8.0.1
       fast-glob: 3.3.1
       github-slugger: 2.0.0
       gray-matter: 4.0.3
       html-escaper: 3.0.3
       http-cache-semantics: 4.1.1
       js-yaml: 4.1.0
       kleur: 4.1.5
-      magic-string: 0.30.3
+      magic-string: 0.30.4
       mime: 3.0.0
       ora: 7.0.1
       p-limit: 4.0.0
       path-to-regexp: 6.2.1
       preferred-pm: 3.1.2
       probe-image-size: 7.2.3
       prompts: 2.4.2
       rehype: 12.0.1
-      resolve: 1.22.4
+      resolve: 1.22.6
       semver: 7.5.4
       server-destroy: 1.0.1
       shiki: 0.14.4
       string-width: 6.1.0
       strip-ansi: 7.1.0
       tsconfig-resolver: 3.0.1
-      undici: 5.23.0
+      undici: 5.25.4
       unist-util-visit: 4.1.2
       vfile: 5.3.7
-      vite: 4.4.9(sass@1.64.1)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
       vitefu: 0.2.4(vite@4.4.9)
       which-pm: 2.1.1
       yargs-parser: 21.1.1
       zod: 3.21.1
     optionalDependencies:
@@ -6760,79 +6755,47 @@ packages:
     dev: false
 
   /axios@0.26.1:
     resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
     dependencies:
-      follow-redirects: 1.15.2
+      follow-redirects: 1.15.3
     transitivePeerDependencies:
       - debug
     dev: false
 
   /axios@1.4.0:
     resolution: {integrity: sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==}
     dependencies:
-      follow-redirects: 1.15.2
+      follow-redirects: 1.15.3
       form-data: 4.0.0
       proxy-from-env: 1.1.0
     transitivePeerDependencies:
       - debug
     dev: false
 
   /b4a@1.6.4:
     resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==}
 
-  /babel-merge@3.0.0(@babel/core@7.22.15):
-    resolution: {integrity: sha512-eBOBtHnzt9xvnjpYNI5HmaPp/b2vMveE5XggzqHnQeHJ8mFIBrBv6WZEVIj5jJ2uwTItkqKo9gWzEEcBxEq0yw==}
-    peerDependencies:
-      '@babel/core': ^7.0.0
-    dependencies:
-      '@babel/core': 7.22.15
-      deepmerge: 2.2.1
-      object.omit: 3.0.0
-    dev: false
-
-  /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.22.15):
-    resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==}
-    peerDependencies:
-      '@babel/core': ^7.20.12
-    dependencies:
-      '@babel/core': 7.22.15
-      '@babel/helper-module-imports': 7.18.6
-      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.15)
-      '@babel/types': 7.22.15
-      html-entities: 2.3.3
-      validate-html-nesting: 1.2.2
-    dev: false
-
-  /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.22.5):
-    resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==}
+  /babel-plugin-jsx-dom-expressions@0.36.18(@babel/core@7.23.0):
+    resolution: {integrity: sha512-8K0CHgzNMB0+1OC+GQf1O49Nc6DfHAoWDjY4YTW3W/3il5KrDKAj65723oPmya68kKKOkqDKuz+Zh1u7VFHthw==}
     peerDependencies:
       '@babel/core': ^7.20.12
     dependencies:
-      '@babel/core': 7.22.5
+      '@babel/core': 7.23.0
       '@babel/helper-module-imports': 7.18.6
-      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5)
-      '@babel/types': 7.22.15
+      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0)
+      '@babel/types': 7.23.0
       html-entities: 2.3.3
       validate-html-nesting: 1.2.2
 
-  /babel-preset-solid@1.7.4(@babel/core@7.22.5):
-    resolution: {integrity: sha512-0mbHNYkbOVYhH6L95VlHVkBEVQjOXSzUqLDiFxUcsg/tU4yTM/qx7FI8C+kmos9LHckQBSm3wtwoe1BZLNJR1w==}
-    peerDependencies:
-      '@babel/core': ^7.0.0
-    dependencies:
-      '@babel/core': 7.22.5
-      babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.22.5)
-
-  /babel-preset-solid@1.7.7(@babel/core@7.22.15):
-    resolution: {integrity: sha512-tdxVzx3kgcIjNXAOmGRbzIhFBPeJjSakiN9yM+IYdL/+LtXNnbGqb0Va5tJb8Sjbk+QVEriovCyuzB5T7jeTvg==}
+  /babel-preset-solid@1.7.12(@babel/core@7.23.0):
+    resolution: {integrity: sha512-vNZn34Dv6IsWK/F59HhZlN8gP0ihZfkhPp8Lx/nxlY+rKtSZEAmmYlXWtds6EDKSiXoj2TEHuCcuqp6cO7oLSg==}
     peerDependencies:
       '@babel/core': ^7.0.0
     dependencies:
-      '@babel/core': 7.22.15
-      babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.22.15)
-    dev: false
+      '@babel/core': 7.23.0
+      babel-plugin-jsx-dom-expressions: 0.36.18(@babel/core@7.23.0)
 
   /bail@2.0.2:
     resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
 
   /balanced-match@1.0.2:
@@ -6949,22 +6912,22 @@ packages:
     resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
     engines: {node: '>=8'}
     dependencies:
       fill-range: 7.0.1
 
-  /browserslist@4.21.10:
-    resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==}
+  /browserslist@4.22.1:
+    resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==}
     engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
     hasBin: true
     dependencies:
-      caniuse-lite: 1.0.30001528
-      electron-to-chromium: 1.4.510
+      caniuse-lite: 1.0.30001546
+      electron-to-chromium: 1.4.544
       node-releases: 2.0.13
-      update-browserslist-db: 1.0.11(browserslist@4.21.10)
+      update-browserslist-db: 1.0.13(browserslist@4.22.1)
 
-  /bson@5.4.0:
-    resolution: {integrity: sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==}
+  /bson@5.5.0:
+    resolution: {integrity: sha512-B+QB4YmDx9RStKv8LLSl/aVIEV3nYJc3cJNNTK2Cd1TL+7P+cNpw9mAPeCgc5K+j01Dv6sxUzcITXDx7ZU3F0w==}
     engines: {node: '>=14.20.1'}
     dev: false
 
   /btoa-lite@1.0.0:
     resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==}
@@ -6974,11 +6937,10 @@ packages:
     resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
     dev: false
 
   /buffer-from@1.1.2:
     resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
-    dev: true
 
   /buffer-indexof-polyfill@1.0.2:
     resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==}
     engines: {node: '>=0.10'}
     dev: false
@@ -7009,16 +6971,10 @@ packages:
     resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==}
     engines: {node: '>=12'}
     dependencies:
       run-applescript: 5.0.0
 
-  /busboy@1.6.0:
-    resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
-    engines: {node: '>=10.16.0'}
-    dependencies:
-      streamsearch: 1.1.0
-
   /bytes@3.1.2:
     resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
     engines: {node: '>= 0.8'}
     dev: false
 
@@ -7048,12 +7004,12 @@ packages:
 
   /camelcase@7.0.1:
     resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
     engines: {node: '>=14.16'}
 
-  /caniuse-lite@1.0.30001528:
-    resolution: {integrity: sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==}
+  /caniuse-lite@1.0.30001546:
+    resolution: {integrity: sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==}
 
   /case-anything@2.1.13:
     resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==}
     engines: {node: '>=12.13'}
     dev: false
@@ -7093,10 +7049,14 @@ packages:
     resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
 
   /character-entities@2.0.2:
     resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
 
+  /character-reference-invalid@2.0.1:
+    resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+    dev: false
+
   /chardet@1.6.0:
     resolution: {integrity: sha512-+QOTw3otC4+FxdjK9RopGpNOglADbr4WPFi0SonkO99JbpkTPbMxmdm4NenhF5Zs+4gPXLI1+y2uazws5TMe8w==}
     dev: false
 
   /charenc@0.0.2:
@@ -7137,23 +7097,29 @@ packages:
       is-binary-path: 2.1.0
       is-glob: 4.0.3
       normalize-path: 3.0.0
       readdirp: 3.6.0
     optionalDependencies:
-      fsevents: 2.3.2
+      fsevents: 2.3.3
 
   /chownr@1.1.4:
     resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
 
   /ci-info@2.0.0:
     resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==}
     dev: true
 
-  /ci-info@3.8.0:
-    resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==}
+  /ci-info@3.9.0:
+    resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
     engines: {node: '>=8'}
 
+  /citty@0.1.4:
+    resolution: {integrity: sha512-Q3bK1huLxzQrvj7hImJ7Z1vKYJRPQCDnd0EjXfHMidcjecGOMuLrmuQmtWmFkuKLcMThlGh1yCKG8IEc6VeNXQ==}
+    dependencies:
+      consola: 3.2.3
+    dev: true
+
   /clean-regexp@1.0.0:
     resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==}
     engines: {node: '>=4'}
     dependencies:
       escape-string-regexp: 1.0.5
@@ -7179,12 +7145,12 @@ packages:
     resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     dependencies:
       restore-cursor: 4.0.0
 
-  /cli-spinners@2.9.0:
-    resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==}
+  /cli-spinners@2.9.1:
+    resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==}
     engines: {node: '>=6'}
 
   /clone@1.0.4:
     resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
     engines: {node: '>=0.8'}
@@ -7265,17 +7231,21 @@ packages:
     engines: {node: '>=16'}
     dev: false
 
   /commander@2.20.3:
     resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
-    dev: true
 
   /commander@5.1.0:
     resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
     engines: {node: '>= 6'}
     dev: false
 
+  /commander@7.2.0:
+    resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+    engines: {node: '>= 10'}
+    dev: false
+
   /commander@9.4.1:
     resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==}
     engines: {node: ^12.20.0 || >=14}
     dev: false
 
@@ -7319,12 +7289,12 @@ packages:
     engines: {node: '>= 0.6'}
     dependencies:
       safe-buffer: 5.2.1
     dev: false
 
-  /convert-source-map@1.9.0:
-    resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
+  /convert-source-map@2.0.0:
+    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
 
   /cookie-es@1.0.0:
     resolution: {integrity: sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ==}
     dev: false
 
@@ -7341,11 +7311,11 @@ packages:
     dev: false
 
   /cross-fetch@3.1.8:
     resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==}
     dependencies:
-      node-fetch: 2.6.12
+      node-fetch: 2.7.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
   /cross-spawn@7.0.3:
@@ -7358,20 +7328,38 @@ packages:
 
   /crypt@0.0.2:
     resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==}
     dev: false
 
+  /css-select@4.3.0:
+    resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
+    dependencies:
+      boolbase: 1.0.0
+      css-what: 6.1.0
+      domhandler: 4.3.1
+      domutils: 2.8.0
+      nth-check: 2.1.1
+    dev: false
+
   /css-select@5.1.0:
     resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
     dependencies:
       boolbase: 1.0.0
       css-what: 6.1.0
       domhandler: 5.0.3
       domutils: 3.1.0
       nth-check: 2.1.1
     dev: false
 
+  /css-tree@1.1.3:
+    resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
+    engines: {node: '>=8.0.0'}
+    dependencies:
+      mdn-data: 2.0.14
+      source-map: 0.6.1
+    dev: false
+
   /css-tree@2.3.1:
     resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==}
     engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
     dependencies:
       mdn-data: 2.0.30
@@ -7386,10 +7374,17 @@ packages:
     resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
     engines: {node: '>=4'}
     hasBin: true
     dev: false
 
+  /csso@4.2.0:
+    resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==}
+    engines: {node: '>=8.0.0'}
+    dependencies:
+      css-tree: 1.1.3
+    dev: false
+
   /csstype@3.1.2:
     resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
 
   /curl-string@3.1.0:
     resolution: {integrity: sha512-lWmmmDIinB03onXTDOZ2DB+v6a6YK4gL+pVaXDC0FfPnfQJaZAt7CpF5Kb0HLv5wHmkoeYB8qfJEUOzbz0s39Q==}
@@ -7400,15 +7395,20 @@ packages:
 
   /dash-get@1.0.2:
     resolution: {integrity: sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ==}
     dev: false
 
+  /data-uri-to-buffer@4.0.1:
+    resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+    engines: {node: '>= 12'}
+    dev: false
+
   /date-fns@2.30.0:
     resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==}
     engines: {node: '>=0.11'}
     dependencies:
-      '@babel/runtime': 7.22.5
+      '@babel/runtime': 7.23.1
     dev: false
 
   /dayjs@1.11.9:
     resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==}
     dev: false
@@ -7461,20 +7461,10 @@ packages:
 
   /deep-is@0.1.4:
     resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
     dev: true
 
-  /deepmerge-ts@4.3.0:
-    resolution: {integrity: sha512-if3ZYdkD2dClhnXR5reKtG98cwyaRT1NeugQoAPTTfsOpV9kqyeiBF9Qa5RHjemb3KzD5ulqygv6ED3t5j9eJw==}
-    engines: {node: '>=12.4.0'}
-    dev: true
-
-  /deepmerge@2.2.1:
-    resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==}
-    engines: {node: '>=0.10.0'}
-    dev: false
-
   /deepmerge@4.3.1:
     resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
     engines: {node: '>=0.10.0'}
 
   /default-browser-id@3.0.0:
@@ -7488,26 +7478,36 @@ packages:
     resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==}
     engines: {node: '>=14.16'}
     dependencies:
       bundle-name: 3.0.0
       default-browser-id: 3.0.0
-      execa: 7.1.1
+      execa: 7.2.0
       titleize: 3.0.0
 
   /defaults@1.0.4:
     resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
     dependencies:
       clone: 1.0.4
 
+  /define-data-property@1.1.0:
+    resolution: {integrity: sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      get-intrinsic: 1.2.1
+      gopd: 1.0.1
+      has-property-descriptors: 1.0.0
+    dev: true
+
   /define-lazy-prop@3.0.0:
     resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
     engines: {node: '>=12'}
 
-  /define-properties@1.2.0:
-    resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==}
+  /define-properties@1.2.1:
+    resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
     engines: {node: '>= 0.4'}
     dependencies:
+      define-data-property: 1.1.0
       has-property-descriptors: 1.0.0
       object-keys: 1.1.1
     dev: true
 
   /defined@1.0.1:
@@ -7547,14 +7547,10 @@ packages:
 
   /dequal@2.0.3:
     resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
     engines: {node: '>=6'}
 
-  /destr@2.0.0:
-    resolution: {integrity: sha512-FJ9RDpf3GicEBvzI3jxc2XhHzbqD8p4ANw/1kPsFBfTvP1b7Gn/Lg1vO7R9J4IVgoMbyUmFrFGZafJ1hPZpvlg==}
-    dev: false
-
   /destr@2.0.1:
     resolution: {integrity: sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA==}
 
   /destroy@1.2.0:
     resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
@@ -7583,10 +7579,16 @@ packages:
     dev: false
 
   /devalue@4.3.2:
     resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
 
+  /devlop@1.1.0:
+    resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+    dependencies:
+      dequal: 2.0.3
+    dev: false
+
   /didyoumean@1.2.2:
     resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
     dev: false
 
   /diff@5.1.0:
@@ -7621,10 +7623,18 @@ packages:
     engines: {node: '>=6.0.0'}
     dependencies:
       esutils: 2.0.3
     dev: true
 
+  /dom-serializer@1.4.1:
+    resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
+    dependencies:
+      domelementtype: 2.3.0
+      domhandler: 4.3.1
+      entities: 2.2.0
+    dev: false
+
   /dom-serializer@2.0.0:
     resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
     dependencies:
       domelementtype: 2.3.0
       domhandler: 5.0.3
@@ -7633,10 +7643,17 @@ packages:
 
   /domelementtype@2.3.0:
     resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
     dev: false
 
+  /domhandler@4.3.1:
+    resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
+    engines: {node: '>= 4'}
+    dependencies:
+      domelementtype: 2.3.0
+    dev: false
+
   /domhandler@5.0.3:
     resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
     engines: {node: '>= 4'}
     dependencies:
       domelementtype: 2.3.0
@@ -7644,10 +7661,18 @@ packages:
 
   /dompurify@3.0.5:
     resolution: {integrity: sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A==}
     dev: false
 
+  /domutils@2.8.0:
+    resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
+    dependencies:
+      dom-serializer: 1.4.1
+      domelementtype: 2.3.0
+      domhandler: 4.3.1
+    dev: false
+
   /domutils@3.1.0:
     resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
     dependencies:
       dom-serializer: 2.0.0
       domelementtype: 2.3.0
@@ -7657,11 +7682,11 @@ packages:
   /dotenv-cli@7.2.1:
     resolution: {integrity: sha512-ODHbGTskqRtXAzZapDPvgNuDVQApu4oKX8lZW7Y0+9hKA6le1ZJlyRS687oU9FXjOVEDU/VFV6zI125HzhM1UQ==}
     hasBin: true
     dependencies:
       cross-spawn: 7.0.3
-      dotenv: 16.1.4
+      dotenv: 16.3.1
       dotenv-expand: 10.0.0
       minimist: 1.2.8
     dev: false
 
   /dotenv-expand@10.0.0:
@@ -7672,12 +7697,12 @@ packages:
   /dotenv-expand@9.0.0:
     resolution: {integrity: sha512-uW8Hrhp5ammm9x7kBLR6jDfujgaDarNA02tprvZdyrJ7MpdzD1KyrIHG4l+YoC2fJ2UcdFdNWNWIjt+sexBHJw==}
     engines: {node: '>=12'}
     dev: false
 
-  /dotenv@16.1.4:
-    resolution: {integrity: sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==}
+  /dotenv@16.3.1:
+    resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
     engines: {node: '>=12'}
     dev: false
 
   /dset@3.1.2:
     resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==}
@@ -7714,15 +7739,15 @@ packages:
 
   /ee-first@1.1.1:
     resolution: {integrity: sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=}
     dev: true
 
-  /electron-to-chromium@1.4.510:
-    resolution: {integrity: sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g==}
+  /electron-to-chromium@1.4.544:
+    resolution: {integrity: sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==}
 
-  /emmet@2.4.4:
-    resolution: {integrity: sha512-v8Mwpjym55CS3EjJgiCLWUB3J2HSR93jhzXW325720u8KvYxdI2voYLstW3pHBxFz54H6jFjayR9G4LfTG0q+g==}
+  /emmet@2.4.6:
+    resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==}
     dependencies:
       '@emmetio/abbreviation': 2.3.3
       '@emmetio/css-abbreviation': 2.1.8
 
   /emoji-regex@10.2.1:
@@ -7742,10 +7767,14 @@ packages:
   /end-of-stream@1.4.4:
     resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
     dependencies:
       once: 1.4.0
 
+  /entities@2.2.0:
+    resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+    dev: false
+
   /entities@3.0.1:
     resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
     engines: {node: '>=0.12'}
     dev: false
 
@@ -7756,75 +7785,80 @@ packages:
 
   /env-schema@5.2.0:
     resolution: {integrity: sha512-36/6cZ+zIbcPA2ANrzp7vTz2bS8/zdZaq2RPFqJVtCGJ4P55EakgJ1BeKP8RMvEmM7ndrnHdJXzL3J1dHrEm1w==}
     dependencies:
       ajv: 8.12.0
-      dotenv: 16.1.4
+      dotenv: 16.3.1
       dotenv-expand: 9.0.0
     dev: false
 
   /error-ex@1.3.2:
     resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
     dependencies:
       is-arrayish: 0.2.1
 
-  /es-abstract@1.21.2:
-    resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==}
+  /es-abstract@1.22.2:
+    resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==}
     engines: {node: '>= 0.4'}
     dependencies:
       array-buffer-byte-length: 1.0.0
+      arraybuffer.prototype.slice: 1.0.2
       available-typed-arrays: 1.0.5
       call-bind: 1.0.2
       es-set-tostringtag: 2.0.1
       es-to-primitive: 1.2.1
-      function.prototype.name: 1.1.5
+      function.prototype.name: 1.1.6
       get-intrinsic: 1.2.1
       get-symbol-description: 1.0.0
       globalthis: 1.0.3
       gopd: 1.0.1
-      has: 1.0.3
+      has: 1.0.4
       has-property-descriptors: 1.0.0
       has-proto: 1.0.1
       has-symbols: 1.0.3
       internal-slot: 1.0.5
       is-array-buffer: 3.0.2
       is-callable: 1.2.7
       is-negative-zero: 2.0.2
       is-regex: 1.1.4
       is-shared-array-buffer: 1.0.2
       is-string: 1.0.7
-      is-typed-array: 1.1.10
+      is-typed-array: 1.1.12
       is-weakref: 1.0.2
       object-inspect: 1.12.3
       object-keys: 1.1.1
       object.assign: 4.1.4
-      regexp.prototype.flags: 1.5.0
+      regexp.prototype.flags: 1.5.1
+      safe-array-concat: 1.0.1
       safe-regex-test: 1.0.0
-      string.prototype.trim: 1.2.7
-      string.prototype.trimend: 1.0.6
-      string.prototype.trimstart: 1.0.6
+      string.prototype.trim: 1.2.8
+      string.prototype.trimend: 1.0.7
+      string.prototype.trimstart: 1.0.7
+      typed-array-buffer: 1.0.0
+      typed-array-byte-length: 1.0.0
+      typed-array-byte-offset: 1.0.0
       typed-array-length: 1.0.4
       unbox-primitive: 1.0.2
-      which-typed-array: 1.1.9
+      which-typed-array: 1.1.11
     dev: true
 
-  /es-module-lexer@1.3.0:
-    resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==}
+  /es-module-lexer@1.3.1:
+    resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==}
 
   /es-set-tostringtag@2.0.1:
     resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==}
     engines: {node: '>= 0.4'}
     dependencies:
       get-intrinsic: 1.2.1
-      has: 1.0.3
+      has: 1.0.4
       has-tostringtag: 1.0.0
     dev: true
 
   /es-shim-unscopables@1.0.0:
     resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==}
     dependencies:
-      has: 1.0.3
+      has: 1.0.4
     dev: true
 
   /es-to-primitive@1.2.1:
     resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
     engines: {node: '>= 0.4'}
@@ -8130,38 +8164,38 @@ packages:
       '@esbuild/sunos-x64': 0.18.16
       '@esbuild/win32-arm64': 0.18.16
       '@esbuild/win32-ia32': 0.18.16
       '@esbuild/win32-x64': 0.18.16
 
-  /esbuild@0.19.3:
-    resolution: {integrity: sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==}
+  /esbuild@0.19.4:
+    resolution: {integrity: sha512-x7jL0tbRRpv4QUyuDMjONtWFciygUxWaUM1kMX2zWxI0X2YWOt7MSA0g4UdeSiHM8fcYVzpQhKYOycZwxTdZkA==}
     engines: {node: '>=12'}
     hasBin: true
     requiresBuild: true
     optionalDependencies:
-      '@esbuild/android-arm': 0.19.3
-      '@esbuild/android-arm64': 0.19.3
-      '@esbuild/android-x64': 0.19.3
-      '@esbuild/darwin-arm64': 0.19.3
-      '@esbuild/darwin-x64': 0.19.3
-      '@esbuild/freebsd-arm64': 0.19.3
-      '@esbuild/freebsd-x64': 0.19.3
-      '@esbuild/linux-arm': 0.19.3
-      '@esbuild/linux-arm64': 0.19.3
-      '@esbuild/linux-ia32': 0.19.3
-      '@esbuild/linux-loong64': 0.19.3
-      '@esbuild/linux-mips64el': 0.19.3
-      '@esbuild/linux-ppc64': 0.19.3
-      '@esbuild/linux-riscv64': 0.19.3
-      '@esbuild/linux-s390x': 0.19.3
-      '@esbuild/linux-x64': 0.19.3
-      '@esbuild/netbsd-x64': 0.19.3
-      '@esbuild/openbsd-x64': 0.19.3
-      '@esbuild/sunos-x64': 0.19.3
-      '@esbuild/win32-arm64': 0.19.3
-      '@esbuild/win32-ia32': 0.19.3
-      '@esbuild/win32-x64': 0.19.3
+      '@esbuild/android-arm': 0.19.4
+      '@esbuild/android-arm64': 0.19.4
+      '@esbuild/android-x64': 0.19.4
+      '@esbuild/darwin-arm64': 0.19.4
+      '@esbuild/darwin-x64': 0.19.4
+      '@esbuild/freebsd-arm64': 0.19.4
+      '@esbuild/freebsd-x64': 0.19.4
+      '@esbuild/linux-arm': 0.19.4
+      '@esbuild/linux-arm64': 0.19.4
+      '@esbuild/linux-ia32': 0.19.4
+      '@esbuild/linux-loong64': 0.19.4
+      '@esbuild/linux-mips64el': 0.19.4
+      '@esbuild/linux-ppc64': 0.19.4
+      '@esbuild/linux-riscv64': 0.19.4
+      '@esbuild/linux-s390x': 0.19.4
+      '@esbuild/linux-x64': 0.19.4
+      '@esbuild/netbsd-x64': 0.19.4
+      '@esbuild/openbsd-x64': 0.19.4
+      '@esbuild/sunos-x64': 0.19.4
+      '@esbuild/win32-arm64': 0.19.4
+      '@esbuild/win32-ia32': 0.19.4
+      '@esbuild/win32-x64': 0.19.4
 
   /escalade@3.1.1:
     resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
     engines: {node: '>=6'}
 
@@ -8205,45 +8239,45 @@ packages:
       eslint: '>=7.0.0'
     dependencies:
       eslint: 8.45.0
     dev: true
 
-  /eslint-config-xtrict@3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.1.6):
+  /eslint-config-xtrict@3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.2.2):
     resolution: {integrity: sha512-5njDMQ1R2s9ghMYpk2Ox84bfd8Umly3yVs4DL5XjgR0XonD/s4Yw1nawqWhr7hZzSUXKcmRvPuOx0eJVX+7t7w==}
     engines: {node: '>=10'}
     peerDependencies:
       eslint: ^6.8.0
       typescript: ^3.8.3
     dependencies:
-      '@typescript-eslint/eslint-plugin': 3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.1.6)
-      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/eslint-plugin': 3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.2.2)
+      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
       eslint: 8.45.0
       eslint-config-prettier: 6.15.0(eslint@8.45.0)
       eslint-plugin-import: 2.27.5(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)
       eslint-plugin-jsdoc: 30.7.13(eslint@8.45.0)
       eslint-plugin-prettier: 3.4.1(eslint-config-prettier@6.15.0)(eslint@8.45.0)(prettier@3.0.2)
       eslint-plugin-sonarjs: 0.5.0(eslint@8.45.0)
       eslint-plugin-unicorn: 21.0.0(eslint@8.45.0)
-      typescript: 5.1.6
+      typescript: 5.2.2
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - prettier
       - supports-color
     dev: true
 
-  /eslint-import-resolver-node@0.3.7:
-    resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==}
+  /eslint-import-resolver-node@0.3.9:
+    resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
     dependencies:
       debug: 3.2.7
-      is-core-module: 2.12.1
-      resolve: 1.22.2
+      is-core-module: 2.13.0
+      resolve: 1.22.6
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /eslint-module-utils@2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0):
+  /eslint-module-utils@2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0):
     resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
     engines: {node: '>=4'}
     peerDependencies:
       '@typescript-eslint/parser': '*'
       eslint: '*'
@@ -8260,19 +8294,19 @@ packages:
       eslint-import-resolver-typescript:
         optional: true
       eslint-import-resolver-webpack:
         optional: true
     dependencies:
-      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
       debug: 3.2.7
       eslint: 8.45.0
-      eslint-import-resolver-node: 0.3.7
+      eslint-import-resolver-node: 0.3.9
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0):
+  /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0):
     resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
     engines: {node: '>=4'}
     peerDependencies:
       '@typescript-eslint/parser': '*'
       eslint: '*'
@@ -8289,14 +8323,14 @@ packages:
       eslint-import-resolver-typescript:
         optional: true
       eslint-import-resolver-webpack:
         optional: true
     dependencies:
-      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
       debug: 3.2.7
       eslint: 8.45.0
-      eslint-import-resolver-node: 0.3.7
+      eslint-import-resolver-node: 0.3.9
     transitivePeerDependencies:
       - supports-color
     dev: true
 
   /eslint-plugin-import@2.27.5(@typescript-eslint/parser@3.10.1)(eslint@8.45.0):
@@ -8307,26 +8341,26 @@ packages:
       eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
     peerDependenciesMeta:
       '@typescript-eslint/parser':
         optional: true
     dependencies:
-      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
-      array-includes: 3.1.6
-      array.prototype.flat: 1.3.1
-      array.prototype.flatmap: 1.3.1
+      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
+      array-includes: 3.1.7
+      array.prototype.flat: 1.3.2
+      array.prototype.flatmap: 1.3.2
       debug: 3.2.7
       doctrine: 2.1.0
       eslint: 8.45.0
-      eslint-import-resolver-node: 0.3.7
-      eslint-module-utils: 2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0)
-      has: 1.0.3
-      is-core-module: 2.12.1
+      eslint-import-resolver-node: 0.3.9
+      eslint-module-utils: 2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0)
+      has: 1.0.4
+      is-core-module: 2.13.0
       is-glob: 4.0.3
       minimatch: 3.1.2
-      object.values: 1.1.6
-      resolve: 1.22.2
-      semver: 6.3.0
+      object.values: 1.1.7
+      resolve: 1.22.6
+      semver: 6.3.1
       tsconfig-paths: 3.14.2
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - supports-color
@@ -8340,26 +8374,26 @@ packages:
       eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
     peerDependenciesMeta:
       '@typescript-eslint/parser':
         optional: true
     dependencies:
-      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
-      array-includes: 3.1.6
-      array.prototype.flat: 1.3.1
-      array.prototype.flatmap: 1.3.1
+      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
+      array-includes: 3.1.7
+      array.prototype.flat: 1.3.2
+      array.prototype.flatmap: 1.3.2
       debug: 3.2.7
       doctrine: 2.1.0
       eslint: 8.45.0
-      eslint-import-resolver-node: 0.3.7
-      eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0)
-      has: 1.0.3
-      is-core-module: 2.12.1
+      eslint-import-resolver-node: 0.3.9
+      eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0)
+      has: 1.0.4
+      is-core-module: 2.13.0
       is-glob: 4.0.3
       minimatch: 3.1.2
-      object.values: 1.1.6
-      resolve: 1.22.2
-      semver: 6.3.0
+      object.values: 1.1.7
+      resolve: 1.22.6
+      semver: 6.3.1
       tsconfig-paths: 3.14.2
     transitivePeerDependencies:
       - eslint-import-resolver-typescript
       - eslint-import-resolver-webpack
       - supports-color
@@ -8398,20 +8432,20 @@ packages:
       eslint-config-prettier: 6.15.0(eslint@8.45.0)
       prettier: 3.0.2
       prettier-linter-helpers: 1.0.0
     dev: true
 
-  /eslint-plugin-solid@0.12.1(eslint@8.45.0)(typescript@5.1.6):
+  /eslint-plugin-solid@0.12.1(eslint@8.45.0)(typescript@5.2.2):
     resolution: {integrity: sha512-fM0sEg9PcS1mcNbWklwc+W/lOv1/XyEwXf53HmFFy4GOA8E3u41h8JW+hc+Vv1m3kh01umKoTalOTET08zKdAQ==}
     engines: {node: '>=12.0.0'}
     peerDependencies:
       eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
     dependencies:
-      '@typescript-eslint/utils': 5.59.11(eslint@8.45.0)(typescript@5.1.6)
+      '@typescript-eslint/utils': 5.62.0(eslint@8.45.0)(typescript@5.2.2)
       eslint: 8.45.0
       is-html: 2.0.0
-      jsx-ast-utils: 3.3.3
+      jsx-ast-utils: 3.3.5
       kebab-case: 1.0.2
       known-css-properties: 0.24.0
       style-to-object: 0.3.0
     transitivePeerDependencies:
       - supports-color
@@ -8457,12 +8491,12 @@ packages:
     dependencies:
       esrecurse: 4.3.0
       estraverse: 4.3.0
     dev: true
 
-  /eslint-scope@7.2.0:
-    resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==}
+  /eslint-scope@7.2.2:
+    resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dependencies:
       esrecurse: 4.3.0
       estraverse: 5.3.0
     dev: true
@@ -8470,12 +8504,12 @@ packages:
   /eslint-template-visitor@2.3.2(eslint@8.45.0):
     resolution: {integrity: sha512-3ydhqFpuV7x1M9EK52BPNj6V0Kwu0KKkcIAfpUhwHbR8ocRln/oUHgfxQupY8O1h4Qv/POHDumb/BwwNfxbtnA==}
     peerDependencies:
       eslint: '>=7.0.0'
     dependencies:
-      '@babel/core': 7.22.5
-      '@babel/eslint-parser': 7.22.5(@babel/core@7.22.5)(eslint@8.45.0)
+      '@babel/core': 7.23.0
+      '@babel/eslint-parser': 7.22.15(@babel/core@7.23.0)(eslint@8.45.0)
       eslint: 8.45.0
       eslint-visitor-keys: 2.1.0
       esquery: 1.5.0
       multimap: 1.1.0
     transitivePeerDependencies:
@@ -8497,43 +8531,43 @@ packages:
   /eslint-visitor-keys@2.1.0:
     resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==}
     engines: {node: '>=10'}
     dev: true
 
-  /eslint-visitor-keys@3.4.1:
-    resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==}
+  /eslint-visitor-keys@3.4.3:
+    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dev: true
 
   /eslint@8.45.0:
     resolution: {integrity: sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     hasBin: true
     dependencies:
       '@eslint-community/eslint-utils': 4.4.0(eslint@8.45.0)
-      '@eslint-community/regexpp': 4.6.1
-      '@eslint/eslintrc': 2.1.0
+      '@eslint-community/regexpp': 4.9.1
+      '@eslint/eslintrc': 2.1.2
       '@eslint/js': 8.44.0
-      '@humanwhocodes/config-array': 0.11.10
+      '@humanwhocodes/config-array': 0.11.11
       '@humanwhocodes/module-importer': 1.0.1
       '@nodelib/fs.walk': 1.2.8
       ajv: 6.12.6
       chalk: 4.1.2
       cross-spawn: 7.0.3
       debug: 4.3.4
       doctrine: 3.0.0
       escape-string-regexp: 4.0.0
-      eslint-scope: 7.2.0
-      eslint-visitor-keys: 3.4.1
+      eslint-scope: 7.2.2
+      eslint-visitor-keys: 3.4.3
       espree: 9.6.1
       esquery: 1.5.0
       esutils: 2.0.3
       fast-deep-equal: 3.1.3
       file-entry-cache: 6.0.1
       find-up: 5.0.0
       glob-parent: 6.0.2
-      globals: 13.20.0
+      globals: 13.23.0
       graphemer: 1.4.0
       ignore: 5.2.4
       imurmurhash: 0.1.4
       is-glob: 4.0.3
       is-path-inside: 3.0.3
@@ -8554,11 +8588,11 @@ packages:
     resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dependencies:
       acorn: 8.10.0
       acorn-jsx: 5.3.2(acorn@8.10.0)
-      eslint-visitor-keys: 3.4.1
+      eslint-visitor-keys: 3.4.3
     dev: true
 
   /esprima@4.0.1:
     resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
     engines: {node: '>=4'}
@@ -8586,20 +8620,53 @@ packages:
   /estraverse@5.3.0:
     resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
     engines: {node: '>=4.0'}
     dev: true
 
+  /estree-util-attach-comments@2.1.1:
+    resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==}
+    dependencies:
+      '@types/estree': 1.0.2
+    dev: false
+
+  /estree-util-build-jsx@2.2.2:
+    resolution: {integrity: sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      estree-util-is-identifier-name: 2.1.0
+      estree-walker: 3.0.3
+    dev: false
+
+  /estree-util-is-identifier-name@2.1.0:
+    resolution: {integrity: sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==}
+    dev: false
+
+  /estree-util-to-js@1.2.0:
+    resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      astring: 1.8.6
+      source-map: 0.7.4
+    dev: false
+
+  /estree-util-visit@1.2.1:
+    resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/unist': 2.0.8
+    dev: false
+
   /estree-walker@2.0.2:
     resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
 
   /estree-walker@3.0.0:
     resolution: {integrity: sha512-s6ceX0NFiU/vKPiKvFdR83U1Zffu7upwZsGwpoqfg5rbbq1l50WQ5hCeIvM6E6oD4shUHCYMsiFPns4Jk0YfMQ==}
 
   /estree-walker@3.0.3:
     resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
     dependencies:
-      '@types/estree': 1.0.1
+      '@types/estree': 1.0.2
 
   /esutils@2.0.3:
     resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
     engines: {node: '>=0.10.0'}
     dev: true
@@ -8653,12 +8720,12 @@ packages:
       npm-run-path: 5.1.0
       onetime: 6.0.0
       signal-exit: 3.0.7
       strip-final-newline: 3.0.0
 
-  /execa@7.1.1:
-    resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==}
+  /execa@7.2.0:
+    resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==}
     engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0}
     dependencies:
       cross-spawn: 7.0.3
       get-stream: 6.0.1
       human-signals: 4.3.1
@@ -8699,12 +8766,12 @@ packages:
   /extract-files@9.0.0:
     resolution: {integrity: sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==}
     engines: {node: ^10.17.0 || ^12.0.0 || >= 13.7.0}
     dev: false
 
-  /fast-content-type-parse@1.0.0:
-    resolution: {integrity: sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA==}
+  /fast-content-type-parse@1.1.0:
+    resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==}
     dev: false
 
   /fast-decode-uri-component@1.0.1:
     resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
     dev: false
@@ -8739,25 +8806,26 @@ packages:
 
   /fast-json-stable-stringify@2.1.0:
     resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
     dev: true
 
-  /fast-json-stringify@5.7.0:
-    resolution: {integrity: sha512-sBVPTgnAZseLu1Qgj6lUbQ0HfjFhZWXAmpZ5AaSGkyLh5gAXBga/uPJjQPHpDFjC9adWIpdOcCLSDTgrZ7snoQ==}
+  /fast-json-stringify@5.8.0:
+    resolution: {integrity: sha512-VVwK8CFMSALIvt14U8AvrSzQAwN/0vaVRiFFUVlpnXSnDGrSkOAO5MtzyN8oQNjLd5AqTW5OZRgyjoNuAuR3jQ==}
     dependencies:
       '@fastify/deepmerge': 1.3.0
       ajv: 8.12.0
       ajv-formats: 2.1.1(ajv@8.12.0)
       fast-deep-equal: 3.1.3
       fast-uri: 2.2.0
       rfdc: 1.3.0
     dev: false
 
-  /fast-jwt@3.1.1:
-    resolution: {integrity: sha512-c6gqmiMU9kUIMs0XcsnnpBMA4A+zi/XULA47r6hYoLR7s1teJ+LwviwZdttCeTZ+F5ZuHlRigNe98C4qN6h4pw==}
-    engines: {node: '>=14 <22'}
+  /fast-jwt@3.3.1:
+    resolution: {integrity: sha512-1YuuIJeh1hEvfcYDe89P2oGACWI5hd2GadRDKHalSxkc1Z0z8I6yzuVK6SF15sW09QZngTV6d7g4+TFL9bvs5A==}
+    engines: {node: '>=16 <22'}
     dependencies:
+      '@lukeed/ms': 2.0.1
       asn1.js: 5.4.1
       ecdsa-sig-formatter: 1.0.11
       mnemonist: 0.39.5
     dev: false
 
@@ -8769,12 +8837,12 @@ packages:
     resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==}
     dependencies:
       fast-decode-uri-component: 1.0.1
     dev: false
 
-  /fast-redact@3.2.0:
-    resolution: {integrity: sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==}
+  /fast-redact@3.3.0:
+    resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==}
     engines: {node: '>=6'}
     dev: false
 
   /fast-uri@2.2.0:
     resolution: {integrity: sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg==}
@@ -8792,33 +8860,33 @@ packages:
     engines: {node: '>=0.10.0'}
     dependencies:
       reusify: 1.0.4
     dev: false
 
-  /fastify-plugin@4.5.0:
-    resolution: {integrity: sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg==}
+  /fastify-plugin@4.5.1:
+    resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==}
     dev: false
 
   /fastify@4.20.0:
     resolution: {integrity: sha512-zWWi5KGAb1YZ6fyrnFnA1CA1EZHkGM6YuELgB3QpS3l4lLRy14W1cc16b4KGPH/zQ98WCSdS+T41JkHY3eq1oA==}
     dependencies:
       '@fastify/ajv-compiler': 3.5.0
-      '@fastify/error': 3.2.1
+      '@fastify/error': 3.4.0
       '@fastify/fast-json-stringify-compiler': 4.3.0
       abstract-logging: 2.0.1
       avvio: 8.2.1
-      fast-content-type-parse: 1.0.0
-      fast-json-stringify: 5.7.0
+      fast-content-type-parse: 1.1.0
+      fast-json-stringify: 5.8.0
       find-my-way: 7.6.2
-      light-my-request: 5.10.0
-      pino: 8.14.1
+      light-my-request: 5.11.0
+      pino: 8.15.6
       process-warning: 2.2.0
       proxy-addr: 2.0.7
       rfdc: 1.3.0
       secure-json-parse: 2.7.0
       semver: 7.5.4
-      tiny-lru: 11.0.1
+      tiny-lru: 11.2.2
     transitivePeerDependencies:
       - supports-color
     dev: false
 
   /fastparallel@2.4.1:
@@ -8838,15 +8906,29 @@ packages:
     dependencies:
       reusify: 1.0.4
       xtend: 4.0.2
     dev: false
 
+  /fault@2.0.1:
+    resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
+    dependencies:
+      format: 0.2.2
+    dev: false
+
+  /fetch-blob@3.2.0:
+    resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+    engines: {node: ^12.20 || >= 14.13}
+    dependencies:
+      node-domexception: 1.0.0
+      web-streams-polyfill: 3.2.1
+    dev: false
+
   /file-entry-cache@6.0.1:
     resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
     engines: {node: ^10.12.0 || >=12.0.0}
     dependencies:
-      flat-cache: 3.0.4
+      flat-cache: 3.1.1
     dev: true
 
   /file-type@18.5.0:
     resolution: {integrity: sha512-yvpl5U868+V6PqXHMmsESpg6unQ5GfnPssl4dxdJudBrr9qy7Fddt7EVX1VLlddFfe8Gj9N7goCZH22FXuSQXQ==}
     engines: {node: '>=14.16'}
@@ -8894,24 +8976,25 @@ packages:
     resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==}
     dependencies:
       micromatch: 4.0.5
       pkg-dir: 4.2.0
 
-  /flat-cache@3.0.4:
-    resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
-    engines: {node: ^10.12.0 || >=12.0.0}
+  /flat-cache@3.1.1:
+    resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==}
+    engines: {node: '>=12.0.0'}
     dependencies:
-      flatted: 3.2.7
+      flatted: 3.2.9
+      keyv: 4.5.4
       rimraf: 3.0.2
     dev: true
 
-  /flatted@3.2.7:
-    resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
+  /flatted@3.2.9:
+    resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
     dev: true
 
-  /follow-redirects@1.15.2:
-    resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
+  /follow-redirects@1.15.3:
+    resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
     engines: {node: '>=4.0'}
     peerDependencies:
       debug: '*'
     peerDependenciesMeta:
       debug:
@@ -8927,11 +9010,11 @@ packages:
   /foreground-child@3.1.1:
     resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
     engines: {node: '>=14'}
     dependencies:
       cross-spawn: 7.0.3
-      signal-exit: 4.0.2
+      signal-exit: 4.1.0
     dev: false
 
   /form-data-encoder@1.7.2:
     resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==}
     dev: false
@@ -8952,18 +9035,30 @@ packages:
       asynckit: 0.4.0
       combined-stream: 1.0.8
       mime-types: 2.1.35
     dev: false
 
+  /format@0.2.2:
+    resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
+    engines: {node: '>=0.4.x'}
+    dev: false
+
   /formdata-node@4.4.1:
     resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
     engines: {node: '>= 12.20'}
     dependencies:
       node-domexception: 1.0.0
       web-streams-polyfill: 4.0.0-beta.3
     dev: false
 
+  /formdata-polyfill@4.0.10:
+    resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+    engines: {node: '>=12.20.0'}
+    dependencies:
+      fetch-blob: 3.2.0
+    dev: false
+
   /forwarded@0.2.0:
     resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
     engines: {node: '>= 0.6'}
     dev: false
 
@@ -9002,12 +9097,12 @@ packages:
     dev: false
 
   /fs.realpath@1.0.0:
     resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
 
-  /fsevents@2.3.2:
-    resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+  /fsevents@2.3.3:
+    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
     engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
     os: [darwin]
     requiresBuild: true
     optional: true
 
@@ -9022,17 +9117,17 @@ packages:
     dev: false
 
   /function-bind@1.1.1:
     resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
 
-  /function.prototype.name@1.1.5:
-    resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
+  /function.prototype.name@1.1.6:
+    resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
       functions-have-names: 1.2.3
     dev: true
 
   /functional-red-black-tree@1.0.1:
     resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==}
@@ -9048,11 +9143,11 @@ packages:
 
   /get-intrinsic@1.2.1:
     resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==}
     dependencies:
       function-bind: 1.1.1
-      has: 1.0.3
+      has: 1.0.4
       has-proto: 1.0.1
       has-symbols: 1.0.3
 
   /get-stdin@6.0.0:
     resolution: {integrity: sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==}
@@ -9100,13 +9195,13 @@ packages:
     resolution: {integrity: sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==}
     engines: {node: '>=16 || 14 >=14.17'}
     hasBin: true
     dependencies:
       foreground-child: 3.1.1
-      jackspeak: 2.2.2
+      jackspeak: 2.3.6
       minimatch: 9.0.3
-      minipass: 6.0.2
+      minipass: 7.0.4
       path-scurry: 1.10.1
     dev: false
 
   /glob@7.2.3:
     resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
@@ -9141,22 +9236,22 @@ packages:
 
   /globals@11.12.0:
     resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
     engines: {node: '>=4'}
 
-  /globals@13.20.0:
-    resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
+  /globals@13.23.0:
+    resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==}
     engines: {node: '>=8'}
     dependencies:
       type-fest: 0.20.2
     dev: true
 
   /globalthis@1.0.3:
     resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
     engines: {node: '>= 0.4'}
     dependencies:
-      define-properties: 1.2.0
+      define-properties: 1.2.1
     dev: true
 
   /globby@11.1.0:
     resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
     engines: {node: '>=10'}
@@ -9166,12 +9261,12 @@ packages:
       fast-glob: 3.3.1
       ignore: 5.2.4
       merge2: 1.4.1
       slash: 3.0.0
 
-  /globby@13.1.4:
-    resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==}
+  /globby@13.2.2:
+    resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     dependencies:
       dir-glob: 3.0.1
       fast-glob: 3.3.1
       ignore: 5.2.4
@@ -9194,26 +9289,26 @@ packages:
 
   /graphemer@1.4.0:
     resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
     dev: true
 
-  /graphql-request@5.2.0(graphql@16.7.1):
+  /graphql-request@5.2.0(graphql@16.8.1):
     resolution: {integrity: sha512-pLhKIvnMyBERL0dtFI3medKqWOz/RhHdcgbZ+hMMIb32mEPa5MJSzS4AuXxfI4sRAu6JVVk5tvXuGfCWl9JYWQ==}
     peerDependencies:
       graphql: 14 - 16
     dependencies:
-      '@graphql-typed-document-node/core': 3.2.0(graphql@16.7.1)
+      '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1)
       cross-fetch: 3.1.8
       extract-files: 9.0.0
       form-data: 3.0.1
-      graphql: 16.7.1
+      graphql: 16.8.1
     transitivePeerDependencies:
       - encoding
     dev: false
 
-  /graphql@16.7.1:
-    resolution: {integrity: sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==}
+  /graphql@16.8.1:
+    resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==}
     engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
     dev: false
 
   /gray-matter@4.0.3:
     resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==}
@@ -9228,20 +9323,21 @@ packages:
     resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
     engines: {node: '>=10'}
     dependencies:
       duplexer: 0.1.2
 
-  /h3@1.7.1:
-    resolution: {integrity: sha512-A9V2NEDNHet7v1gCg7CMwerSigLi0SRbhTy7C3lGb0N4YKIpPmLDjedTUopqp4dnn7COHfqUjjaz3zbtz4QduA==}
+  /h3@1.8.2:
+    resolution: {integrity: sha512-1Ca0orJJlCaiFY68BvzQtP2lKLk46kcLAxVM8JgYbtm2cUg6IY7pjpYgWMwUvDO9QI30N5JAukOKoT8KD3Q0PQ==}
     dependencies:
       cookie-es: 1.0.0
       defu: 6.1.2
-      destr: 2.0.0
-      iron-webcrypto: 0.7.1
-      radix3: 1.0.1
-      ufo: 1.1.2
+      destr: 2.0.1
+      iron-webcrypto: 0.10.1
+      radix3: 1.1.0
+      ufo: 1.3.1
       uncrypto: 0.1.3
+      unenv: 1.7.4
     dev: false
 
   /handlebars@4.7.8:
     resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==}
     engines: {node: '>=0.4.7'}
@@ -9286,40 +9382,57 @@ packages:
     engines: {node: '>= 0.4'}
     dependencies:
       has-symbols: 1.0.3
     dev: true
 
-  /has@1.0.3:
-    resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
+  /has@1.0.4:
+    resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==}
     engines: {node: '>= 0.4.0'}
-    dependencies:
-      function-bind: 1.1.1
 
   /hashlru@2.3.0:
     resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==}
     dev: false
 
   /hast-util-from-parse5@7.1.2:
     resolution: {integrity: sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==}
     dependencies:
-      '@types/hast': 2.3.4
-      '@types/unist': 2.0.6
+      '@types/hast': 2.3.6
+      '@types/unist': 2.0.8
       hastscript: 7.2.0
-      property-information: 6.2.0
+      property-information: 6.3.0
       vfile: 5.3.7
       vfile-location: 4.1.0
       web-namespaces: 2.0.1
 
+  /hast-util-from-parse5@8.0.1:
+    resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==}
+    dependencies:
+      '@types/hast': 3.0.1
+      '@types/unist': 3.0.0
+      devlop: 1.1.0
+      hastscript: 8.0.0
+      property-information: 6.3.0
+      vfile: 6.0.1
+      vfile-location: 5.0.2
+      web-namespaces: 2.0.1
+    dev: false
+
   /hast-util-parse-selector@3.1.1:
     resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 2.3.6
+
+  /hast-util-parse-selector@4.0.0:
+    resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
+    dependencies:
+      '@types/hast': 3.0.1
+    dev: false
 
   /hast-util-raw@7.2.3:
     resolution: {integrity: sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 2.3.6
       '@types/parse5': 6.0.3
       hast-util-from-parse5: 7.1.2
       hast-util-to-parse5: 7.1.0
       html-void-elements: 2.0.1
       parse5: 6.0.1
@@ -9327,49 +9440,134 @@ packages:
       unist-util-visit: 4.1.2
       vfile: 5.3.7
       web-namespaces: 2.0.1
       zwitch: 2.0.4
 
+  /hast-util-raw@9.0.1:
+    resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==}
+    dependencies:
+      '@types/hast': 3.0.1
+      '@types/unist': 3.0.0
+      '@ungap/structured-clone': 1.2.0
+      hast-util-from-parse5: 8.0.1
+      hast-util-to-parse5: 8.0.0
+      html-void-elements: 3.0.0
+      mdast-util-to-hast: 13.0.2
+      parse5: 7.1.2
+      unist-util-position: 5.0.0
+      unist-util-visit: 5.0.0
+      vfile: 6.0.1
+      web-namespaces: 2.0.1
+      zwitch: 2.0.4
+    dev: false
+
+  /hast-util-to-estree@2.3.3:
+    resolution: {integrity: sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==}
+    dependencies:
+      '@types/estree': 1.0.2
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 2.3.6
+      '@types/unist': 2.0.8
+      comma-separated-tokens: 2.0.3
+      estree-util-attach-comments: 2.1.1
+      estree-util-is-identifier-name: 2.1.0
+      hast-util-whitespace: 2.0.1
+      mdast-util-mdx-expression: 1.3.2
+      mdast-util-mdxjs-esm: 1.3.1
+      property-information: 6.3.0
+      space-separated-tokens: 2.0.2
+      style-to-object: 0.4.1
+      unist-util-position: 4.0.4
+      zwitch: 2.0.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /hast-util-to-html@8.0.4:
     resolution: {integrity: sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==}
     dependencies:
-      '@types/hast': 2.3.4
-      '@types/unist': 2.0.6
+      '@types/hast': 2.3.6
+      '@types/unist': 2.0.8
       ccount: 2.0.1
       comma-separated-tokens: 2.0.3
       hast-util-raw: 7.2.3
       hast-util-whitespace: 2.0.1
       html-void-elements: 2.0.1
-      property-information: 6.2.0
+      property-information: 6.3.0
       space-separated-tokens: 2.0.2
       stringify-entities: 4.0.3
       zwitch: 2.0.4
 
-  /hast-util-to-parse5@7.1.0:
-    resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==}
+  /hast-util-to-html@9.0.0:
+    resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 3.0.1
+      '@types/unist': 3.0.0
+      ccount: 2.0.1
       comma-separated-tokens: 2.0.3
-      property-information: 6.2.0
+      hast-util-raw: 9.0.1
+      hast-util-whitespace: 3.0.0
+      html-void-elements: 3.0.0
+      mdast-util-to-hast: 13.0.2
+      property-information: 6.3.0
       space-separated-tokens: 2.0.2
-      web-namespaces: 2.0.1
+      stringify-entities: 4.0.3
       zwitch: 2.0.4
+    dev: false
+
+  /hast-util-to-parse5@7.1.0:
+    resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==}
+    dependencies:
+      '@types/hast': 2.3.6
+      comma-separated-tokens: 2.0.3
+      property-information: 6.3.0
+      space-separated-tokens: 2.0.2
+      web-namespaces: 2.0.1
+      zwitch: 2.0.4
+
+  /hast-util-to-parse5@8.0.0:
+    resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
+    dependencies:
+      '@types/hast': 3.0.1
+      comma-separated-tokens: 2.0.3
+      devlop: 1.1.0
+      property-information: 6.3.0
+      space-separated-tokens: 2.0.2
+      web-namespaces: 2.0.1
+      zwitch: 2.0.4
+    dev: false
 
   /hast-util-whitespace@2.0.1:
     resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==}
 
+  /hast-util-whitespace@3.0.0:
+    resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+    dependencies:
+      '@types/hast': 3.0.1
+    dev: false
+
   /hastscript@7.2.0:
     resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 2.3.6
       comma-separated-tokens: 2.0.3
       hast-util-parse-selector: 3.1.1
-      property-information: 6.2.0
+      property-information: 6.3.0
       space-separated-tokens: 2.0.2
 
-  /headers-polyfill@3.1.2:
-    resolution: {integrity: sha512-tWCK4biJ6hcLqTviLXVR9DTRfYGQMXEIUj3gwJ2rZ5wO/at3XtkI4g8mCvFdUF9l1KMBNCfmNAdnahm1cgavQA==}
+  /hastscript@8.0.0:
+    resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==}
+    dependencies:
+      '@types/hast': 3.0.1
+      comma-separated-tokens: 2.0.3
+      hast-util-parse-selector: 4.0.0
+      property-information: 6.3.0
+      space-separated-tokens: 2.0.2
+    dev: false
+
+  /headers-polyfill@3.3.0:
+    resolution: {integrity: sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ==}
     dev: false
 
   /hey-listen@1.0.8:
     resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
     dev: false
@@ -9434,10 +9632,14 @@ packages:
     dev: false
 
   /html-void-elements@2.0.1:
     resolution: {integrity: sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==}
 
+  /html-void-elements@3.0.0:
+    resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+    dev: false
+
   /htmlparser2@8.0.1:
     resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==}
     dependencies:
       domelementtype: 2.3.0
       domhandler: 5.0.3
@@ -9507,12 +9709,12 @@ packages:
     engines: {node: '>=14.16'}
     dependencies:
       file-type: 18.5.0
     dev: false
 
-  /immutable@4.3.0:
-    resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
+  /immutable@4.3.4:
+    resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==}
 
   /import-fresh@3.3.0:
     resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
     engines: {node: '>=6'}
     dependencies:
@@ -9564,11 +9766,11 @@ packages:
   /internal-slot@1.0.5:
     resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
     engines: {node: '>= 0.4'}
     dependencies:
       get-intrinsic: 1.2.1
-      has: 1.0.3
+      has: 1.0.4
       side-channel: 1.0.4
     dev: true
 
   /interpret@1.4.0:
     resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==}
@@ -9618,20 +9820,31 @@ packages:
   /ipaddr.js@1.9.1:
     resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
     engines: {node: '>= 0.10'}
     dev: false
 
-  /iron-webcrypto@0.7.1:
-    resolution: {integrity: sha512-K/UmlEhPCPXEHV5hAtH5C0tI5JnFuOrv4yO/j7ODPl3HaiiHBLbOLTde+ieUaAyfCATe4LoAnclyF+hmSCOVmQ==}
+  /iron-webcrypto@0.10.1:
+    resolution: {integrity: sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA==}
+    dev: false
+
+  /is-alphabetical@2.0.1:
+    resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+    dev: false
+
+  /is-alphanumerical@2.0.1:
+    resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+    dependencies:
+      is-alphabetical: 2.0.1
+      is-decimal: 2.0.1
     dev: false
 
   /is-array-buffer@3.0.2:
     resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
     dependencies:
       call-bind: 1.0.2
       get-intrinsic: 1.2.1
-      is-typed-array: 1.1.10
+      is-typed-array: 1.1.12
     dev: true
 
   /is-arrayish@0.2.1:
     resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
 
@@ -9676,28 +9889,26 @@ packages:
   /is-callable@1.2.7:
     resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
     engines: {node: '>= 0.4'}
     dev: true
 
-  /is-core-module@2.12.1:
-    resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==}
-    dependencies:
-      has: 1.0.3
-    dev: true
-
   /is-core-module@2.13.0:
     resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
     dependencies:
-      has: 1.0.3
+      has: 1.0.4
 
   /is-date-object@1.0.5:
     resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
     engines: {node: '>= 0.4'}
     dependencies:
       has-tostringtag: 1.0.0
     dev: true
 
+  /is-decimal@2.0.1:
+    resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+    dev: false
+
   /is-docker@2.2.1:
     resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
     engines: {node: '>=8'}
     hasBin: true
 
@@ -9729,10 +9940,14 @@ packages:
     resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
     engines: {node: '>=0.10.0'}
     dependencies:
       is-extglob: 2.1.1
 
+  /is-hexadecimal@2.0.1:
+    resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+    dev: false
+
   /is-html@2.0.0:
     resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==}
     engines: {node: '>=8'}
     dependencies:
       html-tags: 3.3.1
@@ -9796,13 +10011,19 @@ packages:
     dev: false
 
   /is-reference@1.2.1:
     resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
     dependencies:
-      '@types/estree': 1.0.1
+      '@types/estree': 1.0.2
     dev: true
 
+  /is-reference@3.0.2:
+    resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
+    dependencies:
+      '@types/estree': 1.0.2
+    dev: false
+
   /is-regex@1.1.4:
     resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
@@ -9835,19 +10056,15 @@ packages:
     engines: {node: '>= 0.4'}
     dependencies:
       has-symbols: 1.0.3
     dev: true
 
-  /is-typed-array@1.1.10:
-    resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==}
+  /is-typed-array@1.1.12:
+    resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
     engines: {node: '>= 0.4'}
     dependencies:
-      available-typed-arrays: 1.0.5
-      call-bind: 1.0.2
-      for-each: 0.3.3
-      gopd: 1.0.1
-      has-tostringtag: 1.0.0
+      which-typed-array: 1.1.11
     dev: true
 
   /is-unicode-supported@0.1.0:
     resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
     engines: {node: '>=10'}
@@ -9876,20 +10093,24 @@ packages:
     resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
     engines: {node: '>=8'}
     dependencies:
       is-docker: 2.2.1
 
-  /is-wsl@3.0.0:
-    resolution: {integrity: sha512-TQ7xXW/fTBaz/HhGSV779AC99ocpvb9qJPuPwyIea+F+Z+htcQ1wouAA0xEQaa4saVqyP8mwkoYp5efeM/4Gbg==}
+  /is-wsl@3.1.0:
+    resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
     engines: {node: '>=16'}
     dependencies:
-      is-docker: 3.0.0
+      is-inside-container: 1.0.0
 
   /isarray@1.0.0:
     resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
     dev: false
 
+  /isarray@2.0.5:
+    resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+    dev: true
+
   /isexe@2.0.0:
     resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
 
   /isobject@3.0.1:
     resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
@@ -9897,53 +10118,48 @@ packages:
     dev: false
 
   /isomorphic-fetch@3.0.0:
     resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
     dependencies:
-      node-fetch: 2.6.12
-      whatwg-fetch: 3.6.17
+      node-fetch: 2.7.0
+      whatwg-fetch: 3.6.19
     transitivePeerDependencies:
       - encoding
     dev: false
 
   /isomorphic-unfetch@3.1.0:
     resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==}
     dependencies:
-      node-fetch: 2.6.12
+      node-fetch: 2.7.0
       unfetch: 4.2.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
   /isomorphic.js@0.2.5:
     resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==}
     dev: false
 
-  /jackspeak@2.2.2:
-    resolution: {integrity: sha512-mgNtVv4vUuaKA97yxUHoA3+FkuhtxkjdXEWOyB/N76fjy0FjezEt34oy3epBtvCvS+7DyKwqCFWx/oJLV5+kCg==}
+  /jackspeak@2.3.6:
+    resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
     engines: {node: '>=14'}
     dependencies:
       '@isaacs/cliui': 8.0.2
     optionalDependencies:
       '@pkgjs/parseargs': 0.11.0
     dev: false
 
-  /jiti@1.18.2:
-    resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==}
-    hasBin: true
-    dev: true
-
-  /jiti@1.19.3:
-    resolution: {integrity: sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==}
+  /jiti@1.20.0:
+    resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==}
     hasBin: true
 
   /jju@1.4.0:
     resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
     dev: false
 
-  /joi@17.9.2:
-    resolution: {integrity: sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==}
+  /joi@17.11.0:
+    resolution: {integrity: sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==}
     dependencies:
       '@hapi/hoek': 9.3.0
       '@hapi/topo': 5.1.0
       '@sideway/address': 4.1.4
       '@sideway/formula': 3.0.1
@@ -9986,10 +10202,14 @@ packages:
   /jsesc@2.5.2:
     resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
     engines: {node: '>=4'}
     hasBin: true
 
+  /json-buffer@3.0.1:
+    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+    dev: true
+
   /json-parse-even-better-errors@2.3.1:
     resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
 
   /json-schema-resolver@2.0.0:
     resolution: {integrity: sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==}
@@ -10043,30 +10263,38 @@ packages:
     dependencies:
       universalify: 2.0.0
     optionalDependencies:
       graceful-fs: 4.2.11
 
-  /jsonwebtoken@9.0.1:
-    resolution: {integrity: sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==}
+  /jsonwebtoken@9.0.2:
+    resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
     engines: {node: '>=12', npm: '>=6'}
     dependencies:
       jws: 3.2.2
-      lodash: 4.17.21
+      lodash.includes: 4.3.0
+      lodash.isboolean: 3.0.3
+      lodash.isinteger: 4.0.4
+      lodash.isnumber: 3.0.3
+      lodash.isplainobject: 4.0.6
+      lodash.isstring: 4.0.1
+      lodash.once: 4.1.1
       ms: 2.1.3
       semver: 7.5.4
     dev: false
 
-  /jssha@3.3.0:
-    resolution: {integrity: sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==}
+  /jssha@3.3.1:
+    resolution: {integrity: sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==}
     dev: false
 
-  /jsx-ast-utils@3.3.3:
-    resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
+  /jsx-ast-utils@3.3.5:
+    resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
     engines: {node: '>=4.0'}
     dependencies:
-      array-includes: 3.1.6
+      array-includes: 3.1.7
+      array.prototype.flat: 1.3.2
       object.assign: 4.1.4
+      object.values: 1.1.7
     dev: true
 
   /jwa@1.4.1:
     resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==}
     dependencies:
@@ -10088,10 +10316,16 @@ packages:
 
   /keen-slider@6.8.6:
     resolution: {integrity: sha512-dcEQ7GDBpCjUQA8XZeWh3oBBLLmyn8aoeIQFGL/NTVkoEOsmlnXqA4QykUm/SncolAZYGsEk/PfUhLZ7mwMM2w==}
     dev: false
 
+  /keyv@4.5.4:
+    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+    dependencies:
+      json-buffer: 3.0.1
+    dev: true
+
   /kind-of@3.2.2:
     resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==}
     engines: {node: '>=0.10.0'}
     dependencies:
       is-buffer: 1.1.6
@@ -10130,20 +10364,20 @@ packages:
 
   /lexorank@1.0.5:
     resolution: {integrity: sha512-K1B/Yr/gIU0wm68hk/yB0p/mv6xM3ShD5aci42vOwcjof8slG8Kpo3Q7+1WTv7DaRHKWRgLPqrFDt+4GtuFAtA==}
     dev: false
 
-  /lib0@0.2.78:
-    resolution: {integrity: sha512-SV2nU43/6eaYnGH3l0lg2wg1ziB/TH3sAd2E8quXPGwrqo+aX98SNT2ZKucpUr5B8A52jD7ZMjAl+r87Fa/bLQ==}
+  /lib0@0.2.86:
+    resolution: {integrity: sha512-kxigQTM4Q7NwJkEgdqQvU21qiR37twcqqLmh+/SbiGbRLfPlLVbHyY9sWp7PwXh0Xus9ELDSjsUOwcrdt5yZ4w==}
     engines: {node: '>=16'}
     hasBin: true
     dependencies:
       isomorphic.js: 0.2.5
     dev: false
 
-  /light-my-request@5.10.0:
-    resolution: {integrity: sha512-ZU2D9GmAcOUculTTdH9/zryej6n8TzT+fNGdNtm6SDp5MMMpHrJJkvAdE3c6d8d2chE9i+a//dS9CWZtisknqA==}
+  /light-my-request@5.11.0:
+    resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==}
     dependencies:
       cookie: 0.5.0
       process-warning: 2.2.0
       set-cookie-parser: 2.6.0
     dev: false
@@ -10213,23 +10447,52 @@ packages:
 
   /lodash.get@4.4.2:
     resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
     dev: true
 
+  /lodash.includes@4.3.0:
+    resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
+    dev: false
+
   /lodash.isarguments@3.1.0:
     resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
     dev: false
 
+  /lodash.isboolean@3.0.3:
+    resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
+    dev: false
+
+  /lodash.isinteger@4.0.4:
+    resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
+    dev: false
+
+  /lodash.isnumber@3.0.3:
+    resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
+    dev: false
+
+  /lodash.isplainobject@4.0.6:
+    resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+    dev: false
+
+  /lodash.isstring@4.0.1:
+    resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
+    dev: false
+
   /lodash.merge@4.6.2:
     resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
 
+  /lodash.once@4.1.1:
+    resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
+    dev: false
+
   /lodash.zip@4.2.0:
     resolution: {integrity: sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==}
     dev: true
 
   /lodash@4.17.21:
     resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+    dev: true
 
   /log-symbols@4.1.0:
     resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
     engines: {node: '>=10'}
     dependencies:
@@ -10252,12 +10515,12 @@ packages:
     hasBin: true
     dependencies:
       js-tokens: 4.0.0
     dev: false
 
-  /lru-cache@10.0.0:
-    resolution: {integrity: sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==}
+  /lru-cache@10.0.1:
+    resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==}
     engines: {node: 14 || >=16.14}
     dev: false
 
   /lru-cache@5.1.1:
     resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
@@ -10268,41 +10531,34 @@ packages:
     resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
     engines: {node: '>=10'}
     dependencies:
       yallist: 4.0.0
 
-  /lru-cache@9.1.2:
-    resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==}
-    engines: {node: 14 || >=16.14}
-    dev: false
-
   /magic-string@0.27.0:
     resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
     engines: {node: '>=12'}
     dependencies:
       '@jridgewell/sourcemap-codec': 1.4.15
     dev: true
 
-  /magic-string@0.30.1:
-    resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==}
-    engines: {node: '>=12'}
-    dependencies:
-      '@jridgewell/sourcemap-codec': 1.4.15
-    dev: true
-
-  /magic-string@0.30.3:
-    resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==}
+  /magic-string@0.30.4:
+    resolution: {integrity: sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==}
     engines: {node: '>=12'}
     dependencies:
       '@jridgewell/sourcemap-codec': 1.4.15
 
   /make-error@1.3.6:
     resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
     dev: false
 
-  /markdown-it@13.0.1:
-    resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==}
+  /markdown-extensions@1.1.1:
+    resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==}
+    engines: {node: '>=0.10.0'}
+    dev: false
+
+  /markdown-it@13.0.2:
+    resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
     hasBin: true
     dependencies:
       argparse: 2.0.1
       entities: 3.0.1
       linkify-it: 4.0.1
@@ -10334,34 +10590,43 @@ packages:
     dev: false
 
   /mdast-util-definitions@5.1.2:
     resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==}
     dependencies:
-      '@types/mdast': 3.0.11
-      '@types/unist': 2.0.6
+      '@types/mdast': 3.0.13
+      '@types/unist': 2.0.8
       unist-util-visit: 4.1.2
 
   /mdast-util-definitions@6.0.0:
     resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==}
     dependencies:
-      '@types/mdast': 4.0.0
+      '@types/mdast': 4.0.1
       '@types/unist': 3.0.0
       unist-util-visit: 5.0.0
 
   /mdast-util-find-and-replace@2.2.2:
     resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       escape-string-regexp: 5.0.0
       unist-util-is: 5.2.1
       unist-util-visit-parents: 5.1.3
 
+  /mdast-util-find-and-replace@3.0.1:
+    resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      escape-string-regexp: 5.0.0
+      unist-util-is: 6.0.0
+      unist-util-visit-parents: 6.0.1
+    dev: false
+
   /mdast-util-from-markdown@1.3.1:
     resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==}
     dependencies:
-      '@types/mdast': 3.0.11
-      '@types/unist': 2.0.6
+      '@types/mdast': 3.0.13
+      '@types/unist': 2.0.8
       decode-named-character-reference: 1.0.2
       mdast-util-to-string: 3.2.0
       micromark: 3.2.0
       micromark-util-decode-numeric-character-reference: 1.1.0
       micromark-util-decode-string: 1.1.0
@@ -10371,47 +10636,134 @@ packages:
       unist-util-stringify-position: 3.0.3
       uvu: 0.5.6
     transitivePeerDependencies:
       - supports-color
 
+  /mdast-util-from-markdown@2.0.0:
+    resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      '@types/unist': 3.0.0
+      decode-named-character-reference: 1.0.2
+      devlop: 1.1.0
+      mdast-util-to-string: 4.0.0
+      micromark: 4.0.0
+      micromark-util-decode-numeric-character-reference: 2.0.0
+      micromark-util-decode-string: 2.0.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+      unist-util-stringify-position: 4.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-frontmatter@2.0.1:
+    resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      devlop: 1.1.0
+      escape-string-regexp: 5.0.0
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+      micromark-extension-frontmatter: 2.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /mdast-util-gfm-autolink-literal@1.0.3:
     resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       ccount: 2.0.1
       mdast-util-find-and-replace: 2.2.2
       micromark-util-character: 1.2.0
 
+  /mdast-util-gfm-autolink-literal@2.0.0:
+    resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      ccount: 2.0.1
+      devlop: 1.1.0
+      mdast-util-find-and-replace: 3.0.1
+      micromark-util-character: 2.0.1
+    dev: false
+
   /mdast-util-gfm-footnote@1.0.2:
     resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       mdast-util-to-markdown: 1.5.0
       micromark-util-normalize-identifier: 1.1.0
 
+  /mdast-util-gfm-footnote@2.0.0:
+    resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+      micromark-util-normalize-identifier: 2.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /mdast-util-gfm-strikethrough@1.0.3:
     resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       mdast-util-to-markdown: 1.5.0
 
+  /mdast-util-gfm-strikethrough@2.0.0:
+    resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /mdast-util-gfm-table@1.0.7:
     resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       markdown-table: 3.0.3
       mdast-util-from-markdown: 1.3.1
       mdast-util-to-markdown: 1.5.0
     transitivePeerDependencies:
       - supports-color
 
+  /mdast-util-gfm-table@2.0.0:
+    resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      devlop: 1.1.0
+      markdown-table: 3.0.3
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /mdast-util-gfm-task-list-item@1.0.2:
     resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       mdast-util-to-markdown: 1.5.0
 
+  /mdast-util-gfm-task-list-item@2.0.0:
+    resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /mdast-util-gfm@2.0.2:
     resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==}
     dependencies:
       mdast-util-from-markdown: 1.3.1
       mdast-util-gfm-autolink-literal: 1.0.3
@@ -10421,44 +10773,214 @@ packages:
       mdast-util-gfm-task-list-item: 1.0.2
       mdast-util-to-markdown: 1.5.0
     transitivePeerDependencies:
       - supports-color
 
+  /mdast-util-gfm@3.0.0:
+    resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==}
+    dependencies:
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-gfm-autolink-literal: 2.0.0
+      mdast-util-gfm-footnote: 2.0.0
+      mdast-util-gfm-strikethrough: 2.0.0
+      mdast-util-gfm-table: 2.0.0
+      mdast-util-gfm-task-list-item: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdx-expression@1.3.2:
+    resolution: {integrity: sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 2.3.6
+      '@types/mdast': 3.0.13
+      mdast-util-from-markdown: 1.3.1
+      mdast-util-to-markdown: 1.5.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdx-expression@2.0.0:
+    resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 3.0.1
+      '@types/mdast': 4.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdx-jsx@2.1.4:
+    resolution: {integrity: sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 2.3.6
+      '@types/mdast': 3.0.13
+      '@types/unist': 2.0.8
+      ccount: 2.0.1
+      mdast-util-from-markdown: 1.3.1
+      mdast-util-to-markdown: 1.5.0
+      parse-entities: 4.0.1
+      stringify-entities: 4.0.3
+      unist-util-remove-position: 4.0.2
+      unist-util-stringify-position: 3.0.3
+      vfile-message: 3.1.4
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdx-jsx@3.0.0:
+    resolution: {integrity: sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 3.0.1
+      '@types/mdast': 4.0.1
+      '@types/unist': 3.0.0
+      ccount: 2.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+      parse-entities: 4.0.1
+      stringify-entities: 4.0.3
+      unist-util-remove-position: 5.0.0
+      unist-util-stringify-position: 4.0.0
+      vfile-message: 4.0.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdx@2.0.1:
+    resolution: {integrity: sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==}
+    dependencies:
+      mdast-util-from-markdown: 1.3.1
+      mdast-util-mdx-expression: 1.3.2
+      mdast-util-mdx-jsx: 2.1.4
+      mdast-util-mdxjs-esm: 1.3.1
+      mdast-util-to-markdown: 1.5.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdx@3.0.0:
+    resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
+    dependencies:
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-mdx-expression: 2.0.0
+      mdast-util-mdx-jsx: 3.0.0
+      mdast-util-mdxjs-esm: 2.0.1
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdxjs-esm@1.3.1:
+    resolution: {integrity: sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 2.3.6
+      '@types/mdast': 3.0.13
+      mdast-util-from-markdown: 1.3.1
+      mdast-util-to-markdown: 1.5.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
+  /mdast-util-mdxjs-esm@2.0.1:
+    resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+    dependencies:
+      '@types/estree-jsx': 1.0.1
+      '@types/hast': 3.0.1
+      '@types/mdast': 4.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.0
+      mdast-util-to-markdown: 2.1.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /mdast-util-phrasing@3.0.1:
     resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       unist-util-is: 5.2.1
 
+  /mdast-util-phrasing@4.0.0:
+    resolution: {integrity: sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      unist-util-is: 6.0.0
+    dev: false
+
   /mdast-util-to-hast@12.3.0:
     resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==}
     dependencies:
-      '@types/hast': 2.3.4
-      '@types/mdast': 3.0.11
+      '@types/hast': 2.3.6
+      '@types/mdast': 3.0.13
       mdast-util-definitions: 5.1.2
       micromark-util-sanitize-uri: 1.2.0
       trim-lines: 3.0.1
       unist-util-generated: 2.0.1
       unist-util-position: 4.0.4
       unist-util-visit: 4.1.2
 
+  /mdast-util-to-hast@13.0.2:
+    resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==}
+    dependencies:
+      '@types/hast': 3.0.1
+      '@types/mdast': 4.0.1
+      '@ungap/structured-clone': 1.2.0
+      devlop: 1.1.0
+      micromark-util-sanitize-uri: 2.0.0
+      trim-lines: 3.0.1
+      unist-util-position: 5.0.0
+      unist-util-visit: 5.0.0
+    dev: false
+
   /mdast-util-to-markdown@1.5.0:
     resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==}
     dependencies:
-      '@types/mdast': 3.0.11
-      '@types/unist': 2.0.6
+      '@types/mdast': 3.0.13
+      '@types/unist': 2.0.8
       longest-streak: 3.1.0
       mdast-util-phrasing: 3.0.1
       mdast-util-to-string: 3.2.0
       micromark-util-decode-string: 1.1.0
       unist-util-visit: 4.1.2
       zwitch: 2.0.4
 
+  /mdast-util-to-markdown@2.1.0:
+    resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      '@types/unist': 3.0.0
+      longest-streak: 3.1.0
+      mdast-util-phrasing: 4.0.0
+      mdast-util-to-string: 4.0.0
+      micromark-util-decode-string: 2.0.0
+      unist-util-visit: 5.0.0
+      zwitch: 2.0.4
+    dev: false
+
   /mdast-util-to-string@3.2.0:
     resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
+
+  /mdast-util-to-string@4.0.0:
+    resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+    dependencies:
+      '@types/mdast': 4.0.1
+    dev: false
+
+  /mdn-data@2.0.14:
+    resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
+    dev: false
 
   /mdn-data@2.0.30:
     resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
 
   /mdurl@1.0.1:
@@ -10514,18 +11036,57 @@ packages:
       micromark-util-subtokenize: 1.1.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-core-commonmark@2.0.0:
+    resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==}
+    dependencies:
+      decode-named-character-reference: 1.0.2
+      devlop: 1.1.0
+      micromark-factory-destination: 2.0.0
+      micromark-factory-label: 2.0.0
+      micromark-factory-space: 2.0.0
+      micromark-factory-title: 2.0.0
+      micromark-factory-whitespace: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-chunked: 2.0.0
+      micromark-util-classify-character: 2.0.0
+      micromark-util-html-tag-name: 2.0.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-resolve-all: 2.0.0
+      micromark-util-subtokenize: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
+  /micromark-extension-frontmatter@2.0.0:
+    resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==}
+    dependencies:
+      fault: 2.0.1
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm-autolink-literal@1.0.5:
     resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==}
     dependencies:
       micromark-util-character: 1.2.0
       micromark-util-sanitize-uri: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-extension-gfm-autolink-literal@2.0.0:
+    resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==}
+    dependencies:
+      micromark-util-character: 2.0.1
+      micromark-util-sanitize-uri: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm-footnote@1.1.2:
     resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==}
     dependencies:
       micromark-core-commonmark: 1.1.0
       micromark-factory-space: 1.1.0
@@ -10534,43 +11095,93 @@ packages:
       micromark-util-sanitize-uri: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-extension-gfm-footnote@2.0.0:
+    resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-core-commonmark: 2.0.0
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-sanitize-uri: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm-strikethrough@1.0.7:
     resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==}
     dependencies:
       micromark-util-chunked: 1.1.0
       micromark-util-classify-character: 1.1.0
       micromark-util-resolve-all: 1.1.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-extension-gfm-strikethrough@2.0.0:
+    resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-chunked: 2.0.0
+      micromark-util-classify-character: 2.0.0
+      micromark-util-resolve-all: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm-table@1.0.7:
     resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==}
     dependencies:
       micromark-factory-space: 1.1.0
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-extension-gfm-table@2.0.0:
+    resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm-tagfilter@1.0.2:
     resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==}
     dependencies:
       micromark-util-types: 1.1.0
 
+  /micromark-extension-gfm-tagfilter@2.0.0:
+    resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+    dependencies:
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm-task-list-item@1.0.5:
     resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==}
     dependencies:
       micromark-factory-space: 1.1.0
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-extension-gfm-task-list-item@2.0.1:
+    resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-extension-gfm@2.0.3:
     resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==}
     dependencies:
       micromark-extension-gfm-autolink-literal: 1.0.5
       micromark-extension-gfm-footnote: 1.1.2
@@ -10579,125 +11190,442 @@ packages:
       micromark-extension-gfm-tagfilter: 1.0.2
       micromark-extension-gfm-task-list-item: 1.0.5
       micromark-util-combine-extensions: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-extension-gfm@3.0.0:
+    resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+    dependencies:
+      micromark-extension-gfm-autolink-literal: 2.0.0
+      micromark-extension-gfm-footnote: 2.0.0
+      micromark-extension-gfm-strikethrough: 2.0.0
+      micromark-extension-gfm-table: 2.0.0
+      micromark-extension-gfm-tagfilter: 2.0.0
+      micromark-extension-gfm-task-list-item: 2.0.1
+      micromark-util-combine-extensions: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
+  /micromark-extension-mdx-expression@1.0.8:
+    resolution: {integrity: sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==}
+    dependencies:
+      '@types/estree': 1.0.2
+      micromark-factory-mdx-expression: 1.0.9
+      micromark-factory-space: 1.1.0
+      micromark-util-character: 1.2.0
+      micromark-util-events-to-acorn: 1.2.3
+      micromark-util-symbol: 1.1.0
+      micromark-util-types: 1.1.0
+      uvu: 0.5.6
+    dev: false
+
+  /micromark-extension-mdx-expression@2.0.0:
+    resolution: {integrity: sha512-hUI6PJCCVaymBF5paL29sOpcbtVXtumDdJgBDxN+tbHlXAqQwNl4EhhJfx4fe7bUpEZzcFRIBAeOiGq7hsZBXw==}
+    dependencies:
+      '@types/estree': 1.0.2
+      devlop: 1.1.0
+      micromark-factory-mdx-expression: 2.0.1
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-events-to-acorn: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
+  /micromark-extension-mdx-jsx@1.0.5:
+    resolution: {integrity: sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==}
+    dependencies:
+      '@types/acorn': 4.0.6
+      '@types/estree': 1.0.2
+      estree-util-is-identifier-name: 2.1.0
+      micromark-factory-mdx-expression: 1.0.9
+      micromark-factory-space: 1.1.0
+      micromark-util-character: 1.2.0
+      micromark-util-symbol: 1.1.0
+      micromark-util-types: 1.1.0
+      uvu: 0.5.6
+      vfile-message: 3.1.4
+    dev: false
+
+  /micromark-extension-mdx-jsx@2.0.0:
+    resolution: {integrity: sha512-hp6ff4eympWcq3Jh9XIJmJPNpM2RNmBjz5vvU1YkND7h4UwjSZas7lXSrAJjtTG7Z56JMMTyowwcbPkAjZmwMg==}
+    dependencies:
+      '@types/acorn': 4.0.6
+      '@types/estree': 1.0.2
+      devlop: 1.1.0
+      estree-util-is-identifier-name: 2.1.0
+      micromark-factory-mdx-expression: 2.0.1
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+      vfile-message: 4.0.2
+    dev: false
+
+  /micromark-extension-mdx-md@1.0.1:
+    resolution: {integrity: sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==}
+    dependencies:
+      micromark-util-types: 1.1.0
+    dev: false
+
+  /micromark-extension-mdx-md@2.0.0:
+    resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
+    dependencies:
+      micromark-util-types: 2.0.0
+    dev: false
+
+  /micromark-extension-mdxjs-esm@1.0.5:
+    resolution: {integrity: sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==}
+    dependencies:
+      '@types/estree': 1.0.2
+      micromark-core-commonmark: 1.1.0
+      micromark-util-character: 1.2.0
+      micromark-util-events-to-acorn: 1.2.3
+      micromark-util-symbol: 1.1.0
+      micromark-util-types: 1.1.0
+      unist-util-position-from-estree: 1.1.2
+      uvu: 0.5.6
+      vfile-message: 3.1.4
+    dev: false
+
+  /micromark-extension-mdxjs-esm@2.0.1:
+    resolution: {integrity: sha512-HLPrY5XLYzFtG5KxEcZXfUV/SOy9Eu3R+dnpP1P6ko/ZO9xceGxmgJOAMq4r/rPLrHaEosfhNIOXDcvFSkVfKQ==}
+    dependencies:
+      '@types/estree': 1.0.2
+      devlop: 1.1.0
+      micromark-core-commonmark: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-events-to-acorn: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+      unist-util-position-from-estree: 2.0.0
+      vfile-message: 4.0.2
+    dev: false
+
+  /micromark-extension-mdxjs@1.0.1:
+    resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==}
+    dependencies:
+      acorn: 8.10.0
+      acorn-jsx: 5.3.2(acorn@8.10.0)
+      micromark-extension-mdx-expression: 1.0.8
+      micromark-extension-mdx-jsx: 1.0.5
+      micromark-extension-mdx-md: 1.0.1
+      micromark-extension-mdxjs-esm: 1.0.5
+      micromark-util-combine-extensions: 1.1.0
+      micromark-util-types: 1.1.0
+    dev: false
+
+  /micromark-extension-mdxjs@2.0.0:
+    resolution: {integrity: sha512-cICbQUdcgFvfg3JH9XTqZoa1ONCZI0GsiOvl9672Ka3SilIo9kMmaKLdSd/QrDgNGxrirWtZfFh19DSKJUivWQ==}
+    dependencies:
+      acorn: 8.10.0
+      acorn-jsx: 5.3.2(acorn@8.10.0)
+      micromark-extension-mdx-expression: 2.0.0
+      micromark-extension-mdx-jsx: 2.0.0
+      micromark-extension-mdx-md: 2.0.0
+      micromark-extension-mdxjs-esm: 2.0.1
+      micromark-util-combine-extensions: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-factory-destination@1.1.0:
     resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==}
     dependencies:
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-factory-destination@2.0.0:
+    resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
+    dependencies:
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-factory-label@1.1.0:
     resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==}
     dependencies:
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-factory-label@2.0.0:
+    resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
+  /micromark-factory-mdx-expression@1.0.9:
+    resolution: {integrity: sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==}
+    dependencies:
+      '@types/estree': 1.0.2
+      micromark-util-character: 1.2.0
+      micromark-util-events-to-acorn: 1.2.3
+      micromark-util-symbol: 1.1.0
+      micromark-util-types: 1.1.0
+      unist-util-position-from-estree: 1.1.2
+      uvu: 0.5.6
+      vfile-message: 3.1.4
+    dev: false
+
+  /micromark-factory-mdx-expression@2.0.1:
+    resolution: {integrity: sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==}
+    dependencies:
+      '@types/estree': 1.0.2
+      devlop: 1.1.0
+      micromark-util-character: 2.0.1
+      micromark-util-events-to-acorn: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+      unist-util-position-from-estree: 2.0.0
+      vfile-message: 4.0.2
+    dev: false
+
   /micromark-factory-space@1.1.0:
     resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==}
     dependencies:
       micromark-util-character: 1.2.0
       micromark-util-types: 1.1.0
 
+  /micromark-factory-space@2.0.0:
+    resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==}
+    dependencies:
+      micromark-util-character: 2.0.1
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-factory-title@1.1.0:
     resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==}
     dependencies:
       micromark-factory-space: 1.1.0
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-factory-title@2.0.0:
+    resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==}
+    dependencies:
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-factory-whitespace@1.1.0:
     resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==}
     dependencies:
       micromark-factory-space: 1.1.0
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-factory-whitespace@2.0.0:
+    resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==}
+    dependencies:
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-util-character@1.2.0:
     resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==}
     dependencies:
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-util-character@2.0.1:
+    resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-util-chunked@1.1.0:
     resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==}
     dependencies:
       micromark-util-symbol: 1.1.0
 
+  /micromark-util-chunked@2.0.0:
+    resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+    dev: false
+
   /micromark-util-classify-character@1.1.0:
     resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==}
     dependencies:
       micromark-util-character: 1.2.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-util-classify-character@2.0.0:
+    resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==}
+    dependencies:
+      micromark-util-character: 2.0.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-util-combine-extensions@1.1.0:
     resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==}
     dependencies:
       micromark-util-chunked: 1.1.0
       micromark-util-types: 1.1.0
 
+  /micromark-util-combine-extensions@2.0.0:
+    resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==}
+    dependencies:
+      micromark-util-chunked: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-util-decode-numeric-character-reference@1.1.0:
     resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==}
     dependencies:
       micromark-util-symbol: 1.1.0
 
+  /micromark-util-decode-numeric-character-reference@2.0.0:
+    resolution: {integrity: sha512-pIgcsGxpHEtTG/rPJRz/HOLSqp5VTuIIjXlPI+6JSDlK2oljApusG6KzpS8AF0ENUMCHlC/IBb5B9xdFiVlm5Q==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+    dev: false
+
   /micromark-util-decode-string@1.1.0:
     resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==}
     dependencies:
       decode-named-character-reference: 1.0.2
       micromark-util-character: 1.2.0
       micromark-util-decode-numeric-character-reference: 1.1.0
       micromark-util-symbol: 1.1.0
 
+  /micromark-util-decode-string@2.0.0:
+    resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==}
+    dependencies:
+      decode-named-character-reference: 1.0.2
+      micromark-util-character: 2.0.1
+      micromark-util-decode-numeric-character-reference: 2.0.0
+      micromark-util-symbol: 2.0.0
+    dev: false
+
   /micromark-util-encode@1.1.0:
     resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==}
 
+  /micromark-util-encode@2.0.0:
+    resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==}
+    dev: false
+
+  /micromark-util-events-to-acorn@1.2.3:
+    resolution: {integrity: sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==}
+    dependencies:
+      '@types/acorn': 4.0.6
+      '@types/estree': 1.0.2
+      '@types/unist': 2.0.8
+      estree-util-visit: 1.2.1
+      micromark-util-symbol: 1.1.0
+      micromark-util-types: 1.1.0
+      uvu: 0.5.6
+      vfile-message: 3.1.4
+    dev: false
+
+  /micromark-util-events-to-acorn@2.0.1:
+    resolution: {integrity: sha512-3pf0pxvFaTxzTwisMHmEk5lnW7oSU/oRZxpZcrdx/voJgCpPaspexc89mJodW4ekATo1UILtZvjESclKONSB6w==}
+    dependencies:
+      '@types/acorn': 4.0.6
+      '@types/estree': 1.0.2
+      '@types/unist': 3.0.0
+      devlop: 1.1.0
+      estree-util-visit: 1.2.1
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+      vfile-message: 4.0.2
+    dev: false
+
   /micromark-util-html-tag-name@1.2.0:
     resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==}
 
+  /micromark-util-html-tag-name@2.0.0:
+    resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==}
+    dev: false
+
   /micromark-util-normalize-identifier@1.1.0:
     resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==}
     dependencies:
       micromark-util-symbol: 1.1.0
 
+  /micromark-util-normalize-identifier@2.0.0:
+    resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==}
+    dependencies:
+      micromark-util-symbol: 2.0.0
+    dev: false
+
   /micromark-util-resolve-all@1.1.0:
     resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==}
     dependencies:
       micromark-util-types: 1.1.0
 
+  /micromark-util-resolve-all@2.0.0:
+    resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==}
+    dependencies:
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-util-sanitize-uri@1.2.0:
     resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==}
     dependencies:
       micromark-util-character: 1.2.0
       micromark-util-encode: 1.1.0
       micromark-util-symbol: 1.1.0
 
+  /micromark-util-sanitize-uri@2.0.0:
+    resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==}
+    dependencies:
+      micromark-util-character: 2.0.1
+      micromark-util-encode: 2.0.0
+      micromark-util-symbol: 2.0.0
+    dev: false
+
   /micromark-util-subtokenize@1.1.0:
     resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==}
     dependencies:
       micromark-util-chunked: 1.1.0
       micromark-util-symbol: 1.1.0
       micromark-util-types: 1.1.0
       uvu: 0.5.6
 
+  /micromark-util-subtokenize@2.0.0:
+    resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==}
+    dependencies:
+      devlop: 1.1.0
+      micromark-util-chunked: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    dev: false
+
   /micromark-util-symbol@1.1.0:
     resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==}
 
+  /micromark-util-symbol@2.0.0:
+    resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==}
+    dev: false
+
   /micromark-util-types@1.1.0:
     resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==}
 
+  /micromark-util-types@2.0.0:
+    resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==}
+    dev: false
+
   /micromark@3.2.0:
     resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==}
     dependencies:
-      '@types/debug': 4.1.8
+      '@types/debug': 4.1.9
       debug: 4.3.4
       decode-named-character-reference: 1.0.2
       micromark-core-commonmark: 1.1.0
       micromark-factory-space: 1.1.0
       micromark-util-character: 1.2.0
@@ -10713,10 +11641,34 @@ packages:
       micromark-util-types: 1.1.0
       uvu: 0.5.6
     transitivePeerDependencies:
       - supports-color
 
+  /micromark@4.0.0:
+    resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==}
+    dependencies:
+      '@types/debug': 4.1.9
+      debug: 4.3.4
+      decode-named-character-reference: 1.0.2
+      devlop: 1.1.0
+      micromark-core-commonmark: 2.0.0
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.0.1
+      micromark-util-chunked: 2.0.0
+      micromark-util-combine-extensions: 2.0.0
+      micromark-util-decode-numeric-character-reference: 2.0.0
+      micromark-util-encode: 2.0.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-resolve-all: 2.0.0
+      micromark-util-sanitize-uri: 2.0.0
+      micromark-util-subtokenize: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /micromatch@4.0.5:
     resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
     engines: {node: '>=8.6'}
     dependencies:
       braces: 3.0.2
@@ -10790,12 +11742,12 @@ packages:
     dev: false
 
   /minimist@1.2.8:
     resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
 
-  /minipass@6.0.2:
-    resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==}
+  /minipass@7.0.4:
+    resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
     engines: {node: '>=16 || 14 >=14.17'}
     dev: false
 
   /minisearch@6.1.0:
     resolution: {integrity: sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==}
@@ -10809,58 +11761,50 @@ packages:
     hasBin: true
     dependencies:
       minimist: 1.2.8
     dev: false
 
-  /mkdist@1.2.0(typescript@5.2.2):
-    resolution: {integrity: sha512-UTqu/bXmIk/+VKNVgufAeMyjUcNy1dn9Bl7wL1zZlCKVrpDgj/VllmZBeh3ZCC/2HWqUrt6frNFTKt9TRZbNvQ==}
+  /mkdist@1.3.0(typescript@5.2.2):
+    resolution: {integrity: sha512-ZQrUvcL7LkRdzMREpDyg9AT18N9Tl5jc2qeKAUeEw0KGsgykbHbuRvysGAzTuGtwuSg0WQyNit5jh/k+Er3JEg==}
     hasBin: true
     peerDependencies:
-      sass: ^1.60.0
-      typescript: '>=4.9.5'
+      sass: ^1.63.6
+      typescript: '>=5.1.6'
     peerDependenciesMeta:
       sass:
         optional: true
       typescript:
         optional: true
     dependencies:
+      citty: 0.1.4
       defu: 6.1.2
-      esbuild: 0.17.19
+      esbuild: 0.18.16
       fs-extra: 11.1.1
-      globby: 13.1.4
-      jiti: 1.19.3
+      globby: 13.2.2
+      jiti: 1.20.0
       mlly: 1.4.2
       mri: 1.2.0
       pathe: 1.1.1
       typescript: 5.2.2
     dev: true
 
-  /mlly@1.3.0:
-    resolution: {integrity: sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==}
-    dependencies:
-      acorn: 8.10.0
-      pathe: 1.1.1
-      pkg-types: 1.0.3
-      ufo: 1.3.0
-    dev: true
-
   /mlly@1.4.2:
     resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==}
     dependencies:
       acorn: 8.10.0
       pathe: 1.1.1
       pkg-types: 1.0.3
-      ufo: 1.3.0
+      ufo: 1.3.1
 
   /mnemonist@0.39.5:
     resolution: {integrity: sha512-FPUtkhtJ0efmEFGpU14x7jGbTB+s18LrzRL2KgoWz9YvcY3cPomz8tih01GbHwnGk/OmkOKfqd/RAQoc8Lm7DQ==}
     dependencies:
       obliterator: 2.0.4
     dev: false
 
-  /monaco-editor@0.40.0:
-    resolution: {integrity: sha512-1wymccLEuFSMBvCk/jT1YDW/GuxMLYwnFwF9CDyYCxoTw2Pt379J3FUhwy9c43j51JdcxVPjwk0jm0EVDsBS2g==}
+  /monaco-editor@0.43.0:
+    resolution: {integrity: sha512-cnoqwQi/9fml2Szamv1XbSJieGJ1Dc8tENVMD26Kcfl7xGQWp7OBKMjlwKVGYFJ3/AXJjSOGvcqK7Ry/j9BM1Q==}
     dev: false
 
   /mongodb-connection-string-url@2.6.0:
     resolution: {integrity: sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==}
     dependencies:
@@ -10887,11 +11831,11 @@ packages:
       mongodb-client-encryption:
         optional: true
       snappy:
         optional: true
     dependencies:
-      bson: 5.4.0
+      bson: 5.5.0
       mongodb-connection-string-url: 2.6.0
       socks: 2.7.1
     optionalDependencies:
       saslprep: 1.0.3
     dev: false
@@ -10955,11 +11899,11 @@ packages:
     engines: {node: '>= 4.4.x'}
     hasBin: true
     dependencies:
       debug: 3.2.7
       iconv-lite: 0.4.24
-      sax: 1.2.4
+      sax: 1.3.0
     transitivePeerDependencies:
       - supports-color
 
   /negotiator@0.6.3:
     resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
@@ -10978,11 +11922,11 @@ packages:
       typescript: 5.2.2
 
   /nlcst-to-string@3.1.1:
     resolution: {integrity: sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==}
     dependencies:
-      '@types/nlcst': 1.0.0
+      '@types/nlcst': 1.0.2
 
   /node-abi@3.47.0:
     resolution: {integrity: sha512-2s6B2CWZM//kPgwnuI0KrYwNjfdByE25zvAaEpq9IH4zcNsarH8Ihu/UuX6XMPEogDAxkuUFeZn60pXNHAqn3A==}
     engines: {node: '>=10'}
     dependencies:
@@ -10997,25 +11941,34 @@ packages:
     dev: false
 
   /node-fetch-native@1.4.0:
     resolution: {integrity: sha512-F5kfEj95kX8tkDhUCYdV8dg3/8Olx/94zB8+ZNthFs6Bz31UpUi8Xh40TN3thLwXgrwXry1pEg9lJ++tLWTcqA==}
 
-  /node-fetch@2.6.12:
-    resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==}
+  /node-fetch@2.7.0:
+    resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
     engines: {node: 4.x || >=6.0.0}
     peerDependencies:
       encoding: ^0.1.0
     peerDependenciesMeta:
       encoding:
         optional: true
     dependencies:
       whatwg-url: 5.0.0
     dev: false
 
-  /node-mocks-http@1.12.2:
-    resolution: {integrity: sha512-xhWwC0dh35R9rf0j3bRZXuISXdHxxtMx0ywZQBwjrg3yl7KpRETzogfeCamUIjltpn0Fxvs/ZhGJul1vPLrdJQ==}
-    engines: {node: '>=0.6'}
+  /node-fetch@3.3.2:
+    resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    dependencies:
+      data-uri-to-buffer: 4.0.1
+      fetch-blob: 3.2.0
+      formdata-polyfill: 4.0.10
+    dev: false
+
+  /node-mocks-http@1.13.0:
+    resolution: {integrity: sha512-lArD6sJMPJ53WF50GX0nJ89B1nkV1TdMvNwq8WXXFrUXF80ujSyye1T30mgiHh4h2It0/svpF3C4kZ2OAONVlg==}
+    engines: {node: '>=14'}
     dependencies:
       accepts: 1.3.8
       content-disposition: 0.5.4
       depd: 1.1.2
       fresh: 0.5.2
@@ -11045,12 +11998,12 @@ packages:
 
   /normalize-package-data@2.5.0:
     resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
     dependencies:
       hosted-git-info: 2.8.9
-      resolve: 1.22.4
-      semver: 5.7.1
+      resolve: 1.22.6
+      semver: 5.7.2
       validate-npm-package-license: 3.0.4
 
   /normalize-path@3.0.0:
     resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
     engines: {node: '>=0.10.0'}
@@ -11089,11 +12042,11 @@ packages:
   /object.assign@4.1.4:
     resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
+      define-properties: 1.2.1
       has-symbols: 1.0.3
       object-keys: 1.1.1
     dev: true
 
   /object.omit@3.0.0:
@@ -11108,47 +12061,48 @@ packages:
     engines: {node: '>=0.10.0'}
     dependencies:
       isobject: 3.0.1
     dev: false
 
-  /object.values@1.1.6:
-    resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==}
+  /object.values@1.1.7:
+    resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
     dev: true
 
   /obliterator@2.0.4:
     resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==}
     dev: false
 
   /octokit@3.0.0:
     resolution: {integrity: sha512-kcFJmUreomSGA//1KfH7Ci+Xh8XO8yH/GbtTm6R0gB+JyIgjw5qL4DupMSzeTsvByxIBhoXE2PM5ZRXeJa1dDw==}
     engines: {node: '>= 18'}
     dependencies:
-      '@octokit/app': 14.0.0
-      '@octokit/core': 5.0.0
+      '@octokit/app': 14.0.1
+      '@octokit/core': 5.0.1
       '@octokit/oauth-app': 6.0.0
-      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
-      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.0)
-      '@octokit/plugin-retry': 6.0.0(@octokit/core@5.0.0)
-      '@octokit/plugin-throttling': 7.0.0(@octokit/core@5.0.0)
-      '@octokit/request-error': 5.0.0
+      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.1)
+      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.1)
+      '@octokit/plugin-retry': 6.0.1(@octokit/core@5.0.1)
+      '@octokit/plugin-throttling': 7.0.0(@octokit/core@5.0.1)
+      '@octokit/request-error': 5.0.1
       '@octokit/types': 11.1.0
     dev: false
 
   /ofetch@1.3.3:
     resolution: {integrity: sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg==}
     dependencies:
       destr: 2.0.1
       node-fetch-native: 1.4.0
-      ufo: 1.3.0
+      ufo: 1.3.1
 
-  /on-exit-leak-free@2.1.0:
-    resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==}
+  /on-exit-leak-free@2.1.2:
+    resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
+    engines: {node: '>=14.0.0'}
     dev: false
 
   /on-finished@2.4.1:
     resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
     engines: {node: '>= 0.8'}
@@ -11177,12 +12131,12 @@ packages:
     resolution: {integrity: sha512-cQO0c0HF9ZMhSoIEOKMyxbSYwKn6qWBDEdQeCvZnAVwKCxSWj2DV8AwC1J4JCiwZbn/C4grGCJXpvmlAyTXrBg==}
     engines: {node: '>=18.0.0'}
     dependencies:
       chardet: 1.6.0
       cheerio: 1.0.0-rc.12
-      undici: 5.22.1
-      validator: 13.9.0
+      undici: 5.25.4
+      validator: 13.11.0
     dev: false
 
   /open@9.1.0:
     resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==}
     engines: {node: '>=14.16'}
@@ -11194,18 +12148,18 @@ packages:
 
   /openai@4.0.0:
     resolution: {integrity: sha512-UHv70gIw20pxu9tiUueE9iS+4U4eTGiTgQr+zlJ5aX4oj6LUUp+7mBn0xAqilawftwUB/biohPth2vcZFmoNYw==}
     hasBin: true
     dependencies:
-      '@types/node': 18.17.5
-      '@types/node-fetch': 2.6.4
+      '@types/node': 18.18.4
+      '@types/node-fetch': 2.6.6
       abort-controller: 3.0.0
       agentkeepalive: 4.5.0
       digest-fetch: 1.3.0
       form-data-encoder: 1.7.2
       formdata-node: 4.4.1
-      node-fetch: 2.6.12
+      node-fetch: 2.7.0
     transitivePeerDependencies:
       - encoding
     dev: false
 
   /openapi-types@12.1.3:
@@ -11229,11 +12183,11 @@ packages:
     engines: {node: '>=10'}
     dependencies:
       bl: 4.1.0
       chalk: 4.1.2
       cli-cursor: 3.1.0
-      cli-spinners: 2.9.0
+      cli-spinners: 2.9.1
       is-interactive: 1.0.0
       is-unicode-supported: 0.1.0
       log-symbols: 4.1.0
       strip-ansi: 6.0.1
       wcwidth: 1.0.1
@@ -11243,11 +12197,11 @@ packages:
     resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     dependencies:
       chalk: 5.3.0
       cli-cursor: 4.0.0
-      cli-spinners: 2.9.0
+      cli-spinners: 2.9.1
       is-interactive: 2.0.0
       is-unicode-supported: 1.3.0
       log-symbols: 5.1.0
       stdin-discarder: 0.1.0
       strip-ansi: 7.1.0
@@ -11257,11 +12211,11 @@ packages:
     resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==}
     engines: {node: '>=16'}
     dependencies:
       chalk: 5.3.0
       cli-cursor: 4.0.0
-      cli-spinners: 2.9.0
+      cli-spinners: 2.9.1
       is-interactive: 2.0.0
       is-unicode-supported: 1.3.0
       log-symbols: 5.1.0
       stdin-discarder: 0.1.0
       string-width: 6.1.0
@@ -11272,11 +12226,11 @@ packages:
     dev: false
 
   /otpauth@9.1.4:
     resolution: {integrity: sha512-T6T0E1WlzwKWESq8K0Ja47u01XjmDmRY/AiUoMAc6xZI/OsTsD4cqBrfpt2WfJ29W5pRiWkuUuyHdNQl0/Ic+Q==}
     dependencies:
-      jssha: 3.3.0
+      jssha: 3.3.1
     dev: false
 
   /p-limit@2.3.0:
     resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
     engines: {node: '>=6'}
@@ -11321,10 +12275,23 @@ packages:
     engines: {node: '>=6'}
     dependencies:
       callsites: 3.1.0
     dev: true
 
+  /parse-entities@4.0.1:
+    resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==}
+    dependencies:
+      '@types/unist': 2.0.8
+      character-entities: 2.0.2
+      character-entities-legacy: 3.0.0
+      character-reference-invalid: 2.0.1
+      decode-named-character-reference: 1.0.2
+      is-alphanumerical: 2.0.1
+      is-decimal: 2.0.1
+      is-hexadecimal: 2.0.1
+    dev: false
+
   /parse-json@5.2.0:
     resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
     engines: {node: '>=8'}
     dependencies:
       '@babel/code-frame': 7.22.13
@@ -11395,12 +12362,12 @@ packages:
 
   /path-scurry@1.10.1:
     resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
     engines: {node: '>=16 || 14 >=14.17'}
     dependencies:
-      lru-cache: 9.1.2
-      minipass: 6.0.2
+      lru-cache: 10.0.1
+      minipass: 7.0.4
     dev: false
 
   /path-to-regexp@6.2.1:
     resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
 
@@ -11425,10 +12392,18 @@ packages:
     dev: false
 
   /perfect-debounce@1.0.0:
     resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
 
+  /periscopic@3.1.0:
+    resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
+    dependencies:
+      '@types/estree': 1.0.2
+      estree-walker: 3.0.3
+      is-reference: 3.0.2
+    dev: false
+
   /picocolors@1.0.0:
     resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
 
   /picomatch@2.3.1:
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
@@ -11441,36 +12416,36 @@ packages:
 
   /pify@4.0.1:
     resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
     engines: {node: '>=6'}
 
-  /pino-abstract-transport@1.0.0:
-    resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==}
+  /pino-abstract-transport@1.1.0:
+    resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==}
     dependencies:
-      readable-stream: 4.4.0
+      readable-stream: 4.4.2
       split2: 4.2.0
     dev: false
 
-  /pino-std-serializers@6.2.1:
-    resolution: {integrity: sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ==}
+  /pino-std-serializers@6.2.2:
+    resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==}
     dev: false
 
-  /pino@8.14.1:
-    resolution: {integrity: sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==}
+  /pino@8.15.6:
+    resolution: {integrity: sha512-GuxHr61R0ZFD1npu58tB3a3FSVjuy21OwN/haw4OuKiZBL63Pg11Y51WWeD52RENS2mjwPZOwt+2OQOSkck6kQ==}
     hasBin: true
     dependencies:
       atomic-sleep: 1.0.0
-      fast-redact: 3.2.0
-      on-exit-leak-free: 2.1.0
-      pino-abstract-transport: 1.0.0
-      pino-std-serializers: 6.2.1
+      fast-redact: 3.3.0
+      on-exit-leak-free: 2.1.2
+      pino-abstract-transport: 1.1.0
+      pino-std-serializers: 6.2.2
       process-warning: 2.2.0
       quick-format-unescaped: 4.0.4
       real-require: 0.2.0
       safe-stable-stringify: 2.4.3
-      sonic-boom: 3.3.0
-      thread-stream: 2.3.0
+      sonic-boom: 3.6.1
+      thread-stream: 2.4.1
     dev: false
 
   /pkg-dir@4.2.0:
     resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
     engines: {node: '>=8'}
@@ -11512,11 +12487,11 @@ packages:
       postcss: ^8.0.0
     dependencies:
       postcss: 8.4.21
       postcss-value-parser: 4.2.0
       read-cache: 1.0.0
-      resolve: 1.22.4
+      resolve: 1.22.6
     dev: false
 
   /postcss-js@4.0.1(postcss@8.4.21):
     resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
     engines: {node: ^12 || ^14 || >= 16}
@@ -11573,21 +12548,12 @@ packages:
       nanoid: 3.3.6
       picocolors: 1.0.0
       source-map-js: 1.0.2
     dev: false
 
-  /postcss@8.4.26:
-    resolution: {integrity: sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==}
-    engines: {node: ^10 || ^12 || >=14}
-    dependencies:
-      nanoid: 3.3.6
-      picocolors: 1.0.0
-      source-map-js: 1.0.2
-    dev: true
-
-  /postcss@8.4.29:
-    resolution: {integrity: sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==}
+  /postcss@8.4.31:
+    resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
     engines: {node: ^10 || ^12 || >=14}
     dependencies:
       nanoid: 3.3.6
       picocolors: 1.0.0
       source-map-js: 1.0.2
@@ -11608,20 +12574,10 @@ packages:
       rc: 1.2.8
       simple-get: 4.0.1
       tar-fs: 2.1.1
       tunnel-agent: 0.6.0
 
-  /preferred-pm@3.0.3:
-    resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==}
-    engines: {node: '>=10'}
-    dependencies:
-      find-up: 5.0.0
-      find-yarn-workspace-root2: 1.2.16
-      path-exists: 4.0.0
-      which-pm: 2.0.0
-    dev: true
-
   /preferred-pm@3.1.2:
     resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==}
     engines: {node: '>=10'}
     dependencies:
       find-up: 5.0.0
@@ -11643,22 +12599,22 @@ packages:
 
   /prettier-plugin-astro@0.11.0:
     resolution: {integrity: sha512-rl2hJ4Kty/aEfGjk3i4JS+bpng9MjgvwqLRNzeb9NqYhqKoWNwOR39cIJXFjU1vR3zYOPnwWNRMelKb0orunYA==}
     engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'}
     dependencies:
-      '@astrojs/compiler': 1.6.2
+      '@astrojs/compiler': 1.8.2
       prettier: 3.0.2
-      sass-formatter: 0.7.6
+      sass-formatter: 0.7.8
     dev: true
 
   /prettier-plugin-astro@0.9.1:
     resolution: {integrity: sha512-pYZXSbdq0eElvzoIMArzv1SBn1NUXzopjlcnt6Ql8VW32PjC12NovwBjXJ6rh8qQLi7vF8jNqAbraKW03UPfag==}
     engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'}
     dependencies:
       '@astrojs/compiler': 1.8.2
       prettier: 2.8.8
-      sass-formatter: 0.7.6
+      sass-formatter: 0.7.8
       synckit: 0.8.5
 
   /prettier@2.8.8:
     resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
     engines: {node: '>=10.13.0'}
@@ -11672,12 +12628,12 @@ packages:
   /pretty-bytes@5.6.0:
     resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==}
     engines: {node: '>=6'}
     dev: false
 
-  /pretty-bytes@6.1.0:
-    resolution: {integrity: sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==}
+  /pretty-bytes@6.1.1:
+    resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
     engines: {node: ^14.13.1 || >=16.0.0}
     dev: true
 
   /pretty@2.0.0:
     resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==}
@@ -11719,17 +12675,17 @@ packages:
     engines: {node: '>= 6'}
     dependencies:
       kleur: 3.0.3
       sisteransi: 1.0.5
 
-  /property-information@6.2.0:
-    resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==}
+  /property-information@6.3.0:
+    resolution: {integrity: sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg==}
 
   /prosemirror-changeset@2.2.1:
     resolution: {integrity: sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==}
     dependencies:
-      prosemirror-transform: 1.7.3
+      prosemirror-transform: 1.8.0
     dev: false
 
   /prosemirror-collab@1.3.1:
     resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==}
     dependencies:
@@ -11737,139 +12693,136 @@ packages:
     dev: false
 
   /prosemirror-commands@1.5.2:
     resolution: {integrity: sha512-hgLcPaakxH8tu6YvVAaILV2tXYsW3rAdDR8WNkeKGcgeMVQg3/TMhPdVoh7iAmfgVjZGtcOSjKiQaoeKjzd2mQ==}
     dependencies:
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
+      prosemirror-transform: 1.8.0
     dev: false
 
   /prosemirror-dropcursor@1.8.1:
     resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==}
     dependencies:
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
-      prosemirror-view: 1.31.4
+      prosemirror-transform: 1.8.0
+      prosemirror-view: 1.32.0
     dev: false
 
   /prosemirror-gapcursor@1.3.2:
     resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==}
     dependencies:
       prosemirror-keymap: 1.2.2
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-view: 1.31.4
+      prosemirror-view: 1.32.0
     dev: false
 
   /prosemirror-history@1.3.2:
     resolution: {integrity: sha512-/zm0XoU/N/+u7i5zepjmZAEnpvjDtzoPWW6VmKptcAnPadN/SStsBjMImdCEbb3seiNTpveziPTIrXQbHLtU1g==}
     dependencies:
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
-      prosemirror-view: 1.31.4
+      prosemirror-transform: 1.8.0
+      prosemirror-view: 1.32.0
       rope-sequence: 1.3.4
     dev: false
 
   /prosemirror-inputrules@1.2.1:
     resolution: {integrity: sha512-3LrWJX1+ULRh5SZvbIQlwZafOXqp1XuV21MGBu/i5xsztd+9VD15x6OtN6mdqSFI7/8Y77gYUbQ6vwwJ4mr6QQ==}
     dependencies:
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
+      prosemirror-transform: 1.8.0
     dev: false
 
   /prosemirror-keymap@1.2.2:
     resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==}
     dependencies:
       prosemirror-state: 1.4.3
       w3c-keyname: 2.2.8
     dev: false
 
-  /prosemirror-markdown@1.11.0:
-    resolution: {integrity: sha512-yP9mZqPRstjZhhf3yykCQNE3AijxARrHe4e7esV9A+gp4cnGOH4QvrKYPpXLHspNWyvJJ+0URH+iIvV5qP1I2Q==}
+  /prosemirror-markdown@1.11.2:
+    resolution: {integrity: sha512-Eu5g4WPiCdqDTGhdSsG9N6ZjACQRYrsAkrF9KYfdMaCmjIApH75aVncsWYOJvEk2i1B3i8jZppv3J/tnuHGiUQ==}
     dependencies:
-      markdown-it: 13.0.1
-      prosemirror-model: 1.19.2
+      markdown-it: 13.0.2
+      prosemirror-model: 1.19.3
     dev: false
 
-  /prosemirror-menu@1.2.2:
-    resolution: {integrity: sha512-437HIWTq4F9cTX+kPfqZWWm+luJm95Aut/mLUy+9OMrOml0bmWDS26ceC6SNfb2/S94et1sZ186vLO7pDHzxSw==}
+  /prosemirror-menu@1.2.4:
+    resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==}
     dependencies:
       crelt: 1.0.6
       prosemirror-commands: 1.5.2
       prosemirror-history: 1.3.2
       prosemirror-state: 1.4.3
     dev: false
 
-  /prosemirror-model@1.19.2:
-    resolution: {integrity: sha512-RXl0Waiss4YtJAUY3NzKH0xkJmsZupCIccqcIFoLTIKFlKNbIvFDRl27/kQy1FP8iUAxrjRRfIVvOebnnXJgqQ==}
+  /prosemirror-model@1.19.3:
+    resolution: {integrity: sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ==}
     dependencies:
       orderedmap: 2.1.1
     dev: false
 
   /prosemirror-schema-basic@1.2.2:
     resolution: {integrity: sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==}
     dependencies:
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
     dev: false
 
   /prosemirror-schema-list@1.3.0:
     resolution: {integrity: sha512-Hz/7gM4skaaYfRPNgr421CU4GSwotmEwBVvJh5ltGiffUJwm7C8GfN/Bc6DR1EKEp5pDKhODmdXXyi9uIsZl5A==}
     dependencies:
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
+      prosemirror-transform: 1.8.0
     dev: false
 
   /prosemirror-state@1.4.3:
     resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==}
     dependencies:
-      prosemirror-model: 1.19.2
-      prosemirror-transform: 1.7.3
-      prosemirror-view: 1.31.4
+      prosemirror-model: 1.19.3
+      prosemirror-transform: 1.8.0
+      prosemirror-view: 1.32.0
     dev: false
 
-  /prosemirror-tables@1.3.3:
-    resolution: {integrity: sha512-t10hbu4sNDInic3AQYd8ouPN457zVJIhVDqSdqgsVXNoa1watYXBxqNSVrNQoGOFG4Ivreyp3hQE3KG1f9bSpw==}
+  /prosemirror-tables@1.3.4:
+    resolution: {integrity: sha512-z6uLSQ1BLC3rgbGwZmpfb+xkdvD7W/UOsURDfognZFYaTtc0gsk7u/t71Yijp2eLflVpffMk6X0u0+u+MMDvIw==}
     dependencies:
       prosemirror-keymap: 1.2.2
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
-      prosemirror-view: 1.31.4
+      prosemirror-transform: 1.8.0
+      prosemirror-view: 1.32.0
     dev: false
 
-  /prosemirror-trailing-node@2.0.4(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4):
-    resolution: {integrity: sha512-0Yl9w7IdHkaCdqR+NE3FOucePME4OmiGcybnF1iasarEILP5U8+4xTnl53yafULjmwcg1SrSG65Hg7Zk2H2v3g==}
+  /prosemirror-trailing-node@2.0.7(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0):
+    resolution: {integrity: sha512-8zcZORYj/8WEwsGo6yVCRXFMOfBo0Ub3hCUvmoWIZYfMP26WqENU0mpEP27w7mt8buZWuGrydBewr0tOArPb1Q==}
     peerDependencies:
       prosemirror-model: ^1.19.0
       prosemirror-state: ^1.4.2
-      prosemirror-view: ^1.30.2
+      prosemirror-view: ^1.31.2
     dependencies:
-      '@babel/runtime': 7.22.5
-      '@remirror/core-constants': 2.0.1
-      '@remirror/core-helpers': 2.0.3
+      '@remirror/core-constants': 2.0.2
+      '@remirror/core-helpers': 3.0.0
       escape-string-regexp: 4.0.0
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-view: 1.31.4
-    transitivePeerDependencies:
-      - supports-color
+      prosemirror-view: 1.32.0
     dev: false
 
-  /prosemirror-transform@1.7.3:
-    resolution: {integrity: sha512-qDapyx5lqYfxVeUWEw0xTGgeP2S8346QtE7DxkalsXlX89lpzkY6GZfulgfHyk1n4tf74sZ7CcXgcaCcGjsUtA==}
+  /prosemirror-transform@1.8.0:
+    resolution: {integrity: sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==}
     dependencies:
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
     dev: false
 
-  /prosemirror-view@1.31.4:
-    resolution: {integrity: sha512-nJzH2LpYbonSTYFqQ1BUdEhbd1WPN/rp/K9T9qxBEYpgg3jK3BvEUCR45Ymc9IHpO0m3nBJwPm19RBxZdoBVuw==}
+  /prosemirror-view@1.32.0:
+    resolution: {integrity: sha512-HwW7IWgca6ehiW2PA48H/8yl0TakA0Ms5LgN5Krc97oar7GfjIKE/NocUsLe74Jq4mwyWKUNoBljE8WkXKZwng==}
     dependencies:
-      prosemirror-model: 1.19.2
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-transform: 1.7.3
+      prosemirror-transform: 1.8.0
     dev: false
 
   /proto-list@1.2.4:
     resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
     dev: false
@@ -11916,12 +12869,12 @@ packages:
   /quick-lru@5.1.1:
     resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
     engines: {node: '>=10'}
     dev: false
 
-  /radix3@1.0.1:
-    resolution: {integrity: sha512-y+AcwZ3HcUIGc9zGsNVf5+BY/LxL+z+4h4J3/pp8jxSmy1STaCocPS3qrj4tA5ehUSzqtqK+0Aygvz/r/8vy4g==}
+  /radix3@1.1.0:
+    resolution: {integrity: sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==}
     dev: false
 
   /range-parser@1.2.1:
     resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
     engines: {node: '>= 0.6'}
@@ -12008,11 +12961,11 @@ packages:
 
   /read-pkg@5.2.0:
     resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
     engines: {node: '>=8'}
     dependencies:
-      '@types/normalize-package-data': 2.4.1
+      '@types/normalize-package-data': 2.4.2
       normalize-package-data: 2.5.0
       parse-json: 5.2.0
       type-fest: 0.6.0
 
   /read-yaml-file@1.1.0:
@@ -12043,18 +12996,19 @@ packages:
     dependencies:
       inherits: 2.0.4
       string_decoder: 1.3.0
       util-deprecate: 1.0.2
 
-  /readable-stream@4.4.0:
-    resolution: {integrity: sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==}
+  /readable-stream@4.4.2:
+    resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
     dependencies:
       abort-controller: 3.0.0
       buffer: 6.0.3
       events: 3.3.0
       process: 0.11.10
+      string_decoder: 1.3.0
     dev: false
 
   /readable-web-to-node-stream@3.0.2:
     resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==}
     engines: {node: '>=8'}
@@ -12075,11 +13029,11 @@ packages:
 
   /rechoir@0.6.2:
     resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
     engines: {node: '>= 0.10'}
     dependencies:
-      resolve: 1.22.4
+      resolve: 1.22.6
     dev: false
 
   /redis-commands@1.7.0:
     resolution: {integrity: sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==}
     dev: false
@@ -12101,26 +13055,26 @@ packages:
     engines: {node: '>=8.0.0'}
     dependencies:
       bluebird: 3.7.2
     dev: false
 
-  /regenerator-runtime@0.13.11:
-    resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
+  /regenerator-runtime@0.14.0:
+    resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==}
     dev: false
 
   /regexp-tree@0.1.27:
     resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
     hasBin: true
     dev: true
 
-  /regexp.prototype.flags@1.5.0:
-    resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
+  /regexp.prototype.flags@1.5.1:
+    resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      functions-have-names: 1.2.3
+      define-properties: 1.2.1
+      set-function-name: 2.0.1
     dev: true
 
   /regexpp@3.2.0:
     resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==}
     engines: {node: '>=8'}
@@ -12129,64 +13083,84 @@ packages:
   /regextras@0.7.1:
     resolution: {integrity: sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==}
     engines: {node: '>=0.1.14'}
     dev: true
 
-  /rehype-parse@8.0.4:
-    resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==}
+  /rehype-parse@8.0.5:
+    resolution: {integrity: sha512-Ds3RglaY/+clEX2U2mHflt7NlMA72KspZ0JLUJgBBLpRddBcEw3H8uYZQliQriku22NZpYMfjDdSgHcjxue24A==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 2.3.6
       hast-util-from-parse5: 7.1.2
       parse5: 6.0.1
       unified: 10.1.2
 
   /rehype-raw@6.1.1:
     resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 2.3.6
       hast-util-raw: 7.2.3
       unified: 10.1.2
 
   /rehype-stringify@9.0.4:
     resolution: {integrity: sha512-Uk5xu1YKdqobe5XpSskwPvo1XeHUUucWEQSl8hTrXt5selvca1e8K1EZ37E6YoZ4BT8BCqCdVfQW7OfHfthtVQ==}
     dependencies:
-      '@types/hast': 2.3.4
+      '@types/hast': 2.3.6
       hast-util-to-html: 8.0.4
       unified: 10.1.2
 
   /rehype@12.0.1:
     resolution: {integrity: sha512-ey6kAqwLM3X6QnMDILJthGvG1m1ULROS9NT4uG9IDCuv08SFyLlreSuvOa//DgEvbXx62DS6elGVqusWhRUbgw==}
     dependencies:
-      '@types/hast': 2.3.4
-      rehype-parse: 8.0.4
+      '@types/hast': 2.3.6
+      rehype-parse: 8.0.5
       rehype-stringify: 9.0.4
       unified: 10.1.2
 
   /remark-gfm@3.0.1:
     resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       mdast-util-gfm: 2.0.2
       micromark-extension-gfm: 2.0.3
       unified: 10.1.2
     transitivePeerDependencies:
       - supports-color
 
+  /remark-mdx@2.3.0:
+    resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==}
+    dependencies:
+      mdast-util-mdx: 2.0.1
+      micromark-extension-mdxjs: 1.0.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /remark-parse@10.0.2:
     resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==}
     dependencies:
-      '@types/mdast': 3.0.11
+      '@types/mdast': 3.0.13
       mdast-util-from-markdown: 1.3.1
       unified: 10.1.2
     transitivePeerDependencies:
       - supports-color
 
+  /remark-parse@11.0.0:
+    resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      mdast-util-from-markdown: 2.0.0
+      micromark-util-types: 2.0.0
+      unified: 11.0.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /remark-rehype@10.1.0:
     resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==}
     dependencies:
-      '@types/hast': 2.3.4
-      '@types/mdast': 3.0.11
+      '@types/hast': 2.3.6
+      '@types/mdast': 3.0.13
       mdast-util-to-hast: 12.3.0
       unified: 10.1.2
 
   /remark-smartypants@2.0.0:
     resolution: {integrity: sha512-Rc0VDmr/yhnMQIz8n2ACYXlfw/P/XZev884QU1I5u+5DgJls32o97Vc1RbK3pfumLsJomS2yy8eT4Fxj/2MDVA==}
@@ -12194,10 +13168,29 @@ packages:
     dependencies:
       retext: 8.1.0
       retext-smartypants: 5.2.0
       unist-util-visit: 4.1.2
 
+  /remark-stringify@11.0.0:
+    resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      mdast-util-to-markdown: 2.1.0
+      unified: 11.0.3
+    dev: false
+
+  /remark@15.0.1:
+    resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
+    dependencies:
+      '@types/mdast': 4.0.1
+      remark-parse: 11.0.0
+      remark-stringify: 11.0.0
+      unified: 11.0.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: false
+
   /require-from-string@2.0.2:
     resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
     engines: {node: '>=0.10.0'}
     dev: false
 
@@ -12208,21 +13201,24 @@ packages:
   /resolve-from@4.0.0:
     resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
     engines: {node: '>=4'}
     dev: true
 
-  /resolve@1.22.2:
-    resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
-    hasBin: true
+  /resolve-from@5.0.0:
+    resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+    engines: {node: '>=8'}
+    dev: false
+
+  /resolve-pkg@2.0.0:
+    resolution: {integrity: sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==}
+    engines: {node: '>=8'}
     dependencies:
-      is-core-module: 2.12.1
-      path-parse: 1.0.7
-      supports-preserve-symlinks-flag: 1.0.0
-    dev: true
+      resolve-from: 5.0.0
+    dev: false
 
-  /resolve@1.22.4:
-    resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==}
+  /resolve@1.22.6:
+    resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==}
     hasBin: true
     dependencies:
       is-core-module: 2.13.0
       path-parse: 1.0.7
       supports-preserve-symlinks-flag: 1.0.0
@@ -12248,34 +13244,34 @@ packages:
     dev: false
 
   /retext-latin@3.1.0:
     resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==}
     dependencies:
-      '@types/nlcst': 1.0.0
+      '@types/nlcst': 1.0.2
       parse-latin: 5.0.1
       unherit: 3.0.1
       unified: 10.1.2
 
   /retext-smartypants@5.2.0:
     resolution: {integrity: sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==}
     dependencies:
-      '@types/nlcst': 1.0.0
+      '@types/nlcst': 1.0.2
       nlcst-to-string: 3.1.1
       unified: 10.1.2
       unist-util-visit: 4.1.2
 
   /retext-stringify@3.1.0:
     resolution: {integrity: sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==}
     dependencies:
-      '@types/nlcst': 1.0.0
+      '@types/nlcst': 1.0.2
       nlcst-to-string: 3.1.1
       unified: 10.1.2
 
   /retext@8.1.0:
     resolution: {integrity: sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==}
     dependencies:
-      '@types/nlcst': 1.0.0
+      '@types/nlcst': 1.0.2
       retext-latin: 3.1.0
       retext-stringify: 3.1.0
       unified: 10.1.2
 
   /reusify@1.0.4:
@@ -12298,37 +13294,30 @@ packages:
     hasBin: true
     dependencies:
       glob: 7.2.3
     dev: true
 
-  /rollup-plugin-dts@5.3.0(rollup@3.26.2)(typescript@5.2.2):
-    resolution: {integrity: sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ==}
-    engines: {node: '>=v14'}
+  /rollup-plugin-dts@5.3.1(rollup@3.29.4)(typescript@5.2.2):
+    resolution: {integrity: sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==}
+    engines: {node: '>=v14.21.3'}
     peerDependencies:
-      rollup: ^3.0.0
+      rollup: ^3.0
       typescript: ^4.1 || ^5.0
     dependencies:
-      magic-string: 0.30.3
-      rollup: 3.26.2
+      magic-string: 0.30.4
+      rollup: 3.29.4
       typescript: 5.2.2
     optionalDependencies:
       '@babel/code-frame': 7.22.13
     dev: true
 
-  /rollup@3.26.2:
-    resolution: {integrity: sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==}
+  /rollup@3.29.4:
+    resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
     engines: {node: '>=14.18.0', npm: '>=8.0.0'}
     hasBin: true
     optionalDependencies:
-      fsevents: 2.3.2
-
-  /rollup@3.29.0:
-    resolution: {integrity: sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==}
-    engines: {node: '>=14.18.0', npm: '>=8.0.0'}
-    hasBin: true
-    optionalDependencies:
-      fsevents: 2.3.2
+      fsevents: 2.3.3
 
   /rope-sequence@1.3.4:
     resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==}
     dev: false
 
@@ -12354,10 +13343,20 @@ packages:
     resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
     engines: {node: '>=6'}
     dependencies:
       mri: 1.2.0
 
+  /safe-array-concat@1.0.1:
+    resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
+    engines: {node: '>=0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      get-intrinsic: 1.2.1
+      has-symbols: 1.0.3
+      isarray: 2.0.5
+    dev: true
+
   /safe-buffer@5.1.2:
     resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
     dev: false
 
   /safe-buffer@5.2.1:
@@ -12392,31 +13391,30 @@ packages:
     resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
 
   /saslprep@1.0.3:
     resolution: {integrity: sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==}
     engines: {node: '>=6'}
-    requiresBuild: true
     dependencies:
       sparse-bitfield: 3.0.3
     dev: false
 
-  /sass-formatter@0.7.6:
-    resolution: {integrity: sha512-hXdxU6PCkiV3XAiSnX+XLqz2ohHoEnVUlrd8LEVMAI80uB1+OTScIkH9n6qQwImZpTye1r1WG1rbGUteHNhoHg==}
+  /sass-formatter@0.7.8:
+    resolution: {integrity: sha512-7fI2a8THglflhhYis7k06eUf92VQuJoXzEs2KRP0r1bluFxKFvLx0Ns7c478oYGM0fPfrr846ZRWVi2MAgHt9Q==}
     dependencies:
       suf-log: 2.5.3
 
   /sass@1.64.1:
     resolution: {integrity: sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==}
     engines: {node: '>=14.0.0'}
     hasBin: true
     dependencies:
       chokidar: 3.5.3
-      immutable: 4.3.0
+      immutable: 4.3.4
       source-map-js: 1.0.2
 
-  /sax@1.2.4:
-    resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
+  /sax@1.3.0:
+    resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
 
   /scheduler@0.23.0:
     resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
     dependencies:
       loose-envify: 1.4.0
@@ -12451,19 +13449,14 @@ packages:
     resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==}
     dependencies:
       parseley: 0.12.1
     dev: false
 
-  /semver@5.7.1:
-    resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
+  /semver@5.7.2:
+    resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
     hasBin: true
 
-  /semver@6.3.0:
-    resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
-    hasBin: true
-    dev: true
-
   /semver@6.3.1:
     resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
     hasBin: true
 
   /semver@7.5.4:
@@ -12503,10 +13496,19 @@ packages:
 
   /set-cookie-parser@2.6.0:
     resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==}
     dev: false
 
+  /set-function-name@2.0.1:
+    resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      define-data-property: 1.1.0
+      functions-have-names: 1.2.3
+      has-property-descriptors: 1.0.0
+    dev: true
+
   /setimmediate@1.0.5:
     resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
     dev: false
 
   /setprototypeof@1.2.0:
@@ -12547,11 +13549,11 @@ packages:
     dev: false
 
   /shiki@0.14.4:
     resolution: {integrity: sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==}
     dependencies:
-      ansi-sequence-parser: 1.1.0
+      ansi-sequence-parser: 1.1.1
       jsonc-parser: 3.2.0
       vscode-oniguruma: 1.7.0
       vscode-textmate: 8.0.0
 
   /side-channel@1.0.4:
@@ -12562,15 +13564,10 @@ packages:
       object-inspect: 1.12.3
 
   /signal-exit@3.0.7:
     resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
 
-  /signal-exit@4.0.2:
-    resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==}
-    engines: {node: '>=14'}
-    dev: false
-
   /signal-exit@4.1.0:
     resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
     engines: {node: '>=14'}
 
   /simple-concat@1.0.1:
@@ -12587,11 +13584,11 @@ packages:
     resolution: {integrity: sha512-8291lo/z5ZdpmiOFzOs1kF3cxn22bMj5FFH+DNUppLJrpoIlM1QnFiE7KpshHu3J3i21TVcx4yW+gXYjdCKDLQ==}
     dependencies:
       '@hapi/hoek': 10.0.1
       '@hapi/wreck': 18.0.1
       debug: 4.3.4
-      joi: 17.9.2
+      joi: 17.11.0
     transitivePeerDependencies:
       - supports-color
     dev: false
 
   /simple-swizzle@0.2.2:
@@ -12601,11 +13598,11 @@ packages:
 
   /sirv@2.0.3:
     resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==}
     engines: {node: '>= 10'}
     dependencies:
-      '@polka/url': 1.0.0-next.21
+      '@polka/url': 1.0.0-next.23
       mrmime: 1.0.1
       totalist: 3.0.1
 
   /sisteransi@1.0.5:
     resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
@@ -12614,13 +13611,13 @@ packages:
     resolution: {integrity: sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg==}
     engines: {node: '>=12.0.0', npm: '>=5.6.0'}
     hasBin: true
     dependencies:
       '@types/node': 17.0.45
-      '@types/sax': 1.2.4
+      '@types/sax': 1.2.5
       arg: 5.0.2
-      sax: 1.2.4
+      sax: 1.3.0
     dev: false
 
   /slash@3.0.0:
     resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
     engines: {node: '>=8'}
@@ -12646,42 +13643,23 @@ packages:
   /solid-js@1.7.11:
     resolution: {integrity: sha512-JkuvsHt8jqy7USsy9xJtT18aF9r2pFO+GB8JQ2XGTvtF49rGTObB46iebD25sE3qVNvIbwglXOXdALnJq9IHtQ==}
     dependencies:
       csstype: 3.1.2
       seroval: 0.5.1
-    dev: false
-
-  /solid-js@1.7.8:
-    resolution: {integrity: sha512-XHBWk1FvFd0JMKljko7FfhefJMTSgYEuVKcQ2a8hzRXfiuSJAGsrPPafqEo+f6l+e8Oe3cROSpIL6kbzjC1fjQ==}
-    dependencies:
-      csstype: 3.1.2
-      seroval: 0.5.1
 
   /solid-refresh@0.5.3(solid-js@1.7.11):
     resolution: {integrity: sha512-Otg5it5sjOdZbQZJnvo99TEBAr6J7PQ5AubZLNU6szZzg3RQQ5MX04oteBIIGDs0y2Qv8aXKm9e44V8z+UnFdw==}
     peerDependencies:
       solid-js: ^1.3
     dependencies:
-      '@babel/generator': 7.22.5
-      '@babel/helper-module-imports': 7.22.5
-      '@babel/types': 7.22.5
+      '@babel/generator': 7.23.0
+      '@babel/helper-module-imports': 7.22.15
+      '@babel/types': 7.23.0
       solid-js: 1.7.11
-    dev: false
-
-  /solid-refresh@0.5.3(solid-js@1.7.8):
-    resolution: {integrity: sha512-Otg5it5sjOdZbQZJnvo99TEBAr6J7PQ5AubZLNU6szZzg3RQQ5MX04oteBIIGDs0y2Qv8aXKm9e44V8z+UnFdw==}
-    peerDependencies:
-      solid-js: ^1.3
-    dependencies:
-      '@babel/generator': 7.22.5
-      '@babel/helper-module-imports': 7.22.5
-      '@babel/types': 7.22.5
-      solid-js: 1.7.8
-    dev: true
 
-  /sonic-boom@3.3.0:
-    resolution: {integrity: sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==}
+  /sonic-boom@3.6.1:
+    resolution: {integrity: sha512-QV+p5nXPiUiSMxn/k5bOL+hzCpafdj1voL+hywPZhheRSYyYp7CF15rNdz1evOXCUn/tFb7R62PDX1yJmtoTgg==}
     dependencies:
       atomic-sleep: 1.0.0
     dev: false
 
   /sortablejs@1.15.0:
@@ -12695,16 +13673,20 @@ packages:
   /source-map-support@0.5.21:
     resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
     dependencies:
       buffer-from: 1.1.2
       source-map: 0.6.1
-    dev: true
 
   /source-map@0.6.1:
     resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
     engines: {node: '>=0.10.0'}
 
+  /source-map@0.7.4:
+    resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
+    engines: {node: '>= 8'}
+    dev: false
+
   /space-separated-tokens@2.0.2:
     resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
 
   /sparse-bitfield@3.0.3:
     resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==}
@@ -12714,32 +13696,37 @@ packages:
 
   /spdx-correct@3.2.0:
     resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
     dependencies:
       spdx-expression-parse: 3.0.1
-      spdx-license-ids: 3.0.13
+      spdx-license-ids: 3.0.16
 
   /spdx-exceptions@2.3.0:
     resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
 
   /spdx-expression-parse@3.0.1:
     resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
     dependencies:
       spdx-exceptions: 2.3.0
-      spdx-license-ids: 3.0.13
+      spdx-license-ids: 3.0.16
 
-  /spdx-license-ids@3.0.13:
-    resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==}
+  /spdx-license-ids@3.0.16:
+    resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==}
 
   /split2@4.2.0:
     resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
     engines: {node: '>= 10.x'}
     dev: false
 
   /sprintf-js@1.0.3:
     resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
 
+  /stable@0.1.8:
+    resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
+    deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
+    dev: false
+
   /standard-as-callback@2.1.0:
     resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
     dev: false
 
   /statuses@2.0.1:
@@ -12772,14 +13759,10 @@ packages:
   /stream-wormhole@1.1.0:
     resolution: {integrity: sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==}
     engines: {node: '>=4.0.0'}
     dev: false
 
-  /streamsearch@1.1.0:
-    resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
-    engines: {node: '>=10.0.0'}
-
   /streamx@2.15.1:
     resolution: {integrity: sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==}
     dependencies:
       fast-fifo: 1.3.2
       queue-tick: 1.0.1
@@ -12806,33 +13789,33 @@ packages:
     dependencies:
       eastasianwidth: 0.2.0
       emoji-regex: 10.2.1
       strip-ansi: 7.1.0
 
-  /string.prototype.trim@1.2.7:
-    resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==}
+  /string.prototype.trim@1.2.8:
+    resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
     engines: {node: '>= 0.4'}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
     dev: true
 
-  /string.prototype.trimend@1.0.6:
-    resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==}
+  /string.prototype.trimend@1.0.7:
+    resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
     dev: true
 
-  /string.prototype.trimstart@1.0.6:
-    resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==}
+  /string.prototype.trimstart@1.0.7:
+    resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
     dependencies:
       call-bind: 1.0.2
-      define-properties: 1.2.0
-      es-abstract: 1.21.2
+      define-properties: 1.2.1
+      es-abstract: 1.22.2
     dev: true
 
   /string_decoder@1.1.1:
     resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
     dependencies:
@@ -12940,16 +13923,30 @@ packages:
 
   /supports-preserve-symlinks-flag@1.0.0:
     resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
     engines: {node: '>= 0.4'}
 
+  /svgo@2.8.0:
+    resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==}
+    engines: {node: '>=10.13.0'}
+    hasBin: true
+    dependencies:
+      '@trysound/sax': 0.2.0
+      commander: 7.2.0
+      css-select: 4.3.0
+      css-tree: 1.1.3
+      csso: 4.2.0
+      picocolors: 1.0.0
+      stable: 0.1.8
+    dev: false
+
   /synckit@0.8.5:
     resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==}
     engines: {node: ^14.18.0 || >=16.0.0}
     dependencies:
-      '@pkgr/utils': 2.4.1
-      tslib: 2.5.3
+      '@pkgr/utils': 2.4.2
+      tslib: 2.6.2
 
   /tailwindcss@3.2.7(postcss@8.4.21):
     resolution: {integrity: sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==}
     engines: {node: '>=12.13.0'}
     hasBin: true
@@ -12976,11 +13973,11 @@ packages:
       postcss-load-config: 3.1.4(postcss@8.4.21)
       postcss-nested: 6.0.0(postcss@8.4.21)
       postcss-selector-parser: 6.0.13
       postcss-value-parser: 4.2.0
       quick-lru: 5.1.1
-      resolve: 1.22.4
+      resolve: 1.22.6
     transitivePeerDependencies:
       - ts-node
     dev: false
 
   /tar-fs@2.1.1:
@@ -13018,37 +14015,36 @@ packages:
   /terser@5.19.2:
     resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==}
     engines: {node: '>=10'}
     hasBin: true
     dependencies:
-      '@jridgewell/source-map': 0.3.3
+      '@jridgewell/source-map': 0.3.5
       acorn: 8.10.0
       commander: 2.20.3
       source-map-support: 0.5.21
-    dev: true
 
   /text-decoding@1.0.0:
     resolution: {integrity: sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==}
     dev: false
 
   /text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
     dev: true
 
-  /thread-stream@2.3.0:
-    resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==}
+  /thread-stream@2.4.1:
+    resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==}
     dependencies:
       real-require: 0.2.0
     dev: false
 
   /throttle-debounce@3.0.1:
     resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==}
     engines: {node: '>=10'}
     dev: false
 
-  /tiny-lru@11.0.1:
-    resolution: {integrity: sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==}
+  /tiny-lru@11.2.2:
+    resolution: {integrity: sha512-1An82KBJOUKCfRhsk4tHe4rNblnhAUzisesWBGf/0pztaVoNYM7eJxouN+mq6WkV/qNG21AFbrsgQfvBk0X9ng==}
     engines: {node: '>=12'}
     dev: false
 
   /tinykeys@2.1.0:
     resolution: {integrity: sha512-/MESnqBD1xItZJn5oGQ4OsNORQgJfPP96XSGoyu4eLpwpL0ifO0SYR5OD76u0YMhMXsqkb0UqvI9+yXTh4xv8Q==}
@@ -13126,54 +14122,54 @@ packages:
       '@trpc/server': ^10.0.0
       zod: ^3.14.4
     dependencies:
       '@trpc/server': 10.35.0
       co-body: 6.1.0
-      h3: 1.7.1
+      h3: 1.8.2
       lodash.clonedeep: 4.5.0
-      node-mocks-http: 1.12.2
+      node-mocks-http: 1.13.0
       openapi-types: 12.1.3
       zod: 3.21.4
       zod-to-json-schema: 3.21.4(zod@3.21.4)
     dev: false
 
-  /trpc-openapi@1.2.0(@trpc/server@10.35.0)(zod@3.22.2):
+  /trpc-openapi@1.2.0(@trpc/server@10.35.0)(zod@3.22.4):
     resolution: {integrity: sha512-pfYoCd/3KYXWXvUPZBKJw455OOwngKN/6SIcj7Yit19OMLJ+8yVZkEvGEeg5wUSwfsiTdRsKuvqkRPXVSwV7ew==}
     peerDependencies:
       '@trpc/server': ^10.0.0
       zod: ^3.14.4
     dependencies:
       '@trpc/server': 10.35.0
       co-body: 6.1.0
-      h3: 1.7.1
+      h3: 1.8.2
       lodash.clonedeep: 4.5.0
-      node-mocks-http: 1.12.2
+      node-mocks-http: 1.13.0
       openapi-types: 12.1.3
-      zod: 3.22.2
-      zod-to-json-schema: 3.21.4(zod@3.22.2)
+      zod: 3.22.4
+      zod-to-json-schema: 3.21.4(zod@3.22.4)
     dev: false
 
-  /ts-api-utils@1.0.1(typescript@5.1.6):
-    resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
+  /ts-api-utils@1.0.3(typescript@5.2.2):
+    resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
     engines: {node: '>=16.13.0'}
     peerDependencies:
       typescript: '>=4.2.0'
     dependencies:
-      typescript: 5.1.6
+      typescript: 5.2.2
     dev: true
 
-  /tsconfck@2.1.2(typescript@5.1.6):
+  /tsconfck@2.1.2(typescript@5.2.2):
     resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==}
     engines: {node: ^14.13.1 || ^16 || >=18}
     hasBin: true
     peerDependencies:
       typescript: ^4.3.5 || ^5.0.0
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      typescript: 5.1.6
+      typescript: 5.2.2
     dev: true
 
   /tsconfig-paths@3.14.2:
     resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==}
     dependencies:
@@ -13185,38 +14181,38 @@ packages:
 
   /tsconfig-resolver@3.0.1:
     resolution: {integrity: sha512-ZHqlstlQF449v8glscGRXzL6l2dZvASPCdXJRWG4gHEZlUVx2Jtmr+a2zeVG4LCsKhDXKRj5R3h0C/98UcVAQg==}
     dependencies:
       '@types/json5': 0.0.30
-      '@types/resolve': 1.20.2
+      '@types/resolve': 1.20.3
       json5: 2.2.3
-      resolve: 1.22.4
+      resolve: 1.22.6
       strip-bom: 4.0.0
       type-fest: 0.13.1
 
   /tslib@1.14.1:
     resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
 
-  /tslib@2.5.3:
-    resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==}
+  /tslib@2.6.2:
+    resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
 
   /tsm@2.3.0:
     resolution: {integrity: sha512-++0HFnmmR+gMpDtKTnW3XJ4yv9kVGi20n+NfyQWB9qwJvTaIWY9kBmzek2YUQK5APTQ/1DTrXmm4QtFPmW9Rzw==}
     engines: {node: '>=12'}
     hasBin: true
     dependencies:
       esbuild: 0.15.18
     dev: true
 
-  /tsutils@3.21.0(typescript@5.1.6):
+  /tsutils@3.21.0(typescript@5.2.2):
     resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
     engines: {node: '>= 6'}
     peerDependencies:
       typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
     dependencies:
       tslib: 1.14.1
-      typescript: 5.1.6
+      typescript: 5.2.2
     dev: true
 
   /tunnel-agent@0.6.0:
     resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
     dependencies:
@@ -13329,38 +14325,59 @@ packages:
     dependencies:
       media-typer: 0.3.0
       mime-types: 2.1.35
     dev: false
 
+  /typed-array-buffer@1.0.0:
+    resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      get-intrinsic: 1.2.1
+      is-typed-array: 1.1.12
+    dev: true
+
+  /typed-array-byte-length@1.0.0:
+    resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      call-bind: 1.0.2
+      for-each: 0.3.3
+      has-proto: 1.0.1
+      is-typed-array: 1.1.12
+    dev: true
+
+  /typed-array-byte-offset@1.0.0:
+    resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      available-typed-arrays: 1.0.5
+      call-bind: 1.0.2
+      for-each: 0.3.3
+      has-proto: 1.0.1
+      is-typed-array: 1.1.12
+    dev: true
+
   /typed-array-length@1.0.4:
     resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
     dependencies:
       call-bind: 1.0.2
       for-each: 0.3.3
-      is-typed-array: 1.1.10
+      is-typed-array: 1.1.12
     dev: true
 
-  /typescript@5.1.6:
-    resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==}
-    engines: {node: '>=14.17'}
-    hasBin: true
-
   /typescript@5.2.2:
     resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==}
     engines: {node: '>=14.17'}
     hasBin: true
 
   /uc.micro@1.0.6:
     resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
     dev: false
 
-  /ufo@1.1.2:
-    resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
-    dev: false
-
-  /ufo@1.3.0:
-    resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==}
+  /ufo@1.3.1:
+    resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==}
 
   /uglify-js@3.17.4:
     resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
     engines: {node: '>=0.8.0'}
     hasBin: true
@@ -13379,64 +14396,67 @@ packages:
 
   /unbuild@1.2.1:
     resolution: {integrity: sha512-J4efk69Aye43tWcBPCsLK7TIRppGrEN4pAlDzRKo3HSE6MgTSTBxSEuE3ccx7ixc62JvGQ/CoFXYqqF2AHozow==}
     hasBin: true
     dependencies:
-      '@rollup/plugin-alias': 5.0.0(rollup@3.26.2)
-      '@rollup/plugin-commonjs': 24.1.0(rollup@3.26.2)
-      '@rollup/plugin-json': 6.0.0(rollup@3.26.2)
-      '@rollup/plugin-node-resolve': 15.1.0(rollup@3.26.2)
-      '@rollup/plugin-replace': 5.0.2(rollup@3.26.2)
-      '@rollup/pluginutils': 5.0.2(rollup@3.26.2)
+      '@rollup/plugin-alias': 5.0.1(rollup@3.29.4)
+      '@rollup/plugin-commonjs': 24.1.0(rollup@3.29.4)
+      '@rollup/plugin-json': 6.0.1(rollup@3.29.4)
+      '@rollup/plugin-node-resolve': 15.2.2(rollup@3.29.4)
+      '@rollup/plugin-replace': 5.0.3(rollup@3.29.4)
+      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       chalk: 5.3.0
       consola: 3.2.3
       defu: 6.1.2
       esbuild: 0.17.19
-      globby: 13.1.4
+      globby: 13.2.2
       hookable: 5.5.3
-      jiti: 1.18.2
-      magic-string: 0.30.1
-      mkdist: 1.2.0(typescript@5.2.2)
-      mlly: 1.3.0
+      jiti: 1.20.0
+      magic-string: 0.30.4
+      mkdist: 1.3.0(typescript@5.2.2)
+      mlly: 1.4.2
       mri: 1.2.0
       pathe: 1.1.1
       pkg-types: 1.0.3
-      pretty-bytes: 6.1.0
-      rollup: 3.26.2
-      rollup-plugin-dts: 5.3.0(rollup@3.26.2)(typescript@5.2.2)
+      pretty-bytes: 6.1.1
+      rollup: 3.29.4
+      rollup-plugin-dts: 5.3.1(rollup@3.29.4)(typescript@5.2.2)
       scule: 1.0.0
       typescript: 5.2.2
-      untyped: 1.3.2
+      untyped: 1.4.0
     transitivePeerDependencies:
       - sass
       - supports-color
     dev: true
 
-  /unconfig@0.3.10:
-    resolution: {integrity: sha512-tj317lhIq2iZF/NXrJnU1t2UaGUKKz1eL1sK2t63Oq66V9BxqvZV12m55fp/fpQJ+DDmVlLgo7cnLVOZkhlO/A==}
+  /unconfig@0.3.11:
+    resolution: {integrity: sha512-bV/nqePAKv71v3HdVUn6UefbsDKQWRX+bJIkiSm0+twIds6WiD2bJLWWT3i214+J/B4edufZpG2w7Y63Vbwxow==}
     dependencies:
       '@antfu/utils': 0.7.6
       defu: 6.1.2
-      jiti: 1.19.3
+      jiti: 1.20.0
       mlly: 1.4.2
 
   /uncrypto@0.1.3:
     resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==}
     dev: false
 
-  /undici@5.22.1:
-    resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==}
+  /undici@5.25.4:
+    resolution: {integrity: sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==}
     engines: {node: '>=14.0'}
     dependencies:
-      busboy: 1.6.0
-    dev: false
+      '@fastify/busboy': 2.0.0
 
-  /undici@5.23.0:
-    resolution: {integrity: sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==}
-    engines: {node: '>=14.0'}
+  /unenv@1.7.4:
+    resolution: {integrity: sha512-fjYsXYi30It0YCQYqLOcT6fHfMXsBr2hw9XC7ycf8rTG7Xxpe3ZssiqUnD0khrjiZEmkBXWLwm42yCSCH46fMw==}
     dependencies:
-      busboy: 1.6.0
+      consola: 3.2.3
+      defu: 6.1.2
+      mime: 3.0.0
+      node-fetch-native: 1.4.0
+      pathe: 1.1.1
+    dev: false
 
   /unfetch@4.2.0:
     resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
     dev: false
 
@@ -13444,56 +14464,106 @@ packages:
     resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==}
 
   /unified@10.1.2:
     resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       bail: 2.0.2
       extend: 3.0.2
       is-buffer: 2.0.5
       is-plain-obj: 4.1.0
       trough: 2.1.0
       vfile: 5.3.7
 
+  /unified@11.0.3:
+    resolution: {integrity: sha512-jlCV402P+YDcFcB2VcN/n8JasOddqIiaxv118wNBoZXEhOn+lYG7BR4Bfg2BwxvlK58dwbuH2w7GX2esAjL6Mg==}
+    dependencies:
+      '@types/unist': 3.0.0
+      bail: 2.0.2
+      devlop: 1.1.0
+      extend: 3.0.2
+      is-plain-obj: 4.1.0
+      trough: 2.1.0
+      vfile: 6.0.1
+    dev: false
+
   /unist-util-generated@2.0.1:
     resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==}
 
   /unist-util-is@5.2.1:
     resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
 
   /unist-util-is@6.0.0:
     resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
     dependencies:
       '@types/unist': 3.0.0
 
   /unist-util-modify-children@3.1.1:
     resolution: {integrity: sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       array-iterate: 2.0.1
 
+  /unist-util-position-from-estree@1.1.2:
+    resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==}
+    dependencies:
+      '@types/unist': 2.0.8
+    dev: false
+
+  /unist-util-position-from-estree@2.0.0:
+    resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
+    dependencies:
+      '@types/unist': 3.0.0
+    dev: false
+
   /unist-util-position@4.0.4:
     resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
+
+  /unist-util-position@5.0.0:
+    resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+    dependencies:
+      '@types/unist': 3.0.0
+    dev: false
+
+  /unist-util-remove-position@4.0.2:
+    resolution: {integrity: sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==}
+    dependencies:
+      '@types/unist': 2.0.8
+      unist-util-visit: 4.1.2
+    dev: false
+
+  /unist-util-remove-position@5.0.0:
+    resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==}
+    dependencies:
+      '@types/unist': 3.0.0
+      unist-util-visit: 5.0.0
+    dev: false
 
   /unist-util-stringify-position@3.0.3:
     resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
+
+  /unist-util-stringify-position@4.0.0:
+    resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+    dependencies:
+      '@types/unist': 3.0.0
+    dev: false
 
   /unist-util-visit-children@2.0.2:
     resolution: {integrity: sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
 
   /unist-util-visit-parents@5.1.3:
     resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       unist-util-is: 5.2.1
 
   /unist-util-visit-parents@6.0.1:
     resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
     dependencies:
@@ -13501,11 +14571,11 @@ packages:
       unist-util-is: 6.0.0
 
   /unist-util-visit@4.1.2:
     resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       unist-util-is: 5.2.1
       unist-util-visit-parents: 5.1.3
 
   /unist-util-visit@5.0.0:
     resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
@@ -13515,12 +14585,12 @@ packages:
       unist-util-visit-parents: 6.0.1
 
   /universal-github-app-jwt@1.1.1:
     resolution: {integrity: sha512-G33RTLrIBMFmlDV4u4CBF7dh71eWwykck4XgaxaIVeZKOYZRAAxvcGMRFTUclVY6xoUPQvO4Ne5wKGxYm/Yy9w==}
     dependencies:
-      '@types/jsonwebtoken': 9.0.2
-      jsonwebtoken: 9.0.1
+      '@types/jsonwebtoken': 9.0.3
+      jsonwebtoken: 9.0.2
     dev: false
 
   /universal-user-agent@6.0.0:
     resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==}
     dev: false
@@ -13532,50 +14602,11 @@ packages:
 
   /universalify@2.0.0:
     resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
     engines: {node: '>= 10.0.0'}
 
-  /unocss@0.55.7(postcss@8.4.29)(vite@4.4.7):
-    resolution: {integrity: sha512-3W9P7vj2EhSk/4oPCHBS0VgrwSf5zZL6Az1/XARVOpBnRJtCM2szFInYxHkMgt9pkZTsW8SFCuk/g+QIJ6A8tg==}
-    engines: {node: '>=14'}
-    peerDependencies:
-      '@unocss/webpack': 0.55.7
-      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
-    peerDependenciesMeta:
-      '@unocss/webpack':
-        optional: true
-      vite:
-        optional: true
-    dependencies:
-      '@unocss/astro': 0.55.7(vite@4.4.7)
-      '@unocss/cli': 0.55.7
-      '@unocss/core': 0.55.7
-      '@unocss/extractor-arbitrary-variants': 0.55.7
-      '@unocss/postcss': 0.55.7(postcss@8.4.29)
-      '@unocss/preset-attributify': 0.55.7
-      '@unocss/preset-icons': 0.55.7
-      '@unocss/preset-mini': 0.55.7
-      '@unocss/preset-tagify': 0.55.7
-      '@unocss/preset-typography': 0.55.7
-      '@unocss/preset-uno': 0.55.7
-      '@unocss/preset-web-fonts': 0.55.7
-      '@unocss/preset-wind': 0.55.7
-      '@unocss/reset': 0.55.7
-      '@unocss/transformer-attributify-jsx': 0.55.7
-      '@unocss/transformer-attributify-jsx-babel': 0.55.7
-      '@unocss/transformer-compile-class': 0.55.7
-      '@unocss/transformer-directives': 0.55.7
-      '@unocss/transformer-variant-group': 0.55.7
-      '@unocss/vite': 0.55.7(vite@4.4.7)
-      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
-    transitivePeerDependencies:
-      - postcss
-      - rollup
-      - supports-color
-    dev: true
-
-  /unocss@0.55.7(postcss@8.4.29)(vite@4.4.9):
+  /unocss@0.55.7(postcss@8.4.31)(vite@4.4.9):
     resolution: {integrity: sha512-3W9P7vj2EhSk/4oPCHBS0VgrwSf5zZL6Az1/XARVOpBnRJtCM2szFInYxHkMgt9pkZTsW8SFCuk/g+QIJ6A8tg==}
     engines: {node: '>=14'}
     peerDependencies:
       '@unocss/webpack': 0.55.7
       vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
@@ -13587,11 +14618,11 @@ packages:
     dependencies:
       '@unocss/astro': 0.55.7(vite@4.4.9)
       '@unocss/cli': 0.55.7
       '@unocss/core': 0.55.7
       '@unocss/extractor-arbitrary-variants': 0.55.7
-      '@unocss/postcss': 0.55.7(postcss@8.4.29)
+      '@unocss/postcss': 0.55.7(postcss@8.4.31)
       '@unocss/preset-attributify': 0.55.7
       '@unocss/preset-icons': 0.55.7
       '@unocss/preset-mini': 0.55.7
       '@unocss/preset-tagify': 0.55.7
       '@unocss/preset-typography': 0.55.7
@@ -13603,35 +14634,34 @@ packages:
       '@unocss/transformer-attributify-jsx-babel': 0.55.7
       '@unocss/transformer-compile-class': 0.55.7
       '@unocss/transformer-directives': 0.55.7
       '@unocss/transformer-variant-group': 0.55.7
       '@unocss/vite': 0.55.7(vite@4.4.9)
-      vite: 4.4.9(sass@1.64.1)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
     transitivePeerDependencies:
       - postcss
       - rollup
       - supports-color
-    dev: false
 
   /unpipe@1.0.0:
     resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
     engines: {node: '>= 0.8'}
     dev: false
 
   /untildify@4.0.0:
     resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
     engines: {node: '>=8'}
 
-  /untyped@1.3.2:
-    resolution: {integrity: sha512-z219Z65rOGD6jXIvIhpZFfwWdqQckB8sdZec2NO+TkcH1Bph7gL0hwLzRJs1KsOo4Jz4mF9guBXhsEnyEBGVfw==}
+  /untyped@1.4.0:
+    resolution: {integrity: sha512-Egkr/s4zcMTEuulcIb7dgURS6QpN7DyqQYdf+jBtiaJvQ+eRsrtWUoX84SbvQWuLkXsOjM+8sJC9u6KoMK/U7Q==}
     hasBin: true
     dependencies:
-      '@babel/core': 7.22.5
-      '@babel/standalone': 7.22.5
-      '@babel/types': 7.22.15
+      '@babel/core': 7.23.0
+      '@babel/standalone': 7.23.1
+      '@babel/types': 7.23.0
       defu: 6.1.2
-      jiti: 1.19.3
+      jiti: 1.20.0
       mri: 1.2.0
       scule: 1.0.0
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -13649,17 +14679,17 @@ packages:
       listenercount: 1.0.1
       readable-stream: 2.3.8
       setimmediate: 1.0.5
     dev: false
 
-  /update-browserslist-db@1.0.11(browserslist@4.21.10):
-    resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
+  /update-browserslist-db@1.0.13(browserslist@4.22.1):
+    resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
     hasBin: true
     peerDependencies:
       browserslist: '>= 4.21.0'
     dependencies:
-      browserslist: 4.21.10
+      browserslist: 4.22.1
       escalade: 3.1.1
       picocolors: 1.0.0
 
   /uri-js@4.4.1:
     resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -13677,12 +14707,12 @@ packages:
   /uuid@8.3.2:
     resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
     hasBin: true
     dev: false
 
-  /uuid@9.0.0:
-    resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
+  /uuid@9.0.1:
+    resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
     hasBin: true
     dev: false
 
   /uvu@0.5.6:
     resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}
@@ -13708,92 +14738,94 @@ packages:
     resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
     dependencies:
       spdx-correct: 3.2.0
       spdx-expression-parse: 3.0.1
 
-  /validator@13.9.0:
-    resolution: {integrity: sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==}
+  /validator@13.11.0:
+    resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==}
     engines: {node: '>= 0.10'}
     dev: false
 
   /vfile-location@4.1.0:
     resolution: {integrity: sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       vfile: 5.3.7
 
+  /vfile-location@5.0.2:
+    resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==}
+    dependencies:
+      '@types/unist': 3.0.0
+      vfile: 6.0.1
+    dev: false
+
   /vfile-message@3.1.4:
     resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       unist-util-stringify-position: 3.0.3
 
+  /vfile-message@4.0.2:
+    resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
+    dependencies:
+      '@types/unist': 3.0.0
+      unist-util-stringify-position: 4.0.0
+    dev: false
+
   /vfile@5.3.7:
     resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==}
     dependencies:
-      '@types/unist': 2.0.6
+      '@types/unist': 2.0.8
       is-buffer: 2.0.5
       unist-util-stringify-position: 3.0.3
       vfile-message: 3.1.4
 
+  /vfile@6.0.1:
+    resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
+    dependencies:
+      '@types/unist': 3.0.0
+      unist-util-stringify-position: 4.0.0
+      vfile-message: 4.0.2
+    dev: false
+
   /vite-plugin-solid@2.7.0(solid-js@1.7.11)(vite@4.4.9):
     resolution: {integrity: sha512-avp/Jl5zOp/Itfo67xtDB2O61U7idviaIp4mLsjhCa13PjKNasz+IID0jYTyqUp9SFx6/PmBr6v4KgDppqompg==}
     peerDependencies:
       solid-js: ^1.7.2
       vite: ^3.0.0 || ^4.0.0
     dependencies:
-      '@babel/core': 7.22.5
-      '@babel/preset-typescript': 7.22.5(@babel/core@7.22.5)
-      '@types/babel__core': 7.20.1
-      babel-preset-solid: 1.7.4(@babel/core@7.22.5)
+      '@babel/core': 7.23.0
+      '@babel/preset-typescript': 7.23.0(@babel/core@7.23.0)
+      '@types/babel__core': 7.20.2
+      babel-preset-solid: 1.7.12(@babel/core@7.23.0)
       merge-anything: 5.1.7
       solid-js: 1.7.11
       solid-refresh: 0.5.3(solid-js@1.7.11)
-      vite: 4.4.9(sass@1.64.1)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
       vitefu: 0.2.4(vite@4.4.9)
     transitivePeerDependencies:
       - supports-color
-    dev: false
-
-  /vite-plugin-solid@2.7.0(solid-js@1.7.8)(vite@4.4.7):
-    resolution: {integrity: sha512-avp/Jl5zOp/Itfo67xtDB2O61U7idviaIp4mLsjhCa13PjKNasz+IID0jYTyqUp9SFx6/PmBr6v4KgDppqompg==}
-    peerDependencies:
-      solid-js: ^1.7.2
-      vite: ^3.0.0 || ^4.0.0
-    dependencies:
-      '@babel/core': 7.22.5
-      '@babel/preset-typescript': 7.22.5(@babel/core@7.22.5)
-      '@types/babel__core': 7.20.1
-      babel-preset-solid: 1.7.4(@babel/core@7.22.5)
-      merge-anything: 5.1.7
-      solid-js: 1.7.8
-      solid-refresh: 0.5.3(solid-js@1.7.8)
-      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
-      vitefu: 0.2.4(vite@4.4.7)
-    transitivePeerDependencies:
-      - supports-color
-    dev: true
 
-  /vite-tsconfig-paths@4.2.0(typescript@5.1.6)(vite@4.4.7):
+  /vite-tsconfig-paths@4.2.0(typescript@5.2.2)(vite@4.4.9):
     resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==}
     peerDependencies:
       vite: '*'
     peerDependenciesMeta:
       vite:
         optional: true
     dependencies:
       debug: 4.3.4
       globrex: 0.1.2
-      tsconfck: 2.1.2(typescript@5.1.6)
-      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
+      tsconfck: 2.1.2(typescript@5.2.2)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
     transitivePeerDependencies:
       - supports-color
       - typescript
     dev: true
 
-  /vite@4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2):
-    resolution: {integrity: sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==}
+  /vite@4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2):
+    resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:
       '@types/node': '>= 14'
       less: '*'
@@ -13818,106 +14850,72 @@ packages:
       terser:
         optional: true
     dependencies:
       '@types/node': 20.4.4
       esbuild: 0.18.16
-      postcss: 8.4.26
-      rollup: 3.26.2
+      postcss: 8.4.31
+      rollup: 3.29.4
       sass: 1.64.1
       terser: 5.19.2
     optionalDependencies:
-      fsevents: 2.3.2
-    dev: true
-
-  /vite@4.4.9(sass@1.64.1):
-    resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==}
-    engines: {node: ^14.18.0 || >=16.0.0}
-    hasBin: true
-    peerDependencies:
-      '@types/node': '>= 14'
-      less: '*'
-      lightningcss: ^1.21.0
-      sass: '*'
-      stylus: '*'
-      sugarss: '*'
-      terser: ^5.4.0
-    peerDependenciesMeta:
-      '@types/node':
-        optional: true
-      less:
-        optional: true
-      lightningcss:
-        optional: true
-      sass:
-        optional: true
-      stylus:
-        optional: true
-      sugarss:
-        optional: true
-      terser:
-        optional: true
-    dependencies:
-      esbuild: 0.18.16
-      postcss: 8.4.29
-      rollup: 3.29.0
-      sass: 1.64.1
-    optionalDependencies:
-      fsevents: 2.3.2
-
-  /vitefu@0.2.4(vite@4.4.7):
-    resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
-    peerDependencies:
-      vite: ^3.0.0 || ^4.0.0
-    peerDependenciesMeta:
-      vite:
-        optional: true
-    dependencies:
-      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
-    dev: true
+      fsevents: 2.3.3
 
   /vitefu@0.2.4(vite@4.4.9):
     resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
     peerDependencies:
       vite: ^3.0.0 || ^4.0.0
     peerDependenciesMeta:
       vite:
         optional: true
     dependencies:
-      vite: 4.4.9(sass@1.64.1)
+      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
 
-  /vscode-css-languageservice@6.2.6:
-    resolution: {integrity: sha512-SA2WkeOecIpUiEbZnjOsP/fI5CRITZEiQGSHXKiDQDwLApfKcnLhZwMtOBbIifSzESVcQa7b/shX/nbnF4NoCg==}
+  /vscode-css-languageservice@6.2.9:
+    resolution: {integrity: sha512-9MsOvAi+VycKomQ7KEq4o/hLtjHHrtRLLl8lM9nMcH8cxfNI7/6jVXmsV/7pdbDWu9L3DZhsspN1eMXZwiOymw==}
     dependencies:
-      '@vscode/l10n': 0.0.14
-      vscode-languageserver-textdocument: 1.0.8
+      '@vscode/l10n': 0.0.16
+      vscode-languageserver-textdocument: 1.0.11
       vscode-languageserver-types: 3.17.3
-      vscode-uri: 3.0.7
+      vscode-uri: 3.0.8
 
-  /vscode-html-languageservice@5.0.6:
-    resolution: {integrity: sha512-gCixNg6fjPO7+kwSMBAVXcwDRHdjz1WOyNfI0n5Wx0J7dfHG8ggb3zD1FI8E2daTZrwS1cooOiSoc1Xxph4qRQ==}
+  /vscode-html-languageservice@5.1.0:
+    resolution: {integrity: sha512-cGOu5+lrz+2dDXSGS15y24lDtPaML1T8K/SfqgFbLmCZ1btYOxceFieR+ybTS2es/A67kRc62m2cKFLUQPWG5g==}
     dependencies:
-      '@vscode/l10n': 0.0.14
-      vscode-languageserver-textdocument: 1.0.8
-      vscode-languageserver-types: 3.17.3
-      vscode-uri: 3.0.7
+      '@vscode/l10n': 0.0.16
+      vscode-languageserver-textdocument: 1.0.11
+      vscode-languageserver-types: 3.17.5
+      vscode-uri: 3.0.8
 
   /vscode-jsonrpc@8.1.0:
     resolution: {integrity: sha512-6TDy/abTQk+zDGYazgbIPc+4JoXdwC8NHU9Pbn4UJP1fehUyZmM4RHp5IthX7A6L5KS30PRui+j+tbbMMMafdw==}
     engines: {node: '>=14.0.0'}
 
+  /vscode-jsonrpc@8.2.0:
+    resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
+    engines: {node: '>=14.0.0'}
+
   /vscode-languageserver-protocol@3.17.3:
     resolution: {integrity: sha512-924/h0AqsMtA5yK22GgMtCYiMdCOtWTSGgUOkgEDX+wk2b0x4sAfLiO4NxBxqbiVtz7K7/1/RgVrVI0NClZwqA==}
     dependencies:
       vscode-jsonrpc: 8.1.0
       vscode-languageserver-types: 3.17.3
 
-  /vscode-languageserver-textdocument@1.0.8:
-    resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==}
+  /vscode-languageserver-protocol@3.17.5:
+    resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
+    dependencies:
+      vscode-jsonrpc: 8.2.0
+      vscode-languageserver-types: 3.17.5
+
+  /vscode-languageserver-textdocument@1.0.11:
+    resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==}
 
   /vscode-languageserver-types@3.17.3:
     resolution: {integrity: sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==}
 
+  /vscode-languageserver-types@3.17.5:
+    resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
+
   /vscode-languageserver@8.1.0:
     resolution: {integrity: sha512-eUt8f1z2N2IEUDBsKaNapkz7jl5QpskN2Y0G01T/ItMxBxw1fJwvtySGB9QMecatne8jFIWJGWI61dWjyTLQsw==}
     hasBin: true
     dependencies:
       vscode-languageserver-protocol: 3.17.3
@@ -13929,37 +14927,42 @@ packages:
     resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==}
 
   /vscode-uri@2.1.2:
     resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==}
 
-  /vscode-uri@3.0.7:
-    resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==}
+  /vscode-uri@3.0.8:
+    resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
 
   /w3c-keyname@2.2.8:
     resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
     dev: false
 
   /wcwidth@1.0.1:
     resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
     dependencies:
       defaults: 1.0.4
 
-  /weaviate-ts-client@1.4.0(graphql@16.7.1):
+  /weaviate-ts-client@1.4.0(graphql@16.8.1):
     resolution: {integrity: sha512-G2V/IWMHXDjoJeATUYKkZXzAs7iRj4GE8B3AX59XDqMRW12X7VUkRgo4xWcHH1bjpLIHUYTzD5qZXcB8P9Hdmw==}
     engines: {node: '>=16.0.0'}
     dependencies:
-      graphql-request: 5.2.0(graphql@16.7.1)
+      graphql-request: 5.2.0(graphql@16.8.1)
       isomorphic-fetch: 3.0.0
-      uuid: 9.0.0
+      uuid: 9.0.1
     transitivePeerDependencies:
       - encoding
       - graphql
     dev: false
 
   /web-namespaces@2.0.1:
     resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
 
+  /web-streams-polyfill@3.2.1:
+    resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
+    engines: {node: '>= 8'}
+    dev: false
+
   /web-streams-polyfill@4.0.0-beta.3:
     resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==}
     engines: {node: '>= 14'}
     dev: false
 
@@ -13970,12 +14973,12 @@ packages:
   /webidl-conversions@7.0.0:
     resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
     engines: {node: '>=12'}
     dev: false
 
-  /whatwg-fetch@3.6.17:
-    resolution: {integrity: sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ==}
+  /whatwg-fetch@3.6.19:
+    resolution: {integrity: sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==}
     dev: false
 
   /whatwg-url@11.0.0:
     resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==}
     engines: {node: '>=12'}
@@ -14017,20 +15020,19 @@ packages:
     engines: {node: '>=8.15'}
     dependencies:
       load-yaml-file: 0.2.0
       path-exists: 4.0.0
 
-  /which-typed-array@1.1.9:
-    resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==}
+  /which-typed-array@1.1.11:
+    resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==}
     engines: {node: '>= 0.4'}
     dependencies:
       available-typed-arrays: 1.0.5
       call-bind: 1.0.2
       for-each: 0.3.3
       gopd: 1.0.1
       has-tostringtag: 1.0.0
-      is-typed-array: 1.1.10
     dev: true
 
   /which@2.0.2:
     resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
     engines: {node: '>= 8'}
@@ -14079,12 +15081,12 @@ packages:
         optional: true
       utf-8-validate:
         optional: true
     dev: false
 
-  /ws@8.13.0:
-    resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
+  /ws@8.14.2:
+    resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
     engines: {node: '>=10.0.0'}
     peerDependencies:
       bufferutil: ^4.0.1
       utf-8-validate: '>=5.0.2'
     peerDependenciesMeta:
@@ -14097,48 +15099,48 @@ packages:
   /xtend@4.0.2:
     resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
     engines: {node: '>=0.4'}
     dev: false
 
-  /y-prosemirror@1.0.20(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7):
+  /y-prosemirror@1.0.20(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7):
     resolution: {integrity: sha512-LVMtu3qWo0emeYiP+0jgNcvZkqhzE/otOoro+87q0iVKxy/sMKuiJZnokfJdR4cn9qKx0Un5fIxXqbAlR2bFkA==}
     peerDependencies:
       prosemirror-model: ^1.7.1
       prosemirror-state: ^1.2.3
       prosemirror-view: ^1.9.10
       y-protocols: ^1.0.1
       yjs: ^13.3.2
     dependencies:
-      lib0: 0.2.78
-      prosemirror-model: 1.19.2
+      lib0: 0.2.86
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-view: 1.31.4
+      prosemirror-view: 1.32.0
       y-protocols: 1.0.5
       yjs: 13.6.7
     dev: false
 
-  /y-prosemirror@1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7):
+  /y-prosemirror@1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7):
     resolution: {integrity: sha512-czMBfB1eL2awqmOSxQM8cS/fsUOGE6fjvyPLInrh4crPxFiw67wDpwIW+EGBYKRa04sYbS0ScGj7ZgvWuDrmBQ==}
     peerDependencies:
       prosemirror-model: ^1.7.1
       prosemirror-state: ^1.2.3
       prosemirror-view: ^1.9.10
       y-protocols: ^1.0.1
       yjs: ^13.5.38
     dependencies:
-      lib0: 0.2.78
-      prosemirror-model: 1.19.2
+      lib0: 0.2.86
+      prosemirror-model: 1.19.3
       prosemirror-state: 1.4.3
-      prosemirror-view: 1.31.4
+      prosemirror-view: 1.32.0
       y-protocols: 1.0.5
       yjs: 13.6.7
     dev: false
 
   /y-protocols@1.0.5:
     resolution: {integrity: sha512-Wil92b7cGk712lRHDqS4T90IczF6RkcvCwAD0A2OPg+adKmOe+nOiT/N2hvpQIWS3zfjmtL4CPaH5sIW1Hkm/A==}
     dependencies:
-      lib0: 0.2.78
+      lib0: 0.2.86
     dev: false
 
   /yallist@3.1.1:
     resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
 
@@ -14161,11 +15163,11 @@ packages:
 
   /yjs@13.6.7:
     resolution: {integrity: sha512-mCZTh4kjvUS2DnaktsYN6wLH3WZCJBLqrTdkWh1bIDpA/sB/GNFaLA/dyVJj2Hc7KwONuuoC/vWe9bwBBosZLQ==}
     engines: {node: '>=16.0.0', npm: '>=8.0.0'}
     dependencies:
-      lib0: 0.2.78
+      lib0: 0.2.86
     dev: false
 
   /yocto-queue@0.1.0:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
@@ -14187,24 +15189,24 @@ packages:
       zod: ^3.21.4
     dependencies:
       zod: 3.21.4
     dev: false
 
-  /zod-to-json-schema@3.21.4(zod@3.22.2):
+  /zod-to-json-schema@3.21.4(zod@3.22.4):
     resolution: {integrity: sha512-fjUZh4nQ1s6HMccgIeE0VP4QG/YRGPmyjO9sAh890aQKPEk3nqbfUXhMFaC+Dr5KvYBm8BCyvfpZf2jY9aGSsw==}
     peerDependencies:
       zod: ^3.21.4
     dependencies:
-      zod: 3.22.2
+      zod: 3.22.4
     dev: false
 
   /zod@3.21.1:
     resolution: {integrity: sha512-+dTu2m6gmCbO9Ahm4ZBDapx2O6ZY9QSPXst2WXjcznPMwf2YNpn3RevLx4KkZp1OPW/ouFcoBtBzFz/LeY69oA==}
 
   /zod@3.21.4:
     resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
 
-  /zod@3.22.2:
-    resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==}
+  /zod@3.22.4:
+    resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
 
   /zwitch@2.0.4:
     resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}

Vulnerable code: import corsPlugin from "@fastify/cors";
    methods: ["GET", "DELETE", "PUT", "POST"],
    origin(origin, callback) {
      if (!origin || origin === "null") {
        callback(null, true);

        return;
      }

      const { hostname } = new URL(origin);
      const appHostname = new URL(fastify.config.PUBLIC_APP_URL).hostname;

      if (
        hostname === "localhost" ||
        hostname.endsWith(appHostname) ||
        (fastify.config.VRITE_CLOUD && hostname.endsWith("swagger.io"))
      ) {
        callback(null, true);

        return;
      }

      callback(new Error("Not allowed"), false);
    }
  const server = await createServer();
        version: "0.2.0"
import { appRouter, errors, publicPlugin, trpcPlugin } from "@vrite/backend";
import { processAuth } from "@vrite/backend/src/lib/auth";
    return reply.view("index.html", {
  fastify.get<{ Querystring: { url: string } }>("/proxy*", async (request, reply) => {
    const filterOutRegex =
      /(localhost|\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?::\d{0,4})?\b)/;

    if (request.headers.origin) {
      reply.header("Access-Control-Allow-Origin", fastify.config.PUBLIC_APP_URL);
      reply.header("Access-Control-Allow-Methods", "GET");
      reply.header(
        "Access-Control-Allow-Headers",
        request.headers["access-control-request-headers"]
      );
    } else if (
      fastify.config.NODE_ENV !== "development" &&
      !fastify.config.PUBLIC_APP_URL.includes("localhost")
    ) {
      // Prevent proxy abuse in production
      return reply.status(400).send("Invalid Origin");
    }

    if (
      filterOutRegex.test(request.query.url) &&
      !request.query.url.includes(fastify.config.PUBLIC_ASSETS_URL)
    ) {
      return reply.status(400).send("Invalid URL");
    }

    if (request.method === "OPTIONS") {
      // CORS Preflight
      reply.send();
    } else {
      const targetURL = request.query.url;

      try {
        const response = await axios.get(targetURL, {
          responseType: "arraybuffer"
        });

        if (!`${response.headers["content-type"]}`.includes("image")) {
          return reply.status(400).send("Invalid Content-Type");
        }

        reply.header("content-type", response.headers["content-type"]);
        reply.send(Buffer.from(response.data, "binary"));
      } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);

        return reply.status(500).send("Could not fetch");
      }
    }
  });
  const server = await createServer();
    reply.header("Access-Control-Allow-Origin", fastify.config.PUBLIC_APP_URL);
import { assetsService } from "./api";
  const server = await createServer();
  GitData,
  ObjectId,
  jsonToBuffer
import { createEventPublisher } from "@vrite/backend/src/lib/pub-sub";
type GitDataEvent = {
  action: "update";
  data: Partial<GitData>;
};

  private publishGitDataEvent = createEventPublisher<GitDataEvent>((workspaceId) => {
    return `gitData:${workspaceId}`;
  });

    this.publishGitDataEvent({ fastify: this.fastify }, `${details.context.workspaceId}`, {
import { ObjectId, docToBuffer, getContentPiecesCollection } from "@vrite/backend";
  const server = await createServer();
import { publicPlugin, getContentsCollection, getContentVariantsCollection } from "@vrite/backend";
import { SessionData } from "@vrite/backend/src/lib/session";
import { unauthorized } from "@vrite/backend/src/lib/errors";
        throw unauthorized();
        throw unauthorized();
    "trpc-openapi": "^1.2.0"
import { publicPlugin, createContext } from "@vrite/backend";
import corsPlugin from "@fastify/cors";
    credentials: true,
      return createContext({ req, res }, fastify);
import { createServer, z } from "@vrite/backend";
  const server = await createServer();
      JSONContentNode["listItem" | "blockquote" | "doc" | "wrapper"]
          case "wrapper":
              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
      JSONContentNode["listItem" | "blockquote" | "doc" | "wrapper"]
          case "wrapper":
              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
  gpt: gptRouter
      JSONContentNode["listItem" | "blockquote" | "doc" | "wrapper"]
          case "wrapper":
              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
  slug: "javascript-sdk/javascript-sdk";
  data: any
  data: any
  data: any
  data: any
  slug: "usage-guide/content-editor";
  data: any
  slug: "usage-guide/getting-started";
  data: any
  slug: "usage-guide/kanban-dashboard";
  data: any
  slug: "usage-guide/metadata";
  data: any
  slug: "usage-guide/publishing";
  data: any
  slug: "usage-guide/vrite-extensions";
  data: any
    })
import { ParentComponent, createSignal } from "solid-js";
import { Button } from "#components/primitives";

interface EndpointCardSectionsProps {
  sections: Array<{ label: string; id: string }>;
}

const EndpointCardSections: ParentComponent<EndpointCardSectionsProps> = (props) => {
  const [activeSection, setActiveSection] = createSignal(props.sections[0].id);

  return (
    <>
      <div class="flex w-full gap-2">
        {props.sections.map((section) => {
          return (
            <Button
              variant={section.id === activeSection() ? "solid" : "text"}
              text={section.id === activeSection() ? "base" : "soft"}
              color="contrast"
              class="py-1 m-0 text-xl font-semibold"
              onClick={() => {
                setActiveSection(section.id);
              }}
            >
              {section.label}
            </Button>
          );
        })}
      </div>
      <div data-active-section={activeSection()}>{props.children}</div>
    </>
  );
};

export { EndpointCardSections };
import { Code } from "astro:components";
import { Button, Card, IconButton } from "#components/primitives";
import curlString from "curl-string";
import { mdiAsterisk } from "@mdi/js";
import { EndpointCardSections } from "./endpoint-card-sections";

interface Props {
    method: string;
    endpoint: string;
    parameters?: Array<{
        name: string;
        required?: boolean;
        description?: string;
        example?:string;
        schema: { type: string; default?:string };
    }>;
    example?: Record<string, any>;
    requestBody?: string;
    response?: string;
}

const body = JSON.stringify( {}, null, 2);
const sections: Array<{ label: string; id: string }> = [];

if (Astro.props.parameters && Astro.props.parameters.length) {
    sections.push({ label: "Parameters", id: "parameters" });
}

if (Astro.props.requestBody) {
    sections.push({ label: "Body", id: "body" });
}

sections.push({ label: "Response", id: "response" });

const queryString = new URLSearchParams(
    (Astro.props.parameters||[]).map((parameter) => {
        return [parameter.name, parameter.example]
    }) as string[][]
).toString();
const url = `https://api.vrite.io${Astro.props.endpoint}${queryString ? `?${queryString}` : ""}`;
const parsedBody = JSON.parse(body);
const curl = curlString(
    `"${url}"`,
    {
        method: Astro.props.method,
        headers: {
            Authorization: `Bearer ${"<YOUR-TOKEN>"}`,
            ...(body === "{}"
                ? {}
                : {
                      "Content-Type": "application/json"
                  }),
            Accept: "application/json"
        },
        ...(body === "{}"
            ? {}
            : {
                  body: parsedBody
              })
    },
    { colorJson: false, jsonIndentWidth: 4 }
);
const code = `${curl}\n`;

<Card class="relative p-4 m-0 gap-2 flex flex-col text-gray-700 dark:text-gray-300 my-4 bg-gray-100 dark:bg-gray-900">
    <div class="flex">
        <Button badge class="m-0 font-mono font-semibold" size="large" color="contrast">
            {Astro.props.method}
            {" "}{Astro.props.endpoint}
        </Button>
    </div>
    <div class="code-block-contrast">
        <Code code={code} lang="shell" />
    </div>
    <EndpointCardSections client:load sections={sections}>
        {
            Astro.props.parameters && Astro.props.parameters.length ? (
                <div class="flex flex-col gap-2 parameters-section">
                    {(Astro.props.parameters || []).map((parameter) => {
                        return (
                            <Card class="m-0 bg-gray-50 dark:bg-gray-800">
                                <div class="flex items-center">
                                    <Button badge text="soft" class="m-0 font-mono font-semibold">
                                        {parameter.name}
                                    </Button>
                                    <span class="!bg-transparent text-sm font-mono px-2 flex-1">
                                        {parameter.schema.type}
                                    </span>
                                    {parameter.required && (
                                        <IconButton
                                            class="m-0"
                                            path={mdiAsterisk}
                                            color="primary"
                                            badge
                                            label="Required"
                                        />
                                    )}
                                </div>
                                {parameter.description && (
                                    <p class="pl-1 m-0 mt-2">{parameter.description}</p>
                                )}
                            </Card>
                        );
                    })}
                </div>
            ): <></>
        }
        {
            Astro.props.requestBody && (
                <div class="code-block-contrast body-section">
                    <Code code={Astro.props.requestBody} lang="typescript"  />
                </div>
            )
        }
        {
            Astro.props.response && (
                <div class="code-block-contrast response-section">
                    <Code code={Astro.props.response} lang="typescript" />
                </div>
            )
        }
    </EndpointCardSections>
</Card>
interface NavigateProps {
  nextEntry?: { label: string; link: string };
  previousEntry?: { label: string; link: string };
const Navigation: Component<NavigateProps> = (props) => {
export { Navigation };
import { mdiAppleKeyboardCommand, mdiMagnify } from "@mdi/js";
import type { Component } from "solid-js";
import { Icon, IconButton } from "#components/primitives";
import { logoIcon } from "#assets/icons";
    <div class="top-0 bg-gray-50 dark:bg-gray-800 border-b-2 border-gray-200 dark:border-gray-700 left-0 z-50 items-center justify-center w-full flex py-2 px-4 md:px-3">
          <div class="hidden xl:flex w-full items-center min-w-48">
            <span class="pl-1 flex-1 text-start">Search</span>
            <kbd class="bg-gray-300 dark:bg-gray-700 group-hover:bg-gray-200 dark:group-hover:bg-gray-800 flex justify-center items-center rounded-md px-1 h-5 text-sm">
              {isAppleDevice() ? <Icon path={mdiAppleKeyboardCommand} class="h-3 w-3" /> : "Ctrl "}K
            </kbd>
        class="@xl:min-w-48 justify-start m-0 group !hidden"
export { Header };
export * from "./navigation";
import { Component, For, onMount, onCleanup, createSignal, createMemo } from "solid-js";
      return heading.depth === 2;
    const observedElements: HTMLElement[] = [];
          "w-56 flex-col justify-start top-0 pt-16 fixed right-0 hidden xl:flex gap-2",
                class="text-start m-0"
                  document.getElementById(heading.slug)?.scrollIntoView({
                    block: "start",
                    inline: "nearest"
                  });
import { mdiMenu, mdiClose, mdiGithub, mdiChevronDown, mdiCodeJson } from "@mdi/js";
import { Component, For, JSX, createSignal } from "solid-js";
import { discordIcon } from "#assets/icons";
  menu: Array<{
    menu: Array<{ label: string; link: string }>;

const externalLinks = [
  {
    label: "GitHub",
    icon: mdiGithub,
    href: "https://github.com/vriteio/vrite"
  },
  {
    label: "Discord",
    icon: discordIcon,
    href: "https://discord.gg/yYqDWyKnqE"
  },
  {
    label: "Vrite Cloud",
    icon: logoIcon,
    href: "https://app.vrite.io"
  },
  {
    label: "API Reference",
    icon: mdiCodeJson,
    href: "https://generator.swagger.io/?url=https://api.vrite.io/swagger.json#"
  }
];
const SideBarNestedMenu: Component<{
  menu: Array<{ label: string; link: string; menu?: Array<{ label: string; link: string }> }>;
}> = (props) => {
    props.menu.filter((item) => {
      return props.currentPath.includes(item.link);
    }).length > 0
                return props.currentPath.includes(item.link);
            menuOpened() ? "" : "translate-y-full md:translate-y-0"
            <For each={externalLinks}>
              {(link) => {
                    target="_blank"
                    href={link.href}
                      path={link.icon}
                      color="contrast"
                      text="soft"
                    <span class=" ml-2 text-gray-500 dark:text-gray-400">{link.label}</span>
          <For each={props.menu}>
                <SideBarNestedMenu currentPath={props.currentPath} menu={menuItem.menu}>
import { Header, BaseHead, SideBar, SVGDefs, OnThisPage } from "#components/fragments";
    <BaseHead description={description} title={title} image={image} />
        <SideBar menu={menu} currentPath={Astro.url.pathname} client:load />
        <div class="flex overflow-hidden w-full relative h-full">
          <div class="flex-1 flex overflow-y-auto overflow-x-hidden justify-center" id="container">
              class="flex-1 prose max-w-screen-md w-full text-lg px-4 pt-4 pb-24 h-fit xl:w-[calc(100%-15rem)]"
[
  {
    "label": "Usage Guide",
    "menu": [
      {
        "label": "Getting Started",
        "link": "/usage-guide/getting-started"
      },
      {
        "label": "Managing Content with Kanban",
        "link": "/usage-guide/kanban-dashboard"
      },
      {
        "label": "Managing metadata",
        "link": "/usage-guide/metadata"
      },
      {
        "label": "Writing in the Vrite Editor",
        "link": "/usage-guide/content-editor"
      },
      {
        "label": "Configuring Vrite",
        "link": "/usage-guide/configuring-vrite"
      },
      {
        "label": "Publishing content",
        "link": "/usage-guide/publishing"
      }
    ]
  },
  {
    "label": "JavaScript SDK",
    "menu": [
      {
        "label": "Introduction",
        "link": "/javascript-sdk/javascript-sdk"
      }
    ]
  },
  {
    "label": "Self-Hosting",
    "menu": [
      {
        "label": "Docker",
        "link": "/self-hosting/docker"
      },
      {
        "label": "Configuration",
        "link": "/self-hosting/configuration"
      }
    ]
  }
]
  type: "content"
  docs: docsCollection
  const blogEntries = await getCollection("docs");
  return blogEntries.map((entry) => ({
    params: { slug: entry.slug },
    props: { entry }
  }));
<DefaultLayout headings={headings} title={entry.data.title}>


    &::before,
    &::before,
    &::before,
    &::before,
    &::before,
    &::before,
    .open-slash-menu > button {
      @apply font-bold dark:bg-gray-900 dark:border-gray-700;
      position: absolute;
      left: -2.5rem;
      background: #f9fafb;
      height: 2rem;
      width: 2rem;
      justify-content: center;
      display: flex;
      align-items: center;
      color: #6b7280;
      border-radius: 25%;
      font-size: 1rem;
      line-height: 1rem;
      text-align: center;
      top: 50%;
      transform: translateY(-50%);
      //border: 2px solid #e5e7eb;
      @apply border-2;
      opacity: 1;
    }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6,
  .open-slash-menu {
    @apply m-0 relative;
    & > button {
      @apply mt-4;
  }
  .open-slash-menu {
    button {
      font-size: 1.25em;
      line-height: 1.25em;
      font-weight: 600;
  :where(h4):not(:where(.not-prose, .not-prose *)) {
    line-height: 2.1rem;
  }
  :where(h5):not(:where(.not-prose, .not-prose *)) {
    line-height: 2.1rem;
  }
  :where(h6):not(:where(.not-prose, .not-prose *)) {
    font-size: 0.875em;
    line-height: 2.1rem;
    "monaco-editor": "^0.40.0",
          for (var i2 = 0; i2 < octets.length; i2 += 1) {
            var octet = octets[i2];
          for (var i2 = 0; i2 < array.length; i2 += 1) {
            var line = array[i2];
            for (var i2 = 0; i2 < length; i2 += 1) {
              var listener = typeListeners[i2];
          for (var i2 = 0; i2 < typeListeners.length; i2 += 1) {
            if (typeListeners[i2] === listener) {
            for (var i2 = 0; i2 < typeListeners.length; i2 += 1) {
              if (typeListeners[i2] !== listener) {
                filtered.push(typeListeners[i2]);
              for (var i2 = 0; i2 < textChunk.length; i2 += 1) {
                var c = textChunk.charCodeAt(i2);
                  n = i2;
                var i2 = url.indexOf("?");
                requestURL = i2 === -1 ? url : url.slice(0, i2 + 1) + url.slice(i2 + 1).replace(/(?:^|&)([^=&]*)(?:=[^&]*)?/g, function(p, paramName) {
          var s = new XMLHttpRequest(), o = [], u2 = [], i2 = {}, a = function() {
              return i2[e2.toLowerCase()];
              return e2.toLowerCase() in i2;
              o.push(n2 = n2.toLowerCase()), u2.push([n2, t2]), i2[n2] = i2[n2] ? i2[n2] + "," + t2 : t2;
    createClient: () => B
  var import_eventsource, i, w, $, U, f, g, L, d, S, D, O, E, R, C, x, m, I, h, j, v, k, q, l, A, u, z, B;
      i = "/content-groups";
      w = (t) => ({ get: (e) => t("GET", `${i}`, { params: e }), list: (e) => t("GET", `${i}/list`, { params: e }), create: (e) => t("POST", `${i}`, { body: e }), update: (e) => t("PUT", `${i}`, { body: e }), delete: (e) => t("DELETE", `${i}`, { params: e }) });
      $ = "/content-pieces";
      U = (t) => ({ get: (e) => t("GET", `${$}`, { params: e }), create: (e) => t("POST", `${$}`, { body: e }), update: (e) => t("PUT", `${$}`, { body: e }), delete: (e) => t("DELETE", `${$}`, { params: e }), list: (e) => t("GET", `${$}/list`, { params: e }) });
        let e = t.baseURL || "https://api.vrite.io", n = t.extensionId || "", c = t.headers || {}, { token: s } = t;
        return { sendRequest: async (a, p, r) => {
            const { default: o } = await Promise.resolve().then(() => __toESM(require_browser2(), 1)), y = await o(`${e}${p}/?${encodeURI(Object.entries(r?.params || {}).filter(([, b]) => b).map(([b, G]) => `${b}=${G}`).join("&"))}`, { headers: { Authorization: `Bearer ${s}`, Accept: "application/json", ...r?.body ? { "Content-Type": "application/json" } : {}, ...n ? { "X-Vrite-Extension-ID": n } : {}, ...c }, body: r?.body ? JSON.stringify(r.body) : null, method: a });
            let T = null;
              if (T = await y.json(), !T)
            if (!y.ok)
              throw T;
            return T;
        }, reconfigure: (a) => {
          e = a.baseURL || e, s = a.token || s, n = a.extensionId || n, c = a.headers || c;
        }, getConfig: () => ({ baseURL: e, token: s, extensionId: n, headers: c }) };
      g = "/user-settings";
      L = (t) => ({ get: () => t("GET", `${g}`), update: (e) => t("PUT", `${g}`, { body: e }) });
      d = "/tags";
      S = (t) => ({ get: (e) => t("GET", `${d}`, { params: e }), update: (e) => t("PUT", `${d}`, { body: e }), create: (e) => t("PUT", `${d}`, { body: e }), delete: (e) => t("DELETE", `${d}`, { params: e }), list: (e) => t("GET", `${d}/list`, { params: e }) });
      D = "/profile";
      O = (t) => ({ get: () => t("GET", `${D}`) });
      E = "/webhooks";
      R = (t) => ({ get: (e) => t("GET", `${E}`, { params: e }), create: (e) => t("POST", `${E}`, { body: e }), update: (e) => t("PUT", `${E}`, { body: e }), delete: (e) => t("DELETE", `${E}`, { params: e }), list: (e) => t("GET", `${E}/list`, { params: e }) });
      x = (t) => ({ get: () => t("GET", `${C}`) });
      m = "/roles";
      I = (t) => ({ get: (e) => t("GET", `${m}`, { params: e }), create: (e) => t("POST", `${m}`, { body: e }), update: (e) => t("PUT", `${m}`, { body: e }), delete: (e) => t("DELETE", `${m}`, { params: e }), list: (e) => t("GET", `${m}/list`, { params: e }) });
      h = "/workspace-settings";
      j = (t) => ({ get: () => t("GET", `${h}`), update: (e) => t("PUT", `${h}`, { body: e }) });
      v = (t) => ({ listMembers: (e) => t("GET", "/workspace-memberships/list-members", { params: e }), listWorkspaces: (e) => t("GET", "/workspace-memberships/list-workspaces", { params: e }), create: (e) => t("POST", "/workspace-memberships", { body: e }), update: (e) => t("PUT", "/workspace-memberships", { body: e }), delete: (e) => t("DELETE", "/workspace-memberships", { params: e }) });
      k = "/extension";
      q = (t) => ({ get: () => t("GET", `${k}`), updateContentPieceData: (e) => t("POST", `${k}/content-piece-data`, { body: e }) });
      l = "/variants";
      A = (t) => ({ create: (e) => t("POST", `${l}`, { body: e }), update: (e) => t("PUT", `${l}`, { body: e }), delete: (e) => t("DELETE", `${l}`, { params: e }), list: () => t("GET", `${l}/list`) });
      u = "/transformers";
      z = (t) => ({ create: (e) => t("POST", `${u}`, { body: e }), delete: (e) => t("DELETE", `${u}`, { params: e }), list: () => t("GET", `${u}/list`) });
      B = (t) => {
        const { sendRequest: e, reconfigure: n, getConfig: c } = f(t);
        return { contentGroups: w(e), contentPieces: U(e), tags: S(e), profile: O(e), userSettings: L(e), webhooks: R(e), workspace: x(e), roles: I(e), workspaceSettings: j(e), workspaceMemberships: v(e), extension: q(e), variants: A(e), transformers: z(e), search(s) {
          return e("GET", "/search", { params: s });
        }, async ask(s) {
          let a = "";
          const p = new import_eventsource.default(`${c().baseURL}/search/ask?query=${encodeURIComponent(s.query)}`, { headers: { Authorization: `Bearer ${c().token}` } });
          p.addEventListener("error", (r) => {
            const o = r;
            return o.message ? s.onError?.(o.message) : (p.close(), s.onEnd?.(a));
          }), p.addEventListener("message", (r) => {
            const o = decodeURIComponent(r.data);
            a += o, s.onChunk?.(o, a);
          });
        }, reconfigure: n };
  "inherit": false,
  "base": "vs-dark",
  "colors": {
    "focusBorder": "#2188ff",
    "foreground": "#444d56",
    "descriptionForeground": "#6a737d",
    "errorForeground": "#cb2431",
    "textLink.foreground": "#0366d6",
    "textLink.activeForeground": "#005cc5",
    "textBlockQuote.background": "#fafbfc",
    "textBlockQuote.border": "#e1e4e8",
    "textCodeBlock.background": "#f6f8fa",
    "textPreformat.foreground": "#586069",
    "textSeparator.foreground": "#d1d5da",
    "button.background": "#159739",
    "button.foreground": "#ffffff",
    "button.hoverBackground": "#138934",
    "checkbox.background": "#fafbfc",
    "checkbox.border": "#d1d5da",
    "dropdown.background": "#fafbfc",
    "dropdown.border": "#e1e4e8",
    "dropdown.foreground": "#2f363d",
    "dropdown.listBackground": "#ffffff",
    "input.background": "#fafbfc",
    "input.border": "#e1e4e8",
    "input.foreground": "#2f363d",
    "input.placeholderForeground": "#959da5",
    "badge.foreground": "#005cc5",
    "badge.background": "#dbedff",
    "progressBar.background": "#2188ff",
    "titleBar.activeForeground": "#2f363d",
    "titleBar.activeBackground": "#ffffff",
    "titleBar.inactiveForeground": "#6a737d",
    "titleBar.inactiveBackground": "#f6f8fa",
    "titleBar.border": "#e1e4e8",
    "activityBar.foreground": "#2f363d",
    "activityBar.inactiveForeground": "#959da5",
    "activityBar.background": "#ffffff",
    "activityBarBadge.foreground": "#ffffff",
    "activityBarBadge.background": "#2188ff",
    "activityBar.activeBorder": "#f9826c",
    "activityBar.border": "#e1e4e8",
    "sideBar.foreground": "#586069",
    "sideBar.background": "#f6f8fa",
    "sideBar.border": "#e1e4e8",
    "sideBarTitle.foreground": "#2f363d",
    "sideBarSectionHeader.foreground": "#2f363d",
    "sideBarSectionHeader.background": "#f6f8fa",
    "sideBarSectionHeader.border": "#e1e4e8",
    "list.hoverForeground": "#2f363d",
    "list.inactiveSelectionForeground": "#2f363d",
    "list.activeSelectionForeground": "#2f363d",
    "list.hoverBackground": "#ebf0f4",
    "list.inactiveSelectionBackground": "#e8eaed",
    "list.activeSelectionBackground": "#e2e5e9",
    "list.inactiveFocusBackground": "#dbedff",
    "list.focusBackground": "#cce5ff",
    "tree.indentGuidesStroke": "#e1e4e8",
    "notificationCenterHeader.foreground": "#6a737d",
    "notificationCenterHeader.background": "#e1e4e8",
    "notifications.foreground": "#2f363d",
    "notifications.background": "#fafbfc",
    "notifications.border": "#e1e4e8",
    "notificationsErrorIcon.foreground": "#d73a49",
    "notificationsWarningIcon.foreground": "#e36209",
    "notificationsInfoIcon.foreground": "#005cc5",
    "pickerGroup.border": "#e1e4e8",
    "pickerGroup.foreground": "#2f363d",
    "quickInput.background": "#fafbfc",
    "quickInput.foreground": "#2f363d",
    "statusBar.foreground": "#586069",
    "statusBar.background": "#ffffff",
    "statusBar.border": "#e1e4e8",
    "statusBar.noFolderBackground": "#ffffff",
    "statusBar.debuggingBackground": "#f9826c",
    "statusBar.debuggingForeground": "#ffffff",
    "editorGroupHeader.tabsBackground": "#f6f8fa",
    "editorGroupHeader.tabsBorder": "#e1e4e8",
    "editorGroup.border": "#e1e4e8",
    "tab.activeForeground": "#2f363d",
    "tab.inactiveForeground": "#6a737d",
    "tab.inactiveBackground": "#f6f8fa",
    "tab.activeBackground": "#ffffff",
    "tab.hoverBackground": "#ffffff",
    "tab.unfocusedHoverBackground": "#ffffff",
    "tab.border": "#e1e4e8",
    "tab.unfocusedActiveBorderTop": "#e1e4e8",
    "tab.activeBorder": "#ffffff",
    "tab.unfocusedActiveBorder": "#ffffff",
    "tab.activeBorderTop": "#f9826c",
    "breadcrumb.foreground": "#6a737d",
    "breadcrumb.focusForeground": "#2f363d",
    "breadcrumb.activeSelectionForeground": "#586069",
    "breadcrumbPicker.background": "#fafbfc",
    "editor.foreground": "#24292e",
    "editor.background": "#f9fafb",
    "editorWidget.background": "#f3f4f6",
    "editorWidget.border": "#e5e7eb",
    "editor.foldBackground": "#fafbfc",
    "editor.lineHighlightBackground": "#f6f8fa",
    "editorLineNumber.foreground": "#1b1f234d",
    "editorLineNumber.activeForeground": "#24292e",
    "editorIndentGuide.background": "#eff2f6",
    "editorIndentGuide.activeBackground": "#d7dbe0",
    "editorWhitespace.foreground": "#d1d5da",
    "editorCursor.foreground": "#044289",
    "editor.findMatchBackground": "#ffdf5d",
    "editor.findMatchHighlightBackground": "#ffdf5d66",
    "editor.inactiveSelectionBackground": "#0366d611",
    "editor.selectionBackground": "#0366d625",
    "editor.selectionHighlightBackground": "#34d05840",
    "editor.selectionHighlightBorder": "#34d05800",
    "editor.wordHighlightBackground": "#34d05800",
    "editor.wordHighlightStrongBackground": "#34d05800",
    "editor.wordHighlightBorder": "#24943e99",
    "editor.wordHighlightStrongBorder": "#24943e50",
    "editorBracketMatch.background": "#34d05840",
    "editorBracketMatch.border": "#34d05800",
    "editorGutter.modifiedBackground": "#2188ff",
    "editorGutter.addedBackground": "#28a745",
    "editorGutter.deletedBackground": "#d73a49",
    "diffEditor.insertedTextBackground": "#34d05822",
    "diffEditor.removedTextBackground": "#d73a4922",
    "scrollbar.shadow": "#6a737d33",
    "scrollbarSlider.background": "#959da533",
    "scrollbarSlider.hoverBackground": "#959da544",
    "scrollbarSlider.activeBackground": "#959da588",
    "editorOverviewRuler.border": "#ffffff",
    "panel.background": "#f6f8fa",
    "panel.border": "#e1e4e8",
    "panelTitle.activeBorder": "#f9826c",
    "panelTitle.activeForeground": "#2f363d",
    "panelTitle.inactiveForeground": "#6a737d",
    "panelInput.border": "#e1e4e8",
    "terminal.foreground": "#586069",
    "gitDecoration.addedResourceForeground": "#28a745",
    "gitDecoration.modifiedResourceForeground": "#005cc5",
    "gitDecoration.deletedResourceForeground": "#d73a49",
    "gitDecoration.untrackedResourceForeground": "#28a745",
    "gitDecoration.ignoredResourceForeground": "#959da5",
    "gitDecoration.conflictingResourceForeground": "#e36209",
    "gitDecoration.submoduleResourceForeground": "#959da5",
    "debugToolBar.background": "#ffffff",
    "editor.stackFrameHighlightBackground": "#fffbdd",
    "editor.focusedStackFrameHighlightBackground": "#fff5b1",
    "settings.headerForeground": "#2f363d",
    "settings.modifiedItemIndicator": "#2188ff",
    "welcomePage.buttonBackground": "#f6f8fa",
    "welcomePage.buttonHoverBackground": "#e1e4e8"
  },
      "foreground": "#6a737d",
      "token": "comment"
    },
    {
      "foreground": "#6a737d",
      "token": "punctuation.definition.comment"
    },
    {
      "foreground": "#6a737d",
      "token": "string.comment"
    },
    {
      "foreground": "#005cc5",
      "token": "constant"
    },
    {
      "foreground": "#005cc5",
      "token": "entity.name.constant"
    },
    {
      "foreground": "#005cc5",
      "token": "variable.other.constant"
    },
    {
      "foreground": "#005cc5",
      "token": "variable.language"
    },
    {
      "foreground": "#6f42c1",
      "token": "entity"
    },
    {
      "foreground": "#6f42c1",
      "token": "entity.name"
    },
    {
      "foreground": "#24292e",
      "token": "variable.parameter.function"
    },
    {
      "foreground": "#22863a",
      "token": "entity.name.tag"
    },
    {
      "foreground": "#d73a49",
      "token": "keyword"
    },
    {
      "foreground": "#d73a49",
      "token": "storage"
    },
    {
      "foreground": "#d73a49",
      "token": "storage.type"
    },
    {
      "foreground": "#24292e",
      "token": "storage.modifier.package"
    },
    {
      "foreground": "#24292e",
      "token": "storage.modifier.import"
    },
    {
      "foreground": "#24292e",
      "token": "storage.type.java"
    },
    {
      "foreground": "#032f62",
      "token": "string"
    },
    {
      "foreground": "#032f62",
      "token": "punctuation.definition.string"
    },
    {
      "foreground": "#032f62",
      "token": "string punctuation.section.embedded source"
    },
    {
      "foreground": "#005cc5",
      "token": "support"
    },
    {
      "foreground": "#005cc5",
      "token": "meta.property-name"
    },
    {
      "foreground": "#e36209",
      "token": "variable"
    },
    {
      "foreground": "#24292e",
      "token": "variable.other"
    },
    {
      "fontStyle": "italic",
      "foreground": "#b31d28",
      "token": "invalid.broken"
    },
    {
      "fontStyle": "italic",
      "foreground": "#b31d28",
      "token": "invalid.deprecated"
    },
    {
      "fontStyle": "italic",
      "foreground": "#b31d28",
      "token": "invalid.illegal"
    },
    {
      "fontStyle": "italic",
      "foreground": "#b31d28",
      "token": "invalid.unimplemented"
    },
    {
      "fontStyle": "italic underline",
      "background": "#d73a49",
      "foreground": "#fafbfc",
      "content": "^M",
      "token": "carriage-return"
    },
    {
      "foreground": "#b31d28",
      "token": "message.error"
    },
    {
      "foreground": "#24292e",
      "token": "string source"
    },
    {
      "foreground": "#005cc5",
      "token": "string variable"
    },
    {
      "foreground": "#032f62",
      "token": "source.regexp"
    },
    {
      "foreground": "#032f62",
      "token": "string.regexp"
    },
    {
      "foreground": "#032f62",
      "token": "string.regexp.character-class"
    },
    {
      "foreground": "#032f62",
      "token": "string.regexp constant.character.escape"
    },
    {
      "foreground": "#032f62",
      "token": "string.regexp source.ruby.embedded"
    },
    {
      "foreground": "#032f62",
      "token": "string.regexp string.regexp.arbitrary-repitition"
    },
    {
      "fontStyle": "bold",
      "foreground": "#22863a",
      "token": "string.regexp constant.character.escape"
    },
    {
      "foreground": "#005cc5",
      "token": "support.constant"
    },
    {
      "foreground": "#005cc5",
      "token": "support.variable"
    },
    {
      "foreground": "#005cc5",
      "token": "meta.module-reference"
    },
    {
      "foreground": "#e36209",
      "token": "punctuation.definition.list.begin.markdown"
    },
    {
      "fontStyle": "bold",
      "foreground": "#005cc5",
      "token": "markup.heading"
    },
    {
      "fontStyle": "bold",
      "foreground": "#005cc5",
      "token": "markup.heading entity.name"
    },
    {
      "foreground": "#22863a",
      "token": "markup.quote"
    },
    {
      "fontStyle": "italic",
      "foreground": "#24292e",
      "token": "markup.italic"
    },
    {
      "fontStyle": "bold",
      "foreground": "#24292e",
      "token": "markup.bold"
    },
    {
      "foreground": "#005cc5",
      "token": "markup.raw"
    },
    {
      "background": "#ffeef0",
      "foreground": "#b31d28",
      "token": "markup.deleted"
    },
    {
      "background": "#ffeef0",
      "foreground": "#b31d28",
      "token": "meta.diff.header.from-file"
    },
    {
      "background": "#ffeef0",
      "foreground": "#b31d28",
      "token": "punctuation.definition.deleted"
    },
    {
      "background": "#f0fff4",
      "foreground": "#22863a",
      "token": "markup.inserted"
    },
    {
      "background": "#f0fff4",
      "foreground": "#22863a",
      "token": "meta.diff.header.to-file"
    },
    {
      "background": "#f0fff4",
      "foreground": "#22863a",
      "token": "punctuation.definition.inserted"
    },
    {
      "background": "#ffebda",
      "foreground": "#e36209",
      "token": "markup.changed"
    },
    {
      "background": "#ffebda",
      "foreground": "#e36209",
      "token": "punctuation.definition.changed"
    },
    {
      "foreground": "#f6f8fa",
      "background": "#005cc5",
      "token": "markup.ignored"
    },
    {
      "foreground": "#f6f8fa",
      "background": "#005cc5",
      "token": "markup.untracked"
    },
    {
      "foreground": "#6f42c1",
      "fontStyle": "bold",
      "token": "meta.diff.range"
    },
    {
      "foreground": "#005cc5",
      "token": "meta.diff.header"
    },
    {
      "fontStyle": "bold",
      "foreground": "#005cc5",
      "token": "meta.separator"
    },
    {
      "foreground": "#005cc5",
      "token": "meta.output"
    },
    {
      "foreground": "#586069",
      "token": "brackethighlighter.tag"
    },
    {
      "foreground": "#586069",
      "token": "brackethighlighter.curly"
    },
    {
      "foreground": "#586069",
      "token": "brackethighlighter.round"
    },
    {
      "foreground": "#586069",
      "token": "brackethighlighter.square"
    },
    {
      "foreground": "#586069",
      "token": "brackethighlighter.angle"
    },
    {
      "foreground": "#586069",
      "token": "brackethighlighter.quote"
    },
    {
      "foreground": "#b31d28",
      "token": "brackethighlighter.unmatched"
    },
    {
      "foreground": "#032f62",
      "fontStyle": "underline",
      "token": "constant.other.reference.link"
    },
    {
      "foreground": "#032f62",
      "fontStyle": "underline",
      "token": "string.other.link"
  "encodedTokensColors": []
        theme: "dark-contrast",
      createEffect(() => {
        props.monaco.editor.setTheme(
          `${codeEditorTheme()}${props.color === "contrast" ? "-contrast" : ""}`
        );
      });
          "w-full bg-gray-100 border-2 not-prose dark:bg-gray-900 rounded-2xl dark:border-gray-700 rounded",
    userSettings = () => ({ accentColor: "energy", codeEditorTheme: "dark", uiTheme: "auto" })
          } else if (action === "createWrapper") {
            setWorkspaceSettings((workspaceSettings) => ({
              ...workspaceSettings!,
              wrappers: [...(workspaceSettings?.wrappers || []), data]
            }));
          } else if (action === "deleteWrapper") {
            setWorkspaceSettings((workspaceSettings) => ({
              ...workspaceSettings!,
              wrappers: (workspaceSettings?.wrappers || []).filter(
                (wrapper) => wrapper.key !== data.key
              )
            }));
          } else if (action === "updateWrapper") {
            setWorkspaceSettings((workspaceSettings) => ({
              ...workspaceSettings!,
              wrappers: (workspaceSettings?.wrappers || []).map((wrapper) => {
                if (wrapper.key === data.key) {
                  return {
                    ...wrapper,
                    ...data
                  };
                }

                return wrapper;
              })
            }));
              if (error.data?.code === "UNAUTHORIZED") {
  "gpt-3.5": () => import("@vrite/extensions/gpt-3.5.json")
        ":base-2: p-1 w-full flex items-center border-b-2 absolute h-12 border-gray-200 dark:border-gray-700 justify-end @container z-1",
  json: "yaml",
  scss: "scss"
    case "json":
      plugins: parserPlugins,
      ...(language === "json" && {
        trailingComma: "none",
        singleQuote: false
      })
const useSuggestLanguage = (
  languages: monaco.languages.ILanguageExtensionPoint[]
): ((query: string) => string[]) => {
  const languageIds = getLanguageIds(languages);
    engine.addAll(languageIds);
import { CodeBlock, Embed, Image, Wrapper } from "./extensions";
    wrapper: Wrapper,
      label: "Wrapper",
      block: "wrapper",
        return editor.chain().focus().deleteRange(range).setWrapper().run();
                    return node()?.hasMarkup(props.state.editor.schema.nodes[block]);
      } catch (e) {
import { useSolidNodeView } from "@vrite/tiptap-solid";
import { mdiCodeTagsCheck } from "@mdi/js";
import type { monaco } from "#lib/monaco";
import { IconButton, Input, Tooltip } from "#components/primitives";
  monaco: typeof monaco;
  changeLanguage(languageId: string | null): void;
  const { state } = useSolidNodeView();
  const attrs = (): CodeBlockAttributes => state().node.attrs;
  const suggestLanguage = useSuggestLanguage(props.monaco.languages.getLanguages());
  const formattingAvailable = createMemo(() => {
    return isFormattable(attrs().lang || "");
  });
    on(attrs, () => {
      setSuggestions(suggestLanguage(attrs().lang || ""));
      props.changeLanguage(attrs().lang || null);
    <div class="flex p-0 transition-shadow duration-200 border-0 rounded-xl">
      <Input
        wrapperClass="flex-1 max-w-full"
        placeholder="Language"
        value={attrs().lang || ""}
        suggestions={suggestions()}
        color="contrast"
        disabled={!state().editor.isEditable}
        setValue={(value) => {
          state().updateAttributes({ lang: value });
        }}
      />
      <Show when={state().editor.isEditable}>
        <Tooltip text={formattingAvailable() ? "Format" : "Formatting unavailable"}>
            path={mdiCodeTagsCheck}
            color="contrast"
            text="soft"
            disabled={!formattingAvailable()}
            onClick={props.format}
      </Show>
          <NodeViewWrapper class="my-5">
import { Component, createEffect, createSignal, onMount } from "solid-js";
import { Card } from "#components/primitives";
import {
  useAppearance,
  useAuthenticatedUserData,
  useNotifications,
  useLocalStorage
} from "#context";
      const formattedCode = await formattingCode;
    const contentHeight = Math.max(200, monacoEditor.getContentHeight());
        theme: "dark",
        "relative rounded-2xl not-prose text-base leading-4",
          "w-full bg-gray-50 dark:bg-gray-900 h-72 not-prose rounded-t-2xl rounded",
          codeEditorTheme() === "light" && "border-2 border-b-0 dark:border-0"
      <Card
          "m-0 rounded-t-none",
          codeEditorTheme() === "dark" && "border-t-0 dark:border-0 dark:border-t-2",
          codeEditorTheme() === "light" && "dark:border-t-0"
        contentEditable={false}
        <CodeBlockMenu monaco={props.monaco} format={format} changeLanguage={changeLanguage} />
      </Card>
          if (container.parentElement?.classList.contains("ProseMirror")) {
            const parentPos = document.getElementById("pm-container")?.getBoundingClientRect();
              top: rect.top - parentPos.top - 20
import { Component } from "solid-js";
import { mdiDotsGrid } from "@mdi/js";
import { IconButton, Input, Tooltip } from "#components/primitives";
import { EmbedType, getEmbedId, getEmbedSrc } from "#lib/utils";
    <div class="flex p-0 transition-shadow duration-200 border-0 rounded-xl">
      <Input
        wrapperClass="flex-1 max-w-full"
        color="contrast"
        placeholder={getInputPlaceholder(attrs().embed as EmbedType)}
        value={attrs().input || ""}
        disabled={!props.state.editor.isEditable}
        setValue={(value) => {
          props.state.updateAttributes({ input: value, src: getSrc(value) });
        }}
      />
import { Card, Icon } from "#components/primitives";
    <NodeViewWrapper class="my-5">
                "pt-[35%] w-full rounded-t-2xl bg-gradient-to-tr flex justify-center items-center relative"
            class="object-contain w-full m-0 transition-opacity duration-300 border-2 border-gray-200 dark:border-gray-700 aspect-video min-h-96 rounded-t-2xl"

        <Card class="m-0 border-t-0 rounded-t-none">
        </Card>
import { Component, createSignal, Show } from "solid-js";
import { uploadFile as uploadFileUtil } from "#lib/utils";
import { Button, IconButton, Input, Loader, Tooltip } from "#components/primitives";
  const inputId = nanoid();
      if (uploadedUrl) {
        props.state.updateAttributes({ src: uploadedUrl });
      }
  const getPlaceholder = (): string => {
    if (inputMode() === "src") {
      return options().cover ? "Cover image URL" : "Image URL";
    }

    return options().cover ? "Cover alt description" : "Alt description";
  };
    <div class="flex p-0 transition-shadow duration-200 border-0 rounded-xl">
      <Tooltip text="Alt">
        <IconButton
          path={mdiText}
          color={inputMode() === "alt" ? "primary" : "contrast"}
          text={inputMode() === "alt" ? "primary" : "soft"}
          onClick={() => {
            setInputMode("alt");
        ></IconButton>
      </Tooltip>
      <Tooltip text="Image URL">
        <IconButton
          path={mdiLinkVariant}
          color={inputMode() === "src" ? "primary" : "contrast"}
          text={inputMode() === "src" ? "primary" : "soft"}
          onClick={() => {
            setInputMode("src");
          }}
        ></IconButton>
      </Tooltip>
      <Input
        color="contrast"
        wrapperClass="flex-1 max-w-full min-w-unset"
        class="w-full"
        placeholder={getPlaceholder()}
        value={attrs()[inputMode()] || ""}
        disabled={!props.state.editor.isEditable}
        setValue={(value) => {
          updateAttribute.clear();
          updateAttribute(inputMode(), value);
        }}
      />
      <Show when={props.state.editor.isEditable}>
          <Tooltip text={uploading() ? "Uploading" : "Upload image"}>
            <Show
              when={!uploading()}
              fallback={
                <Button badge color="contrast" class="flex items-center justify-center w-8 h-8">
                  <Loader class="w-6 h-6" />
                </Button>
              }
            >
              <IconButton path={mdiUpload} color="contrast" text="soft" badge></IconButton>
            </Show>
      </Show>
import { Card, Icon, Loader } from "#components/primitives";
  const [currentSrc, setCurrentSrc] = createRef("");
    if (objectURL()) {
    try {
      if (!src) {
        setError(false);
        setLoading(false);

        return;
      }

      if (!validateURL(src)) {
        setError(true);
        setLoading(false);

        return;
      }

      const response = await fetch(
        src.startsWith(window.env.PUBLIC_ASSETS_URL) ? src : `/proxy?url=${encodeURIComponent(src)}`
      );

      if (!response.ok) {
        setError(true);
        setLoading(false);

        return;
      }
      const blob = await response.blob();
      const objectURL = URL.createObjectURL(blob);
      setCurrentSrc(src);
      setObjectURL(objectURL);
    } catch (error) {
    } finally {
    <NodeViewWrapper class={clsx(!options().cover && "my-5")}>
            options().cover ? "border-b-2" : "border-2 rounded-t-2xl"
          <Show
            when={objectURL()}
            fallback={
              <div
                class={clsx(
                  "w-full bg-gradient-to-tr flex justify-center items-center relative",
                  options().cover ? "min-h-48" : "rounded-t-2xl"
                )}
                style={{
                  "padding-top": getPaddingTop()
                }}
              >
                <div class="absolute flex flex-col items-center justify-center font-bold text-white transform -translate-y-1/2 top-1/2">
                  <Show when={!loading()} fallback={<Loader class="w-8 h-8" />}>
                    <Show
                      when={!error()}
                      fallback={
                        <>
                          <Icon path={mdiAlertCircle} class="w-16 h-16" />
                          <span class="absolute top-full">Error</span>
                        </>
                      }
                    >
                      <Icon path={mdiImage} class="w-16 h-16" />
                    </Show>
                  </Show>
                </div>
              </div>
            }
                "w-full border-gray-200 dark:border-gray-700 flex justify-center items-center overflow-hidden bg-gray-100 dark:bg-gray-800 relative",
                !options().cover && "rounded-t-2xl"
              <div
                class={clsx(
                  "overflow-hidden min-w-40 !h-full",
                  state().editor.isEditable && "resize"
                )}
                ref={handleNewImageContainer}
                style={{ width: attrs().width }}
              >
                <img
                  alt={attrs().alt}
                  src={objectURL()}
                  data-src={currentSrc()}
                  class={clsx("object-contain w-full m-0 transition-opacity duration-300")}
                  onLoad={(event) => {
                    const image = event.currentTarget;
                    const w = image.naturalWidth;
                    const h = image.naturalHeight;
                    const aspectRatio = w / h;

                    updateAspectRatio.clear();
                    updateAspectRatio(`${aspectRatio}`);
                  }}
                  onError={() => {
                    removeImage();
                    setError(true);
                  }}
                />
        <Card
            "m-0 border-0 border-b-2 rounded-t-none",
            options().cover ? "rounded-none" : "border-x-2"
        </Card>
export * from "./wrapper";
  block?: App.WorkspaceSettings["blocks"][number] | "wrapper";
import { Component, createEffect, createSignal } from "solid-js";
import { SearchableSelect } from "#components/fragments";
import { App, useAuthenticatedUserData } from "#context";

interface WrapperMenuProps {
  state: {
    key: string;
    setKey(key: string): void;
  };
}

const WrapperMenu: Component<WrapperMenuProps> = (props) => {
  const { workspaceSettings } = useAuthenticatedUserData();
  const selectedOption = (): App.Wrapper | null => {
    return (
      (workspaceSettings()?.wrappers || []).find((wrapper) => wrapper.key === props.state.key) ||
      null
    );
  };

  props.state.setKey(selectedOption()?.key || "");

  return (
    <div class="w-full flex items-center justify-start text-base" contentEditable={false}>
      <div>
        <SearchableSelect
          extractId={(option) => option.key}
          filterOption={(option, query) => option.label.toLowerCase().includes(query.toLowerCase())}
          options={workspaceSettings()?.wrappers || []}
          renderOption={(option) => <div class="text-start">{option.label}</div>}
          selectOption={(option) => {
            props.state.setKey(option?.key || "");
          }}
          selected={selectedOption()}
          loading={false}
          placeholder="Wrapper"
          buttonProps={{
            class: "bg-gray-100",
            color: "base",
            text: "soft"
          }}
        />
      </div>
    </div>
  );
};

export { WrapperMenu };
import { WrapperMenu } from "./menu";
import { Wrapper as BaseWrapper, WrapperAttributes } from "@vrite/editor";
import { SolidEditor, SolidRenderer } from "@vrite/tiptap-solid";
import { NodeView } from "@tiptap/core";
import { keymap } from "@tiptap/pm/keymap";
import { Node } from "@tiptap/pm/model";
import { EditorState } from "@tiptap/pm/state";

const Wrapper = BaseWrapper.extend({
  addProseMirrorPlugins() {
    const handleDeleteWrapper = (state: EditorState): boolean => {
      if (this.editor.isActive("wrapper")) {
        const currentDepth = state.selection.$from.depth;

        let node: Node | null = null;
        let pos: number | null = null;

        for (let i = currentDepth; i >= 0; i--) {
          const currentNode = state.selection.$from.node(i);

          if (currentNode.type.name === "wrapper") {
            node = currentNode;
            pos = i > 0 ? state.selection.$from.before(i) : 0;
            break;
          }
        }

        if (
          node &&
          !node.textContent &&
          node.content.childCount === 1 &&
          node.content.firstChild?.type.name === "paragraph" &&
          typeof pos === "number"
        ) {
          this.editor
            .chain()
            .deleteRange({
              from: pos,
              to: pos + node.nodeSize
            })
            .focus()
            .run();

          return true;
        }
      }

      return false;
    };

    return [
      keymap({
        Delete: handleDeleteWrapper,
        Backspace: handleDeleteWrapper
      })
    ];
  },
  addNodeView() {
    const editor = this.editor as SolidEditor;

    return (props) => {
      let node = props.node as Node;

      const referenceView = new NodeView(() => {}, props);
      const dom = document.createElement("div");
      const content = document.createElement("div");
      const menu = document.createElement("div");

      dom.setAttribute(
        "class",
        "px-3 pt-3 my-5 rounded-3xl border-gray-300 bg-gray-300 bg-opacity-30 dark:border-gray-700 dark:bg-gray-700 dark:bg-opacity-40 border-2"
      );
      dom.setAttribute("data-wrapper", "true");
      content.setAttribute("class", "relative content mb-3");
      menu.setAttribute("class", "mb-5");
      menu.contentEditable = "false";

      const renderer = new SolidRenderer<{ key: string; setKey(value: string): void }>(
        WrapperMenu,
        {
          editor: this.editor as SolidEditor,
          state: {
            key: node.attrs.key,
            setKey: (key) => {
              if (typeof props.getPos === "function") {
                editor.view.dispatch(
                  editor.view.state.tr.setNodeMarkup(props.getPos(), undefined, {
                    key: key || null
                  })
                );
              }
            }
          }
        }
      );

      menu.append(renderer.element);
      dom.append(menu, content);

      return {
        dom,
        contentDOM: content,
        ignoreMutation(mutation: MutationRecord | { type: "selection"; target: Element }) {
          if (mutation.type === "selection") {
            return false;
          }

          return referenceView.ignoreMutation(mutation);
        },
        stopEvent(event) {
          return referenceView.stopEvent(event);
        },
        destroy() {
          renderer.destroy();
        },
        update(newNode) {
          if (newNode.type.name !== "wrapper") return false;

          node = newNode as Node;
          renderer.setState((state) => ({
            ...state,
            key: node.attrs.key
          }));

          return true;
        }
      };
    };
  }
});

export { Wrapper };
export type { WrapperAttributes };
monaco.editor.defineTheme("light", { ...lightTheme, base: "vs-dark" });
monaco.editor.defineTheme("dark-contrast", {
  ...darkTheme,
  colors: {
    ...darkTheme.colors,
    "editor.background": "#1f2937",
    "editorWidget.background": "#111827"
  },
  base: "vs-dark"
});
monaco.editor.defineTheme("light-contrast", {
  ...lightTheme,
  colors: {
    ...lightTheme.colors,
    "editor.background": "#f3f4f6",
    "editorWidget.background": "#f9fafb"
  },
  base: "vs-dark"
});
  width: 100%;
  width: 100% !important;
  top: -19px !important;
  @apply !border-primary my-2;
  .ProseMirror:not(:where(.not-prose, .not-prose *)) {
    > * + div:not(.tableWrapper) {
      @apply mb-5;
    }

    padding-bottom: 8rem;
      @apply border-2 border-gray-200 dark:border-gray-700;
      @apply text-left font-500 border-2 border-gray-200 dark:border-gray-700 relative p-2 vertical-top;
    @apply my-5;
    @apply m-0;
  --highlighted-thread: "G3JAKWBAsWA1xXnPcJ-Zu";
  :where(div[data-wrapper="true"]) {
    .content > :first-child [data-node-view-wrapper="true"] {
    .content > :last-child:not([data-wrapper="true"]) {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
      "Courier New", monospace !important;
.rounded {
  .monaco-editor,
  .monaco-editor > *:first-child {
    @apply rounded-2xl;
  }
  .monaco-editor .editor-widget {
    @apply overflow-hidden rounded-lg;
  }
  .monaco-editor .monaco-hover {
    @apply rounded-lg;
  }
}

.ProseMirror .rounded .monaco-editor,
.ProseMirror .rounded .monaco-editor > *:first-child {
        <div class="h-full w-full absolute top-0 left-0 bg-gray-100 dark:bg-gray-800 flex justify-center items-center">
            props.setSlug(convertToSlug(value));
import { AllSelection } from "@tiptap/pm/state";
    if (!view.hasFocus() || isAllSelection) {
      ["image", "codeBlock", "embed", "horizontalRule"].some((name) => {
      $anchor.depth === 1 || ($anchor.depth === 2 && $anchor.node(1).type.name === "wrapper");
import { SolidEditor } from "@vrite/tiptap-solid";
import {
  mdiFormatBold,
  mdiFormatItalic,
  mdiFormatStrikethrough,
  mdiCodeTags,
  mdiLinkVariant,
  mdiFormatColorHighlight,
  mdiFormatSubscript,
  mdiFormatSuperscript,
  mdiCheck,
  mdiDelete,
  mdiTableColumnRemove,
  mdiTableRowRemove,
  mdiTableMergeCells,
  mdiTableSplitCell,
  mdiTableRemove,
  mdiCommentOutline,
  mdiTableHeadersEyeOff,
  mdiPlus,
  mdiKeyboardCloseOutline
} from "@mdi/js";
import { CellSelection } from "@tiptap/pm/tables";
import { Component, createEffect, createSignal, For, Match, on, Show, Switch } from "solid-js";
import { nanoid } from "nanoid";
import clsx from "clsx";
import { breakpoints, createRef, Ref } from "#lib/utils";
import { Card, IconButton, Input, Tooltip } from "#components/primitives";
import { App, useAuthenticatedUserData, useClient } from "#context";

type BubbleMenuMode = "format" | "link" | "table" | "block";
interface BubbleMenuProps {
  editor: SolidEditor;
  opened: boolean;
  contentPieceId?: string;
  class?: string;
  mode?: BubbleMenuMode;
  ref?: Ref<HTMLElement>[1];
  blur?(): void;
  setBlockMenuOpened?(opened: boolean): void;
}

const BubbleMenu: Component<BubbleMenuProps> = (props) => {
  const [activeMarks, setActiveMarks] = createSignal<string[]>([]);
  const { workspaceSettings = () => null } = useAuthenticatedUserData() || {};
  const client = useClient();
  const [mode, setMode] = createSignal<BubbleMenuMode>("format");
  const [link, setLink] = createSignal("");
  const [linkInputRef, setLinkInputRef] = createRef<HTMLInputElement | null>(null);
  const commentMenuItem = {
    icon: mdiCommentOutline,
    mark: "comment",
    label: "Comment",
    async onClick() {
      if (props.editor.isActive("comment")) {
        props.editor.commands.unsetComment();
      } else {
        const threadFragment = nanoid();

        props.editor.chain().setComment({ thread: threadFragment }).focus().run();

        try {
          await client.comments.createThread.mutate({
            contentPieceId: props.contentPieceId || "",
            fragment: threadFragment
          });
        } catch (error) {
          props.editor.commands.unsetComment();
        }
      }
    }
  };
  const closeKeyboardItem = {
    icon: mdiKeyboardCloseOutline,
    label: "Close keyboard",
    async onClick() {
      props.blur?.();
    }
  };
  const menus = (
    [
      {
        icon: mdiFormatBold,
        mark: "bold",
        label: "Bold"
      },
      {
        icon: mdiFormatItalic,
        mark: "italic",
        label: "Italic"
      },
      {
        icon: mdiFormatStrikethrough,
        mark: "strike",
        label: "Strike"
      },
      {
        icon: mdiCodeTags,
        mark: "code",
        label: "Code"
      },
      {
        icon: mdiLinkVariant,
        mark: "link",
        label: "Link",
        onClick() {
          setMode("link");
        }
      },
      { icon: mdiFormatColorHighlight, mark: "highlight", label: "Highlight" },
      { icon: mdiFormatSubscript, mark: "subscript", label: "Subscript" },
      { icon: mdiFormatSuperscript, mark: "superscript", label: "Superscript" },
      ...(props.contentPieceId && breakpoints.md() ? [commentMenuItem] : []),
      ...(breakpoints.md() ? [] : [closeKeyboardItem])
    ] as Array<{ icon: string; mark?: string; label: string; onClick?(): void }>
  ).filter(({ mark }) => {
    if (!mark || mark === "comment") return true;

    if (!workspaceSettings()) {
      return true;
    }

    return workspaceSettings()!.marks.includes(mark as App.WorkspaceSettings["marks"][number]);
  });
  const tableMenus = [
    {
      icon: mdiTableHeadersEyeOff,
      label: "Toggle header cell off",
      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);
          const rowNode = selection.$anchorCell.node(2);

          if (tableNode.child(0) === rowNode) {
            return false;
          }

          return selection.$anchorCell.nodeAfter?.type.name === "tableHeader";
        }

        return false;
      },
      onClick() {
        props.editor.chain().toggleHeaderCell().focus().run();
      }
    },
    {
      icon: mdiTableMergeCells,
      label: "Merge cells",
      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          return selection.$anchorCell.pos !== selection.$headCell.pos;
        }

        return false;
      },
      onClick() {
        props.editor.chain().mergeCells().run();
      }
    },
    {
      icon: mdiTableSplitCell,
      label: "Split cell",
      show() {
        const { selection } = props.editor.state;

        if (
          selection instanceof CellSelection &&
          selection.$anchorCell.pos === selection.$headCell.pos
        ) {
          return (
            selection.$anchorCell.nodeAfter?.attrs.colspan > 1 ||
            selection.$anchorCell.nodeAfter?.attrs.rowspan > 1
          );
        }

        return false;
      },
      onClick() {
        props.editor.chain().splitCell().run();
      }
    },
    {
      icon: mdiTableColumnRemove,
      label: "Delete column(s)",
      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);

          let isSingleColumn = false;

          tableNode.content.forEach((rowNode) => {
            isSingleColumn = rowNode.childCount === 1;
          });

          return !isSingleColumn;
        }

        return true;
      },
      onClick() {
        props.editor.chain().deleteColumn().focus().run();
      }
    },
    {
      icon: mdiTableRowRemove,
      label: "Delete row(s)",

      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);

          if (tableNode.content.childCount === 1) {
            return false;
          }
        }

        return true;
      },
      onClick() {
        props.editor.chain().deleteRow().focus().run();
      }
    },
    {
      icon: mdiTableRemove,
      label: "Delete table",

      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);

          if (tableNode.childCount === 1) return true;

          let isSingleColumn = false;

          tableNode.content.forEach((rowNode) => {
            isSingleColumn = rowNode.childCount === 1;
          });

          return isSingleColumn;
        }

        return false;
      },
      onClick() {
        props.editor.chain().deleteTable().focus().run();
      }
    }
  ];
  const marks = menus.map((menu) => menu.mark);
  const saveLink = (): void => {
    props.editor.chain().unsetCode().setLink({ href: link() }).focus().run();
    setMode("format");
  };

  props.editor.on("update", () => {
    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
  });
  props.editor.on("selectionUpdate", () => {
    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);

    if (props.editor.state.selection instanceof CellSelection) {
      setMode("table");
    } else if (!props.editor.state.selection.empty) {
      setMode("format");
    }
  });
  createEffect(
    on(mode, (mode) => {
      if (mode === "link") {
        setLink(props.editor.getAttributes("link").href || "");
        setTimeout(() => {
          const linkInput = linkInputRef();

          linkInput?.focus();
        }, 300);
      } else {
        setLink("");
      }
    })
  );
  createEffect(
    on(
      () => props.mode,
      (mode) => {
        setMode((currentMode) => mode || currentMode);
      }
    )
  );
  createEffect(
    on(
      () => props.opened,
      (opened) => {
        if (!opened) {
          setLink("");
          setTimeout(() => {
            setMode("format");
          }, 300);
        }
      }
    )
  );

  return (
    <Card
      class={clsx(
        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial",
        props.class
      )}
      ref={props.ref}
    >
      <Switch>
        <Match when={mode() === "block"}>
          <IconButton
            path={mdiPlus}
            text="soft"
            variant="text"
            label="Insert block"
            onClick={(event) => {
              props.setBlockMenuOpened?.(true);
              event.preventDefault();
              event.stopPropagation();
            }}
          />
          <IconButton
            path={mdiKeyboardCloseOutline}
            text="soft"
            variant="text"
            onClick={(event) => {
              props.blur?.();
              event.preventDefault();
              event.stopPropagation();
            }}
          />
        </Match>
        <Match when={mode() === "table"}>
          <For
            each={tableMenus}
            fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
          >
            {(menuItem) => {
              return (
                <Show when={!menuItem.show || menuItem.show()}>
                  <Tooltip text={menuItem.label} side="bottom" wrapperClass="snap-start">
                    <IconButton
                      path={menuItem.icon}
                      text="soft"
                      variant="text"
                      color="base"
                      onClick={(event) => {
                        menuItem.onClick();
                        event.preventDefault();
                        event.stopPropagation();
                      }}
                    />
                  </Tooltip>
                </Show>
              );
            }}
          </For>
        </Match>
        <Match when={mode() === "format"}>
          <div class="flex">
            <For
              each={menus}
              fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
            >
              {(menu) => {
                const active = (): boolean => {
                  return Boolean(menu.mark && activeMarks().includes(menu.mark));
                };

                return (
                  <Tooltip text={menu.label} side="bottom" wrapperClass="snap-start">
                    <IconButton
                      path={menu.icon}
                      text={active() ? "primary" : "soft"}
                      variant={active() ? "solid" : "text"}
                      color={active() ? "primary" : "base"}
                      onClick={(event) => {
                        const chain = props.editor.chain();

                        if (menu.onClick) {
                          menu.onClick();
                        } else if (menu.mark) {
                          if (menu.mark !== "code") {
                            chain.unsetCode();
                          }

                          chain.toggleMark(menu.mark).focus().run();
                        }

                        event.preventDefault();
                        event.stopPropagation();
                      }}
                    />
                  </Tooltip>
                );
              }}
            </For>
          </div>
        </Match>
        <Match when={mode() === "link"}>
          <Input
            ref={setLinkInputRef}
            value={link()}
            placeholder="Paste a link..."
            wrapperClass="w-full md:w-auto"
            setValue={(value) => {
              setLink(value);
            }}
            onEnter={saveLink}
            class="py-0 my-0 bg-transparent"
          />
          <IconButton path={mdiCheck} text="soft" variant="text" onClick={saveLink} />
          <IconButton
            path={mdiDelete}
            text="soft"
            variant="text"
            onClick={() => {
              props.editor.chain().unsetLink().focus().run();
              setMode("format");
            }}
          />
        </Match>
      </Switch>
    </Card>
  );
};

export { BubbleMenu };
export * from "./bubble-menu";
export * from "./export-menu";
export * from "./floating-menu";
export * from "./link-preview-menu";
export * from "./stats-menu";
export * from "./comment-threads-menu";
import { ExtensionDetails, hasPermission, useClient } from "#context";
            await client.git.github.initialSync.mutate();
import { Component, For, Show, createEffect, createResource } from "solid-js";
      <TitledCard icon={mdiThemeLightDark} label="UI theme">
      <TitledCard label="Code editor theme" icon={mdiCodeTags}>
        <ThemePicker
          theme={userSettings()?.codeEditorTheme || "dark"}
          setTheme={async (theme) => {
            await client.userSettings.update.mutate({ codeEditorTheme: theme });
          }}
        />
      </TitledCard>
import { mdiCheck, mdiInformation } from "@mdi/js";
import { Component, createEffect, createMemo, createSignal } from "solid-js";
import { createStore } from "solid-js/store";
import { InputField, TitledCard } from "#components/fragments";
import { Button, IconButton, Tooltip } from "#components/primitives";
import { useClient, App, useNotifications } from "#context";
import { validateKey } from "#lib/utils";

interface ConfigureWrapperSubSectionProps {
  setActionComponent(component: Component<{}> | null): void;
  onWrapperConfigured(): void;
}

const ConfigureWrapperSubSection: Component<ConfigureWrapperSubSectionProps> = (props) => {
  const client = useClient();
  const { notify } = useNotifications();
  const [loading, setLoading] = createSignal(false);
  const [wrapperData, setWrapperData] = createStore<App.Wrapper>({
    key: "",
    label: ""
  });
  const filled = createMemo(() => {
    return Boolean(wrapperData.label && validateKey(wrapperData.key));
  });
  const onClick = async (): Promise<void> => {
    try {
      setLoading(true);
      await client.workspaceSettings.createWrapper.mutate(wrapperData);
      notify({ text: "New Wrapper created", type: "success" });
      props.onWrapperConfigured();
      setLoading(false);
    } catch (error) {
      notify({ text: "Failed to create new Wrapper", type: "error" });
      setLoading(false);
    }
  };

  createEffect(() => {
    setWrapperData("key", wrapperData.label.toLowerCase().replace(/\s|-/g, "_").slice(0, 20));
  });
  props.setActionComponent(() => {
    return (
      <>
        <Button
          color="primary"
          class="m-0 hidden @md:flex"
          loading={loading()}
          disabled={!filled()}
          onClick={onClick}
        >
          Create Wrapper
        </Button>
        <Tooltip text="Create Wrapper" wrapperClass="flex @md:hidden" class="mt-1" fixed>
          <IconButton
            color="primary"
            path={mdiCheck}
            class="m-0"
            loading={loading()}
            disabled={!filled()}
            onClick={onClick}
          />
        </Tooltip>
      </>
    );
  });

  return (
    <>
      <TitledCard icon={mdiInformation} label="Details">
        <InputField
          label="Wrapper label"
          color="contrast"
          placeholder="Label"
          type="text"
          value={wrapperData.label}
          inputProps={{ maxLength: 50 }}
          setValue={(value) => setWrapperData("label", value)}
        >
          Descriptive label for the wrapper.
        </InputField>
        <InputField
          label="Wrapper key"
          color="contrast"
          placeholder="wrapper_key"
          type="text"
          value={wrapperData.key}
          inputProps={{ maxLength: 20 }}
          setValue={(value) => setWrapperData("key", value)}
        >
          Key identifying the Wrapper in JSON content. Has to be unique, and can only contain
          letters, numbers and underscores.
        </InputField>
      </TitledCard>
    </>
  );
};

export { ConfigureWrapperSubSection };
import { ConfigureWrapperSubSection } from "./configure-wrapper-subsection";
const WrapperDetails: Component<{
  wrapper: App.Wrapper;
  onEdit?(): void;
  onDelete?(): void;
}> = (props) => {
  const [loading, setLoading] = createSignal(false);
  const { notify } = useNotifications();
  const client = useClient();

  return (
    <Card class="flex flex-col gap-0 w-full m-0" color="contrast">
      <div class="flex items-start justify-center gap-2 w-full">
        <Heading level={3} class="break-anywhere flex-1">
          {props.wrapper.label || "[No name]"}
        </Heading>
        <Show
          when={!props.wrapper.extension}
          fallback={
            <Tooltip text="Extension" class="mt-1">
              <IconButton path={mdiPuzzle} text="soft" class="m-0" badge />
            </Tooltip>
          }
        >
          <Show when={hasPermission("manageWorkspace")}>
            <Tooltip text="Delete" class="mt-1">
              <IconButton
                path={mdiTrashCan}
                text="soft"
                class="m-0"
                loading={loading()}
                onClick={async () => {
                  try {
                    setLoading(true);
                    await client.workspaceSettings.deleteWrapper.mutate({
                      key: props.wrapper.key
                    });
                    setLoading(false);
                    props.onDelete?.();
                    notify({
                      text: "Wrapper deleted",
                      type: "success"
                    });
                  } catch (error) {
                    setLoading(false);
                    notify({
                      text: "Failed to delete wrapper",
                      type: "error"
                    });
                  }
                }}
              />
            </Tooltip>
          </Show>
        </Show>
      </div>
    </Card>
  );
};
  const [openedSubsection, setOpenedSubsection] = createSignal<"none" | "configure-wrapper">(
    "none"
  );
  const [wrappers, setWrappers] = createSignal<App.WorkspaceSettings["wrappers"]>([]);
  const handleNewWrapper = (): void => {
    setOpenedSubsection("configure-wrapper");
    props.setSubSection({
      label: "New wrapper",
      icon: mdiCube,
      goBack() {
        setOpenedSubsection("none");
      }
    });
  };
    setWrappers(workspaceSettings()?.wrappers || []);
        <Show when={enabledBlocks().includes("wrapper")}>
          <TitledCard
            label="Wrappers"
            icon={mdiCube}
            action={
              <Show when={hasPermission("manageWorkspace")}>
                <>
                  <Button color="primary" class="m-0 hidden @md:flex" onClick={handleNewWrapper}>
                    New Wrapper
                  </Button>
                  <Tooltip text="New Wrapper" wrapperClass="flex @md:hidden" class="mt-1" fixed>
                    <IconButton
                      path={mdiPlus}
                      class="m-0"
                      color="primary"
                      onClick={handleNewWrapper}
                    />
                  </Tooltip>
                </>
              </Show>
            }
          >
            <div class="flex flex-col gap-2 w-full">
              <For
                each={wrappers()}
                fallback={
                  <p class="px-2 w-full text-start text-gray-500 dark:text-gray-400">
                    No wrappers found
                  </p>
                }
              >
                {(wrapper) => {
                  return <WrapperDetails wrapper={wrapper} />;
                }}
              </For>
            </div>
          </TitledCard>
        </Show>
      <Match when={openedSubsection() === "configure-wrapper"}>
        <ConfigureWrapperSubSection
          setActionComponent={props.setActionComponent}
          onWrapperConfigured={() => {
            setOpenedSubsection("none");
          }}
        />
      </Match>
    { label: "Wrapper", icon: mdiCubeOutline, value: "wrapper" }
import { mdiFormatListBulleted, mdiPlusCircle, mdiTrashCan, mdiTune } from "@mdi/js";
  transformer: App.Transformer & { inUse?: boolean };
  transformers(): Array<App.Transformer & { inUse?: boolean }>;
    transformers: Array<App.Transformer>;
      <Show when={hasPermission("manageWorkspace")}>
        <div class="flex gap-2">
          <Tooltip text="Delete" class="mt-1" enabled={!props.transformer.inUse}>
            <IconButton
              path={mdiTrashCan}
              loading={loading()}
              disabled={props.transformer.inUse}
              class="m-0"
              text="soft"
              onClick={async () => {
                setLoading(true);
                await client.transformers.delete.mutate({ id: props.transformer.id });
                setLoading(false);
                props.onDelete?.();
                notify({ text: "Transformer deleted", type: "success" });
              }}
            />
        </div>
    event: "" as App.WebhookEvent,
            setWebhookData("event", value as App.WebhookEvent);
const webhookEvents: Array<{ label: string; value: App.WebhookEvent }> = [
    "types": ["vite/client", "mdx", "@vrite/extensions"],
          target: "http://localhost:3333",
        "/session": { target: "http://localhost:3333", ws: true },
        "/login": { target: "http://localhost:3333", ws: true },
        "/github": { target: "http://localhost:3333", ws: true },
        "/proxy": { target: "http://localhost:3333", ws: true },
        "/upload": { target: "http://localhost:3333", ws: true }
  "version": "0.2.1",
import { Collection, Db, ObjectId } from "mongodb";
import { UnderscoreID, zodId } from "#lib/mongo";
export * from "./versions";
  email: z.string().email(),
import { ContentPiece, contentPiece } from "./content-pieces";
import { ContentPieceVariant, contentPieceVariant } from "./content-piece-variants";
import { Binary, Collection, Db, ObjectId } from "mongodb";
import { z } from "zod";
import { UnderscoreID, zodId } from "#lib/mongo";

const version = z.object({
  id: zodId(),
  name: z.string(),
  date: z.string(),
  content: z.any().optional(),
  contentPiece: contentPieceVariant.omit({ variantId: true, contentPieceId: true, id: true }),
  contentPieceId: zodId(),
  variantId: zodId().optional()
});

interface Version<ID extends string | ObjectId = string>
  extends Omit<
    z.infer<typeof version>,
    "id" | "date" | "contentPieceId" | "variantId" | "content" | "contentPiece"
  > {
  date: ID extends string ? string : Date;
  content?: Binary;
  contentPiece: Omit<ContentPieceVariant<ID>, "id" | "variantId" | "contentPieceId">;
  contentPieceId: ID;
  variantId?: ID;
  id: ID;
}
interface FullVersion<ID extends string | ObjectId = string> extends Version<ID> {
  workspaceId: ID;
}

const getVersionsCollection = (db: Db): Collection<UnderscoreID<FullVersion<ObjectId>>> => {
  return db.collection("contents");
};

export { getVersionsCollection, version };
export type { Version, FullVersion };
const webhookEvent = z.enum([...contentPieceEvents, ...contentGroupEvents, ...memberEvents]);
  event: webhookEvent
type WebhookEvent = z.infer<typeof webhookEvent>;
  webhookEvent,
export type { WebhookEvent, Webhook, FullWebhook };
  email: z.string().email().optional(),
const wrapper = z.object({
  label: z.string().min(1).max(50),
  key: z
    .string()
    .min(1)
    .max(20)
    .regex(/^[a-z0-9_]*$/),
  extension: z.boolean().optional()
});
  "wrapper"
  embeds: z.array(z.enum(embeds)),
  wrappers: z.array(wrapper).optional()
interface Wrapper extends z.infer<typeof wrapper> {}
  extends Omit<z.infer<typeof workspaceSettings>, "id" | "wrappers"> {
  wrappers?: Wrapper[];
  wrapper,
export type { MetadataField, MetadataSettings, WorkspaceSettings, FullWorkspaceSettings, Wrapper };
import { optional, z } from "zod";
export * from "./server";
export * from "./routes";
import { TokenPermission, getTokensCollection } from "#database/tokens";
interface Context {
  return { req, res, db, fastify };
export { createContext };
export type { Context };
import { ObjectId, Binary } from "mongodb";
import { convert as convertToSlug } from "url-slug";
  FullContentPiece,
  FullContents,
import { UnderscoreID, jsonToBuffer, htmlToJSON, bufferToJSON, AuthenticatedContext } from "#lib";

interface ProcessInputResult {
  buffer: Buffer;
  contentHash: string;
  metadata: Partial<
    Pick<FullContentPiece, keyof NonNullable<ReturnType<InputTransformer>["contentPiece"]>>
  >;
}
interface OutputContentProcessorInput {
  buffer: Buffer;
  contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
}

interface InputContentProcessor {
  process(inputContent: string): Promise<ProcessInputResult>;
  processBatch(inputContent: string[]): Promise<ProcessInputResult[]>;
}

interface OutputContentProcessor {
  process(input: OutputContentProcessorInput): Promise<string>;
  processBatch(input: OutputContentProcessorInput[]): Promise<string[]>;
}
const createSyncedPieces = async (
  inputs: Array<{
    path: string;
    content: string;
    workspaceId: ObjectId;
    contentGroupId: ObjectId;
    order: string;
  }>,
  inputContentProcessor: InputContentProcessor
): Promise<
  Array<{
    contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
    content: UnderscoreID<FullContents<ObjectId>>;
    contentHash: string;
  }>
> => {
  const inputContentProcessorOutput = await inputContentProcessor.processBatch(
    inputs.map((input) => input.content)
  );

  return inputs.map((input, index) => {
    const filename = input.path.split("/").pop() || "";
    const { buffer, contentHash, metadata } = inputContentProcessorOutput[index];
    const { members, tags, date, ...inputMetadata } = metadata;
    const contentPiece: UnderscoreID<FullContentPiece<ObjectId>> = {
      _id: new ObjectId(),
      workspaceId: input.workspaceId,
      contentGroupId: input.contentGroupId,
      order: input.order,
      members: [],
      slug: convertToSlug(filename),
      tags: [],
      title: filename,
      filename,
      ...inputMetadata,
      ...(date && { date: new Date(date) }),
      ...(members && { members: members.map((memberId) => new ObjectId(memberId)) }),
      ...(tags && { tags: tags.map((tagId) => new ObjectId(tagId)) })
    };
    const content = {
      _id: new ObjectId(),
      contentPieceId: contentPiece._id,
      content: new Binary(buffer)
    };

    return {
      contentPiece,
      contentHash,
      content
    };
  });
};
export { createSyncedPieces, createInputContentProcessor, createOutputContentProcessor };
export type { OutputContentProcessorInput, OutputContentProcessor, InputContentProcessor };
import { AuthenticatedContext } from "./middleware";
import { ObjectId, UnderscoreID } from "./mongo";
import { jsonToBuffer } from "./processing";
import {
  OutputContentProcessor,
  createOutputContentProcessor as createOutputContentProcessorGitHub
} from "#routes/git/github/process-content";
import { publishGitDataEvent } from "#routes/git/events";
const createGenericOutputContentProcessor = async (
  ctx: AuthenticatedContext,
  gitData: UnderscoreID<FullGitData<ObjectId>>
): Promise<OutputContentProcessor> => {
  if (gitData.provider === "github") {
    return await createOutputContentProcessorGitHub(ctx, gitData);
  }

  return {
    process() {
      return Promise.resolve("");
    },
    processBatch(input) {
      return Promise.resolve(input.map(() => ""));
    }
  };
};
import {
  OutputContentProcessor,
  InputContentProcessor,
  createOutputContentProcessor as createOutputContentProcessorGitHub,
  createInputContentProcessor as createInputContentProcessorGitHub
} from "./github";
export * from "./utils";
export * from "./hash";
export * from "./middleware";
export * from "./git-sync-hooks";
export * as errors from "./errors";
import { Meta, middleware } from "#lib/trpc";
import * as errors from "#lib/errors";
  if (requiredConfig.some((property) => !ctx.fastify.hostConfig[property])) {
import { ObjectId, Db, Collection } from "mongodb";
export { zodId, ObjectId };
export type { UnderscoreID, Db, Collection };
  Wrapper
    Wrapper,
    Wrapper,
import { getUserSettingsCollection } from "#database/user-settings";
import { getWorkspaceMembershipsCollection } from "#database/workspace-memberships";
import { BaseRoleType, FullRole, Permission, getRolesCollection } from "#database/roles";
import * as errors from "#lib/errors";
import { HostConfig } from "#plugins/host-config";
import { ObjectId, zodId } from "#lib/mongo";
import { WebhookEvent, getWebhooksCollection } from "#database/webhooks";
import { contentGroup, contentPiece, getContentGroupsCollection } from "#database";
import { workspaceMembership } from "#database/workspace-memberships";
      // eslint-disable-next-line no-console
      console.error("Failed to run webhook", error);
import { publicPlugin } from "#lib/plugin";
import { getContentPiecesCollection } from "#database/content-pieces";
import { getRolesCollection } from "#database/roles";
import { getTagsCollection } from "#database/tags";
import { getTokensCollection } from "#database/tokens";
import { getUserSettingsCollection } from "#database/user-settings";
import { getWebhooksCollection } from "#database/webhooks";
import { getWorkspaceSettingsCollection } from "#database/workspace-settings";
import { getContentsCollection } from "#database/contents";
import { getUsersCollection } from "#database/users";
import { getCommentThreadsCollection } from "#database/comment-threads";
import { getCommentsCollection } from "#database/comments";
import { publicPlugin } from "../lib/plugin";
import { getWorkspacesCollection } from "#database/workspaces";
import { getUsersCollection } from "#database/users";
import * as errors from "#lib/errors";
        // eslint-disable-next-line no-console
        console.error(error);
        // eslint-disable-next-line no-console
        console.error(error);
    console.error("No email service configured");
import { publicPlugin } from "#lib/plugin";
import { publicPlugin } from "../lib/plugin";
import { z } from "zod";

const hostConfig = z.object({
  githubOAuth: z.boolean(),
  githubApp: z.boolean(),
  sendgrid: z.boolean(),
  smtp: z.boolean(),
  search: z.boolean(),
  aiSearch: z.boolean(),
  extensions: z.boolean()
});

interface HostConfig extends z.infer<typeof hostConfig> {}
export { hostConfigPlugin, hostConfig };
export type { HostConfig };
import { publicPlugin } from "#lib/plugin";
import { generateSalt } from "#lib/hash";
import { createSession } from "#lib/session";
import { createWorkspace } from "#lib/workspace";
import { getUsersCollection } from "#database/users";
import { getUserSettingsCollection } from "#database";
          codeEditorTheme: "dark",
      // eslint-disable-next-line no-console
      console.error(error);
import { publicPlugin } from "../lib/plugin";
import { publicPlugin } from "../lib/plugin";
import {
  S3Client,
  CreateBucketCommand,
  PutBucketCorsCommand,
  HeadBucketCommand
} from "@aws-sdk/client-s3";
import { Db, ObjectId, UnderscoreID, bufferToJSON, publicPlugin } from "#lib";
import { appRouter } from "../routes";
import { publicPlugin } from "#lib/plugin";
import { CustomError } from "#lib/errors";
      const error = e as CustomError;
      const error = e as CustomError;
import { publicPlugin } from "../lib/plugin";
import { createContext } from "../lib/context";
import { appRouter } from "../routes";
import { FullUser, getUsersCollection } from "#database/users";
import { UnderscoreID } from "#lib/mongo";
import { generateSalt, hashValue, verifyValue } from "#lib/hash";
import { procedure, router } from "#lib/trpc";
  updateSession
} from "#lib/session";
import { processAuth } from "#lib/auth";
import * as errors from "#lib/errors";
import { isAuthenticated, isAuthenticatedUser } from "#lib/middleware";
import { getUserSettingsCollection } from "#database";
        email: z.string().email(),
        password: z.string().regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/),
        email: z.string().email(),
        email: z.string().email(),
        password: z.string(),
import { UnderscoreID, zodId } from "#lib/mongo";
import { isAuthenticated } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
  getUsersCollection,
  CommentMember

type CommentEvent =
  | { action: "createThread"; data: CommentThread }
  | { action: "resolveThread"; data: Pick<CommentThread, "id" | "fragment" | "resolved"> }
  | { action: "deleteThread"; data: Pick<CommentThread, "id" | "fragment"> }
  | {
      action: "createComment";
      data: Omit<Comment, "memberId"> & { member: CommentMember | null };
    }
  | {
      action: "updateComment";
      data: Pick<Comment, "id" | "content">;
    }
  | {
      action: "deleteComment";
      data: Pick<Comment, "id">;
    };
const publishEvent = createEventPublisher<CommentEvent>((contentPieceId) => {
  return `comments:${contentPieceId}`;
});
      publishEvent(ctx, `${input.contentPieceId}`, {
      publishEvent(ctx, `${existingThread.contentPieceId}`, {
      publishEvent(ctx, `${existingThread.contentPieceId}`, {
      publishEvent(ctx, `${existingThread.contentPieceId}`, {
      publishEvent(ctx, `${existingThread.contentPieceId}`, {
      publishEvent(ctx, `${existingThread.contentPieceId}`, {
      return createEventSubscription<CommentEvent>(ctx, `comments:${input.contentPieceId}`);
import { procedure, router } from "#lib/trpc";
import { isAuthenticated } from "#lib/middleware";
import { UnderscoreID, zodId } from "#lib/mongo";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { runWebhooks } from "#lib/webhooks";
import { runGitSyncHook } from "#lib";

type ContentGroupEvent =
  | {
      action: "create";
      data: ContentGroup;
    }
  | {
      action: "update";
      data: Partial<ContentGroup> & { id: string };
    }
  | { action: "delete"; data: { id: string } }
  | { action: "move"; data: ContentGroup }
  | { action: "reorder"; data: { id: string; index: number } };

const publishEvent = createEventPublisher<ContentGroupEvent>(
  (workspaceId) => `contentGroups:${workspaceId}`
);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "update", data: { id, ...update } });
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
    return createEventSubscription<ContentGroupEvent>(ctx, `contentGroups:${ctx.auth.workspaceId}`);
export { contentGroupsRouter, publishEvent as publishContentGroupEvent };
import { stringToRegex } from "#lib/utils";
import { UnderscoreID, zodId } from "#lib/mongo";
import { bufferToJSON, DocJSON, htmlToJSON, jsonToBuffer } from "#lib/processing";
import { isAuthenticated } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
  FullContentPieceWithAdditionalData,
  getContentPiecesCollection
} from "#database/content-pieces";
import { Tag, getTagsCollection, tag } from "#database/tags";
import * as errors from "#lib/errors";
import { getContentsCollection } from "#database/contents";
import { runWebhooks } from "#lib/webhooks";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { runGitSyncHook } from "#lib";

type ContentPieceEvent =
  | { action: "delete"; userId: string; data: { id: string } }
  | { action: "create"; userId: string; data: FullContentPieceWithAdditionalData }
  | {
      action: "update";
      userId: string;
      variantId?: string;
      data: Partial<FullContentPieceWithAdditionalData> & { id: string };
    }
  | {
      action: "move";
      userId: string;
      data: {
        contentPiece: FullContentPieceWithAdditionalData;
        nextReferenceId?: string;
        previousReferenceId?: string;
      };
    };
const publishEvent = createEventPublisher<ContentPieceEvent>((contentGroupId) => {
  return `contentPieces:${contentGroupId}`;
});
  variantIdOrName?: string
): Promise<{ variantId: ObjectId | null; variantName: string | null }> => {
  if (!variantIdOrName) return { variantId: null, variantName: null };
  const isId = ObjectId.isValid(variantIdOrName);
    ...(isId && { _id: new ObjectId(variantIdOrName) }),
    ...(!isId && { name: variantIdOrName })
  return { variantId: variant._id || null, variantName: variant.name || null };
      const { variantId, variantName } = await getVariantDetails(ctx.db, input.variant);
              { slug: contentPiece.slug, variant: variantName }
      const { variantId, variantName } = await getVariantDetails(ctx.db, input.variant);
                  { slug: contentPiece.slug, variant: variantName }
      publishEvent(ctx, `${contentPiece.contentGroupId}`, {
      const { variantId, variantName } = await getVariantDetails(ctx.db, variant);
        contentPieceUpdates.slug = convertToSlug(update.slug || update.title || contentPiece.title);
      publishEvent(ctx, `${newContentPiece.contentGroupId}`, {
                { slug: newContentPiece.slug, variant: variantName }
      publishEvent(ctx, `${contentPiece.contentGroupId}`, {
      publishEvent(
      return createEventSubscription<ContentPieceEvent>(
        ctx,
        `contentPieces:${input.contentGroupId}`
      );
export type { ContentPieceEvent };
import { isAuthenticated, isEnabled } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
  Extension,
  ContextObject,
  getContentPiecesCollection,
  FullContentPieceWithAdditionalData
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import * as errors from "#lib/errors";
import { zodId } from "#lib";
type ExtensionEvent =
  | { action: "delete"; data: { id: string } }
  | { action: "create"; data: Extension & { id: string } }
  | { action: "update"; data: { id: string; config: ContextObject } };

const publishEvent = createEventPublisher<ExtensionEvent>((workspaceId) => {
  return `extensions:${workspaceId}`;
});
const publishContentPieceEvent = createEventPublisher<{
  action: "update";
  userId: string;
  data: Partial<FullContentPieceWithAdditionalData> & { id: string };
}>((contentGroupId) => {
  return `contentPieces:${contentGroupId}`;
});
    return createEventSubscription<ExtensionEvent>(ctx, `extensions:${ctx.auth.workspaceId}`);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
import { GitData } from "#database";
import { createEventPublisher } from "#lib/pub-sub";

type GitDataEvent =
  | {
      action: "configure";
      data: GitData;
    }
  | {
      action: "update";
      data: Partial<GitData>;
    }
  | {
      action: "reset";
      data: {};
    };

const publishGitDataEvent = createEventPublisher<GitDataEvent>((workspaceId) => {
  return `gitData:${workspaceId}`;
});

export { publishGitDataEvent };
export type { GitDataEvent };
import {
  createSyncedPieces,
  createInputContentProcessor,
  createOutputContentProcessor,
  OutputContentProcessorInput,
  OutputContentProcessor,
  InputContentProcessor
} from "./process-content";
import { publishGitDataEvent } from "../events";
import { Binary } from "mongodb";
import { AuthenticatedContext, isAuthenticated, isEnabled } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { ObjectId, UnderscoreID, zodId } from "#lib";
import { publishContentGroupEvent } from "#routes/content-groups";
import { publishWorkspaceSettingsEvent } from "#routes/workspace-settings";
      const inputContentProcessor = await createInputContentProcessor(ctx, gitData);
        const outputContentProcessor = await createOutputContentProcessor(ctx, gitData);
      const outputContentProcessor = await createOutputContentProcessor(ctx, gitData);
      const outputContentProcessor = await createOutputContentProcessor(ctx, gitData);
      const inputContentProcessor = await createInputContentProcessor(ctx, gitData);
export { githubRouter, createInputContentProcessor, createOutputContentProcessor };
export type { OutputContentProcessor, InputContentProcessor };
import { createSyncedPieces, createInputContentProcessor } from "./process-content";
  const inputContentProcessor = await createInputContentProcessor(ctx, gitData);
import { GitDataEvent, publishGitDataEvent } from "./events";
import {
  createGenericInputContentProcessor,
  createGenericOutputContentProcessor
} from "./process-content";
import { procedure, router } from "#lib/trpc";
import { errors, isAuthenticated } from "#lib";
import { createEventSubscription } from "#lib/pub-sub";
    return createEventSubscription<GitDataEvent>(ctx, `gitData:${ctx.auth.workspaceId}`);
export { gitRouter, createGenericInputContentProcessor, createGenericOutputContentProcessor };
import { ObjectId, UnderscoreID } from "#lib";
import {
  createGenericInputContentProcessor,
  createGenericOutputContentProcessor,
  gitRouter
} from "./git";
import { Context, createContext } from "#lib/context";
import { router } from "#lib/trpc";
export {
  appRouter,
  createContext,
  createGenericInputContentProcessor,
  createGenericOutputContentProcessor
};
import { procedure, router } from "#lib/trpc";
import { isAuthenticated } from "#lib/middleware";
import { zodId } from "#lib/mongo";
  Role,
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { updateSessionRole } from "#lib/session";

type RoleEvent =
  | {
      action: "create";
      data: Role;
    }
  | { action: "update"; data: Partial<Role> & { id: string } }
  | { action: "delete"; data: { id: string; newRole: Role } };

const publishEvent = createEventPublisher((workspaceId) => `roles:${workspaceId}`);
    return createEventSubscription<RoleEvent>(ctx, `roles:${ctx.auth.workspaceId}`);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
import { isAuthenticated, isEnabled } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import { errors, zodId } from "#lib";
      return results.data.Get.Content.map(({ _additional, ...result }) => result);
import { zodId } from "#lib/mongo";
import { stringToRegex } from "#lib/utils";
import { isAuthenticated } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { ExtendedTag, Tag, getTagsCollection, tag, getContentPiecesCollection } from "#database";

type TagEvent =
  | { action: "create"; data: Tag }
  | { action: "update"; data: Partial<Tag> & { id: string } }
  | {
      action: "delete";
      data: { id: string };
    };
const publishEvent = createEventPublisher<TagEvent>((workspaceId) => `tags:${workspaceId}`);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
    return createEventSubscription<TagEvent>(ctx, `tags:${ctx.auth.workspaceId}`);
import { procedure, router } from "#lib/trpc";
import { AuthenticatedContext, isAuthenticated } from "#lib/middleware";
import { generateSalt, hashValue } from "#lib/hash";
import { UnderscoreID, zodId } from "#lib/mongo";
import { Token, FullToken, getTokensCollection, token } from "#database/tokens";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type TokenEvent =
  | {
      action: "create";
      data: Token;
    }
  | { action: "update"; data: Partial<Token> & { id: string } }
  | { action: "delete"; data: { id: string } };

const publishEvent = createEventPublisher<TokenEvent>((workspaceId) => `tokens:${workspaceId}`);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
    return createEventSubscription<TokenEvent>(ctx, `tokens:${ctx.auth.workspaceId}`);
import { isAuthenticated } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { Transformer, getGitDataCollection, transformer } from "#database";
import { ObjectId, zodId } from "#lib/mongo";
import { getTransformersCollection } from "#database/transformers";
type TransformersEvent =
  | {
      action: "create";
      data: Transformer & { id: string };
    }
  | {
      action: "delete";
      data: { id: string };
    };

const publishEvent = createEventPublisher<TransformersEvent>(
  (workspaceId) => `transformers:${workspaceId}`
);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
    .output(z.array(transformer.extend({ inUse: z.boolean().optional() })))
      return transformers.map(({ _id, workspaceId, ...transformerData }) => {
    return createEventSubscription<TransformersEvent>(ctx, `transformers:${ctx.auth.workspaceId}`);
export type { TransformersEvent };
import { isAuthenticated, isAuthenticatedUser } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
  AppearanceSettings,
import { zodId } from "#lib";
type UserSettingsEvent = { action: "update"; data: Partial<AppearanceSettings> };

const publishEvent = createEventPublisher<UserSettingsEvent>((userId) => `userSettings:${userId}`);
    .input(appearanceSettings.partial())
      publishEvent(ctx, `${ctx.auth.userId}`, { action: "update", data: input });
        codeEditorTheme: userSettings.codeEditorTheme,
    return createEventSubscription<UserSettingsEvent>(ctx, `userSettings:${ctx.auth.userId}`);
export type { UserSettingsEvent };
import { hashValue } from "#lib/hash";
import { isAuthenticated } from "#lib/middleware";
import { UnderscoreID } from "#lib/mongo";
import { procedure, router } from "#lib/trpc";
import {
  FullUser,
  Profile,
  VerificationDetails,
  getUsersCollection,
  profile,
  verificationDetails
} from "#database/users";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { stringToRegex } from "#lib/utils";
type UserEvent = {
  action: "update";
  data: Partial<Profile> & { id: string } & Partial<VerificationDetails>;
};

const publishEvent = createEventPublisher<UserEvent>((userId: string) => `user:${userId}`);
    return createEventSubscription<UserEvent>(ctx, `user:${ctx.auth.userId}`);
      publishEvent(ctx, `${ctx.auth.userId}`, {
import { PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { nanoid } from "nanoid";
import mime from "mime-types";
import { extractPreviewDataFromOpenGraph } from "#lib/utils";
import { isAuthenticated } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { hostConfig, HostConfig } from "#plugins/host-config";
const authenticatedProcedure = procedure.use(isAuthenticated);
import { isAuthenticated } from "#lib/middleware";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
  Variant,
import { ObjectId, zodId } from "#lib/mongo";
type VariantsEvent =
  | {
      action: "create";
      data: Variant & { id: string };
    }
  | {
      action: "update";
      data: Partial<Variant> & { id: string };
    }
  | {
      action: "delete";
      data: { id: string };
    };

const publishEvent = createEventPublisher<VariantsEvent>(
  (workspaceId) => `variants:${workspaceId}`
);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "update", data: input });
      publishEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
    return createEventSubscription<VariantsEvent>(ctx, `variants:${ctx.auth.workspaceId}`);
export type { VariantsEvent };
import { VerificationDetails, getUsersCollection } from "#database/users";
import { procedure, router } from "#lib/trpc";
import { createWorkspace } from "#lib/workspace";
import * as errors from "#lib/errors";
import { createSession } from "#lib/session";
import { isAuthenticatedUser } from "#lib/middleware";
import { verifyValue } from "#lib";
  WorkspaceMembership,
} from "#database/workspace-memberships";
import { runWebhooks } from "#lib/webhooks";
import { createEventPublisher } from "#lib/pub-sub";
import { getUserSettingsCollection } from "#database";

type VerifyUserEvent = {
  action: "update";
  data: { id: string } & Partial<VerificationDetails & { email: string }>;
};
type VerifyWorkspaceInviteEvent = {
  action: "update";
  data: {
    id: string;
    userId: string;
    pendingInvite?: boolean;
    profile?: {
      fullName?: string;
      username?: string;
      avatar?: string;
    };
  } & Partial<WorkspaceMembership>;
};
const publishUserEvent = createEventPublisher<VerifyUserEvent>(
  (userId: string) => `user:${userId}`
);
const publishWorkspaceMembershipEvent = createEventPublisher<VerifyWorkspaceInviteEvent>(
  (workspaceId: string) => `workspaceMemberships:${workspaceId}`
);
          codeEditorTheme: "dark",
        console.error(error);
import { Db, ObjectId } from "mongodb";
import { z } from "zod";
import { isAuthenticated } from "#lib/middleware";
import { UnderscoreID } from "#lib/mongo";
import { procedure, router } from "#lib/trpc";
import * as errors from "#lib/errors";
import {
  FullVersion,
  getContentPieceVariantsCollection,
  getContentPiecesCollection,
  getContentVariantsCollection,
  getContentsCollection,
  getVersionsCollection,
  version
} from "#database";

const authenticatedProcedure = procedure.use(isAuthenticated);
const basePath = "/versions";
const createVersion = async (
  db: Db,
  data: Pick<FullVersion<ObjectId>, "name" | "contentPieceId" | "variantId" | "workspaceId">
): Promise<ObjectId> => {
  const versionsCollection = getVersionsCollection(db);
  const contentPiecesCollection = getContentPiecesCollection(db);
  const contentsCollection = getContentsCollection(db);
  const contentPieceVariantsCollection = getContentPieceVariantsCollection(db);
  const contentVariantsCollection = getContentVariantsCollection(db);

  let contentPiece = await contentPiecesCollection.findOne({
    _id: data.contentPieceId,
    workspaceId: data.workspaceId
  });

  if (!contentPiece) throw errors.notFound("contentPiece");

  let content = await contentsCollection.findOne({
    contentPieceId: contentPiece._id
  });

  if (!content) throw errors.notFound("content");

  if (data.variantId) {
    const contentPieceVariant = await contentPieceVariantsCollection.findOne({
      contentPieceId: contentPiece._id,
      variantId: data.variantId,
      workspaceId: data.workspaceId
    });

    if (!contentPieceVariant) throw errors.notFound("contentPieceVariant");

    const contentVariant = await contentVariantsCollection.findOne({
      contentPieceId: contentPiece._id,
      variantId: data.variantId
    });

    if (!contentVariant) throw errors.notFound("contentVariant");

    contentPiece = { ...contentPiece, ...contentPieceVariant };
    content = { ...content, ...contentVariant };
  }

  const version: UnderscoreID<FullVersion<ObjectId>> = {
    _id: new ObjectId(),
    name: data.name,
    date: new Date(),
    content: content.content,
    contentPiece: {
      members: contentPiece.members,
      tags: contentPiece.tags,
      title: contentPiece.title,
      description: contentPiece.description,
      slug: contentPiece.slug,
      canonicalLink: contentPiece.canonicalLink,
      coverAlt: contentPiece.coverAlt,
      coverUrl: contentPiece.coverUrl,
      customData: contentPiece.customData,
      date: contentPiece.date
    },
    contentPieceId: contentPiece._id,
    variantId: data.variantId,
    workspaceId: data.workspaceId
  };

  await versionsCollection.insertOne(version);

  return version._id;
};
const versionsRouter = router({
  create: authenticatedProcedure
    .input(version.pick({ name: true, contentPieceId: true, variantId: true }))
    .output(version.pick({ id: true }))
    .mutation(async ({ ctx, input }) => {
      const versionId = await createVersion(ctx.db, {
        name: input.name,
        contentPieceId: new ObjectId(input.contentPieceId),
        variantId: new ObjectId(input.variantId),
        workspaceId: ctx.auth.workspaceId
      });

      return { id: `${versionId}` };
    }),
  delete: authenticatedProcedure
    .input(
      version.pick({
        id: true
      })
    )
    .output(z.void())
    .mutation(async ({ ctx, input }) => {
      const versionsCollection = getVersionsCollection(ctx.db);
      const { deletedCount } = await versionsCollection.deleteOne({
        _id: new ObjectId(input.id),
        workspaceId: ctx.auth.workspaceId
      });

      if (!deletedCount) throw errors.notFound("version");
    }),
  restore: authenticatedProcedure
    .input(
      version.pick({
        id: true
      })
    )
    .output(z.void())
    .mutation(async ({ ctx, input }) => {
      const versionsCollection = getVersionsCollection(ctx.db);
      const contentPiecesCollection = getContentPiecesCollection(ctx.db);
      const contentsCollection = getContentsCollection(ctx.db);
      const contentPieceVariantsCollection = getContentPieceVariantsCollection(ctx.db);
      const contentVariantsCollection = getContentVariantsCollection(ctx.db);
      const version = await versionsCollection.findOne({
        _id: new ObjectId(input.id),
        workspaceId: ctx.auth.workspaceId
      });

      if (!version) throw errors.notFound("version");

      if (version.variantId) {
        const contentPieceVariantUpdateResult = await contentPieceVariantsCollection.updateOne(
          {
            contentPieceId: version.contentPieceId,
            variantId: version.variantId,
            workspaceId: ctx.auth.workspaceId
          },
          {
            $set: version.contentPiece
          }
        );

        if (!contentPieceVariantUpdateResult.matchedCount) {
          throw errors.notFound("contentPieceVariant");
        }

        const contentVariantUpdateResult = await contentVariantsCollection.updateOne(
          {
            contentPieceId: version.contentPieceId,
            variantId: version.variantId
          },
          {
            $set: {
              content: version.content
            }
          }
        );

        if (!contentVariantUpdateResult.matchedCount) throw errors.notFound("contentVariant");

        return;
      }

      const contentPieceUpdateResult = await contentPiecesCollection.updateOne(
        {
          _id: version.contentPieceId,
          workspaceId: ctx.auth.workspaceId
        },
        { $set: version.contentPiece }
      );

      if (!contentPieceUpdateResult.matchedCount) throw errors.notFound("contentPiece");

      const contentUpdateResult = await contentsCollection.updateOne(
        {
          contentPieceId: version.contentPieceId
        },
        { $set: { content: version.content } }
      );

      if (!contentUpdateResult.matchedCount) throw errors.notFound("content");
    })
});

export { versionsRouter, createVersion };
import { procedure, router } from "#lib/trpc";
import { isAuthenticated } from "#lib/middleware";
import { UnderscoreID, zodId } from "#lib/mongo";
import { FullWebhook, Webhook, getWebhooksCollection, webhook } from "#database/webhooks";
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type WebhookEvent =
  | {
      action: "create";
      data: Webhook & { id: string };
    }
  | {
      action: "update";
      data: Partial<Webhook> & { id: string };
    }
  | {
      action: "delete";
      data: { id: string };
    };

const publishEvent = createEventPublisher<WebhookEvent>((workspaceId) => {
  return `webhooks:${workspaceId}`;
});
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
    return createEventSubscription<WebhookEvent>(ctx, `webhooks:${ctx.auth.workspaceId}`);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
import { procedure, router } from "../lib/trpc";
import { AuthenticatedContext, isAuthenticated, isAuthenticatedUser } from "../lib/middleware";
import { UnderscoreID, generateSalt, hashValue, stringToRegex, zodId } from "../lib";
  WorkspaceMembership,
  workspaceMembership
} from "#database/workspace-memberships";
import * as errors from "#lib/errors";
import { getWorkspacesCollection, workspace } from "#database/workspaces";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { runWebhooks } from "#lib/webhooks";
import {
  Role,
  contentPieceMember,
  profile,
  role
import { updateSessionUser } from "#lib/session";

type WorkspaceMembershipEvent =
  | { action: "create"; data: { id: string; pendingInvite: boolean } & WorkspaceMembership }
  | {
      action: "update";
      data: {
        id: string;
        userId: string;
        role?: Role;
        pendingInvite?: boolean;
        profile?: {
          fullName?: string;
          username?: string;
          avatar?: string;
        };
      } & Partial<WorkspaceMembership>;
    }
  | {
      action: "delete";
      data: { id: string; userId: string };
    };

const publishEvent = createEventPublisher<WorkspaceMembershipEvent>(
  (workspaceId) => `workspaceMemberships:${workspaceId}`
);
  publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
        email: z.string().email(),
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
    return createEventSubscription<WorkspaceMembershipEvent>(
      ctx,
      `workspaceMemberships:${ctx.auth.workspaceId}`
    );
import { procedure, router } from "../lib/trpc";
import { isAuthenticated } from "../lib/middleware";
  WorkspaceSettings,
  wrapper,
  workspaceSettings,
  Wrapper
import * as errors from "#lib/errors";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
type WorkspaceSettingsEvent =
  | {
      action: "update";
      data: Partial<Omit<WorkspaceSettings, "id">>;
    }
  | {
      action: "createWrapper";
      data: Wrapper;
    }
  | {
      action: "deleteWrapper";
      data: Pick<Wrapper, "key">;
    };

const publishEvent = createEventPublisher<WorkspaceSettingsEvent>((workspaceId) => {
  return `workspaceSettings:${workspaceId}`;
});
        embeds: workspaceSettings.embeds,
        wrappers: workspaceSettings.wrappers || []
      };
    }),
  createWrapper: authenticatedProcedure
    .meta({
      openapi: { method: "POST", path: `${basePath}/wrapper`, protect: true },
      permissions: { session: ["manageWorkspace"], token: ["workspace:write"] }
    })
    .input(wrapper)
    .output(z.object({ key: wrapper.shape.key }))
    .mutation(async ({ input, ctx }) => {
      const extensionId = ctx.req.headers["x-vrite-extension-id"] as string | undefined;
      const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);
      const workspaceSettings = await workspaceSettingsCollection.findOne({
        workspaceId: ctx.auth.workspaceId
      });

      if (!workspaceSettings) throw errors.notFound("workspaceSettings");

      const sameKeyWrapperIndex =
        workspaceSettings.wrappers?.findIndex((wrapper) => wrapper.key === input.key) || -1;

      if (sameKeyWrapperIndex >= 0) {
        await workspaceSettingsCollection.updateOne(
          {
            workspaceId: ctx.auth.workspaceId
          },
          {
            $set: {
              wrappers: (workspaceSettings.wrappers || []).map((item, index) => {
                if (index === sameKeyWrapperIndex) {
                  return {
                    ...item,
                    ...input,
                    ...(extensionId && { extension: item.extension || true })
                  };
                }

                return item;
              })
            }
          }
        );
      } else {
        await workspaceSettingsCollection.updateOne(
          {
            workspaceId: ctx.auth.workspaceId
          },
          {
            $push: {
              wrappers: {
                ...input,
                ...(extensionId && { extension: true })
              }
            }
          }
        );
      }

      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
        action: "createWrapper",
        data: input
      });

      return {
        key: input.key
  deleteWrapper: authenticatedProcedure
    .meta({
      openapi: { method: "DELETE", path: `${basePath}/wrapper`, protect: true },
      permissions: { session: ["manageWorkspace"], token: ["workspace:write"] }
    })
    .input(wrapper.pick({ key: true }))
    .output(z.void())
    .mutation(async ({ input, ctx }) => {
      const workspaceSettingsCollection = getWorkspaceSettingsCollection(ctx.db);

      await workspaceSettingsCollection.updateOne(
        {
          workspaceId: ctx.auth.workspaceId
        },
        {
          $pull: {
            wrappers: {
              key: input.key
            }
          }
        }
      );
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
        action: "deleteWrapper",
        data: input
      });
    }),
    return createEventSubscription<WorkspaceSettingsEvent>(
      ctx,
      `workspaceSettings:${ctx.auth.workspaceId}`
    );
        .omit({ id: true, prettierConfig: true, wrappers: true })
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
export { workspaceSettingsRouter, publishEvent as publishWorkspaceSettingsEvent };
import { procedure, router } from "../lib/trpc";
import { isAuthenticated, isAuthenticatedUser } from "../lib/middleware";
import { zodId } from "../lib";
import * as errors from "#lib/errors";
import { Workspace, getWorkspacesCollection, workspace } from "#database/workspaces";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { createWorkspace, deleteWorkspace } from "#lib/workspace";
import { getUsersCollection } from "#database";
type WorkspaceEvent =
  | { action: "update"; data: Partial<Workspace> & { id: string } }
  | { action: "delete"; data: { id: string } };

const publishEvent = createEventPublisher<WorkspaceEvent>((workspaceId) => {
  return `workspace:${workspaceId}`;
});
    return createEventSubscription<WorkspaceEvent>(ctx, `workspace:${ctx.auth.workspaceId}`);
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishEvent(ctx, `${ctx.auth.workspaceId}`, {
import { OAuthPlugin } from "./plugins/oauth";
import { s3Plugin } from "./plugins/s3";
import { mailPlugin } from "./plugins/email";
import { sessionPlugin } from "./plugins/session";
import { pubSubPlugin } from "./plugins/pub-sub";
import { databasePlugin } from "./plugins/database";
import { ZodRawShape } from "zod";
import { gitSyncPlugin, hostConfigPlugin, searchPlugin } from "#plugins";
const createServer = async (envSchemaExtension?: ZodRawShape): Promise<FastifyInstance> => {
      schema: zodToJsonSchema(envSchema.extend(envSchemaExtension || {}))
  await server
    .register(mongoPlugin, {
    })
    .register(redisPlugin, { url: server.config.REDIS_URL })
    .register(redisPlugin, { url: server.config.REDIS_URL, namespace: "sub" });
  await server.register(databasePlugin).register(pubSubPlugin).register(s3Plugin);
  await server
    .register(cookiePlugin, { secret: server.config.SECRET })
    .register(jwtPlugin, {
      secret: server.config.SECRET,
      cookie: { cookieName: "accessToken", signed: true }
    })
    .register(sessionPlugin)
    .register(OAuthPlugin);
  await server.register(mailPlugin);
  await server.register(gitSyncPlugin);
  await server.register(searchPlugin);
            `:base-2: absolute z-50 flex flex-col p-1 overflow-hidden transition-all duration-300 transform shadow-2xl w-full`
  document.body.addEventListener("pointermove", onPointerMove);
    document.body.removeEventListener("pointermove", onPointerMove);







          class: node.attrs.lang ? `language-${node.attrs.lang}` : null
export * from "./wrapper";
import { nodeInputRule } from "./node-input-rule";
import { Node, mergeAttributes, wrappingInputRule } from "@tiptap/core";

interface WrapperAttributes {
  name?: string;
}
interface WrapperOptions {
  HTMLAttributes: WrapperAttributes;
}

declare module "@tiptap/core" {
  interface Commands<ReturnType> {
    wrapper: {
      setWrapper: (attrs?: WrapperAttributes) => ReturnType;
      toggleWrapper: (attrs?: WrapperAttributes) => ReturnType;
      unsetWrapper: () => ReturnType;
    };
  }
}

const Wrapper = Node.create<WrapperOptions>({
  name: "wrapper",
  content: "block+",
  group: "block",
  isolating: true,
  defining: true,
  addOptions() {
    return {
      HTMLAttributes: {}
    };
  },
  addAttributes() {
    return {
      key: {
        default: null,
        parseHTML: (element) => {
          return element.getAttribute("data-key");
        }
      }
    };
  },
  parseHTML() {
    return [
      {
        tag: "div[data-wrapper=true]"
      }
    ];
  },
  renderHTML({ node, HTMLAttributes }) {
    return [
      "div",
      mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {
        "data-wrapper": "true",
        "data-key": node.attrs.key
      }),
      0
    ];
  },
  addCommands() {
    return {
      setWrapper: (attrs) => {
        return ({ commands }) => {
          return commands.wrapIn(this.name, attrs);
        };
      },
      toggleWrapper: (attrs) => {
        return ({ commands }) => {
          return commands.toggleWrap(this.name, attrs);
        };
      },
      unsetWrapper: () => {
        return ({ commands }) => {
          return commands.lift(this.name);
        };
      }
    };
  },
  addInputRules() {
    return [
      wrappingInputRule({
        find: /(^:::(.*?)\s$)/,
        type: this.type,
        getAttributes: (match) => {
          const [, , key] = match;

          return { key: key.trim() };
        }
      })
    ];
  }
});

export { Wrapper };
export type { WrapperAttributes, WrapperOptions };
type RenderEmail = typeof renderEmail;

const renderEmail = (<T extends keyof typeof templateMap>(
}) as (test: string) => string;
    "on:install": "install",
    "on:install": "install",
    "on:install": "install",
  "version": "0.2.0",
import { ContentPiecesEndpoints, createContentPiecesEndpoints } from "./content-pieces";
    contentPieceID?: string;
  }): Promise<
    Array<{
      contentPieceId: string;
      breadcrumb: string[];
      content: string;
    }>
  >;
  reconfigure(config: ClientConfig): void;
  const { sendRequest, reconfigure, getConfig } = createAPIFetcher(config);

  return {
    reconfigure
export type { Client };
export type { Client } from "./client";
  return { sendRequest, reconfigure, getConfig };
    | WrapperNode
type WrapperNode = {
  type: "wrapper";
  attrs?: {
    key?: string;
    | WrapperNode
    lang: string;
    | WrapperNode
  wrapper: WrapperNode;
      JSONContentNode["listItem" | "taskItem" | "blockquote" | "doc" | "wrapper"]
          case "wrapper":
              child as JSONContentNodeWalker<JSONContentNode["wrapper"]>
      case "wrapper":
          "data-key": nodeWalker.node.attrs?.key
        })}>${(nodeWalker as JSONContentNodeWalker<JSONContentNode["wrapper"]>).children
        version: 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.1.6)
        version: 6.2.0(eslint@8.45.0)(typescript@5.1.6)
        version: 3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.1.6)
        version: 0.12.1(eslint@8.45.0)(typescript@5.1.6)
        version: 5.1.6
        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.2)
        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.2)
        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.2)
        version: 0.55.7(postcss@8.4.29)(vite@4.4.9)
        version: 4.4.9(sass@1.64.1)
        version: 2.2.1(@babel/core@7.22.15)(solid-js@1.7.11)(vite@4.4.9)
        version: 0.55.7(postcss@8.4.29)(vite@4.4.9)
        version: 4.4.9(sass@1.64.1)
        version: 10.16.2(solid-js@1.7.8)
        version: 2.0.15(solid-js@1.7.8)
        version: 0.3.15(solid-js@1.7.8)
        version: 2.2.3(solid-js@1.7.8)
        version: 1.3.2(solid-js@1.7.8)
        version: 1.4.0(solid-js@1.7.8)
        version: 0.8.2(solid-js@1.7.8)
        version: 1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.8)
        specifier: ^0.40.0
        version: 0.40.0
        version: 1.7.8
        version: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
        version: 5.1.6
        version: 0.55.7(postcss@8.4.29)(vite@4.4.7)
        version: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
        version: 2.7.0(solid-js@1.7.8)(vite@4.4.7)
        version: 4.2.0(typescript@5.1.6)(vite@4.4.7)
        version: 1.4.0(typescript@5.1.6)
        version: 5.1.6
        version: 1.4.0(graphql@16.7.1)
        version: 2.0.15(solid-js@1.7.8)
        version: 2.2.3(solid-js@1.7.8)
        version: 1.7.8
        version: 2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.0.3)(@tiptap/pm@2.1.8)
        version: 1.7.8
        version: 2.9.2
        version: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
      '@jridgewell/trace-mapping': 0.3.18
  /@astrojs/compiler@1.6.2:
    resolution: {integrity: sha512-2grH0lSm/Su88ZUd1kF0OdR/CT4ClWKvCwVz4yDdpgLgpzXhs1LdO2V58YfSqnx/z+G5EBWv6yEkp3tDG3GQYQ==}
    dev: true

  /@astrojs/compiler@2.1.0:
    resolution: {integrity: sha512-Mp+qrNhly+27bL/Zq8lGeUY+YrdoU0eDfIlAeGIPrzt0PnI/jGpvPUdCaugv4zbCrDkOUScFfcbeEiYumrdJnw==}

  /@astrojs/internal-helpers@0.1.1:
    resolution: {integrity: sha512-+LySbvFbjv2nO2m/e78suleQOGEru4Cnx73VsZbrQgB2u7A4ddsQg3P2T0zC0e10jgcT+c6nNlKeLpa6nRhQIg==}
    dev: true
    dev: false
      '@jridgewell/trace-mapping': 0.3.18
      '@vscode/emmet-helper': 2.8.9
      vscode-css-languageservice: 6.2.6
      vscode-html-languageservice: 5.0.6
      vscode-languageserver-protocol: 3.17.3
      vscode-languageserver-textdocument: 1.0.8
      vscode-languageserver-types: 3.17.3
      vscode-uri: 3.0.7
    dev: false
  /@astrojs/markdown-remark@2.2.1(astro@2.9.2):
    resolution: {integrity: sha512-VF0HRv4GpC1XEMLnsKf6jth7JSmlt9qpqP0josQgA2eSpCIAC/Et+y94mgdBIZVBYH/yFnMoIxgKVe93xfO2GA==}
      astro: ^2.5.0
      '@astrojs/prism': 2.1.2
      astro: 2.9.2
      github-slugger: 1.5.0
      import-meta-resolve: 2.2.2
    dev: true
  /@astrojs/markdown-remark@3.2.0(astro@3.1.0):
    resolution: {integrity: sha512-jigyLfefUZPKgVmmraCkVpdUuFH1R3SrpgQO13axsgwLDBgkggaQpNR5Ag4O9PDualeBtbdt30aYSfvnBKx9Hg==}
      astro: ^3.1.0
      zod: 3.22.2
  /@astrojs/solid-js@2.2.1(@babel/core@7.22.15)(solid-js@1.7.11)(vite@4.4.9):
      babel-preset-solid: 1.7.7(@babel/core@7.22.15)
      ci-info: 3.8.0
      undici: 5.23.0
      ci-info: 3.8.0
      is-wsl: 3.0.0
      undici: 5.23.0
      undici: 5.23.0
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      '@babel/highlight': 7.22.13
  /@babel/code-frame@7.22.5:
    resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/highlight': 7.22.13

  /@babel/compat-data@7.22.9:
    resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==}
  /@babel/core@7.22.15:
    resolution: {integrity: sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==}
      '@babel/generator': 7.22.15
      '@babel/helper-module-transforms': 7.22.15(@babel/core@7.22.15)
      '@babel/helpers': 7.22.15
      '@babel/parser': 7.22.16
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
      convert-source-map: 1.9.0
      debug: 4.3.4
      gensync: 1.0.0-beta.2
      json5: 2.2.3
      semver: 6.3.1
    transitivePeerDependencies:
      - supports-color

  /@babel/core@7.22.5:
    resolution: {integrity: sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@ampproject/remapping': 2.2.1
      '@babel/code-frame': 7.22.5
      '@babel/generator': 7.22.5
      '@babel/helper-compilation-targets': 7.22.5(@babel/core@7.22.5)
      '@babel/helper-module-transforms': 7.22.5
      '@babel/helpers': 7.22.5
      '@babel/parser': 7.22.5
      '@babel/template': 7.22.5
      '@babel/traverse': 7.22.5
      '@babel/types': 7.22.5
      convert-source-map: 1.9.0
  /@babel/eslint-parser@7.22.5(@babel/core@7.22.5)(eslint@8.45.0):
    resolution: {integrity: sha512-C69RWYNYtrgIRE5CmTd77ZiLDXqgBipahJc/jHP3sLcAGj6AJzxNIuKNpVnICqbyK7X3pFUfEvL++rvtbQpZkQ==}
      '@babel/core': '>=7.11.0'
      '@babel/core': 7.22.5
  /@babel/generator@7.22.15:
    resolution: {integrity: sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/types': 7.22.15
      '@jridgewell/gen-mapping': 0.3.3
      '@jridgewell/trace-mapping': 0.3.18
      jsesc: 2.5.2

  /@babel/generator@7.22.5:
    resolution: {integrity: sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==}
      '@babel/types': 7.22.15
      '@jridgewell/trace-mapping': 0.3.18
      '@babel/types': 7.22.15
      '@babel/compat-data': 7.22.9
      '@babel/helper-validator-option': 7.22.15
      browserslist: 4.21.10
      lru-cache: 5.1.1
      semver: 6.3.1

  /@babel/helper-compilation-targets@7.22.5(@babel/core@7.22.5):
    resolution: {integrity: sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/compat-data': 7.22.9
      '@babel/core': 7.22.5
      browserslist: 4.21.10
  /@babel/helper-create-class-features-plugin@7.22.5(@babel/core@7.22.5):
    resolution: {integrity: sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==}
      '@babel/core': 7.22.5
      '@babel/helper-environment-visitor': 7.22.5
      '@babel/helper-function-name': 7.22.5
      '@babel/helper-member-expression-to-functions': 7.22.5
      '@babel/helper-replace-supers': 7.22.5
      '@babel/helper-split-export-declaration': 7.22.5
    transitivePeerDependencies:
      - supports-color
  /@babel/helper-environment-visitor@7.22.5:
    resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==}
  /@babel/helper-function-name@7.22.5:
    resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==}
      '@babel/template': 7.22.5
      '@babel/types': 7.22.15
      '@babel/types': 7.22.15
  /@babel/helper-member-expression-to-functions@7.22.5:
    resolution: {integrity: sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==}
      '@babel/types': 7.22.15
      '@babel/types': 7.22.15
      '@babel/types': 7.22.15

  /@babel/helper-module-imports@7.22.5:
    resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/types': 7.22.15
  /@babel/helper-module-transforms@7.22.15(@babel/core@7.22.15):
    resolution: {integrity: sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==}
      '@babel/core': 7.22.15
      '@babel/helper-environment-visitor': 7.22.5
      '@babel/helper-module-imports': 7.22.15
      '@babel/helper-simple-access': 7.22.5
      '@babel/helper-split-export-declaration': 7.22.6
      '@babel/helper-validator-identifier': 7.22.15

  /@babel/helper-module-transforms@7.22.5:
    resolution: {integrity: sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/helper-environment-visitor': 7.22.5
      '@babel/helper-validator-identifier': 7.22.15
      '@babel/template': 7.22.15
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
    transitivePeerDependencies:
      - supports-color
      '@babel/types': 7.22.15
  /@babel/helper-replace-supers@7.22.5:
    resolution: {integrity: sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==}
      '@babel/helper-environment-visitor': 7.22.5
      '@babel/helper-member-expression-to-functions': 7.22.5
      '@babel/template': 7.22.15
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
    transitivePeerDependencies:
      - supports-color
      '@babel/types': 7.22.15
      '@babel/types': 7.22.15

  /@babel/helper-split-export-declaration@7.22.5:
    resolution: {integrity: sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/types': 7.22.15
      '@babel/types': 7.22.15
  /@babel/helper-validator-identifier@7.22.15:
    resolution: {integrity: sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==}
    engines: {node: '>=6.9.0'}

  /@babel/helper-validator-identifier@7.22.5:
    resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
  /@babel/helper-validator-option@7.22.5:
    resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==}
    engines: {node: '>=6.9.0'}

  /@babel/helpers@7.22.15:
    resolution: {integrity: sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==}
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
    transitivePeerDependencies:
      - supports-color

  /@babel/helpers@7.22.5:
    resolution: {integrity: sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/template': 7.22.5
      '@babel/traverse': 7.22.5
      '@babel/types': 7.22.15
  /@babel/highlight@7.22.13:
    resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==}
      '@babel/helper-validator-identifier': 7.22.15
  /@babel/parser@7.22.16:
    resolution: {integrity: sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==}
      '@babel/types': 7.22.15
  /@babel/parser@7.22.5:
    resolution: {integrity: sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==}
    engines: {node: '>=6.0.0'}
    hasBin: true
    dependencies:
      '@babel/types': 7.22.15

  /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.15):
    resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-plugin-utils': 7.22.5
      '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.15)
    dev: false

  /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.15):
    resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-plugin-utils': 7.22.5
    dev: false

  /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.15):
    resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-plugin-utils': 7.22.5
    dev: false

  /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.15):
    resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-plugin-utils': 7.22.5

  /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.5):
      '@babel/core': 7.22.5
  /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.5):
      '@babel/core': 7.22.5
      '@babel/helper-plugin-utils': 7.22.5

  /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.15):
    resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-module-transforms': 7.22.5
      '@babel/helper-simple-access': 7.22.5
    transitivePeerDependencies:
      - supports-color
    dev: false
  /@babel/plugin-transform-modules-commonjs@7.22.5(@babel/core@7.22.5):
    resolution: {integrity: sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==}
      '@babel/core': 7.22.5
      '@babel/helper-module-transforms': 7.22.5
    transitivePeerDependencies:
      - supports-color

  /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.15):
    resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-annotate-as-pure': 7.22.5
      '@babel/helper-module-imports': 7.22.15
      '@babel/helper-plugin-utils': 7.22.5
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.15)
      '@babel/types': 7.22.15
  /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.5):
    resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==}
      '@babel/core': 7.22.5
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5)
      '@babel/types': 7.22.15
    dev: true
  /@babel/plugin-transform-typescript@7.22.5(@babel/core@7.22.5):
    resolution: {integrity: sha512-SMubA9S7Cb5sGSFFUlqxyClTA9zWJ8qGQrppNUm05LtFuN1ELRFNndkix4zUJrC9F+YivWwa1dHMSyo0e0N9dA==}
      '@babel/core': 7.22.5
      '@babel/helper-create-class-features-plugin': 7.22.5(@babel/core@7.22.5)
      '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.5)
    transitivePeerDependencies:
      - supports-color
  /@babel/preset-typescript@7.22.5(@babel/core@7.22.5):
    resolution: {integrity: sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==}
      '@babel/core': 7.22.5
      '@babel/helper-validator-option': 7.22.5
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5)
      '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.5)
      '@babel/plugin-transform-typescript': 7.22.5(@babel/core@7.22.5)
    transitivePeerDependencies:
      - supports-color
  /@babel/runtime@7.22.5:
    resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==}
      regenerator-runtime: 0.13.11
  /@babel/standalone@7.22.5:
    resolution: {integrity: sha512-6Lwhzral4YDEbIM3dBC8/w0BMDvOosGBGaJWSORLkerx8byawkmwwzXKUB0jGlI1Zp90+cK2uyTl62UPtLbUjQ==}
      '@babel/parser': 7.22.16
      '@babel/types': 7.22.15

  /@babel/template@7.22.5:
    resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/code-frame': 7.22.5
      '@babel/parser': 7.22.5
      '@babel/types': 7.22.15

  /@babel/traverse@7.22.15:
    resolution: {integrity: sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/code-frame': 7.22.13
      '@babel/generator': 7.22.15
      '@babel/helper-environment-visitor': 7.22.5
      '@babel/helper-function-name': 7.22.5
      '@babel/helper-hoist-variables': 7.22.5
      '@babel/helper-split-export-declaration': 7.22.6
      '@babel/parser': 7.22.16
      '@babel/types': 7.22.15
      debug: 4.3.4
      globals: 11.12.0
    transitivePeerDependencies:
      - supports-color
  /@babel/traverse@7.22.5:
    resolution: {integrity: sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==}
      '@babel/generator': 7.22.15
      '@babel/helper-environment-visitor': 7.22.5
      '@babel/helper-function-name': 7.22.5
      '@babel/parser': 7.22.16
      '@babel/types': 7.22.15
  /@babel/types@7.22.15:
    resolution: {integrity: sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==}
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/helper-string-parser': 7.22.5
      '@babel/helper-validator-identifier': 7.22.15
      to-fast-properties: 2.0.0

  /@babel/types@7.22.5:
    resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==}
      '@babel/helper-validator-identifier': 7.22.5
  /@bufbuild/connect-node@0.9.1(@bufbuild/protobuf@1.3.0):
      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.0)
      '@bufbuild/protobuf': 1.3.0
      headers-polyfill: 3.1.2
  /@bufbuild/connect@0.9.1(@bufbuild/protobuf@1.3.0):
      '@bufbuild/protobuf': 1.3.0
  /@bufbuild/protobuf@1.3.0:
    resolution: {integrity: sha512-G372ods0pLt46yxVRsnP/e2btVPuuzArcMPFpIDeIwiGPuuglEs9y75iG0HMvZgncsj5TvbYRWqbVyOe3PLCWQ==}
  /@esbuild/android-arm64@0.19.3:
    resolution: {integrity: sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==}
  /@esbuild/android-arm@0.19.3:
    resolution: {integrity: sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==}
  /@esbuild/android-x64@0.19.3:
    resolution: {integrity: sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==}
  /@esbuild/darwin-arm64@0.19.3:
    resolution: {integrity: sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==}
  /@esbuild/darwin-x64@0.19.3:
    resolution: {integrity: sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==}
  /@esbuild/freebsd-arm64@0.19.3:
    resolution: {integrity: sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==}
  /@esbuild/freebsd-x64@0.19.3:
    resolution: {integrity: sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==}
  /@esbuild/linux-arm64@0.19.3:
    resolution: {integrity: sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==}
  /@esbuild/linux-arm@0.19.3:
    resolution: {integrity: sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==}
  /@esbuild/linux-ia32@0.19.3:
    resolution: {integrity: sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==}
  /@esbuild/linux-loong64@0.19.3:
    resolution: {integrity: sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==}
  /@esbuild/linux-mips64el@0.19.3:
    resolution: {integrity: sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==}
  /@esbuild/linux-ppc64@0.19.3:
    resolution: {integrity: sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==}
  /@esbuild/linux-riscv64@0.19.3:
    resolution: {integrity: sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==}
  /@esbuild/linux-s390x@0.19.3:
    resolution: {integrity: sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==}
  /@esbuild/linux-x64@0.19.3:
    resolution: {integrity: sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==}
  /@esbuild/netbsd-x64@0.19.3:
    resolution: {integrity: sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==}
  /@esbuild/openbsd-x64@0.19.3:
    resolution: {integrity: sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==}
  /@esbuild/sunos-x64@0.19.3:
    resolution: {integrity: sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==}
  /@esbuild/win32-arm64@0.19.3:
    resolution: {integrity: sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==}
  /@esbuild/win32-ia32@0.19.3:
    resolution: {integrity: sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==}
  /@esbuild/win32-x64@0.19.3:
    resolution: {integrity: sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==}
      eslint-visitor-keys: 3.4.1
  /@eslint-community/regexpp@4.6.1:
    resolution: {integrity: sha512-O7x6dMstWLn2ktjcoiNLDkAGG2EjveHL+Vvc+n0fXumkJYAcSqcVYKtwDU+hDZ0uDUsnUagSYaZrOLAYE8un1A==}
  /@eslint/eslintrc@2.1.0:
    resolution: {integrity: sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==}
      globals: 13.20.0
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
  /@fastify/error@3.2.1:
    resolution: {integrity: sha512-scZVbcpPNWw/yyFmzzO7cf1daTeJp53spN2n7dBTHZd+cV7791fcWJCPP1Tfhdbre+8vDiCyQyqqXfQnYMntYQ==}
      fast-json-stringify: 5.7.0
      '@fastify/error': 3.2.1
      fast-jwt: 3.1.1
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      '@fastify/error': 3.2.1
      '@fastify/swagger': 8.10.0
      '@fastify/swagger-ui': 1.9.3
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      tiny-lru: 11.0.1
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      readable-stream: 4.4.0
  /@fastify/swagger-ui@1.9.3:
    resolution: {integrity: sha512-YYqce4CydjDIEry6Zo4JLjVPe5rjS8iGnk3fHiIQnth9sFSLeyG0U1DCH+IyYmLddNDg1uWJOuErlVqnu/jI3w==}
      fastify-plugin: 4.5.0
  /@fastify/swagger@8.10.0:
    resolution: {integrity: sha512-0o6nd0qWpJbVSv/vbK4bzHSYe7l+PTGPqrQVwWIXVGd7CvXr585SBx+h8EgrMOY80bcOnGreqnjYFOV0osGP5A==}
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      fastify-plugin: 4.5.0
      ws: 8.13.0
  /@floating-ui/core@1.3.1:
    resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
      '@floating-ui/core': 1.3.1
  /@graphql-typed-document-node/core@3.2.0(graphql@16.7.1):
      graphql: 16.7.1
  /@hocuspocus/common@2.5.0:
    resolution: {integrity: sha512-TpnQAb1Rtff1trwURFWaUEYZwqykaIGo6NNnMr6ZISdDZFWNHMAMUmy7dwJDS9ECnEtcjXhpPxXeLV+MVQXVnw==}
      lib0: 0.2.78
      uuid: 9.0.0
      '@hocuspocus/common': 2.5.0
      lib0: 0.2.78
      '@hocuspocus/common': 2.5.0
      lib0: 0.2.78
      uuid: 9.0.0
      ws: 8.13.0
      '@tiptap/starter-kit': 2.0.3(@tiptap/pm@2.1.8)
      y-prosemirror: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
  /@humanwhocodes/config-array@0.11.10:
    resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
  /@iconify/utils@2.1.9:
    resolution: {integrity: sha512-mo+A4n3MwLlWlg1SoSO+Dt6pOPWKElk9sSJ6ZpuzbB9OcjxN8RUWxU3ulPwB1nglErWKRam2x4BAohbYF7FiFA==}
      '@jridgewell/trace-mapping': 0.3.18
  /@jridgewell/resolve-uri@3.1.0:
    resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
  /@jridgewell/source-map@0.3.3:
    resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==}
      '@jridgewell/trace-mapping': 0.3.18
    dev: true

  /@jridgewell/sourcemap-codec@1.4.14:
    resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
  /@jridgewell/trace-mapping@0.3.18:
    resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==}
      '@jridgewell/resolve-uri': 3.1.0
      '@jridgewell/sourcemap-codec': 1.4.14
  /@linaria/core@4.2.9:
    resolution: {integrity: sha512-ELcu37VNVOT/PU0L6WDIN+aLzNFyJrqoBYT0CucGOCAmODbojUMCv8oJYRbWzA3N34w1t199dN4UFdfRWFG2rg==}
    engines: {node: ^12.16.0 || >=13.7.0}
    dependencies:
      '@linaria/logger': 4.0.0
      '@linaria/tags': 4.3.5
      '@linaria/utils': 4.3.4
    transitivePeerDependencies:
      - supports-color
  /@linaria/logger@4.0.0:
    resolution: {integrity: sha512-YnBq0JlDWMEkTOK+tMo5yEVR0f5V//6qMLToGcLhTyM9g9i+IDFn51Z+5q2hLk7RdG4NBPgbcCXYi2w4RKsPeg==}
    engines: {node: ^12.16.0 || >=13.7.0}
    dependencies:
      debug: 4.3.4
      picocolors: 1.0.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /@linaria/tags@4.3.5:
    resolution: {integrity: sha512-PgaIi8Vv89YOjc6rpKL/uPg2w4k0rAwAYxcqeXqzKqsEAste5rgB8xp1/KUOG0oAOkPd3MRL6Duj+m0ZwJ3g+g==}
    engines: {node: ^12.16.0 || >=13.7.0}
    dependencies:
      '@babel/generator': 7.22.15
      '@linaria/logger': 4.0.0
      '@linaria/utils': 4.3.4
    transitivePeerDependencies:
      - supports-color
    dev: false

  /@linaria/utils@4.3.4:
    resolution: {integrity: sha512-vt6WJG54n+KANaqxOfzIIU7aSfFHEWFbnGLsgxL7nASHqO0zezrNA2y2Rrp80zSeTW+wSpbmDM4uJyC9UW1qoA==}
    engines: {node: ^12.16.0 || >=13.7.0}
    dependencies:
      '@babel/core': 7.22.15
      '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.22.15)
      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.15)
      '@babel/plugin-transform-modules-commonjs': 7.22.5(@babel/core@7.22.15)
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
      '@linaria/logger': 4.0.0
      babel-merge: 3.0.0(@babel/core@7.22.15)
    transitivePeerDependencies:
      - supports-color
    dev: false

  /@lukeed/ms@2.0.1:
    resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==}
    engines: {node: '>=8'}
    dev: false

  /@manypkg/find-root@2.1.0:
    resolution: {integrity: sha512-NEYRVlZCJYhRTqQURhv+WBpDcvmsp/M423Wcdvggv8lYJYD4GtqnTMLrQaTjA10fYt/PIc3tSdwV+wxJnWqPfQ==}
    engines: {node: '>=14.18.0'}
  /@motionone/animation@10.15.1:
    resolution: {integrity: sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==}
      '@motionone/easing': 10.15.1
      '@motionone/types': 10.15.1
      '@motionone/utils': 10.15.1
      tslib: 2.5.3
  /@motionone/dom@10.16.2:
    resolution: {integrity: sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg==}
      '@motionone/animation': 10.15.1
      '@motionone/generators': 10.15.1
      '@motionone/types': 10.15.1
      '@motionone/utils': 10.15.1
      tslib: 2.5.3
  /@motionone/easing@10.15.1:
    resolution: {integrity: sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==}
      '@motionone/utils': 10.15.1
      tslib: 2.5.3
  /@motionone/generators@10.15.1:
    resolution: {integrity: sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==}
      '@motionone/types': 10.15.1
      '@motionone/utils': 10.15.1
      tslib: 2.5.3
  /@motionone/solid@10.16.2(solid-js@1.7.8):
      '@motionone/dom': 10.16.2
      '@motionone/utils': 10.15.1
      '@solid-primitives/props': 3.1.6(solid-js@1.7.8)
      '@solid-primitives/refs': 1.0.4(solid-js@1.7.8)
      '@solid-primitives/transition-group': 1.0.2(solid-js@1.7.8)
      solid-js: 1.7.8
  /@motionone/types@10.15.1:
    resolution: {integrity: sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==}
  /@motionone/utils@10.15.1:
    resolution: {integrity: sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==}
      '@motionone/types': 10.15.1
      tslib: 2.5.3
  /@octokit/app@14.0.0:
    resolution: {integrity: sha512-g/zDXttroZ9Se08shK0d0d/j0cgSA+h4WV7qGUevNEM0piNBkIlfb4Fm6bSwCNAZhNf72mBgERmYOoxicPkqdw==}
      '@octokit/auth-app': 6.0.0
      '@octokit/auth-unauthenticated': 5.0.0
      '@octokit/core': 5.0.0
      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
      '@octokit/types': 11.1.0
  /@octokit/auth-app@6.0.0:
    resolution: {integrity: sha512-OKct7Rukf3g9DjpzcpdacQsdmd6oPrJ7fZND22JkjzhDvfhttUOnmh+qPS4kHhaNNyTxqSThnfrUWvkqNLd1nw==}
      '@octokit/auth-oauth-app': 7.0.0
      '@octokit/auth-oauth-user': 4.0.0
      '@octokit/request': 8.1.1
      '@octokit/request-error': 5.0.0
      '@octokit/types': 11.1.0
      lru-cache: 10.0.0
  /@octokit/auth-oauth-app@7.0.0:
    resolution: {integrity: sha512-8JvJEXGoEqrbzLwt3SwIUvkDd+1wrM8up0KawvDIElB8rbxPbvWppGO0SLKAWSJ0q8ILcVq+mWck6pDcZ3a9KA==}
      '@octokit/auth-oauth-device': 6.0.0
      '@octokit/auth-oauth-user': 4.0.0
      '@octokit/request': 8.1.1
      '@octokit/types': 11.1.0
  /@octokit/auth-oauth-device@6.0.0:
    resolution: {integrity: sha512-Zgf/LKhwWk54rJaTGYVYtbKgUty+ouil6VQeRd+pCw7Gd0ECoSWaZuHK6uDGC/HtnWHjpSWFhzxPauDoHcNRtg==}
      '@octokit/request': 8.1.1
      '@octokit/types': 11.1.0
  /@octokit/auth-oauth-user@4.0.0:
    resolution: {integrity: sha512-VOm5aIkVGHaOhIvsF/4YmSjoYDzzrKbbYkdSEO0KqHK7I8SlO3ZndSikQ1fBlNPUEH0ve2BOTxLrVvI1qBf9/Q==}
      '@octokit/auth-oauth-device': 6.0.0
      '@octokit/request': 8.1.1
      '@octokit/types': 11.1.0
  /@octokit/auth-unauthenticated@5.0.0:
    resolution: {integrity: sha512-AjOI6FNB2dweJ85p6rf7D4EhE4y6VBcwYfX/7KJkR5Q9fD9ET6NABAjajUTSNFfCxmNIaQgISggZ3pkgwtTqsA==}
      '@octokit/request-error': 5.0.0
      '@octokit/types': 11.1.0
  /@octokit/core@5.0.0:
    resolution: {integrity: sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==}
      '@octokit/graphql': 7.0.1
      '@octokit/request': 8.1.1
      '@octokit/request-error': 5.0.0
      '@octokit/types': 11.1.0
  /@octokit/endpoint@9.0.0:
    resolution: {integrity: sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==}
      '@octokit/types': 11.1.0
  /@octokit/graphql@7.0.1:
    resolution: {integrity: sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==}
      '@octokit/request': 8.1.1
      '@octokit/types': 11.1.0
      '@octokit/auth-oauth-app': 7.0.0
      '@octokit/auth-oauth-user': 4.0.0
      '@octokit/auth-unauthenticated': 5.0.0
      '@octokit/core': 5.0.0
      '@types/aws-lambda': 8.10.119
      '@octokit/request': 8.1.1
      '@octokit/request-error': 5.0.0
  /@octokit/openapi-types@18.0.0:
    resolution: {integrity: sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==}
  /@octokit/plugin-paginate-rest@8.0.0(@octokit/core@5.0.0):
      '@octokit/core': 5.0.0
  /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.0):
      '@octokit/core': 5.0.0
  /@octokit/plugin-rest-endpoint-methods@9.0.0(@octokit/core@5.0.0):
      '@octokit/core': 5.0.0
  /@octokit/plugin-retry@6.0.0(@octokit/core@5.0.0):
    resolution: {integrity: sha512-a1/A4A+PB1QoAHQfLJxGHhLfSAT03bR1jJz3GgQJZvty2ozawFWs93MiBQXO7SL2YbO7CIq0Goj4qLOBj8JeMQ==}
      '@octokit/core': 5.0.0
      '@octokit/request-error': 5.0.0
      '@octokit/types': 11.1.0
  /@octokit/plugin-throttling@7.0.0(@octokit/core@5.0.0):
      '@octokit/core': 5.0.0
  /@octokit/request-error@5.0.0:
    resolution: {integrity: sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==}
      '@octokit/types': 11.1.0
      node-fetch: 2.6.12
  /@octokit/request@8.1.1:
    resolution: {integrity: sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==}
      '@octokit/endpoint': 9.0.0
      '@octokit/request-error': 5.0.0
      '@octokit/types': 11.1.0
      '@octokit/core': 5.0.0
      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
      '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.0)
      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.0)
      '@octokit/openapi-types': 18.0.0
      '@octokit/openapi-types': 18.0.0
      '@octokit/openapi-types': 18.0.0
      '@octokit/request-error': 5.0.0
  /@pkgr/utils@2.4.1:
    resolution: {integrity: sha512-JOqwkgFEyi+OROIyq7l4Jy28h/WwhDnG/cPkXG2Z1iFbubB6jsHW1NDvmyOzTBxHr3yg68YGirmh1JUgMqa+9w==}
      tslib: 2.5.3
  /@polka/url@1.0.0-next.21:
    resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
  /@qdrant/js-client-grpc@1.4.0(typescript@5.1.6):
      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.0)
      '@bufbuild/connect-node': 0.9.1(@bufbuild/protobuf@1.3.0)
      '@bufbuild/protobuf': 1.3.0
      typescript: 5.1.6
  /@qdrant/js-client-rest@1.4.0(typescript@5.1.6):
      typescript: 5.1.6
      undici: 5.22.1
  /@qdrant/qdrant-js@1.4.0(typescript@5.1.6):
      '@qdrant/js-client-grpc': 1.4.0(typescript@5.1.6)
      '@qdrant/js-client-rest': 1.4.0(typescript@5.1.6)
      typescript: 5.1.6
      '@babel/runtime': 7.22.5
      '@babel/runtime': 7.22.5
  /@remirror/core-constants@2.0.1:
    resolution: {integrity: sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==}
    dependencies:
      '@babel/runtime': 7.22.5
  /@remirror/core-helpers@2.0.3:
    resolution: {integrity: sha512-LqIPF4stGG69l9qu/FFicv9d9B+YaItzgDMC5A0CEvDQfKkGD3BfabLmfpnuWbsc06oKGdTduilgWcALLZoYLg==}
      '@babel/runtime': 7.22.5
      '@linaria/core': 4.2.9
      '@remirror/core-constants': 2.0.1
      '@types/object.omit': 3.0.0
    transitivePeerDependencies:
      - supports-color
  /@rollup/plugin-alias@5.0.0(rollup@3.26.2):
    resolution: {integrity: sha512-l9hY5chSCjuFRPsnRm16twWBiSApl2uYFLsepQYwtBuAxNMQ/1dJqADld40P0Jkqm65GRTLy/AC6hnpVebtLsA==}
      rollup: ^1.20.0||^2.0.0||^3.0.0
      rollup: 3.26.2
  /@rollup/plugin-commonjs@24.1.0(rollup@3.26.2):
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      rollup: 3.26.2
  /@rollup/plugin-json@6.0.0(rollup@3.26.2):
    resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==}
      rollup: ^1.20.0||^2.0.0||^3.0.0
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      rollup: 3.26.2
  /@rollup/plugin-node-resolve@15.1.0(rollup@3.26.2):
    resolution: {integrity: sha512-xeZHCgsiZ9pzYVgAo9580eCGqwh/XCEUM9q6iQfGNocjgkufHAqC3exA+45URvhiYV8sBF9RlBai650eNs7AsA==}
      rollup: ^2.78.0||^3.0.0
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      resolve: 1.22.2
      rollup: 3.26.2
  /@rollup/plugin-replace@5.0.2(rollup@3.26.2):
    resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==}
      rollup: ^1.20.0||^2.0.0||^3.0.0
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      rollup: 3.26.2
    dev: true

  /@rollup/pluginutils@5.0.2(rollup@3.26.2):
    resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
    engines: {node: '>=14.0.0'}
    peerDependencies:
      rollup: ^1.20.0||^2.0.0||^3.0.0
    peerDependenciesMeta:
      rollup:
        optional: true
    dependencies:
      '@types/estree': 1.0.1
      estree-walker: 2.0.2
      picomatch: 2.3.1
      rollup: 3.26.2
  /@rollup/pluginutils@5.0.4(rollup@3.26.2):
    resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==}
      rollup: ^1.20.0||^2.0.0||^3.0.0
      '@types/estree': 1.0.1
      rollup: 3.26.2
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
      tslib: 2.5.3
  /@solid-primitives/active-element@2.0.15(solid-js@1.7.8):
      '@solid-primitives/event-listener': 2.2.13(solid-js@1.7.8)
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/connectivity@0.3.15(solid-js@1.7.8):
      '@solid-primitives/event-listener': 2.2.13(solid-js@1.7.8)
      '@solid-primitives/rootless': 1.4.1(solid-js@1.7.8)
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/event-listener@2.2.13(solid-js@1.7.8):
    resolution: {integrity: sha512-8GtVEq0ECZoa5Klo1jjfGPfwg0zVJ8TNnNkWu8FqRkh0CkhbhCVJAKwjleem9K/qL6zUDfJihLjhqGBTBbb+8w==}
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/media@2.2.3(solid-js@1.7.8):
      '@solid-primitives/event-listener': 2.2.13(solid-js@1.7.8)
      '@solid-primitives/rootless': 1.4.1(solid-js@1.7.8)
      '@solid-primitives/static-store': 0.0.4(solid-js@1.7.8)
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/memo@1.3.2(solid-js@1.7.8):
      '@solid-primitives/scheduled': 1.4.0(solid-js@1.7.8)
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/props@3.1.6(solid-js@1.7.8):
    resolution: {integrity: sha512-ChtvXBDxASR+zZgH0ysoBstbVJdqJk6LITb78CScgHd+Uc8C6eaHKLmhNeuVCd36FGAuyj9vylDHe2GhmFlecA==}
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/refs@1.0.4(solid-js@1.7.8):
    resolution: {integrity: sha512-BxZKkct0OIyADWIoA9UITm+3G5Xb3IkOa0nZd40SgOK5DtMqpXFIEPUkJ/woPB90WqlM9UvvuiJHUyAjMeAmCw==}
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/rootless@1.4.1(solid-js@1.7.8):
    resolution: {integrity: sha512-h7VBUk8usD76Eh1a4wT17PcGtIRxGPlLuJ4Mf7roCNu46W5cc9DAoz8M6XebuZWVKeUkML/JuPMZQSV0mLo2Fw==}
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/scheduled@1.4.0(solid-js@1.7.8):
      solid-js: 1.7.8
  /@solid-primitives/static-store@0.0.4(solid-js@1.7.8):
      '@solid-primitives/utils': 6.2.0(solid-js@1.7.8)
      solid-js: 1.7.8
  /@solid-primitives/transition-group@1.0.2(solid-js@1.7.8):
    resolution: {integrity: sha512-+o3J7TnU0/Sok+LKA0z0wvhim88dpd2eFBk8/05adE6wVypVlME8sKqTMO+xRv8HoT4Kq3sczmvwV07FKg2n+g==}
      solid-js: 1.7.8
  /@solid-primitives/utils@6.2.0(solid-js@1.7.8):
    resolution: {integrity: sha512-T62WlLwKkbmicsw/xpwMQyv9MmZRSaVyutXfS5icc9v0cb8qGMUxRxr5LVvZHYQCZ9DEFboZB0r711xsbVBbeA==}
      solid-js: 1.7.8
  /@solidjs/router@0.8.2(solid-js@1.7.8):
      solid-js: 1.7.8
  /@tiptap/extension-code-block-lowlight@2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.0.3)(@tiptap/pm@2.1.8):
      '@tiptap/extension-code-block': 2.0.3(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
  /@tiptap/extension-code-block@2.0.3(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-F4xMy18EwgpyY9f5Te7UuF7UwxRLptOtCq1p2c2DfxBvHDWhAjQqVqcW/sq/I/WuED7FwCnPLyyAasPiVPkLPw==}
      y-prosemirror: 1.0.20(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
      y-prosemirror: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
      y-prosemirror: 1.0.20(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
      y-prosemirror: 1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7)
  /@tiptap/extension-heading@2.0.3(@tiptap/core@2.1.8):
    resolution: {integrity: sha512-f0IEv5ms6aCzL80WeZ1qLCXTkRVwbpRr1qAETjg3gG4eoJN18+lZNOJYpyZy3P92C5KwF2T3Av00eFyVLIbb8Q==}
      '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
      prosemirror-markdown: 1.11.0
      prosemirror-menu: 1.2.2
      prosemirror-model: 1.19.2
      prosemirror-tables: 1.3.3
      prosemirror-trailing-node: 2.0.4(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)
      prosemirror-transform: 1.7.3
      prosemirror-view: 1.31.4
    transitivePeerDependencies:
      - supports-color
    dev: false

  /@tiptap/starter-kit@2.0.3(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-t4WG4w93zTpL2VxhVyJJvl3kdLF001ZrhpOuEiZqEMBMUMbM56Uiigv1CnUQpTFrjDAh3IM8hkqzAh20TYw2iQ==}
    dependencies:
      '@tiptap/core': 2.1.8(@tiptap/pm@2.1.8)
      '@tiptap/extension-blockquote': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-bold': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-bullet-list': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-code': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-code-block': 2.0.3(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
      '@tiptap/extension-document': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-dropcursor': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
      '@tiptap/extension-gapcursor': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
      '@tiptap/extension-hard-break': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-heading': 2.0.3(@tiptap/core@2.1.8)
      '@tiptap/extension-history': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
      '@tiptap/extension-horizontal-rule': 2.1.8(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
      '@tiptap/extension-italic': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-list-item': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-ordered-list': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-paragraph': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-strike': 2.1.8(@tiptap/core@2.1.8)
      '@tiptap/extension-text': 2.1.8(@tiptap/core@2.1.8)
  /@types/aws-lambda@8.10.119:
    resolution: {integrity: sha512-Vqm22aZrCvCd6I5g1SvpW151jfqwTzEZ7XJ3yZ6xaZG31nUEOEyzzVImjRcsN8Wi/QyPxId/x8GTtgIbsy8kEw==}
  /@types/babel__core@7.20.1:
    resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==}
      '@babel/parser': 7.22.16
      '@babel/types': 7.22.15
      '@types/babel__generator': 7.6.4
      '@types/babel__template': 7.4.1
      '@types/babel__traverse': 7.20.1
  /@types/babel__generator@7.6.4:
    resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==}
      '@babel/types': 7.22.15
  /@types/babel__template@7.4.1:
    resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==}
      '@babel/parser': 7.22.5
      '@babel/types': 7.22.15
  /@types/babel__traverse@7.20.1:
    resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==}
      '@babel/types': 7.22.15
  /@types/debug@4.1.8:
    resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==}
      '@types/ms': 0.7.31
  /@types/dom-view-transitions@1.0.1:
    resolution: {integrity: sha512-A9S1ijj/4MX06I1W/6on8lhaYyq1Ir7gaOvfllW1o4RzVWW88HAeqX0pUx9VgOLnNpdiGeUW2CTkg18p5LWIrA==}
      '@types/trusted-types': 2.0.3
  /@types/estree@1.0.1:
    resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
  /@types/hast@2.3.4:
    resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==}
      '@types/unist': 2.0.6
  /@types/json-schema@7.0.12:
    resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==}
  /@types/jsonwebtoken@9.0.2:
    resolution: {integrity: sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==}
  /@types/mdast@3.0.11:
    resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
      '@types/unist': 2.0.6
  /@types/mdast@4.0.0:
    resolution: {integrity: sha512-YLeG8CujC9adtj/kuDzq1N4tCDYKoZ5l/bnjq8d74+t/3q/tHquJOJKUQXJrLCflOHpKjXgcI/a929gpmLOEng==}
  /@types/ms@0.7.31:
    resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==}
  /@types/nlcst@1.0.0:
    resolution: {integrity: sha512-3TGCfOcy8R8mMQ4CNSNOe3PG66HttvjcLzCoOpvXvDtfWOTi+uT/rxeOKm/qEwbM4SNe1O/PjdiBK2YcTjU4OQ==}
      '@types/unist': 3.0.0
  /@types/node-fetch@2.6.4:
    resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==}
      form-data: 3.0.1
  /@types/node@18.17.5:
    resolution: {integrity: sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==}
    dev: true
  /@types/normalize-package-data@2.4.1:
    resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
  /@types/object.omit@3.0.0:
    resolution: {integrity: sha512-I27IoPpH250TUzc9FzXd0P1BV/BMJuzqD3jOz98ehf9dQqGkxlq+hO1bIqZGWqCg5bVOy0g4AUVJtnxe0klDmw==}
  /@types/prop-types@15.7.5:
    resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
      '@types/prop-types': 15.7.5
      '@types/scheduler': 0.16.3
  /@types/sax@1.2.4:
    resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==}
  /@types/scheduler@0.16.3:
    resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
  /@types/semver@7.5.0:
    resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==}
  /@types/trusted-types@2.0.3:
    resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
  /@types/unist@2.0.6:
    resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
  /@types/webidl-conversions@7.0.0:
    resolution: {integrity: sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==}
      '@types/webidl-conversions': 7.0.0
  /@types/yargs-parser@21.0.0:
    resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==}
  /@typescript-eslint/eslint-plugin@3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.1.6):
      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
      tsutils: 3.21.0(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/eslint-plugin@6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.1.6):
      '@eslint-community/regexpp': 4.6.1
      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
      '@typescript-eslint/type-utils': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
      ts-api-utils: 1.0.1(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/experimental-utils@3.10.1(eslint@8.45.0)(typescript@5.1.6):
      '@types/json-schema': 7.0.12
      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.1.6)
  /@typescript-eslint/parser@3.10.1(eslint@8.45.0)(typescript@5.1.6):
      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/parser@6.2.0(eslint@8.45.0)(typescript@5.1.6):
      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/scope-manager@5.59.11:
    resolution: {integrity: sha512-dHFOsxoLFtrIcSj5h0QoBT/89hxQONwmn3FOQ0GOQcLOOXm+MIrS8zEAhs4tWl5MraxCY3ZJpaXQQdFMc2Tu+Q==}
      '@typescript-eslint/types': 5.59.11
      '@typescript-eslint/visitor-keys': 5.59.11
  /@typescript-eslint/type-utils@6.2.0(eslint@8.45.0)(typescript@5.1.6):
      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6)
      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
      ts-api-utils: 1.0.1(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/types@5.59.11:
    resolution: {integrity: sha512-epoN6R6tkvBYSc+cllrz+c2sOFWkbisJZWkOE+y3xHtvYaOE6Wk6B8e114McRJwFRjGvYdJwLXQH5c9osME/AA==}
  /@typescript-eslint/typescript-estree@3.10.1(typescript@5.1.6):
      tsutils: 3.21.0(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/typescript-estree@5.59.11(typescript@5.1.6):
    resolution: {integrity: sha512-YupOpot5hJO0maupJXixi6l5ETdrITxeo5eBOeuV7RSKgYdU3G5cxO49/9WRnJq9EMrB7AuTSLH/bqOsXi7wPA==}
      '@typescript-eslint/types': 5.59.11
      '@typescript-eslint/visitor-keys': 5.59.11
      tsutils: 3.21.0(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/typescript-estree@6.2.0(typescript@5.1.6):
      ts-api-utils: 1.0.1(typescript@5.1.6)
      typescript: 5.1.6
  /@typescript-eslint/utils@5.59.11(eslint@8.45.0)(typescript@5.1.6):
    resolution: {integrity: sha512-didu2rHSOMUdJThLk4aZ1Or8IcO3HzCw/ZvEjTTIfjIrcdd5cvSIwwDy2AOlE7htSNp7QIZ10fLMyRCveesMLg==}
      '@types/json-schema': 7.0.12
      '@types/semver': 7.5.0
      '@typescript-eslint/scope-manager': 5.59.11
      '@typescript-eslint/types': 5.59.11
      '@typescript-eslint/typescript-estree': 5.59.11(typescript@5.1.6)
  /@typescript-eslint/utils@6.2.0(eslint@8.45.0)(typescript@5.1.6):
      '@types/json-schema': 7.0.12
      '@types/semver': 7.5.0
      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.1.6)
  /@typescript-eslint/visitor-keys@5.59.11:
    resolution: {integrity: sha512-KGYniTGG3AMTuKF9QBD7EIrvufkB6O6uX3knP73xbKLMpH+QRPcgnCxjWXSHjMRuOxFLovljqQgQpR0c7GvjoA==}
      '@typescript-eslint/types': 5.59.11
      eslint-visitor-keys: 3.4.1
      eslint-visitor-keys: 3.4.1
  /@unocss/astro@0.55.7(vite@4.4.7):
    resolution: {integrity: sha512-mw8r14ArxUQBVCCisAJlF/WsZb650iBsduD/lXMk56N/nQ3MMArCcn62kcAxgZSb5tfIOQGQu/tbR8hEcD8y2g==}
    peerDependencies:
      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
    peerDependenciesMeta:
      vite:
        optional: true
    dependencies:
      '@unocss/core': 0.55.7
      '@unocss/reset': 0.55.7
      '@unocss/vite': 0.55.7(vite@4.4.7)
      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
    transitivePeerDependencies:
      - rollup
    dev: true
      vite: 4.4.9(sass@1.64.1)
    dev: false
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      magic-string: 0.30.3
      unconfig: 0.3.10
  /@unocss/postcss@0.55.7(postcss@8.4.29):
      magic-string: 0.30.3
      postcss: 8.4.29
      '@iconify/utils': 2.1.9
  /@unocss/vite@0.55.7(vite@4.4.7):
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      magic-string: 0.30.3
      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
    dev: true
  /@unocss/vite@0.55.7(vite@4.4.9):
    resolution: {integrity: sha512-xmdyDnt9Ag4o7DGl22/P6MaB+HSjWOQw9qYYzIefSv3SVUvn3cEhIX/PCWqFp8Kts2HyvAoJLbZmygSf1XdZNQ==}
      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
    dependencies:
      '@ampproject/remapping': 2.2.1
      '@rollup/pluginutils': 5.0.4(rollup@3.26.2)
      '@unocss/config': 0.55.7
      '@unocss/core': 0.55.7
      '@unocss/inspector': 0.55.7
      '@unocss/scope': 0.55.7
      '@unocss/transformer-directives': 0.55.7
      chokidar: 3.5.3
      fast-glob: 3.3.1
      magic-string: 0.30.3
      vite: 4.4.9(sass@1.64.1)
    transitivePeerDependencies:
      - rollup
    dev: false

  /@vrite/tiptap-solid@1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.8):
    resolution: {integrity: sha512-eSv3kr8VAjyZ8aVEfhzIGe/LLDAcdBS0GEcWr+Eaab3tM6N11PIhI/1vlufU02uAF0JFY4yx/NA1jvGLU8jEWw==}
    peerDependencies:
      '@tiptap/core': 2.1.8
      '@tiptap/pm': 2.1.8
      solid-js: ^1.7.11
      solid-js: 1.7.8
  /@vscode/emmet-helper@2.8.9:
    resolution: {integrity: sha512-ygpVStaePHt9aI9zk4NNJWI/NsRaeDSW1vQsZVmtpVRVCOdwYlsc3BfB/eppUu1OucT0x3OHDAzKcxnitjcSXQ==}
      emmet: 2.4.4
      vscode-languageserver-textdocument: 1.0.8
      vscode-languageserver-types: 3.17.3
  /@vscode/l10n@0.0.14:
    resolution: {integrity: sha512-/yrv59IEnmh655z1oeDnGcvMYwnEzNzHLgeYcQCkhYX0xBvYWrAuefoiLcPBUkMpJsb46bqQ6Yv4pwTTQ4d3Qg==}
    dev: true
  /ansi-sequence-parser@1.1.0:
    resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==}
  /array-includes@3.1.6:
    resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
  /array.prototype.flat@1.3.1:
    resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
  /array.prototype.flatmap@1.3.1:
    resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
      zod: 3.22.2
      '@babel/core': 7.22.15
      '@babel/generator': 7.22.15
      '@babel/parser': 7.22.16
      '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.15)
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
      '@types/babel__core': 7.20.1
      '@types/dom-view-transitions': 1.0.1
      '@types/yargs-parser': 21.0.0
      ci-info: 3.8.0
      es-module-lexer: 1.3.0
      magic-string: 0.30.3
      vite: 4.4.9(sass@1.64.1)
      zod: 3.22.2
    transitivePeerDependencies:
      - '@types/node'
      - less
      - lightningcss
      - sass
      - stylus
      - sugarss
      - supports-color
      - terser
    dev: false

  /astro@2.9.2:
    resolution: {integrity: sha512-ejdGM9SbK58AvJS8lbkre/d5CoW8JftqaRxc9rGqzpiZQ8iU8gfdFmi3Hzkcvd2HrGvYYsJku88pM6tkBPniJQ==}
    engines: {node: '>=16.12.0', npm: '>=6.14.0'}
    hasBin: true
    peerDependencies:
      sharp: '>=0.31.0'
    peerDependenciesMeta:
      sharp:
        optional: true
    dependencies:
      '@astrojs/compiler': 1.6.2
      '@astrojs/internal-helpers': 0.1.1
      '@astrojs/language-server': 1.0.8
      '@astrojs/markdown-remark': 2.2.1(astro@2.9.2)
      '@astrojs/telemetry': 2.1.1
      '@astrojs/webapi': 2.2.0
      '@babel/core': 7.22.5
      '@babel/generator': 7.22.5
      '@babel/parser': 7.22.5
      '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.5)
      '@babel/traverse': 7.22.5
      '@babel/types': 7.22.5
      '@types/babel__core': 7.20.1
      '@types/dom-view-transitions': 1.0.1
      '@types/yargs-parser': 21.0.0
      acorn: 8.10.0
      boxen: 6.2.1
      chokidar: 3.5.3
      ci-info: 3.8.0
      common-ancestor-path: 1.0.1
      cookie: 0.5.0
      debug: 4.3.4
      deepmerge-ts: 4.3.0
      devalue: 4.3.2
      diff: 5.1.0
      es-module-lexer: 1.3.0
      esbuild: 0.17.19
      estree-walker: 3.0.0
      execa: 6.1.0
      fast-glob: 3.3.1
      github-slugger: 2.0.0
      gray-matter: 4.0.3
      html-escaper: 3.0.3
      js-yaml: 4.1.0
      kleur: 4.1.5
      magic-string: 0.27.0
      mime: 3.0.0
      network-information-types: 0.1.1(typescript@5.2.2)
      ora: 6.3.1
      p-limit: 4.0.0
      path-to-regexp: 6.2.1
      preferred-pm: 3.0.3
      prompts: 2.4.2
      rehype: 12.0.1
      semver: 7.5.4
      server-destroy: 1.0.1
      shiki: 0.14.4
      string-width: 5.1.2
      strip-ansi: 7.1.0
      tsconfig-resolver: 3.0.1
      typescript: 5.2.2
      unist-util-visit: 4.1.2
      vfile: 5.3.7
      vite: 4.4.9(sass@1.64.1)
      vitefu: 0.2.4(vite@4.4.9)
      which-pm: 2.0.0
      yargs-parser: 21.1.1
    dev: true
      '@astrojs/compiler': 2.1.0
      '@babel/core': 7.22.15
      '@babel/generator': 7.22.15
      '@babel/parser': 7.22.16
      '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.15)
      '@babel/traverse': 7.22.15
      '@babel/types': 7.22.15
      '@types/babel__core': 7.20.1
      ci-info: 3.8.0
      es-module-lexer: 1.3.0
      esbuild: 0.19.3
      magic-string: 0.30.3
      resolve: 1.22.4
      undici: 5.23.0
      vite: 4.4.9(sass@1.64.1)
      follow-redirects: 1.15.2
      follow-redirects: 1.15.2
  /babel-merge@3.0.0(@babel/core@7.22.15):
    resolution: {integrity: sha512-eBOBtHnzt9xvnjpYNI5HmaPp/b2vMveE5XggzqHnQeHJ8mFIBrBv6WZEVIj5jJ2uwTItkqKo9gWzEEcBxEq0yw==}
    peerDependencies:
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.22.15
      deepmerge: 2.2.1
      object.omit: 3.0.0
    dev: false

  /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.22.15):
    resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==}
    peerDependencies:
      '@babel/core': ^7.20.12
    dependencies:
      '@babel/core': 7.22.15
      '@babel/helper-module-imports': 7.18.6
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.15)
      '@babel/types': 7.22.15
      html-entities: 2.3.3
      validate-html-nesting: 1.2.2
    dev: false

  /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.22.5):
    resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==}
      '@babel/core': 7.22.5
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.5)
      '@babel/types': 7.22.15
  /babel-preset-solid@1.7.4(@babel/core@7.22.5):
    resolution: {integrity: sha512-0mbHNYkbOVYhH6L95VlHVkBEVQjOXSzUqLDiFxUcsg/tU4yTM/qx7FI8C+kmos9LHckQBSm3wtwoe1BZLNJR1w==}
    peerDependencies:
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.22.5
      babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.22.5)

  /babel-preset-solid@1.7.7(@babel/core@7.22.15):
    resolution: {integrity: sha512-tdxVzx3kgcIjNXAOmGRbzIhFBPeJjSakiN9yM+IYdL/+LtXNnbGqb0Va5tJb8Sjbk+QVEriovCyuzB5T7jeTvg==}
      '@babel/core': 7.22.15
      babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.22.15)
    dev: false
  /browserslist@4.21.10:
    resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==}
      caniuse-lite: 1.0.30001528
      electron-to-chromium: 1.4.510
      update-browserslist-db: 1.0.11(browserslist@4.21.10)
  /bson@5.4.0:
    resolution: {integrity: sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==}
    dev: true
  /busboy@1.6.0:
    resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
    engines: {node: '>=10.16.0'}
    dependencies:
      streamsearch: 1.1.0

  /caniuse-lite@1.0.30001528:
    resolution: {integrity: sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q==}
      fsevents: 2.3.2
  /ci-info@3.8.0:
    resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==}
  /cli-spinners@2.9.0:
    resolution: {integrity: sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==}
    dev: true
  /convert-source-map@1.9.0:
    resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
      node-fetch: 2.6.12
      '@babel/runtime': 7.22.5
  /deepmerge-ts@4.3.0:
    resolution: {integrity: sha512-if3ZYdkD2dClhnXR5reKtG98cwyaRT1NeugQoAPTTfsOpV9kqyeiBF9Qa5RHjemb3KzD5ulqygv6ED3t5j9eJw==}
    engines: {node: '>=12.4.0'}
    dev: true

  /deepmerge@2.2.1:
    resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==}
    engines: {node: '>=0.10.0'}
    dev: false

      execa: 7.1.1
  /define-properties@1.2.0:
    resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==}
  /destr@2.0.0:
    resolution: {integrity: sha512-FJ9RDpf3GicEBvzI3jxc2XhHzbqD8p4ANw/1kPsFBfTvP1b7Gn/Lg1vO7R9J4IVgoMbyUmFrFGZafJ1hPZpvlg==}
    dev: false

      dotenv: 16.1.4
  /dotenv@16.1.4:
    resolution: {integrity: sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==}
  /electron-to-chromium@1.4.510:
    resolution: {integrity: sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g==}
  /emmet@2.4.4:
    resolution: {integrity: sha512-v8Mwpjym55CS3EjJgiCLWUB3J2HSR93jhzXW325720u8KvYxdI2voYLstW3pHBxFz54H6jFjayR9G4LfTG0q+g==}
      dotenv: 16.1.4
  /es-abstract@1.21.2:
    resolution: {integrity: sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==}
      function.prototype.name: 1.1.5
      has: 1.0.3
      is-typed-array: 1.1.10
      regexp.prototype.flags: 1.5.0
      string.prototype.trim: 1.2.7
      string.prototype.trimend: 1.0.6
      string.prototype.trimstart: 1.0.6
      which-typed-array: 1.1.9
  /es-module-lexer@1.3.0:
    resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==}
      has: 1.0.3
      has: 1.0.3
  /esbuild@0.19.3:
    resolution: {integrity: sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==}
      '@esbuild/android-arm': 0.19.3
      '@esbuild/android-arm64': 0.19.3
      '@esbuild/android-x64': 0.19.3
      '@esbuild/darwin-arm64': 0.19.3
      '@esbuild/darwin-x64': 0.19.3
      '@esbuild/freebsd-arm64': 0.19.3
      '@esbuild/freebsd-x64': 0.19.3
      '@esbuild/linux-arm': 0.19.3
      '@esbuild/linux-arm64': 0.19.3
      '@esbuild/linux-ia32': 0.19.3
      '@esbuild/linux-loong64': 0.19.3
      '@esbuild/linux-mips64el': 0.19.3
      '@esbuild/linux-ppc64': 0.19.3
      '@esbuild/linux-riscv64': 0.19.3
      '@esbuild/linux-s390x': 0.19.3
      '@esbuild/linux-x64': 0.19.3
      '@esbuild/netbsd-x64': 0.19.3
      '@esbuild/openbsd-x64': 0.19.3
      '@esbuild/sunos-x64': 0.19.3
      '@esbuild/win32-arm64': 0.19.3
      '@esbuild/win32-ia32': 0.19.3
      '@esbuild/win32-x64': 0.19.3
  /eslint-config-xtrict@3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.1.6):
      '@typescript-eslint/eslint-plugin': 3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.1.6)
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
      typescript: 5.1.6
  /eslint-import-resolver-node@0.3.7:
    resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==}
      is-core-module: 2.12.1
      resolve: 1.22.2
  /eslint-module-utils@2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0):
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
      eslint-import-resolver-node: 0.3.7
  /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0):
      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
      eslint-import-resolver-node: 0.3.7
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.1.6)
      array-includes: 3.1.6
      array.prototype.flat: 1.3.1
      array.prototype.flatmap: 1.3.1
      eslint-import-resolver-node: 0.3.7
      eslint-module-utils: 2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0)
      has: 1.0.3
      is-core-module: 2.12.1
      object.values: 1.1.6
      resolve: 1.22.2
      semver: 6.3.0
      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.1.6)
      array-includes: 3.1.6
      array.prototype.flat: 1.3.1
      array.prototype.flatmap: 1.3.1
      eslint-import-resolver-node: 0.3.7
      eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.7)(eslint@8.45.0)
      has: 1.0.3
      is-core-module: 2.12.1
      object.values: 1.1.6
      resolve: 1.22.2
      semver: 6.3.0
  /eslint-plugin-solid@0.12.1(eslint@8.45.0)(typescript@5.1.6):
      '@typescript-eslint/utils': 5.59.11(eslint@8.45.0)(typescript@5.1.6)
      jsx-ast-utils: 3.3.3
  /eslint-scope@7.2.0:
    resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==}
      '@babel/core': 7.22.5
      '@babel/eslint-parser': 7.22.5(@babel/core@7.22.5)(eslint@8.45.0)
  /eslint-visitor-keys@3.4.1:
    resolution: {integrity: sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==}
      '@eslint-community/regexpp': 4.6.1
      '@eslint/eslintrc': 2.1.0
      '@humanwhocodes/config-array': 0.11.10
      eslint-scope: 7.2.0
      eslint-visitor-keys: 3.4.1
      globals: 13.20.0
      eslint-visitor-keys: 3.4.1
      '@types/estree': 1.0.1
  /execa@7.1.1:
    resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==}
  /fast-content-type-parse@1.0.0:
    resolution: {integrity: sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA==}
  /fast-json-stringify@5.7.0:
    resolution: {integrity: sha512-sBVPTgnAZseLu1Qgj6lUbQ0HfjFhZWXAmpZ5AaSGkyLh5gAXBga/uPJjQPHpDFjC9adWIpdOcCLSDTgrZ7snoQ==}
  /fast-jwt@3.1.1:
    resolution: {integrity: sha512-c6gqmiMU9kUIMs0XcsnnpBMA4A+zi/XULA47r6hYoLR7s1teJ+LwviwZdttCeTZ+F5ZuHlRigNe98C4qN6h4pw==}
    engines: {node: '>=14 <22'}
  /fast-redact@3.2.0:
    resolution: {integrity: sha512-zaTadChr+NekyzallAMXATXLOR8MNx3zqpZ0MUF2aGf4EathnG0f32VLODNlY8IuGY3HoRO2L6/6fSzNsLaHIw==}
  /fastify-plugin@4.5.0:
    resolution: {integrity: sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg==}
      '@fastify/error': 3.2.1
      fast-content-type-parse: 1.0.0
      fast-json-stringify: 5.7.0
      light-my-request: 5.10.0
      pino: 8.14.1
      tiny-lru: 11.0.1
      flat-cache: 3.0.4
  /flat-cache@3.0.4:
    resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==}
    engines: {node: ^10.12.0 || >=12.0.0}
      flatted: 3.2.7
  /flatted@3.2.7:
    resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
  /follow-redirects@1.15.2:
    resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
      signal-exit: 4.0.2
  /fsevents@2.3.2:
    resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
  /function.prototype.name@1.1.5:
    resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
      has: 1.0.3
      jackspeak: 2.2.2
      minipass: 6.0.2
  /globals@13.20.0:
    resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
      define-properties: 1.2.0
  /globby@13.1.4:
    resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==}
  /graphql-request@5.2.0(graphql@16.7.1):
      '@graphql-typed-document-node/core': 3.2.0(graphql@16.7.1)
      graphql: 16.7.1
  /graphql@16.7.1:
    resolution: {integrity: sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==}
  /h3@1.7.1:
    resolution: {integrity: sha512-A9V2NEDNHet7v1gCg7CMwerSigLi0SRbhTy7C3lGb0N4YKIpPmLDjedTUopqp4dnn7COHfqUjjaz3zbtz4QduA==}
      destr: 2.0.0
      iron-webcrypto: 0.7.1
      radix3: 1.0.1
      ufo: 1.1.2
  /has@1.0.3:
    resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
    dependencies:
      function-bind: 1.1.1
      '@types/hast': 2.3.4
      '@types/unist': 2.0.6
      property-information: 6.2.0
      '@types/hast': 2.3.4
      '@types/hast': 2.3.4
      '@types/hast': 2.3.4
      '@types/unist': 2.0.6
      property-information: 6.2.0
  /hast-util-to-parse5@7.1.0:
    resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==}
      '@types/hast': 2.3.4
      property-information: 6.2.0
      web-namespaces: 2.0.1
      '@types/hast': 2.3.4
      property-information: 6.2.0
  /headers-polyfill@3.1.2:
    resolution: {integrity: sha512-tWCK4biJ6hcLqTviLXVR9DTRfYGQMXEIUj3gwJ2rZ5wO/at3XtkI4g8mCvFdUF9l1KMBNCfmNAdnahm1cgavQA==}
  /immutable@4.3.0:
    resolution: {integrity: sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==}
      has: 1.0.3
  /iron-webcrypto@0.7.1:
    resolution: {integrity: sha512-K/UmlEhPCPXEHV5hAtH5C0tI5JnFuOrv4yO/j7ODPl3HaiiHBLbOLTde+ieUaAyfCATe4LoAnclyF+hmSCOVmQ==}
      is-typed-array: 1.1.10
  /is-core-module@2.12.1:
    resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==}
    dependencies:
      has: 1.0.3
    dev: true

      has: 1.0.3
      '@types/estree': 1.0.1
  /is-typed-array@1.1.10:
    resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==}
      available-typed-arrays: 1.0.5
      call-bind: 1.0.2
      for-each: 0.3.3
      gopd: 1.0.1
      has-tostringtag: 1.0.0
  /is-wsl@3.0.0:
    resolution: {integrity: sha512-TQ7xXW/fTBaz/HhGSV779AC99ocpvb9qJPuPwyIea+F+Z+htcQ1wouAA0xEQaa4saVqyP8mwkoYp5efeM/4Gbg==}
      is-docker: 3.0.0
      node-fetch: 2.6.12
      whatwg-fetch: 3.6.17
      node-fetch: 2.6.12
  /jackspeak@2.2.2:
    resolution: {integrity: sha512-mgNtVv4vUuaKA97yxUHoA3+FkuhtxkjdXEWOyB/N76fjy0FjezEt34oy3epBtvCvS+7DyKwqCFWx/oJLV5+kCg==}
  /jiti@1.18.2:
    resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==}
    hasBin: true
    dev: true

  /jiti@1.19.3:
    resolution: {integrity: sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==}
  /joi@17.9.2:
    resolution: {integrity: sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==}
  /jsonwebtoken@9.0.1:
    resolution: {integrity: sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==}
      lodash: 4.17.21
  /jssha@3.3.0:
    resolution: {integrity: sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==}
  /jsx-ast-utils@3.3.3:
    resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==}
      array-includes: 3.1.6
  /lib0@0.2.78:
    resolution: {integrity: sha512-SV2nU43/6eaYnGH3l0lg2wg1ziB/TH3sAd2E8quXPGwrqo+aX98SNT2ZKucpUr5B8A52jD7ZMjAl+r87Fa/bLQ==}
  /light-my-request@5.10.0:
    resolution: {integrity: sha512-ZU2D9GmAcOUculTTdH9/zryej6n8TzT+fNGdNtm6SDp5MMMpHrJJkvAdE3c6d8d2chE9i+a//dS9CWZtisknqA==}
  /lru-cache@10.0.0:
    resolution: {integrity: sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==}
  /lru-cache@9.1.2:
    resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==}
    engines: {node: 14 || >=16.14}
    dev: false

  /magic-string@0.30.1:
    resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==}
    engines: {node: '>=12'}
    dependencies:
      '@jridgewell/sourcemap-codec': 1.4.15
    dev: true

  /magic-string@0.30.3:
    resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==}
  /markdown-it@13.0.1:
    resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==}
      '@types/mdast': 3.0.11
      '@types/unist': 2.0.6
      '@types/mdast': 4.0.0
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/unist': 2.0.6
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/hast': 2.3.4
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/unist': 2.0.6
      '@types/mdast': 3.0.11
      '@types/debug': 4.1.8
  /minipass@6.0.2:
    resolution: {integrity: sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==}
  /mkdist@1.2.0(typescript@5.2.2):
    resolution: {integrity: sha512-UTqu/bXmIk/+VKNVgufAeMyjUcNy1dn9Bl7wL1zZlCKVrpDgj/VllmZBeh3ZCC/2HWqUrt6frNFTKt9TRZbNvQ==}
      sass: ^1.60.0
      typescript: '>=4.9.5'
      esbuild: 0.17.19
      globby: 13.1.4
      jiti: 1.19.3
  /mlly@1.3.0:
    resolution: {integrity: sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==}
    dependencies:
      acorn: 8.10.0
      pathe: 1.1.1
      pkg-types: 1.0.3
      ufo: 1.3.0
    dev: true

      ufo: 1.3.0
  /monaco-editor@0.40.0:
    resolution: {integrity: sha512-1wymccLEuFSMBvCk/jT1YDW/GuxMLYwnFwF9CDyYCxoTw2Pt379J3FUhwy9c43j51JdcxVPjwk0jm0EVDsBS2g==}
      bson: 5.4.0
      sax: 1.2.4
      '@types/nlcst': 1.0.0
  /node-fetch@2.6.12:
    resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==}
  /node-mocks-http@1.12.2:
    resolution: {integrity: sha512-xhWwC0dh35R9rf0j3bRZXuISXdHxxtMx0ywZQBwjrg3yl7KpRETzogfeCamUIjltpn0Fxvs/ZhGJul1vPLrdJQ==}
    engines: {node: '>=0.6'}
      resolve: 1.22.4
      semver: 5.7.1
      define-properties: 1.2.0
  /object.values@1.1.6:
    resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
      '@octokit/app': 14.0.0
      '@octokit/core': 5.0.0
      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.0)
      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.0)
      '@octokit/plugin-retry': 6.0.0(@octokit/core@5.0.0)
      '@octokit/plugin-throttling': 7.0.0(@octokit/core@5.0.0)
      '@octokit/request-error': 5.0.0
      ufo: 1.3.0
  /on-exit-leak-free@2.1.0:
    resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==}
      undici: 5.22.1
      validator: 13.9.0
      '@types/node': 18.17.5
      '@types/node-fetch': 2.6.4
      node-fetch: 2.6.12
      cli-spinners: 2.9.0
      cli-spinners: 2.9.0
      cli-spinners: 2.9.0
      jssha: 3.3.0
      lru-cache: 9.1.2
      minipass: 6.0.2
  /pino-abstract-transport@1.0.0:
    resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==}
      readable-stream: 4.4.0
  /pino-std-serializers@6.2.1:
    resolution: {integrity: sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ==}
  /pino@8.14.1:
    resolution: {integrity: sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==}
      fast-redact: 3.2.0
      on-exit-leak-free: 2.1.0
      pino-abstract-transport: 1.0.0
      pino-std-serializers: 6.2.1
      sonic-boom: 3.3.0
      thread-stream: 2.3.0
      resolve: 1.22.4
  /postcss@8.4.26:
    resolution: {integrity: sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==}
    engines: {node: ^10 || ^12 || >=14}
    dependencies:
      nanoid: 3.3.6
      picocolors: 1.0.0
      source-map-js: 1.0.2
    dev: true

  /postcss@8.4.29:
    resolution: {integrity: sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==}
  /preferred-pm@3.0.3:
    resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==}
    engines: {node: '>=10'}
    dependencies:
      find-up: 5.0.0
      find-yarn-workspace-root2: 1.2.16
      path-exists: 4.0.0
      which-pm: 2.0.0
    dev: true

      '@astrojs/compiler': 1.6.2
      sass-formatter: 0.7.6
      sass-formatter: 0.7.6
  /pretty-bytes@6.1.0:
    resolution: {integrity: sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==}
  /property-information@6.2.0:
    resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==}
      prosemirror-transform: 1.7.3
      prosemirror-model: 1.19.2
      prosemirror-transform: 1.7.3
      prosemirror-transform: 1.7.3
      prosemirror-view: 1.31.4
      prosemirror-model: 1.19.2
      prosemirror-view: 1.31.4
      prosemirror-transform: 1.7.3
      prosemirror-view: 1.31.4
      prosemirror-transform: 1.7.3
  /prosemirror-markdown@1.11.0:
    resolution: {integrity: sha512-yP9mZqPRstjZhhf3yykCQNE3AijxARrHe4e7esV9A+gp4cnGOH4QvrKYPpXLHspNWyvJJ+0URH+iIvV5qP1I2Q==}
      markdown-it: 13.0.1
      prosemirror-model: 1.19.2
  /prosemirror-menu@1.2.2:
    resolution: {integrity: sha512-437HIWTq4F9cTX+kPfqZWWm+luJm95Aut/mLUy+9OMrOml0bmWDS26ceC6SNfb2/S94et1sZ186vLO7pDHzxSw==}
  /prosemirror-model@1.19.2:
    resolution: {integrity: sha512-RXl0Waiss4YtJAUY3NzKH0xkJmsZupCIccqcIFoLTIKFlKNbIvFDRl27/kQy1FP8iUAxrjRRfIVvOebnnXJgqQ==}
      prosemirror-model: 1.19.2
      prosemirror-model: 1.19.2
      prosemirror-transform: 1.7.3
      prosemirror-model: 1.19.2
      prosemirror-transform: 1.7.3
      prosemirror-view: 1.31.4
  /prosemirror-tables@1.3.3:
    resolution: {integrity: sha512-t10hbu4sNDInic3AQYd8ouPN457zVJIhVDqSdqgsVXNoa1watYXBxqNSVrNQoGOFG4Ivreyp3hQE3KG1f9bSpw==}
      prosemirror-model: 1.19.2
      prosemirror-transform: 1.7.3
      prosemirror-view: 1.31.4
  /prosemirror-trailing-node@2.0.4(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4):
    resolution: {integrity: sha512-0Yl9w7IdHkaCdqR+NE3FOucePME4OmiGcybnF1iasarEILP5U8+4xTnl53yafULjmwcg1SrSG65Hg7Zk2H2v3g==}
      prosemirror-view: ^1.30.2
      '@babel/runtime': 7.22.5
      '@remirror/core-constants': 2.0.1
      '@remirror/core-helpers': 2.0.3
      prosemirror-model: 1.19.2
      prosemirror-view: 1.31.4
    transitivePeerDependencies:
      - supports-color
  /prosemirror-transform@1.7.3:
    resolution: {integrity: sha512-qDapyx5lqYfxVeUWEw0xTGgeP2S8346QtE7DxkalsXlX89lpzkY6GZfulgfHyk1n4tf74sZ7CcXgcaCcGjsUtA==}
      prosemirror-model: 1.19.2
  /prosemirror-view@1.31.4:
    resolution: {integrity: sha512-nJzH2LpYbonSTYFqQ1BUdEhbd1WPN/rp/K9T9qxBEYpgg3jK3BvEUCR45Ymc9IHpO0m3nBJwPm19RBxZdoBVuw==}
      prosemirror-model: 1.19.2
      prosemirror-transform: 1.7.3
  /radix3@1.0.1:
    resolution: {integrity: sha512-y+AcwZ3HcUIGc9zGsNVf5+BY/LxL+z+4h4J3/pp8jxSmy1STaCocPS3qrj4tA5ehUSzqtqK+0Aygvz/r/8vy4g==}
      '@types/normalize-package-data': 2.4.1
  /readable-stream@4.4.0:
    resolution: {integrity: sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==}
      resolve: 1.22.4
  /regenerator-runtime@0.13.11:
    resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
  /regexp.prototype.flags@1.5.0:
    resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
      define-properties: 1.2.0
      functions-have-names: 1.2.3
  /rehype-parse@8.0.4:
    resolution: {integrity: sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==}
      '@types/hast': 2.3.4
      '@types/hast': 2.3.4
      '@types/hast': 2.3.4
      '@types/hast': 2.3.4
      rehype-parse: 8.0.4
      '@types/mdast': 3.0.11
      '@types/mdast': 3.0.11
      '@types/hast': 2.3.4
      '@types/mdast': 3.0.11
  /resolve@1.22.2:
    resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
    hasBin: true
      is-core-module: 2.12.1
      path-parse: 1.0.7
      supports-preserve-symlinks-flag: 1.0.0
    dev: true
  /resolve@1.22.4:
    resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==}
      '@types/nlcst': 1.0.0
      '@types/nlcst': 1.0.0
      '@types/nlcst': 1.0.0
      '@types/nlcst': 1.0.0
  /rollup-plugin-dts@5.3.0(rollup@3.26.2)(typescript@5.2.2):
    resolution: {integrity: sha512-8FXp0ZkyZj1iU5klkIJYLjIq/YZSwBoERu33QBDxm/1yw5UU4txrEtcmMkrq+ZiKu3Q4qvPCNqc3ovX6rjqzbQ==}
    engines: {node: '>=v14'}
      rollup: ^3.0.0
      magic-string: 0.30.3
      rollup: 3.26.2
  /rollup@3.26.2:
    resolution: {integrity: sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==}
      fsevents: 2.3.2

  /rollup@3.29.0:
    resolution: {integrity: sha512-nszM8DINnx1vSS+TpbWKMkxem0CDWk3cSit/WWCBVs9/JZ1I/XLwOsiUglYuYReaeWWSsW9kge5zE5NZtf/a4w==}
    engines: {node: '>=14.18.0', npm: '>=8.0.0'}
    hasBin: true
    optionalDependencies:
      fsevents: 2.3.2
    requiresBuild: true
  /sass-formatter@0.7.6:
    resolution: {integrity: sha512-hXdxU6PCkiV3XAiSnX+XLqz2ohHoEnVUlrd8LEVMAI80uB1+OTScIkH9n6qQwImZpTye1r1WG1rbGUteHNhoHg==}
      immutable: 4.3.0
  /sax@1.2.4:
    resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
  /semver@5.7.1:
    resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
  /semver@6.3.0:
    resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
    hasBin: true
    dev: true

      ansi-sequence-parser: 1.1.0
  /signal-exit@4.0.2:
    resolution: {integrity: sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==}
    engines: {node: '>=14'}
    dev: false

      joi: 17.9.2
      '@polka/url': 1.0.0-next.21
      '@types/sax': 1.2.4
      sax: 1.2.4
    dev: false

  /solid-js@1.7.8:
    resolution: {integrity: sha512-XHBWk1FvFd0JMKljko7FfhefJMTSgYEuVKcQ2a8hzRXfiuSJAGsrPPafqEo+f6l+e8Oe3cROSpIL6kbzjC1fjQ==}
    dependencies:
      csstype: 3.1.2
      seroval: 0.5.1
      '@babel/generator': 7.22.5
      '@babel/helper-module-imports': 7.22.5
      '@babel/types': 7.22.5
    dev: false

  /solid-refresh@0.5.3(solid-js@1.7.8):
    resolution: {integrity: sha512-Otg5it5sjOdZbQZJnvo99TEBAr6J7PQ5AubZLNU6szZzg3RQQ5MX04oteBIIGDs0y2Qv8aXKm9e44V8z+UnFdw==}
    peerDependencies:
      solid-js: ^1.3
    dependencies:
      '@babel/generator': 7.22.5
      '@babel/helper-module-imports': 7.22.5
      '@babel/types': 7.22.5
      solid-js: 1.7.8
    dev: true
  /sonic-boom@3.3.0:
    resolution: {integrity: sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==}
    dev: true
      spdx-license-ids: 3.0.13
      spdx-license-ids: 3.0.13
  /spdx-license-ids@3.0.13:
    resolution: {integrity: sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==}
  /streamsearch@1.1.0:
    resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
    engines: {node: '>=10.0.0'}

  /string.prototype.trim@1.2.7:
    resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
  /string.prototype.trimend@1.0.6:
    resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
  /string.prototype.trimstart@1.0.6:
    resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==}
      define-properties: 1.2.0
      es-abstract: 1.21.2
      '@pkgr/utils': 2.4.1
      tslib: 2.5.3
      resolve: 1.22.4
      '@jridgewell/source-map': 0.3.3
    dev: true
  /thread-stream@2.3.0:
    resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==}
  /tiny-lru@11.0.1:
    resolution: {integrity: sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==}
      h3: 1.7.1
      node-mocks-http: 1.12.2
  /trpc-openapi@1.2.0(@trpc/server@10.35.0)(zod@3.22.2):
      h3: 1.7.1
      node-mocks-http: 1.12.2
      zod: 3.22.2
      zod-to-json-schema: 3.21.4(zod@3.22.2)
  /ts-api-utils@1.0.1(typescript@5.1.6):
    resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==}
      typescript: 5.1.6
  /tsconfck@2.1.2(typescript@5.1.6):
      typescript: 5.1.6
      '@types/resolve': 1.20.2
      resolve: 1.22.4
  /tslib@2.5.3:
    resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==}
  /tsutils@3.21.0(typescript@5.1.6):
      typescript: 5.1.6
      is-typed-array: 1.1.10
  /typescript@5.1.6:
    resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==}
    engines: {node: '>=14.17'}
    hasBin: true

  /ufo@1.1.2:
    resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
    dev: false

  /ufo@1.3.0:
    resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==}
      '@rollup/plugin-alias': 5.0.0(rollup@3.26.2)
      '@rollup/plugin-commonjs': 24.1.0(rollup@3.26.2)
      '@rollup/plugin-json': 6.0.0(rollup@3.26.2)
      '@rollup/plugin-node-resolve': 15.1.0(rollup@3.26.2)
      '@rollup/plugin-replace': 5.0.2(rollup@3.26.2)
      '@rollup/pluginutils': 5.0.2(rollup@3.26.2)
      globby: 13.1.4
      jiti: 1.18.2
      magic-string: 0.30.1
      mkdist: 1.2.0(typescript@5.2.2)
      mlly: 1.3.0
      pretty-bytes: 6.1.0
      rollup: 3.26.2
      rollup-plugin-dts: 5.3.0(rollup@3.26.2)(typescript@5.2.2)
      untyped: 1.3.2
  /unconfig@0.3.10:
    resolution: {integrity: sha512-tj317lhIq2iZF/NXrJnU1t2UaGUKKz1eL1sK2t63Oq66V9BxqvZV12m55fp/fpQJ+DDmVlLgo7cnLVOZkhlO/A==}
      jiti: 1.19.3
  /undici@5.22.1:
    resolution: {integrity: sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==}
      busboy: 1.6.0
    dev: false
  /undici@5.23.0:
    resolution: {integrity: sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==}
    engines: {node: '>=14.0'}
      busboy: 1.6.0
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/jsonwebtoken': 9.0.2
      jsonwebtoken: 9.0.1
  /unocss@0.55.7(postcss@8.4.29)(vite@4.4.7):
    resolution: {integrity: sha512-3W9P7vj2EhSk/4oPCHBS0VgrwSf5zZL6Az1/XARVOpBnRJtCM2szFInYxHkMgt9pkZTsW8SFCuk/g+QIJ6A8tg==}
    engines: {node: '>=14'}
    peerDependencies:
      '@unocss/webpack': 0.55.7
      vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0
    peerDependenciesMeta:
      '@unocss/webpack':
        optional: true
      vite:
        optional: true
    dependencies:
      '@unocss/astro': 0.55.7(vite@4.4.7)
      '@unocss/cli': 0.55.7
      '@unocss/core': 0.55.7
      '@unocss/extractor-arbitrary-variants': 0.55.7
      '@unocss/postcss': 0.55.7(postcss@8.4.29)
      '@unocss/preset-attributify': 0.55.7
      '@unocss/preset-icons': 0.55.7
      '@unocss/preset-mini': 0.55.7
      '@unocss/preset-tagify': 0.55.7
      '@unocss/preset-typography': 0.55.7
      '@unocss/preset-uno': 0.55.7
      '@unocss/preset-web-fonts': 0.55.7
      '@unocss/preset-wind': 0.55.7
      '@unocss/reset': 0.55.7
      '@unocss/transformer-attributify-jsx': 0.55.7
      '@unocss/transformer-attributify-jsx-babel': 0.55.7
      '@unocss/transformer-compile-class': 0.55.7
      '@unocss/transformer-directives': 0.55.7
      '@unocss/transformer-variant-group': 0.55.7
      '@unocss/vite': 0.55.7(vite@4.4.7)
      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
    transitivePeerDependencies:
      - postcss
      - rollup
      - supports-color
    dev: true

  /unocss@0.55.7(postcss@8.4.29)(vite@4.4.9):
      '@unocss/postcss': 0.55.7(postcss@8.4.29)
      vite: 4.4.9(sass@1.64.1)
    dev: false
  /untyped@1.3.2:
    resolution: {integrity: sha512-z219Z65rOGD6jXIvIhpZFfwWdqQckB8sdZec2NO+TkcH1Bph7gL0hwLzRJs1KsOo4Jz4mF9guBXhsEnyEBGVfw==}
      '@babel/core': 7.22.5
      '@babel/standalone': 7.22.5
      '@babel/types': 7.22.15
      jiti: 1.19.3
  /update-browserslist-db@1.0.11(browserslist@4.21.10):
    resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
      browserslist: 4.21.10
  /uuid@9.0.0:
    resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==}
  /validator@13.9.0:
    resolution: {integrity: sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==}
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@types/unist': 2.0.6
      '@babel/core': 7.22.5
      '@babel/preset-typescript': 7.22.5(@babel/core@7.22.5)
      '@types/babel__core': 7.20.1
      babel-preset-solid: 1.7.4(@babel/core@7.22.5)
      vite: 4.4.9(sass@1.64.1)
    dev: false

  /vite-plugin-solid@2.7.0(solid-js@1.7.8)(vite@4.4.7):
    resolution: {integrity: sha512-avp/Jl5zOp/Itfo67xtDB2O61U7idviaIp4mLsjhCa13PjKNasz+IID0jYTyqUp9SFx6/PmBr6v4KgDppqompg==}
    peerDependencies:
      solid-js: ^1.7.2
      vite: ^3.0.0 || ^4.0.0
    dependencies:
      '@babel/core': 7.22.5
      '@babel/preset-typescript': 7.22.5(@babel/core@7.22.5)
      '@types/babel__core': 7.20.1
      babel-preset-solid: 1.7.4(@babel/core@7.22.5)
      merge-anything: 5.1.7
      solid-js: 1.7.8
      solid-refresh: 0.5.3(solid-js@1.7.8)
      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
      vitefu: 0.2.4(vite@4.4.7)
    transitivePeerDependencies:
      - supports-color
    dev: true
  /vite-tsconfig-paths@4.2.0(typescript@5.1.6)(vite@4.4.7):
      tsconfck: 2.1.2(typescript@5.1.6)
      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
  /vite@4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2):
    resolution: {integrity: sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==}
      postcss: 8.4.26
      rollup: 3.26.2
      fsevents: 2.3.2
    dev: true

  /vite@4.4.9(sass@1.64.1):
    resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==}
    engines: {node: ^14.18.0 || >=16.0.0}
    hasBin: true
    peerDependencies:
      '@types/node': '>= 14'
      less: '*'
      lightningcss: ^1.21.0
      sass: '*'
      stylus: '*'
      sugarss: '*'
      terser: ^5.4.0
    peerDependenciesMeta:
      '@types/node':
        optional: true
      less:
        optional: true
      lightningcss:
        optional: true
      sass:
        optional: true
      stylus:
        optional: true
      sugarss:
        optional: true
      terser:
        optional: true
    dependencies:
      esbuild: 0.18.16
      postcss: 8.4.29
      rollup: 3.29.0
      sass: 1.64.1
    optionalDependencies:
      fsevents: 2.3.2

  /vitefu@0.2.4(vite@4.4.7):
    resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==}
    peerDependencies:
      vite: ^3.0.0 || ^4.0.0
    peerDependenciesMeta:
      vite:
        optional: true
    dependencies:
      vite: 4.4.7(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
    dev: true
      vite: 4.4.9(sass@1.64.1)
  /vscode-css-languageservice@6.2.6:
    resolution: {integrity: sha512-SA2WkeOecIpUiEbZnjOsP/fI5CRITZEiQGSHXKiDQDwLApfKcnLhZwMtOBbIifSzESVcQa7b/shX/nbnF4NoCg==}
      '@vscode/l10n': 0.0.14
      vscode-languageserver-textdocument: 1.0.8
      vscode-uri: 3.0.7
  /vscode-html-languageservice@5.0.6:
    resolution: {integrity: sha512-gCixNg6fjPO7+kwSMBAVXcwDRHdjz1WOyNfI0n5Wx0J7dfHG8ggb3zD1FI8E2daTZrwS1cooOiSoc1Xxph4qRQ==}
      '@vscode/l10n': 0.0.14
      vscode-languageserver-textdocument: 1.0.8
      vscode-languageserver-types: 3.17.3
      vscode-uri: 3.0.7
  /vscode-languageserver-textdocument@1.0.8:
    resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==}
  /vscode-uri@3.0.7:
    resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==}
  /weaviate-ts-client@1.4.0(graphql@16.7.1):
      graphql-request: 5.2.0(graphql@16.7.1)
      uuid: 9.0.0
  /whatwg-fetch@3.6.17:
    resolution: {integrity: sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ==}
  /which-typed-array@1.1.9:
    resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==}
      is-typed-array: 1.1.10
  /ws@8.13.0:
    resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
  /y-prosemirror@1.0.20(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7):
      lib0: 0.2.78
      prosemirror-model: 1.19.2
      prosemirror-view: 1.31.4
  /y-prosemirror@1.2.1(prosemirror-model@1.19.2)(prosemirror-state@1.4.3)(prosemirror-view@1.31.4)(y-protocols@1.0.5)(yjs@13.6.7):
      lib0: 0.2.78
      prosemirror-model: 1.19.2
      prosemirror-view: 1.31.4
      lib0: 0.2.78
      lib0: 0.2.78
  /zod-to-json-schema@3.21.4(zod@3.22.2):
      zod: 3.22.2
  /zod@3.22.2:
    resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==}
Fixed code: docker.env
import corsPlugin, { OriginFunction } from "@fastify/cors";
  const originCallback: OriginFunction = (origin, callback) => {
    if (!origin || origin === "null") {
      callback(null, true);

      return;
    }

    const { hostname } = new URL(origin);
    const appHostname = new URL(fastify.config.PUBLIC_APP_URL).hostname;

    if (
      hostname === "localhost" ||
      hostname.endsWith(appHostname) ||
      (fastify.config.VRITE_CLOUD && hostname.endsWith("swagger.io"))
    ) {
      callback(null, true);

      return;
    }

    callback(new Error("Not allowed"), false);
  };

    origin: true,
    methods: ["GET", "DELETE", "PUT", "POST"]
  const server = await createServer({
    database: true,
    pubSub: true,
    auth: true,
    email: true,
    gitSync: true,
    search: true
  });
        version: "0.3.0"
import { errors, publicPlugin, trpcPlugin, processAuth } from "@vrite/backend";
    return reply.header("X-Frame-Options", "SAMEORIGIN").view("index.html", {
  const server = await createServer({
    database: true,
    pubSub: true,
    auth: true,
    email: true,
    gitSync: true,
    search: true,
    storage: true
  });
    reply.header(
      "Access-Control-Allow-Origin",
      fastify.config.NODE_ENV === "development" ? "*" : fastify.config.PUBLIC_APP_URL
    );
import { assetsService } from "./assets";
  const server = await createServer({
    storage: true
  });
  jsonToBuffer,
  publishGitDataEvent
import { ObjectId } from "mongodb";
    publishGitDataEvent({ fastify: this.fastify }, `${details.context.workspaceId}`, {
import { docToBuffer, getContentPiecesCollection } from "@vrite/backend";
import { ObjectId } from "mongodb";
  const server = await createServer({
    database: true,
    auth: true,
    pubSub: true,
    search: true
  });
import {
  publicPlugin,
  getContentsCollection,
  getContentVariantsCollection,
  errors,
  SessionData
} from "@vrite/backend";
        throw errors.unauthorized();
        throw errors.unauthorized();
    "@prettier/sync": "^0.3.0",
    "@types/hast": "^3.0.1",
    "@types/html-to-text": "^9.0.1",
    "@types/js-yaml": "^4.0.6",
    "@types/mdast": "^4.0.1",
    "dayjs": "^1.11.9",
    "hast-util-to-html": "^9.0.0",
    "html-to-text": "^9.0.5",
    "js-yaml": "^4.1.0",
    "mdast-util-from-markdown": "^2.0.0",
    "mdast-util-frontmatter": "^2.0.1",
    "mdast-util-gfm": "^3.0.0",
    "mdast-util-mdx": "^3.0.0",
    "mdast-util-to-hast": "^13.0.2",
    "micromark-extension-frontmatter": "^2.0.0",
    "micromark-extension-gfm": "^3.0.0",
    "micromark-extension-mdxjs": "^2.0.0",
    "prettier": "^3.0.2",
    "remark": "^15.0.1",
    "remark-mdx": "^2.3.0",
    "remark-parse": "^11.0.0",
    "trpc-openapi": "^1.2.0",
    "unist-util-visit": "^5.0.0"
import { publicPlugin, createFastifyContext } from "@vrite/backend";
import corsPlugin from "@fastify/cors";
    credentials: true,
      return createFastifyContext({ req, res }, fastify);
import { createServer } from "@vrite/backend";
  const server = await createServer({});
      JSONContentNode["listItem" | "blockquote" | "doc" | "element"]
          case "element":
              child as JSONContentNodeWalker<JSONContentNode["element"]>
      JSONContentNode["listItem" | "blockquote" | "doc" | "element"]
          case "element":
              child as JSONContentNodeWalker<JSONContentNode["element"]>
import { mdxRouter } from "./mdx";
  gpt: gptRouter,
  mdx: mdxRouter
import { mdxAsyncInputTransformer } from "./input-transformer";
import { mdxAsyncOutputTransformer } from "./output-transformer";
import { procedure, router, z } from "@vrite/backend";
import { InputTransformer } from "@vrite/sdk/transformers";

const basePath = "/mdx";
const mdxRouter = router({
  input: procedure
    .meta({
      openapi: {
        method: "POST",
        path: `${basePath}/input`
      }
    })
    .input(z.object({ data: z.array(z.string()) }))
    .output(
      z.array(
        z.object({
          content: z.string(),
          contentPiece: z.any()
        })
      )
    )
    .mutation(async ({ input }) => {
      const output: Array<ReturnType<InputTransformer>> = [];

      for await (const content of input.data) {
        output.push(await mdxAsyncInputTransformer(content));
      }

      return output;
    }),
  output: procedure
    .meta({
      openapi: {
        method: "POST",
        path: `${basePath}/output`
      }
    })
    .input(
      z.object({
        data: z.array(
          z.object({
            content: z.any(),
            metadata: z.any()
          })
        )
      })
    )
    .output(z.array(z.string()))
    .mutation(async ({ ctx, input }) => {
      const output: string[] = [];

      for await (const { content, metadata } of input.data) {
        output.push(await mdxAsyncOutputTransformer(content, metadata));
      }

      return output;
    })
});

export { mdxRouter };
import { InputTransformer } from "@vrite/sdk/transformers";
import { mdxjs } from "micromark-extension-mdxjs";
import { fromMarkdown } from "mdast-util-from-markdown";
import { MdxJsxAttribute, MdxJsxExpressionAttribute, mdxFromMarkdown } from "mdast-util-mdx";
import { frontmatter } from "micromark-extension-frontmatter";
import { frontmatterFromMarkdown } from "mdast-util-frontmatter";
import { gfmFromMarkdown } from "mdast-util-gfm";
import { gfm } from "micromark-extension-gfm";
import { toHtml } from "hast-util-to-html";
import { toHast, defaultHandlers } from "mdast-util-to-hast";
import babelPlugin from "prettier/plugins/babel";
import estreePlugin from "prettier/plugins/estree";
import { format } from "prettier/standalone";
import { load } from "js-yaml";
import dayjs from "dayjs";
import type { Plugin } from "prettier";
import type { RootContentMap } from "mdast";
import type { Element, Text } from "hast";

const attributeProcessingPromises: Array<Promise<any>> = [];
const processAttribute = async (value: string): Promise<any> => {
  try {
    const processedValue = await format(value, {
      parser: "json-stringify",
      plugins: [babelPlugin, estreePlugin as Plugin]
    });

    return JSON.parse(processedValue);
  } catch (error) {
    try {
      return JSON.parse(value);
    } catch (error) {
      return value;
    }
  }
};
const attributesToJSON = async (
  attributes: Array<MdxJsxAttribute | MdxJsxExpressionAttribute>
): Promise<Record<string, any>> => {
  const output: Record<string, any> = {};

  for await (const attribute of attributes) {
    if (attribute.type === "mdxJsxAttribute") {
      if (typeof attribute.value === "string") {
        output[attribute.name] = attribute.value;
      } else if (attribute.value === null) {
        output[attribute.name] = true;
      } else if (attribute.value?.value) {
        const value = await processAttribute(attribute.value.value);

        output[attribute.name] = value;
      }
    }
  }

  return output;
};
const mdxAsyncInputTransformer = async (input: string): Promise<ReturnType<InputTransformer>> => {
  const mdast = fromMarkdown(input, {
    extensions: [gfm(), frontmatter(), mdxjs()],
    mdastExtensions: [gfmFromMarkdown(), frontmatterFromMarkdown(), mdxFromMarkdown()]
  });
  const hast = toHast(mdast, {
    handlers: {
      mdxjsEsm(state, node: RootContentMap["mdxjsEsm"]) {
        const result: Element = {
          tagName: "div",
          type: "element",
          properties: {
            "data-element": "true",
            "data-type": "Import"
          },
          children: state.all({
            children: [{ type: "code", lang: "mdx", value: node.value.trim() }],
            type: "root"
          })
        };

        state.patch(node, result);

        return state.applyData(node, result);
      },
      paragraph(state, node: RootContentMap["paragraph"]) {
        if (node.children.length === 1 && node.children[0].type === "image") {
          return defaultHandlers.image(state, node.children[0]);
        } else if (node.children.length === 1 && node.children[0].type === "mdxJsxTextElement") {
          return state.all({ type: "root", children: [node.children[0]] })[0];
        }

        return defaultHandlers.paragraph(state, node);
      },
      code(state, node: RootContentMap["code"]) {
        const result = defaultHandlers.code(state, { ...node, value: node.value.trim() });
        const meta: string[] = [];

        let title = "";

        (node.meta || "").split(" ").forEach((item) => {
          if (item.startsWith("title=")) {
            const match = item.match(/title="(.+?)"/);

            if (match) {
              title = match[1] || title;
            }
          } else {
            meta.push(item);
          }
        });

        const codeElement = result.children[0] as Element;
        const textElement = codeElement.children[0] as Text;

        result.properties["data-title"] = title;
        result.properties["data-meta"] = meta.join(" ");
        textElement.value = textElement.value.trim();

        return result;
      },
      list(state, node: RootContentMap["list"]) {
        const result = defaultHandlers.list(state, node);
        const className = `${result.properties.className || ""}`;

        if (className.includes("contains-task-list")) {
          result.properties.className = className.replace("contains-task-list", "").trim();
          if (!result.properties.className) delete result.properties.className;

          result.properties["data-type"] = "taskList";
        }

        return result;
      },
      mdxFlowExpression() {
        return undefined;
      },
      mdxJsxTextElement(state, node: RootContentMap["mdxJsxTextElement"], parent) {
        if (parent?.children.length === 1) {
          return state.all({
            type: "root",
            children: [
              {
                type: "mdxJsxFlowElement",
                name: node.name,
                attributes: node.attributes,
                children: [{ type: "paragraph", children: node.children }]
              }
            ]
          })[0];
        }

        return undefined;
      },
      mdxTextExpression() {
        return undefined;
      },
      mdxJsxFlowElement(state, node: RootContentMap["mdxJsxFlowElement"]) {
        const result: Element = {
          tagName: "div",
          type: "element",
          properties: {
            "data-element": "true",
            "data-type": node.name
          },
          children: state.all(node)
        };
        const promise = attributesToJSON(node.attributes).then((attributes) => {
          result.properties["data-props"] = JSON.stringify(attributes);
        });

        attributeProcessingPromises.push(promise);
        state.patch(node, result);

        return state.applyData(node, result);
      }
    }
  });
  const frontmatterYAML = mdast.children.find(
    (child) => child.type === "yaml"
  ) as RootContentMap["yaml"];
  const { canonicalLink, coverUrl, description, date, slug, title, ...customData } = (
    frontmatterYAML ? load(frontmatterYAML.value) : {}
  ) as Record<string, any>;

  await Promise.all(attributeProcessingPromises);

  const content = toHtml(hast);

  return {
    content,
    contentPiece: {
      ...(canonicalLink && { canonicalLink }),
      ...(coverUrl && { coverUrl }),
      ...(description && { description: `<p>${description}</p>` }),
      ...(date && { date: dayjs(date).toISOString() }),
      ...(slug && { slug }),
      ...(title && { title }),
      customData
    }
  };
};

export { mdxAsyncInputTransformer };
/* eslint-disable no-use-before-define */
import {
  createContentWalker,
  JSONContentNodeWalker,
  JSONContentNode,
  GenericJSONContentNode
} from "@vrite/sdk/transformers";
import { format } from "prettier/standalone";
import babelPlugin from "prettier/plugins/babel";
import estreePlugin from "prettier/plugins/estree";
import markdownPlugin from "prettier/plugins/markdown";
import { ContentPiece } from "@vrite/sdk/api";
import { convert as convertToText } from "html-to-text";
import { dump } from "js-yaml";
import dayjs from "dayjs";
import type { Plugin } from "prettier";

const processCode = async (code: string, hasContent?: boolean): Promise<string> => {
  const codeTagClosed = code?.trim().replace(/>$/, "/>") || "";
  const formattedCode = await format(codeTagClosed, {
    parser: "babel-ts",
    plugins: [babelPlugin, estreePlugin as Plugin],
    printWidth: 60,
    trailingComma: "none",
    singleQuote: false
  });

  return formattedCode.replace(/ *?\/>;/gm, hasContent ? ">" : "/>").trim();
};
const mdxAsyncOutputTransformer = async (
  contentNode: GenericJSONContentNode,
  contentPiece?: Pick<
    ContentPiece<Record<string, any>>,
    | "date"
    | "title"
    | "description"
    | "tags"
    | "members"
    | "slug"
    | "filename"
    | "coverUrl"
    | "coverAlt"
    | "customData"
    | "canonicalLink"
    | "coverWidth"
  >
): Promise<string> => {
  const contentWalker = createContentWalker(contentNode);
  const transformText = (textWalker: JSONContentNodeWalker<JSONContentNode["text"]>): string => {
    let output = "";

    if (textWalker.node.type === "text") {
      output = textWalker.node.text;
      textWalker.node.marks?.forEach((mark) => {
        switch (mark.type) {
          case "link":
            output = `[${output}](${mark.attrs.href})`;
            break;
          case "bold":
            output = `**${output}**`;
            break;
          case "code":
            output = `\`${output}\``;
            break;
          case "italic":
            output = `_${output}_`;
            break;
          case "strike":
            output = `~~${output}~~`;
            break;
          default:
            break;
        }
      });
    }

    return output;
  };
  const transformTextNode = (
    paragraphWalker: JSONContentNodeWalker<JSONContentNode["paragraph" | "heading" | "codeBlock"]>
  ): string => {
    return `${paragraphWalker.children
      .map((child) => {
        if (child.node.type === "text") {
          return transformText(child as JSONContentNodeWalker<JSONContentNode["text"]>);
        }

        return "\n";
      })
      .join("")}`;
  };
  const transformTable = (tableWalker: JSONContentNodeWalker<JSONContentNode["table"]>): string => {
    let output = "";

    tableWalker.children.forEach((tableRowWalker, rowIndex) => {
      let isHeader = false;

      const columns = tableRowWalker.children.map((tableCellWalker) => {
        if (tableCellWalker.node.type === "tableHeader") {
          isHeader = true;
        }

        return tableCellWalker.children.map(transformTextNode).join("\n");
      });

      if (rowIndex === tableWalker.children.length - 1) {
        output += `| ${columns.map((row) => row.replace(/\n/g, " ")).join(" | ")} |`;
      } else {
        output += `| ${columns.map((row) => row.replace(/\n/g, " ")).join(" | ")} |\n`;
      }

      if (isHeader && rowIndex === 0) {
        output += `| ${columns.map(() => "---").join(" | ")} |\n`;
      }
    });

    return output;
  };
  const transformCodeBlock = (
    codeBlockWalker: JSONContentNodeWalker<JSONContentNode["codeBlock"]>
  ): string => {
    const attrs = codeBlockWalker.node.attrs || {};

    let openingTag = `${attrs?.lang || ""}`;

    if (attrs?.title) {
      openingTag += ` title="${attrs.title}"`;
    }

    if (attrs?.meta) {
      openingTag += ` ${attrs.meta}`;
    }

    return `\`\`\`${openingTag}\n${transformTextNode(codeBlockWalker)}\n\`\`\``;
  };
  const transformElement = async (
    elementWalker: JSONContentNodeWalker<JSONContentNode["element"]>
  ): Promise<string> => {
    const { attrs } = elementWalker.node;

    if (attrs.type === "Import" && elementWalker.children[0]?.node?.type === "codeBlock") {
      return `${transformTextNode(
        elementWalker.children[0] as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
      ).trim()}`;
    }

    const keyValueProps = Object.entries(attrs.props).map(([key, value]) => {
      if (value === true) return key;

      const useBrackets = typeof value !== "string" || value.includes("\n") || value.includes(`"`);

      return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${useBrackets ? "}" : ""}`;
    });
    const openingTag = await processCode(
      `<${attrs.type}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`,
      elementWalker.children.length > 0
    );

    if (elementWalker.children.length > 0) {
      return `${openingTag}\n${(
        await transformContentNode(
          elementWalker as JSONContentNodeWalker<JSONContentNode["element"]>
        )
      )
        .split("\n")
        .map((line) => `  ${line}`)
        .join("\n")}\n</${attrs.type}>`;
    }

    return openingTag;
  };
  const transformContentNode = async (
    nodeWalker: JSONContentNodeWalker<
      JSONContentNode["listItem" | "taskItem" | "blockquote" | "doc" | "element"]
    >
  ): Promise<string> => {
    const output: string[] = [];

    for await (const child of nodeWalker.children) {
      const processChildNode = async (): Promise<string> => {
        const nodeType = child.node.type;
        const previousSibling = child.previousSibling();
        const isPreviousSiblingList = ["bulletList", "orderedList", "taskList"].includes(
          previousSibling?.node.type || ""
        );

        switch (nodeType) {
          case "paragraph":
            return `\n${transformTextNode(
              child as JSONContentNodeWalker<JSONContentNode["paragraph"]>
            )}\n`;
          case "bulletList":
          case "orderedList":
          case "taskList":
            return `${isPreviousSiblingList ? "\n" : ""}${await transformList(
              child as JSONContentNodeWalker<
                JSONContentNode["bulletList" | "orderedList" | "taskList"]
              >
            )}\n`;
          case "table":
            return `\n${transformTable(
              child as JSONContentNodeWalker<JSONContentNode["table"]>
            )}\n`;
          case "horizontalRule":
            return "\n---\n";
          case "image":
            return `\n![${child.node.attrs?.alt || ""}](${child.node.attrs?.src || ""})\n`;
          case "heading":
            return `\n${"#".repeat(child.node.attrs?.level || 1)} ${transformTextNode(
              child as JSONContentNodeWalker<JSONContentNode["heading"]>
            )}\n`;
          case "codeBlock":
            return `\n${transformCodeBlock(
              child as JSONContentNodeWalker<JSONContentNode["codeBlock"]>
            )}\n`;
          case "element":
            return `${child.node.attrs.type === "Import" ? "" : "\n"}${await transformElement(
              child as JSONContentNodeWalker<JSONContentNode["element"]>
            )}\n`;
          case "blockquote":
            return `\n${(
              await transformContentNode(
                child as JSONContentNodeWalker<JSONContentNode["blockquote"]>
              )
            )
              .split("\n")
              .map((line) => `> ${line}`)
              .join("\n")}\n`;
          default:
            return "";
        }
      };

      output.push(await processChildNode());
    }

    return output.join("").trim();
  };
  const transformList = async (
    listWalker: JSONContentNodeWalker<JSONContentNode["bulletList" | "orderedList" | "taskList"]>
  ): Promise<string> => {
    const listItems: Array<{ content: string; node: JSONContentNode["listItem" | "taskItem"] }> =
      [];

    for await (const nodeWalker of listWalker.children) {
      listItems.push({
        content: await transformContentNode(nodeWalker),
        node: nodeWalker.node
      });
    }

    return listItems
      .map(({ content, node }, index) => {
        let prefix = "";
        let indent = 0;

        if (listWalker.node.type === "taskList" && node.type === "taskItem") {
          prefix = `${node.attrs?.checked ? "- [x] " : "- [ ] "} `;
          indent = 2;
        }

        if (listWalker.node.type === "orderedList") {
          const start = listWalker.node.attrs?.start || 1;

          prefix = `${start + index}. `;
          indent = prefix.length;
        }

        if (listWalker.node.type === "bulletList") {
          prefix = "- ";
          indent = prefix.length;
        }

        return content
          .split("\n")
          .map((line, lineIndex) => {
            if (lineIndex === 0) {
              return `${prefix}${line}`;
            }

            return `${" ".repeat(indent)}${line}`;
          })
          .join("\n");
      })
      .join("\n");
  };
  const content = await transformContentNode(
    contentWalker as JSONContentNodeWalker<JSONContentNode["doc"]>
  );
  const frontmatter = dump(
    {
      ...(contentPiece?.canonicalLink && { canonicalLink: contentPiece.canonicalLink }),
      ...(contentPiece?.coverUrl && { coverUrl: contentPiece.coverUrl }),
      ...(contentPiece?.description && {
        description: convertToText(contentPiece.description, { wordwrap: false })
      }),
      ...(contentPiece?.date && { date: dayjs(contentPiece.date).format("YYYY-MM-DD") }),
      ...(contentPiece?.slug && { slug: contentPiece.slug }),
      ...(contentPiece?.title && { title: contentPiece.title }),
      ...(contentPiece?.customData || {})
    },
    { skipInvalid: true, forceQuotes: true, quotingType: '"' }
  );

  return (
    await format(
      `${frontmatter ? "---" : ""}\n${frontmatter.trim()}\n${
        frontmatter ? "---" : ""
      }\n\n${content.trim()}`,
      { plugins: [markdownPlugin], parser: "mdx" }
    )
  ).trim();
};

export { mdxAsyncOutputTransformer };
      JSONContentNode["listItem" | "blockquote" | "doc" | "element"]
          case "element":
              child as JSONContentNodeWalker<JSONContentNode["element"]>
declare module 'astro:content' {
	interface Render {
		'.mdx': Promise<{
			Content: import('astro').MarkdownInstance<{}>['Content'];
			headings: import('astro').MarkdownHeading[];
			remarkPluginFrontmatter: Record<string, any>;
		}>;
	}
}

  slug: "javascript-sdk/introduction";
  data: InferEntrySchema<"docs">
  data: InferEntrySchema<"docs">
  data: InferEntrySchema<"docs">
  data: InferEntrySchema<"docs">
  slug: "/usage-guide/content-editor";
  data: InferEntrySchema<"docs">
  slug: "/usage-guide/getting-started";
  data: InferEntrySchema<"docs">
  slug: "/usage-guide/kanban-dashboard";
  data: InferEntrySchema<"docs">
  slug: "/usage-guide/metadata";
  data: InferEntrySchema<"docs">
  slug: "/usage-guide/publishing";
  data: InferEntrySchema<"docs">
  slug: "/usage-guide/vrite-extensions";
  data: InferEntrySchema<"docs">
};
"recipes": {
"test.mdx": {
	id: "test.mdx";
  slug: "/recipes/content-pieces";
  body: string;
  collection: "recipes";
  data: InferEntrySchema<"recipes">
} & { render(): Render[".mdx"] };
import mdx from "@astrojs/mdx";
import autoImport from "astro-auto-import";
    autoImport({
      imports: [{ "#components/content": ["Card", "CardGrid", "Warning", "Info"] }]
    }),
    }),
    mdx()
    "@astrojs/mdx": "^1.1.1",
    "@solid-primitives/scheduled": "^1.4.0",
    "@vrite/sdk": "workspace:*",
    "astro-auto-import": "^0.3.1",
    "astro-icon": "^0.8.1",
    "seamless-scroll-polyfill": "^2.3.4",
    "tinykeys": "^2.1.0",
    "url-slug": "^4.0.1",
---
import clsx from "clsx";
interface Props {
  cols?: 2 | 3 | 4;
}

const { props } = Astro;
---

<div
  class={clsx("grid grid-reset-margin gap-2 my-4", {
    "sm:grid-cols-2": !props.cols || props.cols === 2,
    "sm:grid-cols-3": props.cols === 3,
    "sm:grid-cols-4": props.cols === 4
  })}
>
  <slot />
</div>
---
import { Card as BaseCard, Heading, IconButton } from "#components/primitives";
import { Icon } from "astro-icon";
import clsx from "clsx";

interface Props {
  icon: string;
  label: string;
  gradient?: boolean;
  link: string;
}

const { props } = Astro;
---

<a href={props.link} class="not-prose cursor-pointer block my-4"
  ><BaseCard
    class={clsx(
      "w-full flex flex-col m-0 p-0 gap-2 items-start h-full",
      props.gradient ? "hover:bg-gradient-to-bl" : "!hover:bg-gray-200"
    )}
    color={props.gradient ? "primary" : "contrast"}
  >
    <div class="flex justify-center items-center pl-3 pr-4 pt-3 w-full">
      <div class="pr-1 py-1">
        <Icon
          name={props.icon}
          class={clsx("h-6 w-6", props.gradient ? "fill-current" : "fill-[url(#gradient)]")}
        />
      </div>
      <Heading level={2} class="pl-1 flex-1">
        {props.label}
      </Heading>
    </div>
    <div
      class={clsx(
        "flex flex-col justify-center items-start gap-2 w-full px-4 pb-4",
        props.gradient ? "" : "text-gray-500 dark:text-gray-400"
      )}
    >
      <slot />
    </div>
  </BaseCard></a
>
export { default as Card } from "./card.astro";
export { default as CardGrid } from "./card-grid.astro";
export { default as Warning } from "./warning.astro";
export { default as Info } from "./info.astro";
---
import { Card, Icon } from "#components/primitives";
import { mdiInformationSlabCircleOutline } from "@mdi/js";
---

<Card class="flex items-center justify-start mx-0 my-4" color="contrast">
  <Icon path={mdiInformationSlabCircleOutline} class="w-6 h-6 mr-2 fill-[url(#gradient)]" />
  <div class="flex-1 not-prose"><slot /></div>
</Card>
---
import { Card, Icon } from "#components/primitives";
import { mdiAlertCircleOutline } from "@mdi/js";
---

<Card class="flex items-center justify-start m-0 my-4" color="primary">
  <Icon path={mdiAlertCircleOutline} class="w-6 h-6 mr-2" />
  <div class="flex-1 not-prose"><slot /></div>
</Card>
interface FooterProps {
  nextEntry?: { label: string; link: string } | null;
  previousEntry?: { label: string; link: string } | null;
const Footer: Component<FooterProps> = (props) => {
            text="soft"
            text="soft"
export { Footer };
import { SearchPaletteProvider, useSearchPalette } from "./search-palette";
import { mdiAppleKeyboardCommand, mdiGithub, mdiMagnify } from "@mdi/js";
import { For, type Component, Show } from "solid-js";
import clsx from "clsx";
import { Button, Icon, IconButton, Tooltip } from "#components/primitives";
import { discordIcon, logoIcon } from "#assets/icons";
const externalLinks = [
  {
    label: "GitHub",
    icon: mdiGithub,
    href: "https://github.com/vriteio/vrite"
  },
  {
    label: "Discord",
    icon: discordIcon,
    href: "https://discord.gg/yYqDWyKnqE"
  }
];
  const { opened, setOpened } = useSearchPalette();

    <div
      class={clsx(
        "top-0 gap-2 h-12 fixed bg-gray-50 dark:bg-gray-800 border-gray-200 dark:border-gray-700 border-b-2 right-0 z-1 items-center justify-center w-full flex py-2 px-4 md:px-8",
        "!pr-[max(1rem,calc((100%-(1536px))/2))]"
      )}
    >
      <div class="flex md:hidden items-center justify-start px-1">
        <IconButton
          path={logoIcon}
          color="primary"
          link="/"
          class="bg-gradient-to-tr from-red-500 to-orange-500 m-0 mr-1"
        />
        <span class="flex-1 text-2xl font-extrabold text-gray-600 dark:text-gray-200">rite</span>
      </div>
      <For each={externalLinks}>
        {(link) => {
          return (
            <a
              class="flex justify-start items-center group cursor-pointer"
              target="_blank"
              href={link.href}
            >
              <Tooltip text={link.label} class="mt-1">
                <IconButton
                  path={link.icon}
                  class="m-0 h-8 min-w-8"
                  iconProps={{ class: "h-5 w-5" }}
                  text="soft"
                />
              </Tooltip>
            </a>
          );
        }}
      </For>
          <div class="hidden md:flex w-full items-center">
            <span class="pl-1 flex-1 text-start pr-3">Search</span>
            <Show when={typeof window === "object"}>
              <kbd class="bg-gray-300 dark:bg-gray-700 group-hover:bg-gray-200 dark:group-hover:bg-gray-800 flex justify-center items-center rounded-md px-1 h-5 text-sm">
                {isAppleDevice() ? (
                  <Icon path={mdiAppleKeyboardCommand} class="h-3 w-3" />
                ) : (
                  "Ctrl "
                )}
                K
              </kbd>
            </Show>
        class="lg:min-w-48 justify-start m-0 group"
        onClick={() => {
          setOpened(!opened());
        }}
      <Button color="primary" class="m-0" link="https://app.vrite.io">
        Sign in
      </Button>
const HeaderWrapper: Component = () => {
  return (
    <SearchPaletteProvider>
      <Header />
    </SearchPaletteProvider>
  );
};
export { HeaderWrapper as Header };
export * from "./footer";
export * from "./search-palette";
export * from "./footer";
import {
  Component,
  For,
  onMount,
  onCleanup,
  createSignal,
  createMemo,
  createEffect
} from "solid-js";
import { scroll } from "seamless-scroll-polyfill";
      return heading.depth === 2 || heading.depth === 3;
  const scrollToActiveHeading = (smooth?: boolean): void => {
    const heading = activeHeading();
    const element = document.getElementById(heading);

    if (!element) return;

    const rect = element.getBoundingClientRect();
    const y = rect.top + window.scrollY - 60;

    scroll(window, {
      top: y,
      behavior: smooth === false ? "instant" : "smooth"
    });
  };
  const handleClick = (event: MouseEvent): void => {
    const target = event.target as HTMLElement;

    if (target.matches("h2, h3")) {
      const { id } = target;

      if (id) {
        setActiveHeading(id);
        scrollToActiveHeading();
        history.replaceState(null, "", `#${id}`);
        navigator.clipboard.writeText(window.location.href);
      }
    }
  };
    const hash = location.hash.slice(1);
    document.body.addEventListener("click", handleClick);
      document.body.removeEventListener("click", handleClick);

    if (hash) {
      setActiveHeading(hash);
      scrollToActiveHeading(false);
    }
          "w-56 flex-col justify-start top-0 pt-24 xl:fixed right-0 hidden xl:flex gap-2",
                class={clsx("text-start m-0", heading.depth === 3 && "ml-6")}
                size={heading.depth === 2 ? "medium" : "small"}
                  scrollToActiveHeading();
import {
  Accessor,
  Component,
  For,
  Match,
  ParentComponent,
  Setter,
  Show,
  Switch,
  createEffect,
  createSignal,
  on,
  onCleanup,
  useContext
} from "solid-js";
import {
  mdiChevronRight,
  mdiCreationOutline,
  mdiFileDocumentOutline,
  mdiHeadSnowflakeOutline,
  mdiInformationOutline,
  mdiKeyboardEsc,
  mdiKeyboardReturn,
  mdiMagnify,
  mdiSwapVertical
} from "@mdi/js";
import clsx from "clsx";
import { scrollIntoView } from "seamless-scroll-polyfill";
import { createContext } from "solid-js";
import { debounce } from "@solid-primitives/scheduled";
import { convert as convertToSlug } from "url-slug";
import { marked } from "marked";
import { createClient, SearchResult } from "@vrite/sdk/api";
import {
  Button,
  Card,
  Icon,
  IconButton,
  Input,
  Loader,
  Overlay,
  Tooltip
} from "#components/primitives";

interface SearchPaletteProps {
  opened: boolean;
  setOpened(opened: boolean): void;
}
interface SearchPaletteContextData {
  opened: Accessor<boolean>;
  setOpened: Setter<boolean>;
}

const SearchPaletteContext = createContext<SearchPaletteContextData>();
const SearchPalette: Component<SearchPaletteProps> = (props) => {
  const client = createClient({
    token: import.meta.env.PUBLIC_VRITE_SEARCH_TOKEN
  });
  const [inputRef, setInputRef] = createSignal<HTMLInputElement | null>(null);
  const [abortControllerRef, setAbortControllerRef] = createSignal<AbortController | null>(null);
  const [mode, setMode] = createSignal<"search" | "ask">("search");
  const [searchResults, setSearchResults] = createSignal<SearchResult[]>([]);
  const [answer, setAnswer] = createSignal<string>("");
  const [loading, setLoading] = createSignal(false);
  const [mouseHoverEnabled, setMouseHoverEnabled] = createSignal(false);
  const [selectedIndex, setSelectedIndex] = createSignal(0);
  const [query, setQuery] = createSignal("");
  const ask = async (): Promise<void> => {
    let content = "";

    client.useSignal(abortControllerRef()?.signal || null).ask({
      query: query(),
      onError(error) {
        setLoading(false);
        throw error;
      },
      onChunk(chunk) {
        content += chunk;
        setAnswer(marked.parse(content, { gfm: true }));
      },
      onEnd() {
        setLoading(false);
      }
    });
    setLoading(false);
  };
  const search = debounce(async () => {
    setSearchResults([]);

    if (abortControllerRef()) abortControllerRef()?.abort();

    if (!query()) {
      setLoading(false);
      setSearchResults([]);

      return;
    }

    setAbortControllerRef(new AbortController());

    try {
      const search = await client
        .useSignal(abortControllerRef()?.signal || null)
        .search({ query: query() });

      setSearchResults(search);
      setLoading(false);

      return;
    } catch (error) {
      const trpcError = error as any;
      const causeErrorName = trpcError.cause?.name?.toLowerCase() || "";

      if (!causeErrorName.includes("aborterror") && abortControllerRef()?.signal.aborted) {
        setLoading(false);
      }
    }
  }, 150);
  const scrollToSelectedResult = (smooth?: boolean): void => {
    const selectedResultElement = document.querySelector("[data-selected=true]");

    if (selectedResultElement) {
      scrollIntoView(selectedResultElement, {
        behavior: smooth ? "smooth" : "instant",
        block: "center"
      });
    }
  };
  const goToContentPiece = (searchResult: SearchResult): void => {
    // eslint-disable-next-line no-console
    props.setOpened(false);

    const { slug } = searchResult.contentPiece;
    const [title, subHeading1, subHeading2] = searchResult.breadcrumb;

    window.location.href = `/${slug.startsWith("/") ? slug.slice(1) : slug}#${convertToSlug(
      subHeading2 || subHeading1
    )}`;
  };

  createEffect(
    on(
      query,
      () => {
        if (mode() === "search") {
          search.clear();
          search();
        }
      },
      { defer: true }
    )
  );
  createEffect(
    on(mode, () => {
      setMouseHoverEnabled(false);
      setSelectedIndex(0);
      setLoading(false);
      setAnswer("");
      setSearchResults([]);
      setQuery("");
    })
  );
  createEffect(() => {
    if (inputRef() && props.opened && mode()) {
      setTimeout(() => {
        inputRef()?.focus();
      }, 300);
    }
  });
  createEffect(() => {
    import("tinykeys").then(({ createKeybindingsHandler }) => {
      const keyShortcutHandler = createKeybindingsHandler({
        "$mod+KeyK": (event) => {
          props.setOpened(!props.opened);
        },
        "escape": (event) => {
          if (!props.opened) return;

          props.setOpened(false);
        },
        "ArrowUp": (event) => {
          if (!props.opened) return;

          setMouseHoverEnabled(false);
          event.preventDefault();
          event.stopPropagation();

          if (selectedIndex() > 0) {
            setSelectedIndex(selectedIndex() - 1);
            scrollToSelectedResult();
          } else if (mode() === "search") {
            setSelectedIndex(searchResults().length - 1);
            scrollToSelectedResult(true);
          }
        },
        "ArrowDown": (event) => {
          if (!props.opened) return;

          setMouseHoverEnabled(false);
          event.preventDefault();
          event.stopPropagation();

          if (mode() === "search" && selectedIndex() < searchResults().length - 1) {
            setSelectedIndex(selectedIndex() + 1);
            scrollToSelectedResult();
          } else {
            setSelectedIndex(0);
            scrollToSelectedResult(true);
          }
        },
        "Enter": (event) => {
          if (!props.opened) return;

          if (mode() === "search") {
            goToContentPiece(searchResults()[selectedIndex()]);
          }
        }
      });

      window.addEventListener("keydown", keyShortcutHandler);
      onCleanup(() => {
        window.removeEventListener("keydown", keyShortcutHandler);
      });
    });
  });

  const getIcon = (): string => {
    switch (mode()) {
      case "search":
        return mdiMagnify;
      case "ask":
        return mdiHeadSnowflakeOutline;
    }
  };
  const getLabel = (): string => {
    switch (mode()) {
      case "ask":
        return "Just ask";
      case "search":
      default:
        return "Search";
    }
  };

  return (
    <Overlay
      opened={props.opened}
      class="items-start"
      shadeClass="bg-opacity-50"
      wrapperClass="mt-32"
      onOverlayClick={() => {
        props.setOpened(false);
      }}
    >
      <Card
        class="w-2xl max-w-[calc(100vw-2rem)] max-h-[calc(100vh-16rem)] flex flex-col p-0 overflow-hidden shadow-xl"
        color="base"
        onPointerMove={() => {
          setMouseHoverEnabled(true);
        }}
      >
        <div class="flex w-full justify-center items-center p-2 border-b-2 dark:border-gray-700">
          <IconButton path={getIcon()} text="soft" variant="text" badge hover={false} class="m-0" />
          <Input
            value={query()}
            setValue={(value) => {
              if (mode() === "search") {
                setLoading(true);
              }

              setQuery(value);
            }}
            ref={setInputRef}
            tabIndex={0}
            placeholder={getLabel()}
            wrapperClass="flex-1 m-0"
            class="m-0 bg-transparent"
            onEnter={() => {
              if (mode() === "ask") {
                setLoading(true);
                setAnswer("");
                ask();
              }
            }}
            onKeyDown={(event) => {
              if (event.key === "Backspace" && !query()) {
                setMode("search");
              }
            }}
            adornment={() => (
              <Show when={mode() === "search" || mode() === "ask"}>
                <Tooltip text="Ask" side="left" class="-ml-1">
                  <IconButton
                    path={mdiCreationOutline}
                    class="m-0"
                    text={mode() === "ask" ? "base" : "soft"}
                    color={mode() === "ask" ? "primary" : "base"}
                    onClick={() => {
                      setMode((mode) => (mode === "ask" ? "search" : "ask"));
                    }}
                    variant="text"
                  />
                </Tooltip>
              </Show>
            )}
          />
        </div>
        <div class="relative overflow-hidden">
          <div class="flex-1 flex flex-col overflow-auto  max-h-[calc(100vh-21.5rem)] scrollbar-sm">
            <Switch>
              <Match when={mode() === "search"}>
                <Show
                  when={!loading()}
                  fallback={
                    <div class="flex justify-center items-center p-4">
                      <Loader />
                    </div>
                  }
                >
                  <For
                    each={searchResults()}
                    fallback={
                      <span class="p-4 text-center text-gray-500 dark:text-gray-400">
                        <Show when={query()} fallback="Type to search">
                          No results
                        </Show>
                      </span>
                    }
                  >
                    {(result, index) => {
                      return (
                        <Card
                          class={clsx(
                            "flex justify-start items-center py-2 px-3 m-0 rounded-none border-none",
                            index() === selectedIndex() &&
                              "bg-gray-300 dark:bg-gray-700 cursor-pointer",
                            index() !== selectedIndex() && "bg-transparent"
                          )}
                          color="base"
                          onClick={() => {
                            goToContentPiece(result);
                          }}
                          onPointerEnter={() => {
                            if (!mouseHoverEnabled()) return;

                            setSelectedIndex(index());
                          }}
                        >
                          <div class="flex w-full">
                            <Icon
                              path={mdiFileDocumentOutline}
                              class="h-6 w-6 mr-2 justify-start items-center"
                            />
                            <div class="flex flex-col justify-start flex-1">
                              <p class="flex items-center justify-start flex-wrap font-semibold">
                                <For each={result.breadcrumb}>
                                  {(breadcrumb, index) => {
                                    return (
                                      <>
                                        <Show when={index()}>
                                          <Icon
                                            path={mdiChevronRight}
                                            class="flex-inline h-5 w-5 text-gray-500 dark:text-gray-400"
                                          />
                                        </Show>
                                        {breadcrumb}
                                      </>
                                    );
                                  }}
                                </For>
                              </p>
                              <p class="prose flex-1 text-sm clamp-2 whitespace-pre-wrap text-gray-500 dark:text-gray-400">
                                {result.content}
                              </p>
                            </div>
                          </div>
                        </Card>
                      );
                    }}
                  </For>
                </Show>
              </Match>
              <Match when={mode() === "ask"}>
                <Show
                  when={answer()}
                  fallback={
                    <Show
                      when={!loading()}
                      fallback={
                        <div class="flex justify-center items-center p-4">
                          <Loader />
                        </div>
                      }
                    >
                      <span class="p-4 text-center text-gray-500 dark:text-gray-400">
                        What do you want to know?
                      </span>
                    </Show>
                  }
                >
                  <Card
                    class={clsx(
                      "flex flex-col items-center py-2 px-3 m-0 rounded-none border-none"
                    )}
                    color="base"
                  >
                    <div
                      class="flex flex-col w-full prose whitespace-pre-wrap"
                      innerHTML={answer()}
                    />
                    <Show when={!loading()}>
                      <IconButton
                        color="contrast"
                        text="soft"
                        size="small"
                        badge
                        class="mt-4"
                        path={mdiInformationOutline}
                        label="The information produced may be inaccurate."
                      />
                    </Show>
                  </Card>
                </Show>
              </Match>
            </Switch>
          </div>
        </div>
        <div class="border-t-2 dark:border-gray-700 px-2 py-1 flex gap-2 bg-gray-100 dark:bg-gray-800">
          <div class="hidden md:flex gap-2">
            <IconButton
              path={mdiSwapVertical}
              hover={false}
              badge
              label="Select"
              size="small"
              variant="text"
              text="soft"
            />
            <IconButton
              path={mdiKeyboardReturn}
              hover={false}
              badge
              label="Open"
              size="small"
              variant="text"
              text="soft"
            />
            <IconButton
              path={mdiKeyboardEsc}
              hover={false}
              badge
              label="Close"
              size="small"
              variant="text"
              text="soft"
            />
          </div>
          <div class="flex-1" />
          <Button
            size="small"
            variant="text"
            color={mode() === "ask" ? "primary" : "base"}
            text={mode() === "ask" ? "base" : "soft"}
            onClick={() => {
              setMode((mode) => (mode === "search" ? "ask" : "search"));
            }}
          >
            Ask a question
          </Button>
        </div>
      </Card>
    </Overlay>
  );
};
const SearchPaletteProvider: ParentComponent = (props) => {
  const [opened, setOpened] = createSignal(false);

  createEffect(() => {
    if (opened()) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "auto";
    }
  });

  return (
    <SearchPaletteContext.Provider
      value={{
        opened,
        setOpened
      }}
    >
      {props.children}
      <SearchPalette opened={opened()} setOpened={setOpened} />
    </SearchPaletteContext.Provider>
  );
};
const useSearchPalette = (): SearchPaletteContextData => {
  return useContext(SearchPaletteContext)!;
};

export { SearchPaletteProvider, useSearchPalette };
import { mdiMenu, mdiClose, mdiChevronDown } from "@mdi/js";
import { Component, For, JSX, createEffect, createSignal } from "solid-js";
  currentSection: string;
  sections: Array<{
    icon: string;
    link: string;
    id: string;
  menu: Record<
    string,
    Array<{
      label: string;
      menu: Array<{ label: string; link?: string; menu?: Array<{ label: string; link: string }> }>;
    }>
  >;
interface SideBarNestedMenuProps {
  menu: Array<{ label: string; link?: string; menu?: Array<{ label: string; link: string }> }>;
  openedByDefault?: boolean;
}

const SideBarNestedMenu: Component<SideBarNestedMenuProps> = (props) => {
    props.openedByDefault ||
      props.menu.filter((item) => {
        return item.link && props.currentPath.includes(item.link);
      }).length > 0
                return Boolean(item.link && props.currentPath.includes(item.link));
  createEffect(() => {
    if (menuOpened()) {
      document.body.style.overflow = "hidden";
    } else {
      document.body.style.overflow = "auto";
    }
  });

            menuOpened() ? "" : "translate-y-[100vh] md:translate-y-0"
            <For each={props.sections}>
              {(section) => {
                    target={section.link.startsWith("http") ? "_blank" : "_self"}
                    href={section.link}
                      path={section.icon}
                      color={section.id === props.currentSection ? "primary" : "contrast"}
                      text={section.id === props.currentSection ? "primary" : "soft"}
                    <span class=" ml-2 text-gray-500 dark:text-gray-400">{section.label}</span>
          <For each={props.menu[props.currentSection]}>
                <SideBarNestedMenu
                  currentPath={props.currentPath}
                  menu={menuItem.menu}
                  openedByDefault
                >
import { Header, BaseHead, SideBar, SVGDefs, OnThisPage, Footer } from "#components/fragments";
import { Button } from "#components/primitives";
import { mdiBookOpenBlankVariant, mdiConsoleLine, mdiTextBoxMultiple } from "@mdi/js";
const flattenMenu = (
  menu: Array<{
    label: string;
    link?: string;
    menu?: Array<{ label: string; link: string }>;
  }>,
  section: string,
  labels: string[]
): Array<{ label: string; link: string; section: string; labels: string[] }> => {
  return menu.flatMap((item) => {
    if (item.link) {
      return [{ label: item.label, link: item.link, section, labels: [...labels, item.label] }];
    }
    if (item.menu) {
      return flattenMenu(item.menu, section, [...labels, item.label]);
    }
    return [];
  });
};
const sections = [
  {
    label: "Documentation",
    link: "/usage-guide/getting-started",
    icon: mdiBookOpenBlankVariant,
    id: "docs"
  },
  {
    label: "API reference",
    link: "https://generator.swagger.io/?url=https://api.vrite.io/swagger.json",
    icon: mdiConsoleLine,
    id: "api"
  }
  /*{
    label: "Recipes",
    link: "/self-hosting/docker",
    icon: mdiTextBoxMultiple,
    id: "recipes"
  }*/
];
const flatMenu = [
  ...flattenMenu(menu.docs, "docs", []),
  ...flattenMenu(menu.recipes, "recipes", [])
];
const currentEntry = flatMenu.find((item) => item.link === Astro.url.pathname);
const nextEntry = currentEntry ? flatMenu[flatMenu.indexOf(currentEntry) + 1] : null;
const prevEntry = currentEntry ? flatMenu[flatMenu.indexOf(currentEntry) - 1] : null;
  description?: string;
    <BaseHead
      description={Astro.props.description || description}
      title={Astro.props.title ? `${Astro.props.title} | Vrite Documentation` : title}
      image={image}
    />
        <Header client:load />
        <SideBar
          menu={menu}
          sections={sections}
          currentSection={currentEntry?.section || "docs"}
          currentPath={Astro.url.pathname}
          client:load
        />
        <div class="flex overflow-hidden w-full relative h-full pt-12">
          <div
            class="flex-1 flex overflow-y-auto overflow-x-hidden justify-center min-h-[calc(100vh-3rem)]"
            id="container"
          >
              class="flex-1 prose max-w-screen-md w-full text-lg px-4 md:px-8 pt-4 pb-24 h-fit xl:w-[calc(100%-15rem)]"
              {
                (currentEntry?.labels.length || 0) > 1 && (
                  <Button badge color="primary" variant="text" class="m-0 pl-1 py-0" hover={false}>
                    {currentEntry?.labels.at(-2)}
                  </Button>
                )
              }
              <h1>{Astro.props.title}</h1>
              <Footer nextEntry={nextEntry} previousEntry={prevEntry} />
{
  "docs": [
    {
      "label": "Usage Guide",
      "menu": [
        {
          "label": "Getting Started",
          "link": "/usage-guide/getting-started"
        },
        {
          "label": "Managing Content with Kanban",
          "link": "/usage-guide/kanban-dashboard"
        },
        {
          "label": "Managing metadata",
          "link": "/usage-guide/metadata"
        },
        {
          "label": "Writing in the Vrite Editor",
          "link": "/usage-guide/content-editor"
        },
        {
          "label": "Configuring Vrite",
          "link": "/usage-guide/configuring-vrite"
        },
        {
          "label": "Publishing content",
          "link": "/usage-guide/publishing"
        },
        {
          "label": "Vrite Extensions",
          "link": "/usage-guide/vrite-extensions"
        }
      ]
    },
    {
      "label": "JavaScript SDK",
      "menu": [
        {
          "label": "Introduction",
          "link": "/javascript-sdk/introduction"
        }
      ]
    },
    {
      "label": "Self-Hosting",
      "menu": [
        {
          "label": "Docker",
          "link": "/self-hosting/docker"
        },
        {
          "label": "Configuration",
          "link": "/self-hosting/configuration"
        }
      ]
    }
  ],
  "recipes": []
}
  type: "content",
  schema: z.object({
    title: z.string().optional(),
    description: z.string().optional()
  })
});
const recipesCollection = defineCollection({
  type: "content",
  schema: z.object({
    title: z.string().optional(),
    description: z.string().optional()
  })
  docs: docsCollection,
  recipes: recipesCollection
---
title: "Introduction"
slug: "javascript-sdk/introduction"
---

---
title: "Configuring Self-Hosted Vrite"
slug: "self-hosting/configuration"
---

---
title: "Self-Hosting Vrite with Docker"
slug: "self-hosting/docker"
---

---
title: "Configuring Vrite"
slug: "usage-guide/configuring-vrite"
---

---
title: "Writing in Vrite Editor"
slug: "/usage-guide/content-editor"
---

---
title: "Getting Started"
slug: "/usage-guide/getting-started"
---

---
title: "Managing Content in Kanban"
slug: "/usage-guide/kanban-dashboard"
---

---
title: "Managing Metadata"
slug: "/usage-guide/metadata"
---

---
title: "Publishing Content"
slug: "/usage-guide/publishing"
---

---
title: "Vrite Extensions"
slug: "/usage-guide/vrite-extensions"
---

---
title: "Content Pieces API"
slug: "/recipes/content-pieces"
---

Content
interface ImportMetaEnv {
  readonly PUBLIC_VRITE_SEARCH_TOKEN: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}
  const docsEntries = await getCollection("docs");
  const recipesEntries = await getCollection("recipes");
  return [
    ...docsEntries.map((entry) => ({
      params: { slug: entry.slug },
      props: { entry }
    })),
    ...recipesEntries.map((entry) => ({
      params: { slug: entry.slug },
      props: { entry }
    }))
  ];
<DefaultLayout headings={headings} title={entry.data.title} description={entry.data.description}>

.clamp-1 {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  overflow-wrap: break-word;
  -webkit-line-clamp: 1;
  line-clamp: 1;
  -webkit-box-orient: vertical;
}
.clamp-2 {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  overflow-wrap: break-word;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
}
.clamp-3 {
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  overflow-wrap: break-word;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
}
.font-jetbrains {
  font-family: "JetBrainsMonoVariable", monospace;
}
svg > path {
  fill: inherit;
}
.grid-reset-margin {
  & > * {
    margin: 0;
  }
}
    @apply relative;
    margin: 0 !important;
  :where(h2, h3):not(:where(.not-prose, .not-prose *)) {
    @apply hover:cursor-pointer;
    &::before {
      @apply hidden md:block absolute pr-6 -left-6 transform scale-90 text-gray-500 dark:text-gray-400 opacity-0;
      content: "#";
    &:hover::before {
      @apply opacity-100;
  h3:not(:where(.not-prose, .not-prose *))::before {
    @apply pr-5 -left-5;

    "monaco-editor": "^0.43.0",
          for (var i = 0; i < octets.length; i += 1) {
            var octet = octets[i];
          for (var i = 0; i < array.length; i += 1) {
            var line = array[i];
            for (var i = 0; i < length; i += 1) {
              var listener = typeListeners[i];
          for (var i = 0; i < typeListeners.length; i += 1) {
            if (typeListeners[i] === listener) {
            for (var i = 0; i < typeListeners.length; i += 1) {
              if (typeListeners[i] !== listener) {
                filtered.push(typeListeners[i]);
              for (var i = 0; i < textChunk.length; i += 1) {
                var c = textChunk.charCodeAt(i);
                  n = i;
                var i = url.indexOf("?");
                requestURL = i === -1 ? url : url.slice(0, i + 1) + url.slice(i + 1).replace(/(?:^|&)([^=&]*)(?:=[^&]*)?/g, function(p, paramName) {
          var s = new XMLHttpRequest(), o = [], u2 = [], i = {}, a = function() {
              return i[e2.toLowerCase()];
              return e2.toLowerCase() in i;
              o.push(n2 = n2.toLowerCase()), u2.push([n2, t2]), i[n2] = i[n2] ? i[n2] + "," + t2 : t2;
    createClient: () => M
  var import_eventsource, l, U, E, S, f, h, L, m, D, O, R, T, x, C, I, u, v, k, j, q, G, A, b, z, y, B, M;
      l = "/content-groups";
      U = (t) => ({ get: (e) => t("GET", `${l}`, { params: e }), list: (e) => t("GET", `${l}/list`, { params: e }), create: (e) => t("POST", `${l}`, { body: e }), update: (e) => t("PUT", `${l}`, { body: e }), delete: (e) => t("DELETE", `${l}`, { params: e }) });
      E = "/content-pieces";
      S = (t) => ({ get: (e) => t("GET", `${E}`, { params: e }), create: (e) => t("POST", `${E}`, { body: e }), update: (e) => t("PUT", `${E}`, { body: e }), delete: (e) => t("DELETE", `${E}`, { params: e }), list: (e) => t("GET", `${E}/list`, { params: e }) });
        let e = t.baseURL || "https://api.vrite.io", c = t.extensionId || "", i = t.headers || {}, $ = null, { token: p } = t;
        return { sendRequest: async (s, a, n) => {
            const { default: o } = await Promise.resolve().then(() => __toESM(require_browser2(), 1)), d = await o(`${e}${a}/?${encodeURI(Object.entries(n?.params || {}).filter(([, g]) => g).map(([g, w]) => `${g}=${w}`).join("&"))}`, { headers: { Authorization: `Bearer ${p}`, Accept: "application/json", ...n?.body ? { "Content-Type": "application/json" } : {}, ...c ? { "X-Vrite-Extension-ID": c } : {}, ...i }, body: n?.body ? JSON.stringify(n.body) : null, signal: $, method: s });
            $ = null;
            let r = null;
              if (r = await d.json(), !r)
            if (!d.ok)
              throw r;
            return r;
        }, reconfigure: (s) => {
          e = s.baseURL || e, p = s.token || p, c = s.extensionId || c, i = s.headers || i;
        }, useSignal: (s) => {
          $ = s;
        }, getConfig: () => ({ baseURL: e, token: p, extensionId: c, headers: i }), getSignal: () => $ };
      h = "/user-settings";
      L = (t) => ({ get: () => t("GET", `${h}`), update: (e) => t("PUT", `${h}`, { body: e }) });
      m = "/tags";
      D = (t) => ({ get: (e) => t("GET", `${m}`, { params: e }), update: (e) => t("PUT", `${m}`, { body: e }), create: (e) => t("PUT", `${m}`, { body: e }), delete: (e) => t("DELETE", `${m}`, { params: e }), list: (e) => t("GET", `${m}/list`, { params: e }) });
      O = "/profile";
      R = (t) => ({ get: () => t("GET", `${O}`) });
      T = "/webhooks";
      x = (t) => ({ get: (e) => t("GET", `${T}`, { params: e }), create: (e) => t("POST", `${T}`, { body: e }), update: (e) => t("PUT", `${T}`, { body: e }), delete: (e) => t("DELETE", `${T}`, { params: e }), list: (e) => t("GET", `${T}/list`, { params: e }) });
      I = (t) => ({ get: () => t("GET", `${C}`) });
      u = "/roles";
      v = (t) => ({ get: (e) => t("GET", `${u}`, { params: e }), create: (e) => t("POST", `${u}`, { body: e }), update: (e) => t("PUT", `${u}`, { body: e }), delete: (e) => t("DELETE", `${u}`, { params: e }), list: (e) => t("GET", `${u}/list`, { params: e }) });
      k = "/workspace-settings";
      j = (t) => ({ get: () => t("GET", `${k}`), update: (e) => t("PUT", `${k}`, { body: e }) });
      q = (t) => ({ listMembers: (e) => t("GET", "/workspace-memberships/list-members", { params: e }), listWorkspaces: (e) => t("GET", "/workspace-memberships/list-workspaces", { params: e }), create: (e) => t("POST", "/workspace-memberships", { body: e }), update: (e) => t("PUT", "/workspace-memberships", { body: e }), delete: (e) => t("DELETE", "/workspace-memberships", { params: e }) });
      G = "/extension";
      A = (t) => ({ get: () => t("GET", `${G}`), updateContentPieceData: (e) => t("POST", `${G}/content-piece-data`, { body: e }) });
      b = "/variants";
      z = (t) => ({ create: (e) => t("POST", `${b}`, { body: e }), update: (e) => t("PUT", `${b}`, { body: e }), delete: (e) => t("DELETE", `${b}`, { params: e }), list: () => t("GET", `${b}/list`) });
      y = "/transformers";
      B = (t) => ({ create: (e) => t("POST", `${y}`, { body: e }), delete: (e) => t("DELETE", `${y}`, { params: e }), list: () => t("GET", `${y}/list`) });
      M = (t) => {
        const { sendRequest: e, reconfigure: c, getConfig: i, getSignal: $, useSignal: p } = f(t), s = { contentGroups: U(e), contentPieces: S(e), tags: D(e), profile: R(e), userSettings: L(e), webhooks: x(e), workspace: I(e), roles: v(e), workspaceSettings: j(e), workspaceMemberships: q(e), extension: A(e), variants: z(e), transformers: B(e), search(a) {
          return e("GET", "/search", { params: a });
        }, async ask(a) {
          let n = "";
          const o = new import_eventsource.default(`${i().baseURL}/search/ask?query=${encodeURIComponent(a.query)}`, { headers: { Authorization: `Bearer ${i().token}` } });
          o.addEventListener("error", (d) => {
            const r = d;
            return r.message ? a.onError?.(r.message) : (o.close(), a.onEnd?.(n));
          }), o.addEventListener("message", (d) => {
            const r = decodeURIComponent(d.data);
            n += r, a.onChunk?.(r, n);
          }), $()?.addEventListener("abort", () => {
            o.close();
          }), p(null);
        }, useSignal(a) {
          return p(a), s;
        }, reconfigure(a) {
          return c(a), s;
        } };
        return s;
  "base": "vs",
  "inherit": true,
      "token": "",
      "settings": {
        "foreground": "#000000",
        "background": "#FFFFFF"
      }
  "colors": {
    "editor.background": "#f9fafb",
    "editorWidget.background": "#f3f4f6",
    "editor.foreground": "#000000",
    "editor.inactiveSelectionBackground": "#E5EBF1",
    "editorIndentGuide.background": "#D3D3D3",
    "editorIndentGuide.activeBackground": "#939393",
    "editor.selectionHighlightBackground": "#ADD6FF80",
    "editorSuggestWidget.background": "#F3F3F3",
    "activityBarBadge.background": "#007ACC",
    "sideBarTitle.foreground": "#6F6F6F",
    "list.hoverBackground": "#E8E8E8",
    "input.placeholderForeground": "#767676",
    "searchEditor.textInputBorder": "#CECECE",
    "settings.textInputBorder": "#CECECE",
    "settings.numberInputBorder": "#CECECE",
    "statusBarItem.remoteForeground": "#FFF",
    "statusBarItem.remoteBackground": "#16825D",
    "sideBarSectionHeader.background": "#0000",
    "sideBarSectionHeader.border": "#61616130",
    "tab.lastPinnedBorder": "#61616130",
    "notebook.cellBorderColor": "#E8E8E8",
    "statusBarItem.errorBackground": "#c72e0f"
  }
          "w-full bg-gray-100 border-2 not-prose dark:bg-gray-900 rounded-2xl dark:border-gray-700 rounded-editor-2xl customized-editor box-content",
          props.color === "contrast" && "customized-editor-contrast",
    userSettings = () => ({ accentColor: "energy", codeEditorTheme: "auto", uiTheme: "auto" })
              if (error.data?.code === "UNAUTHORIZED" && window.location.pathname !== "/auth") {
  "gpt-3.5": () => import("@vrite/extensions/gpt-3.5.json"),
  "mdx": () => import("@vrite/extensions/mdx.json")
        ":base-2: p-1 w-full flex items-center border-b-2 absolute h-12 border-gray-200 dark:border-gray-700 justify-end @container z-10",
  json: "json-stringify",
  scss: "scss",
  mdx: "mdx"
    case "json":
    case "mdx":
      plugins: parserPlugins
const useSuggestLanguage = (): ((query: string) => string[]) => {
    import("#lib/monaco").then(({ monaco }) => {
      const languageIds = getLanguageIds(monaco.languages.getLanguages());

      engine.addAll(languageIds);
    });
import { CodeBlock, Embed, Image, Element } from "./extensions";
    element: Element,
      label: "Element",
      block: "element",
        return editor.chain().focus().deleteRange(range).setElement().run();
                    return node()?.type.name === props.state.editor.schema.nodes[block].name;
      } catch (error) {
import { SolidNodeViewProps } from "@vrite/tiptap-solid";
import { mdiCodeTags, mdiCodeTagsCheck, mdiFileOutline } from "@mdi/js";
import { debounce } from "@solid-primitives/scheduled";
import { Card, IconButton, Input, Tooltip } from "#components/primitives";
import { createRef } from "#lib/utils";
  state: SolidNodeViewProps<CodeBlockAttributes>;
  changeLanguage(lang: string | null): void;
  const [mode, setMode] = createSignal<"title" | "lang">("lang");
  const [menuRef, setMenuRef] = createRef<HTMLElement | null>(null);
  const [left, setLeft] = createSignal(0);
  const attrs = (): CodeBlockAttributes => props.state.node.attrs;
  const suggestLanguage = useSuggestLanguage();
  const formattingAvailable = createMemo(() => isFormattable(attrs().lang?.split(" ")?.[0] || ""));
  const updateAttribute = debounce((attributes: CodeBlockAttributes) => {
    return props.state.updateAttributes(attributes);
  }, 200);
  const currentValue = (): string => {
    if (mode() === "lang") {
      return [attrs().lang, attrs().meta].filter(Boolean).join(" ");
    }

    return attrs().title || "";
  };
    on(attrs, (attrs) => {
      setSuggestions(suggestLanguage(attrs.lang || ""));
      props.changeLanguage(attrs.lang?.split(" ")?.[0] || null);
  createEffect(
    on(
      () => props.state.selected,
      () => {
        const element = menuRef();

        if (!element || !element.parentElement) return;

        const { left, width } = element.parentElement.getBoundingClientRect();
        const right = window.innerWidth - left - width;

        setLeft(-Math.abs((right - left) / 2));
      }
    )
  );
    <div
      class="pointer-events-auto flex bg-gray-50 dark:bg-gray-900 !md:bg-transparent border-gray-200 dark:border-gray-700 border-y-2 md:border-0 backdrop-blur-sm md:gap-2 w-screen md:w-auto !md:left-unset relative md:rounded-2xl"
      style={{ left: `${left()}px` }}
      ref={setMenuRef}
    >
      <Card class="flex py-0 m-0 border-0 md:border-2 px-1 gap-1">
        <Tooltip text="Title">
            path={mdiFileOutline}
            color={mode() === "title" ? "primary" : "contrast"}
            text={mode() === "title" ? "primary" : "soft"}
            variant={mode() === "title" ? "solid" : "text"}
            class="m-0"
            onClick={() => {
              setMode("title");
            }}
        <Tooltip text="Language">
          <IconButton
            path={mdiCodeTags}
            color={mode() === "lang" ? "primary" : "contrast"}
            text={mode() === "lang" ? "primary" : "soft"}
            variant={mode() === "lang" ? "solid" : "text"}
            class="m-0"
            onClick={() => {
              setMode("lang");
            }}
          ></IconButton>
        </Tooltip>
      </Card>
      <Card class="flex m-0 border-0 md:border-2 p-1 gap-1 flex-1">
        <Input
          wrapperClass="flex-1 max-w-full md:w-72"
          placeholder={mode() === "title" ? "Snippet title" : "Language meta"}
          value={currentValue()}
          suggestions={mode() === "lang" ? suggestions() : []}
          suggestionsBoxClass="mt-3 mx-0 mb-0"
          class="m-0 !bg-transparent text-lg"
          color="contrast"
          disabled={!props.state.editor.isEditable}
          setValue={(value) => {
            updateAttribute.clear();

            if (mode() === "lang") {
              const [lang, ...meta] = value.split(" ");

              updateAttribute({ meta: meta.join(" "), lang });
            } else {
              updateAttribute({ title: value });
            }
          }}
        />
      </Card>
      <Card class="flex m-0 border-0 md:border-2 p-1">
        <Show when={props.state.editor.isEditable}>
          <Tooltip text={formattingAvailable() ? "Format" : "Formatting unavailable"} class="mt-1">
            <IconButton
              path={mdiCodeTagsCheck}
              color="contrast"
              text="soft"
              variant="text"
              class="m-0"
              disabled={!formattingAvailable()}
              onClick={props.format}
            ></IconButton>
          </Tooltip>
        </Show>
      </Card>
          <NodeViewWrapper>
import { Component, createEffect, createSignal, on, onMount } from "solid-js";
import { useAppearance, useAuthenticatedUserData, useNotifications } from "#context";
  const [codeEditorActive, setCodeEditorActive] = createSignal(false);
      const formattedCode = (await formattingCode).trim();
    const contentHeight = Math.max(20, monacoEditor.getContentHeight());
        setCodeEditorActive(false);
      });
      codeEditor.onDidFocusEditorText(() => {
        setCodeEditorActive(true);
  createEffect(
    on(codeEditorActive, (active) => {
      if (active) {
        state().editor.commands.setNodeSelection(state().getPos());
      }
    })
  );
        "relative rounded-2xl text-base leading-4 not-prose",
          "bg-gray-50 dark:bg-gray-900 h-72 rounded-2xl rounded-editor-2xl border-2 border-gray-300 dark:border-gray-700 box-content customized-editor"
      <div
          "absolute w-full justify-center items-center -bottom-14 z-1 pointer-events-none",
          selected() ? "grid" : "hidden"
        <CodeBlockMenu changeLanguage={changeLanguage} format={format} state={state()} />
      </div>
      <div data-type="draggable-item" />
          if (
            container.parentElement?.classList.contains("ProseMirror") ||
            container.parentElement?.classList.contains("content") ||
            container.parentElement?.tagName === "TH" ||
            container.parentElement?.tagName === "TD" ||
            container.parentElement?.tagName === "LI" ||
            container.parentElement?.tagName === "BLOCKQUOTE"
          ) {

            let parentPos = document.getElementById("pm-container")?.getBoundingClientRect();

            if (container.parentElement?.classList.contains("content")) {
              parentPos = container.parentElement?.getBoundingClientRect();
            }
              top: rect.top - parentPos.top
import { ElementMenuEditor } from "./editor";
import { SolidEditor } from "@vrite/tiptap-solid";
import { Component, Show, createEffect, createSignal } from "solid-js";
import { Node as PMNode } from "@tiptap/pm/model";

interface ElementMenuProps {
  state: {
    pos: number;
    node: PMNode | null;
    container: HTMLElement | null;
    editor: SolidEditor;
    active: boolean;
  };
}

const ElementMenu: Component<ElementMenuProps> = (props) => {
  const [attributes, setAttributes] = createSignal({ type: "", props: {} as Record<string, any> });

  createEffect(() => {
    setAttributes((attributes) => {
      if (!props.state.node) {
        return { type: "", props: {} };
      }

      const newAttributes = props.state.node.attrs;

      if (
        newAttributes.type !== attributes.type ||
        JSON.stringify(newAttributes.props) !== JSON.stringify(attributes.props)
      ) {
        return { type: newAttributes.type, props: newAttributes.props };
      }

      return attributes;
    });
  });

  return (
    <Show when={props.state.editor.isEditable}>
      <div class="flex">
        <ElementMenuEditor
          state={{
            editor: props.state.editor,
            type: attributes()?.type || "",
            props: attributes()?.props || {},
            active: props.state.active,
            contentSize: props.state.node?.content.size || 0,

            removeElement() {
              props.state.editor.commands.command(({ tr, dispatch }) => {
                if (!dispatch) return false;

                const lastPos = props.state.pos;

                if (typeof lastPos === "number" && props.state.node) {
                  tr.delete(lastPos, lastPos + props.state.node.nodeSize);

                  return true;
                }

                return false;
              });
            },
            setElement(element) {
              props.state.editor.commands.command(({ tr, dispatch }) => {
                if (!dispatch) return false;

                const lastPos = props.state.pos;

                if (lastPos !== null) {
                  tr.setNodeAttribute(lastPos, "type", element.type);
                  tr.setNodeAttribute(lastPos, "props", element.props);

                  if (element.content && !props.state.node?.content.size) {
                    tr.replaceWith(
                      lastPos + 1,
                      lastPos + props.state.node!.content.size + 1,
                      props.state.editor.schema.node("paragraph")
                    );
                  } else if (!element.content && props.state.node?.content.size) {
                    tr.delete(lastPos + 1, lastPos + props.state.node!.content.size + 1);
                  }

                  return true;
                }

                return false;
              });
            }
          }}
        />
      </div>
    </Show>
  );
};

export { ElementMenu };
import {
  createEffect,
  createMemo,
  createRenderEffect,
  createSignal,
  lazy,
  on,
  onCleanup,
  onMount
} from "solid-js";
import { createRef } from "@vrite/components/src/ref";
import clsx from "clsx";
import { nanoid } from "nanoid";
import { SolidEditor } from "@vrite/tiptap-solid";
import { scrollIntoView } from "seamless-scroll-polyfill";
import { monaco } from "#lib/monaco";
import { useAppearance } from "#context";
import { formatCode } from "#lib/code-editor";

interface ElementMenuEditorProps {
  state: {
    type: string;
    active: boolean;
    props: Record<string, any>;
    editor: SolidEditor;
    contentSize: number;
    removeElement(): void;
    setElement(element: { type: string; props: Record<string, any>; content: boolean }): void;
  };
}

const codeEditorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
  automaticLayout: true,
  minimap: { enabled: false },
  contextmenu: false,
  fontSize: 17.5,
  fontFamily: "JetBrainsMonoVariable",
  scrollBeyondLastLine: false,
  model: null,
  wordWrap: "on",
  theme: "dark",
  suggestFontSize: 13,
  codeLensFontSize: 13,
  lineHeight: 26,
  suggestLineHeight: 21,
  overviewRulerBorder: false,
  overviewRulerLanes: 0,
  hideCursorInOverviewRuler: true,
  lineNumbers: "off",
  glyphMargin: false,
  folding: false,
  quickSuggestions: false,
  lightbulb: { enabled: false },
  hover: { enabled: false },
  lineDecorationsWidth: 0,
  lineNumbersMinChars: 0,
  renderLineHighlightOnlyWhenFocus: true,
  renderLineHighlight: "none",
  scrollbar: {
    vertical: "hidden",
    horizontal: "hidden",
    alwaysConsumeMouseWheel: false
  }
};
const ElementMenuEditor = lazy(async () => {
  const { monaco } = await import("#lib/monaco");

  return {
    default: (props: ElementMenuEditorProps) => {
      const { codeEditorTheme = () => "dark" } = useAppearance() || {};
      const [editorContainerRef, setEditorContainerRef] = createRef<HTMLElement | null>(null);
      const [coords, setCoords] = createSignal({ x: 0, y: 0 });
      const [visible, setVisible] = createSignal(true);
      const type = createMemo(() => props.state.type);
      const processCode = async (code: string): Promise<string> => {
        const codeTagClosed = code?.trim().replace(/>$/, "/>") || "";
        const formattedCode = await formatCode(codeTagClosed, "typescript", {
          printWidth: 60,
          trailingComma: "none",
          singleQuote: false
        });

        return formattedCode.replace(/ *?\/>;/gm, props.state.contentSize ? ">" : "/>").trim();
      };
      const propsValue = createMemo((previous) => {
        if (!previous || JSON.stringify(previous) !== JSON.stringify(props.state.props)) {
          return props.state.props;
        }

        return previous;
      });
      const editorCode = createMemo(() => {
        const keyValueProps = Object.entries(propsValue()).map(([key, value]) => {
          if (value === true) return key;

          const useBrackets =
            typeof value !== "string" || value.includes("\n") || value.includes(`"`);

          return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${
            useBrackets ? "}" : ""
          }`;
        });

        return `<${type()}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`;
      });
      const saveLastCoords = (event: MouseEvent): void => {
        setCoords({ x: event.clientX, y: event.clientY });
      };
      const onSave = async (code: string): Promise<void> => {
        const tagRegex = /^<(\w+?)(?:\s|\n|\/|>)/;
        const attributeRegex =
          /\s(\w+?)(?:=(?:(?:{((?:.|\n|\s)+?)})|(?:"((?:.|\n|\s)+?)")|(?:'((?:.|\n|\s)+?)')))?(?=(?:(?:\s|\n)+\w+=?)|(?:(?:\s|\n)*\/?>))/g;
        const [, tag] = tagRegex.exec(code.trim()) || [];
        const attributes: Record<string, any> = {};
        const processAttributes = async (): Promise<void> => {
          const match = attributeRegex.exec(code.trim());

          if (!match) return;

          const [, key] = match;
          const value = (match[2] || match[3] || match[4] || "true").trim();

          try {
            const processedValue = await formatCode(value, "json", {
              trailingComma: "none"
            });

            attributes[key] = JSON.parse(processedValue);
          } catch (e) {
            try {
              attributes[key] = JSON.parse(value);
            } catch (e) {
              if (!props.state.props[key] || typeof props.state.props[key] === "string") {
                attributes[key] = value;
              } else {
                attributes[key] = props.state.props[key];
              }
            }
          }

          await processAttributes();
        };

        await processAttributes();

        if (tag && tag !== "undefined") {
          props.state.setElement({
            type: tag,
            props: attributes,
            content: !code.endsWith("/>")
          });
        } else {
          props.state.removeElement();
        }
      };

      onMount(() => {
        const editorContainer = editorContainerRef()!;
        const codeEditor = monaco.editor.create(editorContainer, codeEditorOptions);
        const updateEditorHeight = (): void => {
          const container = codeEditor.getContainerDomNode();
          const contentHeight = Math.max(26, codeEditor.getContentHeight());

          if (editorContainer) {
            editorContainer.style.height = `${contentHeight}px`;
          }

          container.style.height = `${contentHeight}px`;
          codeEditor.layout({
            width: container.clientWidth,
            height: contentHeight
          });
        };

        codeEditor.onDidContentSizeChange(updateEditorHeight);
        codeEditor.onDidChangeModelContent(() => {
          const element = document.querySelector(".selected-element-tag") as HTMLElement;

          if (element) {
            element.textContent = codeEditor.getValue() || "";
            element.style.height = `${codeEditor.getContentHeight()}px`;
          }
        });
        codeEditor.onDidBlurEditorText(async () => {
          const element = document.querySelector(".selected-element-tag") as HTMLElement;

          if (element) {
            element.textContent = await processCode(editorCode());
          }

          await onSave(codeEditor.getValue());
        });
        codeEditor.onKeyDown((event) => {
          if (event.code === "Escape") {
            props.state.editor.commands.focus();
            event.preventDefault();
            event.stopPropagation();
          }
        });
        codeEditor.setModel(
          monaco.editor.createModel(
            editorCode(),
            "javascript",
            monaco.Uri.parse(`file:///${nanoid()}`)
          )
        );
        createEffect(() => {
          monaco.editor.setTheme(codeEditorTheme());
        });
        createEffect(
          on(
            () => props.state.active,
            (active, _, prevElement) => {
              const element: HTMLElement | null =
                (prevElement as HTMLElement) ||
                (document.querySelector(".selected-element-tag") as HTMLElement);

              if (element) {
                setTimeout(() => {
                  if (active) {
                    element.style.height = `${codeEditor.getContentHeight()}px`;

                    return element;
                  } else {
                    element.style.height = "unset";

                    return null;
                  }
                }, 0);
              }

              return element || null;
            }
          )
        );
        createEffect(
          on(editorCode, async (code) => {
            if (code === "<>") return codeEditor.setValue("");

            const selection = codeEditor.getSelection();
            const formattedCode = await processCode(code);

            codeEditor.setValue(formattedCode);
            if (selection) codeEditor.setSelection(selection);
          })
        );
        createEffect(
          on(type, (type, _previousType, handle) => {
            if (typeof handle === "number") clearTimeout(handle);

            if (type) {
              return window.setTimeout(() => {
                setVisible(true);

                const { position } =
                  codeEditor?.getTargetAtClientPoint(coords().x, coords().y) || {};

                if (position) {
                  codeEditor?.setSelection(monaco.Range.fromPositions(position, position));
                }

                scrollIntoView(editorContainer, { behavior: "smooth", block: "nearest" });
                codeEditor?.focus();
              }, 100);
            }
          })
        );
        onCleanup(() => {
          codeEditor.getModel()?.dispose();
          codeEditor.dispose();
        });
      });
      createRenderEffect(
        on(type, (type, previousType) => {
          if (type !== previousType) setVisible(false);
        })
      );
      window.addEventListener("pointerdown", saveLastCoords);
      onCleanup(() => {
        window.removeEventListener("pointerdown", saveLastCoords);
      });

      return (
        <div
          class={clsx(
            "w-full flex items-center justify-start",
            !visible() && "opacity-0 transition-opacity duration-200"
          )}
          contentEditable={false}
        >
          <div class="relative w-full">
            <div
              ref={setEditorContainerRef}
              class="w-full not-prose customized-editor customized-editor-contrast customized-editor-show-keyboard-hidden"
            ></div>
          </div>
        </div>
      );
    }
  };
});

export { ElementMenuEditor };
export * from "./plugin";
import { ElementMenu } from "./component";
import { Extension } from "@tiptap/core";
import { SolidEditor, SolidRenderer } from "@vrite/tiptap-solid";
import { CellSelection } from "@tiptap/pm/tables";
import { createNanoEvents } from "nanoevents";
import { NodeSelection } from "@tiptap/pm/state";
import { Node as PMNode } from "@tiptap/pm/model";

const emitter = createNanoEvents();
const generalMenuContainer = document.createElement("div");

let generalMenu: SolidRenderer<{
  editor: SolidEditor;
  pos: number;
  node: PMNode | null;
  container: HTMLElement | null;
  active: boolean;
}> | null = null;

const handleUpdate = (editor: SolidEditor): void => {
  const { selection } = editor.state;
  const selectedNode = selection.$from.nodeAfter;
  const isNodeSelection = selection instanceof NodeSelection;

  if (!isNodeSelection || !selectedNode || selectedNode.type.name !== "element") {
    generalMenuContainer.style.display = "none";
    generalMenu?.setState((state) => ({ ...state, active: false }));

    return;
  }

  const { view } = editor;
  const node = view.nodeDOM(selection.$from.pos);

  if (!node) return;

  const blockParent = node as HTMLElement;
  const parentPos = document.getElementById("pm-container")?.getBoundingClientRect();
  const childPos = blockParent?.getBoundingClientRect();

  if (!parentPos || !childPos) return;

  const relativePos = {
    top: childPos.top - parentPos.top,
    right: childPos.right - parentPos.right,
    bottom: childPos.bottom - parentPos.bottom,
    left: childPos.left - parentPos.left
  };

  Object.assign(generalMenuContainer.style, {
    width: `${Math.min(childPos?.width || parentPos.width, parentPos.width)}px`,
    top: `${relativePos.top}px`,
    left: `${relativePos.left}px`,
    position: "absolute",
    display: "block"
  });
  generalMenu?.setState(() => ({
    pos: selection.$from.pos,
    node: selectedNode,
    container: blockParent,
    editor,
    active: true
  }));
};
const ElementMenuPlugin = Extension.create({
  name: "elementMenu",
  onCreate() {
    generalMenu = new SolidRenderer(ElementMenu, {
      editor: this.editor as SolidEditor,
      state: {
        pos: 0,
        node: null as PMNode | null,
        container: null as HTMLElement | null,
        editor: this.editor as SolidEditor,
        active: false as boolean
      }
    });
    generalMenuContainer.appendChild(generalMenu.element);
    document.getElementById("pm-container")?.appendChild(generalMenuContainer);
  },
  onBlur() {
    const menuActive = document.activeElement?.contains(generalMenuContainer);

    if (!menuActive) {
      generalMenuContainer.style.display = "none";
      generalMenu?.setState((state) => ({ ...state, active: false }));
    }
  },
  onFocus() {
    const isCellSelection = this.editor.state.selection instanceof CellSelection;

    if (this.editor.isActive("element") && !isCellSelection) {
      generalMenuContainer.style.display = "block";
      generalMenu?.setState((state) => ({ ...state, active: true }));
    }
  },
  onUpdate() {
    handleUpdate(this.editor as SolidEditor);
  },
  onSelectionUpdate() {
    handleUpdate(this.editor as SolidEditor);
  }
});

export { ElementMenuPlugin, emitter };
import { Element as BaseElement, ElementAttributes } from "@vrite/editor";
import { SolidEditor } from "@vrite/tiptap-solid";
import { NodeView } from "@tiptap/core";
import { keymap } from "@tiptap/pm/keymap";
import { Node } from "@tiptap/pm/model";
import { EditorState } from "@tiptap/pm/state";
import { Node as PMNode } from "@tiptap/pm/model";
import { formatCode } from "#lib/code-editor";

const getOpeningTag = async (node: PMNode): Promise<string> => {
  const keyValueProps = Object.entries(node.attrs.props).map(([key, value]) => {
    if (value === true) return key;

    const useBrackets = typeof value !== "string" || value.includes("\n") || value.includes(`"`);

    return `${key}=${useBrackets ? "{" : ""}${JSON.stringify(value)}${useBrackets ? "}" : ""}`;
  });
  const c = `<${node.attrs.type}${keyValueProps.length ? " " : ""}${keyValueProps.join(" ")}>`;
  const codeTagClosed = c.trim().replace(/>$/, "/>") || "";
  const formattedCode = await formatCode(codeTagClosed, "typescript", {
    printWidth: 60,
    trailingComma: "none",
    singleQuote: false
  });

  return formattedCode.replace(/ *?\/>;/gm, node.content.size ? ">" : "/>").trim();
};
const getClosingTag = (node: PMNode): string => node.attrs.type;
const Element = BaseElement.extend({
  addProseMirrorPlugins() {
    const handleDeleteElement = (state: EditorState): boolean => {
      if (this.editor.isActive("element")) {
        const currentDepth = state.selection.$from.depth;

        let node: Node | null = null;
        let pos: number | null = null;

        for (let i = currentDepth; i >= 0; i--) {
          const currentNode = state.selection.$from.node(i);

          if (currentNode.type.name === "element") {
            node = currentNode;
            pos = i > 0 ? state.selection.$from.before(i) : 0;
            break;
          }
        }

        if (
          node &&
          !node.textContent &&
          node.content.childCount === 1 &&
          node.content.firstChild?.type.name === "paragraph" &&
          typeof pos === "number"
        ) {
          this.editor
            .chain()
            .deleteRange({
              from: pos,
              to: pos + node.nodeSize
            })
            .focus()
            .run();

          return true;
        }
      }

      return false;
    };

    return [
      keymap({
        Delete: handleDeleteElement,
        Backspace: handleDeleteElement
      })
    ];
  },
  addNodeView() {
    return (props) => {
      let node = props.node as Node;

      const editor = this.editor as SolidEditor;
      const referenceView = new NodeView(() => {}, props);
      const dom = document.createElement("div");
      const contentContainer = document.createElement("div");
      const content = document.createElement("div");
      const code = document.createElement("code");
      const bottomCode = document.createElement("code");
      const bottomCodeStart = document.createElement("span");
      const bottomCodeKey = document.createElement("span");
      const bottomCodeEnd = document.createElement("span");
      const handleCodeClick = (event: MouseEvent): void => {
        if (typeof props.getPos === "function") {
          editor.commands.setTextSelection(props.getPos());
          editor.commands.setNodeSelection(props.getPos());
        }

        event.preventDefault();
        event.stopPropagation();
      };

      getOpeningTag(props.node).then((openingTag) => (code.textContent = openingTag));
      bottomCodeKey.textContent = getClosingTag(node);
      contentContainer.setAttribute(
        "class",
        "px-3 w-full border-gray-300 dark:border-gray-700 border-l-2 ml-1 py-0 content"
      );
      dom.setAttribute("class", "flex flex-col justify-center items-center relative");
      dom.setAttribute("data-element", "true");
      content.setAttribute("class", "relative content");
      contentContainer.append(content);
      dom.append(code, contentContainer, bottomCode);
      code.setAttribute(
        "class",
        "!whitespace-pre-wrap leading-[26px] min-h-6.5 block w-full !p-0 !bg-transparent !rounded-0 !text-gray-400 !dark:text-gray-400 cursor-pointer"
      );
      bottomCode.setAttribute(
        "class",
        "block w-full !p-0 leading-[26px] min-h-6.5 !rounded-0 !bg-transparent !text-gray-400 !dark:text-gray-400 cursor-pointer"
      );
      code.contentEditable = "false";
      bottomCode.contentEditable = "false";
      bottomCode.append(bottomCodeStart, bottomCodeKey, bottomCodeEnd);
      bottomCodeStart.textContent = "</";
      bottomCodeEnd.textContent = ">";
      code.addEventListener("click", handleCodeClick);
      bottomCode.addEventListener("click", handleCodeClick);

      if (!node.content.size) {
        bottomCode.classList.add("!hidden");
      }

      return {
        dom,
        contentDOM: content,
        ignoreMutation(mutation: MutationRecord | { type: "selection"; target: Element }) {
          if (mutation.type === "selection") {
            return true;
          }

          return referenceView.ignoreMutation(mutation);
        },
        selectNode() {
          contentContainer.classList.add("!border-primary");
          code.classList.add("selected-element-tag");
          bottomCode.classList.remove("!text-gray-400", "!dark:text-gray-400");
          bottomCode.classList.add("!text-[#000000]", "!dark:text-[#DCDCDC]");
          bottomCodeKey.classList.add("!text-[#008080]", "!dark:text-[#3dc9b0]");
        },
        deselectNode() {
          contentContainer.classList.remove("!border-primary");
          code.classList.remove("selected-element-tag");
          bottomCode.classList.add("!text-gray-400", "!dark:text-gray-400");
          bottomCode.classList.remove("!text-[#000000]", "!dark:text-[#DCDCDC]");
          bottomCodeKey.classList.remove("!text-[#008080]", "!dark:text-[#3dc9b0]");
        },
        stopEvent(event) {
          return referenceView.stopEvent(event);
        },
        update(newNode) {
          if (newNode.type.name !== "element") return false;

          node = newNode as Node;
          getOpeningTag(node).then((openingTag) => (code.textContent = openingTag));
          bottomCodeKey.textContent = getClosingTag(node);

          if (node.content.size) {
            bottomCode.classList.remove("!hidden");
          } else {
            bottomCode.classList.add("!hidden");
          }

          return true;
        }
      };
    };
  }
});

export { Element };
export type { ElementAttributes };
import { Component, createEffect, createSignal, on } from "solid-js";
import { Card, Input } from "#components/primitives";
import { EmbedType, createRef, getEmbedId, getEmbedSrc } from "#lib/utils";
  const [menuRef, setMenuRef] = createRef<HTMLElement | null>(null);
  const [left, setLeft] = createSignal(0);
  createEffect(
    on(
      () => props.state.selected,
      () => {
        const element = menuRef();

        if (!element || !element.parentElement) return;

        const { left, width } = element.parentElement.getBoundingClientRect();
        const right = window.innerWidth - left - width;

        setLeft(-Math.abs((right - left) / 2));
      }
    )
  );

    <div
      class="pointer-events-auto flex bg-gray-50 dark:bg-gray-900 !md:bg-transparent border-gray-200 dark:border-gray-700 border-y-2 md:border-0 backdrop-blur-sm md:gap-2 w-screen md:w-auto !md:left-unset relative md:rounded-2xl"
      style={{ left: `${left()}px` }}
      ref={setMenuRef}
    >
      <Card class="flex m-0 border-0 md:border-2 p-1">
        <Input
          wrapperClass="max-w-full min-w-unset md:w-96 flex-1"
          class="w-full bg-transparent m-0 flex-1 text-lg"
          placeholder={getInputPlaceholder(attrs().embed as EmbedType)}
          value={attrs().input || ""}
          disabled={!props.state.editor.isEditable}
          setValue={(value) => {
            props.state.updateAttributes({ input: value, src: getSrc(value) });
          }}
        />
      </Card>
import { Icon } from "#components/primitives";
    <NodeViewWrapper>
                "pt-[35%] w-full rounded-2xl bg-gradient-to-tr flex justify-center items-center relative border-2 border-gray-300 dark:border-gray-700"
            class="object-contain w-full m-0 transition-opacity duration-300 border-2 border-gray-300 dark:border-gray-700 aspect-video min-h-96 rounded-2xl"
        <div
          class={clsx(
            "absolute w-full justify-center items-center -bottom-14 z-1 pointer-events-none",
            selected() ? "grid" : "hidden"
          )}
        >
        </div>
        <div data-type="draggable-item" />
import { Component, createEffect, createSignal, on, onMount } from "solid-js";
import clsx from "clsx";
import { createRef, uploadFile as uploadFileUtil } from "#lib/utils";
import { Card, IconButton, Input, Tooltip } from "#components/primitives";
  const [menuRef, setMenuRef] = createRef<HTMLElement | null>(null);
  const [left, setLeft] = createSignal(0);
  const placeholder = (): string => {
    if (inputMode() === "src") {
      return options().cover ? "Cover image URL" : "Image URL";
    }

    return options().cover ? "Cover alt description" : "Alt description";
  };
      if (uploadedUrl) props.state.updateAttributes({ src: uploadedUrl });
  const inputId = nanoid();
  createEffect(
    on(
      () => props.state.selected,
      () => {
        const element = menuRef();

        if (!element || !element.parentElement) return;

        const { left, width } = element.parentElement.getBoundingClientRect();
        const right = window.innerWidth - left - width;

        setLeft(-Math.abs((right - left) / 2));
      }
    )
  );

    <div
      class={clsx(
        "pointer-events-auto flex bg-gray-50 dark:bg-gray-900 border-gray-200 dark:border-gray-700 border-y-2 backdrop-blur-sm relative !md:left-unset",
        options().cover && "w-full border-t-0",
        !options().cover &&
          "md:gap-2 w-screen md:w-auto md:border-0 md:rounded-2xl !md:bg-transparent"
      )}
      style={{ left: `${left()}px` }}
      ref={setMenuRef}
    >
      <Card class={clsx("flex py-0 m-0 border-0  px-1 gap-1", !options().cover && "md:border-2")}>
        <Tooltip text="Alt">
          <IconButton
            path={mdiText}
            color={inputMode() === "alt" ? "primary" : "contrast"}
            text={inputMode() === "alt" ? "primary" : "soft"}
            variant={inputMode() === "alt" ? "solid" : "text"}
            class="m-0"
            onClick={() => {
              setInputMode("alt");
            }}
          ></IconButton>
        </Tooltip>
        <Tooltip text="Image URL">
          <IconButton
            path={mdiLinkVariant}
            color={inputMode() === "src" ? "primary" : "contrast"}
            text={inputMode() === "src" ? "primary" : "soft"}
            variant={inputMode() === "src" ? "solid" : "text"}
            class="m-0"
            onClick={() => {
              setInputMode("src");
            }}
          ></IconButton>
        </Tooltip>
      </Card>
      <Card class={clsx("p-1 m-0 border-0 flex-1", !options().cover && "md:border-2")}>
        <Input
          wrapperClass={clsx("max-w-full min-w-unset flex-1", !options().cover && "md:w-96 ")}
          class="w-full bg-transparent m-0 flex-1 text-lg"
          placeholder={placeholder()}
          value={attrs()[inputMode()] || ""}
          disabled={!props.state.editor.isEditable}
          setValue={(value) => {
            updateAttribute.clear();
            updateAttribute(inputMode(), value);
        />
      </Card>
      <Card class={clsx("p-1 m-0 border-0", !options().cover && "md:border-2")}>
          <Tooltip text={uploading() ? "Uploading" : "Upload image"} class="mt-1">
            <IconButton
              loading={uploading()}
              path={mdiUpload}
              color="contrast"
              class="m-0"
              text="soft"
              badge
              variant="text"
            ></IconButton>
      </Card>
import { Icon, Loader } from "#components/primitives";
  const [currentSrc, setCurrentSrc] = createSignal("");
    if (currentSrc()) {
    if (!src) {
      setError(false);
      setLoading(false);
      return;
    }
    if (!validateURL(src)) {

      return;

    setCurrentSrc(src);
    <NodeViewWrapper>
            options().cover ? "border-b-2" : "border-2 rounded-2xl"
          <div
            class={clsx(
              "w-full border-gray-200 dark:border-gray-700 flex justify-center items-center overflow-hidden bg-gray-100 dark:bg-gray-800 relative",
              !error() && !loading() && currentSrc() ? "" : "opacity-0 !absolute",
              !options().cover && "rounded-2xl"
            )}
                "overflow-hidden min-w-40 !h-full",
                state().editor.isEditable && "resize"
              )}
              ref={handleNewImageContainer}
              style={{ width: attrs().width }}
            >
              <img
                alt={attrs().alt}
                src={currentSrc()}
                class={clsx("object-contain w-full m-0 transition-opacity duration-300")}
                onLoad={(event) => {
                  setError(false);
                  setLoading(false);

                  const image = event.currentTarget;
                  const w = image.naturalWidth;
                  const h = image.naturalHeight;
                  const aspectRatio = w / h;

                  updateAspectRatio.clear();
                  updateAspectRatio(`${aspectRatio}`);
                }}
                onError={() => {
                  if (!currentSrc()) return;

                  setLoading(false);
                  removeImage();
                  setError(true);
                }}
              />
            </div>
          </div>
          <Show when={loading() || !currentSrc()}>
            <div
              class={clsx(
                "w-full bg-gradient-to-tr flex justify-center items-center relative",
                options().cover ? "min-h-48" : "rounded-2xl"
              style={{
                "padding-top": getPaddingTop()
              }}
              <div class="absolute flex flex-col items-center justify-center font-bold text-white transform -translate-y-1/2 top-1/2">
                <Show when={!loading()} fallback={<Loader class="w-8 h-8" />}>
                  <Show
                    when={!error()}
                    fallback={
                      <>
                        <Icon path={mdiAlertCircle} class="w-16 h-16" />
                        <span class="absolute top-full">Error</span>
                      </>
                    }
                  >
                    <Icon path={mdiImage} class="w-16 h-16" />
                  </Show>
                </Show>
        <div
            "w-full justify-center items-center z-1 pointer-events-none",
            selected() ? "grid" : "hidden",
            options().cover ? "!flex relative" : "absolute -bottom-14"
        </div>
        <div data-type="draggable-item" />
export * from "./element";
export * from "./element-menu";
  block?: App.WorkspaceSettings["blocks"][number];
monaco.editor.defineTheme("light", { ...lightTheme, base: "vs" });
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
  diagnosticCodesToIgnore: [17008, 1005]
});
  @apply !w-full !m-0;
  @apply !border-primary !w-full !z-1 !my-0 !top-0;
}
div:not([data-element="true"]) + .ProseMirror-gapcursor:has(+ div)::after,
div + .ProseMirror-gapcursor:has(+ div:not([data-element="true"]))::after {
  @apply !my-2.5;
  .ProseMirror {
    @apply pb-48;
      @apply border-2 border-gray-300 dark:border-gray-700;
      @apply text-left font-500 border-2 border-gray-300 dark:border-gray-700 relative p-2 vertical-top;
    // @apply my-5;
    //@apply m-0;
  --highlighted-thread: "";
  :where([aria-expanded="false"] > .ProseMirror, .content, blockquote, li) {
    &
      > :where(div, ul, ol, p, blockquote, hr):not(.ProseMirror-gapcursor)
      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6):not([data-element="true"]),
    &
      > :where(div, ul, ol, p, blockquote, hr):not([data-element="true"], .ProseMirror-gapcursor)
      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6),
    &
      > :where(div, ul, ol, p, blockquote, hr):not(.ProseMirror-gapcursor)
      + .ProseMirror-gapcursor
      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6):not([data-element="true"]),
    &
      > :where(div, ul, ol, p, blockquote, hr):not([data-element="true"], .ProseMirror-gapcursor)
      + .ProseMirror-gapcursor
      + :where(div, ul, ol, p, blockquote, hr, h1, h2, h3, h4, h5, h6) {
      @apply mt-5;
    }
  }
  :where(div[data-element="true"]) {
    .content > .ProseMirror-gapcursor:first-child + *,
    .content > :first-child > div > [data-node-view-wrapper="true"],
    .content > .ProseMirror-gapcursor:first-child + * > div > [data-node-view-wrapper="true"] {
    .content > :last-child,
    .content > .ProseMirror-gapcursor:last-child + *,
    .content > :last-child > div > [data-node-view-wrapper="true"],
    .content > .ProseMirror-gapcursor:last-child + * > div > [data-node-view-wrapper="true"] {
    font-family: "JetBrainsMonoVariable", monospace !important;
.ProseMirror .monaco-editor,
.ProseMirror .monaco-editor > *:first-child {

.monaco-editor .editor-widget {
  @apply overflow-hidden;
  border-radius: 0.5rem !important;
}
.monaco-editor .monaco-hover {
  border-radius: 0.5rem !important;
}
.rounded-editor-2xl {
  .monaco-editor,
  .monaco-editor > *:first-child {
    @apply rounded-2xl;
  }
}
.rounded-editor-t-2xl {
  .monaco-editor,
  .monaco-editor > *:first-child {
    border-top-left-radius: calc(1rem - 2px);
    border-top-right-radius: calc(1rem - 2px);
  }
}

.rounded-editor-lg {
  .monaco-editor,
  .monaco-editor > *:first-child {
    @apply rounded-lg;
  }
}
.customized-editor-show-keyboard-hidden {
  [widgetid="editor.contrib.ShowKeyboardWidget"] {
    display: none !important;
  }
}
.customized-editor {
  --customized-editor-background: #f9fafb;
  --customized-editor-widget-background: #f3f4f6;
  .mtk2 {
    color: var(--customized-editor-background);
  }
  .monaco-editor {
    .inputarea.ime-input {
      background-color: var(--customized-editor-background);
    }
    .view-overlays .current-line {
      background-color: var(--customized-editor-widget-background) !important;
      @apply border-gray-300 border-0;
    }
    .view-overlays > *:last-child:first-child .current-line {
      background-color: transparent !important;
    }
    --vscode-editor-background: var(--customized-editor-background);
    --vscode-editorStickyScroll-background: var(--customized-editor-background);
    --vscode-breadcrumb-background: var(--customized-editor-background);
    --vscode-editorGutter-background: var(--customized-editor-background);
    --vscode-editorMarkerNavigation-background: var(--customized-editor-background);

    // Editor Widget
    .find-widget {
      background-color: var(--customized-editor-widget-background);
    }
    --vscode-editorWidget-background: var(--customized-editor-widget-background);
    --vscode-quickInput-background: var(--customized-editor-widget-background);
    --vscode-editorHoverWidget-background: var(--customized-editor-widget-background);
    --vscode-listFilterWidget-background: var(--customized-editor-widget-background);
    --vscode-checkbox-selectBackground: var(--customized-editor-widget-background);
    --vscode-breadcrumbPicker-background: var(--customized-editor-widget-background);
  }
}
.customized-editor-contrast {
  --customized-editor-background: #f3f4f6;
  --customized-editor-widget-background: #f9fafb;
}
.dark {
  .customized-editor {
    --customized-editor-background: #111827;
    --customized-editor-widget-background: #1f2937;
  }
  .customized-editor-contrast {
    --customized-editor-background: #1f2937;
    --customized-editor-widget-background: #111827;
  }
}
  magicLinkAlreadySent: "Wait 1 min before requesting a new magic link",
        <div class="h-full w-full absolute top-0 left-0 bg-gray-100 dark:bg-gray-800 flex justify-center items-center z-12">
            props.setSlug(
              value
                .split("/")
                .map((slugPart) => convertToSlug(slugPart))
                .join("/")
            );
import { AllSelection, NodeSelection } from "@tiptap/pm/state";
  ElementMenuPlugin,
      ElementMenuPlugin,
    const isNodeSelection = selection instanceof NodeSelection;
    if ((!view.hasFocus() && !isNodeSelection) || isAllSelection) {
      isNodeSelection &&
      ["horizontalRule", "image", "codeBlock", "embed", "element"].some((name) => {
      $anchor.depth === 1 ||
      ["element", "blockquote", "listItem", "taskItem"].includes(
        $anchor.node($anchor.depth - 1)?.type?.name
      );
              placement: "bottom",
              popperOptions: { modifiers: [{ name: "flip", enabled: false }] },
import { mdiPlus, mdiKeyboardCloseOutline } from "@mdi/js";
import clsx from "clsx";
import { Component } from "solid-js";
import { SolidEditor } from "@vrite/tiptap-solid";
import { Card, IconButton } from "#components/primitives";

const BlockMenu: Component<{
  class?: string;
  mode: string;
  opened: boolean;
  editor: SolidEditor;
  blur?(): void;
  setMode(mode: string): void;
  setBlockMenuOpened?(opened: boolean): void;
}> = (props) => {
  return (
    <Card
      class={clsx(
        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
        props.class
      )}
    >
      <IconButton
        path={mdiPlus}
        text="soft"
        variant="text"
        label="Insert block"
        onClick={(event) => {
          props.setBlockMenuOpened?.(true);
          event.preventDefault();
          event.stopPropagation();
        }}
      />
      <IconButton
        path={mdiKeyboardCloseOutline}
        text="soft"
        variant="text"
        onClick={(event) => {
          props.blur?.();
          event.preventDefault();
          event.stopPropagation();
        }}
      />
    </Card>
  );
};

export { BlockMenu };
import clsx from "clsx";
import { Component, For, createSignal } from "solid-js";
import { SolidEditor } from "@vrite/tiptap-solid";
import {
  mdiFormatBold,
  mdiFormatItalic,
  mdiFormatStrikethrough,
  mdiCodeTags,
  mdiLinkVariant,
  mdiFormatColorHighlight,
  mdiFormatSubscript,
  mdiFormatSuperscript,
  mdiKeyboardCloseOutline,
  mdiCommentOutline
} from "@mdi/js";
import { nanoid } from "nanoid";
import { Card, IconButton, Tooltip } from "#components/primitives";
import { App, useAuthenticatedUserData, useClient } from "#context";
import { breakpoints } from "#lib/utils";

const FormatMenu: Component<{
  class?: string;
  mode: string;
  opened: boolean;
  editor: SolidEditor;
  contentPieceId?: string;
  blur?(): void;
  setMode(mode: string): void;
}> = (props) => {
  const [activeMarks, setActiveMarks] = createSignal<string[]>([]);
  const { workspaceSettings = () => null } = useAuthenticatedUserData() || {};
  const client = useClient();
  const commentMenuItem = {
    icon: mdiCommentOutline,
    mark: "comment",
    label: "Comment",
    async onClick() {
      if (props.editor.isActive("comment")) {
        props.editor.commands.unsetComment();
      } else {
        const threadFragment = nanoid();

        props.editor.chain().setComment({ thread: threadFragment }).focus().run();

        try {
          await client.comments.createThread.mutate({
            contentPieceId: props.contentPieceId || "",
            fragment: threadFragment
          });
        } catch (error) {
          props.editor.commands.unsetComment();
        }
      }
    }
  };
  const closeKeyboardItem = {
    icon: mdiKeyboardCloseOutline,
    label: "Close keyboard",
    async onClick() {
      props.editor.commands.blur?.();
    }
  };
  const menus = (
    [
      {
        icon: mdiFormatBold,
        mark: "bold",
        label: "Bold"
      },
      {
        icon: mdiFormatItalic,
        mark: "italic",
        label: "Italic"
      },
      {
        icon: mdiFormatStrikethrough,
        mark: "strike",
        label: "Strike"
      },
      {
        icon: mdiCodeTags,
        mark: "code",
        label: "Code"
      },
      {
        icon: mdiLinkVariant,
        mark: "link",
        label: "Link",
        onClick() {
          props.setMode("link");
        }
      },
      { icon: mdiFormatColorHighlight, mark: "highlight", label: "Highlight" },
      { icon: mdiFormatSubscript, mark: "subscript", label: "Subscript" },
      { icon: mdiFormatSuperscript, mark: "superscript", label: "Superscript" },
      ...(props.contentPieceId && breakpoints.md() ? [commentMenuItem] : []),
      ...(breakpoints.md() ? [] : [closeKeyboardItem])
    ] as Array<{ icon: string; mark?: string; label: string; onClick?(): void }>
  ).filter(({ mark }) => {
    if (!mark || mark === "comment") return true;

    if (!workspaceSettings()) {
      return true;
    }

    return workspaceSettings()!.marks.includes(mark as App.WorkspaceSettings["marks"][number]);
  });
  const marks = menus.map((menu) => menu.mark);

  props.editor.on("update", () => {
    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
  });
  props.editor.on("selectionUpdate", () => {
    setActiveMarks(marks.filter((mark) => mark && props.editor.isActive(mark)) as string[]);
  });

  return (
    <Card
      class={clsx(
        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
        props.class
      )}
    >
      <For
        each={menus}
        fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
      >
        {(menu) => {
          const active = (): boolean => {
            return Boolean(menu.mark && activeMarks().includes(menu.mark));
          };

          return (
            <Tooltip text={menu.label} side="bottom" wrapperClass="snap-start">
              <IconButton
                path={menu.icon}
                text={active() ? "primary" : "soft"}
                variant={active() ? "solid" : "text"}
                color={active() ? "primary" : "base"}
                onClick={(event) => {
                  const chain = props.editor.chain();

                  if (menu.onClick) {
                    menu.onClick();
                  } else if (menu.mark) {
                    if (menu.mark !== "code") {
                      chain.unsetCode();
                    }

                    chain.toggleMark(menu.mark).focus().run();
                  }

                  event.preventDefault();
                  event.stopPropagation();
                }}
              />
            </Tooltip>
          );
        }}
      </For>
    </Card>
  );
};

export { FormatMenu };
import { LinkMenu } from "./link";
import { FormatMenu } from "./format";
import { TableMenu } from "./table";
import { BlockMenu } from "./block";
import { SolidEditor } from "@vrite/tiptap-solid";
import { CellSelection } from "@tiptap/pm/tables";
import { Component, createEffect, createSignal, Match, on, Switch } from "solid-js";
import { Ref } from "#lib/utils";

type BubbleMenuMode = "format" | "link" | "table" | "block";
interface BubbleMenuProps {
  editor: SolidEditor;
  opened: boolean;
  contentPieceId?: string;
  class?: string;
  mode?: BubbleMenuMode;
  ref?: Ref<HTMLElement>[1];
  blur?(): void;
  setBlockMenuOpened?(opened: boolean): void;
}

const BubbleMenu: Component<BubbleMenuProps> = (props) => {
  const [mode, setMode] = createSignal<BubbleMenuMode>("format");

  props.editor.on("selectionUpdate", ({ editor }) => {
    const { selection } = editor.state;

    if (props.editor.state.selection instanceof CellSelection) {
      setMode("table");
    } else if (!props.editor.state.selection.empty) {
      setMode("format");
    }
  });
  createEffect(
    on(
      () => props.mode,
      (mode) => {
        setMode((currentMode) => mode || currentMode);
      }
    )
  );
  createEffect(
    on(
      () => props.opened,
      (opened) => {
        if (!opened) {
          setTimeout(() => {
            setMode("format");
          }, 300);
        }
      }
    )
  );

  return (
    <Switch>
      <Match when={mode() === "block"}>
        <BlockMenu
          editor={props.editor}
          mode={mode()}
          opened={props.opened}
          setMode={setMode}
          setBlockMenuOpened={props.setBlockMenuOpened}
          blur={props.blur}
          class={props.class}
        />
      </Match>
      <Match when={mode() === "table"}>
        <TableMenu
          editor={props.editor}
          mode={mode()}
          opened={props.opened}
          setMode={setMode}
          class={props.class}
        />
      </Match>
      <Match when={mode() === "format"}>
        <FormatMenu
          editor={props.editor}
          mode={mode()}
          opened={props.opened}
          setMode={setMode}
          class={props.class}
          contentPieceId={props.contentPieceId}
          blur={props.blur}
        />
      </Match>
      <Match when={mode() === "link"}>
        <LinkMenu
          editor={props.editor}
          mode={mode()}
          opened={props.opened}
          setMode={setMode}
          class={props.class}
        />
      </Match>
    </Switch>
  );
};

export { BubbleMenu };
import { mdiCheck, mdiDelete } from "@mdi/js";
import clsx from "clsx";
import { Component, createEffect, createSignal, on } from "solid-js";
import { SolidEditor } from "@vrite/tiptap-solid";
import { Card, Input, IconButton } from "#components/primitives";
import { createRef } from "#lib/utils";

const LinkMenu: Component<{
  class?: string;
  mode: string;
  opened: boolean;
  editor: SolidEditor;
  setMode(mode: string): void;
}> = (props) => {
  const [link, setLink] = createSignal("");
  const [linkInputRef, setLinkInputRef] = createRef<HTMLInputElement | null>(null);
  const saveLink = (): void => {
    props.editor.chain().unsetCode().setLink({ href: link() }).focus().run();
    props.setMode("format");
  };

  createEffect(
    on(
      () => props.opened,
      (opened) => {
        if (!opened) {
          setLink("");
        }
      }
    )
  );
  createEffect(
    on(
      () => props.mode,
      (mode) => {
        if (mode === "link") {
          setLink(props.editor.getAttributes("link").href || "");
          setTimeout(() => {
            const linkInput = linkInputRef();

            linkInput?.focus();
          }, 300);
        } else {
          setLink("");
        }
      }
    )
  );

  return (
    <Card
      class={clsx(
        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
        props.class
      )}
    >
      <Input
        ref={setLinkInputRef}
        value={link()}
        placeholder="Paste a link..."
        wrapperClass="w-full md:w-auto"
        setValue={(value) => {
          setLink(value);
        }}
        onEnter={saveLink}
        class="py-0 my-0 bg-transparent"
      />
      <IconButton path={mdiCheck} text="soft" variant="text" onClick={saveLink} />
      <IconButton
        path={mdiDelete}
        text="soft"
        variant="text"
        onClick={() => {
          props.editor.chain().unsetLink().focus().run();
          props.setMode("format");
        }}
      />
    </Card>
  );
};

export { LinkMenu };
import {
  mdiTableColumnRemove,
  mdiTableHeadersEyeOff,
  mdiTableMergeCells,
  mdiTableRemove,
  mdiTableRowRemove,
  mdiTableSplitCell
} from "@mdi/js";
import clsx from "clsx";
import { Component, For, Show, createEffect, on } from "solid-js";
import { SolidEditor } from "@vrite/tiptap-solid";
import { CellSelection } from "@tiptap/pm/tables";
import { Card, IconButton, Tooltip } from "#components/primitives";
import { createRef } from "#lib/utils";

const TableMenu: Component<{
  class?: string;
  mode: string;
  opened: boolean;
  editor: SolidEditor;
  setMode(mode: string): void;
}> = (props) => {
  const tableMenus = [
    {
      icon: mdiTableHeadersEyeOff,
      label: "Toggle header cell off",
      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);
          const rowNode = selection.$anchorCell.node(2);

          if (tableNode.child(0) === rowNode) {
            return false;
          }

          return selection.$anchorCell.nodeAfter?.type.name === "tableHeader";
        }

        return false;
      },
      onClick() {
        props.editor.chain().toggleHeaderCell().focus().run();
      }
    },
    {
      icon: mdiTableMergeCells,
      label: "Merge cells",
      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          return selection.$anchorCell.pos !== selection.$headCell.pos;
        }

        return false;
      },
      onClick() {
        props.editor.chain().mergeCells().run();
      }
    },
    {
      icon: mdiTableSplitCell,
      label: "Split cell",
      show() {
        const { selection } = props.editor.state;

        if (
          selection instanceof CellSelection &&
          selection.$anchorCell.pos === selection.$headCell.pos
        ) {
          return (
            selection.$anchorCell.nodeAfter?.attrs.colspan > 1 ||
            selection.$anchorCell.nodeAfter?.attrs.rowspan > 1
          );
        }

        return false;
      },
      onClick() {
        props.editor.chain().splitCell().run();
      }
    },
    {
      icon: mdiTableColumnRemove,
      label: "Delete column(s)",
      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);

          let isSingleColumn = false;

          tableNode.content.forEach((rowNode) => {
            isSingleColumn = rowNode.childCount === 1;
          });

          return !isSingleColumn;
        }

        return true;
      },
      onClick() {
        props.editor.chain().deleteColumn().focus().run();
      }
    },
    {
      icon: mdiTableRowRemove,
      label: "Delete row(s)",

      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);

          if (tableNode.content.childCount === 1) {
            return false;
          }
        }

        return true;
      },
      onClick() {
        props.editor.chain().deleteRow().focus().run();
      }
    },
    {
      icon: mdiTableRemove,
      label: "Delete table",

      show() {
        const { selection } = props.editor.state;

        if (selection instanceof CellSelection) {
          const tableNode = selection.$anchorCell.node(1);

          if (tableNode.childCount === 1) return true;

          let isSingleColumn = false;

          tableNode.content.forEach((rowNode) => {
            isSingleColumn = rowNode.childCount === 1;
          });

          return isSingleColumn;
        }

        return false;
      },
      onClick() {
        props.editor.chain().deleteTable().focus().run();
      }
    }
  ];

  return (
    <Card
      class={clsx(
        "relative flex p-0 overflow-x-auto scrollbar-hidden md:overflow-initial not-prose",
        props.class
      )}
    >
      <For
        each={tableMenus}
        fallback={<span class="px-1.5 py-0.5 text-base">No available options</span>}
      >
        {(menuItem) => {
          return (
            <Show when={!menuItem.show || menuItem.show()}>
              <Tooltip text={menuItem.label} side="bottom" wrapperClass="snap-start">
                <IconButton
                  path={menuItem.icon}
                  text="soft"
                  variant="text"
                  color="base"
                  onClick={(event) => {
                    menuItem.onClick();
                    event.preventDefault();
                    event.stopPropagation();
                  }}
                />
              </Tooltip>
            </Show>
          );
        }}
      </For>
    </Card>
  );
};

export { TableMenu };
export * from "./bubble";
export * from "./comment-threads";
export * from "./export";
export * from "./floating";
export * from "./link-preview";
export * from "./stats";
import { ExtensionDetails, hasPermission, useClient, useExtensions } from "#context";
  const { callFunction } = useExtensions();
                const onConfigureCallback = props.extension.spec.lifecycle?.["on:configure"];

                if (onConfigureCallback) {
                  await callFunction(props.extension.spec, onConfigureCallback, {
                    extensionId: id,
                    token,
                    context: () => ({
                      config: {},
                      spec: props.extension.spec
                    })
                  });
                }
  const { notify } = useNotifications();

            try {
              await client.git.github.initialSync.mutate();
              notify({ text: "Latest content pulled", type: "success" });
            } catch (error) {
              notify({ text: "Couldn't pull content", type: "error" });
            }

                  setMessage("");
import { Component, For, Show, createEffect, createMemo, createResource, on } from "solid-js";
      <TitledCard icon={mdiThemeLightDark} label="Theme">
  const [openedSubsection, setOpenedSubsection] = createSignal<"none">("none");
            color="contrast"
    { label: "Element", icon: mdiCubeOutline, value: "element" }
import { mdiFormatListBulleted, mdiPlusCircle, mdiPuzzle, mdiTrashCan, mdiTune } from "@mdi/js";
  transformer: App.Transformer & { inUse?: boolean; extension?: boolean };
  transformers(): Array<App.Transformer & { inUse?: boolean; extension?: boolean }>;
    transformers: Array<App.Transformer & { inUse?: boolean; extension?: boolean }>;
      <Show
        when={!props.transformer.extension}
        fallback={
          <Tooltip text="Extension" class="mt-1">
            <IconButton path={mdiPuzzle} text="soft" class="m-0" badge />
        }
      >
        <Show when={hasPermission("manageWorkspace")}>
          <div class="flex gap-2">
            <Tooltip text="Delete" class="mt-1" enabled={!props.transformer.inUse}>
              <IconButton
                path={mdiTrashCan}
                loading={loading()}
                disabled={props.transformer.inUse}
                class="m-0"
                text="soft"
                onClick={async () => {
                  setLoading(true);
                  await client.transformers.delete.mutate({ id: props.transformer.id });
                  setLoading(false);
                  props.onDelete?.();
                  notify({ text: "Transformer deleted", type: "success" });
                }}
              />
            </Tooltip>
          </div>
        </Show>
    event: "" as App.WebhookEventName,
            setWebhookData("event", value as App.WebhookEventName);
const webhookEvents: Array<{ label: string; value: App.WebhookEventName }> = [
    "types": ["vite/client", "@vrite/extensions"],
  const proxyTarget = env.PUBLIC_APP_URL;
          target: proxyTarget,
        "/session": { target: proxyTarget, ws: true },
        "/login": { target: proxyTarget, ws: true },
        "/github": { target: proxyTarget, ws: true },
        "/upload": { target: proxyTarget, ws: true }
  "version": "0.3.0",
import { Collection, Db, ObjectId } from "mongodb";
import { UnderscoreID, zodId } from "#lib/mongo";
  extensionId?: ID;
  email: z.string().email().max(320),
const webhookEventName = z.enum([...contentPieceEvents, ...contentGroupEvents, ...memberEvents]);
  event: webhookEventName
type WebhookEventName = z.infer<typeof webhookEventName>;
  webhookEventName,
export type { WebhookEventName, Webhook, FullWebhook };
  email: z.string().email().max(320).optional(),
  "element"
  embeds: z.array(z.enum(embeds))
  extends Omit<z.infer<typeof workspaceSettings>, "id"> {
export type { MetadataField, MetadataSettings, WorkspaceSettings, FullWorkspaceSettings };
import { z } from "zod";
import { Observable } from "@trpc/server/observable";
import { Comment, CommentThread, CommentMember } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type CommentEvent =
  | { action: "createThread"; data: CommentThread }
  | { action: "resolveThread"; data: Pick<CommentThread, "id" | "fragment" | "resolved"> }
  | { action: "deleteThread"; data: Pick<CommentThread, "id" | "fragment"> }
  | {
      action: "createComment";
      data: Omit<Comment, "memberId"> & { member: CommentMember | null };
    }
  | {
      action: "updateComment";
      data: Pick<Comment, "id" | "content">;
    }
  | {
      action: "deleteComment";
      data: Pick<Comment, "id">;
    };

const publishCommentEvent = createEventPublisher<CommentEvent>((contentPieceId) => {
  return `comments:${contentPieceId}`;
});
const subscribeToCommentEvents = (
  ctx: Context,
  contentPieceId: string
): Observable<CommentEvent, unknown> => {
  return createEventSubscription<CommentEvent>(ctx, `comments:${contentPieceId}`);
};

export { publishCommentEvent, subscribeToCommentEvents };
export type { CommentEvent };
import { Observable } from "@trpc/server/observable";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { ContentGroup } from "#database";

type ContentGroupEvent =
  | {
      action: "create";
      data: ContentGroup;
    }
  | {
      action: "update";
      data: Partial<ContentGroup> & { id: string };
    }
  | { action: "delete"; data: { id: string } }
  | { action: "move"; data: ContentGroup }
  | { action: "reorder"; data: { id: string; index: number } };

const publishContentGroupEvent = createEventPublisher<ContentGroupEvent>(
  (workspaceId) => `contentGroups:${workspaceId}`
);
const subscribeToContentGroupEvents = (
  ctx: Context,
  workspaceId: string
): Observable<ContentGroupEvent, unknown> => {
  return createEventSubscription<ContentGroupEvent>(ctx, `contentGroups:${workspaceId}`);
};

export { publishContentGroupEvent, subscribeToContentGroupEvents };
export type { ContentGroupEvent };
import { Observable } from "@trpc/server/observable";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { FullContentPieceWithAdditionalData } from "#database";

type ContentPieceEvent =
  | { action: "delete"; userId: string; data: { id: string } }
  | { action: "create"; userId: string; data: FullContentPieceWithAdditionalData }
  | {
      action: "update";
      userId: string;
      variantId?: string;
      data: Partial<FullContentPieceWithAdditionalData> & { id: string };
    }
  | {
      action: "move";
      userId: string;
      data: {
        contentPiece: FullContentPieceWithAdditionalData;
        nextReferenceId?: string;
        previousReferenceId?: string;
      };
    };

const publishContentPieceEvent = createEventPublisher<ContentPieceEvent>((contentGroupId) => {
  return `contentPieces:${contentGroupId}`;
});
const subscribeToContentPieceEvents = (
  ctx: Context,
  contentGroupId: string
): Observable<ContentPieceEvent, unknown> => {
  return createEventSubscription<ContentPieceEvent>(ctx, `contentPieces:${contentGroupId}`);
};

export { publishContentPieceEvent, subscribeToContentPieceEvents };
export type { ContentPieceEvent };
import { Observable } from "@trpc/server/observable";
import { ContextObject, Extension } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type ExtensionEvent =
  | { action: "delete"; data: { id: string } }
  | { action: "create"; data: Extension & { id: string } }
  | { action: "update"; data: { id: string; config: ContextObject } };

const publishExtensionEvent = createEventPublisher<ExtensionEvent>((workspaceId) => {
  return `extensions:${workspaceId}`;
});
const subscribeToExtensionEvents = (
  ctx: Context,
  workspaceId: string
): Observable<ExtensionEvent, unknown> => {
  return createEventSubscription<ExtensionEvent>(ctx, `extensions:${workspaceId}`);
};

export { publishExtensionEvent, subscribeToExtensionEvents };
export type { ExtensionEvent };
import { Observable } from "@trpc/server/observable";
import { GitData } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type GitDataEvent =
  | {
      action: "configure";
      data: GitData;
    }
  | {
      action: "update";
      data: Partial<GitData>;
    }
  | {
      action: "reset";
      data: {};
    };

const publishGitDataEvent = createEventPublisher<GitDataEvent>((workspaceId) => {
  return `gitData:${workspaceId}`;
});
const subscribeToGitDataEvents = (
  ctx: Context,
  workspaceId: string
): Observable<GitDataEvent, unknown> => {
  return createEventSubscription<GitDataEvent>(ctx, `gitData:${workspaceId}`);
};

export { publishGitDataEvent, subscribeToGitDataEvents };
export type { GitDataEvent };
export * from "./comment";
export * from "./content-group";
export * from "./content-piece";
export * from "./extension";
export * from "./tag";
export * from "./token";
export * from "./transformer";
export * from "./user-settings";
export * from "./user";
export * from "./variant";
export * from "./workspace-membership";
export * from "./webhook";
export * from "./workspace-settings";
export * from "./workspace";
export * from "./git-data";
export * from "./role";
import { Observable } from "@trpc/server/observable";
import { Role } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type RoleEvent =
  | {
      action: "create";
      data: Role;
    }
  | { action: "update"; data: Partial<Role> & { id: string } }
  | { action: "delete"; data: { id: string; newRole: Role } };

const publishRoleEvent = createEventPublisher((workspaceId) => `roles:${workspaceId}`);
const subscribeToRoleEvents = (
  ctx: Context,
  workspaceId: string
): Observable<RoleEvent, unknown> => {
  return createEventSubscription<RoleEvent>(ctx, `roles:${workspaceId}`);
};

export { publishRoleEvent, subscribeToRoleEvents };
export type { RoleEvent };
import { Observable } from "@trpc/server/observable";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { Tag } from "#database";

type TagEvent =
  | { action: "create"; data: Tag }
  | { action: "update"; data: Partial<Tag> & { id: string } }
  | {
      action: "delete";
      data: { id: string };
    };

const publishTagEvent = createEventPublisher<TagEvent>((workspaceId) => `tags:${workspaceId}`);
const subscribeToTagEvents = (ctx: Context, workspaceId: string): Observable<TagEvent, unknown> => {
  return createEventSubscription<TagEvent>(ctx, `tags:${workspaceId}`);
};

export { publishTagEvent, subscribeToTagEvents };
export type { TagEvent };
import { Observable } from "@trpc/server/observable";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { Token } from "#database";

type TokenEvent =
  | {
      action: "create";
      data: Token;
    }
  | { action: "update"; data: Partial<Token> & { id: string } }
  | { action: "delete"; data: { id: string } };

const publishTokenEvent = createEventPublisher<TokenEvent>(
  (workspaceId) => `tokens:${workspaceId}`
);
const subscribeToTokenEvents = (
  ctx: Context,
  workspaceId: string
): Observable<TokenEvent, unknown> => {
  return createEventSubscription<TokenEvent>(ctx, `tokens:${workspaceId}`);
};

export { publishTokenEvent, subscribeToTokenEvents };
export type { TokenEvent };
import { Observable } from "@trpc/server/observable";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { Transformer } from "#database";

type TransformerEvent =
  | {
      action: "create";
      data: Transformer & { id: string };
    }
  | {
      action: "delete";
      data: { id: string };
    };

const publishTransformerEvent = createEventPublisher<TransformerEvent>(
  (workspaceId) => `transformers:${workspaceId}`
);
const subscribeToTransformerEvents = (
  ctx: Context,
  workspaceId: string
): Observable<TransformerEvent, unknown> => {
  return createEventSubscription<TransformerEvent>(ctx, `transformers:${workspaceId}`);
};

export { publishTransformerEvent, subscribeToTransformerEvents };
export type { TransformerEvent };
import { Observable } from "@trpc/server/observable";
import { AppearanceSettings } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type UserSettingsEvent = { action: "update"; data: Partial<AppearanceSettings> };

const publishUserSettingsEvent = createEventPublisher<UserSettingsEvent>(
  (userId) => `userSettings:${userId}`
);
const subscribeToUserSettingsEvents = (
  ctx: Context,
  userId: string
): Observable<UserSettingsEvent, unknown> => {
  return createEventSubscription<UserSettingsEvent>(ctx, `userSettings:${userId}`);
};

export { publishUserSettingsEvent, subscribeToUserSettingsEvents };
export type { UserSettingsEvent };
import { Observable } from "@trpc/server/observable";
import { VerificationDetails, Profile } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type UserEvent = {
  action: "update";
  data: Partial<Profile> & { id: string } & Partial<VerificationDetails>;
};

const publishUserEvent = createEventPublisher<UserEvent>((userId: string) => `user:${userId}`);
const subscribeToUserEvents = (ctx: Context, userId: string): Observable<UserEvent, unknown> => {
  return createEventSubscription<UserEvent>(ctx, `user:${userId}`);
};

export { publishUserEvent, subscribeToUserEvents };
export type { UserEvent };
import { Observable } from "@trpc/server/observable";
import { Variant } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type VariantEvent =
  | {
      action: "create";
      data: Variant & { id: string };
    }
  | {
      action: "update";
      data: Partial<Variant> & { id: string };
    }
  | {
      action: "delete";
      data: { id: string };
    };

const publishVariantEvent = createEventPublisher<VariantEvent>(
  (workspaceId) => `variants:${workspaceId}`
);
const subscribeToVariantEvents = (
  ctx: Context,
  workspaceId: string
): Observable<VariantEvent, unknown> => {
  return createEventSubscription<VariantEvent>(ctx, `variants:${workspaceId}`);
};

export { publishVariantEvent, subscribeToVariantEvents };
export type { VariantEvent };
import { Observable } from "@trpc/server/observable";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";
import { Webhook } from "#database";

type WebhookEvent =
  | {
      action: "create";
      data: Webhook & { id: string };
    }
  | {
      action: "update";
      data: Partial<Webhook> & { id: string };
    }
  | {
      action: "delete";
      data: { id: string };
    };

const publishWebhookEvent = createEventPublisher<WebhookEvent>((workspaceId) => {
  return `webhooks:${workspaceId}`;
});
const subscribeToWebhookEvents = (
  ctx: Context,
  workspaceId: string
): Observable<WebhookEvent, unknown> => {
  return createEventSubscription<WebhookEvent>(ctx, `webhooks:${workspaceId}`);
};

export { publishWebhookEvent, subscribeToWebhookEvents };
export type { WebhookEvent };
import { Observable } from "@trpc/server/observable";
import { Role, WorkspaceMembership } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type WorkspaceMembershipEvent =
  | { action: "create"; data: { id: string; pendingInvite: boolean } & WorkspaceMembership }
  | {
      action: "update";
      data: {
        id: string;
        userId: string;
        role?: Role;
        pendingInvite?: boolean;
        profile?: {
          fullName?: string;
          username?: string;
          avatar?: string;
        };
      } & Partial<WorkspaceMembership>;
    }
  | {
      action: "delete";
      data: { id: string; userId: string };
    };

const publishWorkspaceMembershipEvent = createEventPublisher<WorkspaceMembershipEvent>(
  (workspaceId: string) => `workspaceMemberships:${workspaceId}`
);
const subscribeToWorkspaceMembershipEvents = (
  ctx: Context,
  workspaceId: string
): Observable<WorkspaceMembershipEvent, unknown> => {
  return createEventSubscription<WorkspaceMembershipEvent>(
    ctx,
    `workspaceMemberships:${workspaceId}`
  );
};

export { publishWorkspaceMembershipEvent, subscribeToWorkspaceMembershipEvents };
export type { WorkspaceMembershipEvent };
import { Observable } from "@trpc/server/observable";
import { WorkspaceSettings } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type WorkspaceSettingsEvent = {
  action: "update";
  data: Partial<Omit<WorkspaceSettings, "id">>;
};

const publishWorkspaceSettingsEvent = createEventPublisher<WorkspaceSettingsEvent>(
  (workspaceId) => {
    return `workspaceSettings:${workspaceId}`;
  }
);
const subscribeToWorkspaceSettingsEvents = (
  ctx: Context,
  workspaceId: string
): Observable<WorkspaceSettingsEvent, unknown> => {
  return createEventSubscription<WorkspaceSettingsEvent>(ctx, `workspaceSettings:${workspaceId}`);
};

export { publishWorkspaceSettingsEvent, subscribeToWorkspaceSettingsEvents };
export type { WorkspaceSettingsEvent };
import { Observable } from "@trpc/server/observable";
import { Workspace } from "#database";
import { Context } from "#lib/context";
import { createEventPublisher, createEventSubscription } from "#lib/pub-sub";

type WorkspaceEvent =
  | { action: "update"; data: Partial<Workspace> & { id: string } }
  | { action: "delete"; data: { id: string } };

const publishWorkspaceEvent = createEventPublisher<WorkspaceEvent>((workspaceId) => {
  return `workspace:${workspaceId}`;
});
const subscribeToWorkspaceEvents = (
  ctx: Context,
  workspaceId: string
): Observable<WorkspaceEvent, unknown> => {
  return createEventSubscription<WorkspaceEvent>(ctx, `workspace:${workspaceId}`);
};

export { publishWorkspaceEvent, subscribeToWorkspaceEvents };
export type { WorkspaceEvent };
export * from "./events";
export * from "./routes";
export * from "./server";
import { TokenPermission, getTokensCollection } from "#database";
interface FastifyContext {
}
interface Context extends FastifyContext {
const createFastifyContext = (
  { req, res }: CreateFastifyContextOptions,
  fastify: FastifyInstance
): FastifyContext => {
  return { req, res, fastify };
};
  return {
    ...createFastifyContext({ req, res }, fastify),
    db
  };
export { createContext, createFastifyContext };
export type { FastifyContext, Context };
export {
  createInputContentProcessor as createInputContentProcessorGitHub,
  createOutputContentProcessor as createOutputContentProcessorGitHub
} from "./process-content";
import { AuthenticatedContext } from "../../middleware";
import { UnderscoreID } from "../../mongo";
import { jsonToBuffer, htmlToJSON, bufferToJSON } from "../../processing";
import { InputContentProcessor, OutputContentProcessor } from "../types";
import { ObjectId } from "mongodb";
export { createInputContentProcessor, createOutputContentProcessor };
import { createGenericOutputContentProcessor } from "./process-content";
import { OutputContentProcessor } from "./types";
import { AuthenticatedContext } from "../middleware";
import { UnderscoreID } from "../mongo";
import { jsonToBuffer } from "../processing";
import { ObjectId } from "mongodb";
import { publishGitDataEvent } from "#events";
export * from "./hooks";
export * from "./process-content";
export * from "./github";
export * from "./types";
import { createOutputContentProcessorGitHub, createInputContentProcessorGitHub } from "./github";
import { InputContentProcessor, OutputContentProcessor } from "./types";
import { InputTransformer } from "@vrite/sdk/transformers";
import { ObjectId } from "mongodb";
import { FullContentPiece } from "#database";
import { UnderscoreID } from "#lib/mongo";

interface ProcessInputResult {
  buffer: Buffer;
  contentHash: string;
  metadata: Partial<
    Pick<FullContentPiece, keyof NonNullable<ReturnType<InputTransformer>["contentPiece"]>>
  >;
}
interface OutputContentProcessorInput {
  buffer: Buffer;
  contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
}

interface InputContentProcessor {
  process(inputContent: string): Promise<ProcessInputResult>;
  processBatch(inputContent: string[]): Promise<ProcessInputResult[]>;
}

interface OutputContentProcessor {
  process(input: OutputContentProcessorInput): Promise<string>;
  processBatch(input: OutputContentProcessorInput[]): Promise<string[]>;
}

export type { InputContentProcessor, OutputContentProcessor, OutputContentProcessorInput };
import { z } from "zod";

const hostConfig = z.object({
  githubOAuth: z.boolean(),
  githubApp: z.boolean(),
  sendgrid: z.boolean(),
  smtp: z.boolean(),
  search: z.boolean(),
  aiSearch: z.boolean(),
  extensions: z.boolean()
});

interface HostConfig extends z.infer<typeof hostConfig> {}

export { hostConfig };
export type { HostConfig };
export * from "./auth";
export * from "./context";
export * as errors from "./errors";
export * from "./git-sync";
export * from "./hash";
export * from "./middleware";
export * from "./pub-sub";
export * from "./session";
export * from "./utils";
export * from "./webhooks";
export * from "./workspace";
export * from "./host-config";
import * as errors from "./errors";
import { HostConfig } from "./host-config";
import { Meta, middleware } from "./trpc";
  if (requiredConfig.some((property) => !ctx.fastify.hostConfig[property as keyof HostConfig])) {
export { zodId };
export type { UnderscoreID };
  Element
    Element,
    Element,
import * as errors from "./errors";
import {
  BaseRoleType,
  FullRole,
  Permission,
  getRolesCollection,
  getUserSettingsCollection,
  getWorkspaceMembershipsCollection
} from "#database";
import { HostConfig } from "./host-config";
import { zodId } from "./mongo";
import { ObjectId } from "mongodb";
import {
  WebhookEvent,
  getWebhooksCollection,
  contentGroup,
  contentPiece,
  getContentGroupsCollection,
  workspaceMembership
} from "#database";
      ctx.fastify.log.error("Failed to run webhook", error);
import { publicPlugin } from "#lib";
  getUserSettingsCollection,
  getWebhooksCollection,
  getWorkspaceSettingsCollection,
  getContentsCollection,
  getUsersCollection,
  getCommentThreadsCollection,
  getCommentsCollection,
  getContentPiecesCollection,
  getRolesCollection,
  getTagsCollection,
  getTokensCollection,
import { getWorkspacesCollection, getUsersCollection } from "#database";
import { errors, publicPlugin } from "#lib";
        fastify.log.error(error);
        fastify.log.error(error);
    fastify.log.error("No email service configured");
import { publicPlugin } from "#lib";
import { HostConfig, publicPlugin } from "#lib";
export { hostConfigPlugin };
import { publicPlugin, generateSalt, createSession, createWorkspace } from "#lib";
import { getUserSettingsCollection, getUsersCollection } from "#database";
          codeEditorTheme: "auto",
      fastify.log.error(error);
import { publicPlugin } from "#lib";
import { S3Client, CreateBucketCommand, HeadBucketCommand } from "@aws-sdk/client-s3";
import { publicPlugin } from "#lib";
import { Db, ObjectId } from "mongodb";
import { UnderscoreID, bufferToJSON, publicPlugin } from "#lib";
import { appRouter } from "#routes";
import { publicPlugin, errors } from "#lib";
      const error = e as errors.CustomError;
      const error = e as errors.CustomError;
import { appRouter } from "#routes";
import { publicPlugin, createContext } from "#lib";
import { FullUser, getUsersCollection, getUserSettingsCollection } from "#database";
  UnderscoreID,
  generateSalt,
  processAuth,
  errors,
  isAuthenticated,
  isAuthenticatedUser,
  hashValue,
  verifyValue,
  updateSession,
  procedure,
  router
} from "#lib";
        email: z.string().email().max(320),
        password: z
          .string()
          .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/)
          .min(8)
          .max(128),
        email: z.string().email().max(320),
      const magicLinkSent = await ctx.fastify.redis.get(`user:${user._id}:magicLinkSent`);

      if (magicLinkSent === "true") {
        throw errors.unauthorized("magicLinkAlreadySent");
      }

      await ctx.fastify.redis.set(`user:${user._id}:magicLinkSent`, "true", "EX", 60);
        email: z.string().email().max(320),
        password: z.string().min(8).max(128),
import { UnderscoreID, zodId, isAuthenticated, procedure, router, errors } from "#lib";
  getUsersCollection
import { publishCommentEvent, subscribeToCommentEvents } from "#events";
      publishCommentEvent(ctx, `${input.contentPieceId}`, {
      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
      publishCommentEvent(ctx, `${existingThread.contentPieceId}`, {
      return subscribeToCommentEvents(ctx, input.contentPieceId);
import {
  runGitSyncHook,
  runWebhooks,
  errors,
  UnderscoreID,
  zodId,
  isAuthenticated,
  procedure,
  router
} from "#lib";
import { subscribeToContentGroupEvents, publishContentGroupEvent } from "#events";

      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
        action: "update",
        data: { id, ...update }
      });
      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishContentGroupEvent(ctx, `${ctx.auth.workspaceId}`, {
    return subscribeToContentGroupEvents(ctx, `${ctx.auth.workspaceId}`);
export { contentGroupsRouter };
  getContentPiecesCollection,
  Tag,
  getTagsCollection,
  tag,
  getContentsCollection
} from "#database";
import {
  runWebhooks,
  errors,
  runGitSyncHook,
  procedure,
  router,
  isAuthenticated,
  bufferToJSON,
  DocJSON,
  htmlToJSON,
  jsonToBuffer,
  UnderscoreID,
  zodId,
  stringToRegex
} from "#lib";
import { publishContentPieceEvent, subscribeToContentPieceEvents } from "#events";
  variantIdOrKey?: string
): Promise<{ variantId: ObjectId | null; variantKey: string | null }> => {
  if (!variantIdOrKey) return { variantId: null, variantKey: null };
  const isId = ObjectId.isValid(variantIdOrKey);
    ...(isId && { _id: new ObjectId(variantIdOrKey) }),
    ...(!isId && { key: variantIdOrKey })
  return { variantId: variant._id || null, variantKey: variant.key || null };
      const { variantId, variantKey } = await getVariantDetails(ctx.db, input.variant);
              { slug: contentPiece.slug, variant: variantKey }
      const { variantId, variantKey } = await getVariantDetails(ctx.db, input.variant);
                  { slug: contentPiece.slug, variant: variantKey }
      publishContentPieceEvent(ctx, `${contentPiece.contentGroupId}`, {
      const { variantId, variantKey } = await getVariantDetails(ctx.db, variant);
        if (update.slug) {
          contentPieceUpdates.slug = update.slug
            .split("/")
            .map((slugPart) => convertToSlug(slugPart))
            .join("/");
        } else {
          contentPieceUpdates.slug = convertToSlug(update.title || contentPiece.title);
        }
      publishContentPieceEvent(ctx, `${newContentPiece.contentGroupId}`, {
                { slug: newContentPiece.slug, variant: variantKey }
      publishContentPieceEvent(ctx, `${contentPiece.contentGroupId}`, {
      publishContentPieceEvent(
      return subscribeToContentPieceEvents(ctx, input.contentGroupId);
  getContentPiecesCollection
import { zodId, errors, procedure, router, isAuthenticated, isEnabled } from "#lib";
import { publishExtensionEvent, subscribeToExtensionEvents } from "#events/extension";
import { publishContentPieceEvent } from "#events";
    return subscribeToExtensionEvents(ctx, `${ctx.auth.workspaceId}`);
      publishExtensionEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishExtensionEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishExtensionEvent(ctx, `${ctx.auth.workspaceId}`, {
import { createSyncedPieces } from "./synced-pieces";
import { Binary, ObjectId } from "mongodb";
import {
  createInputContentProcessorGitHub,
  createOutputContentProcessorGitHub,
  OutputContentProcessorInput,
  AuthenticatedContext,
  isAuthenticated,
  isEnabled,
  procedure,
  router,
  errors
} from "#lib";
import { UnderscoreID, zodId } from "#lib";
import {
  publishContentGroupEvent,
  publishGitDataEvent,
  publishWorkspaceSettingsEvent
} from "#events";
      const inputContentProcessor = await createInputContentProcessorGitHub(ctx, gitData);
        const outputContentProcessor = await createOutputContentProcessorGitHub(ctx, gitData);
      const outputContentProcessor = await createOutputContentProcessorGitHub(ctx, gitData);
      const outputContentProcessor = await createOutputContentProcessorGitHub(ctx, gitData);
      const inputContentProcessor = await createInputContentProcessorGitHub(ctx, gitData);
export { githubRouter };
import { createSyncedPieces } from "./synced-pieces";
import { createInputContentProcessorGitHub } from "#lib";
  const inputContentProcessor = await createInputContentProcessorGitHub(ctx, gitData);
import { ObjectId, Binary } from "mongodb";
import { convert as convertToSlug } from "url-slug";
import { FullContentPiece, FullContents } from "#database";
import { InputContentProcessor, UnderscoreID } from "#lib";

const createSyncedPieces = async (
  inputs: Array<{
    path: string;
    content: string;
    workspaceId: ObjectId;
    contentGroupId: ObjectId;
    order: string;
  }>,
  inputContentProcessor: InputContentProcessor
): Promise<
  Array<{
    contentPiece: UnderscoreID<FullContentPiece<ObjectId>>;
    content: UnderscoreID<FullContents<ObjectId>>;
    contentHash: string;
  }>
> => {
  const inputContentProcessorOutput = await inputContentProcessor.processBatch(
    inputs.map((input) => input.content)
  );

  return inputs.map((input, index) => {
    const filename = input.path.split("/").pop() || "";
    const { buffer, contentHash, metadata } = inputContentProcessorOutput[index];
    const { members, tags, date, ...inputMetadata } = metadata;
    const contentPiece: UnderscoreID<FullContentPiece<ObjectId>> = {
      _id: new ObjectId(),
      workspaceId: input.workspaceId,
      contentGroupId: input.contentGroupId,
      order: input.order,
      members: [],
      slug: convertToSlug(filename),
      tags: [],
      title: filename,
      filename,
      ...inputMetadata,
      ...(date && { date: new Date(date) }),
      ...(members && { members: members.map((memberId) => new ObjectId(memberId)) }),
      ...(tags && { tags: tags.map((tagId) => new ObjectId(tagId)) })
    };
    const content = {
      _id: new ObjectId(),
      contentPieceId: contentPiece._id,
      content: new Binary(buffer)
    };

    return {
      contentPiece,
      contentHash,
      content
    };
  });
};

export { createSyncedPieces };
import { publishGitDataEvent, subscribeToGitDataEvents } from "#events";
import { procedure, router, errors, isAuthenticated } from "#lib";
    return subscribeToGitDataEvents(ctx, `${ctx.auth.workspaceId}`);
export { gitRouter };
import { ObjectId } from "mongodb";
import { UnderscoreID } from "#lib";
import { gitRouter } from "./git";
import { Context, createContext } from "#lib";
import { router } from "#lib";
export { appRouter, createContext };
import { zodId, isAuthenticated, procedure, router, updateSessionRole, errors } from "#lib";
import { publishRoleEvent, subscribeToRoleEvents } from "#events";

    return subscribeToRoleEvents(ctx, `${ctx.auth.workspaceId}`);
      publishRoleEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishRoleEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishRoleEvent(ctx, `${ctx.auth.workspaceId}`, {
import { ObjectId } from "mongodb";
import { errors, zodId, procedure, router, isAuthenticated, isEnabled } from "#lib";
import { contentPiece, getContentPiecesCollection } from "#database";
          contentPiece,
      const contentPiecesCollection = getContentPiecesCollection(ctx.db);
      const processedResults = results.data.Get.Content.map(({ _additional, ...result }) => result);
      const contentPieces = await contentPiecesCollection
        .find({
          _id: { $in: processedResults.map(({ contentPieceId }) => new ObjectId(contentPieceId)) }
        })
        .toArray();

      return processedResults.map(({ contentPieceId, content, breadcrumb }) => {
        const { _id, date, contentGroupId, tags, members, ...contentPiece } = contentPieces.find(
          ({ _id }) => _id.toString() === contentPieceId
        )!;
        return {
          contentPieceId,
          breadcrumb,
          content,
          contentPiece: {
            id: `${_id}`,
            contentGroupId: `${contentGroupId}`,
            ...contentPiece,
            ...(date && { date: date.toISOString() }),
            ...(tags && { tags: tags.map((tagId) => `${tagId}`) }),
            ...(members && { members: members.map((members) => `${members}`) })
          }
        };
      });
import { stringToRegex, isAuthenticated, procedure, router, errors, zodId } from "#lib";
import { ExtendedTag, getTagsCollection, tag, getContentPiecesCollection } from "#database";
import { publishTagEvent, subscribeToTagEvents } from "#events";
      publishTagEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishTagEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishTagEvent(ctx, `${ctx.auth.workspaceId}`, {
    return subscribeToTagEvents(ctx, `${ctx.auth.workspaceId}`);
import {
  AuthenticatedContext,
  isAuthenticated,
  procedure,
  router,
  UnderscoreID,
  zodId,
  errors,
  generateSalt,
  hashValue
} from "#lib";
import { Token, FullToken, getTokensCollection, token } from "#database";
import { publishTokenEvent, subscribeToTokenEvents } from "#events";

      publishTokenEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishTokenEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishTokenEvent(ctx, `${ctx.auth.workspaceId}`, {
    return subscribeToTokenEvents(ctx, `${ctx.auth.workspaceId}`);
import { ObjectId } from "mongodb";
import { getGitDataCollection, transformer, getTransformersCollection } from "#database";
import { zodId, errors, procedure, router, isAuthenticated } from "#lib";
import { publishTransformerEvent, subscribeToTransformerEvents } from "#events";
      const extensionId = ctx.req.headers["x-vrite-extension-id"] as string | undefined;
        ...(extensionId && { extensionId: new ObjectId(extensionId) }),
      publishTransformerEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishTransformerEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
    .output(
      z.array(
        transformer.extend({
          inUse: z.boolean().optional(),
          extension: z.boolean().optional()
        })
      )
    )
      return transformers.map(({ _id, workspaceId, extensionId, ...transformerData }) => {
          ...(extensionId && { extension: true }),
    return subscribeToTransformerEvents(ctx, `${ctx.auth.workspaceId}`);
import { zodId, errors, procedure, router, isAuthenticated, isAuthenticatedUser } from "#lib";
import { publishUserSettingsEvent, subscribeToUserSettingsEvents } from "#events";
    .input(appearanceSettings.omit({ codeEditorTheme: true }).partial())
      publishUserSettingsEvent(ctx, `${ctx.auth.userId}`, {
        action: "update",
        data: { ...input, ...(input.uiTheme ? { codeEditorTheme: input.uiTheme } : {}) }
      });
        codeEditorTheme: userSettings.uiTheme,
    return subscribeToUserSettingsEvents(ctx, `${ctx.auth.userId}`);
import { procedure, router, errors, UnderscoreID, isAuthenticated, hashValue } from "#lib";
import { FullUser, getUsersCollection, profile, verificationDetails } from "#database/users";
import { publishUserEvent, subscribeToUserEvents } from "#events";
    return subscribeToUserEvents(ctx, `${ctx.auth.userId}`);
      publishUserEvent(ctx, `${ctx.auth.userId}`, {
import {
  procedure,
  router,
  errors,
  extractPreviewDataFromOpenGraph,
  hostConfig,
  HostConfig
} from "#lib";
import { ObjectId } from "mongodb";
import { zodId, errors, procedure, router, isAuthenticated } from "#lib";
import { publishVariantEvent, subscribeToVariantEvents } from "#events";
      publishVariantEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishVariantEvent(ctx, `${ctx.auth.workspaceId}`, { action: "update", data: input });
      publishVariantEvent(ctx, `${ctx.auth.workspaceId}`, { action: "delete", data: input });
    return subscribeToVariantEvents(ctx, `${ctx.auth.workspaceId}`);
  getUsersCollection,
  getUserSettingsCollection,
} from "#database";
import {
  runWebhooks,
  verifyValue,
  isAuthenticatedUser,
  createSession,
  errors,
  createWorkspace,
  procedure,
  router
} from "#lib";
import { publishUserEvent, publishWorkspaceMembershipEvent } from "#events";
          codeEditorTheme: "auto",
        ctx.fastify.log.error(error);
import { FullWebhook, Webhook, getWebhooksCollection, webhook } from "#database";
import { errors, isAuthenticated, UnderscoreID, zodId, procedure, router } from "#lib";
import { publishWebhookEvent, subscribeToWebhookEvents } from "#events";

      publishWebhookEvent(ctx, `${ctx.auth.workspaceId}`, {
    return subscribeToWebhookEvents(ctx, `${ctx.auth.workspaceId}`);
      publishWebhookEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishWebhookEvent(ctx, `${ctx.auth.workspaceId}`, {
  contentPieceMember,
  workspaceMembership,
  getWorkspacesCollection,
  workspace
import {
  AuthenticatedContext,
  isAuthenticated,
  procedure,
  router,
  isAuthenticatedUser,
  updateSessionUser,
  runWebhooks,
  errors,
  UnderscoreID,
  generateSalt,
  hashValue,
  stringToRegex,
  zodId
} from "#lib";
import { publishWorkspaceMembershipEvent, subscribeToWorkspaceMembershipEvents } from "#events";

  publishWorkspaceMembershipEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishWorkspaceMembershipEvent(ctx, `${ctx.auth.workspaceId}`, {
        email: z.string().email().max(320),
      publishWorkspaceMembershipEvent(ctx, `${ctx.auth.workspaceId}`, {
    return subscribeToWorkspaceMembershipEvents(ctx, `${ctx.auth.workspaceId}`);
  workspaceSettings
import { errors, isAuthenticated, procedure, router } from "#lib";
import { subscribeToWorkspaceSettingsEvents, publishWorkspaceSettingsEvent } from "#events";
        embeds: workspaceSettings.embeds
    return subscribeToWorkspaceSettingsEvents(ctx, `${ctx.auth.workspaceId}`);
        .omit({ id: true, prettierConfig: true })
      publishWorkspaceSettingsEvent(ctx, `${ctx.auth.workspaceId}`, {
export { workspaceSettingsRouter };
import {
  errors,
  createWorkspace,
  deleteWorkspace,
  isAuthenticated,
  isAuthenticatedUser,
  procedure,
  router
} from "#lib";
import { getWorkspacesCollection, workspace, getUsersCollection } from "#database";
import { subscribeToWorkspaceEvents, publishWorkspaceEvent } from "#events";
    return subscribeToWorkspaceEvents(ctx, `${ctx.auth.workspaceId}`);
      publishWorkspaceEvent(ctx, `${ctx.auth.workspaceId}`, {
      publishWorkspaceEvent(ctx, `${ctx.auth.workspaceId}`, {
import {
  gitSyncPlugin,
  hostConfigPlugin,
  searchPlugin,
  databasePlugin,
  pubSubPlugin,
  sessionPlugin,
  mailPlugin,
  s3Plugin,
  OAuthPlugin
} from "#plugins";
const createServer = async (
  pluginOptions: Partial<{
    database: boolean;
    pubSub: boolean;
    storage: boolean;
    auth: boolean;
    email: boolean;
    gitSync: boolean;
    search: boolean;
  }>
): Promise<FastifyInstance> => {
      schema: zodToJsonSchema(envSchema)

  if (pluginOptions.database) {
    await server.register(mongoPlugin, {
    });
    await server.register(databasePlugin);
  }

  if (pluginOptions.pubSub) {
    await server
      .register(redisPlugin, { url: server.config.REDIS_URL })
      .register(redisPlugin, { url: server.config.REDIS_URL, namespace: "sub" });
    await server.register(pubSubPlugin);
  }

  if (pluginOptions.storage) {
    await server.register(s3Plugin);
  }

  if (pluginOptions.auth) {
    await server
      .register(cookiePlugin, { secret: server.config.SECRET })
      .register(jwtPlugin, {
        secret: server.config.SECRET,
        cookie: { cookieName: "accessToken", signed: true }
      })
      .register(sessionPlugin)
      .register(OAuthPlugin);
  }

  if (pluginOptions.email) {
    await server.register(mailPlugin);
  }

  if (pluginOptions.gitSync) {
    await server.register(gitSyncPlugin);
  }

  if (pluginOptions.search) {
    await server.register(searchPlugin);
  }
  suggestionsBoxClass?: string;
            `:base-2: absolute z-50 flex flex-col p-1 overflow-hidden transition-all duration-300 transform shadow-2xl w-full`,
            props.suggestionsBoxClass
  if (typeof document !== "undefined") {
    document.body.addEventListener("pointermove", onPointerMove);
  }


    if (typeof document !== "undefined") {
      document.body.removeEventListener("pointermove", onPointerMove);
    }
  title?: string;
  meta?: string;
      },
      title: {
        default: null,
        parseHTML: (element) => {
          return element.getAttribute("data-title");
        }
      },
      meta: {
        default: null,
        parseHTML: (element) => {
          return element.getAttribute("data-meta");
        }
          "class": node.attrs.lang ? `language-${node.attrs.lang}` : null,
          "data-title": node.attrs.title,
          "data-meta": node.attrs.meta
import { ExtendedRegExpMatchArray, Node, mergeAttributes, wrappingInputRule } from "@tiptap/core";
import { nodeInputRule } from "#node-input-rule";

interface ElementAttributes {
  type?: string;
  props: Record<string, unknown>;
}

declare module "@tiptap/core" {
  interface Commands<ReturnType> {
    Element: {
      setElement: (attrs?: ElementAttributes) => ReturnType;
      toggleElement: (attrs?: ElementAttributes) => ReturnType;
      unsetElement: () => ReturnType;
    };
  }
}

const Element = Node.create({
  name: "element",
  content: "block*",
  group: "block",
  isolating: true,
  defining: true,
  selectable: true,
  addAttributes() {
    return {
      props: {
        default: {},
        parseHTML: (element) => {
          return JSON.parse(element.getAttribute("data-props") || "{}");
        }
      },
      type: {
        default: "Element",
        parseHTML: (element) => {
          return element.getAttribute("data-type");
        }
      }
    };
  },
  parseHTML() {
    return [
      {
        tag: "div[data-element=true]"
      }
    ];
  },
  renderHTML({ node, HTMLAttributes }) {
    return [
      "div",
      mergeAttributes(HTMLAttributes, {
        "data-element": "true",
        "data-type": node.attrs.type,
        "data-props": JSON.stringify(node.attrs.props)
      }),
      0
    ];
  },
  addCommands() {
    return {
      setElement: (attrs) => {
        return ({ commands }) => {
          return commands.insertContent({
            type: this.name,
            attrs: {
              type: "Element",
              props: {},
              ...attrs
            }
            // content: [{ type: "paragraph" }]
          });
        };
      },
      toggleElement: (attrs) => {
        return ({ commands }) => {
          return commands.toggleWrap(this.name, attrs);
        };
      },
      unsetElement: () => {
        return ({ commands }) => {
          return commands.lift(this.name);
        };
      }
    };
  },
  addInputRules() {
    const getAttributes = (input: ExtendedRegExpMatchArray): Record<string, any> => {
      const [code] = input;
      const tagRegex = /^<(\w+?)(?:\s|\n|\/|>)/;
      const [, tag] = tagRegex.exec(code.trim()) || [];

      if (tag && tag !== "undefined") {
        return { type: tag, props: {} };
      }

      return {};
    };

    return [
      nodeInputRule({
        find: /^<.*?.+?\/>$/,
        type: this.type,
        getAttributes
      }),
      wrappingInputRule({
        find: /^<.*?.+?>$/,
        type: this.type,
        joinPredicate: () => false,
        getAttributes
      })
    ];
  }
});

export { Element };
export type { ElementAttributes };
  draggable: true,
  draggable: true,
export * from "./element";
const renderEmail = <T extends keyof typeof templateMap>(
};

type RenderEmail = typeof renderEmail;
import { ExtensionBaseContext } from "@vrite/extensions";

const configure = async (context: ExtensionBaseContext): Promise<void> => {
  const transformers = await context.client.transformers.list();
  const mdxTransformer = transformers.find((transformer) => {
    return (
      transformer.label === "MDX" &&
      transformer.input === "https://extensions.vrite.io/mdx/input" &&
      transformer.output === "https://extensions.vrite.io/mdx/output"
    );
  });

  if (!mdxTransformer) {
    await context.client.transformers.create({
      input: "https://extensions.vrite.io/mdx/input",
      output: "https://extensions.vrite.io/mdx/output",
      maxBatchSize: 100,
      label: "MDX"
    });
  }
};

export default configure;
import { ExtensionGeneralContext } from "@vrite/extensions";

const uninstall = async (context: ExtensionGeneralContext): Promise<void> => {
  const transformers = await context.client.transformers.list();

  if (transformers.length > 0) {
    const mdxTransformer = transformers.find((transformer) => {
      return (
        transformer.label === "MDX" &&
        transformer.input === "https://extensions.vrite.io/mdx/input" &&
        transformer.output === "https://extensions.vrite.io/mdx/output"
      );
    });

    if (mdxTransformer) {
      await context.client.transformers.delete({
        id: mdxTransformer?.id
      });
    }
  }
};

export default uninstall;
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
    <path
        d="M20.3,16.5l-3.9,3.9-4-3.9,1.1-1.1,2.1,2.1V11.8h1.5v5.8l2.1-2.1ZM3.5,15.7l2.7,2.7L9,15.7v4.4h1.5V12L6.2,16.3,2,12v8.1H3.5Z"
        style="fill:#d2d2d2" />
    <path d="M28.8,20l-3.1-3.1L22.6,20l-1-1.1,3.1-3.1-3.2-3.2,1.1-1,3.1,3.2,3.2-3.2,1.1,1-3.2,3.2,3.1,3.1Z"
        style="fill:#f9ac00" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
    <path
        d="M20.3,16.5l-3.9,3.9-4-3.9,1.1-1.1,2.1,2.1V11.8h1.5v5.8l2.1-2.1ZM3.5,15.7l2.7,2.7L9,15.7v4.4h1.5V12L6.2,16.3,2,12v8.1H3.5Z"
        style="fill:#00000" />
    <path d="M28.8,20l-3.1-3.1L22.6,20l-1-1.1,3.1-3.1-3.2-3.2,1.1-1,3.1,3.2,3.2-3.2,1.1,1-3.2,3.2,3.1,3.1Z"
        style="fill:#f9ac00" />
</svg>
{
  "name": "mdx",
  "displayName": "MDX",
  "description": "Adds MDX transformers to Git sync",
  "permissions": ["workspace:write", "workspace:read"],
  "lifecycle": {
    "on:uninstall": "uninstall",
    "on:configure": "configure"
  }
}
  "version": "0.3.0",
import {
  ContentPiece,
  ContentPiecesEndpoints,
  createContentPiecesEndpoints
} from "./content-pieces";
interface SearchResult {
  contentPieceId: string;
  contentPiece: Omit<ContentPiece, "locked" | "content" | "coverWidth">;
  breadcrumb: string[];
  content: string;
}
    contentPieceId?: string;
  }): Promise<SearchResult[]>;
  useSignal(signal: AbortSignal | null): Client;
  reconfigure(config: ClientConfig): Client;
  const { sendRequest, reconfigure, getConfig, getSignal, useSignal } = createAPIFetcher(config);
  const client: Client = {
      getSignal()?.addEventListener("abort", () => {
        source.close();
      });
      useSignal(null);
    useSignal(signal) {
      useSignal(signal);

      return client;
    },
    reconfigure(config) {
      reconfigure(config);

      return client;
    }

  return client;
export type { Client, SearchResult };
export type { Client, SearchResult } from "./client";
  useSignal: (signal: AbortSignal | null) => void;
  getSignal: () => AbortSignal | null;
  let signal: AbortSignal | null = null;
          signal,
      signal = null;

  const useSignal = (newSignal: AbortSignal | null): void => {
    signal = newSignal;
  };
  const getSignal = (): AbortSignal | null => {
    return signal;
  };
  return { sendRequest, reconfigure, useSignal, getConfig, getSignal };
    | ElementNode
type ElementNode = {
  type: "element";
  attrs: {
    type: string;
    props: Record<string, any>;
    | ElementNode
    lang?: string;
    meta?: string;
    title?: string;
    | ElementNode
  element: ElementNode;
      JSONContentNode["listItem" | "taskItem" | "blockquote" | "doc" | "element"]
          case "element":
              child as JSONContentNodeWalker<JSONContentNode["element"]>
      case "element":
          "data-type": nodeWalker.node.attrs?.type
        })}>${(nodeWalker as JSONContentNodeWalker<JSONContentNode["element"]>).children
        version: 6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.2.2)
        version: 6.2.0(eslint@8.45.0)(typescript@5.2.2)
        version: 3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.2.2)
        version: 0.12.1(eslint@8.45.0)(typescript@5.2.2)
        version: 5.2.2
        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.4)
        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.4)
      '@prettier/sync':
        specifier: ^0.3.0
        version: 0.3.0(prettier@3.0.2)
      '@types/hast':
        specifier: ^3.0.1
        version: 3.0.1
      '@types/html-to-text':
        specifier: ^9.0.1
        version: 9.0.1
      '@types/js-yaml':
        specifier: ^4.0.6
        version: 4.0.6
      '@types/mdast':
        specifier: ^4.0.1
        version: 4.0.1
      dayjs:
        specifier: ^1.11.9
        version: 1.11.9
      hast-util-to-html:
        specifier: ^9.0.0
        version: 9.0.0
      html-to-text:
        specifier: ^9.0.5
        version: 9.0.5
      js-yaml:
        specifier: ^4.1.0
        version: 4.1.0
      mdast-util-from-markdown:
        specifier: ^2.0.0
        version: 2.0.0
      mdast-util-frontmatter:
        specifier: ^2.0.1
        version: 2.0.1
      mdast-util-gfm:
        specifier: ^3.0.0
        version: 3.0.0
      mdast-util-mdx:
        specifier: ^3.0.0
        version: 3.0.0
      mdast-util-to-hast:
        specifier: ^13.0.2
        version: 13.0.2
      micromark-extension-frontmatter:
        specifier: ^2.0.0
        version: 2.0.0
      micromark-extension-gfm:
        specifier: ^3.0.0
        version: 3.0.0
      micromark-extension-mdxjs:
        specifier: ^2.0.0
        version: 2.0.0
      prettier:
        specifier: ^3.0.2
        version: 3.0.2
      remark:
        specifier: ^15.0.1
        version: 15.0.1
      remark-mdx:
        specifier: ^2.3.0
        version: 2.3.0
      remark-parse:
        specifier: ^11.0.0
        version: 11.0.0
        version: 1.2.0(@trpc/server@10.35.0)(zod@3.22.4)
      unist-util-visit:
        specifier: ^5.0.0
        version: 5.0.0
      '@astrojs/mdx':
        specifier: ^1.1.1
        version: 1.1.1(astro@3.1.0)
      '@solid-primitives/scheduled':
        specifier: ^1.4.0
        version: 1.4.0(solid-js@1.7.11)
      '@vrite/sdk':
        specifier: workspace:*
        version: link:../../packages/sdk/javascript
      astro-auto-import:
        specifier: ^0.3.1
        version: 0.3.1(astro@3.1.0)
      astro-icon:
        specifier: ^0.8.1
        version: 0.8.1
      seamless-scroll-polyfill:
        specifier: ^2.3.4
        version: 2.3.4
      tinykeys:
        specifier: ^2.1.0
        version: 2.1.0
        version: 0.55.7(postcss@8.4.31)(vite@4.4.9)
      url-slug:
        specifier: ^4.0.1
        version: 4.0.1
        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
        version: 2.2.1(@babel/core@7.23.0)(solid-js@1.7.11)(vite@4.4.9)
        version: 0.55.7(postcss@8.4.31)(vite@4.4.9)
        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
        version: 10.16.2(solid-js@1.7.11)
        version: 2.0.15(solid-js@1.7.11)
        version: 0.3.15(solid-js@1.7.11)
        version: 2.2.3(solid-js@1.7.11)
        version: 1.3.2(solid-js@1.7.11)
        version: 1.4.0(solid-js@1.7.11)
        version: 0.8.2(solid-js@1.7.11)
        version: 1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.11)
        specifier: ^0.43.0
        version: 0.43.0
        version: 1.7.11
        version: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
        version: 5.2.2
        version: 0.55.7(postcss@8.4.31)(vite@4.4.9)
        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
        version: 2.7.0(solid-js@1.7.11)(vite@4.4.9)
        version: 4.2.0(typescript@5.2.2)(vite@4.4.9)
        version: 1.4.0(typescript@5.2.2)
        version: 5.2.2
        version: 1.4.0(graphql@16.8.1)
        version: 2.0.15(solid-js@1.7.11)
        version: 2.2.3(solid-js@1.7.11)
        version: 1.7.11
        version: 2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.1.11)(@tiptap/pm@2.1.8)
        version: 1.7.11
        version: 2.10.15
        version: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
      '@jridgewell/trace-mapping': 0.3.19
  /@astrojs/compiler@2.2.0:
    resolution: {integrity: sha512-JvmckEJgg8uXUw8Rs6VZDvN7LcweCHOdcxsCXpC+4KMDC9FaB5t9EH/NooSE+hu/rnACEhsXA3FKmf9wnhb7hA==}
      '@jridgewell/trace-mapping': 0.3.19
      '@vscode/emmet-helper': 2.9.2
      vscode-css-languageservice: 6.2.9
      vscode-html-languageservice: 5.1.0
      vscode-languageserver-protocol: 3.17.5
      vscode-languageserver-textdocument: 1.0.11
      vscode-languageserver-types: 3.17.5
      vscode-uri: 3.0.8
  /@astrojs/markdown-remark@3.2.0(astro@3.1.0):
    resolution: {integrity: sha512-jigyLfefUZPKgVmmraCkVpdUuFH1R3SrpgQO13axsgwLDBgkggaQpNR5Ag4O9PDualeBtbdt30aYSfvnBKx9Hg==}
      astro: ^3.1.0
      '@astrojs/prism': 3.0.0
      astro: 3.1.0(sass@1.64.1)
      github-slugger: 2.0.0
      import-meta-resolve: 3.0.0
      mdast-util-definitions: 6.0.0
  /@astrojs/markdown-remark@3.2.1(astro@3.1.0):
    resolution: {integrity: sha512-Z4YNMRtgFZeHhB29uCZl0B9MbMZddW9ZKCNucapoysbvygbDFF1gGtqpVnf+Lyv3rUBHwM/J5qWB2MSZuTuz1g==}
      astro: ^3.2.3
    dev: false

  /@astrojs/mdx@1.1.1(astro@3.1.0):
    resolution: {integrity: sha512-3dfL12ZqI6NCjx0iVOYVSyljlVgsxds5mOhe78xoCVjyqSpZZsxzz4Dt5WfGxDon2nc2bD6XGiZ2PIy8fmX6NQ==}
    engines: {node: '>=18.14.1'}
    peerDependencies:
      astro: ^3.2.3
    dependencies:
      '@astrojs/markdown-remark': 3.2.1(astro@3.1.0)
      '@mdx-js/mdx': 2.3.0
      acorn: 8.10.0
      astro: 3.1.0(sass@1.64.1)
      es-module-lexer: 1.3.1
      estree-util-visit: 1.2.1
      github-slugger: 2.0.0
      gray-matter: 4.0.3
      hast-util-to-html: 8.0.4
      kleur: 4.1.5
      rehype-raw: 6.1.1
      remark-gfm: 3.0.1
      remark-smartypants: 2.0.0
      source-map: 0.7.4
      unist-util-visit: 4.1.2
      vfile: 5.3.7
    transitivePeerDependencies:
      - supports-color
    dev: false
      zod: 3.21.4
  /@astrojs/solid-js@2.2.1(@babel/core@7.23.0)(solid-js@1.7.11)(vite@4.4.9):
      babel-preset-solid: 1.7.12(@babel/core@7.23.0)
      ci-info: 3.9.0
      undici: 5.25.4
      ci-info: 3.9.0
      is-wsl: 3.1.0
      undici: 5.25.4
      undici: 5.25.4
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      '@babel/highlight': 7.22.20
  /@babel/compat-data@7.22.20:
    resolution: {integrity: sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==}
  /@babel/core@7.23.0:
    resolution: {integrity: sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==}
      '@babel/generator': 7.23.0
      '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0)
      '@babel/helpers': 7.23.1
      '@babel/parser': 7.23.0
      '@babel/traverse': 7.23.0
      '@babel/types': 7.23.0
      convert-source-map: 2.0.0
  /@babel/eslint-parser@7.22.15(@babel/core@7.23.0)(eslint@8.45.0):
    resolution: {integrity: sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==}
      '@babel/core': ^7.11.0
      '@babel/core': 7.23.0
  /@babel/generator@7.23.0:
    resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==}
      '@babel/types': 7.23.0
      '@jridgewell/trace-mapping': 0.3.19
      '@babel/types': 7.23.0
      '@babel/compat-data': 7.22.20
      browserslist: 4.22.1
  /@babel/helper-create-class-features-plugin@7.22.15(@babel/core@7.23.0):
    resolution: {integrity: sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==}
      '@babel/core': 7.23.0
      '@babel/helper-environment-visitor': 7.22.20
      '@babel/helper-function-name': 7.23.0
      '@babel/helper-member-expression-to-functions': 7.23.0
      '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.0)
      '@babel/helper-split-export-declaration': 7.22.6
  /@babel/helper-environment-visitor@7.22.20:
    resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
  /@babel/helper-function-name@7.23.0:
    resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
      '@babel/template': 7.22.15
      '@babel/types': 7.23.0
      '@babel/types': 7.23.0
  /@babel/helper-member-expression-to-functions@7.23.0:
    resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==}
      '@babel/types': 7.23.0
      '@babel/types': 7.23.0
      '@babel/types': 7.23.0
  /@babel/helper-module-transforms@7.23.0(@babel/core@7.23.0):
    resolution: {integrity: sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==}
      '@babel/core': 7.23.0
      '@babel/helper-environment-visitor': 7.22.20
      '@babel/helper-validator-identifier': 7.22.20
      '@babel/types': 7.23.0
  /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.0):
    resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==}
    peerDependencies:
      '@babel/core': ^7.0.0
      '@babel/core': 7.23.0
      '@babel/helper-environment-visitor': 7.22.20
      '@babel/helper-member-expression-to-functions': 7.23.0
      '@babel/types': 7.23.0
      '@babel/types': 7.23.0
      '@babel/types': 7.23.0
  /@babel/helper-validator-identifier@7.22.20:
    resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
  /@babel/helpers@7.23.1:
    resolution: {integrity: sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==}
      '@babel/traverse': 7.23.0
      '@babel/types': 7.23.0
  /@babel/highlight@7.22.20:
    resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==}
      '@babel/helper-validator-identifier': 7.22.20
  /@babel/parser@7.23.0:
    resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==}
      '@babel/types': 7.23.0
  /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.0):
      '@babel/core': 7.23.0
  /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.23.0):
      '@babel/core': 7.23.0
  /@babel/plugin-transform-modules-commonjs@7.23.0(@babel/core@7.23.0):
    resolution: {integrity: sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==}
      '@babel/core': 7.23.0
      '@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.0)
  /@babel/plugin-transform-react-jsx@7.22.15(@babel/core@7.23.0):
    resolution: {integrity: sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==}
      '@babel/core': 7.23.0
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0)
      '@babel/types': 7.23.0
  /@babel/plugin-transform-typescript@7.22.15(@babel/core@7.23.0):
    resolution: {integrity: sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==}
      '@babel/core': 7.23.0
      '@babel/helper-create-class-features-plugin': 7.22.15(@babel/core@7.23.0)
      '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.23.0)
  /@babel/preset-typescript@7.23.0(@babel/core@7.23.0):
    resolution: {integrity: sha512-6P6VVa/NM/VlAYj5s2Aq/gdVg8FSENCg3wlZ6Qau9AcPaoF5LbN1nyGlR9DTRIw9PpxI94e+ReydsJHcjwAweg==}
      '@babel/core': 7.23.0
      '@babel/helper-validator-option': 7.22.15
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0)
      '@babel/plugin-transform-modules-commonjs': 7.23.0(@babel/core@7.23.0)
      '@babel/plugin-transform-typescript': 7.22.15(@babel/core@7.23.0)
  /@babel/runtime@7.23.1:
    resolution: {integrity: sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==}
      regenerator-runtime: 0.14.0
  /@babel/standalone@7.23.1:
    resolution: {integrity: sha512-a4muOYz1qUaSoybuUKwK90mRG4sf5rBeUbuzpuGLzG32ZDE/Y2YEebHDODFJN+BtyOKi19hrLfq2qbNyKMx0TA==}
      '@babel/parser': 7.23.0
      '@babel/types': 7.23.0
  /@babel/traverse@7.23.0:
    resolution: {integrity: sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==}
      '@babel/generator': 7.23.0
      '@babel/helper-environment-visitor': 7.22.20
      '@babel/helper-function-name': 7.23.0
      '@babel/parser': 7.23.0
      '@babel/types': 7.23.0
  /@babel/types@7.23.0:
    resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==}
      '@babel/helper-validator-identifier': 7.22.20
  /@bufbuild/connect-node@0.9.1(@bufbuild/protobuf@1.3.3):
    deprecated: Connect has moved to its own org @connectrpc and has a stable v1. Run `npx @connectrpc/connect-migrate@latest` to update. See https://github.com/connectrpc/connect-es/releases/tag/v0.13.1 for details.
      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.3)
      '@bufbuild/protobuf': 1.3.3
      headers-polyfill: 3.3.0
  /@bufbuild/connect@0.9.1(@bufbuild/protobuf@1.3.3):
    deprecated: Connect has moved to its own org @connectrpc and has a stable v1. Run `npx @connectrpc/connect-migrate@latest` to update. See https://github.com/connectrpc/connect-es/releases/tag/v0.13.1 for details.
      '@bufbuild/protobuf': 1.3.3
  /@bufbuild/protobuf@1.3.3:
    resolution: {integrity: sha512-AoHSiIpTFF97SQgmQni4c+Tyr0CDhkaRaR2qGEJTEbauqQwLRpLrd9yVv//wVHOSxr/b4FJcL54VchhY6710xA==}
  /@esbuild/android-arm64@0.19.4:
    resolution: {integrity: sha512-mRsi2vJsk4Bx/AFsNBqOH2fqedxn5L/moT58xgg51DjX1la64Z3Npicut2VbhvDFO26qjWtPMsVxCd80YTFVeg==}
  /@esbuild/android-arm@0.19.4:
    resolution: {integrity: sha512-uBIbiYMeSsy2U0XQoOGVVcpIktjLMEKa7ryz2RLr7L/vTnANNEsPVAh4xOv7ondGz6ac1zVb0F8Jx20rQikffQ==}
  /@esbuild/android-x64@0.19.4:
    resolution: {integrity: sha512-4iPufZ1TMOD3oBlGFqHXBpa3KFT46aLl6Vy7gwed0ZSYgHaZ/mihbYb4t7Z9etjkC9Al3ZYIoOaHrU60gcMy7g==}
  /@esbuild/darwin-arm64@0.19.4:
    resolution: {integrity: sha512-Lviw8EzxsVQKpbS+rSt6/6zjn9ashUZ7Tbuvc2YENgRl0yZTktGlachZ9KMJUsVjZEGFVu336kl5lBgDN6PmpA==}
  /@esbuild/darwin-x64@0.19.4:
    resolution: {integrity: sha512-YHbSFlLgDwglFn0lAO3Zsdrife9jcQXQhgRp77YiTDja23FrC2uwnhXMNkAucthsf+Psr7sTwYEryxz6FPAVqw==}
  /@esbuild/freebsd-arm64@0.19.4:
    resolution: {integrity: sha512-vz59ijyrTG22Hshaj620e5yhs2dU1WJy723ofc+KUgxVCM6zxQESmWdMuVmUzxtGqtj5heHyB44PjV/HKsEmuQ==}
  /@esbuild/freebsd-x64@0.19.4:
    resolution: {integrity: sha512-3sRbQ6W5kAiVQRBWREGJNd1YE7OgzS0AmOGjDmX/qZZecq8NFlQsQH0IfXjjmD0XtUYqr64e0EKNFjMUlPL3Cw==}
  /@esbuild/linux-arm64@0.19.4:
    resolution: {integrity: sha512-ZWmWORaPbsPwmyu7eIEATFlaqm0QGt+joRE9sKcnVUG3oBbr/KYdNE2TnkzdQwX6EDRdg/x8Q4EZQTXoClUqqA==}
  /@esbuild/linux-arm@0.19.4:
    resolution: {integrity: sha512-z/4ArqOo9EImzTi4b6Vq+pthLnepFzJ92BnofU1jgNlcVb+UqynVFdoXMCFreTK7FdhqAzH0vmdwW5373Hm9pg==}
  /@esbuild/linux-ia32@0.19.4:
    resolution: {integrity: sha512-EGc4vYM7i1GRUIMqRZNCTzJh25MHePYsnQfKDexD8uPTCm9mK56NIL04LUfX2aaJ+C9vyEp2fJ7jbqFEYgO9lQ==}
  /@esbuild/linux-loong64@0.19.4:
    resolution: {integrity: sha512-WVhIKO26kmm8lPmNrUikxSpXcgd6HDog0cx12BUfA2PkmURHSgx9G6vA19lrlQOMw+UjMZ+l3PpbtzffCxFDRg==}
  /@esbuild/linux-mips64el@0.19.4:
    resolution: {integrity: sha512-keYY+Hlj5w86hNp5JJPuZNbvW4jql7c1eXdBUHIJGTeN/+0QFutU3GrS+c27L+NTmzi73yhtojHk+lr2+502Mw==}
  /@esbuild/linux-ppc64@0.19.4:
    resolution: {integrity: sha512-tQ92n0WMXyEsCH4m32S21fND8VxNiVazUbU4IUGVXQpWiaAxOBvtOtbEt3cXIV3GEBydYsY8pyeRMJx9kn3rvw==}
  /@esbuild/linux-riscv64@0.19.4:
    resolution: {integrity: sha512-tRRBey6fG9tqGH6V75xH3lFPpj9E8BH+N+zjSUCnFOX93kEzqS0WdyJHkta/mmJHn7MBaa++9P4ARiU4ykjhig==}
  /@esbuild/linux-s390x@0.19.4:
    resolution: {integrity: sha512-152aLpQqKZYhThiJ+uAM4PcuLCAOxDsCekIbnGzPKVBRUDlgaaAfaUl5NYkB1hgY6WN4sPkejxKlANgVcGl9Qg==}
  /@esbuild/linux-x64@0.19.4:
    resolution: {integrity: sha512-Mi4aNA3rz1BNFtB7aGadMD0MavmzuuXNTaYL6/uiYIs08U7YMPETpgNn5oue3ICr+inKwItOwSsJDYkrE9ekVg==}
  /@esbuild/netbsd-x64@0.19.4:
    resolution: {integrity: sha512-9+Wxx1i5N/CYo505CTT7T+ix4lVzEdz0uCoYGxM5JDVlP2YdDC1Bdz+Khv6IbqmisT0Si928eAxbmGkcbiuM/A==}
  /@esbuild/openbsd-x64@0.19.4:
    resolution: {integrity: sha512-MFsHleM5/rWRW9EivFssop+OulYVUoVcqkyOkjiynKBCGBj9Lihl7kh9IzrreDyXa4sNkquei5/DTP4uCk25xw==}
  /@esbuild/sunos-x64@0.19.4:
    resolution: {integrity: sha512-6Xq8SpK46yLvrGxjp6HftkDwPP49puU4OF0hEL4dTxqCbfx09LyrbUj/D7tmIRMj5D5FCUPksBbxyQhp8tmHzw==}
  /@esbuild/win32-arm64@0.19.4:
    resolution: {integrity: sha512-PkIl7Jq4mP6ke7QKwyg4fD4Xvn8PXisagV/+HntWoDEdmerB2LTukRZg728Yd1Fj+LuEX75t/hKXE2Ppk8Hh1w==}
  /@esbuild/win32-ia32@0.19.4:
    resolution: {integrity: sha512-ga676Hnvw7/ycdKB53qPusvsKdwrWzEyJ+AtItHGoARszIqvjffTwaaW3b2L6l90i7MO9i+dlAW415INuRhSGg==}
  /@esbuild/win32-x64@0.19.4:
    resolution: {integrity: sha512-HP0GDNla1T3ZL8Ko/SHAS2GgtjOg+VmWnnYLhuTksr++EnduYB0f3Y2LzHsUwb2iQ13JGoY6G3R8h6Du/WG6uA==}
      eslint-visitor-keys: 3.4.3
  /@eslint-community/regexpp@4.9.1:
    resolution: {integrity: sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==}
  /@eslint/eslintrc@2.1.2:
    resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==}
      globals: 13.23.0
  /@fastify/busboy@2.0.0:
    resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==}
    engines: {node: '>=14'}

      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
  /@fastify/error@3.4.0:
    resolution: {integrity: sha512-e/mafFwbK3MNqxUcFBLgHhgxsF8UT1m8aj0dAlqEa2nJEgPsRtpHTZ3ObgrgkZ2M1eJHPTwgyUl/tXkvabsZdQ==}
      fast-json-stringify: 5.8.0
      '@fastify/error': 3.4.0
      fast-jwt: 3.3.1
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      '@fastify/error': 3.4.0
      '@fastify/swagger': 8.11.0
      '@fastify/swagger-ui': 1.10.0
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      tiny-lru: 11.2.2
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      readable-stream: 4.4.2
  /@fastify/swagger-ui@1.10.0:
    resolution: {integrity: sha512-vps8KRDQ8JWQGG9Dh6fCOzAc81Y5a6RnCU/Sumyw3n7+HXJSYExnLLgv4aS9eRFSODtQ8kzZJ//IxAbf0nZ+sQ==}
      fastify-plugin: 4.5.1
  /@fastify/swagger@8.11.0:
    resolution: {integrity: sha512-K8hAWr3wTBUojjJfNUy0TAl766ga2O/L5mWVbBZ6MImOOB3GYUgqNXC4MKrOejt8Y4Ps4cdKjkgzWLcUtg8SFg==}
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      fastify-plugin: 4.5.1
      ws: 8.14.2
  /@floating-ui/core@1.5.0:
    resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==}
    dependencies:
      '@floating-ui/utils': 0.1.6
      '@floating-ui/core': 1.5.0
    dev: false

  /@floating-ui/utils@0.1.6:
    resolution: {integrity: sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==}
  /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1):
      graphql: 16.8.1
  /@hocuspocus/common@2.6.1:
    resolution: {integrity: sha512-s6//HV4D8Oav3uFHZKWcKtKaKPd6j2hidmplFKufgh1dSKeZ6psiNv9SzB3GUYPva7Vw81dWbJ2U8fkOYNqHzg==}
      lib0: 0.2.86
      uuid: 9.0.1
      '@hocuspocus/common': 2.6.1
      lib0: 0.2.86
      '@hocuspocus/common': 2.6.1
      lib0: 0.2.86
      uuid: 9.0.1
      ws: 8.14.2
      '@tiptap/starter-kit': 2.1.11(@tiptap/pm@2.1.8)
      y-prosemirror: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
  /@humanwhocodes/config-array@0.11.11:
    resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==}
  /@iconify/utils@2.1.11:
    resolution: {integrity: sha512-M/w3PkN8zQYXi8N6qK/KhnYMfEbbb6Sk8RZVn8g+Pmmu5ybw177RpsaGwpziyHeUsu4etrexYSWq3rwnIqzYCg==}
      '@jridgewell/trace-mapping': 0.3.19
  /@jridgewell/resolve-uri@3.1.1:
    resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
  /@jridgewell/source-map@0.3.5:
    resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
      '@jridgewell/trace-mapping': 0.3.19
  /@jridgewell/trace-mapping@0.3.19:
    resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
      '@jridgewell/resolve-uri': 3.1.1
      '@jridgewell/sourcemap-codec': 1.4.15
  /@lukeed/ms@2.0.1:
    resolution: {integrity: sha512-Xs/4RZltsAL7pkvaNStUQt7netTkyxrS0K+RILcVr3TRMS/ToOg4I6uNfhB9SlGsnWBym4U+EaXq0f0cEMNkHA==}
    engines: {node: '>=8'}
  /@manypkg/find-root@2.1.0:
    resolution: {integrity: sha512-NEYRVlZCJYhRTqQURhv+WBpDcvmsp/M423Wcdvggv8lYJYD4GtqnTMLrQaTjA10fYt/PIc3tSdwV+wxJnWqPfQ==}
    engines: {node: '>=14.18.0'}
  /@mdx-js/mdx@2.3.0:
    resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/mdx': 2.0.8
      estree-util-build-jsx: 2.2.2
      estree-util-is-identifier-name: 2.1.0
      estree-util-to-js: 1.2.0
      estree-walker: 3.0.3
      hast-util-to-estree: 2.3.3
      markdown-extensions: 1.1.1
      periscopic: 3.1.0
      remark-mdx: 2.3.0
      remark-parse: 10.0.2
      remark-rehype: 10.1.0
      unified: 10.1.2
      unist-util-position-from-estree: 1.1.2
      unist-util-stringify-position: 3.0.3
      unist-util-visit: 4.1.2
      vfile: 5.3.7
    transitivePeerDependencies:
      - supports-color
    dev: false

  /@motionone/animation@10.16.3:
    resolution: {integrity: sha512-QUGWpLbMFLhyqKlngjZhjtxM8IqiJQjLK0DF+XOF6od9nhSvlaeEpOY/UMCRVcZn/9Tr2rZO22EkuCIjYdI74g==}
      '@motionone/easing': 10.16.3
      '@motionone/types': 10.16.3
      '@motionone/utils': 10.16.3
      tslib: 2.6.2
  /@motionone/dom@10.16.4:
    resolution: {integrity: sha512-HPHlVo/030qpRj9R8fgY50KTN4Ko30moWRTA3L3imrsRBmob93cTYmodln49HYFbQm01lFF7X523OkKY0DX6UA==}
      '@motionone/animation': 10.16.3
      '@motionone/generators': 10.16.4
      '@motionone/types': 10.16.3
      '@motionone/utils': 10.16.3
      tslib: 2.6.2
  /@motionone/easing@10.16.3:
    resolution: {integrity: sha512-HWTMZbTmZojzwEuKT/xCdvoMPXjYSyQvuVM6jmM0yoGU6BWzsmYMeB4bn38UFf618fJCNtP9XeC/zxtKWfbr0w==}
      '@motionone/utils': 10.16.3
      tslib: 2.6.2
  /@motionone/generators@10.16.4:
    resolution: {integrity: sha512-geFZ3w0Rm0ZXXpctWsSf3REGywmLLujEjxPYpBR0j+ymYwof0xbV6S5kGqqsDKgyWKVWpUInqQYvQfL6fRbXeg==}
      '@motionone/types': 10.16.3
      '@motionone/utils': 10.16.3
      tslib: 2.6.2
  /@motionone/solid@10.16.2(solid-js@1.7.11):
      '@motionone/dom': 10.16.4
      '@motionone/utils': 10.16.3
      '@solid-primitives/props': 3.1.8(solid-js@1.7.11)
      '@solid-primitives/refs': 1.0.5(solid-js@1.7.11)
      '@solid-primitives/transition-group': 1.0.3(solid-js@1.7.11)
      solid-js: 1.7.11
  /@motionone/types@10.16.3:
    resolution: {integrity: sha512-W4jkEGFifDq73DlaZs3HUfamV2t1wM35zN/zX7Q79LfZ2sc6C0R1baUHZmqc/K5F3vSw3PavgQ6HyHLd/MXcWg==}
  /@motionone/utils@10.16.3:
    resolution: {integrity: sha512-WNWDksJIxQkaI9p9Z9z0+K27xdqISGNFy1SsWVGaiedTHq0iaT6iZujby8fT/ZnZxj1EOaxJtSfUPCFNU5CRoA==}
      '@motionone/types': 10.16.3
      tslib: 2.6.2
  /@octokit/app@14.0.1:
    resolution: {integrity: sha512-4opdXcWBVhzd6FOxlaxDKXXqi9Vz2hsDSWQGNo49HbYFAX11UqMpksMjEdfvHy0x19Pse8Nvn+R6inNb/V398w==}
      '@octokit/auth-app': 6.0.1
      '@octokit/auth-unauthenticated': 5.0.1
      '@octokit/core': 5.0.1
      '@octokit/plugin-paginate-rest': 9.0.0(@octokit/core@5.0.1)
      '@octokit/types': 12.0.0
  /@octokit/auth-app@6.0.1:
    resolution: {integrity: sha512-tjCD4nzQNZgmLH62+PSnTF6eGerisFgV4v6euhqJik6yWV96e1ZiiGj+NXIqbgnpjLmtnBqVUrNyGKu3DoGEGA==}
      '@octokit/auth-oauth-app': 7.0.1
      '@octokit/auth-oauth-user': 4.0.1
      '@octokit/request': 8.1.3
      '@octokit/request-error': 5.0.1
      '@octokit/types': 12.0.0
      lru-cache: 10.0.1
  /@octokit/auth-oauth-app@7.0.1:
    resolution: {integrity: sha512-RE0KK0DCjCHXHlQBoubwlLijXEKfhMhKm9gO56xYvFmP1QTMb+vvwRPmQLLx0V+5AvV9N9I3lr1WyTzwL3rMDg==}
      '@octokit/auth-oauth-device': 6.0.1
      '@octokit/auth-oauth-user': 4.0.1
      '@octokit/request': 8.1.3
      '@octokit/types': 12.0.0
  /@octokit/auth-oauth-device@6.0.1:
    resolution: {integrity: sha512-yxU0rkL65QkjbqQedgVx3gmW7YM5fF+r5uaSj9tM/cQGVqloXcqP2xK90eTyYvl29arFVCW8Vz4H/t47mL0ELw==}
      '@octokit/request': 8.1.3
      '@octokit/types': 12.0.0
  /@octokit/auth-oauth-user@4.0.1:
    resolution: {integrity: sha512-N94wWW09d0hleCnrO5wt5MxekatqEJ4zf+1vSe8MKMrhZ7gAXKFOKrDEZW2INltvBWJCyDUELgGRv8gfErH1Iw==}
      '@octokit/auth-oauth-device': 6.0.1
      '@octokit/request': 8.1.3
      '@octokit/types': 12.0.0
  /@octokit/auth-unauthenticated@5.0.1:
    resolution: {integrity: sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==}
      '@octokit/request-error': 5.0.1
      '@octokit/types': 12.0.0
  /@octokit/core@5.0.1:
    resolution: {integrity: sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==}
      '@octokit/graphql': 7.0.2
      '@octokit/request': 8.1.3
      '@octokit/request-error': 5.0.1
      '@octokit/types': 12.0.0
  /@octokit/endpoint@9.0.1:
    resolution: {integrity: sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==}
      '@octokit/types': 12.0.0
  /@octokit/graphql@7.0.2:
    resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==}
      '@octokit/request': 8.1.3
      '@octokit/types': 12.0.0
      '@octokit/auth-oauth-app': 7.0.1
      '@octokit/auth-oauth-user': 4.0.1
      '@octokit/auth-unauthenticated': 5.0.1
      '@octokit/core': 5.0.1
      '@types/aws-lambda': 8.10.124
      '@octokit/request': 8.1.3
      '@octokit/request-error': 5.0.1
  /@octokit/openapi-types@18.1.1:
    resolution: {integrity: sha512-VRaeH8nCDtF5aXWnjPuEMIYf1itK/s3JYyJcWFJT8X9pSNnBtriDf7wlEWsGuhPLl4QIH4xM8fqTXDwJ3Mu6sw==}
    dev: false

  /@octokit/openapi-types@19.0.0:
    resolution: {integrity: sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==}
  /@octokit/plugin-paginate-rest@8.0.0(@octokit/core@5.0.1):
      '@octokit/core': 5.0.1
  /@octokit/plugin-paginate-rest@9.0.0(@octokit/core@5.0.1):
    resolution: {integrity: sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==}
    engines: {node: '>= 18'}
    peerDependencies:
      '@octokit/core': '>=5'
    dependencies:
      '@octokit/core': 5.0.1
      '@octokit/types': 12.0.0
    dev: false

  /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.1):
      '@octokit/core': 5.0.1
  /@octokit/plugin-rest-endpoint-methods@9.0.0(@octokit/core@5.0.1):
      '@octokit/core': 5.0.1
  /@octokit/plugin-retry@6.0.1(@octokit/core@5.0.1):
    resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==}
      '@octokit/core': 5.0.1
      '@octokit/request-error': 5.0.1
      '@octokit/types': 12.0.0
  /@octokit/plugin-throttling@7.0.0(@octokit/core@5.0.1):
      '@octokit/core': 5.0.1
  /@octokit/request-error@5.0.1:
    resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==}
      '@octokit/types': 12.0.0
      node-fetch: 2.7.0
  /@octokit/request@8.1.3:
    resolution: {integrity: sha512-iUvXP4QmysS8kyE/a4AGwR0A+tHDVxgW6TmPd2ci8/Xc8KjlBtTKSDpZlUT5Y4S4Nu+eM8LvbOYjVAp/sz3Gpg==}
      '@octokit/endpoint': 9.0.1
      '@octokit/request-error': 5.0.1
      '@octokit/types': 12.0.0
      '@octokit/core': 5.0.1
      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.1)
      '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.1)
      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.1)
      '@octokit/openapi-types': 18.1.1
      '@octokit/openapi-types': 18.1.1
    dev: false

  /@octokit/types@12.0.0:
    resolution: {integrity: sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==}
    dependencies:
      '@octokit/openapi-types': 19.0.0
      '@octokit/openapi-types': 18.1.1
      '@octokit/request-error': 5.0.1
  /@pkgr/utils@2.4.2:
    resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==}
      tslib: 2.6.2
  /@polka/url@1.0.0-next.23:
    resolution: {integrity: sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==}
  /@prettier/sync@0.3.0(prettier@3.0.2):
    resolution: {integrity: sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==}
    peerDependencies:
      prettier: ^3.0.0
    dependencies:
      prettier: 3.0.2
    dev: false

  /@qdrant/js-client-grpc@1.4.0(typescript@5.2.2):
      '@bufbuild/connect': 0.9.1(@bufbuild/protobuf@1.3.3)
      '@bufbuild/connect-node': 0.9.1(@bufbuild/protobuf@1.3.3)
      '@bufbuild/protobuf': 1.3.3
      typescript: 5.2.2
  /@qdrant/js-client-rest@1.4.0(typescript@5.2.2):
      typescript: 5.2.2
      undici: 5.25.4
  /@qdrant/qdrant-js@1.4.0(typescript@5.2.2):
      '@qdrant/js-client-grpc': 1.4.0(typescript@5.2.2)
      '@qdrant/js-client-rest': 1.4.0(typescript@5.2.2)
      typescript: 5.2.2
      '@babel/runtime': 7.23.1
      '@babel/runtime': 7.23.1
  /@remirror/core-constants@2.0.2:
    resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==}
  /@remirror/core-helpers@3.0.0:
    resolution: {integrity: sha512-tusEgQJIqg4qKj6HSBUFcyRnWnziw3neh4T9wOmsPGHFC3w9kl5KSrDb9UAgE8uX6y32FnS7vJ955mWOl3n50A==}
      '@remirror/core-constants': 2.0.2
      '@types/object.omit': 3.0.1
  /@rollup/plugin-alias@5.0.1(rollup@3.29.4):
    resolution: {integrity: sha512-JObvbWdOHoMy9W7SU0lvGhDtWq9PllP5mjpAy+TUslZG/WzOId9u80Hsqq1vCUn9pFJ0cxpdcnAv+QzU2zFH3Q==}
      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
      rollup: 3.29.4
  /@rollup/plugin-commonjs@24.1.0(rollup@3.29.4):
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      rollup: 3.29.4
  /@rollup/plugin-json@6.0.1(rollup@3.29.4):
    resolution: {integrity: sha512-RgVfl5hWMkxN1h/uZj8FVESvPuBJ/uf6ly6GTj0GONnkfoBN5KC0MSz+PN2OLDgYXMhtG0mWpTrkiOjoxAIevw==}
      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      rollup: 3.29.4
  /@rollup/plugin-node-resolve@15.2.2(rollup@3.29.4):
    resolution: {integrity: sha512-f64bU4OKqV0yihtxFemmuf0oj37pToCFMISCA+sJbbIAl5wcpbRO9XgWNWb1tDiWQJUcPxo6V0l59hcuZOQ3kw==}
      rollup: ^2.78.0||^3.0.0||^4.0.0
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      resolve: 1.22.6
      rollup: 3.29.4
  /@rollup/plugin-replace@5.0.3(rollup@3.29.4):
    resolution: {integrity: sha512-je7fu05B800IrMlWjb2wzJcdXzHYW46iTipfChnBDbIbDXhASZs27W1B58T2Yf45jZtJUONegpbce+9Ut2Ti/Q==}
      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      rollup: 3.29.4
  /@rollup/pluginutils@5.0.5(rollup@3.29.4):
    resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==}
      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
      '@types/estree': 1.0.2
      rollup: 3.29.4
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
      tslib: 2.6.2
  /@solid-primitives/active-element@2.0.15(solid-js@1.7.11):
      '@solid-primitives/event-listener': 2.3.0(solid-js@1.7.11)
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/connectivity@0.3.15(solid-js@1.7.11):
      '@solid-primitives/event-listener': 2.3.0(solid-js@1.7.11)
      '@solid-primitives/rootless': 1.4.2(solid-js@1.7.11)
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/event-listener@2.3.0(solid-js@1.7.11):
    resolution: {integrity: sha512-0DS7DQZvCExWSpurVZC9/wjI8RmkhuOtWOy6Pp1Woq9ElMT9/bfjNpkwXsOwisLpcTqh9eUs17kp7jtpWcC20w==}
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/media@2.2.3(solid-js@1.7.11):
      '@solid-primitives/event-listener': 2.3.0(solid-js@1.7.11)
      '@solid-primitives/rootless': 1.4.2(solid-js@1.7.11)
      '@solid-primitives/static-store': 0.0.4(solid-js@1.7.11)
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/memo@1.3.2(solid-js@1.7.11):
      '@solid-primitives/scheduled': 1.4.0(solid-js@1.7.11)
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/props@3.1.8(solid-js@1.7.11):
    resolution: {integrity: sha512-38ERNFhl87emUDPRlYvCmlbvEcK2mOJB38SU22YS2QXFDK7TQf/7P46XZacs7oODc/fckhfZTitht71FMEDe2g==}
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/refs@1.0.5(solid-js@1.7.11):
    resolution: {integrity: sha512-5hmYmYbm6rs43nMHHozyyUngGA7P7q2WtlaCLJEfmlUJf67GWI1PZmqAiol6m9F37XSMZRuvZLoQ7HA/0q3GYg==}
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/rootless@1.4.2(solid-js@1.7.11):
    resolution: {integrity: sha512-ynI/2aEOPyc14IKCX6yDBqnsAYCoLbaP9V/jejEWMVKOT2ZdV2ZxdftaLimOpWPpvjyti5DUJIGTOfLaNb7jlg==}
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/scheduled@1.4.0(solid-js@1.7.11):
      solid-js: 1.7.11
  /@solid-primitives/static-store@0.0.4(solid-js@1.7.11):
      '@solid-primitives/utils': 6.2.1(solid-js@1.7.11)
      solid-js: 1.7.11
  /@solid-primitives/transition-group@1.0.3(solid-js@1.7.11):
    resolution: {integrity: sha512-TnFADZhx9sibdoW5gxkU1QmLabzV2H2OBKYGS2aR5IC61Q/+7v8wlxOJEevxXNbPiRo6qlE3STLU3L9XS8hDbA==}
      solid-js: 1.7.11
  /@solid-primitives/utils@6.2.1(solid-js@1.7.11):
    resolution: {integrity: sha512-TsecNzxiO5bLfzqb4OOuzfUmdOROcssuGqgh5rXMMaasoFZ3GoveUgdY1wcf17frMJM7kCNGNuK34EjErneZkg==}
      solid-js: 1.7.11
  /@solidjs/router@0.8.2(solid-js@1.7.11):
      solid-js: 1.7.11
    dev: false

  /@tiptap/core@2.1.11(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-1W2DdjpPwfphHgQ3Qm4s5wzCnEjiXm1TeZ+6/zBl89yKURXgv8Mw1JGdj/NcImQjtDcsNn97MscACK3GKbEJBA==}
    peerDependencies:
      '@tiptap/pm': ^2.0.0
    dependencies:
      '@tiptap/pm': 2.1.8
  /@tiptap/extension-blockquote@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-IEVe3goA0rgp1G8Wm733BSRJiy71Vh2fmTCyZKWmc2A6GREVSy1X3fCvAo6pMENRObhjIoaBQUCE3p4iJYOxqg==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-bold@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-vhdkBtvd029ufOYt2ug49Gz+RLKSczO/CCqKYBqBmpIpsifyK7M6jkgamvAQg3c/vYk0LNcKiL2dp0Jp7L+5Gw==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-bullet-list@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-SOOVH2aSmdMtjWL7TTLbN72xbAFz2G5jifT4UCXb7Qx6LsyhNCyDCu0ukOW8rSosGoSdmBXxAsD9sBJ1jEOmZw==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-code-block-lowlight@2.1.8(@tiptap/core@2.1.8)(@tiptap/extension-code-block@2.1.11)(@tiptap/pm@2.1.8):
      '@tiptap/extension-code-block': 2.1.11(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)
      '@tiptap/pm': 2.1.8
    dev: false

  /@tiptap/extension-code-block@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-QhmhCCWqg/5qLXpZ3sl2A0rqJqV8zMOegcxUFaqcJMOqNbsuHcRgc9C+1hWSVLbCmstB7M6sgF02QpTBOkYHxg==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
      '@tiptap/pm': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
  /@tiptap/extension-code-block@2.1.11(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-QhmhCCWqg/5qLXpZ3sl2A0rqJqV8zMOegcxUFaqcJMOqNbsuHcRgc9C+1hWSVLbCmstB7M6sgF02QpTBOkYHxg==}
  /@tiptap/extension-code@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-G0UEbMFunujy/F86yHN0/dumPLbwTis9C+6IQv1XRPNsV28U0MgxBhlPcJUgyO5lwuleePDxiBVcRv2XrysgKw==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

      y-prosemirror: 1.0.20(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
      y-prosemirror: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
      y-prosemirror: 1.0.20(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
      y-prosemirror: 1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7)
    dev: false

  /@tiptap/extension-document@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-L/iLuqxvJep33ycCFNrnUhdR0VtcZyeNnqB+ZvVHzEwLoRud+LBy44lpEdBrAFsvRm3DG14m/FGYL+TfaD0vxA==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
  /@tiptap/extension-dropcursor@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-MiJepRpHlu93aInOMW8NeRCvm9VE5rL0MA9TONY/IspJFGFIqonc/01J6t33JQa3Xh/x3xAfis4nKa/UazeVJw==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
      '@tiptap/pm': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
      '@tiptap/pm': 2.1.8
    dev: false

  /@tiptap/extension-gapcursor@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-P/xjyhSOVyop5XXbNtRPgrooQrSlpYblwR67ClI9FAC7uQliuOwi5VcndmEItjWWSe85kJa2IHjOS7mLYvJe8A==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
      '@tiptap/pm': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
      '@tiptap/pm': 2.1.8
    dev: false

  /@tiptap/extension-hard-break@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-qhiPe6FA0b6PPb/ITlgSnY0l9tEVmXZ9e7eSjvks12ORfqL/dofSCLtChHWvhZxugzo92xejG2hXLi6lyOLbkg==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-heading@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-QBtl0S1aDFB+F1wvTrS5iGdNUEeXp+WuTddj+L2f5EP4KqG2x7sj7e7ENMy20g/l8tbKwzd3AZZydvClH4Ybbw==}
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
  /@tiptap/extension-history@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-88dovV2O9icmBn0IvaArFFeS6X5ts6BxZPu5VbGML8KBL8iAu+Og7RXEPdOy5e13K0K4V21fDpO3n7KdvNOAYQ==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
      '@tiptap/pm': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
      '@tiptap/pm': 2.1.8
    dev: false

  /@tiptap/extension-horizontal-rule@2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-uvHPa2YCKnDhtSBSZB3lk5U4H3wRKP0DNvVx4Y2F7MdQianVzcyOd1pZYO9BQs+lUB1aZots6doE69Zqz3mU2Q==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
      '@tiptap/pm': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
      '@tiptap/pm': 2.1.8
    dev: false

  /@tiptap/extension-italic@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-QmDsHtnBBit/1KtQpBPxjSPjDC1mVKtoNTgsEwMWK6YAkCKOKPj7oPEqqjaNZIRMKPPzE5XCsfBoS3jtVmo+6A==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-list-item@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-YhwHaPGhffsFsg/zjCu1G24//j/BTRDRZbZXmMwp77m1yEqPULcWyoWrI+gUzetQxJRD/ruAucqjLtoLLfICmQ==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-ordered-list@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-/tghfEJ5U7WFbF8xyOqRJks8KxP/lRjnroMXMglaushSMx8PYPo1dZDB/dJZw7ksy47MAaKJfKlx3gyN2CPXBQ==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-paragraph@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-gXMgJ2CU3X4yh1wKnb8RdbDmhITB76pH6DX0uWprmEgvzNMN3Qw+h5uBD9lgxg1WVghbCmkG9mY9J4PPbPTLxw==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-strike@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-UnjeSVgu3bDuyjjUdWsUErRCoQKAHCzH/pAiqTEPEEdFYgZFQPBpcJICRVdlYjRmI2ZKh6d0TMUS55m7ckmwmQ==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

  /@tiptap/extension-text@2.1.11(@tiptap/core@2.1.11):
    resolution: {integrity: sha512-Iey0EXYv9079+lbHMvZtLc6XcYfKrq++msEXuFFNHxvL0i/XzndhGf+qlDhLROLgEtDiiTqzOBBwFCGlFjbDow==}
    peerDependencies:
      '@tiptap/core': ^2.0.0
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
    dev: false

      prosemirror-markdown: 1.11.2
      prosemirror-menu: 1.2.4
      prosemirror-model: 1.19.3
      prosemirror-tables: 1.3.4
      prosemirror-trailing-node: 2.0.7(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)
      prosemirror-transform: 1.8.0
      prosemirror-view: 1.32.0
    dev: false

  /@tiptap/starter-kit@2.1.11(@tiptap/pm@2.1.8):
    resolution: {integrity: sha512-kZXwuo9yxrs1ASxluRKjXThjdcy90d7owJxnJWD7SyEwXaXYc4h+Ar1M9rP3jieCDBuRTtCgvAOKbVbhnRJ2jg==}
    dependencies:
      '@tiptap/core': 2.1.11(@tiptap/pm@2.1.8)
      '@tiptap/extension-blockquote': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-bold': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-bullet-list': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-code': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-code-block': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
      '@tiptap/extension-document': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-dropcursor': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
      '@tiptap/extension-gapcursor': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
      '@tiptap/extension-hard-break': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-heading': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-history': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
      '@tiptap/extension-horizontal-rule': 2.1.11(@tiptap/core@2.1.11)(@tiptap/pm@2.1.8)
      '@tiptap/extension-italic': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-list-item': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-ordered-list': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-paragraph': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-strike': 2.1.11(@tiptap/core@2.1.11)
      '@tiptap/extension-text': 2.1.11(@tiptap/core@2.1.11)
  /@trysound/sax@0.2.0:
    resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
    engines: {node: '>=10.13.0'}
    dev: false

  /@types/acorn@4.0.6:
    resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==}
    dependencies:
      '@types/estree': 1.0.2
    dev: false

  /@types/aws-lambda@8.10.124:
    resolution: {integrity: sha512-PHqK0SuAkFS3tZjceqRXecxxrWIN3VqTicuialtK2wZmvBy7H9WGc3u3+wOgaZB7N8SpSXDpWk9qa7eorpTStg==}
  /@types/babel__core@7.20.2:
    resolution: {integrity: sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==}
      '@babel/parser': 7.23.0
      '@babel/types': 7.23.0
      '@types/babel__generator': 7.6.5
      '@types/babel__template': 7.4.2
      '@types/babel__traverse': 7.20.2
  /@types/babel__generator@7.6.5:
    resolution: {integrity: sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==}
      '@babel/types': 7.23.0
  /@types/babel__template@7.4.2:
    resolution: {integrity: sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==}
      '@babel/parser': 7.23.0
      '@babel/types': 7.23.0
  /@types/babel__traverse@7.20.2:
    resolution: {integrity: sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==}
      '@babel/types': 7.23.0
  /@types/debug@4.1.9:
    resolution: {integrity: sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==}
      '@types/ms': 0.7.32
  /@types/dom-view-transitions@1.0.2:
    resolution: {integrity: sha512-+ctRyzGMOZB5AbvhpTv37OWkP9N3Xxfac7bhS7AcuRMmO03SHxm5/5kWCPtcatx2gW+NhFMdl7l1DqJvvPVtwg==}
      '@types/trusted-types': 2.0.4
  /@types/estree-jsx@1.0.1:
    resolution: {integrity: sha512-sHyakZlAezNFxmYRo0fopDZW+XvK6ipeZkkp5EAOLjdPfZp8VjZBJ67vSRI99RSCAoqXVmXOHS4fnWoxpuGQtQ==}
    dependencies:
      '@types/estree': 1.0.2
    dev: false

  /@types/estree@1.0.2:
    resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==}
  /@types/hast@2.3.6:
    resolution: {integrity: sha512-47rJE80oqPmFdVDCD7IheXBrVdwuBgsYwoczFvKmwfo2Mzsnt+V9OONsYauFmICb6lQPpCuXYJWejBNs4pDJRg==}
    dependencies:
      '@types/unist': 2.0.8

  /@types/hast@3.0.1:
    resolution: {integrity: sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==}
      '@types/unist': 3.0.0
    dev: false
  /@types/js-yaml@4.0.6:
    resolution: {integrity: sha512-ACTuifTSIIbyksx2HTon3aFtCKWcID7/h3XEmRpDYdMCXxPbl+m9GteOJeaAkiAta/NJaSFuA7ahZ0NkwajDSw==}
    dev: false

  /@types/json-schema@7.0.13:
    resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==}
  /@types/jsonwebtoken@9.0.3:
    resolution: {integrity: sha512-b0jGiOgHtZ2jqdPgPnP6WLCXZk1T8p06A/vPGzUvxpFGgKMbjXJDjC5m52ErqBnIuWZFgGoIJyRdeG5AyreJjA==}
  /@types/mdast@3.0.13:
    resolution: {integrity: sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==}
      '@types/unist': 2.0.8
  /@types/mdast@4.0.1:
    resolution: {integrity: sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==}
  /@types/mdx@2.0.8:
    resolution: {integrity: sha512-r7/zWe+f9x+zjXqGxf821qz++ld8tp6Z4jUS6qmPZUXH6tfh4riXOhAqb12tWGWAevCFtMt1goLWkQMqIJKpsA==}
    dev: false

  /@types/ms@0.7.32:
    resolution: {integrity: sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==}
  /@types/nlcst@1.0.2:
    resolution: {integrity: sha512-ykxL/GDDUhqikjU0LIywZvEwb1NTYXTEWf+XgMSS2o6IXIakafPccxZmxgZcvJPZ3yFl2kdL1gJZz3U3iZF3QA==}
      '@types/unist': 2.0.8
  /@types/node-fetch@2.6.6:
    resolution: {integrity: sha512-95X8guJYhfqiuVVhRFxVQcf4hW/2bCuoPwDasMf/531STFoNoWTT7YDnWdXHEZKqAGUigmpG31r2FE70LwnzJw==}
      form-data: 4.0.0
  /@types/node@18.18.4:
    resolution: {integrity: sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ==}
  /@types/normalize-package-data@2.4.2:
    resolution: {integrity: sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==}
  /@types/object.omit@3.0.1:
    resolution: {integrity: sha512-24XD34UeRWw505TsMNBrQ4bES2s8IxiFC59mmNUFhTz9IX2hAtA7gQ8wVww1i17QmhBYILg5iqYP2y7aqA3pwQ==}
  /@types/prop-types@15.7.8:
    resolution: {integrity: sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ==}
      '@types/prop-types': 15.7.8
      '@types/scheduler': 0.16.4
    dev: true
  /@types/resolve@1.20.3:
    resolution: {integrity: sha512-NH5oErHOtHZYcjCtg69t26aXEk4BN2zLWqf7wnDZ+dpe0iR7Rds1SPGEItl3fca21oOe0n3OCnZ4W7jBxu7FOw==}

  /@types/sax@1.2.5:
    resolution: {integrity: sha512-9jWta97bBVC027/MShr3gLab8gPhKy4l6qpb+UJLF5pDm3501NvA7uvqVCW+REFtx00oTi6Cq9JzLwgq6evVgw==}
  /@types/scheduler@0.16.4:
    resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==}
  /@types/semver@7.5.3:
    resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==}
  /@types/trusted-types@2.0.4:
    resolution: {integrity: sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==}
  /@types/unist@2.0.8:
    resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==}
  /@types/webidl-conversions@7.0.1:
    resolution: {integrity: sha512-8hKOnOan+Uu+NgMaCouhg3cT9x5fFZ92Jwf+uDLXLu/MFRbXxlWwGeQY7KVHkeSft6RvY+tdxklUBuyY9eIEKg==}
      '@types/webidl-conversions': 7.0.1
  /@types/yargs-parser@21.0.1:
    resolution: {integrity: sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==}
  /@typescript-eslint/eslint-plugin@3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.2.2):
      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
      tsutils: 3.21.0(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/eslint-plugin@6.2.0(@typescript-eslint/parser@6.2.0)(eslint@8.45.0)(typescript@5.2.2):
      '@eslint-community/regexpp': 4.9.1
      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
      '@typescript-eslint/type-utils': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
      ts-api-utils: 1.0.3(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/experimental-utils@3.10.1(eslint@8.45.0)(typescript@5.2.2):
      '@types/json-schema': 7.0.13
      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.2.2)
  /@typescript-eslint/parser@3.10.1(eslint@8.45.0)(typescript@5.2.2):
      '@typescript-eslint/experimental-utils': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
      '@typescript-eslint/typescript-estree': 3.10.1(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/parser@6.2.0(eslint@8.45.0)(typescript@5.2.2):
      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/scope-manager@5.62.0:
    resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==}
      '@typescript-eslint/types': 5.62.0
      '@typescript-eslint/visitor-keys': 5.62.0
  /@typescript-eslint/type-utils@6.2.0(eslint@8.45.0)(typescript@5.2.2):
      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.2.2)
      '@typescript-eslint/utils': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
      ts-api-utils: 1.0.3(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/types@5.62.0:
    resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==}
  /@typescript-eslint/typescript-estree@3.10.1(typescript@5.2.2):
      tsutils: 3.21.0(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/typescript-estree@5.62.0(typescript@5.2.2):
    resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
      '@typescript-eslint/types': 5.62.0
      '@typescript-eslint/visitor-keys': 5.62.0
      tsutils: 3.21.0(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/typescript-estree@6.2.0(typescript@5.2.2):
      ts-api-utils: 1.0.3(typescript@5.2.2)
      typescript: 5.2.2
  /@typescript-eslint/utils@5.62.0(eslint@8.45.0)(typescript@5.2.2):
    resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==}
      '@types/json-schema': 7.0.13
      '@types/semver': 7.5.3
      '@typescript-eslint/scope-manager': 5.62.0
      '@typescript-eslint/types': 5.62.0
      '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2)
  /@typescript-eslint/utils@6.2.0(eslint@8.45.0)(typescript@5.2.2):
      '@types/json-schema': 7.0.13
      '@types/semver': 7.5.3
      '@typescript-eslint/typescript-estree': 6.2.0(typescript@5.2.2)
  /@typescript-eslint/visitor-keys@5.62.0:
    resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==}
      '@typescript-eslint/types': 5.62.0
      eslint-visitor-keys: 3.4.3
      eslint-visitor-keys: 3.4.3
  /@ungap/structured-clone@1.2.0:
    resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
    dev: false
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      magic-string: 0.30.4
      unconfig: 0.3.11
  /@unocss/postcss@0.55.7(postcss@8.4.31):
      magic-string: 0.30.4
      postcss: 8.4.31
      '@iconify/utils': 2.1.11
  /@unocss/vite@0.55.7(vite@4.4.9):
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      magic-string: 0.30.4
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
  /@vrite/tiptap-solid@1.0.0(@tiptap/core@2.1.8)(@tiptap/pm@2.1.8)(solid-js@1.7.11):
    resolution: {integrity: sha512-eSv3kr8VAjyZ8aVEfhzIGe/LLDAcdBS0GEcWr+Eaab3tM6N11PIhI/1vlufU02uAF0JFY4yx/NA1jvGLU8jEWw==}
      '@tiptap/core': 2.1.8
      '@tiptap/pm': 2.1.8
      solid-js: ^1.7.11
      solid-js: 1.7.11
  /@vscode/emmet-helper@2.9.2:
    resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==}
      emmet: 2.4.6
      vscode-languageserver-textdocument: 1.0.11
      vscode-languageserver-types: 3.17.5
  /@vscode/l10n@0.0.16:
    resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==}
  /ansi-sequence-parser@1.1.1:
    resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==}
  /array-includes@3.1.7:
    resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
  /array.prototype.flat@1.3.2:
    resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
  /array.prototype.flatmap@1.3.2:
    resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
  /arraybuffer.prototype.slice@1.0.2:
    resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
    engines: {node: '>= 0.4'}
    dependencies:
      array-buffer-byte-length: 1.0.0
      call-bind: 1.0.2
      define-properties: 1.2.1
      es-abstract: 1.22.2
      get-intrinsic: 1.2.1
      is-array-buffer: 3.0.2
      is-shared-array-buffer: 1.0.2
    dev: true

  /astring@1.8.6:
    resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==}
    hasBin: true
    dev: false

  /astro-auto-import@0.3.1(astro@3.1.0):
    resolution: {integrity: sha512-4kXZMlZFiq3dqT6fcfPbCjHTABQ279eKbIqZAb6qktBhGlmHwpHr1spOUFj/RQFilaWVgfjzOBmuZnoydZb5Vg==}
    engines: {node: '>=16.0.0'}
    peerDependencies:
      astro: ^2.0.0 || ^3.0.0-beta
    dependencies:
      '@types/node': 18.18.4
      acorn: 8.10.0
      astro: 3.1.0(sass@1.64.1)
    dev: false

  /astro-icon@0.8.1:
    resolution: {integrity: sha512-APk+fbFnoyGdIVSPFrdrOW9YBK96/1fYuVe7ULTGW92+z00RKB8GfLJiUvzNVXUAX2rZJCFmruGVF4rrhcTYsg==}
    dependencies:
      node-fetch: 3.3.2
      resolve-pkg: 2.0.0
      svgo: 2.8.0
    dev: false

      zod: 3.22.4
      '@babel/core': 7.23.0
      '@babel/generator': 7.23.0
      '@babel/parser': 7.23.0
      '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.0)
      '@babel/traverse': 7.23.0
      '@babel/types': 7.23.0
      '@types/babel__core': 7.20.2
      '@types/dom-view-transitions': 1.0.2
      '@types/yargs-parser': 21.0.1
      ci-info: 3.9.0
      es-module-lexer: 1.3.1
      magic-string: 0.30.4
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
      '@astrojs/compiler': 2.2.0
      '@babel/core': 7.23.0
      '@babel/generator': 7.23.0
      '@babel/parser': 7.23.0
      '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.0)
      '@babel/traverse': 7.23.0
      '@babel/types': 7.23.0
      '@types/babel__core': 7.20.2
      ci-info: 3.9.0
      es-module-lexer: 1.3.1
      esbuild: 0.19.4
      magic-string: 0.30.4
      resolve: 1.22.6
      undici: 5.25.4
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
      follow-redirects: 1.15.3
      follow-redirects: 1.15.3
  /babel-plugin-jsx-dom-expressions@0.36.18(@babel/core@7.23.0):
    resolution: {integrity: sha512-8K0CHgzNMB0+1OC+GQf1O49Nc6DfHAoWDjY4YTW3W/3il5KrDKAj65723oPmya68kKKOkqDKuz+Zh1u7VFHthw==}
      '@babel/core': 7.23.0
      '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.23.0)
      '@babel/types': 7.23.0
  /babel-preset-solid@1.7.12(@babel/core@7.23.0):
    resolution: {integrity: sha512-vNZn34Dv6IsWK/F59HhZlN8gP0ihZfkhPp8Lx/nxlY+rKtSZEAmmYlXWtds6EDKSiXoj2TEHuCcuqp6cO7oLSg==}
      '@babel/core': 7.23.0
      babel-plugin-jsx-dom-expressions: 0.36.18(@babel/core@7.23.0)
  /browserslist@4.22.1:
    resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==}
      caniuse-lite: 1.0.30001546
      electron-to-chromium: 1.4.544
      update-browserslist-db: 1.0.13(browserslist@4.22.1)
  /bson@5.5.0:
    resolution: {integrity: sha512-B+QB4YmDx9RStKv8LLSl/aVIEV3nYJc3cJNNTK2Cd1TL+7P+cNpw9mAPeCgc5K+j01Dv6sxUzcITXDx7ZU3F0w==}
  /caniuse-lite@1.0.30001546:
    resolution: {integrity: sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==}
  /character-reference-invalid@2.0.1:
    resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
    dev: false

      fsevents: 2.3.3
  /ci-info@3.9.0:
    resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
  /citty@0.1.4:
    resolution: {integrity: sha512-Q3bK1huLxzQrvj7hImJ7Z1vKYJRPQCDnd0EjXfHMidcjecGOMuLrmuQmtWmFkuKLcMThlGh1yCKG8IEc6VeNXQ==}
    dependencies:
      consola: 3.2.3
    dev: true

  /cli-spinners@2.9.1:
    resolution: {integrity: sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==}
  /commander@7.2.0:
    resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
    engines: {node: '>= 10'}
    dev: false

  /convert-source-map@2.0.0:
    resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
      node-fetch: 2.7.0
  /css-select@4.3.0:
    resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==}
    dependencies:
      boolbase: 1.0.0
      css-what: 6.1.0
      domhandler: 4.3.1
      domutils: 2.8.0
      nth-check: 2.1.1
    dev: false

  /css-tree@1.1.3:
    resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
    engines: {node: '>=8.0.0'}
    dependencies:
      mdn-data: 2.0.14
      source-map: 0.6.1
    dev: false

  /csso@4.2.0:
    resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==}
    engines: {node: '>=8.0.0'}
    dependencies:
      css-tree: 1.1.3
    dev: false

  /data-uri-to-buffer@4.0.1:
    resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
    engines: {node: '>= 12'}
    dev: false

      '@babel/runtime': 7.23.1
      execa: 7.2.0
  /define-data-property@1.1.0:
    resolution: {integrity: sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==}
    engines: {node: '>= 0.4'}
    dependencies:
      get-intrinsic: 1.2.1
      gopd: 1.0.1
      has-property-descriptors: 1.0.0
    dev: true

  /define-properties@1.2.1:
    resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
      define-data-property: 1.1.0
  /devlop@1.1.0:
    resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
    dependencies:
      dequal: 2.0.3
    dev: false

  /dom-serializer@1.4.1:
    resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
    dependencies:
      domelementtype: 2.3.0
      domhandler: 4.3.1
      entities: 2.2.0
    dev: false

  /domhandler@4.3.1:
    resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
    engines: {node: '>= 4'}
    dependencies:
      domelementtype: 2.3.0
    dev: false

  /domutils@2.8.0:
    resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
    dependencies:
      dom-serializer: 1.4.1
      domelementtype: 2.3.0
      domhandler: 4.3.1
    dev: false

      dotenv: 16.3.1
  /dotenv@16.3.1:
    resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==}
  /electron-to-chromium@1.4.544:
    resolution: {integrity: sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==}
  /emmet@2.4.6:
    resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==}
  /entities@2.2.0:
    resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
    dev: false

      dotenv: 16.3.1
  /es-abstract@1.22.2:
    resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==}
      arraybuffer.prototype.slice: 1.0.2
      function.prototype.name: 1.1.6
      has: 1.0.4
      is-typed-array: 1.1.12
      regexp.prototype.flags: 1.5.1
      safe-array-concat: 1.0.1
      string.prototype.trim: 1.2.8
      string.prototype.trimend: 1.0.7
      string.prototype.trimstart: 1.0.7
      typed-array-buffer: 1.0.0
      typed-array-byte-length: 1.0.0
      typed-array-byte-offset: 1.0.0
      which-typed-array: 1.1.11
  /es-module-lexer@1.3.1:
    resolution: {integrity: sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==}
      has: 1.0.4
      has: 1.0.4
  /esbuild@0.19.4:
    resolution: {integrity: sha512-x7jL0tbRRpv4QUyuDMjONtWFciygUxWaUM1kMX2zWxI0X2YWOt7MSA0g4UdeSiHM8fcYVzpQhKYOycZwxTdZkA==}
      '@esbuild/android-arm': 0.19.4
      '@esbuild/android-arm64': 0.19.4
      '@esbuild/android-x64': 0.19.4
      '@esbuild/darwin-arm64': 0.19.4
      '@esbuild/darwin-x64': 0.19.4
      '@esbuild/freebsd-arm64': 0.19.4
      '@esbuild/freebsd-x64': 0.19.4
      '@esbuild/linux-arm': 0.19.4
      '@esbuild/linux-arm64': 0.19.4
      '@esbuild/linux-ia32': 0.19.4
      '@esbuild/linux-loong64': 0.19.4
      '@esbuild/linux-mips64el': 0.19.4
      '@esbuild/linux-ppc64': 0.19.4
      '@esbuild/linux-riscv64': 0.19.4
      '@esbuild/linux-s390x': 0.19.4
      '@esbuild/linux-x64': 0.19.4
      '@esbuild/netbsd-x64': 0.19.4
      '@esbuild/openbsd-x64': 0.19.4
      '@esbuild/sunos-x64': 0.19.4
      '@esbuild/win32-arm64': 0.19.4
      '@esbuild/win32-ia32': 0.19.4
      '@esbuild/win32-x64': 0.19.4
  /eslint-config-xtrict@3.0.1(eslint@8.45.0)(prettier@3.0.2)(typescript@5.2.2):
      '@typescript-eslint/eslint-plugin': 3.10.1(@typescript-eslint/parser@3.10.1)(eslint@8.45.0)(typescript@5.2.2)
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
      typescript: 5.2.2
  /eslint-import-resolver-node@0.3.9:
    resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
      is-core-module: 2.13.0
      resolve: 1.22.6
  /eslint-module-utils@2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0):
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
      eslint-import-resolver-node: 0.3.9
  /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0):
      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
      eslint-import-resolver-node: 0.3.9
      '@typescript-eslint/parser': 3.10.1(eslint@8.45.0)(typescript@5.2.2)
      array-includes: 3.1.7
      array.prototype.flat: 1.3.2
      array.prototype.flatmap: 1.3.2
      eslint-import-resolver-node: 0.3.9
      eslint-module-utils: 2.8.0(@typescript-eslint/parser@3.10.1)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0)
      has: 1.0.4
      is-core-module: 2.13.0
      object.values: 1.1.7
      resolve: 1.22.6
      semver: 6.3.1
      '@typescript-eslint/parser': 6.2.0(eslint@8.45.0)(typescript@5.2.2)
      array-includes: 3.1.7
      array.prototype.flat: 1.3.2
      array.prototype.flatmap: 1.3.2
      eslint-import-resolver-node: 0.3.9
      eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.2.0)(eslint-import-resolver-node@0.3.9)(eslint@8.45.0)
      has: 1.0.4
      is-core-module: 2.13.0
      object.values: 1.1.7
      resolve: 1.22.6
      semver: 6.3.1
  /eslint-plugin-solid@0.12.1(eslint@8.45.0)(typescript@5.2.2):
      '@typescript-eslint/utils': 5.62.0(eslint@8.45.0)(typescript@5.2.2)
      jsx-ast-utils: 3.3.5
  /eslint-scope@7.2.2:
    resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
      '@babel/core': 7.23.0
      '@babel/eslint-parser': 7.22.15(@babel/core@7.23.0)(eslint@8.45.0)
  /eslint-visitor-keys@3.4.3:
    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
      '@eslint-community/regexpp': 4.9.1
      '@eslint/eslintrc': 2.1.2
      '@humanwhocodes/config-array': 0.11.11
      eslint-scope: 7.2.2
      eslint-visitor-keys: 3.4.3
      globals: 13.23.0
      eslint-visitor-keys: 3.4.3
  /estree-util-attach-comments@2.1.1:
    resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==}
    dependencies:
      '@types/estree': 1.0.2
    dev: false

  /estree-util-build-jsx@2.2.2:
    resolution: {integrity: sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      estree-util-is-identifier-name: 2.1.0
      estree-walker: 3.0.3
    dev: false

  /estree-util-is-identifier-name@2.1.0:
    resolution: {integrity: sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==}
    dev: false

  /estree-util-to-js@1.2.0:
    resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      astring: 1.8.6
      source-map: 0.7.4
    dev: false

  /estree-util-visit@1.2.1:
    resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/unist': 2.0.8
    dev: false

      '@types/estree': 1.0.2
  /execa@7.2.0:
    resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==}
  /fast-content-type-parse@1.1.0:
    resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==}
  /fast-json-stringify@5.8.0:
    resolution: {integrity: sha512-VVwK8CFMSALIvt14U8AvrSzQAwN/0vaVRiFFUVlpnXSnDGrSkOAO5MtzyN8oQNjLd5AqTW5OZRgyjoNuAuR3jQ==}
  /fast-jwt@3.3.1:
    resolution: {integrity: sha512-1YuuIJeh1hEvfcYDe89P2oGACWI5hd2GadRDKHalSxkc1Z0z8I6yzuVK6SF15sW09QZngTV6d7g4+TFL9bvs5A==}
    engines: {node: '>=16 <22'}
      '@lukeed/ms': 2.0.1
  /fast-redact@3.3.0:
    resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==}
  /fastify-plugin@4.5.1:
    resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==}
      '@fastify/error': 3.4.0
      fast-content-type-parse: 1.1.0
      fast-json-stringify: 5.8.0
      light-my-request: 5.11.0
      pino: 8.15.6
      tiny-lru: 11.2.2
  /fault@2.0.1:
    resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
    dependencies:
      format: 0.2.2
    dev: false

  /fetch-blob@3.2.0:
    resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
    engines: {node: ^12.20 || >= 14.13}
    dependencies:
      node-domexception: 1.0.0
      web-streams-polyfill: 3.2.1
    dev: false

      flat-cache: 3.1.1
  /flat-cache@3.1.1:
    resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==}
    engines: {node: '>=12.0.0'}
      flatted: 3.2.9
      keyv: 4.5.4
  /flatted@3.2.9:
    resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
  /follow-redirects@1.15.3:
    resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==}
      signal-exit: 4.1.0
  /format@0.2.2:
    resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
    engines: {node: '>=0.4.x'}
    dev: false

  /formdata-polyfill@4.0.10:
    resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
    engines: {node: '>=12.20.0'}
    dependencies:
      fetch-blob: 3.2.0
    dev: false

  /fsevents@2.3.3:
    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
  /function.prototype.name@1.1.6:
    resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
      has: 1.0.4
      jackspeak: 2.3.6
      minipass: 7.0.4
  /globals@13.23.0:
    resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==}
      define-properties: 1.2.1
  /globby@13.2.2:
    resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==}
  /graphql-request@5.2.0(graphql@16.8.1):
      '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1)
      graphql: 16.8.1
  /graphql@16.8.1:
    resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==}
  /h3@1.8.2:
    resolution: {integrity: sha512-1Ca0orJJlCaiFY68BvzQtP2lKLk46kcLAxVM8JgYbtm2cUg6IY7pjpYgWMwUvDO9QI30N5JAukOKoT8KD3Q0PQ==}
      destr: 2.0.1
      iron-webcrypto: 0.10.1
      radix3: 1.1.0
      ufo: 1.3.1
      unenv: 1.7.4
  /has@1.0.4:
    resolution: {integrity: sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==}
      '@types/hast': 2.3.6
      '@types/unist': 2.0.8
      property-information: 6.3.0
  /hast-util-from-parse5@8.0.1:
    resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==}
    dependencies:
      '@types/hast': 3.0.1
      '@types/unist': 3.0.0
      devlop: 1.1.0
      hastscript: 8.0.0
      property-information: 6.3.0
      vfile: 6.0.1
      vfile-location: 5.0.2
      web-namespaces: 2.0.1
    dev: false

      '@types/hast': 2.3.6

  /hast-util-parse-selector@4.0.0:
    resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
    dependencies:
      '@types/hast': 3.0.1
    dev: false
      '@types/hast': 2.3.6
  /hast-util-raw@9.0.1:
    resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==}
    dependencies:
      '@types/hast': 3.0.1
      '@types/unist': 3.0.0
      '@ungap/structured-clone': 1.2.0
      hast-util-from-parse5: 8.0.1
      hast-util-to-parse5: 8.0.0
      html-void-elements: 3.0.0
      mdast-util-to-hast: 13.0.2
      parse5: 7.1.2
      unist-util-position: 5.0.0
      unist-util-visit: 5.0.0
      vfile: 6.0.1
      web-namespaces: 2.0.1
      zwitch: 2.0.4
    dev: false

  /hast-util-to-estree@2.3.3:
    resolution: {integrity: sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==}
    dependencies:
      '@types/estree': 1.0.2
      '@types/estree-jsx': 1.0.1
      '@types/hast': 2.3.6
      '@types/unist': 2.0.8
      comma-separated-tokens: 2.0.3
      estree-util-attach-comments: 2.1.1
      estree-util-is-identifier-name: 2.1.0
      hast-util-whitespace: 2.0.1
      mdast-util-mdx-expression: 1.3.2
      mdast-util-mdxjs-esm: 1.3.1
      property-information: 6.3.0
      space-separated-tokens: 2.0.2
      style-to-object: 0.4.1
      unist-util-position: 4.0.4
      zwitch: 2.0.4
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/hast': 2.3.6
      '@types/unist': 2.0.8
      property-information: 6.3.0
  /hast-util-to-html@9.0.0:
    resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==}
      '@types/hast': 3.0.1
      '@types/unist': 3.0.0
      ccount: 2.0.1
      hast-util-raw: 9.0.1
      hast-util-whitespace: 3.0.0
      html-void-elements: 3.0.0
      mdast-util-to-hast: 13.0.2
      property-information: 6.3.0
      stringify-entities: 4.0.3
    dev: false

  /hast-util-to-parse5@7.1.0:
    resolution: {integrity: sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==}
    dependencies:
      '@types/hast': 2.3.6
      comma-separated-tokens: 2.0.3
      property-information: 6.3.0
      space-separated-tokens: 2.0.2
      web-namespaces: 2.0.1
      zwitch: 2.0.4

  /hast-util-to-parse5@8.0.0:
    resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
    dependencies:
      '@types/hast': 3.0.1
      comma-separated-tokens: 2.0.3
      devlop: 1.1.0
      property-information: 6.3.0
      space-separated-tokens: 2.0.2
      web-namespaces: 2.0.1
      zwitch: 2.0.4
    dev: false
  /hast-util-whitespace@3.0.0:
    resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
    dependencies:
      '@types/hast': 3.0.1
    dev: false

      '@types/hast': 2.3.6
      property-information: 6.3.0
  /hastscript@8.0.0:
    resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==}
    dependencies:
      '@types/hast': 3.0.1
      comma-separated-tokens: 2.0.3
      hast-util-parse-selector: 4.0.0
      property-information: 6.3.0
      space-separated-tokens: 2.0.2
    dev: false

  /headers-polyfill@3.3.0:
    resolution: {integrity: sha512-5e57etwBpNcDc0b6KCVWEh/Ro063OxPvzVimUdM0/tsYM/T7Hfy3kknIGj78SFTOhNd8AZY41U8mOHoO4LzmIQ==}
  /html-void-elements@3.0.0:
    resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
    dev: false

  /immutable@4.3.4:
    resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==}
      has: 1.0.4
  /iron-webcrypto@0.10.1:
    resolution: {integrity: sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA==}
    dev: false

  /is-alphabetical@2.0.1:
    resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
    dev: false

  /is-alphanumerical@2.0.1:
    resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
    dependencies:
      is-alphabetical: 2.0.1
      is-decimal: 2.0.1
      is-typed-array: 1.1.12
      has: 1.0.4
  /is-decimal@2.0.1:
    resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
    dev: false

  /is-hexadecimal@2.0.1:
    resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
    dev: false

      '@types/estree': 1.0.2
  /is-reference@3.0.2:
    resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==}
    dependencies:
      '@types/estree': 1.0.2
    dev: false

  /is-typed-array@1.1.12:
    resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
      which-typed-array: 1.1.11
  /is-wsl@3.1.0:
    resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==}
      is-inside-container: 1.0.0
  /isarray@2.0.5:
    resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
    dev: true

      node-fetch: 2.7.0
      whatwg-fetch: 3.6.19
      node-fetch: 2.7.0
  /jackspeak@2.3.6:
    resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
  /jiti@1.20.0:
    resolution: {integrity: sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==}
  /joi@17.11.0:
    resolution: {integrity: sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==}
  /json-buffer@3.0.1:
    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
    dev: true

  /jsonwebtoken@9.0.2:
    resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
      lodash.includes: 4.3.0
      lodash.isboolean: 3.0.3
      lodash.isinteger: 4.0.4
      lodash.isnumber: 3.0.3
      lodash.isplainobject: 4.0.6
      lodash.isstring: 4.0.1
      lodash.once: 4.1.1
  /jssha@3.3.1:
    resolution: {integrity: sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==}
  /jsx-ast-utils@3.3.5:
    resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
      array-includes: 3.1.7
      array.prototype.flat: 1.3.2
      object.values: 1.1.7
  /keyv@4.5.4:
    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
    dependencies:
      json-buffer: 3.0.1
    dev: true

  /lib0@0.2.86:
    resolution: {integrity: sha512-kxigQTM4Q7NwJkEgdqQvU21qiR37twcqqLmh+/SbiGbRLfPlLVbHyY9sWp7PwXh0Xus9ELDSjsUOwcrdt5yZ4w==}
  /light-my-request@5.11.0:
    resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==}
  /lodash.includes@4.3.0:
    resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
    dev: false

  /lodash.isboolean@3.0.3:
    resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
    dev: false

  /lodash.isinteger@4.0.4:
    resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
    dev: false

  /lodash.isnumber@3.0.3:
    resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
    dev: false

  /lodash.isplainobject@4.0.6:
    resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
    dev: false

  /lodash.isstring@4.0.1:
    resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
    dev: false

  /lodash.once@4.1.1:
    resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
    dev: false

    dev: true
  /lru-cache@10.0.1:
    resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==}
  /magic-string@0.30.4:
    resolution: {integrity: sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==}
  /markdown-extensions@1.1.1:
    resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==}
    engines: {node: '>=0.10.0'}
    dev: false

  /markdown-it@13.0.2:
    resolution: {integrity: sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==}
      '@types/mdast': 3.0.13
      '@types/unist': 2.0.8
      '@types/mdast': 4.0.1
      '@types/mdast': 3.0.13
  /mdast-util-find-and-replace@3.0.1:
    resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==}
    dependencies:
      '@types/mdast': 4.0.1
      escape-string-regexp: 5.0.0
      unist-util-is: 6.0.0
      unist-util-visit-parents: 6.0.1
    dev: false

      '@types/mdast': 3.0.13
      '@types/unist': 2.0.8
  /mdast-util-from-markdown@2.0.0:
    resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==}
    dependencies:
      '@types/mdast': 4.0.1
      '@types/unist': 3.0.0
      decode-named-character-reference: 1.0.2
      devlop: 1.1.0
      mdast-util-to-string: 4.0.0
      micromark: 4.0.0
      micromark-util-decode-numeric-character-reference: 2.0.0
      micromark-util-decode-string: 2.0.0
      micromark-util-normalize-identifier: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
      unist-util-stringify-position: 4.0.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-frontmatter@2.0.1:
    resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==}
    dependencies:
      '@types/mdast': 4.0.1
      devlop: 1.1.0
      escape-string-regexp: 5.0.0
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
      micromark-extension-frontmatter: 2.0.0
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/mdast': 3.0.13
  /mdast-util-gfm-autolink-literal@2.0.0:
    resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==}
    dependencies:
      '@types/mdast': 4.0.1
      ccount: 2.0.1
      devlop: 1.1.0
      mdast-util-find-and-replace: 3.0.1
      micromark-util-character: 2.0.1
    dev: false

      '@types/mdast': 3.0.13
  /mdast-util-gfm-footnote@2.0.0:
    resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==}
    dependencies:
      '@types/mdast': 4.0.1
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
      micromark-util-normalize-identifier: 2.0.0
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/mdast': 3.0.13
  /mdast-util-gfm-strikethrough@2.0.0:
    resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
    dependencies:
      '@types/mdast': 4.0.1
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/mdast': 3.0.13
  /mdast-util-gfm-table@2.0.0:
    resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
    dependencies:
      '@types/mdast': 4.0.1
      devlop: 1.1.0
      markdown-table: 3.0.3
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/mdast': 3.0.13
  /mdast-util-gfm-task-list-item@2.0.0:
    resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
    dependencies:
      '@types/mdast': 4.0.1
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-gfm@3.0.0:
    resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==}
    dependencies:
      mdast-util-from-markdown: 2.0.0
      mdast-util-gfm-autolink-literal: 2.0.0
      mdast-util-gfm-footnote: 2.0.0
      mdast-util-gfm-strikethrough: 2.0.0
      mdast-util-gfm-table: 2.0.0
      mdast-util-gfm-task-list-item: 2.0.0
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdx-expression@1.3.2:
    resolution: {integrity: sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/hast': 2.3.6
      '@types/mdast': 3.0.13
      mdast-util-from-markdown: 1.3.1
      mdast-util-to-markdown: 1.5.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdx-expression@2.0.0:
    resolution: {integrity: sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/hast': 3.0.1
      '@types/mdast': 4.0.1
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdx-jsx@2.1.4:
    resolution: {integrity: sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/hast': 2.3.6
      '@types/mdast': 3.0.13
      '@types/unist': 2.0.8
      ccount: 2.0.1
      mdast-util-from-markdown: 1.3.1
      mdast-util-to-markdown: 1.5.0
      parse-entities: 4.0.1
      stringify-entities: 4.0.3
      unist-util-remove-position: 4.0.2
      unist-util-stringify-position: 3.0.3
      vfile-message: 3.1.4
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdx-jsx@3.0.0:
    resolution: {integrity: sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/hast': 3.0.1
      '@types/mdast': 4.0.1
      '@types/unist': 3.0.0
      ccount: 2.0.1
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
      parse-entities: 4.0.1
      stringify-entities: 4.0.3
      unist-util-remove-position: 5.0.0
      unist-util-stringify-position: 4.0.0
      vfile-message: 4.0.2
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdx@2.0.1:
    resolution: {integrity: sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==}
    dependencies:
      mdast-util-from-markdown: 1.3.1
      mdast-util-mdx-expression: 1.3.2
      mdast-util-mdx-jsx: 2.1.4
      mdast-util-mdxjs-esm: 1.3.1
      mdast-util-to-markdown: 1.5.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdx@3.0.0:
    resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==}
    dependencies:
      mdast-util-from-markdown: 2.0.0
      mdast-util-mdx-expression: 2.0.0
      mdast-util-mdx-jsx: 3.0.0
      mdast-util-mdxjs-esm: 2.0.1
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdxjs-esm@1.3.1:
    resolution: {integrity: sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/hast': 2.3.6
      '@types/mdast': 3.0.13
      mdast-util-from-markdown: 1.3.1
      mdast-util-to-markdown: 1.5.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /mdast-util-mdxjs-esm@2.0.1:
    resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
    dependencies:
      '@types/estree-jsx': 1.0.1
      '@types/hast': 3.0.1
      '@types/mdast': 4.0.1
      devlop: 1.1.0
      mdast-util-from-markdown: 2.0.0
      mdast-util-to-markdown: 2.1.0
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/mdast': 3.0.13
  /mdast-util-phrasing@4.0.0:
    resolution: {integrity: sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==}
    dependencies:
      '@types/mdast': 4.0.1
      unist-util-is: 6.0.0
    dev: false

      '@types/hast': 2.3.6
      '@types/mdast': 3.0.13
  /mdast-util-to-hast@13.0.2:
    resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==}
    dependencies:
      '@types/hast': 3.0.1
      '@types/mdast': 4.0.1
      '@ungap/structured-clone': 1.2.0
      devlop: 1.1.0
      micromark-util-sanitize-uri: 2.0.0
      trim-lines: 3.0.1
      unist-util-position: 5.0.0
      unist-util-visit: 5.0.0
    dev: false

      '@types/mdast': 3.0.13
      '@types/unist': 2.0.8
  /mdast-util-to-markdown@2.1.0:
    resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==}
    dependencies:
      '@types/mdast': 4.0.1
      '@types/unist': 3.0.0
      longest-streak: 3.1.0
      mdast-util-phrasing: 4.0.0
      mdast-util-to-string: 4.0.0
      micromark-util-decode-string: 2.0.0
      unist-util-visit: 5.0.0
      zwitch: 2.0.4
    dev: false

      '@types/mdast': 3.0.13

  /mdast-util-to-string@4.0.0:
    resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
    dependencies:
      '@types/mdast': 4.0.1
    dev: false

  /mdn-data@2.0.14:
    resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
    dev: false
  /micromark-core-commonmark@2.0.0:
    resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==}
    dependencies:
      decode-named-character-reference: 1.0.2
      devlop: 1.1.0
      micromark-factory-destination: 2.0.0
      micromark-factory-label: 2.0.0
      micromark-factory-space: 2.0.0
      micromark-factory-title: 2.0.0
      micromark-factory-whitespace: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-chunked: 2.0.0
      micromark-util-classify-character: 2.0.0
      micromark-util-html-tag-name: 2.0.0
      micromark-util-normalize-identifier: 2.0.0
      micromark-util-resolve-all: 2.0.0
      micromark-util-subtokenize: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-frontmatter@2.0.0:
    resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==}
    dependencies:
      fault: 2.0.1
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm-autolink-literal@2.0.0:
    resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==}
    dependencies:
      micromark-util-character: 2.0.1
      micromark-util-sanitize-uri: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm-footnote@2.0.0:
    resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==}
    dependencies:
      devlop: 1.1.0
      micromark-core-commonmark: 2.0.0
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-normalize-identifier: 2.0.0
      micromark-util-sanitize-uri: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm-strikethrough@2.0.0:
    resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==}
    dependencies:
      devlop: 1.1.0
      micromark-util-chunked: 2.0.0
      micromark-util-classify-character: 2.0.0
      micromark-util-resolve-all: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm-table@2.0.0:
    resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==}
    dependencies:
      devlop: 1.1.0
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm-tagfilter@2.0.0:
    resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
    dependencies:
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm-task-list-item@2.0.1:
    resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==}
    dependencies:
      devlop: 1.1.0
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-gfm@3.0.0:
    resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
    dependencies:
      micromark-extension-gfm-autolink-literal: 2.0.0
      micromark-extension-gfm-footnote: 2.0.0
      micromark-extension-gfm-strikethrough: 2.0.0
      micromark-extension-gfm-table: 2.0.0
      micromark-extension-gfm-tagfilter: 2.0.0
      micromark-extension-gfm-task-list-item: 2.0.1
      micromark-util-combine-extensions: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-mdx-expression@1.0.8:
    resolution: {integrity: sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==}
    dependencies:
      '@types/estree': 1.0.2
      micromark-factory-mdx-expression: 1.0.9
      micromark-factory-space: 1.1.0
      micromark-util-character: 1.2.0
      micromark-util-events-to-acorn: 1.2.3
      micromark-util-symbol: 1.1.0
      micromark-util-types: 1.1.0
      uvu: 0.5.6
    dev: false

  /micromark-extension-mdx-expression@2.0.0:
    resolution: {integrity: sha512-hUI6PJCCVaymBF5paL29sOpcbtVXtumDdJgBDxN+tbHlXAqQwNl4EhhJfx4fe7bUpEZzcFRIBAeOiGq7hsZBXw==}
    dependencies:
      '@types/estree': 1.0.2
      devlop: 1.1.0
      micromark-factory-mdx-expression: 2.0.1
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-events-to-acorn: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-mdx-jsx@1.0.5:
    resolution: {integrity: sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==}
    dependencies:
      '@types/acorn': 4.0.6
      '@types/estree': 1.0.2
      estree-util-is-identifier-name: 2.1.0
      micromark-factory-mdx-expression: 1.0.9
      micromark-factory-space: 1.1.0
      micromark-util-character: 1.2.0
      micromark-util-symbol: 1.1.0
      micromark-util-types: 1.1.0
      uvu: 0.5.6
      vfile-message: 3.1.4
    dev: false

  /micromark-extension-mdx-jsx@2.0.0:
    resolution: {integrity: sha512-hp6ff4eympWcq3Jh9XIJmJPNpM2RNmBjz5vvU1YkND7h4UwjSZas7lXSrAJjtTG7Z56JMMTyowwcbPkAjZmwMg==}
    dependencies:
      '@types/acorn': 4.0.6
      '@types/estree': 1.0.2
      devlop: 1.1.0
      estree-util-is-identifier-name: 2.1.0
      micromark-factory-mdx-expression: 2.0.1
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
      vfile-message: 4.0.2
    dev: false

  /micromark-extension-mdx-md@1.0.1:
    resolution: {integrity: sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==}
    dependencies:
      micromark-util-types: 1.1.0
    dev: false

  /micromark-extension-mdx-md@2.0.0:
    resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==}
    dependencies:
      micromark-util-types: 2.0.0
    dev: false

  /micromark-extension-mdxjs-esm@1.0.5:
    resolution: {integrity: sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==}
    dependencies:
      '@types/estree': 1.0.2
      micromark-core-commonmark: 1.1.0
      micromark-util-character: 1.2.0
      micromark-util-events-to-acorn: 1.2.3
      micromark-util-symbol: 1.1.0
      micromark-util-types: 1.1.0
      unist-util-position-from-estree: 1.1.2
      uvu: 0.5.6
      vfile-message: 3.1.4
    dev: false

  /micromark-extension-mdxjs-esm@2.0.1:
    resolution: {integrity: sha512-HLPrY5XLYzFtG5KxEcZXfUV/SOy9Eu3R+dnpP1P6ko/ZO9xceGxmgJOAMq4r/rPLrHaEosfhNIOXDcvFSkVfKQ==}
    dependencies:
      '@types/estree': 1.0.2
      devlop: 1.1.0
      micromark-core-commonmark: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-events-to-acorn: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
      unist-util-position-from-estree: 2.0.0
      vfile-message: 4.0.2
    dev: false

  /micromark-extension-mdxjs@1.0.1:
    resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==}
    dependencies:
      acorn: 8.10.0
      acorn-jsx: 5.3.2(acorn@8.10.0)
      micromark-extension-mdx-expression: 1.0.8
      micromark-extension-mdx-jsx: 1.0.5
      micromark-extension-mdx-md: 1.0.1
      micromark-extension-mdxjs-esm: 1.0.5
      micromark-util-combine-extensions: 1.1.0
      micromark-util-types: 1.1.0
    dev: false

  /micromark-extension-mdxjs@2.0.0:
    resolution: {integrity: sha512-cICbQUdcgFvfg3JH9XTqZoa1ONCZI0GsiOvl9672Ka3SilIo9kMmaKLdSd/QrDgNGxrirWtZfFh19DSKJUivWQ==}
    dependencies:
      acorn: 8.10.0
      acorn-jsx: 5.3.2(acorn@8.10.0)
      micromark-extension-mdx-expression: 2.0.0
      micromark-extension-mdx-jsx: 2.0.0
      micromark-extension-mdx-md: 2.0.0
      micromark-extension-mdxjs-esm: 2.0.1
      micromark-util-combine-extensions: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-factory-destination@2.0.0:
    resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
    dependencies:
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-factory-label@2.0.0:
    resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==}
    dependencies:
      devlop: 1.1.0
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-factory-mdx-expression@1.0.9:
    resolution: {integrity: sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==}
    dependencies:
      '@types/estree': 1.0.2
      micromark-util-character: 1.2.0
      micromark-util-events-to-acorn: 1.2.3
      micromark-util-symbol: 1.1.0
      micromark-util-types: 1.1.0
      unist-util-position-from-estree: 1.1.2
      uvu: 0.5.6
      vfile-message: 3.1.4
    dev: false

  /micromark-factory-mdx-expression@2.0.1:
    resolution: {integrity: sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==}
    dependencies:
      '@types/estree': 1.0.2
      devlop: 1.1.0
      micromark-util-character: 2.0.1
      micromark-util-events-to-acorn: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
      unist-util-position-from-estree: 2.0.0
      vfile-message: 4.0.2
    dev: false

  /micromark-factory-space@2.0.0:
    resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==}
    dependencies:
      micromark-util-character: 2.0.1
      micromark-util-types: 2.0.0
    dev: false

  /micromark-factory-title@2.0.0:
    resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==}
    dependencies:
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-factory-whitespace@2.0.0:
    resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==}
    dependencies:
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-util-character@2.0.1:
    resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==}
    dependencies:
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-util-chunked@2.0.0:
    resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==}
    dependencies:
      micromark-util-symbol: 2.0.0
    dev: false

  /micromark-util-classify-character@2.0.0:
    resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==}
    dependencies:
      micromark-util-character: 2.0.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-util-combine-extensions@2.0.0:
    resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==}
    dependencies:
      micromark-util-chunked: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-util-decode-numeric-character-reference@2.0.0:
    resolution: {integrity: sha512-pIgcsGxpHEtTG/rPJRz/HOLSqp5VTuIIjXlPI+6JSDlK2oljApusG6KzpS8AF0ENUMCHlC/IBb5B9xdFiVlm5Q==}
    dependencies:
      micromark-util-symbol: 2.0.0
    dev: false

  /micromark-util-decode-string@2.0.0:
    resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==}
    dependencies:
      decode-named-character-reference: 1.0.2
      micromark-util-character: 2.0.1
      micromark-util-decode-numeric-character-reference: 2.0.0
      micromark-util-symbol: 2.0.0
    dev: false

  /micromark-util-encode@2.0.0:
    resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==}
    dev: false

  /micromark-util-events-to-acorn@1.2.3:
    resolution: {integrity: sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==}
    dependencies:
      '@types/acorn': 4.0.6
      '@types/estree': 1.0.2
      '@types/unist': 2.0.8
      estree-util-visit: 1.2.1
      micromark-util-symbol: 1.1.0
      micromark-util-types: 1.1.0
      uvu: 0.5.6
      vfile-message: 3.1.4
    dev: false

  /micromark-util-events-to-acorn@2.0.1:
    resolution: {integrity: sha512-3pf0pxvFaTxzTwisMHmEk5lnW7oSU/oRZxpZcrdx/voJgCpPaspexc89mJodW4ekATo1UILtZvjESclKONSB6w==}
    dependencies:
      '@types/acorn': 4.0.6
      '@types/estree': 1.0.2
      '@types/unist': 3.0.0
      devlop: 1.1.0
      estree-util-visit: 1.2.1
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
      vfile-message: 4.0.2
    dev: false

  /micromark-util-html-tag-name@2.0.0:
    resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==}
    dev: false

  /micromark-util-normalize-identifier@2.0.0:
    resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==}
    dependencies:
      micromark-util-symbol: 2.0.0
    dev: false

  /micromark-util-resolve-all@2.0.0:
    resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==}
    dependencies:
      micromark-util-types: 2.0.0
    dev: false

  /micromark-util-sanitize-uri@2.0.0:
    resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==}
    dependencies:
      micromark-util-character: 2.0.1
      micromark-util-encode: 2.0.0
      micromark-util-symbol: 2.0.0
    dev: false

  /micromark-util-subtokenize@2.0.0:
    resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==}
    dependencies:
      devlop: 1.1.0
      micromark-util-chunked: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    dev: false

  /micromark-util-symbol@2.0.0:
    resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==}
    dev: false

  /micromark-util-types@2.0.0:
    resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==}
    dev: false

      '@types/debug': 4.1.9
  /micromark@4.0.0:
    resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==}
    dependencies:
      '@types/debug': 4.1.9
      debug: 4.3.4
      decode-named-character-reference: 1.0.2
      devlop: 1.1.0
      micromark-core-commonmark: 2.0.0
      micromark-factory-space: 2.0.0
      micromark-util-character: 2.0.1
      micromark-util-chunked: 2.0.0
      micromark-util-combine-extensions: 2.0.0
      micromark-util-decode-numeric-character-reference: 2.0.0
      micromark-util-encode: 2.0.0
      micromark-util-normalize-identifier: 2.0.0
      micromark-util-resolve-all: 2.0.0
      micromark-util-sanitize-uri: 2.0.0
      micromark-util-subtokenize: 2.0.0
      micromark-util-symbol: 2.0.0
      micromark-util-types: 2.0.0
    transitivePeerDependencies:
      - supports-color
    dev: false

  /minipass@7.0.4:
    resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
  /mkdist@1.3.0(typescript@5.2.2):
    resolution: {integrity: sha512-ZQrUvcL7LkRdzMREpDyg9AT18N9Tl5jc2qeKAUeEw0KGsgykbHbuRvysGAzTuGtwuSg0WQyNit5jh/k+Er3JEg==}
      sass: ^1.63.6
      typescript: '>=5.1.6'
      citty: 0.1.4
      esbuild: 0.18.16
      globby: 13.2.2
      jiti: 1.20.0
      ufo: 1.3.1
  /monaco-editor@0.43.0:
    resolution: {integrity: sha512-cnoqwQi/9fml2Szamv1XbSJieGJ1Dc8tENVMD26Kcfl7xGQWp7OBKMjlwKVGYFJ3/AXJjSOGvcqK7Ry/j9BM1Q==}
      bson: 5.5.0
      sax: 1.3.0
      '@types/nlcst': 1.0.2
  /node-fetch@2.7.0:
    resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
  /node-fetch@3.3.2:
    resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
    dependencies:
      data-uri-to-buffer: 4.0.1
      fetch-blob: 3.2.0
      formdata-polyfill: 4.0.10
    dev: false

  /node-mocks-http@1.13.0:
    resolution: {integrity: sha512-lArD6sJMPJ53WF50GX0nJ89B1nkV1TdMvNwq8WXXFrUXF80ujSyye1T30mgiHh4h2It0/svpF3C4kZ2OAONVlg==}
    engines: {node: '>=14'}
      resolve: 1.22.6
      semver: 5.7.2
      define-properties: 1.2.1
  /object.values@1.1.7:
    resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
      '@octokit/app': 14.0.1
      '@octokit/core': 5.0.1
      '@octokit/plugin-paginate-rest': 8.0.0(@octokit/core@5.0.1)
      '@octokit/plugin-rest-endpoint-methods': 9.0.0(@octokit/core@5.0.1)
      '@octokit/plugin-retry': 6.0.1(@octokit/core@5.0.1)
      '@octokit/plugin-throttling': 7.0.0(@octokit/core@5.0.1)
      '@octokit/request-error': 5.0.1
      ufo: 1.3.1
  /on-exit-leak-free@2.1.2:
    resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
    engines: {node: '>=14.0.0'}
      undici: 5.25.4
      validator: 13.11.0
      '@types/node': 18.18.4
      '@types/node-fetch': 2.6.6
      node-fetch: 2.7.0
      cli-spinners: 2.9.1
      cli-spinners: 2.9.1
      cli-spinners: 2.9.1
      jssha: 3.3.1
  /parse-entities@4.0.1:
    resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==}
    dependencies:
      '@types/unist': 2.0.8
      character-entities: 2.0.2
      character-entities-legacy: 3.0.0
      character-reference-invalid: 2.0.1
      decode-named-character-reference: 1.0.2
      is-alphanumerical: 2.0.1
      is-decimal: 2.0.1
      is-hexadecimal: 2.0.1
    dev: false

      lru-cache: 10.0.1
      minipass: 7.0.4
  /periscopic@3.1.0:
    resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==}
    dependencies:
      '@types/estree': 1.0.2
      estree-walker: 3.0.3
      is-reference: 3.0.2
    dev: false

  /pino-abstract-transport@1.1.0:
    resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==}
      readable-stream: 4.4.2
  /pino-std-serializers@6.2.2:
    resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==}
  /pino@8.15.6:
    resolution: {integrity: sha512-GuxHr61R0ZFD1npu58tB3a3FSVjuy21OwN/haw4OuKiZBL63Pg11Y51WWeD52RENS2mjwPZOwt+2OQOSkck6kQ==}
      fast-redact: 3.3.0
      on-exit-leak-free: 2.1.2
      pino-abstract-transport: 1.1.0
      pino-std-serializers: 6.2.2
      sonic-boom: 3.6.1
      thread-stream: 2.4.1
      resolve: 1.22.6
  /postcss@8.4.31:
    resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
      '@astrojs/compiler': 1.8.2
      sass-formatter: 0.7.8
      sass-formatter: 0.7.8
  /pretty-bytes@6.1.1:
    resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
  /property-information@6.3.0:
    resolution: {integrity: sha512-gVNZ74nqhRMiIUYWGQdosYetaKc83x8oT41a0LlV3AAFCAZwCpg4vmGkq8t34+cUhp3cnM4XDiU/7xlgK7HGrg==}
      prosemirror-transform: 1.8.0
      prosemirror-model: 1.19.3
      prosemirror-transform: 1.8.0
      prosemirror-transform: 1.8.0
      prosemirror-view: 1.32.0
      prosemirror-model: 1.19.3
      prosemirror-view: 1.32.0
      prosemirror-transform: 1.8.0
      prosemirror-view: 1.32.0
      prosemirror-transform: 1.8.0
  /prosemirror-markdown@1.11.2:
    resolution: {integrity: sha512-Eu5g4WPiCdqDTGhdSsG9N6ZjACQRYrsAkrF9KYfdMaCmjIApH75aVncsWYOJvEk2i1B3i8jZppv3J/tnuHGiUQ==}
      markdown-it: 13.0.2
      prosemirror-model: 1.19.3
  /prosemirror-menu@1.2.4:
    resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==}
  /prosemirror-model@1.19.3:
    resolution: {integrity: sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ==}
      prosemirror-model: 1.19.3
      prosemirror-model: 1.19.3
      prosemirror-transform: 1.8.0
      prosemirror-model: 1.19.3
      prosemirror-transform: 1.8.0
      prosemirror-view: 1.32.0
  /prosemirror-tables@1.3.4:
    resolution: {integrity: sha512-z6uLSQ1BLC3rgbGwZmpfb+xkdvD7W/UOsURDfognZFYaTtc0gsk7u/t71Yijp2eLflVpffMk6X0u0+u+MMDvIw==}
      prosemirror-model: 1.19.3
      prosemirror-transform: 1.8.0
      prosemirror-view: 1.32.0
  /prosemirror-trailing-node@2.0.7(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0):
    resolution: {integrity: sha512-8zcZORYj/8WEwsGo6yVCRXFMOfBo0Ub3hCUvmoWIZYfMP26WqENU0mpEP27w7mt8buZWuGrydBewr0tOArPb1Q==}
      prosemirror-view: ^1.31.2
      '@remirror/core-constants': 2.0.2
      '@remirror/core-helpers': 3.0.0
      prosemirror-model: 1.19.3
      prosemirror-view: 1.32.0
  /prosemirror-transform@1.8.0:
    resolution: {integrity: sha512-BaSBsIMv52F1BVVMvOmp1yzD3u65uC3HTzCBQV1WDPqJRQ2LuHKcyfn0jwqodo8sR9vVzMzZyI+Dal5W9E6a9A==}
      prosemirror-model: 1.19.3
  /prosemirror-view@1.32.0:
    resolution: {integrity: sha512-HwW7IWgca6ehiW2PA48H/8yl0TakA0Ms5LgN5Krc97oar7GfjIKE/NocUsLe74Jq4mwyWKUNoBljE8WkXKZwng==}
      prosemirror-model: 1.19.3
      prosemirror-transform: 1.8.0
  /radix3@1.1.0:
    resolution: {integrity: sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A==}
      '@types/normalize-package-data': 2.4.2
  /readable-stream@4.4.2:
    resolution: {integrity: sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==}
      string_decoder: 1.3.0
      resolve: 1.22.6
  /regenerator-runtime@0.14.0:
    resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==}
  /regexp.prototype.flags@1.5.1:
    resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
      define-properties: 1.2.1
      set-function-name: 2.0.1
  /rehype-parse@8.0.5:
    resolution: {integrity: sha512-Ds3RglaY/+clEX2U2mHflt7NlMA72KspZ0JLUJgBBLpRddBcEw3H8uYZQliQriku22NZpYMfjDdSgHcjxue24A==}
      '@types/hast': 2.3.6
      '@types/hast': 2.3.6
      '@types/hast': 2.3.6
      '@types/hast': 2.3.6
      rehype-parse: 8.0.5
      '@types/mdast': 3.0.13
  /remark-mdx@2.3.0:
    resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==}
    dependencies:
      mdast-util-mdx: 2.0.1
      micromark-extension-mdxjs: 1.0.1
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/mdast': 3.0.13
  /remark-parse@11.0.0:
    resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
    dependencies:
      '@types/mdast': 4.0.1
      mdast-util-from-markdown: 2.0.0
      micromark-util-types: 2.0.0
      unified: 11.0.3
    transitivePeerDependencies:
      - supports-color
    dev: false

      '@types/hast': 2.3.6
      '@types/mdast': 3.0.13
  /remark-stringify@11.0.0:
    resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
    dependencies:
      '@types/mdast': 4.0.1
      mdast-util-to-markdown: 2.1.0
      unified: 11.0.3
    dev: false

  /remark@15.0.1:
    resolution: {integrity: sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==}
    dependencies:
      '@types/mdast': 4.0.1
      remark-parse: 11.0.0
      remark-stringify: 11.0.0
      unified: 11.0.3
    transitivePeerDependencies:
      - supports-color
    dev: false

  /resolve-from@5.0.0:
    resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
    engines: {node: '>=8'}
    dev: false

  /resolve-pkg@2.0.0:
    resolution: {integrity: sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ==}
    engines: {node: '>=8'}
      resolve-from: 5.0.0
    dev: false
  /resolve@1.22.6:
    resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==}
      '@types/nlcst': 1.0.2
      '@types/nlcst': 1.0.2
      '@types/nlcst': 1.0.2
      '@types/nlcst': 1.0.2
  /rollup-plugin-dts@5.3.1(rollup@3.29.4)(typescript@5.2.2):
    resolution: {integrity: sha512-gusMi+Z4gY/JaEQeXnB0RUdU82h1kF0WYzCWgVmV4p3hWXqelaKuCvcJawfeg+EKn2T1Ie+YWF2OiN1/L8bTVg==}
    engines: {node: '>=v14.21.3'}
      rollup: ^3.0
      magic-string: 0.30.4
      rollup: 3.29.4
  /rollup@3.29.4:
    resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==}
      fsevents: 2.3.3
  /safe-array-concat@1.0.1:
    resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
    engines: {node: '>=0.4'}
    dependencies:
      call-bind: 1.0.2
      get-intrinsic: 1.2.1
      has-symbols: 1.0.3
      isarray: 2.0.5
    dev: true

  /sass-formatter@0.7.8:
    resolution: {integrity: sha512-7fI2a8THglflhhYis7k06eUf92VQuJoXzEs2KRP0r1bluFxKFvLx0Ns7c478oYGM0fPfrr846ZRWVi2MAgHt9Q==}
      immutable: 4.3.4
  /sax@1.3.0:
    resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
  /semver@5.7.2:
    resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
  /set-function-name@2.0.1:
    resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==}
    engines: {node: '>= 0.4'}
    dependencies:
      define-data-property: 1.1.0
      functions-have-names: 1.2.3
      has-property-descriptors: 1.0.0
    dev: true

      ansi-sequence-parser: 1.1.1
      joi: 17.11.0
      '@polka/url': 1.0.0-next.23
      '@types/sax': 1.2.5
      sax: 1.3.0
      '@babel/generator': 7.23.0
      '@babel/helper-module-imports': 7.22.15
      '@babel/types': 7.23.0
  /sonic-boom@3.6.1:
    resolution: {integrity: sha512-QV+p5nXPiUiSMxn/k5bOL+hzCpafdj1voL+hywPZhheRSYyYp7CF15rNdz1evOXCUn/tFb7R62PDX1yJmtoTgg==}
  /source-map@0.7.4:
    resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
    engines: {node: '>= 8'}
    dev: false

      spdx-license-ids: 3.0.16
      spdx-license-ids: 3.0.16
  /spdx-license-ids@3.0.16:
    resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==}
  /stable@0.1.8:
    resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
    deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
    dev: false

  /string.prototype.trim@1.2.8:
    resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
  /string.prototype.trimend@1.0.7:
    resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
  /string.prototype.trimstart@1.0.7:
    resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
      define-properties: 1.2.1
      es-abstract: 1.22.2
  /svgo@2.8.0:
    resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==}
    engines: {node: '>=10.13.0'}
    hasBin: true
    dependencies:
      '@trysound/sax': 0.2.0
      commander: 7.2.0
      css-select: 4.3.0
      css-tree: 1.1.3
      csso: 4.2.0
      picocolors: 1.0.0
      stable: 0.1.8
    dev: false

      '@pkgr/utils': 2.4.2
      tslib: 2.6.2
      resolve: 1.22.6
      '@jridgewell/source-map': 0.3.5
  /thread-stream@2.4.1:
    resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==}
  /tiny-lru@11.2.2:
    resolution: {integrity: sha512-1An82KBJOUKCfRhsk4tHe4rNblnhAUzisesWBGf/0pztaVoNYM7eJxouN+mq6WkV/qNG21AFbrsgQfvBk0X9ng==}
      h3: 1.8.2
      node-mocks-http: 1.13.0
  /trpc-openapi@1.2.0(@trpc/server@10.35.0)(zod@3.22.4):
      h3: 1.8.2
      node-mocks-http: 1.13.0
      zod: 3.22.4
      zod-to-json-schema: 3.21.4(zod@3.22.4)
  /ts-api-utils@1.0.3(typescript@5.2.2):
    resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==}
      typescript: 5.2.2
  /tsconfck@2.1.2(typescript@5.2.2):
      typescript: 5.2.2
      '@types/resolve': 1.20.3
      resolve: 1.22.6
  /tslib@2.6.2:
    resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
  /tsutils@3.21.0(typescript@5.2.2):
      typescript: 5.2.2
  /typed-array-buffer@1.0.0:
    resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
    engines: {node: '>= 0.4'}
    dependencies:
      call-bind: 1.0.2
      get-intrinsic: 1.2.1
      is-typed-array: 1.1.12
    dev: true

  /typed-array-byte-length@1.0.0:
    resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
    engines: {node: '>= 0.4'}
    dependencies:
      call-bind: 1.0.2
      for-each: 0.3.3
      has-proto: 1.0.1
      is-typed-array: 1.1.12
    dev: true

  /typed-array-byte-offset@1.0.0:
    resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
    engines: {node: '>= 0.4'}
    dependencies:
      available-typed-arrays: 1.0.5
      call-bind: 1.0.2
      for-each: 0.3.3
      has-proto: 1.0.1
      is-typed-array: 1.1.12
    dev: true

      is-typed-array: 1.1.12
  /ufo@1.3.1:
    resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==}
      '@rollup/plugin-alias': 5.0.1(rollup@3.29.4)
      '@rollup/plugin-commonjs': 24.1.0(rollup@3.29.4)
      '@rollup/plugin-json': 6.0.1(rollup@3.29.4)
      '@rollup/plugin-node-resolve': 15.2.2(rollup@3.29.4)
      '@rollup/plugin-replace': 5.0.3(rollup@3.29.4)
      '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
      globby: 13.2.2
      jiti: 1.20.0
      magic-string: 0.30.4
      mkdist: 1.3.0(typescript@5.2.2)
      mlly: 1.4.2
      pretty-bytes: 6.1.1
      rollup: 3.29.4
      rollup-plugin-dts: 5.3.1(rollup@3.29.4)(typescript@5.2.2)
      untyped: 1.4.0
  /unconfig@0.3.11:
    resolution: {integrity: sha512-bV/nqePAKv71v3HdVUn6UefbsDKQWRX+bJIkiSm0+twIds6WiD2bJLWWT3i214+J/B4edufZpG2w7Y63Vbwxow==}
      jiti: 1.20.0
  /undici@5.25.4:
    resolution: {integrity: sha512-450yJxT29qKMf3aoudzFpIciqpx6Pji3hEWaXqXmanbXF58LTAGCKxcJjxMXWu3iG+Mudgo3ZUfDB6YDFd/dAw==}
      '@fastify/busboy': 2.0.0
  /unenv@1.7.4:
    resolution: {integrity: sha512-fjYsXYi30It0YCQYqLOcT6fHfMXsBr2hw9XC7ycf8rTG7Xxpe3ZssiqUnD0khrjiZEmkBXWLwm42yCSCH46fMw==}
      consola: 3.2.3
      defu: 6.1.2
      mime: 3.0.0
      node-fetch-native: 1.4.0
      pathe: 1.1.1
    dev: false
      '@types/unist': 2.0.8
  /unified@11.0.3:
    resolution: {integrity: sha512-jlCV402P+YDcFcB2VcN/n8JasOddqIiaxv118wNBoZXEhOn+lYG7BR4Bfg2BwxvlK58dwbuH2w7GX2esAjL6Mg==}
    dependencies:
      '@types/unist': 3.0.0
      bail: 2.0.2
      devlop: 1.1.0
      extend: 3.0.2
      is-plain-obj: 4.1.0
      trough: 2.1.0
      vfile: 6.0.1
    dev: false

      '@types/unist': 2.0.8
      '@types/unist': 2.0.8
  /unist-util-position-from-estree@1.1.2:
    resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==}
    dependencies:
      '@types/unist': 2.0.8
    dev: false

  /unist-util-position-from-estree@2.0.0:
    resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==}
    dependencies:
      '@types/unist': 3.0.0
    dev: false

      '@types/unist': 2.0.8

  /unist-util-position@5.0.0:
    resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
    dependencies:
      '@types/unist': 3.0.0
    dev: false

  /unist-util-remove-position@4.0.2:
    resolution: {integrity: sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==}
    dependencies:
      '@types/unist': 2.0.8
      unist-util-visit: 4.1.2
    dev: false

  /unist-util-remove-position@5.0.0:
    resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==}
    dependencies:
      '@types/unist': 3.0.0
      unist-util-visit: 5.0.0
    dev: false
      '@types/unist': 2.0.8

  /unist-util-stringify-position@4.0.0:
    resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
    dependencies:
      '@types/unist': 3.0.0
    dev: false
      '@types/unist': 2.0.8
      '@types/unist': 2.0.8
      '@types/unist': 2.0.8
      '@types/jsonwebtoken': 9.0.3
      jsonwebtoken: 9.0.2
  /unocss@0.55.7(postcss@8.4.31)(vite@4.4.9):
      '@unocss/postcss': 0.55.7(postcss@8.4.31)
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
  /untyped@1.4.0:
    resolution: {integrity: sha512-Egkr/s4zcMTEuulcIb7dgURS6QpN7DyqQYdf+jBtiaJvQ+eRsrtWUoX84SbvQWuLkXsOjM+8sJC9u6KoMK/U7Q==}
      '@babel/core': 7.23.0
      '@babel/standalone': 7.23.1
      '@babel/types': 7.23.0
      jiti: 1.20.0
  /update-browserslist-db@1.0.13(browserslist@4.22.1):
    resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
      browserslist: 4.22.1
  /uuid@9.0.1:
    resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
  /validator@13.11.0:
    resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==}
      '@types/unist': 2.0.8
  /vfile-location@5.0.2:
    resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==}
    dependencies:
      '@types/unist': 3.0.0
      vfile: 6.0.1
    dev: false

      '@types/unist': 2.0.8
  /vfile-message@4.0.2:
    resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
    dependencies:
      '@types/unist': 3.0.0
      unist-util-stringify-position: 4.0.0
    dev: false

      '@types/unist': 2.0.8
  /vfile@6.0.1:
    resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==}
    dependencies:
      '@types/unist': 3.0.0
      unist-util-stringify-position: 4.0.0
      vfile-message: 4.0.2
    dev: false

      '@babel/core': 7.23.0
      '@babel/preset-typescript': 7.23.0(@babel/core@7.23.0)
      '@types/babel__core': 7.20.2
      babel-preset-solid: 1.7.12(@babel/core@7.23.0)
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
  /vite-tsconfig-paths@4.2.0(typescript@5.2.2)(vite@4.4.9):
      tsconfck: 2.1.2(typescript@5.2.2)
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
  /vite@4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2):
    resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==}
      postcss: 8.4.31
      rollup: 3.29.4
      fsevents: 2.3.3
      vite: 4.4.9(@types/node@20.4.4)(sass@1.64.1)(terser@5.19.2)
  /vscode-css-languageservice@6.2.9:
    resolution: {integrity: sha512-9MsOvAi+VycKomQ7KEq4o/hLtjHHrtRLLl8lM9nMcH8cxfNI7/6jVXmsV/7pdbDWu9L3DZhsspN1eMXZwiOymw==}
      '@vscode/l10n': 0.0.16
      vscode-languageserver-textdocument: 1.0.11
      vscode-uri: 3.0.8
  /vscode-html-languageservice@5.1.0:
    resolution: {integrity: sha512-cGOu5+lrz+2dDXSGS15y24lDtPaML1T8K/SfqgFbLmCZ1btYOxceFieR+ybTS2es/A67kRc62m2cKFLUQPWG5g==}
      '@vscode/l10n': 0.0.16
      vscode-languageserver-textdocument: 1.0.11
      vscode-languageserver-types: 3.17.5
      vscode-uri: 3.0.8
  /vscode-jsonrpc@8.2.0:
    resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
    engines: {node: '>=14.0.0'}

  /vscode-languageserver-protocol@3.17.5:
    resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
    dependencies:
      vscode-jsonrpc: 8.2.0
      vscode-languageserver-types: 3.17.5

  /vscode-languageserver-textdocument@1.0.11:
    resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==}
  /vscode-languageserver-types@3.17.5:
    resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}

  /vscode-uri@3.0.8:
    resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
  /weaviate-ts-client@1.4.0(graphql@16.8.1):
      graphql-request: 5.2.0(graphql@16.8.1)
      uuid: 9.0.1
  /web-streams-polyfill@3.2.1:
    resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==}
    engines: {node: '>= 8'}
    dev: false

  /whatwg-fetch@3.6.19:
    resolution: {integrity: sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==}
  /which-typed-array@1.1.11:
    resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==}
  /ws@8.14.2:
    resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
  /y-prosemirror@1.0.20(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7):
      lib0: 0.2.86
      prosemirror-model: 1.19.3
      prosemirror-view: 1.32.0
  /y-prosemirror@1.2.1(prosemirror-model@1.19.3)(prosemirror-state@1.4.3)(prosemirror-view@1.32.0)(y-protocols@1.0.5)(yjs@13.6.7):
      lib0: 0.2.86
      prosemirror-model: 1.19.3
      prosemirror-view: 1.32.0
      lib0: 0.2.86
      lib0: 0.2.86
  /zod-to-json-schema@3.21.4(zod@3.22.4):
      zod: 3.22.4
  /zod@3.22.4:
    resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}