diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/html.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/html.ts index be2275268a46b..ef8221d5da6a7 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/html.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/html.ts @@ -27,7 +27,7 @@ export const embedSyncedDocBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher = { if (type === 'content') { const syncedDocId = o.node.props.pageId as string; - const syncedDoc = job.collection.getDoc(syncedDocId); + const syncedDoc = job.docCRUD.get(syncedDocId); walkerContext.setGlobalContext('hast:html-root-doc', false); if (!syncedDoc) return; diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/markdown.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/markdown.ts index 4cea3df2d60c6..ad2c97be5d223 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/markdown.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/markdown.ts @@ -29,7 +29,7 @@ export const embedSyncedDocBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatc if (type === 'content') { const syncedDocId = o.node.props.pageId as string; - const syncedDoc = job.collection.getDoc(syncedDocId); + const syncedDoc = job.docCRUD.get(syncedDocId); if (!syncedDoc) return; if (counter === 1) { diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/plain-text.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/plain-text.ts index 287a14add9735..378c8bc7dc520 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/plain-text.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/adapters/plain-text.ts @@ -31,7 +31,7 @@ export const embedSyncedDocBlockPlainTextAdapterMatcher: BlockPlainTextAdapterMa if (type === 'content') { const syncedDocId = o.node.props.pageId as string; - const syncedDoc = job.collection.getDoc(syncedDocId); + const syncedDoc = job.docCRUD.get(syncedDocId); if (!syncedDoc) return; if (counter === 1) { diff --git a/blocksuite/affine/shared/src/services/drag-handle-config.ts b/blocksuite/affine/shared/src/services/drag-handle-config.ts index 7dcb2d4b63e14..0a4d0669ab5e7 100644 --- a/blocksuite/affine/shared/src/services/drag-handle-config.ts +++ b/blocksuite/affine/shared/src/services/drag-handle-config.ts @@ -4,7 +4,7 @@ import { StdIdentifier, } from '@blocksuite/block-std'; import { type Container, createIdentifier } from '@blocksuite/global/di'; -import { Job, Slice, type SliceSnapshot } from '@blocksuite/store'; +import { Slice, type SliceSnapshot } from '@blocksuite/store'; export const DndApiExtensionIdentifier = createIdentifier( 'AffineDndApiIdentifier' @@ -40,7 +40,7 @@ export class DNDAPIExtension extends Extension { const { docId, flavour = 'affine:embed-linked-doc', blockId } = options; const slice = Slice.fromModels(this.std.doc, []); - const job = new Job({ collection: this.std.collection }); + const job = this.std.getJob(); const snapshot = job.sliceToSnapshot(slice); if (!snapshot) { console.error('Failed to convert slice to snapshot'); diff --git a/blocksuite/affine/widget-drag-handle/src/middleware/new-id-cross-doc.ts b/blocksuite/affine/widget-drag-handle/src/middleware/new-id-cross-doc.ts index bbb92fa1741bf..0cb2dc564652e 100644 --- a/blocksuite/affine/widget-drag-handle/src/middleware/new-id-cross-doc.ts +++ b/blocksuite/affine/widget-drag-handle/src/middleware/new-id-cross-doc.ts @@ -3,14 +3,14 @@ import type { JobMiddleware } from '@blocksuite/store'; export const newIdCrossDoc = (std: BlockStdScope): JobMiddleware => - ({ slots, collection }) => { + ({ slots }) => { let samePage = false; slots.beforeImport.on(payload => { if (payload.type === 'slice') { samePage = payload.snapshot.pageId === std.doc.id; } if (payload.type === 'block' && !samePage) { - payload.snapshot.id = collection.idGenerator(); + payload.snapshot.id = std.collection.idGenerator(); } }); }; diff --git a/blocksuite/affine/widget-drag-handle/src/middleware/surface-ref-to-embed.ts b/blocksuite/affine/widget-drag-handle/src/middleware/surface-ref-to-embed.ts index 7f1784794ba31..3ffb436b6e0c7 100644 --- a/blocksuite/affine/widget-drag-handle/src/middleware/surface-ref-to-embed.ts +++ b/blocksuite/affine/widget-drag-handle/src/middleware/surface-ref-to-embed.ts @@ -3,7 +3,7 @@ import type { JobMiddleware } from '@blocksuite/store'; export const surfaceRefToEmbed = (std: BlockStdScope): JobMiddleware => - ({ slots, collection }) => { + ({ slots }) => { let pageId: string | null = null; slots.beforeImport.on(payload => { if (payload.type === 'slice') { @@ -18,7 +18,7 @@ export const surfaceRefToEmbed = !std.doc.hasBlock(payload.snapshot.id) ) { const id = payload.snapshot.id; - payload.snapshot.id = collection.idGenerator(); + payload.snapshot.id = std.collection.idGenerator(); payload.snapshot.flavour = 'affine:embed-linked-doc'; payload.snapshot.props = { blockId: id, diff --git a/blocksuite/affine/widget-drag-handle/src/watchers/drag-event-watcher.ts b/blocksuite/affine/widget-drag-handle/src/watchers/drag-event-watcher.ts index 9f91ad68d6d9e..8f8f1ee1e2117 100644 --- a/blocksuite/affine/widget-drag-handle/src/watchers/drag-event-watcher.ts +++ b/blocksuite/affine/widget-drag-handle/src/watchers/drag-event-watcher.ts @@ -30,7 +30,7 @@ import { } from '@blocksuite/block-std'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; import { Bound, Point } from '@blocksuite/global/utils'; -import { Job, Slice, type SliceSnapshot } from '@blocksuite/store'; +import { Slice, type SliceSnapshot } from '@blocksuite/store'; import { DropIndicator } from '../components/drop-indicator.js'; import { AFFINE_DRAG_HANDLE_WIDGET } from '../consts.js'; @@ -544,14 +544,11 @@ export class DragEventWatcher { private _getJob() { const std = this._std; - return new Job({ - collection: std.collection, - middlewares: [ - newIdCrossDoc(std), - reorderList(std), - surfaceRefToEmbed(std), - ], - }); + return std.getJob([ + newIdCrossDoc(std), + reorderList(std), + surfaceRefToEmbed(std), + ]); } private _serializeData(slice: Slice, state: DndEventState) { diff --git a/blocksuite/blocks/src/__tests__/utils/create-job.ts b/blocksuite/blocks/src/__tests__/utils/create-job.ts index 1a029d2e97d9c..032dc178d3fcf 100644 --- a/blocksuite/blocks/src/__tests__/utils/create-job.ts +++ b/blocksuite/blocks/src/__tests__/utils/create-job.ts @@ -27,5 +27,14 @@ export function createJob(middlewares?: JobMiddleware[]) { const schema = new Schema().register(AffineSchemas); const docCollection = new DocCollection({ schema }); docCollection.meta.initialize(); - return new Job({ collection: docCollection, middlewares: testMiddlewares }); + return new Job({ + schema, + blobCRUD: docCollection.blobSync, + middlewares: testMiddlewares, + docCRUD: { + create: (id: string) => docCollection.createDoc({ id }), + get: (id: string) => docCollection.getDoc(id), + delete: (id: string) => docCollection.removeDoc(id), + }, + }); } diff --git a/blocksuite/blocks/src/_common/transformers/html.ts b/blocksuite/blocks/src/_common/transformers/html.ts index 135c989c222b5..38ce650d2811b 100644 --- a/blocksuite/blocks/src/_common/transformers/html.ts +++ b/blocksuite/blocks/src/_common/transformers/html.ts @@ -45,8 +45,17 @@ const provider = container.provider(); */ async function exportDoc(doc: Doc) { const job = new Job({ - collection: doc.collection, - middlewares: [docLinkBaseURLMiddleware, titleMiddleware], + schema: doc.schema, + blobCRUD: doc.blobSync, + docCRUD: { + create: (id: string) => doc.collection.createDoc({ id }), + get: (id: string) => doc.collection.getDoc(id), + delete: (id: string) => doc.collection.removeDoc(id), + }, + middlewares: [ + docLinkBaseURLMiddleware(doc.collection.id), + titleMiddleware(doc.collection.meta.docMetas), + ], }); const snapshot = job.docToSnapshot(doc); const adapter = new HtmlAdapter(job, provider); @@ -91,11 +100,17 @@ async function importHTMLToDoc({ fileName, }: ImportHTMLToDocOptions) { const job = new Job({ - collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares: [ defaultImageProxyMiddleware, fileNameMiddleware(fileName), - docLinkBaseURLMiddleware, + docLinkBaseURLMiddleware(collection.id), ], }); const htmlAdapter = new HtmlAdapter(job, provider); @@ -147,11 +162,17 @@ async function importHTMLZip({ collection, imported }: ImportHTMLZipOptions) { htmlBlobs.map(async ([fileName, blob]) => { const fileNameWithoutExt = fileName.replace(/\.[^/.]+$/, ''); const job = new Job({ - collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares: [ defaultImageProxyMiddleware, fileNameMiddleware(fileNameWithoutExt), - docLinkBaseURLMiddleware, + docLinkBaseURLMiddleware(collection.id), ], }); const assets = job.assets; diff --git a/blocksuite/blocks/src/_common/transformers/markdown.ts b/blocksuite/blocks/src/_common/transformers/markdown.ts index a304f912605bc..60e86114333c6 100644 --- a/blocksuite/blocks/src/_common/transformers/markdown.ts +++ b/blocksuite/blocks/src/_common/transformers/markdown.ts @@ -51,8 +51,17 @@ type ImportMarkdownZipOptions = { */ async function exportDoc(doc: Doc) { const job = new Job({ - collection: doc.collection, - middlewares: [docLinkBaseURLMiddleware, titleMiddleware], + schema: doc.schema, + blobCRUD: doc.blobSync, + docCRUD: { + create: (id: string) => doc.collection.createDoc({ id }), + get: (id: string) => doc.collection.getDoc(id), + delete: (id: string) => doc.collection.removeDoc(id), + }, + middlewares: [ + docLinkBaseURLMiddleware(doc.collection.id), + titleMiddleware(doc.collection.meta.docMetas), + ], }); const snapshot = job.docToSnapshot(doc); @@ -101,8 +110,17 @@ async function importMarkdownToBlock({ blockId, }: ImportMarkdownToBlockOptions) { const job = new Job({ - collection: doc.collection, - middlewares: [defaultImageProxyMiddleware, docLinkBaseURLMiddleware], + schema: doc.schema, + blobCRUD: doc.blobSync, + docCRUD: { + create: (id: string) => doc.collection.createDoc({ id }), + get: (id: string) => doc.collection.getDoc(id), + delete: (id: string) => doc.collection.removeDoc(id), + }, + middlewares: [ + defaultImageProxyMiddleware, + docLinkBaseURLMiddleware(doc.collection.id), + ], }); const adapter = new MarkdownAdapter(job, provider); const snapshot = await adapter.toSliceSnapshot({ @@ -137,11 +155,17 @@ async function importMarkdownToDoc({ fileName, }: ImportMarkdownToDocOptions) { const job = new Job({ - collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares: [ defaultImageProxyMiddleware, fileNameMiddleware(fileName), - docLinkBaseURLMiddleware, + docLinkBaseURLMiddleware(collection.id), ], }); const mdAdapter = new MarkdownAdapter(job, provider); @@ -195,11 +219,17 @@ async function importMarkdownZip({ markdownBlobs.map(async ([fileName, blob]) => { const fileNameWithoutExt = fileName.replace(/\.[^/.]+$/, ''); const job = new Job({ - collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares: [ defaultImageProxyMiddleware, fileNameMiddleware(fileNameWithoutExt), - docLinkBaseURLMiddleware, + docLinkBaseURLMiddleware(collection.id), ], }); const assets = job.assets; diff --git a/blocksuite/blocks/src/_common/transformers/middlewares.ts b/blocksuite/blocks/src/_common/transformers/middlewares.ts index 6486c8f7a7293..fd538b3447602 100644 --- a/blocksuite/blocks/src/_common/transformers/middlewares.ts +++ b/blocksuite/blocks/src/_common/transformers/middlewares.ts @@ -8,193 +8,197 @@ import type { } from '@blocksuite/affine-model'; import { DEFAULT_IMAGE_PROXY_ENDPOINT } from '@blocksuite/affine-shared/consts'; import { assertExists } from '@blocksuite/global/utils'; -import type { DeltaOperation, JobMiddleware } from '@blocksuite/store'; +import type { DeltaOperation, DocMeta, JobMiddleware } from '@blocksuite/store'; -export const replaceIdMiddleware: JobMiddleware = ({ slots, collection }) => { - const idMap = new Map(); - slots.afterImport.on(payload => { - if ( - payload.type === 'block' && - payload.snapshot.flavour === 'affine:database' - ) { - const model = payload.model as DatabaseBlockModel; - Object.keys(model.cells).forEach(cellId => { - if (idMap.has(cellId)) { - model.cells[idMap.get(cellId)!] = model.cells[cellId]; - delete model.cells[cellId]; - } - }); - } - - // replace LinkedPage pageId with new id in paragraph blocks - if ( - payload.type === 'block' && - ['affine:list', 'affine:paragraph'].includes(payload.snapshot.flavour) - ) { - const model = payload.model as ParagraphBlockModel | ListBlockModel; - let prev = 0; - const delta: DeltaOperation[] = []; - for (const d of model.text.toDelta()) { - if (d.attributes?.reference?.pageId) { - const newId = idMap.get(d.attributes.reference.pageId); - if (!newId) { - prev += d.insert?.length ?? 0; - continue; +export const replaceIdMiddleware = + (idGenerator: () => string): JobMiddleware => + ({ slots, docCRUD }) => { + const idMap = new Map(); + slots.afterImport.on(payload => { + if ( + payload.type === 'block' && + payload.snapshot.flavour === 'affine:database' + ) { + const model = payload.model as DatabaseBlockModel; + Object.keys(model.cells).forEach(cellId => { + if (idMap.has(cellId)) { + model.cells[idMap.get(cellId)!] = model.cells[cellId]; + delete model.cells[cellId]; } + }); + } - if (prev > 0) { - delta.push({ retain: prev }); - } + // replace LinkedPage pageId with new id in paragraph blocks + if ( + payload.type === 'block' && + ['affine:list', 'affine:paragraph'].includes(payload.snapshot.flavour) + ) { + const model = payload.model as ParagraphBlockModel | ListBlockModel; + let prev = 0; + const delta: DeltaOperation[] = []; + for (const d of model.text.toDelta()) { + if (d.attributes?.reference?.pageId) { + const newId = idMap.get(d.attributes.reference.pageId); + if (!newId) { + prev += d.insert?.length ?? 0; + continue; + } + + if (prev > 0) { + delta.push({ retain: prev }); + } - delta.push({ - retain: d.insert?.length ?? 0, - attributes: { - reference: { - ...d.attributes.reference, - pageId: newId, + delta.push({ + retain: d.insert?.length ?? 0, + attributes: { + reference: { + ...d.attributes.reference, + pageId: newId, + }, }, - }, - }); - prev = 0; - } else { - prev += d.insert?.length ?? 0; + }); + prev = 0; + } else { + prev += d.insert?.length ?? 0; + } + } + if (delta.length > 0) { + model.text.applyDelta(delta); } } - if (delta.length > 0) { - model.text.applyDelta(delta); - } - } - if ( - payload.type === 'block' && - payload.snapshot.flavour === 'affine:surface-ref' - ) { - const model = payload.model as SurfaceRefBlockModel; - const original = model.reference; - // If there exists a replacement, replace the reference with the new id. - // Otherwise, - // 1. If the reference is an affine:frame not in doc, generate a new id. - // 2. If the reference is graph, keep the original id. - if (idMap.has(original)) { - model.reference = idMap.get(original)!; - } else if ( - model.refFlavour === 'affine:frame' && - !model.doc.hasBlock(original) + if ( + payload.type === 'block' && + payload.snapshot.flavour === 'affine:surface-ref' ) { - const newId = collection.idGenerator(); - idMap.set(original, newId); - model.reference = newId; - } - } - - // TODO(@fundon): process linked block/element - if ( - payload.type === 'block' && - ['affine:embed-linked-doc', 'affine:embed-synced-doc'].includes( - payload.snapshot.flavour - ) - ) { - const model = payload.model as EmbedLinkedDocModel | EmbedSyncedDocModel; - const original = model.pageId; - // If the pageId is not in the doc, generate a new id. - // If we already have a replacement, use it. - if (!collection.getDoc(original)) { + const model = payload.model as SurfaceRefBlockModel; + const original = model.reference; + // If there exists a replacement, replace the reference with the new id. + // Otherwise, + // 1. If the reference is an affine:frame not in doc, generate a new id. + // 2. If the reference is graph, keep the original id. if (idMap.has(original)) { - model.pageId = idMap.get(original)!; - } else { - const newId = collection.idGenerator(); + model.reference = idMap.get(original)!; + } else if ( + model.refFlavour === 'affine:frame' && + !model.doc.hasBlock(original) + ) { + const newId = idGenerator(); idMap.set(original, newId); - model.pageId = newId; + model.reference = newId; } } - } - }); - slots.beforeImport.on(payload => { - if (payload.type === 'page') { - if (idMap.has(payload.snapshot.meta.id)) { - payload.snapshot.meta.id = idMap.get(payload.snapshot.meta.id)!; - return; - } - const newId = collection.idGenerator(); - idMap.set(payload.snapshot.meta.id, newId); - payload.snapshot.meta.id = newId; - return; - } - if (payload.type === 'block') { - const { snapshot } = payload; - if (snapshot.flavour === 'affine:page') { - const index = snapshot.children.findIndex( - c => c.flavour === 'affine:surface' - ); - if (index !== -1) { - const [surface] = snapshot.children.splice(index, 1); - snapshot.children.push(surface); + // TODO(@fundon): process linked block/element + if ( + payload.type === 'block' && + ['affine:embed-linked-doc', 'affine:embed-synced-doc'].includes( + payload.snapshot.flavour + ) + ) { + const model = payload.model as + | EmbedLinkedDocModel + | EmbedSyncedDocModel; + const original = model.pageId; + // If the pageId is not in the doc, generate a new id. + // If we already have a replacement, use it. + if (!docCRUD.get(original)) { + if (idMap.has(original)) { + model.pageId = idMap.get(original)!; + } else { + const newId = idGenerator(); + idMap.set(original, newId); + model.pageId = newId; + } } } - - const original = snapshot.id; - let newId: string; - if (idMap.has(original)) { - newId = idMap.get(original)!; - } else { - newId = collection.idGenerator(); - idMap.set(original, newId); + }); + slots.beforeImport.on(payload => { + if (payload.type === 'page') { + if (idMap.has(payload.snapshot.meta.id)) { + payload.snapshot.meta.id = idMap.get(payload.snapshot.meta.id)!; + return; + } + const newId = idGenerator(); + idMap.set(payload.snapshot.meta.id, newId); + payload.snapshot.meta.id = newId; + return; } - snapshot.id = newId; - if (snapshot.flavour === 'affine:surface') { - // Generate new IDs for images and frames in advance. - snapshot.children.forEach(child => { - const original = child.id; - if (idMap.has(original)) { - newId = idMap.get(original)!; - } else { - newId = collection.idGenerator(); - idMap.set(original, newId); + if (payload.type === 'block') { + const { snapshot } = payload; + if (snapshot.flavour === 'affine:page') { + const index = snapshot.children.findIndex( + c => c.flavour === 'affine:surface' + ); + if (index !== -1) { + const [surface] = snapshot.children.splice(index, 1); + snapshot.children.push(surface); } - }); + } - Object.entries( - snapshot.props.elements as Record> - ).forEach(([_, value]) => { - switch (value.type) { - case 'connector': { - let connection = value.source as Record; - if (idMap.has(connection.id)) { - const newId = idMap.get(connection.id); - assertExists(newId, 'reference id must exist'); - connection.id = newId; - } - connection = value.target as Record; - if (idMap.has(connection.id)) { - const newId = idMap.get(connection.id); - assertExists(newId, 'reference id must exist'); - connection.id = newId; - } - break; + const original = snapshot.id; + let newId: string; + if (idMap.has(original)) { + newId = idMap.get(original)!; + } else { + newId = idGenerator(); + idMap.set(original, newId); + } + snapshot.id = newId; + + if (snapshot.flavour === 'affine:surface') { + // Generate new IDs for images and frames in advance. + snapshot.children.forEach(child => { + const original = child.id; + if (idMap.has(original)) { + newId = idMap.get(original)!; + } else { + newId = idGenerator(); + idMap.set(original, newId); } - case 'group': { - const json = (value.children as Record) - .json as Record; - Object.entries(json).forEach(([key, value]) => { - if (idMap.has(key)) { - delete json[key]; - const newKey = idMap.get(key); - assertExists(newKey, 'reference id must exist'); - json[newKey] = value; + }); + + Object.entries( + snapshot.props.elements as Record> + ).forEach(([_, value]) => { + switch (value.type) { + case 'connector': { + let connection = value.source as Record; + if (idMap.has(connection.id)) { + const newId = idMap.get(connection.id); + assertExists(newId, 'reference id must exist'); + connection.id = newId; + } + connection = value.target as Record; + if (idMap.has(connection.id)) { + const newId = idMap.get(connection.id); + assertExists(newId, 'reference id must exist'); + connection.id = newId; } - }); - break; + break; + } + case 'group': { + const json = (value.children as Record) + .json as Record; + Object.entries(json).forEach(([key, value]) => { + if (idMap.has(key)) { + delete json[key]; + const newKey = idMap.get(key); + assertExists(newKey, 'reference id must exist'); + json[newKey] = value; + } + }); + break; + } + default: + break; } - default: - break; - } - }); + }); + } } - } - }); -}; + }); + }; export const customImageProxyMiddleware = ( imageProxyURL: string @@ -204,46 +208,52 @@ export const customImageProxyMiddleware = ( }; }; -const customDocLinkBaseUrlMiddleware = (baseUrl: string): JobMiddleware => { - return ({ adapterConfigs, collection }) => { +const customDocLinkBaseUrlMiddleware = ( + baseUrl: string, + collectionId: string +): JobMiddleware => { + return ({ adapterConfigs }) => { const docLinkBaseUrl = baseUrl - ? `${baseUrl}/workspace/${collection.id}` + ? `${baseUrl}/workspace/${collectionId}` : ''; adapterConfigs.set('docLinkBaseUrl', docLinkBaseUrl); }; }; -export const titleMiddleware: JobMiddleware = ({ - slots, - collection, - adapterConfigs, -}) => { - slots.beforeExport.on(() => { - for (const meta of collection.meta.docMetas) { - adapterConfigs.set('title:' + meta.id, meta.title); - } - }); -}; +export const titleMiddleware = + (metas: DocMeta[]): JobMiddleware => + ({ slots, adapterConfigs }) => { + slots.beforeExport.on(() => { + for (const meta of metas) { + adapterConfigs.set('title:' + meta.id, meta.title); + } + }); + }; -export const docLinkBaseURLMiddlewareBuilder = (baseUrl: string) => { - let middleware = customDocLinkBaseUrlMiddleware(baseUrl); +export const docLinkBaseURLMiddlewareBuilder = ( + baseUrl: string, + collectionId: string +) => { + let middleware = customDocLinkBaseUrlMiddleware(baseUrl, collectionId); return { get: () => middleware, set: (url: string) => { - middleware = customDocLinkBaseUrlMiddleware(url); + middleware = customDocLinkBaseUrlMiddleware(url, collectionId); }, }; }; -const defaultDocLinkBaseURLMiddlewareBuilder = docLinkBaseURLMiddlewareBuilder( - typeof window !== 'undefined' ? window.location.origin : '.' -); +const defaultDocLinkBaseURLMiddlewareBuilder = (collectionId: string) => + docLinkBaseURLMiddlewareBuilder( + typeof window !== 'undefined' ? window.location.origin : '.', + collectionId + ); -export const docLinkBaseURLMiddleware = - defaultDocLinkBaseURLMiddlewareBuilder.get(); +export const docLinkBaseURLMiddleware = (collectionId: string) => + defaultDocLinkBaseURLMiddlewareBuilder(collectionId).get(); -export const setDocLinkBaseURLMiddleware = - defaultDocLinkBaseURLMiddlewareBuilder.set; +export const setDocLinkBaseURLMiddleware = (collectionId: string) => + defaultDocLinkBaseURLMiddlewareBuilder(collectionId).set; const imageProxyMiddlewareBuilder = () => { let middleware = customImageProxyMiddleware(DEFAULT_IMAGE_PROXY_ENDPOINT); diff --git a/blocksuite/blocks/src/_common/transformers/notion-html.ts b/blocksuite/blocks/src/_common/transformers/notion-html.ts index c4cb0f7972ad2..fbb5bcd98b8da 100644 --- a/blocksuite/blocks/src/_common/transformers/notion-html.ts +++ b/blocksuite/blocks/src/_common/transformers/notion-html.ts @@ -119,7 +119,13 @@ async function importNotionZip({ } const pagePromises = Array.from(pagePaths).map(async path => { const job = new Job({ - collection: collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares: [defaultImageProxyMiddleware], }); const htmlAdapter = new NotionHtmlAdapter(job, provider); diff --git a/blocksuite/blocks/src/_common/transformers/zip.ts b/blocksuite/blocks/src/_common/transformers/zip.ts index d6c5e72e6ebe7..913548b839d05 100644 --- a/blocksuite/blocks/src/_common/transformers/zip.ts +++ b/blocksuite/blocks/src/_common/transformers/zip.ts @@ -7,12 +7,21 @@ import { replaceIdMiddleware, titleMiddleware } from './middlewares.js'; async function exportDocs(collection: DocCollection, docs: Doc[]) { const zip = new Zip(); - const job = new Job({ collection }); + const job = new Job({ + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, + middlewares: [ + replaceIdMiddleware(collection.idGenerator), + titleMiddleware(collection.meta.docMetas), + ], + }); const snapshots = await Promise.all(docs.map(job.docToSnapshot)); - const collectionInfo = job.collectionInfoToSnapshot(); - await zip.file('info.json', JSON.stringify(collectionInfo, null, 2)); - await Promise.all( snapshots .filter((snapshot): snapshot is DocSnapshot => !!snapshot) @@ -69,8 +78,17 @@ async function importDocs(collection: DocCollection, imported: Blob) { } const job = new Job({ - collection, - middlewares: [replaceIdMiddleware, titleMiddleware], + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, + middlewares: [ + replaceIdMiddleware(collection.idGenerator), + titleMiddleware(collection.meta.docMetas), + ], }); const assetsMap = job.assets; diff --git a/blocksuite/blocks/src/root-block/clipboard/index.ts b/blocksuite/blocks/src/root-block/clipboard/index.ts index b609581cb1c9e..c9e84e41dba01 100644 --- a/blocksuite/blocks/src/root-block/clipboard/index.ts +++ b/blocksuite/blocks/src/root-block/clipboard/index.ts @@ -59,8 +59,12 @@ export class PageClipboard { const paste = pasteMiddleware(this._std); this._std.clipboard.use(copy); this._std.clipboard.use(paste); - this._std.clipboard.use(replaceIdMiddleware); - this._std.clipboard.use(titleMiddleware); + this._std.clipboard.use( + replaceIdMiddleware(this._std.doc.collection.idGenerator) + ); + this._std.clipboard.use( + titleMiddleware(this._std.doc.collection.meta.docMetas) + ); this._std.clipboard.use(defaultImageProxyMiddleware); this._disposables.add({ @@ -80,8 +84,12 @@ export class PageClipboard { this._std.clipboard.unregisterAdapter('*/*'); this._std.clipboard.unuse(copy); this._std.clipboard.unuse(paste); - this._std.clipboard.unuse(replaceIdMiddleware); - this._std.clipboard.unuse(titleMiddleware); + this._std.clipboard.unuse( + replaceIdMiddleware(this._std.doc.collection.idGenerator) + ); + this._std.clipboard.unuse( + titleMiddleware(this._std.doc.collection.meta.docMetas) + ); this._std.clipboard.unuse(defaultImageProxyMiddleware); }, }); diff --git a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts index 0c8ad53712246..78cadd84faa82 100644 --- a/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts +++ b/blocksuite/blocks/src/root-block/edgeless/clipboard/clipboard.ts @@ -369,7 +369,15 @@ export class EdgelessClipboardController extends PageClipboard { if (mayBeSurfaceDataJson !== undefined) { const elementsRawData = JSON.parse(mayBeSurfaceDataJson); const { snapshot, blobs } = elementsRawData; - const job = new Job({ collection: this.std.collection }); + const job = new Job({ + schema: this.std.collection.schema, + blobCRUD: this.std.collection.blobSync, + docCRUD: { + create: (id: string) => this.std.collection.createDoc({ id }), + get: (id: string) => this.std.collection.getDoc(id), + delete: (id: string) => this.std.collection.removeDoc(id), + }, + }); const map = job.assetsManager.getAssets(); decodeClipboardBlobs(blobs, map); for (const blobId of map.keys()) { @@ -1366,7 +1374,13 @@ export async function prepareClipboardData( std: BlockStdScope ) { const job = new Job({ - collection: std.collection, + schema: std.collection.schema, + blobCRUD: std.collection.blobSync, + docCRUD: { + create: (id: string) => std.collection.createDoc({ id }), + get: (id: string) => std.collection.getDoc(id), + delete: (id: string) => std.collection.removeDoc(id), + }, }); const selected = await Promise.all( selectedAll.map(async selected => { diff --git a/blocksuite/blocks/src/root-block/edgeless/services/template.ts b/blocksuite/blocks/src/root-block/edgeless/services/template.ts index 1423b594fc41e..d4332a9abc9db 100644 --- a/blocksuite/blocks/src/root-block/edgeless/services/template.ts +++ b/blocksuite/blocks/src/root-block/edgeless/services/template.ts @@ -87,7 +87,16 @@ export class TemplateJob { type: TemplateType; constructor({ model, type, middlewares }: TemplateJobConfig) { - this.job = new Job({ collection: model.doc.collection, middlewares: [] }); + this.job = new Job({ + schema: model.doc.collection.schema, + blobCRUD: model.doc.collection.blobSync, + docCRUD: { + create: (id: string) => model.doc.collection.createDoc({ id }), + get: (id: string) => model.doc.collection.getDoc(id), + delete: (id: string) => model.doc.collection.removeDoc(id), + }, + middlewares: [], + }); this.model = model; this.type = TEMPLATE_TYPES.includes(type as TemplateType) ? (type as TemplateType) diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/clone-utils.ts b/blocksuite/blocks/src/root-block/edgeless/utils/clone-utils.ts index f508016e57fe7..a99c2453c58f5 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/clone-utils.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/clone-utils.ts @@ -40,7 +40,13 @@ export function getSortedCloneElements(elements: GfxModel[]) { export function prepareCloneData(elements: GfxModel[], std: BlockStdScope) { elements = sortEdgelessElements(elements); const job = new Job({ - collection: std.collection, + schema: std.collection.schema, + blobCRUD: std.collection.blobSync, + docCRUD: { + create: (id: string) => std.collection.createDoc({ id }), + get: (id: string) => std.collection.getDoc(id), + delete: (id: string) => std.collection.removeDoc(id), + }, }); const res = elements.map(element => { const data = serializeElement(element, elements, job); diff --git a/blocksuite/blocks/src/surface-block/mini-mindmap/mindmap-preview.ts b/blocksuite/blocks/src/surface-block/mini-mindmap/mindmap-preview.ts index 28d5d9450173d..067a4af63feb2 100644 --- a/blocksuite/blocks/src/surface-block/mini-mindmap/mindmap-preview.ts +++ b/blocksuite/blocks/src/surface-block/mini-mindmap/mindmap-preview.ts @@ -247,7 +247,15 @@ export const markdownToMindmap = ( provider: ServiceProvider ) => { let result: Node | null = null; - const job = new Job({ collection: doc.collection }); + const job = new Job({ + schema: doc.collection.schema, + blobCRUD: doc.collection.blobSync, + docCRUD: { + create: (id: string) => doc.collection.createDoc({ id }), + get: (id: string) => doc.collection.getDoc(id), + delete: (id: string) => doc.collection.removeDoc(id), + }, + }); const markdown = new MarkdownAdapter(job, provider); const ast: Root = markdown['_markdownToAst'](answer); const traverse = ( diff --git a/blocksuite/framework/block-std/src/clipboard/index.ts b/blocksuite/framework/block-std/src/clipboard/index.ts index fcb8888efbb16..fefcf3b47e5f3 100644 --- a/blocksuite/framework/block-std/src/clipboard/index.ts +++ b/blocksuite/framework/block-std/src/clipboard/index.ts @@ -4,10 +4,10 @@ import type { BaseAdapter, BlockSnapshot, Doc, + Job, JobMiddleware, Slice, } from '@blocksuite/store'; -import { Job } from '@blocksuite/store'; import DOMPurify from 'dompurify'; import type { RootContentMap } from 'hast'; import * as lz from 'lz-string'; @@ -286,10 +286,7 @@ export class Clipboard extends LifeCycleWatcher { } private _getJob() { - return new Job({ - middlewares: this._jobMiddlewares, - collection: this.std.collection, - }); + return this.std.getJob(this._jobMiddlewares); } readFromClipboard(clipboardData: DataTransfer) { diff --git a/blocksuite/framework/block-std/src/scope/block-std-scope.ts b/blocksuite/framework/block-std/src/scope/block-std-scope.ts index f5cc61f8b3ab7..60e25a30eefda 100644 --- a/blocksuite/framework/block-std/src/scope/block-std-scope.ts +++ b/blocksuite/framework/block-std/src/scope/block-std-scope.ts @@ -1,7 +1,7 @@ import type { ServiceProvider } from '@blocksuite/global/di'; import { Container } from '@blocksuite/global/di'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -import type { Doc } from '@blocksuite/store'; +import { type Doc, Job, type JobMiddleware } from '@blocksuite/store'; import { Clipboard } from '../clipboard/index.js'; import { CommandManager } from '../command/index.js'; @@ -168,6 +168,19 @@ export class BlockStdScope { return this.getOptional(BlockViewIdentifier(flavour)); } + getJob(middlewares: JobMiddleware[] = []) { + return new Job({ + schema: this.collection.schema, + blobCRUD: this.collection.blobSync, + docCRUD: { + create: (id: string) => this.collection.createDoc({ id }), + get: (id: string) => this.collection.getDoc(id), + delete: (id: string) => this.collection.removeDoc(id), + }, + middlewares, + }); + } + mount() { this._lifeCycleWatchers.forEach(watcher => { watcher.mounted.call(watcher); diff --git a/blocksuite/framework/store/src/transformer/assets.ts b/blocksuite/framework/store/src/transformer/assets.ts index 0dcb50284ee9a..bff088f2bcbf0 100644 --- a/blocksuite/framework/store/src/transformer/assets.ts +++ b/blocksuite/framework/store/src/transformer/assets.ts @@ -1,11 +1,6 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; -interface BlobCRUD { - get: (key: string) => Promise | Blob | null; - set: (key: string, value: Blob) => Promise | string; - delete: (key: string) => Promise | void; - list: () => Promise | string[]; -} +import type { BlobCRUD } from './type.js'; type AssetsManagerConfig = { blob: BlobCRUD; diff --git a/blocksuite/framework/store/src/transformer/job.ts b/blocksuite/framework/store/src/transformer/job.ts index 999c2e3e358ce..5ebb2930c89d5 100644 --- a/blocksuite/framework/store/src/transformer/job.ts +++ b/blocksuite/framework/store/src/transformer/job.ts @@ -1,8 +1,8 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { nextTick, Slot } from '@blocksuite/global/utils'; -import type { BlockModel, BlockSchemaType } from '../schema/index.js'; -import type { Doc, DocCollection, DocMeta } from '../store/index.js'; +import type { BlockModel, BlockSchemaType, Schema } from '../schema/index.js'; +import type { Doc } from '../store/index.js'; import { AssetsManager } from './assets.js'; import { BaseBlockTransformer } from './base.js'; import type { DraftModel } from './draft.js'; @@ -15,20 +15,22 @@ import type { } from './middleware.js'; import { Slice } from './slice.js'; import type { + BlobCRUD, BlockSnapshot, - CollectionInfoSnapshot, + DocCRUD, DocSnapshot, SliceSnapshot, } from './type.js'; import { BlockSnapshotSchema, - CollectionInfoSnapshotSchema, DocSnapshotSchema, SliceSnapshotSchema, } from './type.js'; export type JobConfig = { - collection: DocCollection; + schema: Schema; + blobCRUD: BlobCRUD; + docCRUD: DocCRUD; middlewares?: JobMiddleware[]; }; @@ -52,7 +54,9 @@ export class Job { private readonly _assetsManager: AssetsManager; - private readonly _collection: DocCollection; + private readonly _schema: Schema; + + private readonly _docCRUD: DocCRUD; private readonly _slots: JobSlots = { beforeImport: new Slot(), @@ -74,31 +78,6 @@ export class Job { } }; - collectionInfoToSnapshot = (): CollectionInfoSnapshot | undefined => { - try { - this._slots.beforeExport.emit({ - type: 'info', - }); - const collectionMeta = this._getCollectionMeta(); - const snapshot: CollectionInfoSnapshot = { - type: 'info', - id: this._collection.id, - ...collectionMeta, - }; - this._slots.afterExport.emit({ - type: 'info', - snapshot, - }); - CollectionInfoSnapshotSchema.parse(snapshot); - - return snapshot; - } catch (error) { - console.error(`Error when transforming collection info to snapshot:`); - console.error(error); - return; - } - }; - docToSnapshot = (doc: Doc): DocSnapshot | undefined => { try { this._slots.beforeExport.emit({ @@ -199,7 +178,7 @@ export class Job { }); DocSnapshotSchema.parse(snapshot); const { meta, blocks } = snapshot; - const doc = this._collection.createDoc({ id: meta.id }); + const doc = this.docCRUD.create(meta.id); doc.load(); await this.snapshotToBlock(blocks, doc); this._slots.afterImport.emit({ @@ -328,19 +307,24 @@ export class Job { return this._assetsManager; } - get collection() { - return this._collection; + get schema() { + return this._schema; + } + + get docCRUD() { + return this._docCRUD; } - constructor({ collection, middlewares = [] }: JobConfig) { - this._collection = collection; - this._assetsManager = new AssetsManager({ blob: collection.blobSync }); + constructor({ blobCRUD, schema, docCRUD, middlewares = [] }: JobConfig) { + this._assetsManager = new AssetsManager({ blob: blobCRUD }); + this._schema = schema; + this._docCRUD = docCRUD; middlewares.forEach(middleware => { middleware({ slots: this._slots, + docCRUD: this._docCRUD, assetsManager: this._assetsManager, - collection: this._collection, adapterConfigs: this._adapterConfigs, }); }); @@ -465,20 +449,8 @@ export class Job { } } - private _getCollectionMeta() { - const { meta } = this._collection; - const { docs } = meta; - if (!docs) { - throw new BlockSuiteError(ErrorCode.TransformerError, 'Docs not found'); - } - return { - properties: {}, // for backward compatibility - pages: JSON.parse(JSON.stringify(docs)) as DocMeta[], - }; - } - private _getSchema(flavour: string) { - const schema = this._collection.schema.flavourSchemaMap.get(flavour); + const schema = this.schema.flavourSchemaMap.get(flavour); if (!schema) { throw new BlockSuiteError( ErrorCode.TransformerError, diff --git a/blocksuite/framework/store/src/transformer/middleware.ts b/blocksuite/framework/store/src/transformer/middleware.ts index e12d04b443d9c..3f6b9a310477d 100644 --- a/blocksuite/framework/store/src/transformer/middleware.ts +++ b/blocksuite/framework/store/src/transformer/middleware.ts @@ -1,12 +1,13 @@ import type { Slot } from '@blocksuite/global/utils'; -import type { Doc, DocCollection } from '../store/index.js'; +import type { Doc } from '../store/index.js'; import type { AssetsManager } from './assets.js'; import type { DraftModel } from './draft.js'; import type { Slice } from './slice.js'; import type { BlockSnapshot, CollectionInfoSnapshot, + DocCRUD, DocSnapshot, SliceSnapshot, } from './type.js'; @@ -79,9 +80,9 @@ export type JobSlots = { }; type JobMiddlewareOptions = { - collection: DocCollection; assetsManager: AssetsManager; slots: JobSlots; + docCRUD: DocCRUD; adapterConfigs: Map; }; diff --git a/blocksuite/framework/store/src/transformer/type.ts b/blocksuite/framework/store/src/transformer/type.ts index 98dba8c531161..7ece53061cf06 100644 --- a/blocksuite/framework/store/src/transformer/type.ts +++ b/blocksuite/framework/store/src/transformer/type.ts @@ -1,5 +1,6 @@ import { z } from 'zod'; +import type { Doc } from '../store/doc/doc.js'; import type { DocMeta, DocsPropertiesMeta } from '../store/meta.js'; export type BlockSnapshot = { @@ -65,3 +66,16 @@ export const DocSnapshotSchema: z.ZodType = z.object({ meta: DocMetaSchema, blocks: BlockSnapshotSchema, }); + +export interface BlobCRUD { + get: (key: string) => Promise | Blob | null; + set: (key: string, value: Blob) => Promise | string; + delete: (key: string) => Promise | void; + list: () => Promise | string[]; +} + +export interface DocCRUD { + create: (id: string) => Doc; + get: (id: string) => Doc | null; + delete: (id: string) => void; +} diff --git a/blocksuite/playground/apps/_common/components/adapters-panel.ts b/blocksuite/playground/apps/_common/components/adapters-panel.ts index 0cd29ad0ea922..4d7683ca7b081 100644 --- a/blocksuite/playground/apps/_common/components/adapters-panel.ts +++ b/blocksuite/playground/apps/_common/components/adapters-panel.ts @@ -102,10 +102,19 @@ export class AdaptersPanel extends WithDisposable(ShadowlessElement) { private _createJob() { return new Job({ - collection: this.doc.collection, + schema: this.doc.collection.schema, + blobCRUD: this.doc.collection.blobSync, + docCRUD: { + create: (id: string) => this.doc.collection.createDoc({ id }), + get: (id: string) => this.doc.collection.getDoc(id), + delete: (id: string) => this.doc.collection.removeDoc(id), + }, middlewares: [ - docLinkBaseURLMiddlewareBuilder('https://example.com').get(), - titleMiddleware, + docLinkBaseURLMiddlewareBuilder( + 'https://example.com', + this.doc.collection.id + ).get(), + titleMiddleware(this.doc.collection.meta.docMetas), embedSyncedDocMiddleware('content'), defaultImageProxyMiddleware, ], diff --git a/blocksuite/playground/apps/_common/components/starter-debug-menu.ts b/blocksuite/playground/apps/_common/components/starter-debug-menu.ts index b975418166872..3fe1688f7b1a7 100644 --- a/blocksuite/playground/apps/_common/components/starter-debug-menu.ts +++ b/blocksuite/playground/apps/_common/components/starter-debug-menu.ts @@ -242,8 +242,17 @@ export class StarterDebugMenu extends ShadowlessElement { private async _exportFile(config: AdapterConfig) { const doc = this.editor.doc; const job = new Job({ - collection: this.editor.doc.collection, - middlewares: [docLinkBaseURLMiddleware, titleMiddleware], + schema: this.collection.schema, + blobCRUD: this.collection.blobSync, + docCRUD: { + create: (id: string) => this.collection.createDoc({ id }), + get: (id: string) => this.collection.getDoc(id), + delete: (id: string) => this.collection.removeDoc(id), + }, + middlewares: [ + docLinkBaseURLMiddleware(this.collection.id), + titleMiddleware(this.collection.meta.docMetas), + ], }); const adapterFactory = this.editor.std.provider.get(config.identifier); @@ -432,7 +441,13 @@ export class StarterDebugMenu extends ShadowlessElement { }); if (!file) return; const job = new Job({ - collection: this.collection, + schema: this.collection.schema, + blobCRUD: this.collection.blobSync, + docCRUD: { + create: (id: string) => this.collection.createDoc({ id }), + get: (id: string) => this.collection.getDoc(id), + delete: (id: string) => this.collection.removeDoc(id), + }, middlewares: [defaultImageProxyMiddleware], }); const htmlAdapter = new NotionHtmlAdapter(job, this.editor.std.provider); diff --git a/blocksuite/playground/apps/default/utils/collection.ts b/blocksuite/playground/apps/default/utils/collection.ts index f1347cf424517..9fce813425ff4 100644 --- a/blocksuite/playground/apps/default/utils/collection.ts +++ b/blocksuite/playground/apps/default/utils/collection.ts @@ -84,7 +84,15 @@ export async function createDefaultDocCollection() { // debug info window.collection = collection; window.blockSchemas = AffineSchemas; - window.job = new Job({ collection }); + window.job = new Job({ + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, + }); window.Y = DocCollection.Y; return collection; diff --git a/blocksuite/playground/apps/starter/utils/collection.ts b/blocksuite/playground/apps/starter/utils/collection.ts index cdb1f84a404fa..d6769e4c4ddfb 100644 --- a/blocksuite/playground/apps/starter/utils/collection.ts +++ b/blocksuite/playground/apps/starter/utils/collection.ts @@ -83,7 +83,15 @@ export function createStarterDocCollection() { // debug info window.collection = collection; window.blockSchemas = AffineSchemas; - window.job = new Job({ collection: collection }); + window.job = new Job({ + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, + }); window.Y = DocCollection.Y; window.testUtils = new TestUtils(); diff --git a/blocksuite/presets/src/__tests__/utils/misc.ts b/blocksuite/presets/src/__tests__/utils/misc.ts index 1afba19ec4290..49e294d49e39c 100644 --- a/blocksuite/presets/src/__tests__/utils/misc.ts +++ b/blocksuite/presets/src/__tests__/utils/misc.ts @@ -6,8 +6,14 @@ export async function importFromSnapshot( snapshot: DocSnapshot ) { const job = new Job({ - collection, - middlewares: [replaceIdMiddleware], + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, + middlewares: [replaceIdMiddleware(collection.idGenerator)], }); return job.snapshotToDoc(snapshot); diff --git a/packages/frontend/apps/ios/src/app.tsx b/packages/frontend/apps/ios/src/app.tsx index c39125e7d2eda..a89c1c265c5bc 100644 --- a/packages/frontend/apps/ios/src/app.tsx +++ b/packages/frontend/apps/ios/src/app.tsx @@ -174,8 +174,17 @@ const frameworkProvider = framework.provider(); const blockSuiteDoc = doc.blockSuiteDoc; const job = new Job({ - collection: blockSuiteDoc.collection, - middlewares: [docLinkBaseURLMiddleware, titleMiddleware], + schema: blockSuiteDoc.collection.schema, + blobCRUD: blockSuiteDoc.collection.blobSync, + docCRUD: { + create: (id: string) => blockSuiteDoc.collection.createDoc({ id }), + get: (id: string) => blockSuiteDoc.collection.getDoc(id), + delete: (id: string) => blockSuiteDoc.collection.removeDoc(id), + }, + middlewares: [ + docLinkBaseURLMiddleware(blockSuiteDoc.collection.id), + titleMiddleware(blockSuiteDoc.collection.meta.docMetas), + ], }); const snapshot = job.docToSnapshot(blockSuiteDoc); diff --git a/packages/frontend/core/src/blocksuite/presets/_common/utils/markdown-utils.ts b/packages/frontend/core/src/blocksuite/presets/_common/utils/markdown-utils.ts index 5414cfbcd5e39..9a7f696a046c3 100644 --- a/packages/frontend/core/src/blocksuite/presets/_common/utils/markdown-utils.ts +++ b/packages/frontend/core/src/blocksuite/presets/_common/utils/markdown-utils.ts @@ -78,8 +78,17 @@ export async function getContentFromSlice( type: 'markdown' | 'plain-text' = 'markdown' ) { const job = new Job({ - collection: host.std.doc.collection, - middlewares: [titleMiddleware, embedSyncedDocMiddleware('content')], + schema: host.std.doc.collection.schema, + blobCRUD: host.std.doc.collection.blobSync, + docCRUD: { + create: (id: string) => host.std.doc.collection.createDoc({ id }), + get: (id: string) => host.std.doc.collection.getDoc(id), + delete: (id: string) => host.std.doc.collection.removeDoc(id), + }, + middlewares: [ + titleMiddleware(host.std.doc.collection.meta.docMetas), + embedSyncedDocMiddleware('content'), + ], }); const snapshot = job.sliceToSnapshot(slice); if (!snapshot) { @@ -99,8 +108,14 @@ export async function getContentFromSlice( export async function getPlainTextFromSlice(host: EditorHost, slice: Slice) { const job = new Job({ - collection: host.std.doc.collection, - middlewares: [titleMiddleware], + schema: host.std.doc.collection.schema, + blobCRUD: host.std.doc.collection.blobSync, + docCRUD: { + create: (id: string) => host.std.doc.collection.createDoc({ id }), + get: (id: string) => host.std.doc.collection.getDoc(id), + delete: (id: string) => host.std.doc.collection.removeDoc(id), + }, + middlewares: [titleMiddleware(host.std.doc.collection.meta.docMetas)], }); const snapshot = job.sliceToSnapshot(slice); if (!snapshot) { @@ -120,7 +135,13 @@ export const markdownToSnapshot = async ( host: EditorHost ) => { const job = new Job({ - collection: host.std.doc.collection, + schema: host.std.doc.collection.schema, + blobCRUD: host.std.doc.collection.blobSync, + docCRUD: { + create: (id: string) => host.std.doc.collection.createDoc({ id }), + get: (id: string) => host.std.doc.collection.getDoc(id), + delete: (id: string) => host.std.doc.collection.removeDoc(id), + }, middlewares: [defaultImageProxyMiddleware, pasteMiddleware(host.std)], }); const markdownAdapter = new MixTextAdapter(job, host.std.provider); @@ -204,7 +225,13 @@ export async function markDownToDoc( middlewares.push(...additionalMiddlewares); } const job = new Job({ - collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares, }); const mdAdapter = new MarkdownAdapter(job, provider); diff --git a/packages/frontend/core/src/components/hooks/affine/use-export-page.ts b/packages/frontend/core/src/components/hooks/affine/use-export-page.ts index 8a38e4811aaa3..c1b5c507d84b6 100644 --- a/packages/frontend/core/src/components/hooks/affine/use-export-page.ts +++ b/packages/frontend/core/src/components/hooks/affine/use-export-page.ts @@ -55,10 +55,16 @@ interface AdapterConfig { async function exportDoc(doc: Doc, std: BlockStdScope, config: AdapterConfig) { const job = new Job({ - collection: doc.collection, + schema: doc.collection.schema, + blobCRUD: doc.collection.blobSync, + docCRUD: { + create: (id: string) => doc.collection.createDoc({ id }), + get: (id: string) => doc.collection.getDoc(id), + delete: (id: string) => doc.collection.removeDoc(id), + }, middlewares: [ - docLinkBaseURLMiddleware, - titleMiddleware, + docLinkBaseURLMiddleware(doc.collection.id), + titleMiddleware(doc.collection.meta.docMetas), embedSyncedDocMiddleware('content'), ], }); diff --git a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/docs/index.ts b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/docs/index.ts index ccad21654624e..01d12d4630255 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/docs/index.ts +++ b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/docs/index.ts @@ -79,7 +79,13 @@ async function initDoc(name: DocName) { const snapshot = (await loaders[name]()) as DocSnapshot; const collection = await getCollection(); const job = new Job({ - collection, + schema: collection.schema, + blobCRUD: collection.blobSync, + docCRUD: { + create: (id: string) => collection.createDoc({ id }), + get: (id: string) => collection.getDoc(id), + delete: (id: string) => collection.removeDoc(id), + }, middlewares: [], }); diff --git a/packages/frontend/core/src/modules/docs-search/worker/in-worker.ts b/packages/frontend/core/src/modules/docs-search/worker/in-worker.ts index 739bfdca428b9..5a5b3048abdcb 100644 --- a/packages/frontend/core/src/modules/docs-search/worker/in-worker.ts +++ b/packages/frontend/core/src/modules/docs-search/worker/in-worker.ts @@ -192,7 +192,13 @@ function generateMarkdownPreviewBuilder( const provider = container.provider(); const markdownAdapter = new MarkdownAdapter( new Job({ - collection: markdownPreviewDocCollection, + schema: markdownPreviewDocCollection.schema, + blobCRUD: markdownPreviewDocCollection.blobSync, + docCRUD: { + create: (id: string) => markdownPreviewDocCollection.createDoc({ id }), + get: (id: string) => markdownPreviewDocCollection.getDoc(id), + delete: (id: string) => markdownPreviewDocCollection.removeDoc(id), + }, middlewares: [docLinkBaseURLMiddleware, titleMiddleware], }), provider