mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-30 00:29:46 +08:00
feat(editor): schema extension (#10447)
1. **Major Architectural Change: Schema Management**
- Moved from `workspace.schema` to `store.schema` throughout the codebase
- Removed schema property from Workspace and Doc interfaces
- Added `BlockSchemaExtension` pattern across multiple block types
2. **Block Schema Extensions Added**
- Added new `BlockSchemaExtension` to numerous block types including:
- DataView, Surface, Attachment, Bookmark, Code
- Database, Divider, EdgelessText, Embed blocks (Figma, Github, HTML, etc.)
- Frame, Image, Latex, List, Note, Paragraph
- Root, Surface Reference, Table blocks
3. **Import/Export System Updates**
- Updated import functions to accept `schema` parameter:
- `importHTMLToDoc`
- `importHTMLZip`
- `importMarkdownToDoc`
- `importMarkdownZip`
- `importNotionZip`
- Modified export functions to use new schema pattern
4. **Test Infrastructure Updates**
- Updated test files to use new schema extensions
- Modified test document creation to include schema extensions
- Removed direct schema registration in favor of extensions
5. **Service Layer Changes**
- Updated various services to use `getAFFiNEWorkspaceSchema()`
- Modified transformer initialization to use document schema
- Updated collection initialization patterns
6. **Version Management**
- Removed version-related properties and methods from:
- `WorkspaceMetaImpl`
- `TestMeta`
- `DocImpl`
- Removed `blockVersions` and `workspaceVersion/pageVersion`
7. **Store and Extension Updates**
- Added new store extensions and adapters
- Updated store initialization patterns
- Added new schema-related functionality in store extension
This PR represents a significant architectural shift in how schemas are managed, moving from a workspace-centric to a store-centric approach, while introducing a more extensible block schema system through `BlockSchemaExtension`. The changes touch multiple layers of the application including core functionality, services, testing infrastructure, and import/export capabilities.
This commit is contained in:
@@ -3,7 +3,11 @@ import type {
|
||||
GfxElementGeometry,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { GfxCompatible } from '@blocksuite/block-std/gfx';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import type { EmbedCardStyle } from '../../utils/index.js';
|
||||
import { AttachmentBlockTransformer } from './attachment-transformer.js';
|
||||
@@ -86,6 +90,10 @@ export const AttachmentBlockSchema = defineBlockSchema({
|
||||
toModel: () => new AttachmentBlockModel(),
|
||||
});
|
||||
|
||||
export const AttachmentBlockSchemaExtension = BlockSchemaExtension(
|
||||
AttachmentBlockSchema
|
||||
);
|
||||
|
||||
export class AttachmentBlockModel
|
||||
extends GfxCompatible<AttachmentBlockProps>(BlockModel)
|
||||
implements GfxElementGeometry {}
|
||||
|
||||
@@ -3,7 +3,11 @@ import type {
|
||||
GfxElementGeometry,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { GfxCompatible } from '@blocksuite/block-std/gfx';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import type { EmbedCardStyle, LinkPreviewData } from '../../utils/index.js';
|
||||
|
||||
@@ -54,6 +58,9 @@ export const BookmarkBlockSchema = defineBlockSchema({
|
||||
toModel: () => new BookmarkBlockModel(),
|
||||
});
|
||||
|
||||
export const BookmarkBlockSchemaExtension =
|
||||
BlockSchemaExtension(BookmarkBlockSchema);
|
||||
|
||||
export class BookmarkBlockModel
|
||||
extends GfxCompatible<BookmarkBlockProps>(BlockModel)
|
||||
implements GfxElementGeometry {}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
type Text,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
interface CodeBlockProps {
|
||||
text: Text;
|
||||
@@ -30,6 +35,8 @@ export const CodeBlockSchema = defineBlockSchema({
|
||||
toModel: () => new CodeBlockModel(),
|
||||
});
|
||||
|
||||
export const CodeBlockSchemaExtension = BlockSchemaExtension(CodeBlockSchema);
|
||||
|
||||
export class CodeBlockModel extends BlockModel<CodeBlockProps> {
|
||||
override text!: Text;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { Text } from '@blocksuite/store';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import type { Column, SerializedCells, ViewBasicDataType } from './types.js';
|
||||
|
||||
@@ -28,3 +32,6 @@ export const DatabaseBlockSchema = defineBlockSchema({
|
||||
},
|
||||
toModel: () => new DatabaseBlockModel(),
|
||||
});
|
||||
|
||||
export const DatabaseBlockSchemaExtension =
|
||||
BlockSchemaExtension(DatabaseBlockSchema);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export const DividerBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:divider',
|
||||
@@ -15,3 +19,6 @@ type Props = {
|
||||
};
|
||||
|
||||
export class DividerBlockModel extends BlockModel<Props> {}
|
||||
|
||||
export const DividerBlockSchemaExtension =
|
||||
BlockSchemaExtension(DividerBlockSchema);
|
||||
|
||||
@@ -3,7 +3,11 @@ import type {
|
||||
GfxElementGeometry,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { GfxCompatible } from '@blocksuite/block-std/gfx';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
@@ -76,6 +80,10 @@ export const EdgelessTextBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const EdgelessTextBlockSchemaExtension = BlockSchemaExtension(
|
||||
EdgelessTextBlockSchema
|
||||
);
|
||||
|
||||
export class EdgelessTextBlockModel
|
||||
extends GfxCompatible<EdgelessTextProps>(BlockModel)
|
||||
implements GfxElementGeometry {}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedFigmaBlockProps,
|
||||
@@ -20,3 +22,7 @@ export const EmbedFigmaBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedFigmaModel(),
|
||||
props: (): EmbedFigmaBlockProps => defaultEmbedFigmaProps,
|
||||
});
|
||||
|
||||
export const EmbedFigmaBlockSchemaExtension = BlockSchemaExtension(
|
||||
EmbedFigmaBlockSchema
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedGithubBlockProps,
|
||||
@@ -29,3 +31,7 @@ export const EmbedGithubBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedGithubModel(),
|
||||
props: (): EmbedGithubBlockProps => defaultEmbedGithubProps,
|
||||
});
|
||||
|
||||
export const EmbedGithubBlockSchemaExtension = BlockSchemaExtension(
|
||||
EmbedGithubBlockSchema
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedHtmlBlockProps,
|
||||
@@ -18,3 +20,6 @@ export const EmbedHtmlBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedHtmlModel(),
|
||||
props: (): EmbedHtmlBlockProps => defaultEmbedHtmlProps,
|
||||
});
|
||||
|
||||
export const EmbedHtmlBlockSchemaExtension =
|
||||
BlockSchemaExtension(EmbedHtmlBlockSchema);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedLinkedDocBlockProps,
|
||||
@@ -20,3 +22,7 @@ export const EmbedLinkedDocBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedLinkedDocModel(),
|
||||
props: (): EmbedLinkedDocBlockProps => defaultEmbedLinkedDocBlockProps,
|
||||
});
|
||||
|
||||
export const EmbedLinkedDocBlockSchemaExtension = BlockSchemaExtension(
|
||||
EmbedLinkedDocBlockSchema
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedLoomBlockProps,
|
||||
@@ -22,3 +24,6 @@ export const EmbedLoomBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedLoomModel(),
|
||||
props: (): EmbedLoomBlockProps => defaultEmbedLoomProps,
|
||||
});
|
||||
|
||||
export const EmbedLoomBlockSchemaExtension =
|
||||
BlockSchemaExtension(EmbedLoomBlockSchema);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedSyncedDocBlockProps,
|
||||
@@ -21,3 +23,7 @@ export const EmbedSyncedDocBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedSyncedDocModel(),
|
||||
props: (): EmbedSyncedDocBlockProps => defaultEmbedSyncedDocBlockProps,
|
||||
});
|
||||
|
||||
export const EmbedSyncedDocBlockSchemaExtension = BlockSchemaExtension(
|
||||
EmbedSyncedDocBlockSchema
|
||||
);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BlockSchemaExtension } from '@blocksuite/store';
|
||||
|
||||
import { createEmbedBlockSchema } from '../../../utils/index.js';
|
||||
import {
|
||||
type EmbedYoutubeBlockProps,
|
||||
@@ -25,3 +27,7 @@ export const EmbedYoutubeBlockSchema = createEmbedBlockSchema({
|
||||
toModel: () => new EmbedYoutubeModel(),
|
||||
props: (): EmbedYoutubeBlockProps => defaultEmbedYoutubeProps,
|
||||
});
|
||||
|
||||
export const EmbedYoutubeBlockSchemaExtension = BlockSchemaExtension(
|
||||
EmbedYoutubeBlockSchema
|
||||
);
|
||||
|
||||
@@ -15,7 +15,12 @@ import {
|
||||
hasDescendantElementImpl,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { Bound } from '@blocksuite/global/utils';
|
||||
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
type Text,
|
||||
} from '@blocksuite/store';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { type Color, ColorSchema, DefaultTheme } from '../../themes/index.js';
|
||||
@@ -57,6 +62,8 @@ export const FrameBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const FrameBlockSchemaExtension = BlockSchemaExtension(FrameBlockSchema);
|
||||
|
||||
export class FrameBlockModel
|
||||
extends GfxCompatible<FrameBlockProps>(BlockModel)
|
||||
implements GfxElementGeometry, GfxGroupCompatibleInterface
|
||||
|
||||
@@ -3,7 +3,11 @@ import type {
|
||||
GfxElementGeometry,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { GfxCompatible } from '@blocksuite/block-std/gfx';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import { ImageBlockTransformer } from './image-transformer.js';
|
||||
|
||||
@@ -40,6 +44,8 @@ export const ImageBlockSchema = defineBlockSchema({
|
||||
toModel: () => new ImageBlockModel(),
|
||||
});
|
||||
|
||||
export const ImageBlockSchemaExtension = BlockSchemaExtension(ImageBlockSchema);
|
||||
|
||||
export class ImageBlockModel
|
||||
extends GfxCompatible<ImageBlockProps>(BlockModel)
|
||||
implements GfxElementGeometry {}
|
||||
|
||||
@@ -3,7 +3,11 @@ import {
|
||||
GfxCompatible,
|
||||
type GfxElementGeometry,
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export type LatexProps = {
|
||||
latex: string;
|
||||
@@ -34,6 +38,8 @@ export const LatexBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const LatexBlockSchemaExtension = BlockSchemaExtension(LatexBlockSchema);
|
||||
|
||||
export class LatexBlockModel
|
||||
extends GfxCompatible<LatexProps>(BlockModel)
|
||||
implements GfxElementGeometry {}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { Text } from '@blocksuite/store';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
// `toggle` type has been deprecated, do not use it
|
||||
export type ListType = 'bulleted' | 'numbered' | 'todo' | 'toggle';
|
||||
@@ -38,6 +42,8 @@ export const ListBlockSchema = defineBlockSchema({
|
||||
toModel: () => new ListBlockModel(),
|
||||
});
|
||||
|
||||
export const ListBlockSchemaExtension = BlockSchemaExtension(ListBlockSchema);
|
||||
|
||||
export class ListBlockModel extends BlockModel<ListProps> {
|
||||
override text!: Text;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@ import type {
|
||||
} from '@blocksuite/block-std/gfx';
|
||||
import { GfxCompatible } from '@blocksuite/block-std/gfx';
|
||||
import { Bound } from '@blocksuite/global/utils';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
@@ -21,6 +25,7 @@ import {
|
||||
StrokeStyleSchema,
|
||||
} from '../../consts/note';
|
||||
import { type Color, ColorSchema, DefaultTheme } from '../../themes';
|
||||
import { TableModelFlavour } from '../table';
|
||||
|
||||
export const NoteZodSchema = z
|
||||
.object({
|
||||
@@ -47,7 +52,6 @@ export const NoteZodSchema = z
|
||||
},
|
||||
},
|
||||
});
|
||||
import { TableModelFlavour } from '../table';
|
||||
|
||||
export const NoteBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:note',
|
||||
@@ -92,6 +96,7 @@ export const NoteBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const NoteBlockSchemaExtension = BlockSchemaExtension(NoteBlockSchema);
|
||||
export type NoteProps = {
|
||||
background: Color;
|
||||
displayMode: NoteDisplayMode;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
type Text,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export type ParagraphType =
|
||||
| 'text'
|
||||
@@ -37,6 +42,9 @@ export const ParagraphBlockSchema = defineBlockSchema({
|
||||
toModel: () => new ParagraphBlockModel(),
|
||||
});
|
||||
|
||||
export const ParagraphBlockSchemaExtension =
|
||||
BlockSchemaExtension(ParagraphBlockSchema);
|
||||
|
||||
export class ParagraphBlockModel extends BlockModel<ParagraphProps> {
|
||||
override text!: Text;
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import type { Text } from '@blocksuite/store';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export type RootBlockProps = {
|
||||
title: Text;
|
||||
@@ -51,3 +55,5 @@ export const RootBlockSchema = defineBlockSchema({
|
||||
},
|
||||
toModel: () => new RootBlockModel(),
|
||||
});
|
||||
|
||||
export const RootBlockSchemaExtension = BlockSchemaExtension(RootBlockSchema);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export type SurfaceRefProps = {
|
||||
reference: string;
|
||||
@@ -21,4 +25,8 @@ export const SurfaceRefBlockSchema = defineBlockSchema({
|
||||
toModel: () => new SurfaceRefBlockModel(),
|
||||
});
|
||||
|
||||
export const SurfaceRefBlockSchemaExtension = BlockSchemaExtension(
|
||||
SurfaceRefBlockSchema
|
||||
);
|
||||
|
||||
export class SurfaceRefBlockModel extends BlockModel<SurfaceRefProps> {}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import type { DeltaInsert } from '@blocksuite/inline';
|
||||
import type { Text } from '@blocksuite/store';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export type TableCell = {
|
||||
text: Text;
|
||||
@@ -56,3 +60,5 @@ export const TableBlockSchema = defineBlockSchema({
|
||||
},
|
||||
toModel: () => new TableBlockModel(),
|
||||
});
|
||||
|
||||
export const TableBlockSchemaExtension = BlockSchemaExtension(TableBlockSchema);
|
||||
|
||||
Reference in New Issue
Block a user