mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-07 01:09:54 +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:
@@ -238,7 +238,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
private async _exportFile(config: AdapterConfig) {
|
||||
const doc = this.editor.doc;
|
||||
const job = new Transformer({
|
||||
schema: this.collection.schema,
|
||||
schema: doc.schema,
|
||||
blobCRUD: this.collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => this.collection.createDoc({ id }),
|
||||
@@ -325,6 +325,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
private async _exportSnapshot() {
|
||||
await ZipTransformer.exportDocs(
|
||||
this.collection,
|
||||
this.editor.doc.schema,
|
||||
Array.from(this.collection.docs.values()).map(collection =>
|
||||
collection.getStore()
|
||||
)
|
||||
@@ -346,6 +347,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
const fileName = file.name.split('.').slice(0, -1).join('.');
|
||||
const pageId = await HtmlTransformer.importHTMLToDoc({
|
||||
collection: this.collection,
|
||||
schema: this.editor.doc.schema,
|
||||
html: text,
|
||||
fileName,
|
||||
});
|
||||
@@ -369,6 +371,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
if (!file) return;
|
||||
const result = await HtmlTransformer.importHTMLZip({
|
||||
collection: this.collection,
|
||||
schema: this.editor.doc.schema,
|
||||
imported: file,
|
||||
});
|
||||
if (!this.editor.host) return;
|
||||
@@ -396,6 +399,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
const fileName = file.name.split('.').slice(0, -1).join('.');
|
||||
const pageId = await MarkdownTransformer.importMarkdownToDoc({
|
||||
collection: this.collection,
|
||||
schema: this.editor.doc.schema,
|
||||
markdown: text,
|
||||
fileName,
|
||||
});
|
||||
@@ -419,6 +423,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
if (!file) return;
|
||||
const result = await MarkdownTransformer.importMarkdownZip({
|
||||
collection: this.collection,
|
||||
schema: this.editor.doc.schema,
|
||||
imported: file,
|
||||
});
|
||||
if (!this.editor.host) return;
|
||||
@@ -438,8 +443,9 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
multiple: false,
|
||||
});
|
||||
if (!file) return;
|
||||
const doc = this.editor.doc;
|
||||
const job = new Transformer({
|
||||
schema: this.collection.schema,
|
||||
schema: doc.schema,
|
||||
blobCRUD: this.collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => this.collection.createDoc({ id }),
|
||||
@@ -465,6 +471,7 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
if (!file) return;
|
||||
const result = await NotionHtmlTransformer.importNotionZip({
|
||||
collection: this.collection,
|
||||
schema: this.editor.doc.schema,
|
||||
imported: file,
|
||||
});
|
||||
if (!this.editor.host) return;
|
||||
@@ -488,7 +495,11 @@ export class StarterDebugMenu extends ShadowlessElement {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const docs = await ZipTransformer.importDocs(this.collection, file);
|
||||
const docs = await ZipTransformer.importDocs(
|
||||
this.collection,
|
||||
this.editor.doc.schema,
|
||||
file
|
||||
);
|
||||
for (const doc of docs) {
|
||||
if (doc) {
|
||||
const noteBlock = window.doc.getBlockByFlavour('affine:note');
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { AffineSchemas, SpecProvider } from '@blocksuite/blocks';
|
||||
import { Schema } from '@blocksuite/store';
|
||||
import { SpecProvider } from '@blocksuite/blocks';
|
||||
import { TestWorkspace } from '@blocksuite/store/test';
|
||||
|
||||
export function createEmptyDoc() {
|
||||
const schema = new Schema().register(AffineSchemas);
|
||||
const collection = new TestWorkspace({ schema });
|
||||
const collection = new TestWorkspace();
|
||||
collection.storeExtensions = SpecProvider._.getSpec('store').value;
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ZipTransformer } from '@blocksuite/blocks';
|
||||
import { Text, type Workspace } from '@blocksuite/store';
|
||||
import { AffineSchemas, ZipTransformer } from '@blocksuite/blocks';
|
||||
import { Schema, Text, type Workspace } from '@blocksuite/store';
|
||||
|
||||
export async function affineSnapshot(collection: Workspace, id: string) {
|
||||
const doc = collection.createDoc({ id });
|
||||
@@ -13,7 +13,9 @@ export async function affineSnapshot(collection: Workspace, id: string) {
|
||||
const path = '/apps/starter/data/snapshots/affine-default.zip';
|
||||
const response = await fetch(path);
|
||||
const file = await response.blob();
|
||||
await ZipTransformer.importDocs(collection, file);
|
||||
const schema = new Schema();
|
||||
schema.register(AffineSchemas);
|
||||
await ZipTransformer.importDocs(collection, schema, file);
|
||||
}
|
||||
|
||||
affineSnapshot.id = 'affine-snapshot';
|
||||
|
||||
@@ -49,7 +49,6 @@ export function createStarterDocCollection() {
|
||||
|
||||
const options: DocCollectionOptions = {
|
||||
id: collectionId,
|
||||
schema,
|
||||
idGenerator,
|
||||
awarenessSources: [new BroadcastChannelAwarenessSource(id)],
|
||||
docSources,
|
||||
@@ -63,7 +62,7 @@ export function createStarterDocCollection() {
|
||||
window.collection = collection;
|
||||
window.blockSchemas = AffineSchemas;
|
||||
window.job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
|
||||
Reference in New Issue
Block a user