diff --git a/package.json b/package.json index cc2b07dfed49..bdf35a180ddc 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@aws-sdk/credential-providers": "^3.363.0", "@blocknote/mantine": "^0.22.0", "@blocknote/react": "^0.22.0", + "@blocknote/server-util": "0.17.1", "@codesandbox/sandpack-react": "^2.13.5", "@dagrejs/dagre": "^1.1.2", "@emotion/react": "^11.11.1", diff --git a/packages/twenty-server/src/database/commands/database-command.module.ts b/packages/twenty-server/src/database/commands/database-command.module.ts index 8422f1e9cfd7..f6f95ce43620 100644 --- a/packages/twenty-server/src/database/commands/database-command.module.ts +++ b/packages/twenty-server/src/database/commands/database-command.module.ts @@ -8,6 +8,7 @@ import { DataSeedDemoWorkspaceModule } from 'src/database/commands/data-seed-dem import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-workspace.command'; import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question'; import { UpgradeTo0_40CommandModule } from 'src/database/commands/upgrade-version/0-40/0-40-upgrade-version.module'; +import { UpgradeTo0_41CommandModule } from 'src/database/commands/upgrade-version/0-41/0-41-upgrade-version.module'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; @@ -49,6 +50,7 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp WorkspaceCacheStorageModule, WorkspaceMetadataVersionModule, UpgradeTo0_40CommandModule, + UpgradeTo0_41CommandModule, FeatureFlagModule, ], providers: [ diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-fix-body-v2-view-field-position.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-fix-body-v2-view-field-position.command.ts new file mode 100644 index 000000000000..7a5ccaf393be --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-fix-body-v2-view-field-position.command.ts @@ -0,0 +1,134 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { In, Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { isCommandLogger } from 'src/database/commands/logger'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; + +@Command({ + name: 'upgrade-0.41:fix-body-v2-view-field-position', + description: 'Make bodyV2 field position to match body field position', +}) +export class FixBodyV2ViewFieldPositionCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise { + this.logger.log('Running command to fix bodyV2 field position'); + + if (isCommandLogger(this.logger)) { + this.logger.setVerbose(options.verbose ?? false); + } + + let workspaceIterator = 1; + + for (const workspaceId of workspaceIds) { + this.logger.log( + `Running command for workspace ${workspaceId} ${workspaceIterator}/${workspaceIds.length}`, + ); + + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'view', + ); + + const viewFieldRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'viewField', + false, + ); + + const taskAndNoteObjectMetadata = + await this.objectMetadataRepository.find({ + where: { + workspaceId, + nameSingular: In(['note', 'task']), + }, + relations: ['fields'], + }); + + const taskAndNoteViews = await viewRepository.find({ + where: { + objectMetadataId: In( + taskAndNoteObjectMetadata.map((object) => object.id), + ), + }, + }); + + for (const view of taskAndNoteViews) { + const viewFields = await viewFieldRepository.find({ + where: { + viewId: view.id, + }, + }); + + const fields = taskAndNoteObjectMetadata.flatMap( + (objectMetadata) => objectMetadata.fields, + ); + + const fieldNameByMetadataId: Record = fields.reduce( + (fieldNameByMetadataId, fieldMetadata) => ({ + ...fieldNameByMetadataId, + [fieldMetadata.id]: fieldMetadata.name, + }), + {}, + ); + + const bodyField = viewFields.find( + (field) => fieldNameByMetadataId[field.fieldMetadataId] === 'body', + ); + const bodyV2Field = viewFields.find( + (field) => fieldNameByMetadataId[field.fieldMetadataId] === 'bodyV2', + ); + + if (bodyField && bodyV2Field) { + await viewFieldRepository.update( + { id: bodyV2Field.id }, + { position: bodyField.position, isVisible: bodyField.isVisible }, + ); + chalk.green( + `Updated bodyV2 field position for view ${view.id} to ${bodyField.position}`, + ); + } else { + chalk.red(`No body or bodyV2 field found for view ${view.id}`); + } + + await this.workspaceMetadataVersionService.incrementMetadataVersion( + workspaceId, + ); + + workspaceIterator++; + this.logger.log( + chalk.green(`Command completed for workspace ${workspaceId}`), + ); + } + } + + this.logger.log(chalk.green('Command completed!')); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-migrate-rich-text-field.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-migrate-rich-text-field.command.ts new file mode 100644 index 000000000000..d58ab1f85cf3 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-migrate-rich-text-field.command.ts @@ -0,0 +1,200 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { ServerBlockNoteEditor } from '@blocknote/server-util'; +import chalk from 'chalk'; +import { Command } from 'nest-commander'; +import { FieldMetadataType } from 'twenty-shared'; +import { Repository } from 'typeorm'; + +import { + ActiveWorkspacesCommandOptions, + ActiveWorkspacesCommandRunner, +} from 'src/database/commands/active-workspaces.command'; +import { isCommandLogger } from 'src/database/commands/logger'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; +import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; +import { + WorkspaceMigrationColumnActionType, + WorkspaceMigrationColumnCreate, + WorkspaceMigrationTableAction, + WorkspaceMigrationTableActionType, +} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; +import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; +import { computeTableName } from 'src/engine/utils/compute-table-name.util'; +import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; +import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; +import { isDefined } from 'src/utils/is-defined'; + +@Command({ + name: 'upgrade-0.41:migrate-rich-text-field', + description: 'Migrate RICH_TEXT fields to new composite structure', +}) +export class MigrateRichTextFieldCommand extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository, + private readonly workspaceDataSourceService: WorkspaceDataSourceService, + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + private readonly workspaceMigrationService: WorkspaceMigrationService, + private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService, + private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + _passedParam: string[], + options: ActiveWorkspacesCommandOptions, + workspaceIds: string[], + ): Promise { + this.logger.log( + 'Running command to migrate RICH_TEXT fields to new composite structure', + ); + + if (isCommandLogger(this.logger)) { + this.logger.setVerbose(options.verbose ?? false); + } + + let workspaceIterator = 1; + + for (const workspaceId of workspaceIds) { + this.logger.log( + `Running command for workspace ${workspaceId} ${workspaceIterator}/${workspaceIds.length}`, + ); + + const richTextFields = await this.fieldMetadataRepository.find({ + where: { + workspaceId, + type: FieldMetadataType.RICH_TEXT, + }, + }); + + if (!richTextFields.length) { + this.logger.log('No RICH_TEXT fields found in this workspace'); + workspaceIterator++; + continue; + } + + this.logger.log(`Found ${richTextFields.length} RICH_TEXT fields`); + + for (const richTextField of richTextFields) { + const newRichTextField: Partial = { + ...richTextField, + name: `${richTextField.name}V2`, + id: undefined, + type: FieldMetadataType.RICH_TEXT_V2, + defaultValue: null, + }; + + await this.fieldMetadataRepository.insert(newRichTextField); + + const objectMetadata = await this.objectMetadataRepository.findOne({ + where: { id: richTextField.objectMetadataId }, + }); + + if (!isDefined(objectMetadata)) { + this.logger.log( + `Object metadata not found for rich text field ${richTextField.name} in workspace ${workspaceId}`, + ); + continue; + } + + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName( + `migrate-rich-text-field-${objectMetadata.nameSingular}-${richTextField.name}`, + ), + workspaceId, + [ + { + name: computeObjectTargetTable(objectMetadata), + action: WorkspaceMigrationTableActionType.ALTER, + columns: [ + { + action: WorkspaceMigrationColumnActionType.CREATE, + columnName: `${richTextField.name}V2Blocknote`, + columnType: 'text', + isNullable: true, + defaultValue: null, + } satisfies WorkspaceMigrationColumnCreate, + { + action: WorkspaceMigrationColumnActionType.CREATE, + columnName: `${richTextField.name}V2Markdown`, + columnType: 'text', + isNullable: true, + defaultValue: null, + } satisfies WorkspaceMigrationColumnCreate, + ], + } satisfies WorkspaceMigrationTableAction, + ], + ); + } + + await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( + workspaceId, + ); + + await this.workspaceMetadataVersionService.incrementMetadataVersion( + workspaceId, + ); + + const serverBlockNoteEditor = ServerBlockNoteEditor.create(); + + for (const richTextField of richTextFields) { + const objectMetadata = await this.objectMetadataRepository.findOne({ + where: { id: richTextField.objectMetadataId }, + }); + + if (!isDefined(objectMetadata)) { + this.logger.log( + `Object metadata not found for rich text field ${richTextField.name} in workspace ${workspaceId}`, + ); + continue; + } + + const schemaName = + this.workspaceDataSourceService.getSchemaName(workspaceId); + + const workspaceDataSource = + await this.twentyORMGlobalManager.getDataSourceForWorkspace( + workspaceId, + ); + + const rows = await workspaceDataSource.query( + `SELECT id, "${richTextField.name}" FROM "${schemaName}"."${computeTableName(objectMetadata.nameSingular, objectMetadata.isCustom)}"`, + ); + + this.logger.log(`Generating markdown for ${rows.length} records`); + + for (const row of rows) { + const blocknoteFieldValue = row[richTextField.name]; + const markdownFieldValue = blocknoteFieldValue + ? await serverBlockNoteEditor.blocksToMarkdownLossy( + JSON.parse(blocknoteFieldValue), + ) + : null; + + await workspaceDataSource.query( + `UPDATE "${schemaName}"."${computeTableName(objectMetadata.nameSingular, objectMetadata.isCustom)}" SET "${richTextField.name}V2Blocknote" = $1, "${richTextField.name}V2Markdown" = $2 WHERE id = $3`, + [blocknoteFieldValue, markdownFieldValue, row.id], + ); + } + } + + workspaceIterator++; + this.logger.log( + chalk.green(`Command completed for workspace ${workspaceId}`), + ); + } + + this.logger.log(chalk.green('Command completed!')); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-upgrade-version.command.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-upgrade-version.command.ts new file mode 100644 index 000000000000..0b669ed94f60 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-upgrade-version.command.ts @@ -0,0 +1,45 @@ +import { InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { Repository } from 'typeorm'; + +import { ActiveWorkspacesCommandRunner } from 'src/database/commands/active-workspaces.command'; +import { BaseCommandOptions } from 'src/database/commands/base.command'; +import { FixBodyV2ViewFieldPositionCommand } from 'src/database/commands/upgrade-version/0-41/0-41-fix-body-v2-view-field-position.command'; +import { MigrateRichTextFieldCommand } from 'src/database/commands/upgrade-version/0-41/0-41-migrate-rich-text-field.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; + +@Command({ + name: 'upgrade-0.41', + description: 'Upgrade to 0.41', +}) +export class UpgradeTo0_41Command extends ActiveWorkspacesCommandRunner { + constructor( + @InjectRepository(Workspace, 'core') + protected readonly workspaceRepository: Repository, + private readonly migrateRichTextFieldCommand: MigrateRichTextFieldCommand, + private readonly fixBodyV2ViewFieldPositionCommand: FixBodyV2ViewFieldPositionCommand, + ) { + super(workspaceRepository); + } + + async executeActiveWorkspacesCommand( + passedParam: string[], + options: BaseCommandOptions, + workspaceIds: string[], + ): Promise { + this.logger.log('Running command to upgrade to 0.41'); + + await this.migrateRichTextFieldCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + + await this.fixBodyV2ViewFieldPositionCommand.executeActiveWorkspacesCommand( + passedParam, + options, + workspaceIds, + ); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-upgrade-version.module.ts b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-upgrade-version.module.ts new file mode 100644 index 000000000000..41b0f6165b36 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version/0-41/0-41-upgrade-version.module.ts @@ -0,0 +1,33 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { FixBodyV2ViewFieldPositionCommand } from 'src/database/commands/upgrade-version/0-41/0-41-fix-body-v2-view-field-position.command'; + +import { MigrateRichTextFieldCommand } from 'src/database/commands/upgrade-version/0-41/0-41-migrate-rich-text-field.command'; +import { UpgradeTo0_41Command } from 'src/database/commands/upgrade-version/0-41/0-41-upgrade-version.command'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; +import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module'; +import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; +import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([Workspace], 'core'), + TypeOrmModule.forFeature( + [ObjectMetadataEntity, FieldMetadataEntity], + 'metadata', + ), + WorkspaceMigrationRunnerModule, + WorkspaceMigrationModule, + WorkspaceMetadataVersionModule, + WorkspaceDataSourceModule, + ], + providers: [ + UpgradeTo0_41Command, + MigrateRichTextFieldCommand, + FixBodyV2ViewFieldPositionCommand, + ], +}) +export class UpgradeTo0_41CommandModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts index f7f943b825ca..aed105c3c015 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/index.ts @@ -9,6 +9,7 @@ import { emailsCompositeType } from 'src/engine/metadata-modules/field-metadata/ import { fullNameCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/full-name.composite-type'; import { linksCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/links.composite-type'; import { phonesCompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/phones.composite-type'; +import { richTextV2CompositeType } from 'src/engine/metadata-modules/field-metadata/composite-types/rich-text-v2.composite-type'; export const compositeTypeDefinitions = new Map< FieldMetadataType, @@ -21,4 +22,5 @@ export const compositeTypeDefinitions = new Map< [FieldMetadataType.ACTOR, actorCompositeType], [FieldMetadataType.EMAILS, emailsCompositeType], [FieldMetadataType.PHONES, phonesCompositeType], + [FieldMetadataType.RICH_TEXT_V2, richTextV2CompositeType], ]); diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/rich-text-v2.composite-type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/rich-text-v2.composite-type.ts new file mode 100644 index 000000000000..0d7a98cedaab --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/composite-types/rich-text-v2.composite-type.ts @@ -0,0 +1,29 @@ +import { FieldMetadataType } from 'twenty-shared'; +import { z } from 'zod'; + +import { CompositeType } from 'src/engine/metadata-modules/field-metadata/interfaces/composite-type.interface'; + +export const richTextV2CompositeType: CompositeType = { + type: FieldMetadataType.RICH_TEXT_V2, + properties: [ + { + name: 'blocknote', + type: FieldMetadataType.TEXT, + hidden: false, + isRequired: false, + }, + { + name: 'markdown', + type: FieldMetadataType.TEXT, + hidden: false, + isRequired: false, + }, + ], +}; + +export const richTextV2ValueSchema = z.object({ + blocknote: z.string().nullable(), + markdown: z.string().nullable(), +}); + +export type RichTextV2Metadata = z.infer; diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts index 0fb1c6968ebf..172751bb0fd4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/utils/is-composite-field-metadata-type.util.ts @@ -9,7 +9,8 @@ export const isCompositeFieldMetadataType = ( | FieldMetadataType.LINKS | FieldMetadataType.ACTOR | FieldMetadataType.EMAILS - | FieldMetadataType.PHONES => { + | FieldMetadataType.PHONES + | FieldMetadataType.RICH_TEXT_V2 => { return [ FieldMetadataType.CURRENCY, FieldMetadataType.FULL_NAME, @@ -18,5 +19,6 @@ export const isCompositeFieldMetadataType = ( FieldMetadataType.ACTOR, FieldMetadataType.EMAILS, FieldMetadataType.PHONES, + FieldMetadataType.RICH_TEXT_V2, ].includes(type); }; diff --git a/packages/twenty-shared/src/types/FieldMetadataType.ts b/packages/twenty-shared/src/types/FieldMetadataType.ts index 83589ce928bb..c8cddee59082 100644 --- a/packages/twenty-shared/src/types/FieldMetadataType.ts +++ b/packages/twenty-shared/src/types/FieldMetadataType.ts @@ -19,6 +19,7 @@ export enum FieldMetadataType { ADDRESS = 'ADDRESS', RAW_JSON = 'RAW_JSON', RICH_TEXT = 'RICH_TEXT', + RICH_TEXT_V2 = 'RICH_TEXT_V2', ACTOR = 'ACTOR', ARRAY = 'ARRAY', TS_VECTOR = 'TS_VECTOR', diff --git a/yarn.lock b/yarn.lock index bff71569429b..62e3a69a473b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3415,6 +3415,55 @@ __metadata: languageName: node linkType: hard +"@blocknote/core@npm:^0.17.1": + version: 0.17.1 + resolution: "@blocknote/core@npm:0.17.1" + dependencies: + "@emoji-mart/data": "npm:^1.2.1" + "@tiptap/core": "npm:^2.7.1" + "@tiptap/extension-bold": "npm:^2.7.1" + "@tiptap/extension-code": "npm:^2.7.1" + "@tiptap/extension-collaboration": "npm:^2.7.1" + "@tiptap/extension-collaboration-cursor": "npm:^2.7.1" + "@tiptap/extension-dropcursor": "npm:^2.7.1" + "@tiptap/extension-gapcursor": "npm:^2.7.1" + "@tiptap/extension-hard-break": "npm:^2.7.1" + "@tiptap/extension-history": "npm:^2.7.1" + "@tiptap/extension-horizontal-rule": "npm:^2.7.1" + "@tiptap/extension-italic": "npm:^2.7.1" + "@tiptap/extension-link": "npm:^2.7.1" + "@tiptap/extension-paragraph": "npm:^2.7.1" + "@tiptap/extension-strike": "npm:^2.7.1" + "@tiptap/extension-table-cell": "npm:^2.7.1" + "@tiptap/extension-table-header": "npm:^2.7.1" + "@tiptap/extension-table-row": "npm:^2.7.1" + "@tiptap/extension-text": "npm:^2.7.1" + "@tiptap/extension-underline": "npm:^2.7.1" + "@tiptap/pm": "npm:^2.7.1" + emoji-mart: "npm:^5.6.0" + hast-util-from-dom: "npm:^4.2.0" + prosemirror-model: "npm:^1.21.0" + prosemirror-state: "npm:^1.4.3" + prosemirror-tables: "npm:^1.3.7" + prosemirror-transform: "npm:^1.9.0" + prosemirror-view: "npm:^1.33.7" + rehype-format: "npm:^5.0.0" + rehype-parse: "npm:^8.0.4" + rehype-remark: "npm:^9.1.2" + rehype-stringify: "npm:^9.0.3" + remark-gfm: "npm:^3.0.1" + remark-parse: "npm:^10.0.1" + remark-rehype: "npm:^10.1.0" + remark-stringify: "npm:^10.0.2" + unified: "npm:^10.1.2" + uuid: "npm:^8.3.2" + y-prosemirror: "npm:1.2.12" + y-protocols: "npm:^1.0.6" + yjs: "npm:^13.6.15" + checksum: 10c0/0acd1a099832d8e271983924f19e59aa056ead278a8bac8ab7a64d6c7d40a787a27143bdee3d6b6f3dfa26c7723207d98d7124ffef8ff9c4cfdf3034140716ab + languageName: node + linkType: hard + "@blocknote/core@npm:^0.22.0": version: 0.22.0 resolution: "@blocknote/core@npm:0.22.0" @@ -3483,6 +3532,25 @@ __metadata: languageName: node linkType: hard +"@blocknote/react@npm:^0.17.1": + version: 0.17.1 + resolution: "@blocknote/react@npm:0.17.1" + dependencies: + "@blocknote/core": "npm:^0.17.1" + "@floating-ui/react": "npm:^0.26.4" + "@tiptap/core": "npm:^2.7.1" + "@tiptap/react": "npm:^2.7.1" + lodash.merge: "npm:^4.6.2" + react: "npm:^18" + react-dom: "npm:^18" + react-icons: "npm:^5.2.1" + peerDependencies: + react: ^18 + react-dom: ^18 + checksum: 10c0/4914dce225f60905b3dfe59805d7cf1f0c0c6d87295a09204333b913f6449cc90c2947baeb65c1f06106beaea8b50ac5c2785782cb2528f7e913b2877427c3e4 + languageName: node + linkType: hard + "@blocknote/react@npm:^0.22.0": version: 0.22.0 resolution: "@blocknote/react@npm:0.22.0" @@ -3500,6 +3568,27 @@ __metadata: languageName: node linkType: hard +"@blocknote/server-util@npm:0.17.1": + version: 0.17.1 + resolution: "@blocknote/server-util@npm:0.17.1" + dependencies: + "@blocknote/core": "npm:^0.17.1" + "@blocknote/react": "npm:^0.17.1" + "@tiptap/core": "npm:^2.7.1" + "@tiptap/pm": "npm:^2.7.1" + jsdom: "npm:^21.1.0" + react: "npm:^18" + react-dom: "npm:^18" + y-prosemirror: "npm:1.2.12" + y-protocols: "npm:^1.0.6" + yjs: "npm:^13.6.15" + peerDependencies: + react: ^18 + react-dom: ^18 + checksum: 10c0/7d400dbf19562f8827bc524f87d673d711fba95a50fb299e0eb638f01c2dc87fd840a132b33dae60c0944637208f18a632f72f7664cb03b8ce81f5be7f8e59f0 + languageName: node + linkType: hard + "@blocknote/xl-docx-exporter@npm:^0.22.0": version: 0.22.0 resolution: "@blocknote/xl-docx-exporter@npm:0.22.0" @@ -15631,6 +15720,16 @@ __metadata: languageName: node linkType: hard +"@tiptap/extension-dropcursor@npm:^2.7.1": + version: 2.11.2 + resolution: "@tiptap/extension-dropcursor@npm:2.11.2" + peerDependencies: + "@tiptap/core": ^2.7.0 + "@tiptap/pm": ^2.7.0 + checksum: 10c0/3f01d164f9586ef571857a155f22bb1a2f3478240a4755aad61b6afd7f2a13a154d0302910f6ea95538bdd3588a5eec0e6fd080ba4e02009eaa40046f29789f9 + languageName: node + linkType: hard + "@tiptap/extension-floating-menu@npm:^2.10.4": version: 2.10.4 resolution: "@tiptap/extension-floating-menu@npm:2.10.4" @@ -32877,6 +32976,45 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^21.1.0": + version: 21.1.2 + resolution: "jsdom@npm:21.1.2" + dependencies: + abab: "npm:^2.0.6" + acorn: "npm:^8.8.2" + acorn-globals: "npm:^7.0.0" + cssstyle: "npm:^3.0.0" + data-urls: "npm:^4.0.0" + decimal.js: "npm:^10.4.3" + domexception: "npm:^4.0.0" + escodegen: "npm:^2.0.0" + form-data: "npm:^4.0.0" + html-encoding-sniffer: "npm:^3.0.0" + http-proxy-agent: "npm:^5.0.0" + https-proxy-agent: "npm:^5.0.1" + is-potential-custom-element-name: "npm:^1.0.1" + nwsapi: "npm:^2.2.4" + parse5: "npm:^7.1.2" + rrweb-cssom: "npm:^0.6.0" + saxes: "npm:^6.0.0" + symbol-tree: "npm:^3.2.4" + tough-cookie: "npm:^4.1.2" + w3c-xmlserializer: "npm:^4.0.0" + webidl-conversions: "npm:^7.0.0" + whatwg-encoding: "npm:^2.0.0" + whatwg-mimetype: "npm:^3.0.0" + whatwg-url: "npm:^12.0.1" + ws: "npm:^8.13.0" + xml-name-validator: "npm:^4.0.0" + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 10c0/905012680891fa0c92b8c18acfa35fc0b3e4b15f778ee3494aec1aca3274875160d2be35917d666b8eacd0b3121f483bd95fbe35e14790a004b805b1cf01818a + languageName: node + linkType: hard + "jsdom@npm:~22.1.0": version: 22.1.0 resolution: "jsdom@npm:22.1.0" @@ -40060,7 +40198,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-tables@npm:^1.6.1": +"prosemirror-tables@npm:^1.3.7, prosemirror-tables@npm:^1.6.1": version: 1.6.2 resolution: "prosemirror-tables@npm:1.6.2" dependencies: @@ -40096,7 +40234,7 @@ __metadata: languageName: node linkType: hard -"prosemirror-transform@npm:^1.10.2": +"prosemirror-transform@npm:^1.10.2, prosemirror-transform@npm:^1.9.0": version: 1.10.2 resolution: "prosemirror-transform@npm:1.10.2" dependencies: @@ -40581,7 +40719,7 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^18.2.0": +"react-dom@npm:^18, react-dom@npm:^18.2.0": version: 18.3.1 resolution: "react-dom@npm:18.3.1" dependencies: @@ -45737,6 +45875,7 @@ __metadata: "@babel/preset-typescript": "npm:^7.24.6" "@blocknote/mantine": "npm:^0.22.0" "@blocknote/react": "npm:^0.22.0" + "@blocknote/server-util": "npm:0.17.1" "@codesandbox/sandpack-react": "npm:^2.13.5" "@crxjs/vite-plugin": "npm:^1.0.14" "@dagrejs/dagre": "npm:^1.1.2" @@ -48718,6 +48857,21 @@ __metadata: languageName: node linkType: hard +"y-prosemirror@npm:1.2.12": + version: 1.2.12 + resolution: "y-prosemirror@npm:1.2.12" + dependencies: + lib0: "npm:^0.2.42" + peerDependencies: + prosemirror-model: ^1.7.1 + prosemirror-state: ^1.2.3 + prosemirror-view: ^1.9.10 + y-protocols: ^1.0.1 + yjs: ^13.5.38 + checksum: 10c0/c460aa9104c71806112a17b52449221343095c774bc929a3bcfaa6d752ce9af1a5a8359c974625c70de8bf48e10b2aa8702f12ca2027f85c6097d1621969beeb + languageName: node + linkType: hard + "y-prosemirror@npm:1.2.13": version: 1.2.13 resolution: "y-prosemirror@npm:1.2.13"