mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00: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:
@@ -4,8 +4,11 @@ import type { SliceSnapshot } from '@blocksuite/store';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { createJob } from '../utils/create-job.js';
|
||||
import { getProvider } from '../utils/get-provider.js';
|
||||
import { nanoidReplacement } from '../utils/nanoid-replacement.js';
|
||||
|
||||
getProvider();
|
||||
|
||||
describe('notion-text to snapshot', () => {
|
||||
test('basic', () => {
|
||||
const notionText =
|
||||
|
||||
@@ -11,39 +11,37 @@ import {
|
||||
type Cell,
|
||||
type Column,
|
||||
type DatabaseBlockModel,
|
||||
DatabaseBlockSchema,
|
||||
NoteBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
RootBlockSchema,
|
||||
DatabaseBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { propertyModelPresets } from '@blocksuite/data-view/property-pure-presets';
|
||||
import type { BlockModel, Store } from '@blocksuite/store';
|
||||
import { Schema, Text } from '@blocksuite/store';
|
||||
import { Text } from '@blocksuite/store';
|
||||
import {
|
||||
createAutoIncrementIdGenerator,
|
||||
TestWorkspace,
|
||||
} from '@blocksuite/store/test';
|
||||
import { beforeEach, describe, expect, test } from 'vitest';
|
||||
|
||||
const AffineSchemas = [
|
||||
RootBlockSchema,
|
||||
NoteBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
DatabaseBlockSchema,
|
||||
const extensions = [
|
||||
RootBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
DatabaseBlockSchemaExtension,
|
||||
];
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register(AffineSchemas);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
function createTestDoc(docId = 'doc0') {
|
||||
const options = createTestOptions();
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc({ id: docId });
|
||||
const doc = collection.createDoc({ id: docId, extensions });
|
||||
doc.load();
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image';
|
||||
import { FeatureFlagService } from '@blocksuite/affine-shared/services';
|
||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
Schema,
|
||||
Transformer,
|
||||
@@ -26,8 +26,8 @@ export function createJob(middlewares?: TransformerMiddleware[]) {
|
||||
const testMiddlewares = middlewares ?? [];
|
||||
testMiddlewares.push(defaultImageProxyMiddleware);
|
||||
const schema = new Schema().register(AffineSchemas);
|
||||
const docCollection = new TestWorkspace({ schema });
|
||||
docCollection.storeExtensions = [FeatureFlagService];
|
||||
const docCollection = new TestWorkspace();
|
||||
docCollection.storeExtensions = SpecProvider._.getSpec('store').value;
|
||||
docCollection.meta.initialize();
|
||||
return new Transformer({
|
||||
schema,
|
||||
|
||||
@@ -2,15 +2,12 @@ import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
|
||||
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
|
||||
import { CodeBlockSpec } from '@blocksuite/affine-block-code';
|
||||
import { DataViewBlockSpec } from '@blocksuite/affine-block-data-view';
|
||||
import {
|
||||
DatabaseBlockSpec,
|
||||
DatabaseSelectionExtension,
|
||||
} from '@blocksuite/affine-block-database';
|
||||
import { DatabaseBlockSpec } from '@blocksuite/affine-block-database';
|
||||
import { DividerBlockSpec } from '@blocksuite/affine-block-divider';
|
||||
import { EdgelessTextBlockSpec } from '@blocksuite/affine-block-edgeless-text';
|
||||
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
|
||||
import { FrameBlockSpec } from '@blocksuite/affine-block-frame';
|
||||
import { ImageBlockSpec, ImageStoreSpec } from '@blocksuite/affine-block-image';
|
||||
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
|
||||
import { LatexBlockSpec } from '@blocksuite/affine-block-latex';
|
||||
import { ListBlockSpec } from '@blocksuite/affine-block-list';
|
||||
import {
|
||||
@@ -26,43 +23,19 @@ import {
|
||||
EdgelessSurfaceRefBlockSpec,
|
||||
PageSurfaceRefBlockSpec,
|
||||
} from '@blocksuite/affine-block-surface-ref';
|
||||
import {
|
||||
TableBlockSpec,
|
||||
TableSelectionExtension,
|
||||
} from '@blocksuite/affine-block-table';
|
||||
import { TableBlockSpec } from '@blocksuite/affine-block-table';
|
||||
import {
|
||||
RefNodeSlotsExtension,
|
||||
RichTextExtensions,
|
||||
} from '@blocksuite/affine-components/rich-text';
|
||||
import {
|
||||
HighlightSelectionExtension,
|
||||
ImageSelectionExtension,
|
||||
} from '@blocksuite/affine-shared/selection';
|
||||
import {
|
||||
DefaultOpenDocExtension,
|
||||
DocDisplayMetaService,
|
||||
EditPropsStore,
|
||||
FeatureFlagService,
|
||||
FileSizeLimitService,
|
||||
FontLoaderService,
|
||||
LinkPreviewerService,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
BlockSelectionExtension,
|
||||
CursorSelectionExtension,
|
||||
SurfaceSelectionExtension,
|
||||
TextSelectionExtension,
|
||||
} from '@blocksuite/block-std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import {
|
||||
AdapterFactoryExtensions,
|
||||
HtmlAdapterExtension,
|
||||
MarkdownAdapterExtension,
|
||||
NotionHtmlAdapterExtension,
|
||||
PlainTextAdapterExtension,
|
||||
} from '../adapters/extension.js';
|
||||
|
||||
export const CommonBlockSpecs: ExtensionType[] = [
|
||||
DocDisplayMetaService,
|
||||
RefNodeSlotsExtension,
|
||||
@@ -82,7 +55,6 @@ export const CommonBlockSpecs: ExtensionType[] = [
|
||||
ParagraphBlockSpec,
|
||||
DefaultOpenDocExtension,
|
||||
FontLoaderService,
|
||||
AdapterFactoryExtensions,
|
||||
].flat();
|
||||
|
||||
export const PageFirstPartyBlockSpecs: ExtensionType[] = [
|
||||
@@ -101,24 +73,3 @@ export const EdgelessFirstPartyBlockSpecs: ExtensionType[] = [
|
||||
FrameBlockSpec,
|
||||
EdgelessTextBlockSpec,
|
||||
].flat();
|
||||
|
||||
export const StoreExtensions: ExtensionType[] = [
|
||||
BlockSelectionExtension,
|
||||
TextSelectionExtension,
|
||||
SurfaceSelectionExtension,
|
||||
CursorSelectionExtension,
|
||||
HighlightSelectionExtension,
|
||||
ImageSelectionExtension,
|
||||
DatabaseSelectionExtension,
|
||||
TableSelectionExtension,
|
||||
|
||||
FeatureFlagService,
|
||||
LinkPreviewerService,
|
||||
FileSizeLimitService,
|
||||
ImageStoreSpec,
|
||||
|
||||
HtmlAdapterExtension,
|
||||
MarkdownAdapterExtension,
|
||||
NotionHtmlAdapterExtension,
|
||||
PlainTextAdapterExtension,
|
||||
].flat();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './common.js';
|
||||
export * from './editor-specs.js';
|
||||
export * from './preview-specs.js';
|
||||
export * from './store.js';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||
|
||||
import { StoreExtensions } from './common.js';
|
||||
import {
|
||||
EdgelessEditorBlockSpecs,
|
||||
PageEditorBlockSpecs,
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
PreviewEdgelessEditorBlockSpecs,
|
||||
PreviewPageEditorBlockSpecs,
|
||||
} from './preview-specs.js';
|
||||
import { StoreExtensions } from './store.js';
|
||||
|
||||
export function registerSpecs() {
|
||||
SpecProvider._.addSpec('store', StoreExtensions);
|
||||
|
||||
101
blocksuite/blocks/src/extensions/store.ts
Normal file
101
blocksuite/blocks/src/extensions/store.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { DataViewBlockSchemaExtension } from '@blocksuite/affine-block-data-view';
|
||||
import { DatabaseSelectionExtension } from '@blocksuite/affine-block-database';
|
||||
import { ImageStoreSpec } from '@blocksuite/affine-block-image';
|
||||
import { SurfaceBlockSchemaExtension } from '@blocksuite/affine-block-surface';
|
||||
import { TableSelectionExtension } from '@blocksuite/affine-block-table';
|
||||
import {
|
||||
AttachmentBlockSchemaExtension,
|
||||
BookmarkBlockSchemaExtension,
|
||||
CodeBlockSchemaExtension,
|
||||
DatabaseBlockSchemaExtension,
|
||||
DividerBlockSchemaExtension,
|
||||
EdgelessTextBlockSchemaExtension,
|
||||
EmbedFigmaBlockSchemaExtension,
|
||||
EmbedGithubBlockSchemaExtension,
|
||||
EmbedHtmlBlockSchemaExtension,
|
||||
EmbedLinkedDocBlockSchemaExtension,
|
||||
EmbedLoomBlockSchemaExtension,
|
||||
EmbedSyncedDocBlockSchemaExtension,
|
||||
EmbedYoutubeBlockSchemaExtension,
|
||||
FrameBlockSchemaExtension,
|
||||
ImageBlockSchemaExtension,
|
||||
LatexBlockSchemaExtension,
|
||||
ListBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
SurfaceRefBlockSchemaExtension,
|
||||
TableBlockSchemaExtension,
|
||||
} from '@blocksuite/affine-model';
|
||||
import {
|
||||
HighlightSelectionExtension,
|
||||
ImageSelectionExtension,
|
||||
} from '@blocksuite/affine-shared/selection';
|
||||
import {
|
||||
FeatureFlagService,
|
||||
FileSizeLimitService,
|
||||
LinkPreviewerService,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
BlockSelectionExtension,
|
||||
CursorSelectionExtension,
|
||||
SurfaceSelectionExtension,
|
||||
TextSelectionExtension,
|
||||
} from '@blocksuite/block-std';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import {
|
||||
AdapterFactoryExtensions,
|
||||
HtmlAdapterExtension,
|
||||
MarkdownAdapterExtension,
|
||||
NotionHtmlAdapterExtension,
|
||||
PlainTextAdapterExtension,
|
||||
} from '../adapters/extension.js';
|
||||
|
||||
export const StoreExtensions: ExtensionType[] = [
|
||||
CodeBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
ListBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
DividerBlockSchemaExtension,
|
||||
ImageBlockSchemaExtension,
|
||||
SurfaceBlockSchemaExtension,
|
||||
BookmarkBlockSchemaExtension,
|
||||
FrameBlockSchemaExtension,
|
||||
DatabaseBlockSchemaExtension,
|
||||
SurfaceRefBlockSchemaExtension,
|
||||
DataViewBlockSchemaExtension,
|
||||
AttachmentBlockSchemaExtension,
|
||||
EmbedSyncedDocBlockSchemaExtension,
|
||||
EmbedLinkedDocBlockSchemaExtension,
|
||||
EmbedHtmlBlockSchemaExtension,
|
||||
EmbedGithubBlockSchemaExtension,
|
||||
EmbedFigmaBlockSchemaExtension,
|
||||
EmbedLoomBlockSchemaExtension,
|
||||
EmbedYoutubeBlockSchemaExtension,
|
||||
EdgelessTextBlockSchemaExtension,
|
||||
LatexBlockSchemaExtension,
|
||||
TableBlockSchemaExtension,
|
||||
|
||||
BlockSelectionExtension,
|
||||
TextSelectionExtension,
|
||||
SurfaceSelectionExtension,
|
||||
CursorSelectionExtension,
|
||||
HighlightSelectionExtension,
|
||||
ImageSelectionExtension,
|
||||
DatabaseSelectionExtension,
|
||||
TableSelectionExtension,
|
||||
|
||||
FeatureFlagService,
|
||||
LinkPreviewerService,
|
||||
FileSizeLimitService,
|
||||
ImageStoreSpec,
|
||||
|
||||
HtmlAdapterExtension,
|
||||
MarkdownAdapterExtension,
|
||||
NotionHtmlAdapterExtension,
|
||||
PlainTextAdapterExtension,
|
||||
|
||||
AdapterFactoryExtensions,
|
||||
].flat();
|
||||
Reference in New Issue
Block a user