mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-15 05:37:32 +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:
@@ -5,7 +5,11 @@ import {
|
||||
type InsertToPosition,
|
||||
} from '@blocksuite/affine-shared/utils';
|
||||
import type { DataViewDataType } from '@blocksuite/data-view';
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
@@ -93,3 +97,6 @@ export const DataViewBlockSchema = defineBlockSchema({
|
||||
return new DataViewBlockModel();
|
||||
},
|
||||
});
|
||||
|
||||
export const DataViewBlockSchemaExtension =
|
||||
BlockSchemaExtension(DataViewBlockSchema);
|
||||
|
||||
@@ -374,7 +374,7 @@ export class EdgelessClipboardController extends PageClipboard {
|
||||
const elementsRawData = JSON.parse(mayBeSurfaceDataJson);
|
||||
const { snapshot, blobs } = elementsRawData;
|
||||
const job = new Transformer({
|
||||
schema: this.std.workspace.schema,
|
||||
schema: this.std.store.schema,
|
||||
blobCRUD: this.std.workspace.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => this.std.workspace.createDoc({ id }),
|
||||
@@ -1378,7 +1378,7 @@ export async function prepareClipboardData(
|
||||
std: BlockStdScope
|
||||
) {
|
||||
const job = new Transformer({
|
||||
schema: std.workspace.schema,
|
||||
schema: std.store.schema,
|
||||
blobCRUD: std.workspace.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => std.workspace.createDoc({ id }),
|
||||
|
||||
@@ -91,7 +91,7 @@ export class TemplateJob {
|
||||
|
||||
constructor({ model, type, middlewares }: TemplateJobConfig) {
|
||||
this.job = new Transformer({
|
||||
schema: model.doc.workspace.schema,
|
||||
schema: model.doc.schema,
|
||||
blobCRUD: model.doc.workspace.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => model.doc.workspace.createDoc({ id }),
|
||||
@@ -320,8 +320,7 @@ export class TemplateJob {
|
||||
from: Record<string, Record<string, unknown>>,
|
||||
to: Y.Map<Y.Map<unknown>>
|
||||
) {
|
||||
const schema =
|
||||
this.model.doc.workspace.schema.flavourSchemaMap.get('affine:surface');
|
||||
const schema = this.model.doc.schema.get('affine:surface');
|
||||
const surfaceTransformer = schema?.transformer?.(
|
||||
new Map()
|
||||
) as SurfaceBlockTransformer;
|
||||
|
||||
@@ -41,7 +41,7 @@ export function getSortedCloneElements(elements: GfxModel[]) {
|
||||
export function prepareCloneData(elements: GfxModel[], std: BlockStdScope) {
|
||||
elements = sortEdgelessElements(elements);
|
||||
const job = new Transformer({
|
||||
schema: std.workspace.schema,
|
||||
schema: std.store.schema,
|
||||
blobCRUD: std.workspace.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => std.workspace.createDoc({ id }),
|
||||
|
||||
@@ -8,19 +8,21 @@ import {
|
||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||
import { Container } from '@blocksuite/global/di';
|
||||
import { sha } from '@blocksuite/global/utils';
|
||||
import type { Store, Workspace } from '@blocksuite/store';
|
||||
import type { Schema, Store, Workspace } from '@blocksuite/store';
|
||||
import { extMimeMap, Transformer } from '@blocksuite/store';
|
||||
|
||||
import { createAssetsArchive, download, Unzip } from './utils.js';
|
||||
|
||||
type ImportHTMLToDocOptions = {
|
||||
collection: Workspace;
|
||||
schema: Schema;
|
||||
html: string;
|
||||
fileName?: string;
|
||||
};
|
||||
|
||||
type ImportHTMLZipOptions = {
|
||||
collection: Workspace;
|
||||
schema: Schema;
|
||||
imported: Blob;
|
||||
};
|
||||
|
||||
@@ -87,18 +89,20 @@ async function exportDoc(doc: Store) {
|
||||
*
|
||||
* @param options - The import options.
|
||||
* @param options.collection - The target doc collection.
|
||||
* @param options.schema - The schema of the target doc collection.
|
||||
* @param options.html - The HTML content to import.
|
||||
* @param options.fileName - Optional filename for the imported doc.
|
||||
* @returns A Promise that resolves to the ID of the newly created doc, or undefined if import fails.
|
||||
*/
|
||||
async function importHTMLToDoc({
|
||||
collection,
|
||||
schema,
|
||||
html,
|
||||
fileName,
|
||||
}: ImportHTMLToDocOptions) {
|
||||
const provider = getProvider();
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
@@ -127,10 +131,15 @@ async function importHTMLToDoc({
|
||||
*
|
||||
* @param options - The import options.
|
||||
* @param options.collection - The target doc collection.
|
||||
* @param options.schema - The schema of the target doc collection.
|
||||
* @param options.imported - The zip file as a Blob.
|
||||
* @returns A Promise that resolves to an array of IDs of the newly created docs.
|
||||
*/
|
||||
async function importHTMLZip({ collection, imported }: ImportHTMLZipOptions) {
|
||||
async function importHTMLZip({
|
||||
collection,
|
||||
schema,
|
||||
imported,
|
||||
}: ImportHTMLZipOptions) {
|
||||
const provider = getProvider();
|
||||
const unzip = new Unzip();
|
||||
await unzip.load(imported);
|
||||
@@ -161,7 +170,7 @@ async function importHTMLZip({ collection, imported }: ImportHTMLZipOptions) {
|
||||
htmlBlobs.map(async ([fileName, blob]) => {
|
||||
const fileNameWithoutExt = fileName.replace(/\.[^/.]+$/, '');
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
|
||||
@@ -9,7 +9,7 @@ import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||
import { Container } from '@blocksuite/global/di';
|
||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||
import { assertExists, sha } from '@blocksuite/global/utils';
|
||||
import type { Store, Workspace } from '@blocksuite/store';
|
||||
import type { Schema, Store, Workspace } from '@blocksuite/store';
|
||||
import { extMimeMap, Transformer } from '@blocksuite/store';
|
||||
|
||||
import { createAssetsArchive, download, Unzip } from './utils.js';
|
||||
@@ -31,12 +31,14 @@ type ImportMarkdownToBlockOptions = {
|
||||
|
||||
type ImportMarkdownToDocOptions = {
|
||||
collection: Workspace;
|
||||
schema: Schema;
|
||||
markdown: string;
|
||||
fileName?: string;
|
||||
};
|
||||
|
||||
type ImportMarkdownZipOptions = {
|
||||
collection: Workspace;
|
||||
schema: Schema;
|
||||
imported: Blob;
|
||||
};
|
||||
|
||||
@@ -143,18 +145,20 @@ async function importMarkdownToBlock({
|
||||
* Imports Markdown content into a new doc within a collection.
|
||||
* @param options Object containing import options
|
||||
* @param options.collection The target doc collection
|
||||
* @param options.schema The schema of the target doc collection
|
||||
* @param options.markdown The Markdown content to import
|
||||
* @param options.fileName Optional filename for the imported doc
|
||||
* @returns A Promise that resolves to the ID of the newly created doc, or undefined if import fails
|
||||
*/
|
||||
async function importMarkdownToDoc({
|
||||
collection,
|
||||
schema,
|
||||
markdown,
|
||||
fileName,
|
||||
}: ImportMarkdownToDocOptions) {
|
||||
const provider = getProvider();
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
@@ -182,11 +186,13 @@ async function importMarkdownToDoc({
|
||||
* Imports a zip file containing Markdown files and assets into a collection.
|
||||
* @param options Object containing import options
|
||||
* @param options.collection The target doc collection
|
||||
* @param options.schema The schema of the target doc collection
|
||||
* @param options.imported The zip file as a Blob
|
||||
* @returns A Promise that resolves to an array of IDs of the newly created docs
|
||||
*/
|
||||
async function importMarkdownZip({
|
||||
collection,
|
||||
schema,
|
||||
imported,
|
||||
}: ImportMarkdownZipOptions) {
|
||||
const provider = getProvider();
|
||||
@@ -219,7 +225,7 @@ async function importMarkdownZip({
|
||||
markdownBlobs.map(async ([fileName, blob]) => {
|
||||
const fileNameWithoutExt = fileName.replace(/\.[^/.]+$/, '');
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
|
||||
@@ -3,12 +3,18 @@ import { NotionHtmlAdapter } from '@blocksuite/affine-shared/adapters';
|
||||
import { SpecProvider } from '@blocksuite/affine-shared/utils';
|
||||
import { Container } from '@blocksuite/global/di';
|
||||
import { sha } from '@blocksuite/global/utils';
|
||||
import { extMimeMap, Transformer, type Workspace } from '@blocksuite/store';
|
||||
import {
|
||||
extMimeMap,
|
||||
type Schema,
|
||||
Transformer,
|
||||
type Workspace,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import { Unzip } from './utils.js';
|
||||
|
||||
type ImportNotionZipOptions = {
|
||||
collection: Workspace;
|
||||
schema: Schema;
|
||||
imported: Blob;
|
||||
};
|
||||
|
||||
@@ -26,6 +32,7 @@ function getProvider() {
|
||||
*
|
||||
* @param options - The options for importing.
|
||||
* @param options.collection - The BlockSuite document collection.
|
||||
* @param options.schema - The schema of the BlockSuite document collection.
|
||||
* @param options.imported - The imported zip file as a Blob.
|
||||
*
|
||||
* @returns A promise that resolves to an object containing:
|
||||
@@ -36,6 +43,7 @@ function getProvider() {
|
||||
*/
|
||||
async function importNotionZip({
|
||||
collection,
|
||||
schema,
|
||||
imported,
|
||||
}: ImportNotionZipOptions) {
|
||||
const provider = getProvider();
|
||||
@@ -117,7 +125,7 @@ async function importNotionZip({
|
||||
}
|
||||
const pagePromises = Array.from(pagePaths).map(async path => {
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
|
||||
@@ -3,15 +3,19 @@ import {
|
||||
titleMiddleware,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import { sha } from '@blocksuite/global/utils';
|
||||
import type { DocSnapshot, Store, Workspace } from '@blocksuite/store';
|
||||
import type { DocSnapshot, Schema, Store, Workspace } from '@blocksuite/store';
|
||||
import { extMimeMap, getAssetName, Transformer } from '@blocksuite/store';
|
||||
|
||||
import { download, Unzip, Zip } from '../transformers/utils.js';
|
||||
|
||||
async function exportDocs(collection: Workspace, docs: Store[]) {
|
||||
async function exportDocs(
|
||||
collection: Workspace,
|
||||
schema: Schema,
|
||||
docs: Store[]
|
||||
) {
|
||||
const zip = new Zip();
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
@@ -70,7 +74,11 @@ async function exportDocs(collection: Workspace, docs: Store[]) {
|
||||
return download(downloadBlob, `${collection.id}.bs.zip`);
|
||||
}
|
||||
|
||||
async function importDocs(collection: Workspace, imported: Blob) {
|
||||
async function importDocs(
|
||||
collection: Workspace,
|
||||
schema: Schema,
|
||||
imported: Blob
|
||||
) {
|
||||
const unzip = new Unzip();
|
||||
await unzip.load(imported);
|
||||
|
||||
@@ -98,7 +106,7 @@ async function importDocs(collection: Workspace, imported: Blob) {
|
||||
}
|
||||
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema,
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
|
||||
@@ -233,6 +233,7 @@ export function createNewDocMenuGroup(
|
||||
};
|
||||
showImportModal({
|
||||
collection: doc.workspace,
|
||||
schema: doc.schema,
|
||||
onSuccess,
|
||||
onFail,
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from '@blocksuite/affine-components/icons';
|
||||
import { openFileOrFiles } from '@blocksuite/affine-shared/utils';
|
||||
import { WithDisposable } from '@blocksuite/global/utils';
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import type { Schema, Workspace } from '@blocksuite/store';
|
||||
import { html, LitElement, type PropertyValues } from 'lit';
|
||||
import { query, state } from 'lit/decorators.js';
|
||||
|
||||
@@ -31,6 +31,7 @@ export class ImportDoc extends WithDisposable(LitElement) {
|
||||
|
||||
constructor(
|
||||
private readonly collection: Workspace,
|
||||
private readonly schema: Schema,
|
||||
private readonly onSuccess?: OnSuccessHandler,
|
||||
private readonly onFail?: OnFailHandler,
|
||||
private readonly abortController = new AbortController()
|
||||
@@ -63,6 +64,7 @@ export class ImportDoc extends WithDisposable(LitElement) {
|
||||
}
|
||||
const pageId = await HtmlTransformer.importHTMLToDoc({
|
||||
collection: this.collection,
|
||||
schema: this.schema,
|
||||
html: text,
|
||||
fileName,
|
||||
});
|
||||
@@ -93,6 +95,7 @@ export class ImportDoc extends WithDisposable(LitElement) {
|
||||
}
|
||||
const pageId = await MarkdownTransformer.importMarkdownToDoc({
|
||||
collection: this.collection,
|
||||
schema: this.schema,
|
||||
markdown: text,
|
||||
fileName,
|
||||
});
|
||||
@@ -117,6 +120,7 @@ export class ImportDoc extends WithDisposable(LitElement) {
|
||||
const { entryId, pageIds, isWorkspaceFile, hasMarkdown } =
|
||||
await NotionHtmlTransformer.importNotionZip({
|
||||
collection: this.collection,
|
||||
schema: this.schema,
|
||||
imported: file,
|
||||
});
|
||||
needLoading && this.abortController.abort();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import type { Schema, Workspace } from '@blocksuite/store';
|
||||
|
||||
import {
|
||||
ImportDoc,
|
||||
@@ -7,12 +7,14 @@ import {
|
||||
} from './import-doc.js';
|
||||
|
||||
export function showImportModal({
|
||||
schema,
|
||||
collection,
|
||||
onSuccess,
|
||||
onFail,
|
||||
container = document.body,
|
||||
abortController = new AbortController(),
|
||||
}: {
|
||||
schema: Schema;
|
||||
collection: Workspace;
|
||||
onSuccess?: OnSuccessHandler;
|
||||
onFail?: OnFailHandler;
|
||||
@@ -22,6 +24,7 @@ export function showImportModal({
|
||||
}) {
|
||||
const importDoc = new ImportDoc(
|
||||
collection,
|
||||
schema,
|
||||
onSuccess,
|
||||
onFail,
|
||||
abortController
|
||||
|
||||
@@ -50,7 +50,11 @@ export {
|
||||
} from './adapters/index.js';
|
||||
export type { SurfaceContext } from './surface-block.js';
|
||||
export { SurfaceBlockComponent } from './surface-block.js';
|
||||
export { SurfaceBlockModel, SurfaceBlockSchema } from './surface-model.js';
|
||||
export {
|
||||
SurfaceBlockModel,
|
||||
SurfaceBlockSchema,
|
||||
SurfaceBlockSchemaExtension,
|
||||
} from './surface-model.js';
|
||||
export type { SurfaceBlockService } from './surface-service.js';
|
||||
export {
|
||||
EdgelessSurfaceBlockSpec,
|
||||
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
import type { SurfaceBlockProps } from '@blocksuite/block-std/gfx';
|
||||
import { SurfaceBlockModel as BaseSurfaceModel } from '@blocksuite/block-std/gfx';
|
||||
import { DisposableGroup } from '@blocksuite/global/utils';
|
||||
import { defineBlockSchema } from '@blocksuite/store';
|
||||
import { BlockSchemaExtension, defineBlockSchema } from '@blocksuite/store';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { elementsCtorMap } from './element-model/index.js';
|
||||
@@ -36,6 +36,9 @@ export const SurfaceBlockSchema = defineBlockSchema({
|
||||
toModel: () => new SurfaceBlockModel(),
|
||||
});
|
||||
|
||||
export const SurfaceBlockSchemaExtension =
|
||||
BlockSchemaExtension(SurfaceBlockSchema);
|
||||
|
||||
export type SurfaceMiddleware = (surface: SurfaceBlockModel) => () => void;
|
||||
|
||||
export class SurfaceBlockModel extends BaseSurfaceModel {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
@@ -1,4 +1,3 @@
|
||||
import { Schema } from '@blocksuite/store';
|
||||
import {
|
||||
createAutoIncrementIdGenerator,
|
||||
TestWorkspace,
|
||||
@@ -9,19 +8,23 @@ import { effects } from '../effects.js';
|
||||
import { TestEditorContainer } from './test-editor.js';
|
||||
import {
|
||||
type HeadingBlockModel,
|
||||
HeadingBlockSchema,
|
||||
NoteBlockSchema,
|
||||
RootBlockSchema,
|
||||
HeadingBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
} from './test-schema.js';
|
||||
import { testSpecs } from './test-spec.js';
|
||||
|
||||
effects();
|
||||
|
||||
const extensions = [
|
||||
RootBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
HeadingBlockSchemaExtension,
|
||||
];
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register([RootBlockSchema, NoteBlockSchema, HeadingBlockSchema]);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
function wait(time: number) {
|
||||
@@ -33,7 +36,7 @@ describe('editor host', () => {
|
||||
const collection = new TestWorkspace(createTestOptions());
|
||||
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
const rootId = doc.addBlock('test:page');
|
||||
const noteId = doc.addBlock('test:note', {}, rootId);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
|
||||
import {
|
||||
BlockModel,
|
||||
BlockSchemaExtension,
|
||||
defineBlockSchema,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
export const RootBlockSchema = defineBlockSchema({
|
||||
flavour: 'test:page',
|
||||
@@ -15,6 +19,8 @@ export const RootBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const RootBlockSchemaExtension = BlockSchemaExtension(RootBlockSchema);
|
||||
|
||||
export class RootBlockModel extends BlockModel<
|
||||
ReturnType<(typeof RootBlockSchema)['model']['props']>
|
||||
> {}
|
||||
@@ -30,6 +36,8 @@ export const NoteBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const NoteBlockSchemaExtension = BlockSchemaExtension(NoteBlockSchema);
|
||||
|
||||
export class NoteBlockModel extends BlockModel<
|
||||
ReturnType<(typeof NoteBlockSchema)['model']['props']>
|
||||
> {}
|
||||
@@ -47,6 +55,9 @@ export const HeadingBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const HeadingBlockSchemaExtension =
|
||||
BlockSchemaExtension(HeadingBlockSchema);
|
||||
|
||||
export class HeadingBlockModel extends BlockModel<
|
||||
ReturnType<(typeof HeadingBlockSchema)['model']['props']>
|
||||
> {}
|
||||
|
||||
@@ -142,7 +142,7 @@ export class BlockStdScope {
|
||||
|
||||
getTransformer(middlewares: TransformerMiddleware[] = []) {
|
||||
return new Transformer({
|
||||
schema: this.workspace.schema,
|
||||
schema: this.store.schema,
|
||||
blobCRUD: this.workspace.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => this.workspace.createDoc({ id }),
|
||||
|
||||
@@ -2,6 +2,7 @@ import { computed, effect } from '@preact/signals-core';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { BlockSchemaExtension } from '../extension/schema.js';
|
||||
import {
|
||||
Block,
|
||||
BlockModel,
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
internalPrimitives,
|
||||
} from '../model/block/index.js';
|
||||
import type { YBlock } from '../model/block/types.js';
|
||||
import { Schema } from '../schema/index.js';
|
||||
import { createAutoIncrementIdGenerator } from '../test/index.js';
|
||||
import { TestWorkspace } from '../test/test-workspace.js';
|
||||
|
||||
@@ -27,6 +27,7 @@ const pageSchema = defineBlockSchema({
|
||||
version: 1,
|
||||
},
|
||||
});
|
||||
const pageSchemaExtension = BlockSchemaExtension(pageSchema);
|
||||
|
||||
const tableSchema = defineBlockSchema({
|
||||
flavour: 'table',
|
||||
@@ -39,6 +40,7 @@ const tableSchema = defineBlockSchema({
|
||||
version: 1,
|
||||
},
|
||||
});
|
||||
const tableSchemaExtension = BlockSchemaExtension(tableSchema);
|
||||
|
||||
const flatTableSchema = defineBlockSchema({
|
||||
flavour: 'flat-table',
|
||||
@@ -54,6 +56,8 @@ const flatTableSchema = defineBlockSchema({
|
||||
isFlatData: true,
|
||||
},
|
||||
});
|
||||
const flatTableSchemaExtension = BlockSchemaExtension(flatTableSchema);
|
||||
|
||||
class RootModel extends BlockModel<
|
||||
ReturnType<(typeof pageSchema)['model']['props']>
|
||||
> {}
|
||||
@@ -66,9 +70,7 @@ class FlatTableModel extends BlockModel<
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register([pageSchema, tableSchema, flatTableSchema]);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
const defaultDocId = 'doc:home';
|
||||
@@ -76,7 +78,14 @@ function createTestDoc(docId = defaultDocId) {
|
||||
const options = createTestOptions();
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc({ id: docId });
|
||||
const doc = collection.createDoc({
|
||||
id: docId,
|
||||
extensions: [
|
||||
pageSchemaExtension,
|
||||
tableSchemaExtension,
|
||||
flatTableSchemaExtension,
|
||||
],
|
||||
});
|
||||
doc.load();
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -4,29 +4,20 @@ import type { Slot } from '@blocksuite/global/utils';
|
||||
import { assert, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { applyUpdate, type Doc, encodeStateAsUpdate } from 'yjs';
|
||||
|
||||
import type { BlockModel, BlockSchemaType, DocMeta, Store } from '../index.js';
|
||||
import { Schema } from '../index.js';
|
||||
import type { BlockModel, DocMeta, Store } from '../index.js';
|
||||
import { Text } from '../reactive/text.js';
|
||||
import { createAutoIncrementIdGenerator } from '../test/index.js';
|
||||
import { TestWorkspace } from '../test/test-workspace.js';
|
||||
import {
|
||||
NoteBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
RootBlockSchema,
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
} from './test-schema.js';
|
||||
import { assertExists } from './test-utils-dom.js';
|
||||
|
||||
export const BlockSchemas = [
|
||||
ParagraphBlockSchema,
|
||||
RootBlockSchema,
|
||||
NoteBlockSchema,
|
||||
] as BlockSchemaType[];
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register(BlockSchemas);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
const defaultDocId = 'doc:home';
|
||||
@@ -58,11 +49,20 @@ function createRoot(doc: Store) {
|
||||
return doc.root;
|
||||
}
|
||||
|
||||
const extensions = [
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
];
|
||||
|
||||
function createTestDoc(docId = defaultDocId) {
|
||||
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;
|
||||
}
|
||||
@@ -113,13 +113,6 @@ describe('basic', () => {
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
workspaceVersion: 2,
|
||||
pageVersion: 2,
|
||||
blockVersions: {
|
||||
'affine:note': 1,
|
||||
'affine:page': 2,
|
||||
'affine:paragraph': 1,
|
||||
},
|
||||
},
|
||||
spaces: {
|
||||
[spaceId]: {
|
||||
@@ -155,6 +148,7 @@ describe('basic', () => {
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc({
|
||||
id: 'space:0',
|
||||
extensions,
|
||||
});
|
||||
|
||||
const readyCallback = vi.fn();
|
||||
@@ -181,6 +175,7 @@ describe('basic', () => {
|
||||
const collection2 = new TestWorkspace(options);
|
||||
const doc = collection.createDoc({
|
||||
id: 'space:0',
|
||||
extensions,
|
||||
});
|
||||
doc.load(() => {
|
||||
doc.addBlock('affine:page', {
|
||||
@@ -209,7 +204,9 @@ describe('basic', () => {
|
||||
// apply doc update
|
||||
const update = encodeStateAsUpdate(doc.spaceDoc);
|
||||
expect(collection2.docs.size).toBe(1);
|
||||
const doc2 = collection2.getDoc('space:0');
|
||||
const doc2 = collection2.getDoc('space:0', {
|
||||
extensions,
|
||||
});
|
||||
assertExists(doc2);
|
||||
applyUpdate(doc2.spaceDoc, update);
|
||||
expect(serializCollection(collection2.doc)['spaces']).toEqual({
|
||||
|
||||
@@ -2,31 +2,28 @@ import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import type { BlockModel, Store } from '../model/index.js';
|
||||
import { Schema } from '../schema/index.js';
|
||||
import { createAutoIncrementIdGenerator } from '../test/index.js';
|
||||
import { TestWorkspace } from '../test/test-workspace.js';
|
||||
import {
|
||||
DividerBlockSchema,
|
||||
ListBlockSchema,
|
||||
NoteBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
DividerBlockSchemaExtension,
|
||||
ListBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
type RootBlockModel,
|
||||
RootBlockSchema,
|
||||
RootBlockSchemaExtension,
|
||||
} from './test-schema.js';
|
||||
|
||||
const BlockSchemas = [
|
||||
RootBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
ListBlockSchema,
|
||||
NoteBlockSchema,
|
||||
DividerBlockSchema,
|
||||
const extensions = [
|
||||
RootBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
ListBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
DividerBlockSchemaExtension,
|
||||
];
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register(BlockSchemas);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
test('trigger props updated', () => {
|
||||
@@ -34,7 +31,7 @@ test('trigger props updated', () => {
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
|
||||
doc.addBlock('affine:page');
|
||||
@@ -94,7 +91,7 @@ test('stash and pop', () => {
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
|
||||
doc.addBlock('affine:page');
|
||||
@@ -164,7 +161,7 @@ test('always get latest value in onChange', () => {
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
|
||||
doc.addBlock('affine:page');
|
||||
@@ -210,11 +207,12 @@ test('query', () => {
|
||||
const options = createTestOptions();
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
const doc1 = collection.createDoc({ id: 'home' });
|
||||
const doc1 = collection.createDoc({ id: 'home', extensions });
|
||||
doc1.load();
|
||||
const doc2 = collection.getDoc('home');
|
||||
const doc2 = collection.getDoc('home', { extensions });
|
||||
|
||||
const doc3 = collection.getDoc('home', {
|
||||
extensions,
|
||||
query: {
|
||||
mode: 'loose',
|
||||
match: [
|
||||
@@ -247,10 +245,10 @@ test('local readonly', () => {
|
||||
const options = createTestOptions();
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
const doc1 = collection.createDoc({ id: 'home' });
|
||||
const doc1 = collection.createDoc({ id: 'home', extensions });
|
||||
doc1.load();
|
||||
const doc2 = collection.getDoc('home', { readonly: true });
|
||||
const doc3 = collection.getDoc('home', { readonly: false });
|
||||
const doc2 = collection.getDoc('home', { readonly: true, extensions });
|
||||
const doc3 = collection.getDoc('home', { readonly: false, extensions });
|
||||
|
||||
expect(doc1.readonly).toBeFalsy();
|
||||
expect(doc2?.readonly).toBeTruthy();
|
||||
@@ -276,7 +274,7 @@ describe('move blocks', () => {
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
const pageId = doc.addBlock('affine:page');
|
||||
const page = doc.getBlock(pageId)!.model;
|
||||
|
||||
@@ -1,25 +1,23 @@
|
||||
import { literal } from 'lit/static-html.js';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { BlockSchemaExtension } from '../extension/schema.js';
|
||||
import { defineBlockSchema } from '../model/block/zod.js';
|
||||
// import some blocks
|
||||
import { SchemaValidateError } from '../schema/error.js';
|
||||
import { Schema } from '../schema/index.js';
|
||||
import { createAutoIncrementIdGenerator } from '../test/index.js';
|
||||
import { TestWorkspace } from '../test/test-workspace.js';
|
||||
import {
|
||||
DividerBlockSchema,
|
||||
ListBlockSchema,
|
||||
NoteBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
RootBlockSchema,
|
||||
DividerBlockSchemaExtension,
|
||||
ListBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
RootBlockSchemaExtension,
|
||||
} from './test-schema.js';
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register(BlockSchemas);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
const TestCustomNoteBlockSchema = defineBlockSchema({
|
||||
@@ -35,6 +33,10 @@ const TestCustomNoteBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
const TestCustomNoteBlockSchemaExtension = BlockSchemaExtension(
|
||||
TestCustomNoteBlockSchema
|
||||
);
|
||||
|
||||
const TestInvalidNoteBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:note-invalid-block-video',
|
||||
props: internal => ({
|
||||
@@ -48,14 +50,18 @@ const TestInvalidNoteBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
const BlockSchemas = [
|
||||
RootBlockSchema,
|
||||
ParagraphBlockSchema,
|
||||
ListBlockSchema,
|
||||
NoteBlockSchema,
|
||||
DividerBlockSchema,
|
||||
TestCustomNoteBlockSchema,
|
||||
TestInvalidNoteBlockSchema,
|
||||
const TestInvalidNoteBlockSchemaExtension = BlockSchemaExtension(
|
||||
TestInvalidNoteBlockSchema
|
||||
);
|
||||
|
||||
const extensions = [
|
||||
RootBlockSchemaExtension,
|
||||
ParagraphBlockSchemaExtension,
|
||||
ListBlockSchemaExtension,
|
||||
NoteBlockSchemaExtension,
|
||||
DividerBlockSchemaExtension,
|
||||
TestCustomNoteBlockSchemaExtension,
|
||||
TestInvalidNoteBlockSchemaExtension,
|
||||
];
|
||||
|
||||
const defaultDocId = 'doc0';
|
||||
@@ -63,7 +69,7 @@ function createTestDoc(docId = defaultDocId) {
|
||||
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,3 +1,4 @@
|
||||
import { BlockSchemaExtension } from '../extension/schema.js';
|
||||
import { BlockModel, defineBlockSchema } from '../model/index.js';
|
||||
|
||||
export const RootBlockSchema = defineBlockSchema({
|
||||
@@ -14,6 +15,8 @@ export const RootBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const RootBlockSchemaExtension = BlockSchemaExtension(RootBlockSchema);
|
||||
|
||||
export class RootBlockModel extends BlockModel<
|
||||
ReturnType<(typeof RootBlockSchema)['model']['props']>
|
||||
> {}
|
||||
@@ -42,6 +45,8 @@ export const NoteBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const NoteBlockSchemaExtension = BlockSchemaExtension(NoteBlockSchema);
|
||||
|
||||
export const ParagraphBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:paragraph',
|
||||
props: internal => ({
|
||||
@@ -60,6 +65,9 @@ export const ParagraphBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const ParagraphBlockSchemaExtension =
|
||||
BlockSchemaExtension(ParagraphBlockSchema);
|
||||
|
||||
export const ListBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:list',
|
||||
props: internal => ({
|
||||
@@ -80,6 +88,8 @@ export const ListBlockSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
export const ListBlockSchemaExtension = BlockSchemaExtension(ListBlockSchema);
|
||||
|
||||
export const DividerBlockSchema = defineBlockSchema({
|
||||
flavour: 'affine:divider',
|
||||
metadata: {
|
||||
@@ -88,3 +98,6 @@ export const DividerBlockSchema = defineBlockSchema({
|
||||
children: [],
|
||||
},
|
||||
});
|
||||
|
||||
export const DividerBlockSchemaExtension =
|
||||
BlockSchemaExtension(DividerBlockSchema);
|
||||
|
||||
@@ -2,10 +2,10 @@ import { expect, test } from 'vitest';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { MemoryBlobCRUD } from '../adapter/index.js';
|
||||
import { BlockSchemaExtension } from '../extension/schema.js';
|
||||
import { BlockModel } from '../model/block/block-model.js';
|
||||
import { defineBlockSchema } from '../model/block/zod.js';
|
||||
import { Text } from '../reactive/index.js';
|
||||
import { Schema } from '../schema/index.js';
|
||||
import { createAutoIncrementIdGenerator } from '../test/index.js';
|
||||
import { TestWorkspace } from '../test/test-workspace.js';
|
||||
import { AssetsManager, BaseBlockTransformer } from '../transformer/index.js';
|
||||
@@ -39,15 +39,16 @@ const docSchema = defineBlockSchema({
|
||||
},
|
||||
});
|
||||
|
||||
const docSchemaExtension = BlockSchemaExtension(docSchema);
|
||||
class RootBlockModel extends BlockModel<
|
||||
ReturnType<(typeof docSchema)['model']['props']>
|
||||
> {}
|
||||
|
||||
const extensions = [docSchemaExtension];
|
||||
|
||||
function createTestOptions() {
|
||||
const idGenerator = createAutoIncrementIdGenerator();
|
||||
const schema = new Schema();
|
||||
schema.register([docSchema]);
|
||||
return { id: 'test-collection', idGenerator, schema };
|
||||
return { id: 'test-collection', idGenerator };
|
||||
}
|
||||
|
||||
const transformer = new BaseBlockTransformer(new Map());
|
||||
@@ -58,7 +59,7 @@ test('model to snapshot', () => {
|
||||
const options = createTestOptions();
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
doc.addBlock('page');
|
||||
const rootModel = doc.root as RootBlockModel;
|
||||
@@ -75,7 +76,7 @@ test('snapshot to model', async () => {
|
||||
const options = createTestOptions();
|
||||
const collection = new TestWorkspace(options);
|
||||
collection.meta.initialize();
|
||||
const doc = collection.createDoc({ id: 'home' });
|
||||
const doc = collection.createDoc({ id: 'home', extensions });
|
||||
doc.load();
|
||||
doc.addBlock('page');
|
||||
const rootModel = doc.root as RootBlockModel;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './extension';
|
||||
export * from './schema';
|
||||
export * from './selection';
|
||||
export * from './store-extension';
|
||||
|
||||
20
blocksuite/framework/store/src/extension/schema.ts
Normal file
20
blocksuite/framework/store/src/extension/schema.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { createIdentifier } from '@blocksuite/global/di';
|
||||
|
||||
import type { BlockSchemaType } from '../model/block/zod';
|
||||
import type { ExtensionType } from './extension';
|
||||
|
||||
export const BlockSchemaIdentifier =
|
||||
createIdentifier<BlockSchemaType>('BlockSchema');
|
||||
|
||||
export function BlockSchemaExtension(
|
||||
blockSchema: BlockSchemaType
|
||||
): ExtensionType {
|
||||
return {
|
||||
setup: di => {
|
||||
di.addImpl(
|
||||
BlockSchemaIdentifier(blockSchema.model.flavour),
|
||||
() => blockSchema
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Slot } from '@blocksuite/global/utils';
|
||||
import type * as Y from 'yjs';
|
||||
|
||||
import type { Schema } from '../schema/schema.js';
|
||||
import type { AwarenessStore } from '../yjs/awareness.js';
|
||||
import type { YBlock } from './block/types.js';
|
||||
import type { Query } from './store/query.js';
|
||||
@@ -18,7 +17,6 @@ export type YBlocks = Y.Map<YBlock>;
|
||||
export interface Doc {
|
||||
readonly id: string;
|
||||
get meta(): DocMeta | undefined;
|
||||
get schema(): Schema;
|
||||
|
||||
remove(): void;
|
||||
load(initFn?: () => void): void;
|
||||
|
||||
@@ -4,8 +4,11 @@ import { type Disposable, Slot } from '@blocksuite/global/utils';
|
||||
import { computed, signal } from '@preact/signals-core';
|
||||
|
||||
import type { ExtensionType } from '../../extension/extension.js';
|
||||
import { StoreSelectionExtension } from '../../extension/index.js';
|
||||
import type { Schema } from '../../schema/index.js';
|
||||
import {
|
||||
BlockSchemaIdentifier,
|
||||
StoreSelectionExtension,
|
||||
} from '../../extension/index.js';
|
||||
import { Schema } from '../../schema/index.js';
|
||||
import {
|
||||
Block,
|
||||
type BlockModel,
|
||||
@@ -20,7 +23,6 @@ import { type Query, runQuery } from './query.js';
|
||||
import { syncBlockProps } from './utils.js';
|
||||
|
||||
export type StoreOptions = {
|
||||
schema: Schema;
|
||||
doc: Doc;
|
||||
id?: string;
|
||||
readonly?: boolean;
|
||||
@@ -298,14 +300,7 @@ export class Store {
|
||||
return this._doc.withoutTransact.bind(this._doc);
|
||||
}
|
||||
|
||||
constructor({
|
||||
schema,
|
||||
doc,
|
||||
readonly,
|
||||
query,
|
||||
provider,
|
||||
extensions,
|
||||
}: StoreOptions) {
|
||||
constructor({ doc, readonly, query, provider, extensions }: StoreOptions) {
|
||||
const container = new Container();
|
||||
container.addImpl(StoreIdentifier, () => this);
|
||||
|
||||
@@ -331,8 +326,11 @@ export class Store {
|
||||
yBlockUpdated: this._doc.slots.yBlockUpdated,
|
||||
};
|
||||
|
||||
this._crud = new DocCRUD(this._yBlocks, doc.schema);
|
||||
this._schema = schema;
|
||||
this._schema = new Schema();
|
||||
this._provider.getAll(BlockSchemaIdentifier).forEach(schema => {
|
||||
this._schema.register([schema]);
|
||||
});
|
||||
this._crud = new DocCRUD(this._yBlocks, this._schema);
|
||||
if (readonly !== undefined) {
|
||||
this._readonly.value = readonly;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { Slot } from '@blocksuite/global/utils';
|
||||
|
||||
import type { Workspace } from './workspace.js';
|
||||
|
||||
export type Tag = {
|
||||
id: string;
|
||||
value: string;
|
||||
@@ -38,8 +36,6 @@ export interface WorkspaceMeta {
|
||||
get name(): string | undefined;
|
||||
setName(name: string): void;
|
||||
|
||||
hasVersion: boolean;
|
||||
writeVersion(workspace: Workspace): void;
|
||||
get docs(): unknown[] | undefined;
|
||||
initialize(): void;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { BlobEngine } from '@blocksuite/sync';
|
||||
import type { Awareness } from 'y-protocols/awareness.js';
|
||||
import type * as Y from 'yjs';
|
||||
|
||||
import type { Schema } from '../schema/schema.js';
|
||||
import type { IdGenerator } from '../utils/id-generator.js';
|
||||
import type { AwarenessStore } from '../yjs/awareness.js';
|
||||
import type { CreateBlocksOptions, Doc, GetBlocksOptions } from './doc.js';
|
||||
@@ -19,7 +18,6 @@ export interface Workspace {
|
||||
readonly onLoadDoc?: (doc: Y.Doc) => void;
|
||||
readonly onLoadAwareness?: (awareness: Awareness) => void;
|
||||
|
||||
get schema(): Schema;
|
||||
get doc(): Y.Doc;
|
||||
get docs(): Map<string, Doc>;
|
||||
|
||||
|
||||
@@ -162,10 +162,6 @@ export class TestDoc implements Doc {
|
||||
return this._ready;
|
||||
}
|
||||
|
||||
get schema() {
|
||||
return this.workspace.schema;
|
||||
}
|
||||
|
||||
get spaceDoc() {
|
||||
return this._ySpaceDoc;
|
||||
}
|
||||
@@ -189,13 +185,6 @@ export class TestDoc implements Doc {
|
||||
return (readonly?.toString() as 'true' | 'false') ?? 'false';
|
||||
}
|
||||
|
||||
private _handleVersion() {
|
||||
// Initialization from empty yDoc, indicating that the document is new.
|
||||
if (!this.workspace.meta.hasVersion) {
|
||||
this.workspace.meta.writeVersion(this.workspace);
|
||||
}
|
||||
}
|
||||
|
||||
private _handleYBlockAdd(id: string) {
|
||||
this.slots.yBlockUpdated.emit({ type: 'add', id });
|
||||
}
|
||||
@@ -306,7 +295,6 @@ export class TestDoc implements Doc {
|
||||
|
||||
const doc = new Store({
|
||||
doc: this,
|
||||
schema: this.workspace.schema,
|
||||
readonly,
|
||||
query,
|
||||
provider,
|
||||
@@ -327,10 +315,6 @@ export class TestDoc implements Doc {
|
||||
|
||||
this._ySpaceDoc.load();
|
||||
|
||||
if ((this.workspace.meta.docs?.length ?? 0) <= 1) {
|
||||
this._handleVersion();
|
||||
}
|
||||
|
||||
this._initYBlocks();
|
||||
|
||||
this._yBlocks.forEach((_, id) => {
|
||||
|
||||
@@ -4,20 +4,13 @@ import type * as Y from 'yjs';
|
||||
import type {
|
||||
DocMeta,
|
||||
DocsPropertiesMeta,
|
||||
Workspace,
|
||||
WorkspaceMeta,
|
||||
} from '../model/index.js';
|
||||
import { createYProxy } from '../reactive/proxy.js';
|
||||
|
||||
const COLLECTION_VERSION = 2;
|
||||
const PAGE_VERSION = 2;
|
||||
|
||||
type DocCollectionMetaState = {
|
||||
pages?: unknown[];
|
||||
properties?: DocsPropertiesMeta;
|
||||
workspaceVersion?: number;
|
||||
pageVersion?: number;
|
||||
blockVersions?: Record<string, number>;
|
||||
name?: string;
|
||||
avatar?: string;
|
||||
};
|
||||
@@ -68,10 +61,6 @@ export class TestMeta implements WorkspaceMeta {
|
||||
return this._proxy.avatar;
|
||||
}
|
||||
|
||||
get blockVersions() {
|
||||
return this._proxy.blockVersions;
|
||||
}
|
||||
|
||||
get docMetas() {
|
||||
if (!this._proxy.pages) {
|
||||
return [] as DocMeta[];
|
||||
@@ -83,21 +72,10 @@ export class TestMeta implements WorkspaceMeta {
|
||||
return this._proxy.pages;
|
||||
}
|
||||
|
||||
get hasVersion() {
|
||||
if (!this.blockVersions || !this.pageVersion || !this.workspaceVersion) {
|
||||
return false;
|
||||
}
|
||||
return Object.keys(this.blockVersions).length > 0;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this._proxy.name;
|
||||
}
|
||||
|
||||
get pageVersion() {
|
||||
return this._proxy.pageVersion;
|
||||
}
|
||||
|
||||
get properties(): DocsPropertiesMeta {
|
||||
const meta = this._proxy.properties;
|
||||
if (!meta) {
|
||||
@@ -110,10 +88,6 @@ export class TestMeta implements WorkspaceMeta {
|
||||
return meta;
|
||||
}
|
||||
|
||||
get workspaceVersion() {
|
||||
return this._proxy.workspaceVersion;
|
||||
}
|
||||
|
||||
get yDocs() {
|
||||
return this._yMap.get('pages') as unknown as Y.Array<unknown>;
|
||||
}
|
||||
@@ -232,33 +206,4 @@ export class TestMeta implements WorkspaceMeta {
|
||||
this._proxy.properties = meta;
|
||||
this.docMetaUpdated.emit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal Only for doc initialization
|
||||
*/
|
||||
writeVersion(collection: Workspace) {
|
||||
const { blockVersions, pageVersion, workspaceVersion } = this._proxy;
|
||||
|
||||
if (!workspaceVersion) {
|
||||
this._proxy.workspaceVersion = COLLECTION_VERSION;
|
||||
} else {
|
||||
console.error('Workspace version is already set');
|
||||
}
|
||||
|
||||
if (!pageVersion) {
|
||||
this._proxy.pageVersion = PAGE_VERSION;
|
||||
} else {
|
||||
console.error('Doc version is already set');
|
||||
}
|
||||
|
||||
if (!blockVersions) {
|
||||
const _versions: Record<string, number> = {};
|
||||
collection.schema.flavourSchemaMap.forEach((schema, flavour) => {
|
||||
_versions[flavour] = schema.version;
|
||||
});
|
||||
this._proxy.blockVersions = _versions;
|
||||
} else {
|
||||
console.error('Block versions is already set');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,14 +21,12 @@ import type {
|
||||
Workspace,
|
||||
WorkspaceMeta,
|
||||
} from '../model/index.js';
|
||||
import type { Schema } from '../schema/index.js';
|
||||
import { type IdGenerator, nanoid } from '../utils/id-generator.js';
|
||||
import { AwarenessStore } from '../yjs/index.js';
|
||||
import { TestDoc } from './test-doc.js';
|
||||
import { TestMeta } from './test-meta.js';
|
||||
|
||||
export type DocCollectionOptions = {
|
||||
schema: Schema;
|
||||
id?: string;
|
||||
idGenerator?: IdGenerator;
|
||||
docSources?: {
|
||||
@@ -47,8 +45,6 @@ export type DocCollectionOptions = {
|
||||
* Do not use this in production
|
||||
*/
|
||||
export class TestWorkspace implements Workspace {
|
||||
protected readonly _schema: Schema;
|
||||
|
||||
storeExtensions: ExtensionType[] = [];
|
||||
|
||||
readonly awarenessStore: AwarenessStore;
|
||||
@@ -79,13 +75,8 @@ export class TestWorkspace implements Workspace {
|
||||
return this.blockCollections;
|
||||
}
|
||||
|
||||
get schema() {
|
||||
return this._schema;
|
||||
}
|
||||
|
||||
constructor({
|
||||
id,
|
||||
schema,
|
||||
idGenerator,
|
||||
awarenessSources = [],
|
||||
docSources = {
|
||||
@@ -94,9 +85,7 @@ export class TestWorkspace implements Workspace {
|
||||
blobSources = {
|
||||
main: new MemoryBlobSource(),
|
||||
},
|
||||
}: DocCollectionOptions) {
|
||||
this._schema = schema;
|
||||
|
||||
}: DocCollectionOptions = {}) {
|
||||
this.id = id || '';
|
||||
this.doc = new Y.Doc({ guid: id });
|
||||
this.awarenessStore = new AwarenessStore(new Awareness(this.doc));
|
||||
@@ -165,7 +154,12 @@ export class TestWorkspace implements Workspace {
|
||||
* will be created in the doc simultaneously.
|
||||
*/
|
||||
createDoc(options: CreateBlocksOptions = {}) {
|
||||
const { id: docId = this.idGenerator(), query, readonly } = options;
|
||||
const {
|
||||
id: docId = this.idGenerator(),
|
||||
query,
|
||||
readonly,
|
||||
extensions,
|
||||
} = options;
|
||||
if (this._hasDoc(docId)) {
|
||||
throw new BlockSuiteError(
|
||||
ErrorCode.DocCollectionError,
|
||||
@@ -184,6 +178,7 @@ export class TestWorkspace implements Workspace {
|
||||
id: docId,
|
||||
query,
|
||||
readonly,
|
||||
extensions,
|
||||
}) as Store;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { type SurfaceBlockModel, ZipTransformer } from '@blocksuite/blocks';
|
||||
import {
|
||||
AffineSchemas,
|
||||
type SurfaceBlockModel,
|
||||
ZipTransformer,
|
||||
} from '@blocksuite/blocks';
|
||||
import type { PointLocation } from '@blocksuite/global/utils';
|
||||
import { Schema } from '@blocksuite/store';
|
||||
import { beforeEach, expect, test } from 'vitest';
|
||||
|
||||
import { wait } from '../utils/common.js';
|
||||
@@ -25,6 +30,8 @@ const skipFields = new Set(['_lastXYWH']);
|
||||
|
||||
const snapshotTest = async (snapshotUrl: string, elementsCount: number) => {
|
||||
const transformer = ZipTransformer;
|
||||
const schema = new Schema();
|
||||
schema.register(AffineSchemas);
|
||||
|
||||
const snapshotFile = await fetch(snapshotUrl)
|
||||
.then(res => res.blob())
|
||||
@@ -32,8 +39,10 @@ const snapshotTest = async (snapshotUrl: string, elementsCount: number) => {
|
||||
console.error(e);
|
||||
throw e;
|
||||
});
|
||||
|
||||
const [newDoc] = await transformer.importDocs(
|
||||
window.editor.doc.workspace,
|
||||
schema,
|
||||
snapshotFile
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { replaceIdMiddleware } from '@blocksuite/blocks';
|
||||
import { AffineSchemas, replaceIdMiddleware } from '@blocksuite/blocks';
|
||||
import {
|
||||
type DocSnapshot,
|
||||
Schema,
|
||||
Transformer,
|
||||
type Workspace,
|
||||
} from '@blocksuite/store';
|
||||
@@ -10,7 +11,7 @@ export async function importFromSnapshot(
|
||||
snapshot: DocSnapshot
|
||||
) {
|
||||
const job = new Transformer({
|
||||
schema: collection.schema,
|
||||
schema: new Schema().register(AffineSchemas),
|
||||
blobCRUD: collection.blobSync,
|
||||
docCRUD: {
|
||||
create: (id: string) => collection.createDoc({ id }),
|
||||
|
||||
@@ -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 }),
|
||||
|
||||
@@ -66,33 +66,6 @@ export const defaultStore = {
|
||||
tags: [],
|
||||
},
|
||||
],
|
||||
blockVersions: {
|
||||
'affine:paragraph': 1,
|
||||
'affine:page': 2,
|
||||
'affine:database': 3,
|
||||
'affine:data-view': 1,
|
||||
'affine:list': 1,
|
||||
'affine:note': 1,
|
||||
'affine:divider': 1,
|
||||
'affine:embed-youtube': 1,
|
||||
'affine:embed-figma': 1,
|
||||
'affine:embed-github': 1,
|
||||
'affine:embed-loom': 1,
|
||||
'affine:embed-html': 1,
|
||||
'affine:embed-linked-doc': 1,
|
||||
'affine:embed-synced-doc': 1,
|
||||
'affine:image': 1,
|
||||
'affine:latex': 1,
|
||||
'affine:frame': 1,
|
||||
'affine:code': 1,
|
||||
'affine:surface': 5,
|
||||
'affine:bookmark': 1,
|
||||
'affine:attachment': 1,
|
||||
'affine:surface-ref': 1,
|
||||
'affine:edgeless-text': 1,
|
||||
},
|
||||
workspaceVersion: 2,
|
||||
pageVersion: 2,
|
||||
},
|
||||
spaces: {
|
||||
'doc:home': {
|
||||
|
||||
Reference in New Issue
Block a user