From 64781be7d2a672b0d7e05ffddad3629f96f9cee9 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Tue, 21 Oct 2025 18:28:16 +0530 Subject: [PATCH] regression: downgrade to tiptap v2 (#7982) * chore: downgrade to tiptap v2 * fix: revert back to hocuspocus * fix: collaboration events added * fix: lock unlock issues * fix: build errors * fix: type errors * fix: graceful shutdown --------- Co-authored-by: Palanikannan M --- apps/live/package.json | 10 +- apps/live/src/extensions/database.ts | 77 +- .../src/extensions/force-close-handler.ts | 203 +++ apps/live/src/extensions/redis.ts | 124 +- apps/live/src/lib/auth-middleware.ts | 50 + apps/live/src/lib/auth.ts | 20 +- apps/live/src/lib/errors.ts | 73 + apps/live/src/lib/stateless.ts | 2 +- apps/live/src/redis.ts | 17 +- apps/live/src/server.ts | 1 - apps/live/src/services/api.service.ts | 5 +- apps/live/src/services/page/core.service.ts | 38 +- apps/live/src/services/page/handler.ts | 3 +- .../src/services/page/project-page.service.ts | 5 +- apps/live/src/services/user.service.ts | 8 +- apps/live/src/start.ts | 52 +- apps/live/src/types/admin-commands.ts | 143 ++ apps/live/src/utils/broadcast-error.ts | 38 + apps/live/src/utils/broadcast-message.ts | 34 + apps/live/src/utils/document.ts | 98 +- .../components/pages/dropdowns/actions.tsx | 4 +- .../pages/editor/toolbar/options-dropdown.tsx | 1 - .../pages/modals/delete-page-modal.tsx | 2 +- .../hooks/use-collaborative-page-actions.tsx | 40 +- apps/web/core/hooks/use-page-operations.ts | 1 - .../core/hooks/use-realtime-page-events.tsx | 193 +++ apps/web/core/store/pages/base-page.ts | 27 +- .../core/store/pages/project-page.store.ts | 4 +- packages/editor/package.json | 36 +- .../components/menus/bubble-menu/root.tsx | 22 +- .../document-collaborative-events.ts | 95 +- .../extensions/code/code-block-node-view.tsx | 2 +- .../src/core/extensions/core-without-props.ts | 2 + .../core/extensions/custom-link/extension.tsx | 26 + .../src/core/extensions/emoji/suggestion.ts | 6 +- .../editor/src/core/extensions/extensions.ts | 4 +- .../src/core/extensions/headings-list.ts | 5 +- .../src/core/extensions/mentions/utils.ts | 2 +- .../editor/src/core/extensions/placeholder.ts | 2 +- .../editor/src/core/extensions/starter-kit.ts | 4 +- .../editor/src/core/helpers/editor-ref.ts | 7 +- packages/editor/src/core/hooks/use-editor.ts | 7 +- .../editor/src/core/plugins/file/delete.ts | 1 - .../editor/src/core/plugins/file/restore.ts | 1 - .../src/core/plugins/markdown-clipboard.ts | 1 - .../types/document-collaborative-events.ts | 83 +- pnpm-lock.yaml | 1364 ++++++++++------- pnpm-workspace.yaml | 4 +- 48 files changed, 2123 insertions(+), 824 deletions(-) create mode 100644 apps/live/src/extensions/force-close-handler.ts create mode 100644 apps/live/src/lib/auth-middleware.ts create mode 100644 apps/live/src/lib/errors.ts create mode 100644 apps/live/src/types/admin-commands.ts create mode 100644 apps/live/src/utils/broadcast-error.ts create mode 100644 apps/live/src/utils/broadcast-message.ts create mode 100644 apps/web/core/hooks/use-realtime-page-events.tsx diff --git a/apps/live/package.json b/apps/live/package.json index ca065a879..476b6f9ff 100644 --- a/apps/live/package.json +++ b/apps/live/package.json @@ -20,11 +20,11 @@ "author": "Plane Software Inc.", "dependencies": { "@dotenvx/dotenvx": "^1.49.0", - "@hocuspocus/extension-database": "3.2.5", - "@hocuspocus/extension-logger": "3.2.5", - "@hocuspocus/extension-redis": "3.2.5", - "@hocuspocus/server": "3.2.5", - "@hocuspocus/transformer": "3.2.5", + "@hocuspocus/extension-database": "2.15.2", + "@hocuspocus/extension-logger": "2.15.2", + "@hocuspocus/extension-redis": "2.15.2", + "@hocuspocus/server": "2.15.2", + "@hocuspocus/transformer": "2.15.2", "@plane/decorators": "workspace:*", "@plane/editor": "workspace:*", "@plane/logger": "workspace:*", diff --git a/apps/live/src/extensions/database.ts b/apps/live/src/extensions/database.ts index a4b18ad9e..be7a3139c 100644 --- a/apps/live/src/extensions/database.ts +++ b/apps/live/src/extensions/database.ts @@ -6,22 +6,17 @@ import { } from "@plane/editor"; // logger import { logger } from "@plane/logger"; -// lib +import { AppError } from "@/lib/errors"; +// services import { getPageService } from "@/services/page/handler"; // type import type { FetchPayloadWithContext, StorePayloadWithContext } from "@/types"; +import { ForceCloseReason, CloseCode } from "@/types/admin-commands"; +import { broadcastError } from "@/utils/broadcast-error"; +// force close utility +import { forceCloseDocumentAcrossServers } from "./force-close-handler"; -const normalizeToError = (error: unknown, fallbackMessage: string) => { - if (error instanceof Error) { - return error; - } - - const message = typeof error === "string" && error.trim().length > 0 ? error : fallbackMessage; - - return new Error(message); -}; - -const fetchDocument = async ({ context, documentName: pageId }: FetchPayloadWithContext) => { +const fetchDocument = async ({ context, documentName: pageId, instance }: FetchPayloadWithContext) => { try { const service = getPageService(context.documentType, context); // fetch details @@ -38,12 +33,22 @@ const fetchDocument = async ({ context, documentName: pageId }: FetchPayloadWith // return binary data return binaryData; } catch (error) { - logger.error("DATABASE_EXTENSION: Error in fetching document", error); - throw normalizeToError(error, `Failed to fetch document: ${pageId}`); + const appError = new AppError(error, { context: { pageId } }); + logger.error("Error in fetching document", appError); + + // Broadcast error to frontend for user document types + await broadcastError(instance, pageId, "Unable to load the page. Please try refreshing.", "fetch", context); + + throw appError; } }; -const storeDocument = async ({ context, state: pageBinaryData, documentName: pageId }: StorePayloadWithContext) => { +const storeDocument = async ({ + context, + state: pageBinaryData, + documentName: pageId, + instance, +}: StorePayloadWithContext) => { try { const service = getPageService(context.documentType, context); // convert binary data to all formats @@ -57,8 +62,46 @@ const storeDocument = async ({ context, state: pageBinaryData, documentName: pag }; await service.updateDescriptionBinary(pageId, payload); } catch (error) { - logger.error("DATABASE_EXTENSION: Error in updating document:", error); - throw normalizeToError(error, `Failed to update document: ${pageId}`); + const appError = new AppError(error, { context: { pageId } }); + logger.error("Error in updating document:", appError); + + // Check error types + const isContentTooLarge = appError.statusCode === 413; + + // Determine if we should disconnect and unload + const shouldDisconnect = isContentTooLarge; + + // Determine error message and code + let errorMessage: string; + let errorCode: "content_too_large" | "page_locked" | "page_archived" | undefined; + + if (isContentTooLarge) { + errorMessage = "Document is too large to save. Please reduce the content size."; + errorCode = "content_too_large"; + } else { + errorMessage = "Unable to save the page. Please try again."; + } + + // Broadcast error to frontend for user document types + await broadcastError(instance, pageId, errorMessage, "store", context, errorCode, shouldDisconnect); + + // If we should disconnect, close connections and unload document + if (shouldDisconnect) { + // Map error code to ForceCloseReason with proper types + const reason = + errorCode === "content_too_large" ? ForceCloseReason.DOCUMENT_TOO_LARGE : ForceCloseReason.CRITICAL_ERROR; + + const closeCode = errorCode === "content_too_large" ? CloseCode.DOCUMENT_TOO_LARGE : CloseCode.FORCE_CLOSE; + + // force close connections and unload document + await forceCloseDocumentAcrossServers(instance, pageId, reason, closeCode); + + // Don't throw after force close - document is already unloaded + // Throwing would cause hocuspocus's finally block to access the null document + return; + } + + throw appError; } }; diff --git a/apps/live/src/extensions/force-close-handler.ts b/apps/live/src/extensions/force-close-handler.ts new file mode 100644 index 000000000..522d0909a --- /dev/null +++ b/apps/live/src/extensions/force-close-handler.ts @@ -0,0 +1,203 @@ +import type { Connection, Extension, Hocuspocus, onConfigurePayload } from "@hocuspocus/server"; +import { logger } from "@plane/logger"; +import { Redis } from "@/extensions/redis"; +import { + AdminCommand, + CloseCode, + ForceCloseReason, + getForceCloseMessage, + isForceCloseCommand, + type ClientForceCloseMessage, + type ForceCloseCommandData, +} from "@/types/admin-commands"; + +/** + * Extension to handle force close commands from other servers via Redis admin channel + */ +export class ForceCloseHandler implements Extension { + name = "ForceCloseHandler"; + priority = 999; + + async onConfigure({ instance }: onConfigurePayload) { + const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis) as Redis | undefined; + + if (!redisExt) { + logger.warn("[FORCE_CLOSE_HANDLER] Redis extension not found"); + return; + } + + // Register handler for force_close admin command + redisExt.onAdminCommand(AdminCommand.FORCE_CLOSE, async (data) => { + // Type guard for safety + if (!isForceCloseCommand(data)) { + logger.error("[FORCE_CLOSE_HANDLER] Received invalid force close command"); + return; + } + + const { docId, reason, code } = data; + + const document = instance.documents.get(docId); + if (!document) { + // Not our document, ignore + return; + } + + const connectionCount = document.getConnectionsCount(); + logger.info(`[FORCE_CLOSE_HANDLER] Sending force close message to ${connectionCount} clients...`); + + // Step 1: Send force close message to ALL clients first + const forceCloseMessage: ClientForceCloseMessage = { + type: "force_close", + reason, + code, + message: getForceCloseMessage(reason), + timestamp: new Date().toISOString(), + }; + + let messageSent = 0; + document.connections.forEach(({ connection }: { connection: Connection }) => { + try { + connection.sendStateless(JSON.stringify(forceCloseMessage)); + messageSent++; + } catch (error) { + logger.error("[FORCE_CLOSE_HANDLER] Failed to send message:", error); + } + }); + + logger.info(`[FORCE_CLOSE_HANDLER] Sent force close message to ${messageSent}/${connectionCount} clients`); + + // Wait a moment for messages to be delivered + await new Promise((resolve) => setTimeout(resolve, 50)); + + // Step 2: Close connections + logger.info(`[FORCE_CLOSE_HANDLER] Closing ${connectionCount} connections...`); + + let closed = 0; + document.connections.forEach(({ connection }: { connection: Connection }) => { + try { + connection.close({ code, reason }); + closed++; + } catch (error) { + logger.error("[FORCE_CLOSE_HANDLER] Failed to close connection:", error); + } + }); + + logger.info(`[FORCE_CLOSE_HANDLER] Closed ${closed}/${connectionCount} connections for ${docId}`); + }); + + logger.info("[FORCE_CLOSE_HANDLER] Registered with Redis extension"); + } +} + +/** + * Force close all connections to a document across all servers and unload it from memory. + * Used for critical errors or admin operations. + * + * @param instance - The Hocuspocus server instance + * @param pageId - The document ID to force close + * @param reason - The reason for force closing + * @param code - Optional WebSocket close code (defaults to FORCE_CLOSE) + * @returns Promise that resolves when document is closed and unloaded + * @throws Error if document not found in memory + */ +export const forceCloseDocumentAcrossServers = async ( + instance: Hocuspocus, + pageId: string, + reason: ForceCloseReason, + code: CloseCode = CloseCode.FORCE_CLOSE +): Promise => { + // STEP 1: VERIFY DOCUMENT EXISTS + const document = instance.documents.get(pageId); + + if (!document) { + logger.info(`[FORCE_CLOSE] Document ${pageId} already unloaded - no action needed`); + return; // Document already cleaned up, nothing to do + } + + const connectionsBefore = document.getConnectionsCount(); + logger.info(`[FORCE_CLOSE] Sending force close message to ${connectionsBefore} local clients...`); + + const forceCloseMessage: ClientForceCloseMessage = { + type: "force_close", + reason, + code, + message: getForceCloseMessage(reason), + timestamp: new Date().toISOString(), + }; + + let messageSentCount = 0; + document.connections.forEach(({ connection }: { connection: Connection }) => { + try { + connection.sendStateless(JSON.stringify(forceCloseMessage)); + messageSentCount++; + } catch (error) { + logger.error("[FORCE_CLOSE] Failed to send message to client:", error); + } + }); + + logger.info(`[FORCE_CLOSE] Sent force close message to ${messageSentCount}/${connectionsBefore} clients`); + + // Wait a moment for messages to be delivered + await new Promise((resolve) => setTimeout(resolve, 50)); + + // STEP 3: CLOSE LOCAL CONNECTIONS + logger.info(`[FORCE_CLOSE] Closing ${connectionsBefore} local connections...`); + + let closedCount = 0; + document.connections.forEach(({ connection }: { connection: Connection }) => { + try { + connection.close({ code, reason }); + closedCount++; + } catch (error) { + logger.error("[FORCE_CLOSE] Failed to close local connection:", error); + } + }); + + logger.info(`[FORCE_CLOSE] Closed ${closedCount}/${connectionsBefore} local connections`); + + // STEP 4: BROADCAST TO OTHER SERVERS + const redisExt = instance.configuration.extensions.find((ext) => ext instanceof Redis) as Redis | undefined; + + if (redisExt) { + const commandData: ForceCloseCommandData = { + command: AdminCommand.FORCE_CLOSE, + docId: pageId, + reason, + code, + originServer: instance.configuration.name || "unknown", + timestamp: new Date().toISOString(), + }; + + const receivers = await redisExt.publishAdminCommand(commandData); + logger.info(`[FORCE_CLOSE] Notified ${receivers} other server(s)`); + } else { + logger.warn("[FORCE_CLOSE] Redis extension not found, cannot notify other servers"); + } + + // STEP 5: WAIT FOR OTHER SERVERS + const waitTime = 800; + logger.info(`[FORCE_CLOSE] Waiting ${waitTime}ms for other servers to close connections...`); + await new Promise((resolve) => setTimeout(resolve, waitTime)); + + // STEP 6: UNLOAD DOCUMENT after closing all the connections + logger.info(`[FORCE_CLOSE] Unloading document from memory...`); + + try { + await instance.unloadDocument(document); + logger.info(`[FORCE_CLOSE] Document unloaded successfully ✅`); + } catch (unloadError: unknown) { + logger.error("[FORCE_CLOSE] UNLOAD FAILED:", unloadError); + logger.error(` Error: ${unloadError instanceof Error ? unloadError.message : "unknown"}`); + } + + // STEP 7: VERIFY UNLOAD + const documentAfterUnload = instance.documents.get(pageId); + + if (documentAfterUnload) { + logger.error( + `❌ [FORCE_CLOSE] Document still in memory!, Document ID: ${pageId}, Connections: ${documentAfterUnload.getConnectionsCount()}` + ); + } else { + logger.info(`✅ [FORCE_CLOSE] COMPLETE, Document: ${pageId}, Status: Successfully closed and unloaded`); + } +}; diff --git a/apps/live/src/extensions/redis.ts b/apps/live/src/extensions/redis.ts index 5edf63592..66c728f2b 100644 --- a/apps/live/src/extensions/redis.ts +++ b/apps/live/src/extensions/redis.ts @@ -1,30 +1,134 @@ import { Redis as HocuspocusRedis } from "@hocuspocus/extension-redis"; -import { OutgoingMessage } from "@hocuspocus/server"; -// redis +import { OutgoingMessage, type onConfigurePayload } from "@hocuspocus/server"; +import { logger } from "@plane/logger"; +import { AppError } from "@/lib/errors"; import { redisManager } from "@/redis"; +import { AdminCommand } from "@/types/admin-commands"; +import type { AdminCommandData, AdminCommandHandler } from "@/types/admin-commands"; const getRedisClient = () => { const redisClient = redisManager.getClient(); if (!redisClient) { - throw new Error("Redis client not initialized"); + throw new AppError("Redis client not initialized"); } return redisClient; }; export class Redis extends HocuspocusRedis { + private adminHandlers = new Map(); + private readonly ADMIN_CHANNEL = "hocuspocus:admin"; + constructor() { super({ redis: getRedisClient() }); } - public broadcastToDocument(documentName: string, payload: any): Promise { + async onConfigure(payload: onConfigurePayload) { + await super.onConfigure(payload); + + // Subscribe to admin channel + await new Promise((resolve, reject) => { + this.sub.subscribe(this.ADMIN_CHANNEL, (error: Error) => { + if (error) { + logger.error(`[Redis] Failed to subscribe to admin channel:`, error); + reject(error); + } else { + logger.info(`[Redis] Subscribed to admin channel: ${this.ADMIN_CHANNEL}`); + resolve(); + } + }); + }); + + // Listen for admin messages + this.sub.on("message", this.handleAdminMessage); + logger.info(`[Redis] Attached admin message listener`); + } + + private handleAdminMessage = async (channel: string, message: string) => { + if (channel !== this.ADMIN_CHANNEL) return; + + try { + const data = JSON.parse(message) as AdminCommandData; + + // Validate command + if (!data.command || !Object.values(AdminCommand).includes(data.command as AdminCommand)) { + logger.warn(`[Redis] Invalid admin command received: ${data.command}`); + return; + } + + const handler = this.adminHandlers.get(data.command); + + if (handler) { + await handler(data); + } else { + logger.warn(`[Redis] No handler registered for admin command: ${data.command}`); + } + } catch (error) { + logger.error("[Redis] Error handling admin message:", error); + } + }; + + /** + * Register handler for an admin command + */ + public onAdminCommand( + command: AdminCommand, + handler: AdminCommandHandler + ) { + this.adminHandlers.set(command, handler as AdminCommandHandler); + logger.info(`[Redis] Registered admin command: ${command}`); + } + + /** + * Publish admin command to global channel + */ + public async publishAdminCommand(data: T): Promise { + // Validate command data + if (!data.command || !Object.values(AdminCommand).includes(data.command)) { + throw new AppError(`Invalid admin command: ${data.command}`); + } + + const message = JSON.stringify(data); + const receivers = await this.pub.publish(this.ADMIN_CHANNEL, message); + + logger.info(`[Redis] Published "${data.command}" command, received by ${receivers} server(s)`); + return receivers; + } + + async onDestroy() { + // Unsubscribe from admin channel + await new Promise((resolve) => { + this.sub.unsubscribe(this.ADMIN_CHANNEL, (error: Error) => { + if (error) { + logger.error(`[Redis] Error unsubscribing from admin channel:`, error); + } + resolve(); + }); + }); + + // Remove the message listener to prevent memory leaks + this.sub.removeListener("message", this.handleAdminMessage); + logger.info(`[Redis] Removed admin message listener`); + + await super.onDestroy(); + } + + /** + * Broadcast a message to a document across all servers via Redis. + * Uses empty identifier so ALL servers process the message. + */ + public async broadcastToDocument(documentName: string, payload: unknown): Promise { const stringPayload = typeof payload === "string" ? payload : JSON.stringify(payload); + const message = new OutgoingMessage(documentName).writeBroadcastStateless(stringPayload); - return this.pub.publish( - // we're accessing the private method of the hocuspocus redis extension - this["pubKey"](documentName), - // we're accessing the private method of the hocuspocus redis extension to encode the message - this["encodeMessage"](message.toUint8Array()) - ); + const emptyPrefix = Buffer.concat([Buffer.from([0])]); + const channel = this["pubKey"](documentName); + const encodedMessage = Buffer.concat([emptyPrefix, Buffer.from(message.toUint8Array())]); + + const result = await this.pub.publishBuffer(channel, encodedMessage); + + logger.info(`REDIS_EXTENSION: Published to ${documentName}, ${result} subscribers`); + + return result; } } diff --git a/apps/live/src/lib/auth-middleware.ts b/apps/live/src/lib/auth-middleware.ts new file mode 100644 index 000000000..8cdfc1b32 --- /dev/null +++ b/apps/live/src/lib/auth-middleware.ts @@ -0,0 +1,50 @@ +import type { Request, Response, NextFunction } from "express"; +import { logger } from "@plane/logger"; +import { env } from "@/env"; + +/** + * Express middleware to verify secret key authentication for protected endpoints + * + * Checks for secret key in headers: + * - x-admin-secret-key (preferred for admin endpoints) + * - live-server-secret-key (for backward compatibility) + * + * @param req - Express request object + * @param res - Express response object + * @param next - Express next function + * + * @example + * ```typescript + * import { Middleware } from "@plane/decorators"; + * import { requireSecretKey } from "@/lib/auth-middleware"; + * + * @Get("/protected") + * @Middleware(requireSecretKey) + * async protectedEndpoint(req: Request, res: Response) { + * // This will only execute if secret key is valid + * } + * ``` + */ +// TODO - Move to hmac +export const requireSecretKey = (req: Request, res: Response, next: NextFunction): void => { + const secretKey = req.headers["live-server-secret-key"]; + + if (!secretKey || secretKey !== env.LIVE_SERVER_SECRET_KEY) { + logger.warn(` + ⚠️ [AUTH] Unauthorized access attempt + Endpoint: ${req.path} + Method: ${req.method} + IP: ${req.ip} + User-Agent: ${req.headers["user-agent"]} + `); + + res.status(401).json({ + error: "Unauthorized", + status: 401, + }); + return; + } + + // Secret key is valid, proceed to the route handler + next(); +}; diff --git a/apps/live/src/lib/auth.ts b/apps/live/src/lib/auth.ts index 8b5c37d94..a1e82314a 100644 --- a/apps/live/src/lib/auth.ts +++ b/apps/live/src/lib/auth.ts @@ -2,6 +2,7 @@ import type { IncomingHttpHeaders } from "http"; import type { TUserDetails } from "@plane/editor"; import { logger } from "@plane/logger"; +import { AppError } from "@/lib/errors"; // services import { UserService } from "@/services/user.service"; // types @@ -35,8 +36,10 @@ export const onAuthenticate = async ({ userId = parsedToken.id; cookie = parsedToken.cookie; } catch (error) { - // If token parsing fails, fallback to request headers - logger.error("AUTH: Token parsing failed, using request headers:", error); + const appError = new AppError(error, { + context: { operation: "onAuthenticate" }, + }); + logger.error("Token parsing failed, using request headers", appError); } finally { // If cookie is still not found, fallback to request headers if (!cookie) { @@ -45,7 +48,9 @@ export const onAuthenticate = async ({ } if (!cookie || !userId) { - throw new Error("Credentials not provided"); + const appError = new AppError("Credentials not provided", { code: "AUTH_MISSING_CREDENTIALS" }); + logger.error("Credentials not provided", appError); + throw appError; } // set cookie in context, so it can be used throughout the ws connection @@ -67,7 +72,7 @@ export const handleAuthentication = async ({ cookie, userId }: { cookie: string; const userService = new UserService(); const user = await userService.currentUser(cookie); if (user.id !== userId) { - throw new Error("Authentication unsuccessful!"); + throw new AppError("Authentication unsuccessful: User ID mismatch", { code: "AUTH_USER_MISMATCH" }); } return { @@ -77,7 +82,10 @@ export const handleAuthentication = async ({ cookie, userId }: { cookie: string; }, }; } catch (error) { - logger.error("AUTH: Token parsing failed, using request headers:", error); - throw Error("Authentication unsuccessful!"); + const appError = new AppError(error, { + context: { operation: "handleAuthentication" }, + }); + logger.error("Authentication failed", appError); + throw new AppError("Authentication unsuccessful", { code: appError.code }); } }; diff --git a/apps/live/src/lib/errors.ts b/apps/live/src/lib/errors.ts new file mode 100644 index 000000000..480d4317b --- /dev/null +++ b/apps/live/src/lib/errors.ts @@ -0,0 +1,73 @@ +import { AxiosError } from "axios"; + +/** + * Application error class that sanitizes and standardizes errors across the app. + * Extracts only essential information from AxiosError to prevent massive log bloat + * and sensitive data leaks (cookies, tokens, etc). + * + * Usage: + * new AppError("Simple error message") + * new AppError("Custom error", { code: "MY_CODE", statusCode: 400 }) + * new AppError(axiosError) // Auto-extracts essential info + * new AppError(anyError) // Works with any error type + */ +export class AppError extends Error { + statusCode?: number; + method?: string; + url?: string; + code?: string; + context?: Record; + + constructor(messageOrError: string | unknown, data?: Partial>) { + // Handle error objects - extract essential info + const error = messageOrError; + + // Already AppError - return immediately for performance (no need to re-process) + if (error instanceof AppError) { + return error; + } + + // Handle string message (simple case like regular Error) + if (typeof messageOrError === "string") { + super(messageOrError); + this.name = "AppError"; + if (data) { + Object.assign(this, data); + } + return; + } + + // AxiosError - extract ONLY essential info (no config, no headers, no cookies) + if (error && typeof error === "object" && "isAxiosError" in error) { + const axiosError = error as AxiosError; + const responseData = axiosError.response?.data as any; + super(responseData?.message || axiosError.message); + this.name = "AppError"; + this.statusCode = axiosError.response?.status; + this.method = axiosError.config?.method?.toUpperCase(); + this.url = axiosError.config?.url; + this.code = axiosError.code; + return; + } + + // DOMException (AbortError from cancelled requests) + if (error instanceof DOMException && error.name === "AbortError") { + super(error.message); + this.name = "AppError"; + this.code = "ABORT_ERROR"; + return; + } + + // Standard Error objects + if (error instanceof Error) { + super(error.message); + this.name = "AppError"; + this.code = error.name; + return; + } + + // Unknown error types - safe fallback + super("Unknown error occurred"); + this.name = "AppError"; + } +} diff --git a/apps/live/src/lib/stateless.ts b/apps/live/src/lib/stateless.ts index 178b87da6..2f74f0e94 100644 --- a/apps/live/src/lib/stateless.ts +++ b/apps/live/src/lib/stateless.ts @@ -6,7 +6,7 @@ import { DocumentCollaborativeEvents, type TDocumentEventsServer } from "@plane/ * @param param0 */ export const onStateless = async ({ payload, document }: onStatelessPayload) => { - const response = DocumentCollaborativeEvents[payload as TDocumentEventsServer].client; + const response = DocumentCollaborativeEvents[payload as TDocumentEventsServer]?.client; if (response) { document.broadcastStateless(response); } diff --git a/apps/live/src/redis.ts b/apps/live/src/redis.ts index f1dacd64a..aac0eb712 100644 --- a/apps/live/src/redis.ts +++ b/apps/live/src/redis.ts @@ -59,13 +59,20 @@ export class RedisManager { return; } + // Configuration optimized for BOTH regular operations AND pub/sub + // HocuspocusRedis uses .duplicate() which inherits these settings this.redisClient = new Redis(redisUrl, { - lazyConnect: true, + lazyConnect: false, // Connect immediately for reliability (duplicates inherit this) keepAlive: 30000, connectTimeout: 10000, - commandTimeout: 5000, - // enableOfflineQueue: false, maxRetriesPerRequest: 3, + enableOfflineQueue: true, // Keep commands queued during reconnection + retryStrategy: (times: number) => { + // Exponential backoff with max 2 seconds + const delay = Math.min(times * 50, 2000); + logger.info(`REDIS_MANAGER: Reconnection attempt ${times}, delay: ${delay}ms`); + return delay; + }, }); // Set up event listeners @@ -94,10 +101,6 @@ export class RedisManager { this.isConnected = false; }); - // Connect to Redis - await this.redisClient.connect(); - - // Test the connection await this.redisClient.ping(); logger.info("REDIS_MANAGER: Redis connection test successful"); } catch (error) { diff --git a/apps/live/src/server.ts b/apps/live/src/server.ts index 6f8a40f25..1535844fe 100644 --- a/apps/live/src/server.ts +++ b/apps/live/src/server.ts @@ -39,7 +39,6 @@ export class Server { const manager = HocusPocusServerManager.getInstance(); this.hocuspocusServer = await manager.initialize(); logger.info("SERVER: HocusPocus setup completed"); - this.setupRoutes(this.hocuspocusServer); this.setupNotFoundHandler(); } catch (error) { diff --git a/apps/live/src/services/api.service.ts b/apps/live/src/services/api.service.ts index a5531d6b8..8c2cb2e31 100644 --- a/apps/live/src/services/api.service.ts +++ b/apps/live/src/services/api.service.ts @@ -1,6 +1,6 @@ import axios, { AxiosInstance } from "axios"; -import { logger } from "@plane/logger"; import { env } from "@/env"; +import { AppError } from "@/lib/errors"; export abstract class APIService { protected baseURL: string; @@ -21,8 +21,7 @@ export abstract class APIService { this.axiosInstance.interceptors.response.use( (response) => response, (error) => { - logger.error("AXIOS_ERROR:", error); - return Promise.reject(error); + return Promise.reject(new AppError(error)); } ); } diff --git a/apps/live/src/services/page/core.service.ts b/apps/live/src/services/page/core.service.ts index 922c1e5d5..ca4d5d28b 100644 --- a/apps/live/src/services/page/core.service.ts +++ b/apps/live/src/services/page/core.service.ts @@ -1,5 +1,7 @@ +import { logger } from "@plane/logger"; import { TPage } from "@plane/types"; // services +import { AppError } from "@/lib/errors"; import { APIService } from "../api.service"; export type TPageDescriptionPayload = { @@ -21,7 +23,11 @@ export abstract class PageCoreService extends APIService { }) .then((response) => response?.data) .catch((error) => { - throw error; + const appError = new AppError(error, { + context: { operation: "fetchDetails", pageId }, + }); + logger.error("Failed to fetch page details", appError); + throw appError; }); } @@ -35,7 +41,11 @@ export abstract class PageCoreService extends APIService { }) .then((response) => response?.data) .catch((error) => { - throw error; + const appError = new AppError(error, { + context: { operation: "fetchDescriptionBinary", pageId }, + }); + logger.error("Failed to fetch page description binary", appError); + throw appError; }); } @@ -50,7 +60,7 @@ export abstract class PageCoreService extends APIService { // Early abort check if (abortSignal?.aborted) { - throw new DOMException("Aborted", "AbortError"); + throw new AppError(new DOMException("Aborted", "AbortError")); } // Create an abort listener that will reject the pending promise @@ -58,7 +68,7 @@ export abstract class PageCoreService extends APIService { const abortPromise = new Promise((_, reject) => { if (abortSignal) { abortListener = () => { - reject(new DOMException("Aborted", "AbortError")); + reject(new AppError(new DOMException("Aborted", "AbortError"))); }; abortSignal.addEventListener("abort", abortListener); } @@ -66,16 +76,22 @@ export abstract class PageCoreService extends APIService { try { return await Promise.race([ - this.patch(`${this.basePath}/pages/${pageId}`, data, { + this.patch(`${this.basePath}/pages/${pageId}/`, data, { headers: this.getHeader(), signal: abortSignal, }) .then((response) => response?.data) .catch((error) => { - if (error.name === "AbortError") { - throw new DOMException("Aborted", "AbortError"); + const appError = new AppError(error, { + context: { operation: "updatePageProperties", pageId }, + }); + + if (appError.code === "ABORT_ERROR") { + throw appError; } - throw error; + + logger.error("Failed to update page properties", appError); + throw appError; }), abortPromise, ]); @@ -93,7 +109,11 @@ export abstract class PageCoreService extends APIService { }) .then((response) => response?.data) .catch((error) => { - throw error; + const appError = new AppError(error, { + context: { operation: "updateDescriptionBinary", pageId }, + }); + logger.error("Failed to update page description binary", appError); + throw appError; }); } } diff --git a/apps/live/src/services/page/handler.ts b/apps/live/src/services/page/handler.ts index fab4077d6..9b2f5adac 100644 --- a/apps/live/src/services/page/handler.ts +++ b/apps/live/src/services/page/handler.ts @@ -1,3 +1,4 @@ +import { AppError } from "@/lib/errors"; import type { HocusPocusServerContext, TDocumentTypes } from "@/types"; // services import { ProjectPageService } from "./project-page.service"; @@ -11,5 +12,5 @@ export const getPageService = (documentType: TDocumentTypes, context: HocusPocus }); } - throw new Error(`Invalid document type ${documentType} provided.`); + throw new AppError(`Invalid document type ${documentType} provided.`); }; diff --git a/apps/live/src/services/page/project-page.service.ts b/apps/live/src/services/page/project-page.service.ts index 4a659c243..89a115627 100644 --- a/apps/live/src/services/page/project-page.service.ts +++ b/apps/live/src/services/page/project-page.service.ts @@ -1,3 +1,4 @@ +import { AppError } from "@/lib/errors"; import { PageService } from "./extended.service"; interface ProjectPageServiceParams { @@ -13,9 +14,9 @@ export class ProjectPageService extends PageService { constructor(params: ProjectPageServiceParams) { super(); const { workspaceSlug, projectId } = params; - if (!workspaceSlug || !projectId) throw new Error("Missing required fields."); + if (!workspaceSlug || !projectId) throw new AppError("Missing required fields."); // validate cookie - if (!params.cookie) throw new Error("Cookie is required."); + if (!params.cookie) throw new AppError("Cookie is required."); // set cookie this.setHeader("Cookie", params.cookie); // set base path diff --git a/apps/live/src/services/user.service.ts b/apps/live/src/services/user.service.ts index 8a7bcc2e4..272d7543c 100644 --- a/apps/live/src/services/user.service.ts +++ b/apps/live/src/services/user.service.ts @@ -1,6 +1,8 @@ // types +import { logger } from "@plane/logger"; import type { IUser } from "@plane/types"; // services +import { AppError } from "@/lib/errors"; import { APIService } from "@/services/api.service"; export class UserService extends APIService { @@ -22,7 +24,11 @@ export class UserService extends APIService { }) .then((response) => response?.data) .catch((error) => { - throw error; + const appError = new AppError(error, { + context: { operation: "currentUser" }, + }); + logger.error("Failed to fetch current user", appError); + throw appError; }); } } diff --git a/apps/live/src/start.ts b/apps/live/src/start.ts index 421a7be88..7929b9b9b 100644 --- a/apps/live/src/start.ts +++ b/apps/live/src/start.ts @@ -1,8 +1,9 @@ +// eslint-disable-next-line import/order import { setupSentry } from "./instrument"; setupSentry(); -// eslint-disable-next-line import/order import { logger } from "@plane/logger"; +import { AppError } from "@/lib/errors"; import { Server } from "./server"; let server: Server; @@ -20,28 +21,41 @@ async function startServer() { startServer(); -// Graceful shutdown on unhandled rejection -process.on("unhandledRejection", async (err: Error) => { - logger.error(`UNHANDLED REJECTION!`, err); +// Handle process signals +process.on("SIGTERM", async () => { + logger.info("Received SIGTERM signal. Initiating graceful shutdown..."); try { - // if (server) { - // await server.destroy(); - // } - } finally { - // logger.info("Exiting process..."); - // process.exit(1); + if (server) { + await server.destroy(); + } + logger.info("Server shut down gracefully"); + } catch (error) { + logger.error("Error during graceful shutdown:", error); + process.exit(1); } + process.exit(0); }); -// Graceful shutdown on uncaught exception -process.on("uncaughtException", async (err: Error) => { - logger.error(`UNCAUGHT EXCEPTION!`, err); +process.on("SIGINT", async () => { + logger.info("Received SIGINT signal. Killing node process..."); try { - // if (server) { - // await server.destroy(); - // } - } finally { - // logger.info("Exiting process..."); - // process.exit(1); + if (server) { + await server.destroy(); + } + logger.info("Server shut down gracefully"); + } catch (error) { + logger.error("Error during graceful shutdown:", error); + process.exit(1); } + process.exit(1); +}); + +process.on("unhandledRejection", (err: Error) => { + const error = new AppError(err); + logger.error(`[UNHANDLED_REJECTION]`, error); +}); + +process.on("uncaughtException", (err: Error) => { + const error = new AppError(err); + logger.error(`[UNCAUGHT_EXCEPTION]`, error); }); diff --git a/apps/live/src/types/admin-commands.ts b/apps/live/src/types/admin-commands.ts new file mode 100644 index 000000000..bd8e5cd59 --- /dev/null +++ b/apps/live/src/types/admin-commands.ts @@ -0,0 +1,143 @@ +/** + * Type-safe admin commands for server-to-server communication + */ + +/** + * Force close error codes - reasons why a document is being force closed + */ +export enum ForceCloseReason { + CRITICAL_ERROR = "critical_error", + MEMORY_LEAK = "memory_leak", + DOCUMENT_TOO_LARGE = "document_too_large", + ADMIN_REQUEST = "admin_request", + SERVER_SHUTDOWN = "server_shutdown", + SECURITY_VIOLATION = "security_violation", + CORRUPTION_DETECTED = "corruption_detected", +} + +/** + * WebSocket close codes + * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code + */ +export enum CloseCode { + /** Normal closure; the connection successfully completed */ + NORMAL = 1000, + /** The endpoint is going away (server shutdown or browser navigating away) */ + GOING_AWAY = 1001, + /** Protocol error */ + PROTOCOL_ERROR = 1002, + /** Unsupported data */ + UNSUPPORTED_DATA = 1003, + /** Reserved (no status code was present) */ + NO_STATUS = 1005, + /** Abnormal closure */ + ABNORMAL = 1006, + /** Invalid frame payload data */ + INVALID_DATA = 1007, + /** Policy violation */ + POLICY_VIOLATION = 1008, + /** Message too big */ + MESSAGE_TOO_BIG = 1009, + /** Client expected extension not negotiated */ + MANDATORY_EXTENSION = 1010, + /** Server encountered unexpected condition */ + INTERNAL_ERROR = 1011, + /** Custom: Force close requested */ + FORCE_CLOSE = 4000, + /** Custom: Document too large */ + DOCUMENT_TOO_LARGE = 4001, + /** Custom: Memory pressure */ + MEMORY_PRESSURE = 4002, + /** Custom: Security violation */ + SECURITY_VIOLATION = 4003, +} + +/** + * Admin command types + */ +export enum AdminCommand { + FORCE_CLOSE = "force_close", + HEALTH_CHECK = "health_check", + RESTART_DOCUMENT = "restart_document", +} + +/** + * Force close command data structure + */ +export interface ForceCloseCommandData { + command: AdminCommand.FORCE_CLOSE; + docId: string; + reason: ForceCloseReason; + code: CloseCode; + originServer: string; + timestamp?: string; +} + +/** + * Health check command data structure + */ +export interface HealthCheckCommandData { + command: AdminCommand.HEALTH_CHECK; + originServer: string; + timestamp: string; +} + +/** + * Union type for all admin commands + */ +export type AdminCommandData = ForceCloseCommandData | HealthCheckCommandData; + +/** + * Client force close message structure (sent to clients via sendStateless) + */ +export interface ClientForceCloseMessage { + type: "force_close"; + reason: ForceCloseReason; + code: CloseCode; + message?: string; + timestamp?: string; +} + +/** + * Admin command handler function type + */ +export type AdminCommandHandler = (data: T) => Promise | void; + +/** + * Type guard to check if data is a ForceCloseCommandData + */ +export function isForceCloseCommand(data: AdminCommandData): data is ForceCloseCommandData { + return data.command === AdminCommand.FORCE_CLOSE; +} + +/** + * Type guard to check if data is a HealthCheckCommandData + */ +export function isHealthCheckCommand(data: AdminCommandData): data is HealthCheckCommandData { + return data.command === AdminCommand.HEALTH_CHECK; +} + +/** + * Validate force close reason + */ +export function isValidForceCloseReason(reason: string): reason is ForceCloseReason { + return Object.values(ForceCloseReason).includes(reason as ForceCloseReason); +} + +/** + * Get human-readable message for force close reason + */ +export function getForceCloseMessage(reason: ForceCloseReason): string { + const messages: Record = { + [ForceCloseReason.CRITICAL_ERROR]: "A critical error occurred. Please refresh the page.", + [ForceCloseReason.MEMORY_LEAK]: "Memory limit exceeded. Please refresh the page.", + [ForceCloseReason.DOCUMENT_TOO_LARGE]: + "Content limit reached and live sync is off. Create a new page or use nested pages to continue syncing.", + [ForceCloseReason.ADMIN_REQUEST]: "Connection closed by administrator. Please try again later.", + [ForceCloseReason.SERVER_SHUTDOWN]: "Server is shutting down. Please reconnect in a moment.", + [ForceCloseReason.SECURITY_VIOLATION]: "Security violation detected. Connection terminated.", + [ForceCloseReason.CORRUPTION_DETECTED]: "Data corruption detected. Please refresh the page.", + }; + + return messages[reason] || "Connection closed. Please refresh the page."; +} diff --git a/apps/live/src/utils/broadcast-error.ts b/apps/live/src/utils/broadcast-error.ts new file mode 100644 index 000000000..3dfa9da41 --- /dev/null +++ b/apps/live/src/utils/broadcast-error.ts @@ -0,0 +1,38 @@ +import { type Hocuspocus } from "@hocuspocus/server"; +import { createRealtimeEvent } from "@plane/editor"; +import { logger } from "@plane/logger"; +import type { FetchPayloadWithContext, StorePayloadWithContext } from "@/types"; +import { broadcastMessageToPage } from "./broadcast-message"; + +// Helper to broadcast error to frontend +export const broadcastError = async ( + hocuspocusServerInstance: Hocuspocus, + pageId: string, + errorMessage: string, + errorType: "fetch" | "store", + context: FetchPayloadWithContext["context"] | StorePayloadWithContext["context"], + errorCode?: "content_too_large" | "page_locked" | "page_archived", + shouldDisconnect?: boolean +) => { + try { + const errorEvent = createRealtimeEvent({ + action: "error", + page_id: pageId, + parent_id: undefined, + descendants_ids: [], + data: { + error_message: errorMessage, + error_type: errorType, + error_code: errorCode, + should_disconnect: shouldDisconnect, + user_id: context.userId || "", + }, + workspace_slug: context.workspaceSlug || "", + user_id: context.userId || "", + }); + + await broadcastMessageToPage(hocuspocusServerInstance, pageId, errorEvent); + } catch (broadcastError) { + logger.error("Error broadcasting error message to frontend:", broadcastError); + } +}; diff --git a/apps/live/src/utils/broadcast-message.ts b/apps/live/src/utils/broadcast-message.ts new file mode 100644 index 000000000..7c9a3ced6 --- /dev/null +++ b/apps/live/src/utils/broadcast-message.ts @@ -0,0 +1,34 @@ +import { Hocuspocus } from "@hocuspocus/server"; +import { BroadcastedEvent } from "@plane/editor"; +import { logger } from "@plane/logger"; +import { Redis } from "@/extensions/redis"; +import { AppError } from "@/lib/errors"; + +export const broadcastMessageToPage = async ( + hocuspocusServerInstance: Hocuspocus, + documentName: string, + eventData: BroadcastedEvent +): Promise => { + if (!hocuspocusServerInstance || !hocuspocusServerInstance.documents) { + const appError = new AppError("HocusPocus server not available or initialized", { + context: { operation: "broadcastMessageToPage", documentName }, + }); + logger.error("Error while broadcasting message:", appError); + return false; + } + + const redisExtension = hocuspocusServerInstance.configuration.extensions.find((ext) => ext instanceof Redis); + + if (!redisExtension) { + logger.error("BROADCAST_MESSAGE_TO_PAGE: Redis extension not found"); + return false; + } + + try { + await redisExtension.broadcastToDocument(documentName, eventData); + return true; + } catch (error) { + logger.error(`BROADCAST_MESSAGE_TO_PAGE: Error broadcasting to ${documentName}:`, error); + return false; + } +}; diff --git a/apps/live/src/utils/document.ts b/apps/live/src/utils/document.ts index c03a7e160..318a506e0 100644 --- a/apps/live/src/utils/document.ts +++ b/apps/live/src/utils/document.ts @@ -1,83 +1,21 @@ -import { getSchema } from "@tiptap/core"; -import { generateHTML, generateJSON } from "@tiptap/html"; -import { prosemirrorJSONToYDoc, yXmlFragmentToProseMirrorRootNode } from "y-prosemirror"; -import * as Y from "yjs"; -// plane editor -import { - getAllDocumentFormatsFromDocumentEditorBinaryData, - getAllDocumentFormatsFromRichTextEditorBinaryData, - getBinaryDataFromDocumentEditorHTMLString, - getBinaryDataFromRichTextEditorHTMLString, -} from "@plane/editor"; -import { CoreEditorExtensionsWithoutProps, DocumentEditorExtensionsWithoutProps } from "@plane/editor/lib"; -// plane types -import { TDocumentPayload } from "@plane/types"; - -const DOCUMENT_EDITOR_EXTENSIONS = [...CoreEditorExtensionsWithoutProps, ...DocumentEditorExtensionsWithoutProps]; -const documentEditorSchema = getSchema(DOCUMENT_EDITOR_EXTENSIONS); - -type TArgs = { - document_html: string; - variant: "rich" | "document"; -}; - -export const convertHTMLDocumentToAllFormats = (args: TArgs): TDocumentPayload => { - const { document_html, variant } = args; - - if (variant === "rich") { - const contentBinary = getBinaryDataFromRichTextEditorHTMLString(document_html); - const { contentBinaryEncoded, contentHTML, contentJSON } = - getAllDocumentFormatsFromRichTextEditorBinaryData(contentBinary); - return { - description: contentJSON, - description_html: contentHTML, - description_binary: contentBinaryEncoded, - }; - } - - if (variant === "document") { - const contentBinary = getBinaryDataFromDocumentEditorHTMLString(document_html); - const { contentBinaryEncoded, contentHTML, contentJSON } = - getAllDocumentFormatsFromDocumentEditorBinaryData(contentBinary); - return { - description: contentJSON, - description_html: contentHTML, - description_binary: contentBinaryEncoded, - }; - } - - throw new Error(`Invalid variant provided: ${variant}`); -}; - -export const getAllDocumentFormatsFromBinaryData = ( - description: Uint8Array -): { - contentBinaryEncoded: string; - contentJSON: object; - contentHTML: string; -} => { - // encode binary description data - const base64Data = Buffer.from(description).toString("base64"); - const yDoc = new Y.Doc(); - Y.applyUpdate(yDoc, description); - // convert to JSON - const type = yDoc.getXmlFragment("default"); - const contentJSON = yXmlFragmentToProseMirrorRootNode(type, documentEditorSchema).toJSON(); - // convert to HTML - const contentHTML = generateHTML(contentJSON, DOCUMENT_EDITOR_EXTENSIONS); - +export const generateTitleProsemirrorJson = (text: string) => { return { - contentBinaryEncoded: base64Data, - contentJSON, - contentHTML, + type: "doc", + content: [ + { + type: "heading", + attrs: { level: 1 }, + ...(text + ? { + content: [ + { + type: "text", + text, + }, + ], + } + : {}), + }, + ], }; }; - -export const getBinaryDataFromHTMLString = (descriptionHTML: string): Uint8Array => { - // convert HTML to JSON - const contentJSON = generateJSON(descriptionHTML ?? "

", DOCUMENT_EDITOR_EXTENSIONS); - // convert JSON to Y.Doc format - const transformedData = prosemirrorJSONToYDoc(documentEditorSchema, contentJSON, "default"); - // convert Y.Doc to Uint8Array format - return Y.encodeStateAsUpdate(transformedData); -}; diff --git a/apps/web/core/components/pages/dropdowns/actions.tsx b/apps/web/core/components/pages/dropdowns/actions.tsx index b6f92bb6a..bf71af469 100644 --- a/apps/web/core/components/pages/dropdowns/actions.tsx +++ b/apps/web/core/components/pages/dropdowns/actions.tsx @@ -54,7 +54,6 @@ export type TPageActions = | "move"; type Props = { - editorRef?: EditorRefApi | null; extraOptions?: (TContextMenuItem & { key: TPageActions })[]; optionsOrder: TPageActions[]; page: TPageInstance; @@ -63,7 +62,7 @@ type Props = { }; export const PageActions: React.FC = observer((props) => { - const { editorRef, extraOptions, optionsOrder, page, parentRef, storeType } = props; + const { extraOptions, optionsOrder, page, parentRef, storeType } = props; // states const [deletePageModal, setDeletePageModal] = useState(false); const [movePageModal, setMovePageModal] = useState(false); @@ -75,7 +74,6 @@ export const PageActions: React.FC = observer((props) => { }); // page operations const { pageOperations } = usePageOperations({ - editorRef, page, }); // derived values diff --git a/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx b/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx index 762054a2c..6dbe26a2c 100644 --- a/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx +++ b/apps/web/core/components/pages/editor/toolbar/options-dropdown.tsx @@ -130,7 +130,6 @@ export const PageOptionsDropdown: React.FC = observer((props) => { pageTitle={name ?? ""} /> = observer((pr const handleDelete = async () => { setIsDeleting(true); - await removePage(pageId) + await removePage({ pageId }) .then(() => { captureSuccess({ eventName: PROJECT_PAGE_TRACKER_EVENTS.delete, diff --git a/apps/web/core/hooks/use-collaborative-page-actions.tsx b/apps/web/core/hooks/use-collaborative-page-actions.tsx index d4bcfadab..b10d8405d 100644 --- a/apps/web/core/hooks/use-collaborative-page-actions.tsx +++ b/apps/web/core/hooks/use-collaborative-page-actions.tsx @@ -6,51 +6,51 @@ import { TOAST_TYPE, setToast } from "@plane/propel/toast"; // store import type { TPageInstance } from "@/store/pages/base-page"; -// Better type naming and structure -type CollaborativeAction = { - execute: (shouldSync?: boolean) => Promise; +export type CollaborativeAction = { + execute: (shouldSync?: boolean, recursive?: boolean) => Promise; errorMessage: string; }; type CollaborativeActionEvent = - | { type: "sendMessageToServer"; message: TDocumentEventsServer } + | { type: "sendMessageToServer"; message: TDocumentEventsServer; recursive?: boolean } | { type: "receivedMessageFromServer"; message: TDocumentEventsClient }; type Props = { - editorRef?: EditorRefApi | null; page: TPageInstance; }; export const useCollaborativePageActions = (props: Props) => { - const { editorRef, page } = props; + const { page } = props; + const editorRef = page.editor.editorRef; // currentUserAction local state to track if the current action is being processed, a // local action is basically the action performed by the current user to avoid double operations const [currentActionBeingProcessed, setCurrentActionBeingProcessed] = useState(null); + // @ts-expect-error - TODO: fix this const actionHandlerMap: Record = useMemo( () => ({ [DocumentCollaborativeEvents.lock.client]: { - execute: (shouldSync) => page.lock(shouldSync), + execute: (shouldSync?: boolean, recursive?: boolean) => page.lock({ shouldSync, recursive }), errorMessage: "Page could not be locked. Please try again later.", }, [DocumentCollaborativeEvents.unlock.client]: { - execute: (shouldSync) => page.unlock(shouldSync), + execute: (shouldSync?: boolean, recursive?: boolean) => page.unlock({ shouldSync, recursive }), errorMessage: "Page could not be unlocked. Please try again later.", }, [DocumentCollaborativeEvents.archive.client]: { - execute: (shouldSync) => page.archive(shouldSync), + execute: (shouldSync?: boolean) => page.archive({ shouldSync }), errorMessage: "Page could not be archived. Please try again later.", }, [DocumentCollaborativeEvents.unarchive.client]: { - execute: (shouldSync) => page.restore(shouldSync), + execute: (shouldSync?: boolean) => page.restore({ shouldSync }), errorMessage: "Page could not be restored. Please try again later.", }, [DocumentCollaborativeEvents["make-public"].client]: { - execute: (shouldSync) => page.makePublic(shouldSync), + execute: (shouldSync?: boolean) => page.makePublic({ shouldSync }), errorMessage: "Page could not be made public. Please try again later.", }, [DocumentCollaborativeEvents["make-private"].client]: { - execute: (shouldSync) => page.makePrivate(shouldSync), + execute: (shouldSync?: boolean) => page.makePrivate({ shouldSync }), errorMessage: "Page could not be made private. Please try again later.", }, }), @@ -62,22 +62,22 @@ export const useCollaborativePageActions = (props: Props) => { const isPerformedByCurrentUser = event.type === "sendMessageToServer"; const clientAction = isPerformedByCurrentUser ? DocumentCollaborativeEvents[event.message].client : event.message; const actionDetails = actionHandlerMap[clientAction]; - try { - await actionDetails.execute(isPerformedByCurrentUser); + await actionDetails.execute(isPerformedByCurrentUser, isPerformedByCurrentUser ? event?.recursive : undefined); if (isPerformedByCurrentUser) { const serverEventName = getServerEventName(clientAction); if (serverEventName) { editorRef?.emitRealTimeUpdate(serverEventName); } - setCurrentActionBeingProcessed(clientAction); } } catch { - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error!", - message: actionDetails.errorMessage, - }); + if (actionDetails?.errorMessage) { + setToast({ + type: TOAST_TYPE.ERROR, + title: "Error!", + message: actionDetails.errorMessage, + }); + } } }, [actionHandlerMap, editorRef] diff --git a/apps/web/core/hooks/use-page-operations.ts b/apps/web/core/hooks/use-page-operations.ts index 5fd32565b..95537ef5d 100644 --- a/apps/web/core/hooks/use-page-operations.ts +++ b/apps/web/core/hooks/use-page-operations.ts @@ -25,7 +25,6 @@ export type TPageOperations = { }; type Props = { - editorRef?: EditorRefApi | null; page: TPageInstance; }; diff --git a/apps/web/core/hooks/use-realtime-page-events.tsx b/apps/web/core/hooks/use-realtime-page-events.tsx new file mode 100644 index 000000000..630c89954 --- /dev/null +++ b/apps/web/core/hooks/use-realtime-page-events.tsx @@ -0,0 +1,193 @@ +import { useCallback, useMemo } from "react"; +// plane imports +import type { EventToPayloadMap } from "@plane/editor"; +import { setToast, TOAST_TYPE } from "@plane/propel/toast"; +// types +import type { IUserLite } from "@plane/types"; +// components +import type { TEditorBodyHandlers } from "@/components/pages/editor/editor-body"; +// hooks +import { useUser } from "@/hooks/store/user"; +import { useAppRouter } from "@/hooks/use-app-router"; +import type { EPageStoreType } from "@/plane-web/hooks/store"; +import { usePageStore } from "@/plane-web/hooks/store"; +// store +import type { TPageInstance } from "@/store/pages/base-page"; + +// Type for page update handlers with proper typing for action data +export type PageUpdateHandler = (params: { + pageIds: string[]; + data: EventToPayloadMap[T]; + performAction: boolean; +}) => void; + +// Type for custom event handlers that can be provided to override default behavior +export type TCustomEventHandlers = { + [K in keyof EventToPayloadMap]?: PageUpdateHandler; +}; + +interface UsePageEventsProps { + page: TPageInstance; + storeType: EPageStoreType; + getUserDetails: (userId: string) => IUserLite | undefined; + customRealtimeEventHandlers?: TCustomEventHandlers; + handlers: TEditorBodyHandlers; +} + +export const useRealtimePageEvents = ({ + page, + storeType, + getUserDetails, + customRealtimeEventHandlers, + handlers, +}: UsePageEventsProps) => { + const router = useAppRouter(); + const { removePage, getPageById } = usePageStore(storeType); + + const { data: currentUser } = useUser(); + + // Helper function to safely get user display text + const getUserDisplayText = useCallback( + (userId: string | undefined) => { + if (!userId) return ""; + try { + const userDetails = getUserDetails(userId as string); + return userDetails?.display_name ? ` by ${userDetails.display_name}` : ""; + } catch { + return ""; + } + }, + [getUserDetails] + ); + + const ACTION_HANDLERS = useMemo< + Partial<{ + [K in keyof EventToPayloadMap]: PageUpdateHandler; + }> + >( + () => ({ + archived: ({ pageIds, data }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) pageItem.archive({ archived_at: data.archived_at, shouldSync: false }); + }); + }, + unarchived: ({ pageIds }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) pageItem.restore({ shouldSync: false }); + }); + }, + locked: ({ pageIds }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) pageItem.lock({ shouldSync: false, recursive: false }); + }); + }, + unlocked: ({ pageIds }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) pageItem.unlock({ shouldSync: false, recursive: false }); + }); + }, + "made-public": ({ pageIds }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) pageItem.makePublic({ shouldSync: false }); + }); + }, + "made-private": ({ pageIds }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) pageItem.makePrivate({ shouldSync: false }); + }); + }, + deleted: ({ pageIds, data }) => { + pageIds.forEach((pageId) => { + const pageItem = getPageById(pageId); + if (pageItem) { + removePage({ pageId, shouldSync: false }); + if (page.id === pageId && data?.user_id !== currentUser?.id) { + setToast({ + type: TOAST_TYPE.ERROR, + title: "Page deleted", + message: `Page deleted${getUserDisplayText(data.user_id)}`, + }); + router.push(handlers.getRedirectionLink()); + } else if (page.id === pageId) { + router.push(handlers.getRedirectionLink()); + } + } + }); + }, + property_updated: ({ pageIds, data }) => { + pageIds.forEach((pageId) => { + const pageInstance = getPageById(pageId); + const { name: updatedName, ...rest } = data; + if (updatedName != null) pageInstance?.updateTitle(updatedName); + pageInstance?.mutateProperties(rest); + }); + }, + error: ({ pageIds, data }) => { + const errorType = data.error_type; + const errorMessage = data.error_message || "An error occurred"; + const errorCode = data.error_code; + + if (page.id && pageIds.includes(page.id)) { + // Show toast notification + setToast({ + type: TOAST_TYPE.ERROR, + title: errorType === "fetch" ? "Failed to load page" : "Failed to save page", + message: errorMessage, + }); + + // Handle specific error codes + const pageInstance = getPageById(page.id); + if (pageInstance) { + if (errorCode === "page_locked") { + // Lock the page if not already locked + if (!pageInstance.is_locked) { + pageInstance.mutateProperties({ is_locked: true }); + } + } else if (errorCode === "page_archived") { + // Mark page as archived if not already + if (!pageInstance.archived_at) { + pageInstance.mutateProperties({ archived_at: new Date().toISOString() }); + } + } + } + } + }, + ...customRealtimeEventHandlers, + }), + [getPageById, page, router, getUserDisplayText, removePage, currentUser, customRealtimeEventHandlers, handlers] + ); + + // The main function that will be returned from this hook + const updatePageProperties = useCallback( + ( + pageIds: string | string[], + actionType: T, + data: EventToPayloadMap[T], + performAction = false + ) => { + // Convert to array if single string is passed + const normalizedPageIds = Array.isArray(pageIds) ? pageIds : [pageIds]; + + if (normalizedPageIds.length === 0) return; + + // Get the handler for this message type + const handler = ACTION_HANDLERS[actionType]; + + if (handler) { + // Now TypeScript knows that handler and data match in type + handler({ pageIds: normalizedPageIds, data, performAction }); + } else { + console.warn(`No handler for message type: ${actionType.toString()}`); + } + }, + [ACTION_HANDLERS] + ); + + return { updatePageProperties }; +}; diff --git a/apps/web/core/store/pages/base-page.ts b/apps/web/core/store/pages/base-page.ts index 3396bc74e..ca0b0a226 100644 --- a/apps/web/core/store/pages/base-page.ts +++ b/apps/web/core/store/pages/base-page.ts @@ -25,12 +25,12 @@ export type TBasePage = TPage & { update: (pageData: Partial) => Promise | undefined>; updateTitle: (title: string) => void; updateDescription: (document: TDocumentPayload) => Promise; - makePublic: (shouldSync?: boolean) => Promise; - makePrivate: (shouldSync?: boolean) => Promise; - lock: (shouldSync?: boolean) => Promise; - unlock: (shouldSync?: boolean) => Promise; - archive: (shouldSync?: boolean) => Promise; - restore: (shouldSync?: boolean) => Promise; + makePublic: (params: { shouldSync?: boolean }) => Promise; + makePrivate: (params: { shouldSync?: boolean }) => Promise; + lock: (params: { shouldSync?: boolean; recursive?: boolean }) => Promise; + unlock: (params: { shouldSync?: boolean; recursive?: boolean }) => Promise; + archive: (params: { shouldSync?: boolean; archived_at?: string | null }) => Promise; + restore: (params: { shouldSync?: boolean }) => Promise; updatePageLogo: (value: TChangeHandlerProps) => Promise; addToFavorites: () => Promise; removePageFromFavorites: () => Promise; @@ -315,7 +315,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage { /** * @description make the page public */ - makePublic = async (shouldSync: boolean = true) => { + makePublic = async ({ shouldSync = true }) => { const pageAccess = this.access; runInAction(() => { this.access = EPageAccess.PUBLIC; @@ -338,7 +338,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage { /** * @description make the page private */ - makePrivate = async (shouldSync: boolean = true) => { + makePrivate = async ({ shouldSync = true }) => { const pageAccess = this.access; runInAction(() => { this.access = EPageAccess.PRIVATE; @@ -361,7 +361,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage { /** * @description lock the page */ - lock = async (shouldSync: boolean = true) => { + lock = async ({ shouldSync = true }) => { const pageIsLocked = this.is_locked; runInAction(() => (this.is_locked = true)); @@ -378,7 +378,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage { /** * @description unlock the page */ - unlock = async (shouldSync: boolean = true) => { + unlock = async ({ shouldSync = true }) => { const pageIsLocked = this.is_locked; runInAction(() => (this.is_locked = false)); @@ -395,12 +395,12 @@ export class BasePage extends ExtendedBasePage implements TBasePage { /** * @description archive the page */ - archive = async (shouldSync: boolean = true) => { + archive = async ({ shouldSync = true, archived_at }: { shouldSync?: boolean; archived_at?: string | null }) => { if (!this.id) return undefined; try { runInAction(() => { - this.archived_at = new Date().toISOString(); + this.archived_at = archived_at ?? new Date().toISOString(); }); if (this.rootStore.favorite.entityMap[this.id]) this.rootStore.favorite.removeFavoriteFromStore(this.id); @@ -422,7 +422,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage { /** * @description restore the page */ - restore = async (shouldSync: boolean = true) => { + restore = async ({ shouldSync = true }: { shouldSync?: boolean }) => { const archivedAtBeforeRestore = this.archived_at; try { @@ -438,6 +438,7 @@ export class BasePage extends ExtendedBasePage implements TBasePage { runInAction(() => { this.archived_at = archivedAtBeforeRestore; }); + throw error; } }; diff --git a/apps/web/core/store/pages/project-page.store.ts b/apps/web/core/store/pages/project-page.store.ts index a09067390..0169a9eb9 100644 --- a/apps/web/core/store/pages/project-page.store.ts +++ b/apps/web/core/store/pages/project-page.store.ts @@ -57,7 +57,7 @@ export interface IProjectPageStore { options?: { trackVisit?: boolean } ) => Promise; createPage: (pageData: Partial) => Promise; - removePage: (pageId: string) => Promise; + removePage: (params: { pageId: string; shouldSync?: boolean }) => Promise; movePage: (workspaceSlug: string, projectId: string, pageId: string, newProjectId: string) => Promise; } @@ -321,7 +321,7 @@ export class ProjectPageStore implements IProjectPageStore { * @description delete a page * @param {string} pageId */ - removePage = async (pageId: string) => { + removePage = async ({ pageId, shouldSync = true }: { pageId: string; shouldSync?: boolean }) => { try { const { workspaceSlug, projectId } = this.store.router; if (!workspaceSlug || !projectId || !pageId) return undefined; diff --git a/packages/editor/package.json b/packages/editor/package.json index 2bf6fbe52..9910a173b 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -38,29 +38,31 @@ "@floating-ui/dom": "^1.7.1", "@floating-ui/react": "^0.26.4", "@headlessui/react": "^1.7.3", - "@hocuspocus/provider": "3.2.5", + "@hocuspocus/provider": "2.15.2", "@plane/constants": "workspace:*", "@plane/hooks": "workspace:*", "@plane/types": "workspace:*", "@plane/ui": "workspace:*", "@plane/utils": "workspace:*", "@tiptap/core": "catalog:", - "@tiptap/extension-blockquote": "^3.5.3", - "@tiptap/extension-collaboration": "^3.5.3", - "@tiptap/extension-emoji": "^3.5.3", - "@tiptap/extension-image": "^3.5.3", - "@tiptap/extension-list-item": "^3.5.3", - "@tiptap/extension-mention": "^3.5.3", - "@tiptap/extension-task-item": "^3.5.3", - "@tiptap/extension-task-list": "^3.5.3", - "@tiptap/extension-text-align": "^3.5.3", - "@tiptap/extension-text-style": "^3.5.3", - "@tiptap/extensions": "^3.5.3", + "@tiptap/extension-blockquote": "^2.22.3", + "@tiptap/extension-character-count": "^2.22.3", + "@tiptap/extension-collaboration": "^2.22.3", + "@tiptap/extension-emoji": "^2.22.3", + "@tiptap/extension-image": "^2.22.3", + "@tiptap/extension-list-item": "^2.22.3", + "@tiptap/extension-mention": "^2.22.3", + "@tiptap/extension-placeholder": "^2.22.3", + "@tiptap/extension-task-item": "^2.22.3", + "@tiptap/extension-task-list": "^2.22.3", + "@tiptap/extension-text-align": "^2.22.3", + "@tiptap/extension-text-style": "^2.22.3", + "@tiptap/extension-underline": "^2.22.3", "@tiptap/html": "catalog:", - "@tiptap/pm": "^3.5.3", - "@tiptap/react": "^3.5.3", - "@tiptap/starter-kit": "^3.5.3", - "@tiptap/suggestion": "^3.5.3", + "@tiptap/pm": "^2.22.3", + "@tiptap/react": "^2.22.3", + "@tiptap/starter-kit": "^2.22.3", + "@tiptap/suggestion": "^2.22.3", "emoji-regex": "^10.3.0", "highlight.js": "^11.8.0", "is-emoji-supported": "^0.0.5", @@ -70,7 +72,7 @@ "lucide-react": "catalog:", "prosemirror-codemark": "^0.4.2", "tippy.js": "^6.3.7", - "tiptap-markdown": "^0.9.0", + "tiptap-markdown": "^0.8.10", "uuid": "catalog:", "y-indexeddb": "^9.0.12", "y-prosemirror": "^1.2.15", diff --git a/packages/editor/src/core/components/menus/bubble-menu/root.tsx b/packages/editor/src/core/components/menus/bubble-menu/root.tsx index 588b43439..002cf0ab6 100644 --- a/packages/editor/src/core/components/menus/bubble-menu/root.tsx +++ b/packages/editor/src/core/components/menus/bubble-menu/root.tsx @@ -1,6 +1,5 @@ import { type Editor, isNodeSelection } from "@tiptap/core"; -import { useEditorState } from "@tiptap/react"; -import { BubbleMenu, type BubbleMenuProps } from "@tiptap/react/menus"; +import { BubbleMenu, type BubbleMenuProps, useEditorState } from "@tiptap/react"; import { FC, useEffect, useState, useRef } from "react"; // plane utils import { cn } from "@plane/utils"; @@ -119,7 +118,10 @@ export const EditorBubbleMenu: FC = (props) => { } return true; }, - options: { + tippyOptions: { + moveTransition: "transform 0.15s ease-out", + duration: [300, 0], + zIndex: 9, onShow: () => { if (editor.storage.link) { editor.storage.link.isBubbleMenuOpen = true; @@ -134,13 +136,15 @@ export const EditorBubbleMenu: FC = (props) => { editor.commands.removeActiveDropbarExtension("bubble-menu"); }, 0); }, + onHidden: () => { + if (editor.storage.link) { + editor.storage.link.isBubbleMenuOpen = false; + } + setTimeout(() => { + editor.commands.removeActiveDropbarExtension("bubble-menu"); + }, 0); + }, }, - // TODO: Migrate these to floating UI options - // tippyOptions: { - // moveTransition: "transform 0.15s ease-out", - // duration: [300, 0], - // zIndex: 9, - // }, }; useEffect(() => { diff --git a/packages/editor/src/core/constants/document-collaborative-events.ts b/packages/editor/src/core/constants/document-collaborative-events.ts index 72e8b1dbd..d602015c2 100644 --- a/packages/editor/src/core/constants/document-collaborative-events.ts +++ b/packages/editor/src/core/constants/document-collaborative-events.ts @@ -1,8 +1,91 @@ +import { EPageAccess } from "@plane/constants"; +import { TPage } from "@plane/types"; +import { CreatePayload, BaseActionPayload } from "@/types"; + +// Define all payload types for each event. +export type ArchivedPayload = CreatePayload<{ archived_at: string | null }>; +export type UnarchivedPayload = BaseActionPayload; +export type LockedPayload = CreatePayload<{ is_locked: boolean }>; +export type UnlockedPayload = BaseActionPayload; +export type MadePublicPayload = CreatePayload<{ access: EPageAccess }>; +export type MadePrivatePayload = CreatePayload<{ access: EPageAccess }>; +export type DeletedPayload = CreatePayload<{ deleted_at: Date | null }>; +export type DuplicatedPayload = CreatePayload<{ new_page_id: string }>; +export type PropertyUpdatedPayload = CreatePayload>; +export type MovedPayload = CreatePayload<{ + new_project_id: string; + new_page_id: string; +}>; +export type RestoredPayload = CreatePayload<{ deleted_page_ids?: string[] }>; +export type ErrorPayload = CreatePayload<{ + error_message: string; + error_type: "fetch" | "store"; + error_code?: "content_too_large" | "page_locked" | "page_archived"; + should_disconnect?: boolean; +}>; + +// Enhanced DocumentCollaborativeEvents with payload types. +// Both the client name and server name are defined, and we add a "payloadType" property +// so that we can later derive a mapping from client event to payload type. export const DocumentCollaborativeEvents = { - lock: { client: "locked", server: "lock" }, - unlock: { client: "unlocked", server: "unlock" }, - archive: { client: "archived", server: "archive" }, - unarchive: { client: "unarchived", server: "unarchive" }, - "make-public": { client: "made-public", server: "make-public" }, - "make-private": { client: "made-private", server: "make-private" }, + lock: { + client: "locked", + server: "lock", + payloadType: {} as LockedPayload, + }, + unlock: { + client: "unlocked", + server: "unlock", + payloadType: {} as UnlockedPayload, + }, + archive: { + client: "archived", + server: "archive", + payloadType: {} as ArchivedPayload, + }, + unarchive: { + client: "unarchived", + server: "unarchive", + payloadType: {} as UnarchivedPayload, + }, + "make-public": { + client: "made-public", + server: "make-public", + payloadType: {} as MadePublicPayload, + }, + "make-private": { + client: "made-private", + server: "make-private", + payloadType: {} as MadePrivatePayload, + }, + delete: { + client: "deleted", + server: "delete", + payloadType: {} as DeletedPayload, + }, + move: { + client: "moved", + server: "move", + payloadType: {} as MovedPayload, + }, + duplicate: { + client: "duplicated", + server: "duplicate", + payloadType: {} as DuplicatedPayload, + }, + property_update: { + client: "property_updated", + server: "property_update", + payloadType: {} as PropertyUpdatedPayload, + }, + restore: { + client: "restored", + server: "restore", + payloadType: {} as RestoredPayload, + }, + error: { + client: "error", + server: "error", + payloadType: {} as ErrorPayload, + }, } as const; diff --git a/packages/editor/src/core/extensions/code/code-block-node-view.tsx b/packages/editor/src/core/extensions/code/code-block-node-view.tsx index 0c53d82f9..6e13924a1 100644 --- a/packages/editor/src/core/extensions/code/code-block-node-view.tsx +++ b/packages/editor/src/core/extensions/code/code-block-node-view.tsx @@ -56,7 +56,7 @@ export const CodeBlockComponent: React.FC = ({ node }) => {
-         as="code" className="whitespace-pre-wrap" />
+        
       
); diff --git a/packages/editor/src/core/extensions/core-without-props.ts b/packages/editor/src/core/extensions/core-without-props.ts index 3dd46d2f0..064f5b3e9 100644 --- a/packages/editor/src/core/extensions/core-without-props.ts +++ b/packages/editor/src/core/extensions/core-without-props.ts @@ -1,6 +1,7 @@ import TaskItem from "@tiptap/extension-task-item"; import TaskList from "@tiptap/extension-task-list"; import { TextStyle } from "@tiptap/extension-text-style"; +import { Underline } from "@tiptap/extension-underline"; // plane editor imports import { CoreEditorAdditionalExtensionsWithoutProps } from "@/plane-editor/extensions/core/without-props"; // extensions @@ -30,6 +31,7 @@ export const CoreEditorExtensionsWithoutProps = [ CustomLinkExtension, ImageExtensionConfig, CustomImageExtensionConfig, + Underline, TextStyle, TaskList.configure({ HTMLAttributes: { diff --git a/packages/editor/src/core/extensions/custom-link/extension.tsx b/packages/editor/src/core/extensions/custom-link/extension.tsx index 432ff2f50..d7b746d42 100644 --- a/packages/editor/src/core/extensions/custom-link/extension.tsx +++ b/packages/editor/src/core/extensions/custom-link/extension.tsx @@ -50,6 +50,32 @@ type LinkOptions = { }; declare module "@tiptap/core" { + interface Commands { + [CORE_EXTENSIONS.CUSTOM_LINK]: { + /** + * Set a link mark + */ + setLink: (attributes: { + href: string; + target?: string | null; + rel?: string | null; + class?: string | null; + }) => ReturnType; + /** + * Toggle a link mark + */ + toggleLink: (attributes: { + href: string; + target?: string | null; + rel?: string | null; + class?: string | null; + }) => ReturnType; + /** + * Unset a link mark + */ + unsetLink: () => ReturnType; + }; + } interface Storage { [CORE_EXTENSIONS.CUSTOM_LINK]: CustomLinkStorage; } diff --git a/packages/editor/src/core/extensions/emoji/suggestion.ts b/packages/editor/src/core/extensions/emoji/suggestion.ts index 83847d8d5..c67d68dae 100644 --- a/packages/editor/src/core/extensions/emoji/suggestion.ts +++ b/packages/editor/src/core/extensions/emoji/suggestion.ts @@ -1,4 +1,4 @@ -import type { EmojiOptions } from "@tiptap/extension-emoji"; +import type { EmojiOptions, EmojiStorage } from "@tiptap/extension-emoji"; import { ReactRenderer, type Editor } from "@tiptap/react"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; @@ -12,7 +12,7 @@ const DEFAULT_EMOJIS = ["+1", "-1", "smile", "orange_heart", "eyes"]; export const emojiSuggestion: EmojiOptions["suggestion"] = { items: ({ editor, query }: { editor: Editor; query: string }): EmojiItem[] => { - const { emojis, isSupported } = editor.storage.emoji; + const { emojis, isSupported } = editor.storage.emoji as EmojiStorage; const filteredEmojis = emojis.filter((emoji) => { const hasEmoji = !!emoji?.emoji; const hasFallbackImage = !!emoji?.fallbackImage; @@ -79,7 +79,7 @@ export const emojiSuggestion: EmojiOptions["suggestion"] = { component.updateProps(props); if (!props.clientRect) return; cleanup(); - cleanup = updateFloatingUIFloaterPosition(props.editor, component.element).cleanup; + cleanup = updateFloatingUIFloaterPosition(props.editor, component.element as HTMLElement).cleanup; }, onKeyDown: ({ event }) => { if ([...DROPDOWN_NAVIGATION_KEYS, "Escape"].includes(event.key)) { diff --git a/packages/editor/src/core/extensions/extensions.ts b/packages/editor/src/core/extensions/extensions.ts index 5be0645df..f17d11587 100644 --- a/packages/editor/src/core/extensions/extensions.ts +++ b/packages/editor/src/core/extensions/extensions.ts @@ -1,8 +1,9 @@ import { Extensions } from "@tiptap/core"; +import { CharacterCount } from "@tiptap/extension-character-count"; import TaskItem from "@tiptap/extension-task-item"; import TaskList from "@tiptap/extension-task-list"; import { TextStyle } from "@tiptap/extension-text-style"; -import { CharacterCount } from "@tiptap/extensions"; +import { Underline } from "@tiptap/extension-underline"; import { Markdown } from "tiptap-markdown"; // extensions import { @@ -75,6 +76,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => { ListKeymap({ tabIndex }), CustomLinkExtension, CustomTypographyExtension, + Underline, TextStyle, TaskList.configure({ HTMLAttributes: { diff --git a/packages/editor/src/core/extensions/headings-list.ts b/packages/editor/src/core/extensions/headings-list.ts index 5dc46c1c0..1acb9d446 100644 --- a/packages/editor/src/core/extensions/headings-list.ts +++ b/packages/editor/src/core/extensions/headings-list.ts @@ -52,7 +52,6 @@ export const HeadingListExtension = Extension.create { if ([...DROPDOWN_NAVIGATION_KEYS, "Escape"].includes(event.key)) { diff --git a/packages/editor/src/core/extensions/placeholder.ts b/packages/editor/src/core/extensions/placeholder.ts index b3d70fc7e..7a236332c 100644 --- a/packages/editor/src/core/extensions/placeholder.ts +++ b/packages/editor/src/core/extensions/placeholder.ts @@ -1,4 +1,4 @@ -import { Placeholder } from "@tiptap/extensions"; +import { Placeholder } from "@tiptap/extension-placeholder"; // constants import { CORE_EXTENSIONS } from "@/constants/extension"; // types diff --git a/packages/editor/src/core/extensions/starter-kit.ts b/packages/editor/src/core/extensions/starter-kit.ts index 286768ace..e6a4c968d 100644 --- a/packages/editor/src/core/extensions/starter-kit.ts +++ b/packages/editor/src/core/extensions/starter-kit.ts @@ -27,8 +27,6 @@ export const CustomStarterKitExtension = (args: TArgs) => { codeBlock: false, horizontalRule: false, blockquote: false, - link: false, - listKeymap: false, paragraph: { HTMLAttributes: { class: "editor-paragraph-block", @@ -43,6 +41,6 @@ export const CustomStarterKitExtension = (args: TArgs) => { class: "text-custom-text-300 transition-all motion-reduce:transition-none motion-reduce:hover:transform-none duration-200 ease-[cubic-bezier(0.165, 0.84, 0.44, 1)]", }, - ...(enableHistory ? {} : { undoRedo: false }), + ...(enableHistory ? {} : { history: false }), }); }; diff --git a/packages/editor/src/core/helpers/editor-ref.ts b/packages/editor/src/core/helpers/editor-ref.ts index e56aa7bdf..958624ee1 100644 --- a/packages/editor/src/core/helpers/editor-ref.ts +++ b/packages/editor/src/core/helpers/editor-ref.ts @@ -94,11 +94,8 @@ export const getEditorRefHelpers = (args: TArgs): EditorRefApi => { ?.chain() .setMeta(CORE_EDITOR_META.SKIP_FILE_DELETION, true) .setMeta(CORE_EDITOR_META.INTENTIONAL_DELETION, true) - .setContent(content, { - emitUpdate, - parseOptions: { - preserveWhitespace: true, - }, + .setContent(content, emitUpdate, { + preserveWhitespace: true, }) .run(); }, diff --git a/packages/editor/src/core/hooks/use-editor.ts b/packages/editor/src/core/hooks/use-editor.ts index 8e991d033..8dd174a19 100644 --- a/packages/editor/src/core/hooks/use-editor.ts +++ b/packages/editor/src/core/hooks/use-editor.ts @@ -93,11 +93,8 @@ export const useEditor = (props: TEditorHookProps) => { const { uploadInProgress: isUploadInProgress } = editor.storage.utility; if (!editor.isDestroyed && !isUploadInProgress) { try { - editor.commands.setContent(value, { - emitUpdate: false, - parseOptions: { - preserveWhitespace: true, - }, + editor.commands.setContent(value, false, { + preserveWhitespace: true, }); if (editor.state.selection) { const docLength = editor.state.doc.content.size; diff --git a/packages/editor/src/core/plugins/file/delete.ts b/packages/editor/src/core/plugins/file/delete.ts index fbb434e7d..5d0aa8ca4 100644 --- a/packages/editor/src/core/plugins/file/delete.ts +++ b/packages/editor/src/core/plugins/file/delete.ts @@ -57,7 +57,6 @@ export const TrackFileDeletionPlugin = (editor: Editor, deleteHandler: TFileHand const nodeFileSetDetails = NODE_FILE_MAP[nodeType]; if (!nodeFileSetDetails || !src) return; try { - // @ts-expect-error add proper types for storage editor.storage[nodeType]?.[nodeFileSetDetails.fileSetName]?.set(src, true); // update assets list storage value editor.commands.updateAssetsList?.({ diff --git a/packages/editor/src/core/plugins/file/restore.ts b/packages/editor/src/core/plugins/file/restore.ts index 87da43711..cf25a818b 100644 --- a/packages/editor/src/core/plugins/file/restore.ts +++ b/packages/editor/src/core/plugins/file/restore.ts @@ -63,7 +63,6 @@ export const TrackFileRestorationPlugin = (editor: Editor, restoreHandler: TFile const src = node.attrs.src; const nodeFileSetDetails = NODE_FILE_MAP[nodeType]; if (!nodeFileSetDetails) return; - // @ts-expect-error add proper types for storage const extensionFileSetStorage = editor.storage[nodeType]?.[nodeFileSetDetails.fileSetName]; const wasDeleted = extensionFileSetStorage?.get(src); if (!nodeFileSetDetails || !src) return; diff --git a/packages/editor/src/core/plugins/markdown-clipboard.ts b/packages/editor/src/core/plugins/markdown-clipboard.ts index 7eda09eea..78f649b23 100644 --- a/packages/editor/src/core/plugins/markdown-clipboard.ts +++ b/packages/editor/src/core/plugins/markdown-clipboard.ts @@ -9,7 +9,6 @@ export const MarkdownClipboardPlugin = (editor: Editor): Plugin => key: new PluginKey("markdownClipboard"), props: { clipboardTextSerializer: (slice) => { - // @ts-expect-error tiptap-markdown types are not updated const markdownSerializer = editor.storage.markdown.serializer; const isTableRow = slice.content.firstChild?.type?.name === CORE_EXTENSIONS.TABLE_ROW; const nodeSelect = slice.openStart === 0 && slice.openEnd === 0; diff --git a/packages/editor/src/core/types/document-collaborative-events.ts b/packages/editor/src/core/types/document-collaborative-events.ts index 99936a5ad..5f8a40304 100644 --- a/packages/editor/src/core/types/document-collaborative-events.ts +++ b/packages/editor/src/core/types/document-collaborative-events.ts @@ -1,10 +1,87 @@ import { DocumentCollaborativeEvents } from "@/constants/document-collaborative-events"; -export type TDocumentEventKey = keyof typeof DocumentCollaborativeEvents; -export type TDocumentEventsClient = (typeof DocumentCollaborativeEvents)[TDocumentEventKey]["client"]; -export type TDocumentEventsServer = (typeof DocumentCollaborativeEvents)[TDocumentEventKey]["server"]; +// Base type for all action payloads +export type BaseActionPayload = { + user_id?: string; +}; + +// Generic type for creating specific payloads +export type CreatePayload> = BaseActionPayload & T; export type TDocumentEventEmitter = { on: (event: string, callback: (message: { payload: TDocumentEventsClient }) => void) => void; off: (event: string, callback: (message: { payload: TDocumentEventsClient }) => void) => void; }; + +export type TDocumentEventKey = keyof typeof DocumentCollaborativeEvents; +export type TDocumentEventsClient = (typeof DocumentCollaborativeEvents)[TDocumentEventKey]["client"]; +export type TDocumentEventsServer = (typeof DocumentCollaborativeEvents)[TDocumentEventKey]["server"]; + +// In this version, our union of all events (the client names) is: +export type TAllEventTypes = TDocumentEventsClient; + +// Create a mapping from each client event to its payload type using key remapping. +export type EventToPayloadMap = { + [K in keyof typeof DocumentCollaborativeEvents as (typeof DocumentCollaborativeEvents)[K]["client"]]: (typeof DocumentCollaborativeEvents)[K]["payloadType"]; +}; + +// Common fields for every realtime event +export type CommonRealtimeFields = { + affectedPages: { + currentPage: string; + parentPage: string | null; + descendantPages: string[]; + }; + workspace_slug: string; + project_id?: string; + teamspace_id?: string; + user_id: string; + timestamp: string; +}; + +// Helper function to create a realtime event in a type‑safe way. +export function createRealtimeEvent( + opts: ApiServerPayload +): CommonRealtimeFields & BroadcastedEvent { + return { + affectedPages: { + currentPage: opts.page_id || "", + parentPage: opts.parent_id || null, + descendantPages: opts.descendants_ids || [], + }, + workspace_slug: opts.workspace_slug, + project_id: opts.project_id || "", + teamspace_id: opts.teamspace_id || "", + user_id: opts.user_id, + timestamp: new Date().toISOString(), + action: opts.action, + data: opts.data, + }; +} + +export type ApiServerPayload = { + action: T; + descendants_ids: string[]; + page_id?: string; + parent_id?: string; + data: EventToPayloadMap[T]; + project_id?: string; + teamspace_id?: string; + workspace_slug: string; + user_id: string; +}; + +// Create a discriminated union for broadcast payloads. +// For every key in EventToPayloadMap, we make a union member with the common fields. +export type BroadcastPayloadUnion = { + [K in keyof EventToPayloadMap]: ApiServerPayload; +}[keyof EventToPayloadMap]; + +export type BroadcastedEventUnion = { + [K in keyof EventToPayloadMap]: BroadcastedEvent; +}[keyof EventToPayloadMap]; + +export type BroadcastedEvent = CommonRealtimeFields & { + action: T; + data: EventToPayloadMap[T]; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 54ddde453..6b7aedc27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,11 +22,11 @@ catalogs: specifier: 10.5.0 version: 10.5.0 '@tiptap/core': - specifier: ^3.5.3 - version: 3.6.2 + specifier: ^2.22.3 + version: 2.26.2 '@tiptap/html': - specifier: ^3.5.3 - version: 3.6.2 + specifier: ^2.22.3 + version: 2.26.2 '@types/lodash-es': specifier: 4.17.12 version: 4.17.12 @@ -208,20 +208,20 @@ importers: specifier: ^1.49.0 version: 1.49.0 '@hocuspocus/extension-database': - specifier: 3.2.5 - version: 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + specifier: 2.15.2 + version: 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) '@hocuspocus/extension-logger': - specifier: 3.2.5 - version: 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + specifier: 2.15.2 + version: 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) '@hocuspocus/extension-redis': - specifier: 3.2.5 - version: 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + specifier: 2.15.2 + version: 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) '@hocuspocus/server': - specifier: 3.2.5 - version: 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + specifier: 2.15.2 + version: 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) '@hocuspocus/transformer': - specifier: 3.2.5 - version: 3.2.5(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))(yjs@13.6.27) + specifier: 2.15.2 + version: 2.15.2(@tiptap/core@2.26.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))(yjs@13.6.27) '@plane/decorators': specifier: workspace:* version: link:../../packages/decorators @@ -242,10 +242,10 @@ importers: version: 10.5.0 '@tiptap/core': specifier: 'catalog:' - version: 3.6.2(@tiptap/pm@3.6.6) + version: 2.26.2(@tiptap/pm@3.6.6) '@tiptap/html': specifier: 'catalog:' - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(happy-dom@20.0.2) + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) axios: specifier: 'catalog:' version: 1.12.0 @@ -713,8 +713,8 @@ importers: specifier: ^1.7.3 version: 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@hocuspocus/provider': - specifier: 3.2.5 - version: 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + specifier: 2.15.2 + version: 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) '@plane/constants': specifier: workspace:* version: link:../constants @@ -732,55 +732,61 @@ importers: version: link:../utils '@tiptap/core': specifier: 'catalog:' - version: 3.6.2(@tiptap/pm@3.6.6) + version: 2.26.2(@tiptap/pm@2.26.3) '@tiptap/extension-blockquote': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-character-count': + specifier: ^2.22.3 + version: 2.26.1(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) '@tiptap/extension-collaboration': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@tiptap/y-tiptap@3.0.0(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))(yjs@13.6.27) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)) '@tiptap/extension-emoji': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@tiptap/suggestion@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))(emojibase@16.0.0) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(@tiptap/suggestion@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(emojibase@16.0.0) '@tiptap/extension-image': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) '@tiptap/extension-list-item': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) '@tiptap/extension-mention': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@tiptap/suggestion@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(@tiptap/suggestion@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)) + '@tiptap/extension-placeholder': + specifier: ^2.22.3 + version: 2.26.1(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) '@tiptap/extension-task-item': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) '@tiptap/extension-task-list': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) '@tiptap/extension-text-align': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) '@tiptap/extension-text-style': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extensions': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-underline': + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) '@tiptap/html': specifier: 'catalog:' - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(happy-dom@20.0.2) + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) '@tiptap/pm': - specifier: ^3.5.3 - version: 3.6.6 + specifier: ^2.22.3 + version: 2.26.3 '@tiptap/react': - specifier: ^3.5.3 - version: 3.6.2(@floating-ui/dom@1.7.4)(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tiptap/starter-kit': - specifier: ^3.5.3 - version: 3.6.2 + specifier: ^2.22.3 + version: 2.26.1 '@tiptap/suggestion': - specifier: ^3.5.3 - version: 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) + specifier: ^2.22.3 + version: 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) emoji-regex: specifier: ^10.3.0 version: 10.5.0 @@ -815,8 +821,8 @@ importers: specifier: ^6.3.7 version: 6.3.7 tiptap-markdown: - specifier: ^0.9.0 - version: 0.9.0(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) + specifier: ^0.8.10 + version: 0.8.10(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) uuid: specifier: 'catalog:' version: 13.0.0 @@ -1896,40 +1902,40 @@ packages: react: ^16 || ^17 || ^18 react-dom: ^16 || ^17 || ^18 - '@hocuspocus/common@3.2.5': - resolution: {integrity: sha512-unodX1+dBUp2sink7nKg/PSNDDUjM+AyMxg3WGpRTZb1LI0z/22DjjwFCgWWvoCNQALPVp9PFB/wyAI0xNo6GA==} + '@hocuspocus/common@2.15.3': + resolution: {integrity: sha512-Rzh1HF0a2o/tf90A3w2XNdXd9Ym3aQzMDfD3lAUONCX9B9QOdqdyiORrj6M25QEaJrEIbXFy8LtAFcL0wRdWzA==} - '@hocuspocus/extension-database@3.2.5': - resolution: {integrity: sha512-NGAPoHYLKGDGJgjHBhP1g+LLuUCx/fR9/frTMHytNtxqnyFbzo7meV5uUZjOO8X/ELii0c9VC8dG6Q9va9n7LQ==} + '@hocuspocus/extension-database@2.15.2': + resolution: {integrity: sha512-BkYDfKA99udx7AEkqWReBS61kvGMC9SqoPJs3v8xNgpaj2GGyMJQlUdQRMhPyZTn2osV+pqhk8Hn7xUJCW1RJg==} peerDependencies: yjs: ^13.6.8 - '@hocuspocus/extension-logger@3.2.5': - resolution: {integrity: sha512-KrzwbiRrqDlNzSg9Dc6h4i0B6gCRmsne6quwnKeJp0U6XXWCmsWABZ4rn55NdwadcOvZdCLEAbbcI7k/UiHXjQ==} + '@hocuspocus/extension-logger@2.15.2': + resolution: {integrity: sha512-nqSnSFI+xO7dBTsgzSANKvx09ptq8J4Doz3AdLgxfaweYC85qFao7mAx1ZCtWoVHseVwBYua6S3dTwQq5IsWEg==} - '@hocuspocus/extension-redis@3.2.5': - resolution: {integrity: sha512-yfJUH4y30ZpcvORO0fn2No9wtlfydqWxGnIIKfpuTsPyNoiemPMSMDZnjAQPyPib2wGUlIHBuFcuHw9B2uMvQA==} + '@hocuspocus/extension-redis@2.15.2': + resolution: {integrity: sha512-2BNBLnDEQq2v3uQSidBSdUOIbHhH383SGxn+hmy6tDQfrt2hLE4MwilgDdcCO0FKOCYaJrV7HyKu6/WyzLbAOg==} peerDependencies: y-protocols: ^1.0.6 yjs: ^13.6.8 - '@hocuspocus/provider@3.2.5': - resolution: {integrity: sha512-UZpmPYSp8T2ms1E049GayQcaUIVBAZCWiNIiuxfO/+lydTto8svqEgJVmIUqxmSJ3lO64zo9wsyQz9wXu2hlnQ==} + '@hocuspocus/provider@2.15.2': + resolution: {integrity: sha512-mdBurviyaUd7bQx4vMIE39WqRJDTpfFelHOVXr7w/jA8G1E7K7lxQ9/DacSrbg+9o8s+1z1+SerZiUjaToaBJg==} peerDependencies: y-protocols: ^1.0.6 yjs: ^13.6.8 - '@hocuspocus/server@3.2.5': - resolution: {integrity: sha512-2U8JJDXdD+xff6Vp6BQslYcSw7eoqV4V89fK4MIAEaptNMsgPASNUYfTYEwpL65+/nI1n4L6O6PGc/vwh8ycfg==} + '@hocuspocus/server@2.15.2': + resolution: {integrity: sha512-+fLRVswg+bkgfHqJ+wFgywivw3H08WMOtVvJF7dJzWT2ZR/Sc3nDMFh2KqMF6Ygh4z6mt23xr7SKIm3eP1zoLA==} peerDependencies: y-protocols: ^1.0.6 yjs: ^13.6.8 - '@hocuspocus/transformer@3.2.5': - resolution: {integrity: sha512-nbWNk6wLPBli4n74P8j8Zn6o9RmYiZAuWMJLMjv0zxFd4bMkfkXYa0OuwSqIG1d5nZGx1SSyxdx8ZxFtLPQqow==} + '@hocuspocus/transformer@2.15.2': + resolution: {integrity: sha512-FAo/rt0kch+YeBBp/iit74q+4RV6YRjdZXmvE0/Aw+n/nSW1W0ZNGXnhncfm8qP0CuXnss/Aw8dpfEPZKUWDJw==} peerDependencies: - '@tiptap/core': ^3.0.1 - '@tiptap/pm': ^3.0.1 + '@tiptap/core': ^2.6.4 + '@tiptap/pm': ^2.6.4 y-prosemirror: ^1.2.1 yjs: ^13.6.8 @@ -2492,12 +2498,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@oxc-project/runtime@0.82.3': - resolution: {integrity: sha512-LNh5GlJvYHAnMurO+EyA8jJwN1rki7l3PSHuosDh2I7h00T6/u9rCkUjg/SvPmT1CZzvhuW0y+gf7jcqUy/Usg==} - engines: {node: '>=6.9.0'} - - '@oxc-project/types@0.82.3': - resolution: {integrity: sha512-6nCUxBnGX0c6qfZW5MaF6/fmu5dHJDMiMPaioKHKs5mi5+8/FHQ7WGjgQIz1zxpmceMYfdIXkOaLYE+ejbuOtA==} + '@oxc-project/types@0.89.0': + resolution: {integrity: sha512-yuo+ECPIW5Q9mSeNmCDC2im33bfKuwW18mwkaHMQh8KakHYDzj4ci/q7wxf2qS3dMlVVCIyrs3kFtH5LmnlYnw==} '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} @@ -2769,78 +2771,91 @@ packages: '@remirror/core-constants@3.0.0': resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} - '@rolldown/binding-android-arm64@1.0.0-beta.34': - resolution: {integrity: sha512-jf5GNe5jP3Sr1Tih0WKvg2bzvh5T/1TA0fn1u32xSH7ca/p5t+/QRr4VRFCV/na5vjwKEhwWrChsL2AWlY+eoA==} + '@rolldown/binding-android-arm64@1.0.0-beta.38': + resolution: {integrity: sha512-AE3HFQrjWCKLFZD1Vpiy+qsqTRwwoil1oM5WsKPSmfQ5fif/A+ZtOZetF32erZdsR7qyvns6qHEteEsF6g6rsQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.0.0-beta.34': - resolution: {integrity: sha512-2F/TqH4QuJQ34tgWxqBjFL3XV1gMzeQgUO8YRtCPGBSP0GhxtoFzsp7KqmQEothsxztlv+KhhT9Dbg3HHwHViQ==} + '@rolldown/binding-darwin-arm64@1.0.0-beta.38': + resolution: {integrity: sha512-RaoWOKc0rrFsVmKOjQpebMY6c6/I7GR1FBc25v7L/R7NlM0166mUotwGEv7vxu7ruXH4SJcFeVrfADFUUXUmmQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.0.0-beta.34': - resolution: {integrity: sha512-E1QuFslgLWbHQ8Qli/AqUKdfg0pockQPwRxVbhNQ74SciZEZpzLaujkdmOLSccMlSXDfFCF8RPnMoRAzQ9JV8Q==} + '@rolldown/binding-darwin-x64@1.0.0-beta.38': + resolution: {integrity: sha512-Ymojqc2U35iUc8NFU2XX1WQPfBRRHN6xHcrxAf9WS8BFFBn8pDrH5QPvH1tYs3lDkw6UGGbanr1RGzARqdUp1g==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.0.0-beta.34': - resolution: {integrity: sha512-VS8VInNCwnkpI9WeQaWu3kVBq9ty6g7KrHdLxYMzeqz24+w9hg712TcWdqzdY6sn+24lUoMD9jTZrZ/qfVpk0g==} + '@rolldown/binding-freebsd-x64@1.0.0-beta.38': + resolution: {integrity: sha512-0ermTQ//WzSI0nOL3z/LUWMNiE9xeM5cLGxjewPFEexqxV/0uM8/lNp9QageQ8jfc/VO1OURsGw34HYO5PaL8w==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.34': - resolution: {integrity: sha512-4St4emjcnULnxJYb/5ZDrH/kK/j6PcUgc3eAqH5STmTrcF+I9m/X2xvSF2a2bWv1DOQhxBewThu0KkwGHdgu5w==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.38': + resolution: {integrity: sha512-GADxzVUTCTp6EWI52831A29Tt7PukFe94nhg/SUsfkI33oTiNQtPxyLIT/3oRegizGuPSZSlrdBurkjDwxyEUQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.34': - resolution: {integrity: sha512-a737FTqhFUoWfnebS2SnQ2BS50p0JdukdkUBwy2J06j4hZ6Eej0zEB8vTfAqoCjn8BQKkXBy+3Sx0IRkgwz1gA==} + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.38': + resolution: {integrity: sha512-SKO7Exl5Yem/OSNoA5uLHzyrptUQ8Hg70kHDxuwEaH0+GUg+SQe9/7PWmc4hFKBMrJGdQtii8WZ0uIz9Dofg5Q==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.34': - resolution: {integrity: sha512-NH+FeQWKyuw0k+PbXqpFWNfvD8RPvfJk766B/njdaWz4TmiEcSB0Nb6guNw1rBpM1FmltQYb3fFnTumtC6pRfA==} + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.38': + resolution: {integrity: sha512-SOo6+WqhXPBaShLxLT0eCgH17d3Yu1lMAe4mFP0M9Bvr/kfMSOPQXuLxBcbBU9IFM9w3N6qP9xWOHO+oUJvi8Q==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.34': - resolution: {integrity: sha512-Q3RSCivp8pNadYK8ke3hLnQk08BkpZX9BmMjgwae2FWzdxhxxUiUzd9By7kneUL0vRQ4uRnhD9VkFQ+Haeqdvw==} + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.38': + resolution: {integrity: sha512-yvsQ3CyrodOX+lcoi+lejZGCOvJZa9xTsNB8OzpMDmHeZq3QzJfpYjXSAS6vie70fOkLVJb77UqYO193Cl8XBQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-linux-x64-musl@1.0.0-beta.34': - resolution: {integrity: sha512-wDd/HrNcVoBhWWBUW3evJHoo7GJE/RofssBy3Dsiip05YUBmokQVrYAyrboOY4dzs/lJ7HYeBtWQ9hj8wlyF0A==} + '@rolldown/binding-linux-x64-musl@1.0.0-beta.38': + resolution: {integrity: sha512-84qzKMwUwikfYeOuJ4Kxm/3z15rt0nFGGQArHYIQQNSTiQdxGHxOkqXtzPFqrVfBJUdxBAf+jYzR1pttFJuWyg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - '@rolldown/binding-openharmony-arm64@1.0.0-beta.34': - resolution: {integrity: sha512-dH3FTEV6KTNWpYSgjSXZzeX7vLty9oBYn6R3laEdhwZftQwq030LKL+5wyQdlbX5pnbh4h127hpv3Hl1+sj8dg==} + '@rolldown/binding-openharmony-arm64@1.0.0-beta.38': + resolution: {integrity: sha512-QrNiWlce01DYH0rL8K3yUBu+lNzY+B0DyCbIc2Atan6/S6flxOL0ow5DLQvMamOI/oKhrJ4xG+9MkMb9dDHbLQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.0.0-beta.34': - resolution: {integrity: sha512-y5BUf+QtO0JsIDKA51FcGwvhJmv89BYjUl8AmN7jqD6k/eU55mH6RJYnxwCsODq5m7KSSTigVb6O7/GqB8wbPw==} + '@rolldown/binding-wasm32-wasi@1.0.0-beta.38': + resolution: {integrity: sha512-fnLtHyjwEsG4/aNV3Uv3Qd1ZbdH+CopwJNoV0RgBqrcQB8V6/Qdikd5JKvnO23kb3QvIpP+dAMGZMv1c2PJMzw==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.34': - resolution: {integrity: sha512-ga5hFhdTwpaNxEiuxZHWnD3ed0GBAzbgzS5tRHpe0ObptxM1a9Xrq6TVfNQirBLwb5Y7T/FJmJi3pmdLy95ljg==} + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.38': + resolution: {integrity: sha512-19cTfnGedem+RY+znA9J6ARBOCEFD4YSjnx0p5jiTm9tR6pHafRfFIfKlTXhun+NL0WWM/M0eb2IfPPYUa8+wg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.34': - resolution: {integrity: sha512-4/MBp9T9eRnZskxWr8EXD/xHvLhdjWaeX/qY9LPRG1JdCGV3DphkLTy5AWwIQ5jhAy2ZNJR5z2fYRlpWU0sIyQ==} + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.38': + resolution: {integrity: sha512-HcICm4YzFJZV+fI0O0bFLVVlsWvRNo/AB9EfUXvNYbtAxakCnQZ15oq22deFdz6sfi9Y4/SagH2kPU723dhCFA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.34': - resolution: {integrity: sha512-7O5iUBX6HSBKlQU4WykpUoEmb0wQmonb6ziKFr3dJTHud2kzDnWMqk344T0qm3uGv9Ddq6Re/94pInxo1G2d4w==} + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.38': + resolution: {integrity: sha512-4Qx6cgEPXLb0XsCyLoQcUgYBpfL0sjugftob+zhUH0EOk/NVCAIT+h0NJhY+jn7pFpeKxhNMqhvTNx3AesxIAQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rolldown/pluginutils@1.0.0-beta.34': - resolution: {integrity: sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA==} + '@rolldown/pluginutils@1.0.0-beta.38': + resolution: {integrity: sha512-N/ICGKleNhA5nc9XXQG/kkKHJ7S55u0x0XUJbbkmdCnFuoRkM1Il12q9q0eX19+M7KKUEPw/daUPIRnxhcxAIw==} '@rollup/pluginutils@5.2.0': resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==} @@ -2851,51 +2866,101 @@ packages: rollup: optional: true + '@rollup/rollup-android-arm-eabi@4.50.0': + resolution: {integrity: sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==} + cpu: [arm] + os: [android] + '@rollup/rollup-android-arm-eabi@4.52.4': resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] os: [android] + '@rollup/rollup-android-arm64@4.50.0': + resolution: {integrity: sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==} + cpu: [arm64] + os: [android] + '@rollup/rollup-android-arm64@4.52.4': resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} cpu: [arm64] os: [android] + '@rollup/rollup-darwin-arm64@4.50.0': + resolution: {integrity: sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==} + cpu: [arm64] + os: [darwin] + '@rollup/rollup-darwin-arm64@4.52.4': resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} cpu: [arm64] os: [darwin] + '@rollup/rollup-darwin-x64@4.50.0': + resolution: {integrity: sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==} + cpu: [x64] + os: [darwin] + '@rollup/rollup-darwin-x64@4.52.4': resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} cpu: [x64] os: [darwin] + '@rollup/rollup-freebsd-arm64@4.50.0': + resolution: {integrity: sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==} + cpu: [arm64] + os: [freebsd] + '@rollup/rollup-freebsd-arm64@4.52.4': resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} cpu: [arm64] os: [freebsd] + '@rollup/rollup-freebsd-x64@4.50.0': + resolution: {integrity: sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==} + cpu: [x64] + os: [freebsd] + '@rollup/rollup-freebsd-x64@4.52.4': resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} cpu: [x64] os: [freebsd] + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': + resolution: {integrity: sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.50.0': + resolution: {integrity: sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==} + cpu: [arm] + os: [linux] + '@rollup/rollup-linux-arm-musleabihf@4.52.4': resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} cpu: [arm] os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.50.0': + resolution: {integrity: sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-gnu@4.52.4': resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} cpu: [arm64] os: [linux] + '@rollup/rollup-linux-arm64-musl@4.50.0': + resolution: {integrity: sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==} + cpu: [arm64] + os: [linux] + '@rollup/rollup-linux-arm64-musl@4.52.4': resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} cpu: [arm64] @@ -2906,46 +2971,96 @@ packages: cpu: [loong64] os: [linux] + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': + resolution: {integrity: sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.50.0': + resolution: {integrity: sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==} + cpu: [ppc64] + os: [linux] + '@rollup/rollup-linux-ppc64-gnu@4.52.4': resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} cpu: [ppc64] os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.50.0': + resolution: {integrity: sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-gnu@4.52.4': resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.50.0': + resolution: {integrity: sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==} + cpu: [riscv64] + os: [linux] + '@rollup/rollup-linux-riscv64-musl@4.52.4': resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} cpu: [riscv64] os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.50.0': + resolution: {integrity: sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-s390x-gnu@4.52.4': resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} cpu: [s390x] os: [linux] + '@rollup/rollup-linux-x64-gnu@4.50.0': + resolution: {integrity: sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.52.4': resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} cpu: [x64] os: [linux] + '@rollup/rollup-linux-x64-musl@4.50.0': + resolution: {integrity: sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==} + cpu: [x64] + os: [linux] + '@rollup/rollup-linux-x64-musl@4.52.4': resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} cpu: [x64] os: [linux] + '@rollup/rollup-openharmony-arm64@4.50.0': + resolution: {integrity: sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==} + cpu: [arm64] + os: [openharmony] + '@rollup/rollup-openharmony-arm64@4.52.4': resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} cpu: [arm64] os: [openharmony] + '@rollup/rollup-win32-arm64-msvc@4.50.0': + resolution: {integrity: sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==} + cpu: [arm64] + os: [win32] + '@rollup/rollup-win32-arm64-msvc@4.52.4': resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} cpu: [arm64] os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.50.0': + resolution: {integrity: sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==} + cpu: [ia32] + os: [win32] + '@rollup/rollup-win32-ia32-msvc@4.52.4': resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} cpu: [ia32] @@ -2956,6 +3071,11 @@ packages: cpu: [x64] os: [win32] + '@rollup/rollup-win32-x64-msvc@4.50.0': + resolution: {integrity: sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==} + cpu: [x64] + os: [win32] + '@rollup/rollup-win32-x64-msvc@4.52.4': resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} cpu: [x64] @@ -3006,12 +3126,6 @@ packages: engines: {node: '>=18'} hasBin: true - '@sesamecare-oss/redlock@1.4.0': - resolution: {integrity: sha512-2z589R+yxKLN4CgKxP1oN4dsg6Y548SE4bVYam/R0kHk7Q9VrQ9l66q+k1ehhSLLY4or9hcchuF9/MhuuZdjJg==} - engines: {node: '>=16'} - peerDependencies: - ioredis: '>=5' - '@storybook/addon-actions@8.6.14': resolution: {integrity: sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==} peerDependencies: @@ -3420,224 +3534,210 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' - '@tiptap/core@3.6.2': - resolution: {integrity: sha512-XKZYrCVFsyQGF6dXQR73YR222l/76wkKfZ+2/4LCrem5qtcOarmv5pYxjUBG8mRuBPskTTBImSFTeQltJIUNCg==} + '@tiptap/core@2.26.2': + resolution: {integrity: sha512-cr30QWJECl5j7qUUG4Z4BDitHgJIBWipbC3JbjoDtumgZLedGa5SV+JiGa4GUhNt9E34Pw1BH0gBDL4adGHiLg==} peerDependencies: - '@tiptap/pm': ^3.6.2 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-blockquote@3.6.2': - resolution: {integrity: sha512-TSl41UZhi3ugJMDaf91CA4F5NeFylgTSm6GqnZAHOE6IREdCpAK3qej2zaW3EzfpzxW7sRGLlytkZRvpeyjgJA==} + '@tiptap/extension-blockquote@2.26.2': + resolution: {integrity: sha512-SQNMX2rkWdAOYT6pM9KZ4bZK07YiCqX6wkHiKbLSZ8GMLi35dhkiSBxvY2I72q5ucIjgC9asGf8knA/2fbVypA==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-bold@3.6.2': - resolution: {integrity: sha512-Q9KO8CCPCAXYqHzIw8b/ookVmrfqfCg2cyh9h9Hvw6nhO4LOOnJMcGVmWsrpFItbwCGMafI5iY9SbSj7RpCyuw==} + '@tiptap/extension-bold@2.26.2': + resolution: {integrity: sha512-kNjbHZhLyDu2ZBZmJINzXg3MAW7+05KqGkcwxudC1X/DQM5V5FpW7u6TOlC+nf1I9wABgayxURyU8FsIaXDxqA==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-bubble-menu@3.6.6': - resolution: {integrity: sha512-O+V+9T4encURWEccn17koU4rPBHA9QuyWErvx+XnVnC+cabhAcEVJEeCD5SjU4KarLBmnmw+bhDARe+AuR8WSw==} + '@tiptap/extension-bubble-menu@2.26.3': + resolution: {integrity: sha512-vliC5bv/md4qkguqqL8w7LW8jnXBD1FLdSMDavHRVwdRaRnEfLRAIY7Oxtc1Voy3+762tfn912TuwDlCOPsNSQ==} peerDependencies: - '@tiptap/core': ^3.6.6 - '@tiptap/pm': ^3.6.6 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-bullet-list@3.6.2': - resolution: {integrity: sha512-Y5Uhir+za7xMm6RAe592aNNlLvCayVSQt2HfSckOr+c/v/Zd2bFUHv0ef6l/nUzUhDBs32Bg9SvfWx/yyMyNEw==} + '@tiptap/extension-bullet-list@2.26.2': + resolution: {integrity: sha512-L0qxUa5vzUciLEVtr1nY6HG8gH8432GtuX807MM/5wKiYYdbSii3I22456ZnboiozoqXrjjvYUHeB++HhOSPgQ==} peerDependencies: - '@tiptap/extension-list': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-code-block@3.6.2': - resolution: {integrity: sha512-5jfoiQ/3AUrIyuVU1NmEXar6sZFnY7wDFf3ZU2zpcBUG++yg/CmpOe5bXpoolczhl58cM/jyBG5gumQjyOxLNg==} + '@tiptap/extension-character-count@2.26.1': + resolution: {integrity: sha512-F7LP1a9GF28thbApowWT2I41baqX74HMUTrV9LGrNXaOkW2gxZz+CDOzfHsbHyfuwfIxIjv07Qf/HKA6Cc1qbA==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-code@3.6.2': - resolution: {integrity: sha512-U6jilbcpCxtLZAgJrTapXzzVJTXnS78kJITFSOLyGCTyGSm6PXatQ4hnaxVGmNet66GySONGjhwAVZ8+l94Rwg==} + '@tiptap/extension-code-block@2.26.2': + resolution: {integrity: sha512-MJZ4QtziIWJ1zuSW2ogAHv+UHGk3DvGbVi+Dfmo0ybonXX7vRVHE+3qT7OcdTRBF+pC2oCnsjzqwFcGBP3BbZw==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-collaboration@3.6.2': - resolution: {integrity: sha512-cg57tmFNoFlkYB03WalsmkLEtgF6SvlVG4uaSt9ZjF6EE6InNT4hwm5BRPl6lcBSb6x3pvclPUaW7sQsXtmEFg==} + '@tiptap/extension-code@2.26.2': + resolution: {integrity: sha512-xnKJvzlAp75dheyaK5tLKAksHf9PtSr8a7OuPjf2IXS5K+QMtnwxx7KAHHijmecfWjLR0wyu9AvT/FWFfKi5LQ==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 - '@tiptap/y-tiptap': ^3.0.0-beta.3 - yjs: ^13 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-document@3.6.2': - resolution: {integrity: sha512-4qg3KWL3aO1M7hfDpZR6/vSo7Cfqr3McyGUfqb/BXqYDW1DwT8jJkDTcHrGU7WUKRlWgoyPyzM8pZiGlP0uQHg==} + '@tiptap/extension-collaboration@2.26.2': + resolution: {integrity: sha512-kvlzKnkhH57YgpuDIOu/h9iOuoIRZf8Bc+yAy/ldbCz9EnT8/k4BMaixb98lrYExaQfozGxuAAOZmK0sR95j4Q==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + y-prosemirror: ^1.2.11 - '@tiptap/extension-dropcursor@3.6.2': - resolution: {integrity: sha512-6R5sma/i2TKd5h9OpIcy3a0wOGp5BNT/zIgnE/1HTmKi40eNcCAVe8sxd6+iWA5ETONP1E48kDy4hqA5ZzZCiQ==} + '@tiptap/extension-document@2.26.2': + resolution: {integrity: sha512-s0/P3A8zxWL/h3e20xWMTT/rcwD0+57I6mT9JgNBPtvhPePy8d698G6/qFK+x+GdIyjJylfsq2BrSE9H+QhIBg==} peerDependencies: - '@tiptap/extensions': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-emoji@3.6.2': - resolution: {integrity: sha512-PLJu2ndQekeo78Bkyma25LeCI5ddpTLvwsQR3uuFLGY5CJcfpEK5BWrwwr873i/KO1h7BslFQZBniayzIBo+BQ==} + '@tiptap/extension-dropcursor@2.26.2': + resolution: {integrity: sha512-o5j4Gkurb/WBu1wP2tihYnZ8dENzmlxFWWMx++g6abEpn9xdud7VxHT5Ny7mBSBptI8uMwKT53weYC0on38n3g==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 - '@tiptap/suggestion': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-floating-menu@3.6.6': - resolution: {integrity: sha512-2ZKhBIgCs88Mju/9Kv4ngY5D1luwX7Fb8yemc6kXp9pYNFfJnXYeVP/110dRHJUbRrKtGXmnz8I5cgL/nqGEVQ==} + '@tiptap/extension-emoji@2.26.2': + resolution: {integrity: sha512-NeYU3H2arrjx7fFPnWl4IqjTMID8k5BKyDRgWarKQ1ApJpeq+8EzTGIffflHNcrIiZxezTtx4anhsC1NL+/Gdw==} peerDependencies: - '@floating-ui/dom': ^1.0.0 - '@tiptap/core': ^3.6.6 - '@tiptap/pm': ^3.6.6 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + '@tiptap/suggestion': ^2.7.0 - '@tiptap/extension-gapcursor@3.6.2': - resolution: {integrity: sha512-gXg+EvUKlv3ZO1GxKkRmAsi/V4yyA8AzLW6ppOcYrM2CKf6epmPaVRgAjdwHCA6cm3QuCBJyWeGTCAjhjNakhw==} + '@tiptap/extension-floating-menu@2.26.3': + resolution: {integrity: sha512-i2dsIMa0L6vjCPnTiXjPZXZqUu3sIIIAI+E1T4p0FsGYjjPTmN+AgkJqeO3bbe5XHmWcWKtgQevNCMF0kmU5rQ==} peerDependencies: - '@tiptap/extensions': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-hard-break@3.6.2': - resolution: {integrity: sha512-ncuPBHhGY58QjluJvEH6vXotaa1QZ/vphXBGAr55kiATZwMIEHgwh2Hgc6AiFTcw057gabGn6jNFDfRB+HjbmA==} + '@tiptap/extension-gapcursor@2.26.2': + resolution: {integrity: sha512-a68mi8V0mh058UrBIk23f50K5JGVeRZnF6ViptIleAD/Ny1K6VLjGCz6k190de+Tb9tnQLPEwwwDcy+ZnvCmYQ==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-heading@3.6.2': - resolution: {integrity: sha512-JQ2yjwXGAiwGc+MhS1mULBr354MHfmWqVDQLRg8ey6LkdXggTDDJ1Ni3GrUS7B5YcA/ICdhr4krXaQpNkT5Syw==} + '@tiptap/extension-hard-break@2.26.2': + resolution: {integrity: sha512-OLpeTey7p3ChyEsABLPvNv7rD/8E4k1JTt+H+MUjyL0dnrZuIWluckUJCJKnV8PhR9Mifngk1MTFUilpooiv1g==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-horizontal-rule@3.6.2': - resolution: {integrity: sha512-3TlPqedPDM9QkRTUPhOTxNxQVPSsBwlsuLrAZOgyM1y871Xi7M1DFX0h9LLXuqzPndYzUY16NjrfBGFJX+O56w==} + '@tiptap/extension-heading@2.26.2': + resolution: {integrity: sha512-0VAr1l1QKFJ0B2l4D4wV0LRlyFYeJt0S09mz+HPF2TqKF4twmPjaGD6o5zzXWl8c4cQj1CmM8P+9an3SKRjOaA==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-image@3.6.2': - resolution: {integrity: sha512-AuetGUr1sGH18UDREk0EMt7jYnFkBFsnYlXNNcp0g0rGACRKaCD7Bzv451nHc8m1WYOpqMAyTTlRg+eYs442xA==} + '@tiptap/extension-history@2.26.1': + resolution: {integrity: sha512-m6YR1gkkauIDo3PRl0gP+7Oc4n5OqDzcjVh6LvWREmZP8nmi94hfseYbqOXUb6RPHIc0JKF02eiRifT4MSd2nw==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-italic@3.6.2': - resolution: {integrity: sha512-46zYKqM3o9w1A2G9hWr0ERGbJpqIncoH45XIfLdAI6ZldZVVf+NeXMGwjOPf4+03cZ5/emk3MRTnVp9vF4ToIg==} + '@tiptap/extension-horizontal-rule@2.26.2': + resolution: {integrity: sha512-whlUskFUwmi7nXn4OT55xHXSAqwEAEQfZWswmae1Y5wTMDxavZ0FF4xvCVgsQ7gYG782tIgLCzriTN4AjBphIQ==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-link@3.6.2': - resolution: {integrity: sha512-3yiRDWa187h30e6iUOJeejZLsbzbJthLfBwTeJGx7pHh7RngsEW82npBRuqLoI3udhJGTkXbzwAFZ9qOGOjl1Q==} + '@tiptap/extension-image@2.26.2': + resolution: {integrity: sha512-3gK+ETLiWGAUdyPDXDheNJ38OgQabSzZJ+1nQo9KWjI7P3LQ7/ctxLtT+hAFpxX0qMK4bnu5vZaItSXxE3ZtpQ==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-list-item@3.6.2': - resolution: {integrity: sha512-ma/D2GKylpNB04FfNI3tDMY+C9nz7Yk85H21YTIGv8QL5KlDK97L6orydmx6IVRc2nNMZQVitBIEKDOXcczX9w==} + '@tiptap/extension-italic@2.26.2': + resolution: {integrity: sha512-/4AiE2JWtjY9yW+MifMP8EOOwOSDKDUxCyqtGT6e4xqqFUNLZJA0o4P/MYjcKVwsa1/IsDRsOaFRlAiMmAXVXw==} peerDependencies: - '@tiptap/extension-list': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-list-keymap@3.6.2': - resolution: {integrity: sha512-1kl/lggH+LL/FUwcSx8p761ebk9L5ZGK06mGyDDU9XiGLS310CktZYLnpEuFgn/oMPbRHo26oNl9SXLn1/U53A==} + '@tiptap/extension-list-item@2.26.2': + resolution: {integrity: sha512-T1dFfx1JjRRX0iyStSTwMNajMyT+OE7XEggn+DON1g+zbgA+4cJ11WQpfrfA9VM2H5QWYyKGfHFigoFcJ8rjog==} peerDependencies: - '@tiptap/extension-list': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-list@3.6.6': - resolution: {integrity: sha512-JOPOAl78gDycPD/fAby92M1I/59cgNQzsXXrY8lqFSl4d52RmqzYHx8VrBee1X441xnerZBpHkfsxFYwJCLaWg==} + '@tiptap/extension-mention@2.26.2': + resolution: {integrity: sha512-fezYJQlewhfaIXBQ85LTDRBMsWfynb9xSsEYC8EeRhbwI5fFlWKEAi876oQiSqqJTg6NV/pda9dUn+wZkV7U4w==} peerDependencies: - '@tiptap/core': ^3.6.6 - '@tiptap/pm': ^3.6.6 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + '@tiptap/suggestion': ^2.7.0 - '@tiptap/extension-mention@3.6.2': - resolution: {integrity: sha512-GrD+CB+kYWSAG1GzrWHoqPqtrE16vfNV2QnAwMb1tdmJIBBF971OVx6qjdvjxXdbccwnHMeCIl+oj7ydrwtQLw==} + '@tiptap/extension-ordered-list@2.26.2': + resolution: {integrity: sha512-UVGYyWKB5wWWvrvdN/WrPXPHJoP/UD1TNyeoE75M6nq4oD4l+Nc9Y5MIPsngrv/TimbomLNilR4ZRHibEriG9w==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 - '@tiptap/suggestion': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-ordered-list@3.6.2': - resolution: {integrity: sha512-KdJ5MLIw19N+XiqQ2COXGtaq9TzUbtlLE5dgYCJQ2EumeZKIGELvUnHjrnIB9gH/gRlMs+hprLTh23xVUDJovg==} + '@tiptap/extension-paragraph@2.26.2': + resolution: {integrity: sha512-dccyffm95nNT9arjxGOyv4/cOPF4XS5Osylccp9KYLrmiSTXEuzVIYtMXhXbc0UUdABGvbFQWi88tRxgeDTkgA==} peerDependencies: - '@tiptap/extension-list': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-paragraph@3.6.2': - resolution: {integrity: sha512-jeJWj2xKib3392iHQEcB7wYZ30dUgXuwqpCTwtN9eANor+Zvv6CpDKBs1R2al6BYFbIJCgKeTulqxce0yoC80g==} + '@tiptap/extension-placeholder@2.26.1': + resolution: {integrity: sha512-MBlqbkd+63btY7Qu+SqrXvWjPwooGZDsLTtl7jp52BczBl61cq9yygglt9XpM11TFMBdySgdLHBrLtQ0B7fBlw==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-strike@3.6.2': - resolution: {integrity: sha512-976u5WaioIN/0xCjl/UIEypmzACzxgVz6OGgfIsYyreMUiPjhhgzXb0A/2Po5p3nZpKcaMcxifOdhqdw+lDpIQ==} + '@tiptap/extension-strike@2.26.2': + resolution: {integrity: sha512-gY8/P8ycvICiZsa9OeTpOnSL0o+PAYH1QpBomaBhdZZ2tcsziMYN9BZto6uQARi9tdxeOYRePyZ+Junk4xsyFg==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-task-item@3.6.2': - resolution: {integrity: sha512-lD4qJTRYDmj01bdRcfyuznWqsckKQk9R53fTFUu/6BflfP4LcDUmC7n2aeeX9a0uOXCgVDP6FMpreLtDgD0pjA==} + '@tiptap/extension-task-item@2.26.2': + resolution: {integrity: sha512-KFfl9QraNldIR9ayP7t+b69BvjmdGeE9Mr+u/6h6jOmUVFpnES45geuEBSYuWWpK4EeD3ZUKXo7WGEWnTLSyfQ==} peerDependencies: - '@tiptap/extension-list': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-task-list@3.6.2': - resolution: {integrity: sha512-Usbb+/b8VHLpo6/gakTuC4Vobfu0wowyU1qzaf3F4UOyaVP3qYeE3hJSJKOCOro8JB8OQHdCb/PMixdocsn0/g==} + '@tiptap/extension-task-list@2.26.2': + resolution: {integrity: sha512-mQdB0BVULJiiFPGdst4JbQPm/ZGZMIeYafVu6iGSMYxdP4piMvMbY4txtLV8zN8oUEAO5zooiXXbS3OFFBDZyQ==} peerDependencies: - '@tiptap/extension-list': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-text-align@3.6.2': - resolution: {integrity: sha512-P3IYe6pyOe9hZoSQfHypFioLbGrr24d55/RkvNnwSd8qzd0RhjXIyiuOmYLcXdLio4PkJ+KjbZcptQ9zW8Mh4g==} + '@tiptap/extension-text-align@2.26.2': + resolution: {integrity: sha512-fra+weXocCINVPGjykteTiQ+p34POSWyxw+Y+KFBegw24uecHhB5NCK6aXa68tvEMLC9EdvZRHuoKRfkxBQ9rw==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-text-style@3.6.2': - resolution: {integrity: sha512-1N5suFcjZLdccYN+5zjFGFPV6YsLWbz0aYnLcwUvrRSxMm5VkOqKSm5ZLV11rikU06WgkfpLCtmZ5jpl0piD9Q==} + '@tiptap/extension-text-style@2.26.2': + resolution: {integrity: sha512-rNkV3dgT3nTISEf3Ax/DdqQsSy9p46n2fOBkD8FCtdrwsWNH5N4uUh4jI/q0exYKJUyZGvl60uXwCkZiQ3pVBA==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-text@3.6.2': - resolution: {integrity: sha512-fFSUEv1H3lM92yr6jZdELk0gog8rPTK5hTf08kP8RsY8pA80Br1ADVenejrMV4UNTmT1JWTXGBGhMqfQFHUvAQ==} + '@tiptap/extension-text@2.26.2': + resolution: {integrity: sha512-Rb8Le/Li+EixQNc/pGkEJpLjozTjWYP9glaYfnjPtRVw4tHcd7khVm5mer0TQjonbBUjVC1zSuXv9gifXOv6DQ==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-underline@3.6.2': - resolution: {integrity: sha512-IrG6vjxTMI2EeyhZCtx0sNTEu83PsAvzIh4vxmG1fUi/RYokks+sFbgGMuq0jtO96iVNEszlpAC/vaqfxFJwew==} + '@tiptap/extension-underline@2.26.2': + resolution: {integrity: sha512-kpKJSfsn1+b8l96YPg2GRn3aaN78pLqSeyzfA5FYVbN0lyptbqRVOrNM8p3n6l0LbAkiEjc/TgOMwNNEL93kyA==} peerDependencies: - '@tiptap/core': ^3.6.2 + '@tiptap/core': ^2.7.0 - '@tiptap/extensions@3.6.2': - resolution: {integrity: sha512-tg7/DgaI6SpkeawryapUtNoBxsJUMJl3+nSjTfTvsaNXed+BHzLPsvmPbzlF9ScrAbVEx8nj6CCkneECYIQ4CQ==} + '@tiptap/html@2.26.2': + resolution: {integrity: sha512-I1h+aVpP94j9elO3aO49BMSISl4jrLZPhUijshFGgsSr94xRqLd/s4iBceRxeoBfhCgtHxsKaWXrdBbvL+N0pQ==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/html@3.6.2': - resolution: {integrity: sha512-48ibDQwsW4TQBskUmLghitP4H3L/XobeYYfHcBvTtKCqTAXo8QWkph+UdYZ7L/j9Mqhb5r2JdaxzLLOqD9y/Lw==} - peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 - happy-dom: 20.0.2 + '@tiptap/pm@2.26.3': + resolution: {integrity: sha512-8gUmdxWlUevmgq2mNvGxvf2CpDW097tVKECMWKEn8sf846kXv3CoqaGRhI3db4kfR+09uWZeRM7rtrjRBmUThg==} '@tiptap/pm@3.6.6': resolution: {integrity: sha512-E/rtpPEqPiQJrchdOUDcMPR69x96a+JeMWLL12fos4KfF7YVzQ5oUIij21RffV+qeHxug7HMUpQKBtCuJfek/Q==} - '@tiptap/react@3.6.2': - resolution: {integrity: sha512-jgG+bM/GDvI6jnqW3YyLtr/vOR6iO2ta9PYVzoWqNYIxISsMOJeRfinsIqB8l6hkiGZApn9bQji6oUXTc59fgA==} + '@tiptap/react@2.26.2': + resolution: {integrity: sha512-p7jv0sltCC2L4iHIVNthtjv/CIxajOalb7ytjLx6ijx5q2J564VIny0U7O33Ymbo2cV0dJoB+Bo5aeaJ5SfHGg==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - '@types/react-dom': ^17.0.0 || ^18.0.0 || ^19.0.0 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 - '@tiptap/starter-kit@3.6.2': - resolution: {integrity: sha512-nPzraIx/f1cOUNqG1LSC0OTnEu3mudcN3jQVuyGh3dvdOnik7FUciJEVfHKnloAyeoijidEeiLpiGHInp2uREg==} + '@tiptap/starter-kit@2.26.1': + resolution: {integrity: sha512-oziMGCds8SVQ3s5dRpBxVdEKZAmO/O//BjZ69mhA3q4vJdR0rnfLb5fTxSeQvHiqB878HBNn76kNaJrHrV35GA==} - '@tiptap/suggestion@3.6.2': - resolution: {integrity: sha512-tkqHAiRvxo5tnRF/Y6l/VOg7Hno9X6lBjqajEXWPfPjlW/6tdC08Te9Gr7+mhfd168yPDjVhLyKMI209ypnwbw==} + '@tiptap/suggestion@2.26.2': + resolution: {integrity: sha512-BtigI3xOJQbdNh2OeKN5wQDI/EPGN4GXdpoMHhENZeXKrX6PvWNaqjyLVsV3QiLgv6P352nZWcgo51wPXY2JgQ==} peerDependencies: - '@tiptap/core': ^3.6.2 - '@tiptap/pm': ^3.6.2 - - '@tiptap/y-tiptap@3.0.0': - resolution: {integrity: sha512-HIeJZCj+KYJde2x6fONzo4o6kd7gW7eonwhQsv2p2VQnUgwNXMVhN+D6Z3AH/2i541Sq33y1PO4U/1ThCPjqbA==} - engines: {node: '>=16.0.0', npm: '>=8.0.0'} - peerDependencies: - prosemirror-model: ^1.7.1 - prosemirror-state: ^1.2.3 - prosemirror-view: 1.40.0 - y-protocols: ^1.0.1 - yjs: ^13.5.38 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 '@tokenizer/inflate@0.2.7': resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} @@ -3796,9 +3896,6 @@ packages: '@types/mysql@2.15.27': resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==} - '@types/node@20.19.15': - resolution: {integrity: sha512-W3bqcbLsRdFDVcmAM5l6oLlcl67vjevn8j1FPZ4nx+K5jNoWCh+FC/btxFoBPnvQlrHHDwfjp1kjIEDfwJ0Mog==} - '@types/node@22.12.0': resolution: {integrity: sha512-Fll2FZ1riMjNmlmJOdAyY5pUbkftXslB5DgEzlIuNaiWhXd00FhWxVC/r4yV/4wBb9JfImTu+jiSvXTkJ7F/gA==} @@ -3880,9 +3977,6 @@ packages: '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - '@types/whatwg-mimetype@3.0.2': - resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} - '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} @@ -4305,9 +4399,6 @@ packages: async-lock@1.4.1: resolution: {integrity: sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==} - async-mutex@0.5.0: - resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} - async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} @@ -4388,6 +4479,9 @@ packages: birpc@2.6.1: resolution: {integrity: sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==} + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + body-parser@1.20.3: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -4796,6 +4890,15 @@ packages: supports-color: optional: true + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -4851,6 +4954,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + denque@1.5.1: + resolution: {integrity: sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==} + engines: {node: '>=0.10'} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -5047,6 +5154,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@5.0.0: + resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==} + engines: {node: '>=0.12'} + entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} @@ -5590,10 +5701,6 @@ packages: gud@1.0.0: resolution: {integrity: sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==} - happy-dom@20.0.2: - resolution: {integrity: sha512-pYOyu624+6HDbY+qkjILpQGnpvZOusItCk+rvF5/V+6NkcgTKnbOldpIy22tBnxoaLtlM9nXgoqAcW29/B7CIw==} - engines: {node: '>=20.0.0'} - has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -5769,6 +5876,10 @@ packages: intl-messageformat@10.7.16: resolution: {integrity: sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==} + ioredis@4.30.1: + resolution: {integrity: sha512-17Ed70njJ7wT7JZsdTVLb0j/cmwHwfQCFu+AP6jY7nFKd+CA7MBW7nX121mM64eT8S9ekAVtYYt8nGQPmm3euA==} + engines: {node: '>=6'} + ioredis@5.7.0: resolution: {integrity: sha512-NUcA93i1lukyXU+riqEyPtSEkyFq8tX90uL659J+qpCZ3rEdViB/APC58oAhIh3+bJln2hzdlZbBZsGNrlsR8g==} engines: {node: '>=12.22.0'} @@ -6113,6 +6224,9 @@ packages: lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} @@ -6597,6 +6711,10 @@ packages: resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -7244,6 +7362,10 @@ packages: resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} engines: {node: '>=4'} + redlock@4.2.0: + resolution: {integrity: sha512-j+oQlG+dOwcetUt2WJWttu4CZVeRzUrcVcISFmEmfyuwCVSJ93rDT7YSgg7H7rnxwoRyk/jU46kycVka5tW7jA==} + engines: {node: '>=8.0.0'} + reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} @@ -7333,8 +7455,14 @@ packages: vue-tsc: optional: true - rolldown@1.0.0-beta.34: - resolution: {integrity: sha512-Wwh7EwalMzzX3Yy3VN58VEajeR2Si8+HDNMf706jPLIqU7CxneRW+dQVfznf5O0TWTnJyu4npelwg2bzTXB1Nw==} + rolldown@1.0.0-beta.38: + resolution: {integrity: sha512-58frPNX55Je1YsyrtPJv9rOSR3G5efUZpRqok94Efsj0EUa8dnqJV3BldShyI7A+bVPleucOtzXHwVpJRcR0kQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.50.0: + resolution: {integrity: sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true rollup@4.52.4: @@ -7768,10 +7896,10 @@ packages: tippy.js@6.3.7: resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} - tiptap-markdown@0.9.0: - resolution: {integrity: sha512-dKLQ9iiuGNgrlGVjrNauF/UBzWu4LYOx5pkD0jNkmQt/GOwfCJsBuzZTsf1jZ204ANHOm572mZ9PYvGh1S7tpQ==} + tiptap-markdown@0.8.10: + resolution: {integrity: sha512-iDVkR2BjAqkTDtFX0h94yVvE2AihCXlF0Q7RIXSJPRSR5I0PA1TMuAg6FHFpmqTn4tPxJ0by0CK7PUMlnFLGEQ==} peerDependencies: - '@tiptap/core': ^3.0.1 + '@tiptap/core': ^2.0.3 tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} @@ -7955,9 +8083,6 @@ packages: undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - unicode-properties@1.4.1: resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==} @@ -8066,6 +8191,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + uuid@13.0.0: resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} hasBin: true @@ -8193,10 +8322,6 @@ packages: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} - whatwg-mimetype@3.0.0: - resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} - engines: {node: '>=12'} - whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} @@ -8353,6 +8478,10 @@ packages: yoga-layout@2.0.1: resolution: {integrity: sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q==} + zeed-dom@0.15.1: + resolution: {integrity: sha512-dtZ0aQSFyZmoJS0m06/xBN1SazUBPL5HpzlAcs/KcRW0rzadYw12deQBjeMhGKMMeGEp7bA9vmikMLaO4exBcg==} + engines: {node: '>=14.13.1'} + zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} @@ -8407,7 +8536,7 @@ snapshots: '@babel/types': 7.28.4 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -8481,7 +8610,7 @@ snapshots: '@babel/parser': 7.28.4 '@babel/template': 7.27.2 '@babel/types': 7.28.4 - debug: 4.4.3 + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -8898,35 +9027,36 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@hocuspocus/common@3.2.5': + '@hocuspocus/common@2.15.3': dependencies: lib0: 0.2.114 - '@hocuspocus/extension-database@3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': + '@hocuspocus/extension-database@2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': dependencies: - '@hocuspocus/server': 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + '@hocuspocus/server': 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) yjs: 13.6.27 transitivePeerDependencies: - bufferutil - utf-8-validate - y-protocols - '@hocuspocus/extension-logger@3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': + '@hocuspocus/extension-logger@2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': dependencies: - '@hocuspocus/server': 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + '@hocuspocus/server': 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) transitivePeerDependencies: - bufferutil - utf-8-validate - y-protocols - yjs - '@hocuspocus/extension-redis@3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': + '@hocuspocus/extension-redis@2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': dependencies: - '@hocuspocus/server': 3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) - '@sesamecare-oss/redlock': 1.4.0(ioredis@5.7.0) - ioredis: 5.7.0 + '@hocuspocus/server': 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) + ioredis: 4.30.1 kleur: 4.1.5 lodash.debounce: 4.0.8 + redlock: 4.2.0 + uuid: 11.1.0 y-protocols: 1.0.6(yjs@13.6.27) yjs: 13.6.27 transitivePeerDependencies: @@ -8934,9 +9064,9 @@ snapshots: - supports-color - utf-8-validate - '@hocuspocus/provider@3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': + '@hocuspocus/provider@2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': dependencies: - '@hocuspocus/common': 3.2.5 + '@hocuspocus/common': 2.15.3 '@lifeomic/attempt': 3.1.0 lib0: 0.2.114 ws: 8.18.3 @@ -8946,13 +9076,13 @@ snapshots: - bufferutil - utf-8-validate - '@hocuspocus/server@3.2.5(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': + '@hocuspocus/server@2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': dependencies: - '@hocuspocus/common': 3.2.5 + '@hocuspocus/common': 2.15.3 async-lock: 1.4.1 - async-mutex: 0.5.0 kleur: 4.1.5 lib0: 0.2.114 + uuid: 11.1.0 ws: 8.18.3 y-protocols: 1.0.6(yjs@13.6.27) yjs: 13.6.27 @@ -8960,11 +9090,11 @@ snapshots: - bufferutil - utf-8-validate - '@hocuspocus/transformer@3.2.5(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))(yjs@13.6.27)': + '@hocuspocus/transformer@2.15.2(@tiptap/core@2.26.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))(yjs@13.6.27)': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@3.6.6) '@tiptap/pm': 3.6.6 - '@tiptap/starter-kit': 3.6.2 + '@tiptap/starter-kit': 2.26.1 y-prosemirror: 1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) yjs: 13.6.27 @@ -9532,9 +9662,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.1.0(@opentelemetry/api@1.9.0) - '@oxc-project/runtime@0.82.3': {} - - '@oxc-project/types@0.82.3': {} + '@oxc-project/types@0.89.0': {} '@pkgjs/parseargs@0.11.0': optional: true @@ -9868,51 +9996,51 @@ snapshots: '@remirror/core-constants@3.0.0': {} - '@rolldown/binding-android-arm64@1.0.0-beta.34': + '@rolldown/binding-android-arm64@1.0.0-beta.38': optional: true - '@rolldown/binding-darwin-arm64@1.0.0-beta.34': + '@rolldown/binding-darwin-arm64@1.0.0-beta.38': optional: true - '@rolldown/binding-darwin-x64@1.0.0-beta.34': + '@rolldown/binding-darwin-x64@1.0.0-beta.38': optional: true - '@rolldown/binding-freebsd-x64@1.0.0-beta.34': + '@rolldown/binding-freebsd-x64@1.0.0-beta.38': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.34': + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.38': optional: true - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.34': + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.38': optional: true - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.34': + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.38': optional: true - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.34': + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.38': optional: true - '@rolldown/binding-linux-x64-musl@1.0.0-beta.34': + '@rolldown/binding-linux-x64-musl@1.0.0-beta.38': optional: true - '@rolldown/binding-openharmony-arm64@1.0.0-beta.34': + '@rolldown/binding-openharmony-arm64@1.0.0-beta.38': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-beta.34': + '@rolldown/binding-wasm32-wasi@1.0.0-beta.38': dependencies: '@napi-rs/wasm-runtime': 1.0.5 optional: true - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.34': + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.38': optional: true - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.34': + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.38': optional: true - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.34': + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.38': optional: true - '@rolldown/pluginutils@1.0.0-beta.34': {} + '@rolldown/pluginutils@1.0.0-beta.38': {} '@rollup/pluginutils@5.2.0(rollup@4.52.4)': dependencies: @@ -9922,69 +10050,132 @@ snapshots: optionalDependencies: rollup: 4.52.4 + '@rollup/rollup-android-arm-eabi@4.50.0': + optional: true + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true + '@rollup/rollup-android-arm64@4.50.0': + optional: true + '@rollup/rollup-android-arm64@4.52.4': optional: true + '@rollup/rollup-darwin-arm64@4.50.0': + optional: true + '@rollup/rollup-darwin-arm64@4.52.4': optional: true + '@rollup/rollup-darwin-x64@4.50.0': + optional: true + '@rollup/rollup-darwin-x64@4.52.4': optional: true + '@rollup/rollup-freebsd-arm64@4.50.0': + optional: true + '@rollup/rollup-freebsd-arm64@4.52.4': optional: true + '@rollup/rollup-freebsd-x64@4.50.0': + optional: true + '@rollup/rollup-freebsd-x64@4.52.4': optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.50.0': + optional: true + '@rollup/rollup-linux-arm-gnueabihf@4.52.4': optional: true + '@rollup/rollup-linux-arm-musleabihf@4.50.0': + optional: true + '@rollup/rollup-linux-arm-musleabihf@4.52.4': optional: true + '@rollup/rollup-linux-arm64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-arm64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-arm64-musl@4.50.0': + optional: true + '@rollup/rollup-linux-arm64-musl@4.52.4': optional: true '@rollup/rollup-linux-loong64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-loongarch64-gnu@4.50.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-ppc64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-riscv64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-riscv64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-riscv64-musl@4.50.0': + optional: true + '@rollup/rollup-linux-riscv64-musl@4.52.4': optional: true + '@rollup/rollup-linux-s390x-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-s390x-gnu@4.52.4': optional: true + '@rollup/rollup-linux-x64-gnu@4.50.0': + optional: true + '@rollup/rollup-linux-x64-gnu@4.52.4': optional: true + '@rollup/rollup-linux-x64-musl@4.50.0': + optional: true + '@rollup/rollup-linux-x64-musl@4.52.4': optional: true + '@rollup/rollup-openharmony-arm64@4.50.0': + optional: true + '@rollup/rollup-openharmony-arm64@4.52.4': optional: true + '@rollup/rollup-win32-arm64-msvc@4.50.0': + optional: true + '@rollup/rollup-win32-arm64-msvc@4.52.4': optional: true + '@rollup/rollup-win32-ia32-msvc@4.50.0': + optional: true + '@rollup/rollup-win32-ia32-msvc@4.52.4': optional: true '@rollup/rollup-win32-x64-gnu@4.52.4': optional: true + '@rollup/rollup-win32-x64-msvc@4.50.0': + optional: true + '@rollup/rollup-win32-x64-msvc@4.52.4': optional: true @@ -10069,10 +10260,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@sesamecare-oss/redlock@1.4.0(ioredis@5.7.0)': - dependencies: - ioredis: 5.7.0 - '@storybook/addon-actions@8.6.14(storybook@8.6.14(prettier@3.6.2))': dependencies: '@storybook/global': 5.0.0 @@ -10354,7 +10541,7 @@ snapshots: '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.8.3)(webpack@5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.0))': dependencies: - debug: 4.4.3 + debug: 4.4.1 endent: 2.1.0 find-cache-dir: 3.3.2 flat-cache: 3.2.0 @@ -10585,167 +10772,193 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 - '@tiptap/core@3.6.2(@tiptap/pm@3.6.6)': + '@tiptap/core@2.26.2(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/pm': 2.26.3 + + '@tiptap/core@2.26.2(@tiptap/pm@3.6.6)': dependencies: '@tiptap/pm': 3.6.6 - '@tiptap/extension-blockquote@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': + '@tiptap/extension-blockquote@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) - '@tiptap/extension-bold@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': + '@tiptap/extension-bold@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) - '@tiptap/extension-bubble-menu@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': + '@tiptap/extension-bubble-menu@2.26.3(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': dependencies: - '@floating-ui/dom': 1.7.4 - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - optional: true + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + tippy.js: 6.3.7 - '@tiptap/extension-bullet-list@3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': + '@tiptap/extension-bullet-list@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': dependencies: - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) - '@tiptap/extension-code-block@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': + '@tiptap/extension-character-count@2.26.1(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 - '@tiptap/extension-code@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': + '@tiptap/extension-code-block@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 - '@tiptap/extension-collaboration@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@tiptap/y-tiptap@3.0.0(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))(yjs@13.6.27)': + '@tiptap/extension-code@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - '@tiptap/y-tiptap': 3.0.0(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) - yjs: 13.6.27 + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) - '@tiptap/extension-document@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': + '@tiptap/extension-collaboration@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27))': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + y-prosemirror: 1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27) - '@tiptap/extension-dropcursor@3.6.2(@tiptap/extensions@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': + '@tiptap/extension-document@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': dependencies: - '@tiptap/extensions': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) - '@tiptap/extension-emoji@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@tiptap/suggestion@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))(emojibase@16.0.0)': + '@tiptap/extension-dropcursor@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - '@tiptap/suggestion': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + + '@tiptap/extension-emoji@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(@tiptap/suggestion@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))(emojibase@16.0.0)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + '@tiptap/suggestion': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) emoji-regex: 10.5.0 emojibase-data: 15.3.2(emojibase@16.0.0) is-emoji-supported: 0.0.5 transitivePeerDependencies: - emojibase - '@tiptap/extension-floating-menu@3.6.6(@floating-ui/dom@1.7.4)(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': + '@tiptap/extension-floating-menu@2.26.3(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': dependencies: - '@floating-ui/dom': 1.7.4 - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + tippy.js: 6.3.7 + + '@tiptap/extension-gapcursor@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + + '@tiptap/extension-hard-break@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-heading@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-history@2.26.1(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + + '@tiptap/extension-horizontal-rule@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + + '@tiptap/extension-image@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-italic@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-list-item@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-mention@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(@tiptap/suggestion@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + '@tiptap/suggestion': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + + '@tiptap/extension-ordered-list@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-paragraph@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-placeholder@2.26.1(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + + '@tiptap/extension-strike@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-task-item@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + + '@tiptap/extension-task-list@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-text-align@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-text-style@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-text@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/extension-underline@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + + '@tiptap/html@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 + zeed-dom: 0.15.1 + + '@tiptap/html@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': + dependencies: + '@tiptap/core': 2.26.2(@tiptap/pm@3.6.6) '@tiptap/pm': 3.6.6 - optional: true + zeed-dom: 0.15.1 - '@tiptap/extension-gapcursor@3.6.2(@tiptap/extensions@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': + '@tiptap/pm@2.26.3': dependencies: - '@tiptap/extensions': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-hard-break@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-heading@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-horizontal-rule@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - - '@tiptap/extension-image@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-italic@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-link@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - linkifyjs: 4.3.2 - - '@tiptap/extension-list-item@3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-list-keymap@3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - - '@tiptap/extension-mention@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@tiptap/suggestion@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - '@tiptap/suggestion': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-ordered-list@3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-paragraph@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-strike@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-task-item@3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-task-list@3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - - '@tiptap/extension-text-align@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-text-style@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-text@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extension-underline@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - - '@tiptap/extensions@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - - '@tiptap/html@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(happy-dom@20.0.2)': - dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - happy-dom: 20.0.2 + prosemirror-changeset: 2.3.1 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.7.1 + prosemirror-dropcursor: 1.8.2 + prosemirror-gapcursor: 1.3.2 + prosemirror-history: 1.4.1 + prosemirror-inputrules: 1.5.0 + prosemirror-keymap: 1.2.3 + prosemirror-markdown: 1.13.2 + prosemirror-menu: 1.2.5 + prosemirror-model: 1.25.3 + prosemirror-schema-basic: 1.2.4 + prosemirror-schema-list: 1.5.1 + prosemirror-state: 1.4.3 + prosemirror-tables: 1.7.1 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0) + prosemirror-transform: 1.10.4 + prosemirror-view: 1.40.0 '@tiptap/pm@3.6.6': dependencies: @@ -10768,63 +10981,46 @@ snapshots: prosemirror-transform: 1.10.4 prosemirror-view: 1.40.0 - '@tiptap/react@3.6.2(@floating-ui/dom@1.7.4)(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@tiptap/react@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - '@types/react': 18.3.11 - '@types/react-dom': 18.3.1 + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/extension-bubble-menu': 2.26.3(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/extension-floating-menu': 2.26.3(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 '@types/use-sync-external-store': 0.0.6 fast-deep-equal: 3.1.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) use-sync-external-store: 1.5.0(react@18.3.1) - optionalDependencies: - '@tiptap/extension-bubble-menu': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - '@tiptap/extension-floating-menu': 3.6.6(@floating-ui/dom@1.7.4)(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - transitivePeerDependencies: - - '@floating-ui/dom' - '@tiptap/starter-kit@3.6.2': + '@tiptap/starter-kit@2.26.1': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/extension-blockquote': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-bold': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-bullet-list': 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) - '@tiptap/extension-code': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-code-block': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - '@tiptap/extension-document': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-dropcursor': 3.6.2(@tiptap/extensions@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) - '@tiptap/extension-gapcursor': 3.6.2(@tiptap/extensions@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) - '@tiptap/extension-hard-break': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-heading': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-horizontal-rule': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - '@tiptap/extension-italic': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-link': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - '@tiptap/extension-list': 3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - '@tiptap/extension-list-item': 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) - '@tiptap/extension-list-keymap': 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) - '@tiptap/extension-ordered-list': 3.6.2(@tiptap/extension-list@3.6.6(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)) - '@tiptap/extension-paragraph': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-strike': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-text': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extension-underline': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)) - '@tiptap/extensions': 3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/extension-blockquote': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-bold': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-bullet-list': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-code': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-code-block': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/extension-document': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-dropcursor': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/extension-gapcursor': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/extension-hard-break': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-heading': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-history': 2.26.1(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/extension-horizontal-rule': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3) + '@tiptap/extension-italic': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-list-item': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-ordered-list': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-paragraph': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-strike': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-text': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/extension-text-style': 2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)) + '@tiptap/pm': 2.26.3 - '@tiptap/suggestion@3.6.2(@tiptap/core@3.6.2(@tiptap/pm@3.6.6))(@tiptap/pm@3.6.6)': + '@tiptap/suggestion@2.26.2(@tiptap/core@2.26.2(@tiptap/pm@2.26.3))(@tiptap/pm@2.26.3)': dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) - '@tiptap/pm': 3.6.6 - - '@tiptap/y-tiptap@3.0.0(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)': - dependencies: - lib0: 0.2.114 - prosemirror-model: 1.25.3 - prosemirror-state: 1.4.3 - prosemirror-view: 1.40.0 - y-protocols: 1.0.6(yjs@13.6.27) - yjs: 13.6.27 + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) + '@tiptap/pm': 2.26.3 '@tokenizer/inflate@0.2.7': dependencies: @@ -11013,10 +11209,6 @@ snapshots: dependencies: '@types/node': 22.12.0 - '@types/node@20.19.15': - dependencies: - undici-types: 6.21.0 - '@types/node@22.12.0': dependencies: undici-types: 6.20.0 @@ -11096,8 +11288,6 @@ snapshots: '@types/uuid@9.0.8': {} - '@types/whatwg-mimetype@3.0.2': {} - '@types/ws@8.18.1': dependencies: '@types/node': 22.12.0 @@ -11135,7 +11325,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.44.0(typescript@5.8.3) '@typescript-eslint/types': 8.44.0 - debug: 4.4.3 + debug: 4.4.1 typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -11575,10 +11765,6 @@ snapshots: async-lock@1.4.1: {} - async-mutex@0.5.0: - dependencies: - tslib: 2.8.1 - async@3.2.6: {} asynckit@0.4.0: {} @@ -11653,6 +11839,8 @@ snapshots: birpc@2.6.1: {} + bluebird@3.7.2: {} + body-parser@1.20.3: dependencies: bytes: 3.1.2 @@ -11730,7 +11918,7 @@ snapshots: camel-case@4.1.2: dependencies: pascal-case: 3.1.2 - tslib: 2.5.3 + tslib: 2.8.1 camelcase-css@2.0.1: {} @@ -11739,7 +11927,7 @@ snapshots: capital-case@1.0.4: dependencies: no-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 upper-case-first: 2.0.2 case-sensitive-paths-webpack-plugin@2.4.0: {} @@ -11781,7 +11969,7 @@ snapshots: path-case: 3.0.4 sentence-case: 3.0.4 snake-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 character-entities@2.0.2: {} @@ -11914,7 +12102,7 @@ snapshots: constant-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 upper-case: 2.0.2 constants-browserify@1.0.0: {} @@ -12091,6 +12279,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.1: + dependencies: + ms: 2.1.3 + debug@4.4.3: dependencies: ms: 2.1.3 @@ -12138,6 +12330,8 @@ snapshots: delayed-stream@1.0.0: {} + denque@1.5.1: {} + denque@2.1.0: {} depd@2.0.0: {} @@ -12232,7 +12426,7 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 dotenv@16.0.3: {} @@ -12305,6 +12499,8 @@ snapshots: entities@4.5.0: {} + entities@5.0.0: {} + entities@6.0.1: {} error-ex@1.3.4: @@ -13073,12 +13269,6 @@ snapshots: gud@1.0.0: {} - happy-dom@20.0.2: - dependencies: - '@types/node': 20.19.15 - '@types/whatwg-mimetype': 3.0.2 - whatwg-mimetype: 3.0.0 - has-bigints@1.1.0: {} has-flag@3.0.0: {} @@ -13110,7 +13300,7 @@ snapshots: header-case@2.0.4: dependencies: capital-case: 1.0.4 - tslib: 2.5.3 + tslib: 2.8.1 helmet@7.2.0: {} @@ -13174,14 +13364,14 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 - debug: 4.4.3 + debug: 4.4.1 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.4.3 + debug: 4.4.1 transitivePeerDependencies: - supports-color @@ -13251,6 +13441,22 @@ snapshots: '@formatjs/icu-messageformat-parser': 2.11.2 tslib: 2.8.1 + ioredis@4.30.1: + dependencies: + '@ioredis/commands': 1.3.0 + cluster-key-slot: 1.1.2 + debug: 4.4.1 + denque: 1.5.1 + lodash.defaults: 4.2.0 + lodash.flatten: 4.4.0 + lodash.isarguments: 3.1.0 + p-map: 2.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + ioredis@5.7.0: dependencies: '@ioredis/commands': 1.3.0 @@ -13612,6 +13818,8 @@ snapshots: lodash.defaults@4.2.0: {} + lodash.flatten@4.4.0: {} + lodash.isarguments@3.1.0: {} lodash.isplainobject@4.0.6: {} @@ -13637,7 +13845,7 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.5.3 + tslib: 2.8.1 lowlight@2.9.0: dependencies: @@ -13869,7 +14077,7 @@ snapshots: micromark@3.2.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.3 + debug: 4.4.1 decode-named-character-reference: 1.2.0 micromark-core-commonmark: 1.1.0 micromark-factory-space: 1.1.0 @@ -14002,7 +14210,7 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.5.3 + tslib: 2.8.1 node-abi@3.75.0: dependencies: @@ -14167,6 +14375,8 @@ snapshots: dependencies: p-limit: 4.0.0 + p-map@2.1.0: {} + p-try@2.2.0: {} package-json-from-dist@1.0.1: {} @@ -14178,7 +14388,7 @@ snapshots: param-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 parent-module@1.0.1: dependencies: @@ -14202,14 +14412,14 @@ snapshots: pascal-case@3.1.2: dependencies: no-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 path-browserify@1.0.1: {} path-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 path-exists@4.0.0: {} @@ -14823,6 +15033,10 @@ snapshots: dependencies: redis-errors: 1.2.0 + redlock@4.2.0: + dependencies: + bluebird: 3.7.2 + reflect-metadata@0.2.2: {} reflect.getprototypeof@1.0.10: @@ -14910,7 +15124,7 @@ snapshots: dependencies: glob: 7.2.3 - rolldown-plugin-dts@0.16.11(rolldown@1.0.0-beta.34)(typescript@5.8.3): + rolldown-plugin-dts@0.16.11(rolldown@1.0.0-beta.38)(typescript@5.8.3): dependencies: '@babel/generator': 7.28.3 '@babel/parser': 7.28.4 @@ -14921,34 +15135,60 @@ snapshots: dts-resolver: 2.1.2 get-tsconfig: 4.10.1 magic-string: 0.30.19 - rolldown: 1.0.0-beta.34 + rolldown: 1.0.0-beta.38 optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: - oxc-resolver - supports-color - rolldown@1.0.0-beta.34: + rolldown@1.0.0-beta.38: dependencies: - '@oxc-project/runtime': 0.82.3 - '@oxc-project/types': 0.82.3 - '@rolldown/pluginutils': 1.0.0-beta.34 + '@oxc-project/types': 0.89.0 + '@rolldown/pluginutils': 1.0.0-beta.38 ansis: 4.1.0 optionalDependencies: - '@rolldown/binding-android-arm64': 1.0.0-beta.34 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.34 - '@rolldown/binding-darwin-x64': 1.0.0-beta.34 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.34 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.34 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.34 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.34 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.34 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.34 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.34 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.34 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.34 - '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.34 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.34 + '@rolldown/binding-android-arm64': 1.0.0-beta.38 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.38 + '@rolldown/binding-darwin-x64': 1.0.0-beta.38 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.38 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.38 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.38 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.38 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.38 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.38 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.38 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.38 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.38 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.38 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.38 + + rollup@4.50.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.50.0 + '@rollup/rollup-android-arm64': 4.50.0 + '@rollup/rollup-darwin-arm64': 4.50.0 + '@rollup/rollup-darwin-x64': 4.50.0 + '@rollup/rollup-freebsd-arm64': 4.50.0 + '@rollup/rollup-freebsd-x64': 4.50.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.50.0 + '@rollup/rollup-linux-arm-musleabihf': 4.50.0 + '@rollup/rollup-linux-arm64-gnu': 4.50.0 + '@rollup/rollup-linux-arm64-musl': 4.50.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.50.0 + '@rollup/rollup-linux-ppc64-gnu': 4.50.0 + '@rollup/rollup-linux-riscv64-gnu': 4.50.0 + '@rollup/rollup-linux-riscv64-musl': 4.50.0 + '@rollup/rollup-linux-s390x-gnu': 4.50.0 + '@rollup/rollup-linux-x64-gnu': 4.50.0 + '@rollup/rollup-linux-x64-musl': 4.50.0 + '@rollup/rollup-openharmony-arm64': 4.50.0 + '@rollup/rollup-win32-arm64-msvc': 4.50.0 + '@rollup/rollup-win32-ia32-msvc': 4.50.0 + '@rollup/rollup-win32-x64-msvc': 4.50.0 + fsevents: 2.3.3 rollup@4.52.4: dependencies: @@ -14977,6 +15217,7 @@ snapshots: '@rollup/rollup-win32-x64-gnu': 4.52.4 '@rollup/rollup-win32-x64-msvc': 4.52.4 fsevents: 2.3.3 + optional: true rope-sequence@1.3.4: {} @@ -15070,7 +15311,7 @@ snapshots: sentence-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 upper-case-first: 2.0.2 serialize-javascript@6.0.2: @@ -15189,7 +15430,7 @@ snapshots: snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.5.3 + tslib: 2.8.1 source-map-js@1.2.1: {} @@ -15495,9 +15736,9 @@ snapshots: dependencies: '@popperjs/core': 2.11.8 - tiptap-markdown@0.9.0(@tiptap/core@3.6.2(@tiptap/pm@3.6.6)): + tiptap-markdown@0.8.10(@tiptap/core@2.26.2(@tiptap/pm@2.26.3)): dependencies: - '@tiptap/core': 3.6.2(@tiptap/pm@3.6.6) + '@tiptap/core': 2.26.2(@tiptap/pm@2.26.3) '@types/markdown-it': 13.0.9 markdown-it: 14.1.0 markdown-it-task-lists: 2.1.1 @@ -15569,8 +15810,8 @@ snapshots: diff: 8.0.2 empathic: 2.0.0 hookable: 5.5.3 - rolldown: 1.0.0-beta.34 - rolldown-plugin-dts: 0.16.11(rolldown@1.0.0-beta.34)(typescript@5.8.3) + rolldown: 1.0.0-beta.38 + rolldown-plugin-dts: 0.16.11(rolldown@1.0.0-beta.38)(typescript@5.8.3) semver: 7.7.2 tinyexec: 1.0.1 tinyglobby: 0.2.15 @@ -15686,8 +15927,6 @@ snapshots: undici-types@6.20.0: {} - undici-types@6.21.0: {} - unicode-properties@1.4.1: dependencies: base64-js: 1.5.1 @@ -15776,11 +16015,11 @@ snapshots: upper-case-first@2.0.2: dependencies: - tslib: 2.5.3 + tslib: 2.8.1 upper-case@2.0.2: dependencies: - tslib: 2.5.3 + tslib: 2.8.1 uri-js@4.4.1: dependencies: @@ -15829,6 +16068,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@11.1.0: {} + uuid@13.0.0: {} uuid@9.0.1: {} @@ -15883,7 +16124,7 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.52.4 + rollup: 4.50.0 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 22.12.0 @@ -15969,8 +16210,6 @@ snapshots: dependencies: iconv-lite: 0.6.3 - whatwg-mimetype@3.0.0: {} - whatwg-mimetype@4.0.0: {} whatwg-url@14.2.0: @@ -16127,4 +16366,9 @@ snapshots: yoga-layout@2.0.1: {} + zeed-dom@0.15.1: + dependencies: + css-what: 6.2.2 + entities: 5.0.0 + zod@3.25.76: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 7ee73f42f..baa842f50 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -29,8 +29,8 @@ catalog: tsdown: 0.15.5 vite: 7.1.11 uuid: 13.0.0 - "@tiptap/core": ^3.5.3 - "@tiptap/html": ^3.5.3 + "@tiptap/core": ^2.22.3 + "@tiptap/html": ^2.22.3 onlyBuiltDependencies: - turbo