diff --git a/blocksuite/affine/block-database/src/adapters/notion-html.ts b/blocksuite/affine/block-database/src/adapters/notion-html.ts index 5d3869bd3a..a8b7fcb41a 100644 --- a/blocksuite/affine/block-database/src/adapters/notion-html.ts +++ b/blocksuite/affine/block-database/src/adapters/notion-html.ts @@ -1,9 +1,9 @@ import { DatabaseBlockSchema } from '@blocksuite/affine-model'; import { + AdapterTextUtils, BlockNotionHtmlAdapterExtension, type BlockNotionHtmlAdapterMatcher, HastUtils, - TextUtils, } from '@blocksuite/affine-shared/adapters'; import { getTagColor } from '@blocksuite/data-view'; import { type BlockSnapshot, nanoid } from '@blocksuite/store'; @@ -219,7 +219,7 @@ export const databaseBlockNotionHtmlAdapterMatcher: BlockNotionHtmlAdapterMatche column.type = 'rich-text'; row[column.id] = { columnId: column.id, - value: TextUtils.createText(text), + value: AdapterTextUtils.createText(text), }; } else { row[column.id] = { @@ -235,11 +235,11 @@ export const databaseBlockNotionHtmlAdapterMatcher: BlockNotionHtmlAdapterMatche } if ( column.type === 'rich-text' && - !TextUtils.isText(row[column.id].value) + !AdapterTextUtils.isText(row[column.id].value) ) { row[column.id] = { columnId: column.id, - value: TextUtils.createText(row[column.id].value), + value: AdapterTextUtils.createText(row[column.id].value), }; } }); diff --git a/blocksuite/affine/block-embed/src/common/render-linked-doc.ts b/blocksuite/affine/block-embed/src/common/render-linked-doc.ts index 3ed5f5cd48..a978d1982b 100644 --- a/blocksuite/affine/block-embed/src/common/render-linked-doc.ts +++ b/blocksuite/affine/block-embed/src/common/render-linked-doc.ts @@ -197,7 +197,7 @@ async function renderNoteContent( match: ids.map(id => ({ id, viewType: 'display' })), }; const previewDoc = doc.doc.getStore({ query }); - const previewSpec = SpecProvider.getInstance().getSpec('page:preview'); + const previewSpec = SpecProvider.getInstance().getSpec('preview:page'); const previewStd = new BlockStdScope({ store: previewDoc, extensions: previewSpec.value, diff --git a/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/html.ts b/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/html.ts index cd81dac2a9..59ab7c22ac 100644 --- a/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/html.ts +++ b/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/html.ts @@ -1,8 +1,8 @@ import { EmbedLinkedDocBlockSchema } from '@blocksuite/affine-model'; import { + AdapterTextUtils, BlockHtmlAdapterExtension, type BlockHtmlAdapterMatcher, - TextUtils, } from '@blocksuite/affine-shared/adapters'; export const embedLinkedDocBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher = { @@ -18,7 +18,7 @@ export const embedLinkedDocBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher = { return; } const title = configs.get('title:' + o.node.props.pageId) ?? 'untitled'; - const url = TextUtils.generateDocUrl( + const url = AdapterTextUtils.generateDocUrl( configs.get('docLinkBaseUrl') ?? '', String(o.node.props.pageId), o.node.props.params ?? Object.create(null) diff --git a/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/markdown.ts b/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/markdown.ts index eafa6b52a1..796a67ac3b 100644 --- a/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/markdown.ts +++ b/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/markdown.ts @@ -1,8 +1,8 @@ import { EmbedLinkedDocBlockSchema } from '@blocksuite/affine-model'; import { + AdapterTextUtils, BlockMarkdownAdapterExtension, type BlockMarkdownAdapterMatcher, - TextUtils, } from '@blocksuite/affine-shared/adapters'; export const embedLinkedDocBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = @@ -19,7 +19,7 @@ export const embedLinkedDocBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatc return; } const title = configs.get('title:' + o.node.props.pageId) ?? 'untitled'; - const url = TextUtils.generateDocUrl( + const url = AdapterTextUtils.generateDocUrl( configs.get('docLinkBaseUrl') ?? '', String(o.node.props.pageId), o.node.props.params ?? Object.create(null) diff --git a/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/plain-text.ts b/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/plain-text.ts index 2df2e154e2..c8b6c7291d 100644 --- a/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/plain-text.ts +++ b/blocksuite/affine/block-embed/src/embed-linked-doc-block/adapters/plain-text.ts @@ -1,8 +1,8 @@ import { EmbedLinkedDocBlockSchema } from '@blocksuite/affine-model'; import { + AdapterTextUtils, BlockPlainTextAdapterExtension, type BlockPlainTextAdapterMatcher, - TextUtils, } from '@blocksuite/affine-shared/adapters'; export const embedLinkedDocBlockPlainTextAdapterMatcher: BlockPlainTextAdapterMatcher = @@ -19,7 +19,7 @@ export const embedLinkedDocBlockPlainTextAdapterMatcher: BlockPlainTextAdapterMa return; } const title = configs.get('title:' + o.node.props.pageId) ?? 'untitled'; - const url = TextUtils.generateDocUrl( + const url = AdapterTextUtils.generateDocUrl( configs.get('docLinkBaseUrl') ?? '', String(o.node.props.pageId), o.node.props.params ?? Object.create(null) diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts index 00600120de..3aac6d2163 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts @@ -70,7 +70,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
${new BlockStdScope({ store: syncedDoc, - extensions: this._buildPreviewSpec('page:preview'), + extensions: this._buildPreviewSpec('preview:page'), }).render()}
`, @@ -81,7 +81,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
${new BlockStdScope({ store: syncedDoc, - extensions: this._buildPreviewSpec('edgeless:preview'), + extensions: this._buildPreviewSpec('preview:edgeless'), }).render()}
`, diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts index 5c10b24381..32f9438ec3 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts @@ -116,7 +116,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent { + protected _buildPreviewSpec = (name: 'preview:page' | 'preview:edgeless') => { const nextDepth = this.depth + 1; const previewSpecBuilder = SpecProvider.getInstance().getSpec(name); const currentDisposables = this.disposables; @@ -203,7 +203,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent ${new BlockStdScope({ store: syncedDoc, - extensions: this._buildPreviewSpec('page:preview'), + extensions: this._buildPreviewSpec('preview:page'), }).render()} `, @@ -214,7 +214,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent ${new BlockStdScope({ store: syncedDoc, - extensions: this._buildPreviewSpec('edgeless:preview'), + extensions: this._buildPreviewSpec('preview:edgeless'), }).render()} `, diff --git a/blocksuite/affine/block-frame/src/index.ts b/blocksuite/affine/block-frame/src/index.ts index 4adaa45b65..4f3971956a 100644 --- a/blocksuite/affine/block-frame/src/index.ts +++ b/blocksuite/affine/block-frame/src/index.ts @@ -1,3 +1,4 @@ export * from './frame-block.js'; export * from './frame-manager.js'; export * from './frame-spec.js'; +export * from './tool.js'; diff --git a/blocksuite/affine/fragment-frame-panel/src/tool.ts b/blocksuite/affine/block-frame/src/tool.ts similarity index 85% rename from blocksuite/affine/fragment-frame-panel/src/tool.ts rename to blocksuite/affine/block-frame/src/tool.ts index ad411d3fbf..83d33a4e52 100644 --- a/blocksuite/affine/fragment-frame-panel/src/tool.ts +++ b/blocksuite/affine/block-frame/src/tool.ts @@ -1,6 +1,7 @@ -import type { NavigatorMode } from '@blocksuite/affine-block-frame'; import { BaseTool } from '@blocksuite/block-std/gfx'; +import type { NavigatorMode } from './frame-manager'; + type PresentToolOption = { mode?: NavigatorMode; }; diff --git a/blocksuite/affine/block-image/src/adapters/index.ts b/blocksuite/affine/block-image/src/adapters/index.ts index 94b5ef70c3..eff5f4e0ee 100644 --- a/blocksuite/affine/block-image/src/adapters/index.ts +++ b/blocksuite/affine/block-image/src/adapters/index.ts @@ -1,3 +1,4 @@ export * from './html.js'; export * from './markdown.js'; +export * from './middleware.js'; export * from './notion-html.js'; diff --git a/blocksuite/affine/block-list/src/adapters/html.ts b/blocksuite/affine/block-list/src/adapters/html.ts index 8b98f3e362..4dcb66f6c7 100644 --- a/blocksuite/affine/block-list/src/adapters/html.ts +++ b/blocksuite/affine/block-list/src/adapters/html.ts @@ -1,9 +1,9 @@ import { ListBlockSchema } from '@blocksuite/affine-model'; import { + AdapterTextUtils, BlockHtmlAdapterExtension, type BlockHtmlAdapterMatcher, HastUtils, - TextUtils, } from '@blocksuite/affine-shared/adapters'; import type { DeltaInsert } from '@blocksuite/inline'; import { nanoid } from '@blocksuite/store'; @@ -124,7 +124,7 @@ export const listBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher = { Array.isArray(currentTNode.properties.className) && currentTNode.properties.className.includes('todo-list') ) === - TextUtils.isNullish( + AdapterTextUtils.isNullish( o.node.props.type === 'todo' ? (o.node.props.checked as boolean) : undefined @@ -177,7 +177,7 @@ export const listBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher = { Array.isArray(previousTNode.properties.className) && previousTNode.properties.className.includes('todo-list') ) === - TextUtils.isNullish( + AdapterTextUtils.isNullish( o.node.props.type === 'todo' ? (o.node.props.checked as boolean) : undefined diff --git a/blocksuite/affine/block-list/src/adapters/markdown.ts b/blocksuite/affine/block-list/src/adapters/markdown.ts index bd9bc4032c..47ddf70e69 100644 --- a/blocksuite/affine/block-list/src/adapters/markdown.ts +++ b/blocksuite/affine/block-list/src/adapters/markdown.ts @@ -1,9 +1,9 @@ import { ListBlockSchema } from '@blocksuite/affine-model'; import { + AdapterTextUtils, BlockMarkdownAdapterExtension, type BlockMarkdownAdapterMatcher, type MarkdownAST, - TextUtils, } from '@blocksuite/affine-shared/adapters'; import type { DeltaInsert } from '@blocksuite/inline'; import { nanoid } from '@blocksuite/store'; @@ -75,8 +75,8 @@ export const listBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = { walkerContext.getNodeContext('affine:list:parent') === o.parent && currentTNode.type === 'list' && currentTNode.ordered === (o.node.props.type === 'numbered') && - TextUtils.isNullish(currentTNode.children[0].checked) === - TextUtils.isNullish( + AdapterTextUtils.isNullish(currentTNode.children[0].checked) === + AdapterTextUtils.isNullish( o.node.props.type === 'todo' ? (o.node.props.checked as boolean) : undefined @@ -129,8 +129,8 @@ export const listBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = { currentTNode.type === 'listItem' && previousTNode?.type === 'list' && previousTNode.ordered === (o.node.props.type === 'numbered') && - TextUtils.isNullish(currentTNode.checked) === - TextUtils.isNullish( + AdapterTextUtils.isNullish(currentTNode.checked) === + AdapterTextUtils.isNullish( o.node.props.type === 'todo' ? (o.node.props.checked as boolean) : undefined diff --git a/blocksuite/affine/block-surface-ref/src/portal/note.ts b/blocksuite/affine/block-surface-ref/src/portal/note.ts index c560eeaa26..2beacca903 100644 --- a/blocksuite/affine/block-surface-ref/src/portal/note.ts +++ b/blocksuite/affine/block-surface-ref/src/portal/note.ts @@ -118,7 +118,7 @@ export class SurfaceRefNotePortal extends WithDisposable(ShadowlessElement) { query: this.query, readonly: true, }); - const previewSpec = SpecProvider.getInstance().getSpec('page:preview'); + const previewSpec = SpecProvider.getInstance().getSpec('preview:page'); return new BlockStdScope({ store: doc, extensions: previewSpec.value.slice(), diff --git a/blocksuite/affine/block-surface-ref/src/surface-ref-block.ts b/blocksuite/affine/block-surface-ref/src/surface-ref-block.ts index dea698f7cc..507c49fcee 100644 --- a/blocksuite/affine/block-surface-ref/src/surface-ref-block.ts +++ b/blocksuite/affine/block-surface-ref/src/surface-ref-block.ts @@ -240,7 +240,7 @@ export class SurfaceRefBlockComponent extends BlockComponent { const cellId = `${row.rowId}:${column.columnId}`; const text = rowTextLists[i]?.[j]; cells[cellId] = { - text: TextUtils.createText(text ?? ''), + text: AdapterTextUtils.createText(text ?? ''), }; } } diff --git a/blocksuite/affine/components/src/rich-text/inline/adapters/html/inline-delta.ts b/blocksuite/affine/components/src/rich-text/inline/adapters/html/inline-delta.ts index 840d3cf948..b2b2b4c2f1 100644 --- a/blocksuite/affine/components/src/rich-text/inline/adapters/html/inline-delta.ts +++ b/blocksuite/affine/components/src/rich-text/inline/adapters/html/inline-delta.ts @@ -1,7 +1,7 @@ import type { InlineHtmlAST } from '@blocksuite/affine-shared/adapters'; import { + AdapterTextUtils, InlineDeltaToHtmlAdapterExtension, - TextUtils, } from '@blocksuite/affine-shared/adapters'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; @@ -90,7 +90,7 @@ export const referenceDeltaToHtmlAdapterMatcher = const { configs } = context; const title = configs.get(`title:${reference.pageId}`); - const url = TextUtils.generateDocUrl( + const url = AdapterTextUtils.generateDocUrl( configs.get('docLinkBaseUrl') ?? '', String(reference.pageId), reference.params ?? Object.create(null) diff --git a/blocksuite/affine/components/src/rich-text/inline/adapters/markdown/inline-delta.ts b/blocksuite/affine/components/src/rich-text/inline/adapters/markdown/inline-delta.ts index 10729b3207..ee66081c80 100644 --- a/blocksuite/affine/components/src/rich-text/inline/adapters/markdown/inline-delta.ts +++ b/blocksuite/affine/components/src/rich-text/inline/adapters/markdown/inline-delta.ts @@ -1,7 +1,7 @@ import { + AdapterTextUtils, FOOTNOTE_DEFINITION_PREFIX, InlineDeltaToMarkdownAdapterExtension, - TextUtils, } from '@blocksuite/affine-shared/adapters'; import type { PhrasingContent } from 'mdast'; import type RemarkMath from 'remark-math'; @@ -74,7 +74,7 @@ export const referenceDeltaToMarkdownAdapterMatcher = const { configs } = context; const title = configs.get(`title:${reference.pageId}`); const params = reference.params ?? {}; - const url = TextUtils.generateDocUrl( + const url = AdapterTextUtils.generateDocUrl( configs.get('docLinkBaseUrl') ?? '', String(reference.pageId), params diff --git a/blocksuite/affine/components/src/rich-text/inline/adapters/plain-text/inline-delta.ts b/blocksuite/affine/components/src/rich-text/inline/adapters/plain-text/inline-delta.ts index 09a9bdb7bd..7a10c98f7a 100644 --- a/blocksuite/affine/components/src/rich-text/inline/adapters/plain-text/inline-delta.ts +++ b/blocksuite/affine/components/src/rich-text/inline/adapters/plain-text/inline-delta.ts @@ -1,7 +1,7 @@ import { + AdapterTextUtils, InlineDeltaToPlainTextAdapterExtension, type TextBuffer, - TextUtils, } from '@blocksuite/affine-shared/adapters'; import type { ExtensionType } from '@blocksuite/store'; @@ -20,7 +20,7 @@ export const referenceDeltaMarkdownAdapterMatch = const { configs } = context; const title = configs.get(`title:${reference.pageId}`) ?? ''; - const url = TextUtils.generateDocUrl( + const url = AdapterTextUtils.generateDocUrl( configs.get('docLinkBaseUrl') ?? '', String(reference.pageId), reference.params ?? Object.create(null) diff --git a/blocksuite/affine/fragment-frame-panel/src/index.ts b/blocksuite/affine/fragment-frame-panel/src/index.ts index c4351250d7..807739d4f7 100644 --- a/blocksuite/affine/fragment-frame-panel/src/index.ts +++ b/blocksuite/affine/fragment-frame-panel/src/index.ts @@ -1,2 +1 @@ export * from './frame-panel'; -export * from './tool'; diff --git a/blocksuite/affine/model/src/utils/types.ts b/blocksuite/affine/model/src/utils/types.ts index ef8fe53e95..4f72dd9a78 100644 --- a/blocksuite/affine/model/src/utils/types.ts +++ b/blocksuite/affine/model/src/utils/types.ts @@ -1,3 +1,11 @@ +import type { GfxModel } from '@blocksuite/block-std/gfx'; + +import type { + BrushElementModel, + ConnectorElementModel, + GroupElementModel, +} from '../elements'; + export type EmbedCardStyle = | 'horizontal' | 'horizontalThin' @@ -17,3 +25,8 @@ export type LinkPreviewData = { image: string | null; title: string | null; }; + +export type Connectable = Exclude< + GfxModel, + ConnectorElementModel | BrushElementModel | GroupElementModel +>; diff --git a/blocksuite/affine/shared/src/adapters/html/delta-converter.ts b/blocksuite/affine/shared/src/adapters/html/delta-converter.ts index dce670ac78..c607f8578e 100644 --- a/blocksuite/affine/shared/src/adapters/html/delta-converter.ts +++ b/blocksuite/affine/shared/src/adapters/html/delta-converter.ts @@ -14,7 +14,7 @@ import { type InlineDeltaMatcher, } from '../types/adapter.js'; import type { HtmlAST, InlineHtmlAST } from '../types/hast.js'; -import { TextUtils } from '../utils/text.js'; +import { AdapterTextUtils } from '../utils/text.js'; export type InlineDeltaToHtmlAdapterMatcher = InlineDeltaMatcher; @@ -119,7 +119,7 @@ export class HtmlDeltaConverter extends DeltaASTConverter< options: DeltaASTConverterOptions = Object.create(null) ): DeltaInsert[] { return this._spreadAstToDelta(ast, options).reduce((acc, cur) => { - return TextUtils.mergeDeltas(acc, cur); + return AdapterTextUtils.mergeDeltas(acc, cur); }, [] as DeltaInsert[]); } diff --git a/blocksuite/affine/shared/src/adapters/middlewares/doc-link.ts b/blocksuite/affine/shared/src/adapters/middlewares/doc-link.ts new file mode 100644 index 0000000000..9ee244cc8a --- /dev/null +++ b/blocksuite/affine/shared/src/adapters/middlewares/doc-link.ts @@ -0,0 +1,44 @@ +import type { TransformerMiddleware } from '@blocksuite/store'; + +const customDocLinkBaseUrlMiddleware = ( + baseUrl: string, + collectionId: string +): TransformerMiddleware => { + return ({ adapterConfigs }) => { + const docLinkBaseUrl = baseUrl + ? `${baseUrl}/workspace/${collectionId}` + : ''; + adapterConfigs.set('docLinkBaseUrl', docLinkBaseUrl); + }; +}; + +export const docLinkBaseURLMiddlewareBuilder = ( + baseUrl: string, + collectionId: string +) => { + let middleware = customDocLinkBaseUrlMiddleware(baseUrl, collectionId); + return { + get: () => middleware, + set: (url: string) => { + middleware = customDocLinkBaseUrlMiddleware(url, collectionId); + }, + }; +}; + +const defaultDocLinkBaseURLMiddlewareBuilder = (collectionId: string) => + docLinkBaseURLMiddlewareBuilder( + typeof window !== 'undefined' ? window.location.origin : '.', + collectionId + ); + +export const docLinkBaseURLMiddleware = (collectionId: string) => + defaultDocLinkBaseURLMiddlewareBuilder(collectionId).get(); + +export const setDocLinkBaseURLMiddleware = (collectionId: string) => + defaultDocLinkBaseURLMiddlewareBuilder(collectionId).set; + +export const embedSyncedDocMiddleware = + (type: 'content'): TransformerMiddleware => + ({ adapterConfigs }) => { + adapterConfigs.set('embedSyncedDocExportType', type); + }; diff --git a/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts b/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts new file mode 100644 index 0000000000..01fe47c4c1 --- /dev/null +++ b/blocksuite/affine/shared/src/adapters/middlewares/file-name.ts @@ -0,0 +1,23 @@ +import type { TransformerMiddleware } from '@blocksuite/store'; + +export const fileNameMiddleware = + (fileName?: string): TransformerMiddleware => + ({ slots }) => { + slots.beforeImport.on(payload => { + if (payload.type !== 'page') { + return; + } + if (!fileName) { + return; + } + payload.snapshot.meta.title = fileName; + payload.snapshot.blocks.props.title = { + '$blocksuite:internal:text$': true, + delta: [ + { + insert: fileName, + }, + ], + }; + }); + }; diff --git a/blocksuite/affine/shared/src/adapters/middlewares/index.ts b/blocksuite/affine/shared/src/adapters/middlewares/index.ts index c576d4a835..131fa6b1f0 100644 --- a/blocksuite/affine/shared/src/adapters/middlewares/index.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/index.ts @@ -1,4 +1,8 @@ export * from './code'; export * from './copy'; +export * from './doc-link'; +export * from './file-name'; export * from './paste'; +export * from './replace-id'; export * from './surface-ref-to-embed'; +export * from './title'; diff --git a/blocksuite/blocks/src/_common/transformers/middlewares.ts b/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts similarity index 69% rename from blocksuite/blocks/src/_common/transformers/middlewares.ts rename to blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts index 2300beb068..fa6f02a9b3 100644 --- a/blocksuite/blocks/src/_common/transformers/middlewares.ts +++ b/blocksuite/affine/shared/src/adapters/middlewares/replace-id.ts @@ -6,13 +6,8 @@ import type { ParagraphBlockModel, SurfaceRefBlockModel, } from '@blocksuite/affine-model'; -import { DEFAULT_IMAGE_PROXY_ENDPOINT } from '@blocksuite/affine-shared/consts'; import { assertExists } from '@blocksuite/global/utils'; -import type { - DeltaOperation, - DocMeta, - TransformerMiddleware, -} from '@blocksuite/store'; +import type { DeltaOperation, TransformerMiddleware } from '@blocksuite/store'; export const replaceIdMiddleware = (idGenerator: () => string): TransformerMiddleware => @@ -203,103 +198,3 @@ export const replaceIdMiddleware = } }); }; - -export const customImageProxyMiddleware = ( - imageProxyURL: string -): TransformerMiddleware => { - return ({ adapterConfigs }) => { - adapterConfigs.set('imageProxy', imageProxyURL); - }; -}; - -const customDocLinkBaseUrlMiddleware = ( - baseUrl: string, - collectionId: string -): TransformerMiddleware => { - return ({ adapterConfigs }) => { - const docLinkBaseUrl = baseUrl - ? `${baseUrl}/workspace/${collectionId}` - : ''; - adapterConfigs.set('docLinkBaseUrl', docLinkBaseUrl); - }; -}; - -export const titleMiddleware = - (metas: DocMeta[]): TransformerMiddleware => - ({ slots, adapterConfigs }) => { - slots.beforeExport.on(() => { - for (const meta of metas) { - adapterConfigs.set('title:' + meta.id, meta.title); - } - }); - }; - -export const docLinkBaseURLMiddlewareBuilder = ( - baseUrl: string, - collectionId: string -) => { - let middleware = customDocLinkBaseUrlMiddleware(baseUrl, collectionId); - return { - get: () => middleware, - set: (url: string) => { - middleware = customDocLinkBaseUrlMiddleware(url, collectionId); - }, - }; -}; - -const defaultDocLinkBaseURLMiddlewareBuilder = (collectionId: string) => - docLinkBaseURLMiddlewareBuilder( - typeof window !== 'undefined' ? window.location.origin : '.', - collectionId - ); - -export const docLinkBaseURLMiddleware = (collectionId: string) => - defaultDocLinkBaseURLMiddlewareBuilder(collectionId).get(); - -export const setDocLinkBaseURLMiddleware = (collectionId: string) => - defaultDocLinkBaseURLMiddlewareBuilder(collectionId).set; - -const imageProxyMiddlewareBuilder = () => { - let middleware = customImageProxyMiddleware(DEFAULT_IMAGE_PROXY_ENDPOINT); - return { - get: () => middleware, - set: (url: string) => { - middleware = customImageProxyMiddleware(url); - }, - }; -}; - -const defaultImageProxyMiddlewarBuilder = imageProxyMiddlewareBuilder(); - -export const setImageProxyMiddlewareURL = defaultImageProxyMiddlewarBuilder.set; - -export const defaultImageProxyMiddleware = - defaultImageProxyMiddlewarBuilder.get(); - -export const embedSyncedDocMiddleware = - (type: 'content'): TransformerMiddleware => - ({ adapterConfigs }) => { - adapterConfigs.set('embedSyncedDocExportType', type); - }; - -export const fileNameMiddleware = - (fileName?: string): TransformerMiddleware => - ({ slots }) => { - slots.beforeImport.on(payload => { - if (payload.type !== 'page') { - return; - } - if (!fileName) { - return; - } - payload.snapshot.meta.title = fileName; - payload.snapshot.blocks.props.title = { - '$blocksuite:internal:text$': true, - delta: [ - { - insert: fileName, - }, - ], - }; - }); - }; diff --git a/blocksuite/affine/shared/src/adapters/middlewares/title.ts b/blocksuite/affine/shared/src/adapters/middlewares/title.ts new file mode 100644 index 0000000000..4ad24cc1ff --- /dev/null +++ b/blocksuite/affine/shared/src/adapters/middlewares/title.ts @@ -0,0 +1,11 @@ +import type { DocMeta, TransformerMiddleware } from '@blocksuite/store'; + +export const titleMiddleware = + (metas: DocMeta[]): TransformerMiddleware => + ({ slots, adapterConfigs }) => { + slots.beforeExport.on(() => { + for (const meta of metas) { + adapterConfigs.set('title:' + meta.id, meta.title); + } + }); + }; diff --git a/blocksuite/affine/shared/src/adapters/utils/text.ts b/blocksuite/affine/shared/src/adapters/utils/text.ts index ce9c5da607..7ee92da5bb 100644 --- a/blocksuite/affine/shared/src/adapters/utils/text.ts +++ b/blocksuite/affine/shared/src/adapters/utils/text.ts @@ -86,7 +86,7 @@ function generateDocUrl( return url; } -export const TextUtils = { +export const AdapterTextUtils = { mergeDeltas, isNullish, createText, diff --git a/blocksuite/affine/shared/src/utils/spec/spec-provider.ts b/blocksuite/affine/shared/src/utils/spec/spec-provider.ts index c0e9120a54..64adabe5f2 100644 --- a/blocksuite/affine/shared/src/utils/spec/spec-provider.ts +++ b/blocksuite/affine/shared/src/utils/spec/spec-provider.ts @@ -3,10 +3,17 @@ import type { ExtensionType } from '@blocksuite/store'; import { SpecBuilder } from './spec-builder.js'; +type SpecId = + | 'store' + | 'page' + | 'edgeless' + | 'preview:page' + | 'preview:edgeless'; + export class SpecProvider { static instance: SpecProvider; - private readonly specMap = new Map(); + private readonly specMap = new Map(); private constructor() {} @@ -17,17 +24,17 @@ export class SpecProvider { return SpecProvider.instance; } - addSpec(id: string, spec: ExtensionType[]) { + addSpec(id: SpecId, spec: ExtensionType[]) { if (!this.specMap.has(id)) { this.specMap.set(id, spec); } } - clearSpec(id: string) { + clearSpec(id: SpecId) { this.specMap.delete(id); } - extendSpec(id: string, newSpec: ExtensionType[]) { + extendSpec(id: SpecId, newSpec: ExtensionType[]) { const existingSpec = this.specMap.get(id); if (!existingSpec) { console.error(`Spec not found for ${id}`); @@ -36,26 +43,17 @@ export class SpecProvider { this.specMap.set(id, [...existingSpec, ...newSpec]); } - getSpec(id: string) { + getSpec(id: SpecId) { const spec = this.specMap.get(id); assertExists(spec, `Spec not found for ${id}`); return new SpecBuilder(spec); } - hasSpec(id: string) { + hasSpec(id: SpecId) { return this.specMap.has(id); } - cloneSpec(id: string, targetId: string) { - const existingSpec = this.specMap.get(id); - if (!existingSpec) { - console.error(`Spec not found for ${id}`); - return; - } - this.specMap.set(targetId, [...existingSpec]); - } - - omitSpec(id: string, targetSpec: ExtensionType) { + omitSpec(id: SpecId, targetSpec: ExtensionType) { const existingSpec = this.specMap.get(id); if (!existingSpec) { console.error(`Spec not found for ${id}`); @@ -68,7 +66,7 @@ export class SpecProvider { ); } - replaceSpec(id: string, targetSpec: ExtensionType, newSpec: ExtensionType) { + replaceSpec(id: SpecId, targetSpec: ExtensionType, newSpec: ExtensionType) { const existingSpec = this.specMap.get(id); if (!existingSpec) { console.error(`Spec not found for ${id}`); diff --git a/blocksuite/affine/widget-drag-handle/src/helpers/preview-helper.ts b/blocksuite/affine/widget-drag-handle/src/helpers/preview-helper.ts index 5c63c28658..9aa8a6bdd3 100644 --- a/blocksuite/affine/widget-drag-handle/src/helpers/preview-helper.ts +++ b/blocksuite/affine/widget-drag-handle/src/helpers/preview-helper.ts @@ -103,7 +103,7 @@ export class PreviewHelper { const query = this._calculateQuery(blockIds as string[], mode); const store = widget.doc.doc.getStore({ query }); const previewSpec = SpecProvider.getInstance().getSpec( - isEdgeless ? 'edgeless:preview' : 'page:preview' + isEdgeless ? 'preview:edgeless' : 'preview:page' ); const settingSignal = signal({ ...editorSetting }); const extensions = [ diff --git a/blocksuite/blocks/src/__tests__/adapters/html.unit.spec.ts b/blocksuite/blocks/src/__tests__/adapters/html.unit.spec.ts index 3971fcb39f..313d1dcc79 100644 --- a/blocksuite/blocks/src/__tests__/adapters/html.unit.spec.ts +++ b/blocksuite/blocks/src/__tests__/adapters/html.unit.spec.ts @@ -3,7 +3,10 @@ import { InlineDeltaToHtmlAdapterExtensions, } from '@blocksuite/affine-components/rich-text'; import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; -import { HtmlAdapter } from '@blocksuite/affine-shared/adapters'; +import { + embedSyncedDocMiddleware, + HtmlAdapter, +} from '@blocksuite/affine-shared/adapters'; import { Container } from '@blocksuite/global/di'; import type { BlockSnapshot, @@ -14,7 +17,6 @@ import { AssetsManager, MemoryBlobCRUD } from '@blocksuite/store'; import { describe, expect, test } from 'vitest'; import { defaultBlockHtmlAdapterMatchers } from '../../_common/adapters/html/block-matcher.js'; -import { embedSyncedDocMiddleware } from '../../_common/transformers/middlewares.js'; import { createJob } from '../utils/create-job.js'; import { nanoidReplacement } from '../utils/nanoid-replacement.js'; diff --git a/blocksuite/blocks/src/__tests__/adapters/markdown.unit.spec.ts b/blocksuite/blocks/src/__tests__/adapters/markdown.unit.spec.ts index d39474c0de..8313e0ee3d 100644 --- a/blocksuite/blocks/src/__tests__/adapters/markdown.unit.spec.ts +++ b/blocksuite/blocks/src/__tests__/adapters/markdown.unit.spec.ts @@ -7,7 +7,10 @@ import { NoteDisplayMode, TableModelFlavour, } from '@blocksuite/affine-model'; -import { MarkdownAdapter } from '@blocksuite/affine-shared/adapters'; +import { + embedSyncedDocMiddleware, + MarkdownAdapter, +} from '@blocksuite/affine-shared/adapters'; import { Container } from '@blocksuite/global/di'; import type { BlockSnapshot, @@ -19,7 +22,6 @@ import { AssetsManager, MemoryBlobCRUD } from '@blocksuite/store'; import { describe, expect, test } from 'vitest'; import { defaultBlockMarkdownAdapterMatchers } from '../../_common/adapters/markdown/block-matcher.js'; -import { embedSyncedDocMiddleware } from '../../_common/transformers/middlewares.js'; import { createJob } from '../utils/create-job.js'; import { nanoidReplacement } from '../utils/nanoid-replacement.js'; diff --git a/blocksuite/blocks/src/__tests__/adapters/plain-text.unit.spec.ts b/blocksuite/blocks/src/__tests__/adapters/plain-text.unit.spec.ts index 2552034b2f..e7038b2cb1 100644 --- a/blocksuite/blocks/src/__tests__/adapters/plain-text.unit.spec.ts +++ b/blocksuite/blocks/src/__tests__/adapters/plain-text.unit.spec.ts @@ -1,6 +1,9 @@ import { InlineDeltaToPlainTextAdapterExtensions } from '@blocksuite/affine-components/rich-text'; import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; -import { PlainTextAdapter } from '@blocksuite/affine-shared/adapters'; +import { + embedSyncedDocMiddleware, + PlainTextAdapter, +} from '@blocksuite/affine-shared/adapters'; import { Container } from '@blocksuite/global/di'; import type { BlockSnapshot, @@ -10,7 +13,6 @@ import type { import { describe, expect, test } from 'vitest'; import { defaultBlockPlainTextAdapterMatchers } from '../../_common/adapters/plain-text/block-matcher.js'; -import { embedSyncedDocMiddleware } from '../../_common/transformers/middlewares.js'; import { createJob } from '../utils/create-job.js'; const container = new Container(); diff --git a/blocksuite/blocks/src/__tests__/utils/create-job.ts b/blocksuite/blocks/src/__tests__/utils/create-job.ts index 328cb13503..6586647d3a 100644 --- a/blocksuite/blocks/src/__tests__/utils/create-job.ts +++ b/blocksuite/blocks/src/__tests__/utils/create-job.ts @@ -1,3 +1,4 @@ +import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image'; import { FeatureFlagService } from '@blocksuite/affine-shared/services'; import { Schema, @@ -6,7 +7,6 @@ import { } from '@blocksuite/store'; import { TestWorkspace } from '@blocksuite/store/test'; -import { defaultImageProxyMiddleware } from '../../_common/transformers/middlewares.js'; import { AffineSchemas } from '../../schemas.js'; declare global { diff --git a/blocksuite/blocks/src/_common/transformers/index.ts b/blocksuite/blocks/src/_common/transformers/index.ts deleted file mode 100644 index 11253674fd..0000000000 --- a/blocksuite/blocks/src/_common/transformers/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export { HtmlTransformer } from './html.js'; -export { MarkdownTransformer } from './markdown.js'; -export { - customImageProxyMiddleware, - defaultImageProxyMiddleware, - docLinkBaseURLMiddleware, - docLinkBaseURLMiddlewareBuilder, - embedSyncedDocMiddleware, - replaceIdMiddleware, - setImageProxyMiddlewareURL, - titleMiddleware, -} from './middlewares.js'; -export { NotionHtmlTransformer } from './notion-html.js'; -export { createAssetsArchive, download } from './utils.js'; -export { ZipTransformer } from './zip.js'; diff --git a/blocksuite/blocks/src/_common/types.ts b/blocksuite/blocks/src/_common/types.ts deleted file mode 100644 index 9b00589ae9..0000000000 --- a/blocksuite/blocks/src/_common/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { - BrushElementModel, - ConnectorElementModel, - GroupElementModel, -} from '@blocksuite/affine-model'; -import type { GfxModel } from '@blocksuite/block-std/gfx'; - -export type Connectable = Exclude< - GfxModel, - ConnectorElementModel | BrushElementModel | GroupElementModel ->; diff --git a/blocksuite/blocks/src/_specs/common.ts b/blocksuite/blocks/src/_specs/common.ts index b5ae2d8d9a..be108c9816 100644 --- a/blocksuite/blocks/src/_specs/common.ts +++ b/blocksuite/blocks/src/_specs/common.ts @@ -56,6 +56,11 @@ import { import type { ExtensionType } from '@blocksuite/store'; import { AdapterFactoryExtensions } from '../_common/adapters/extension.js'; +import { + HtmlAdapterExtension, + MarkdownAdapterExtension, + NotionHtmlAdapterExtension, +} from './preset/adapters.js'; export const CommonBlockSpecs: ExtensionType[] = [ DocDisplayMetaService, @@ -110,4 +115,8 @@ export const StoreExtensions: ExtensionType[] = [ LinkPreviewerService, FileSizeLimitService, ImageStoreSpec, + + HtmlAdapterExtension, + MarkdownAdapterExtension, + NotionHtmlAdapterExtension, ].flat(); diff --git a/blocksuite/blocks/src/_specs/preset/adapters.ts b/blocksuite/blocks/src/_specs/preset/adapters.ts new file mode 100644 index 0000000000..02c1510808 --- /dev/null +++ b/blocksuite/blocks/src/_specs/preset/adapters.ts @@ -0,0 +1,31 @@ +import { + HtmlInlineToDeltaAdapterExtensions, + InlineDeltaToHtmlAdapterExtensions, + InlineDeltaToMarkdownAdapterExtensions, + MarkdownInlineToDeltaAdapterExtensions, + NotionHtmlInlineToDeltaAdapterExtensions, +} from '@blocksuite/affine-components/rich-text'; +import type { ExtensionType } from '@blocksuite/store'; + +import { + defaultBlockHtmlAdapterMatchers, + defaultBlockMarkdownAdapterMatchers, + defaultBlockNotionHtmlAdapterMatchers, +} from '../../_common/adapters'; + +export const HtmlAdapterExtension: ExtensionType[] = [ + ...HtmlInlineToDeltaAdapterExtensions, + ...defaultBlockHtmlAdapterMatchers, + ...InlineDeltaToHtmlAdapterExtensions, +]; + +export const MarkdownAdapterExtension: ExtensionType[] = [ + ...MarkdownInlineToDeltaAdapterExtensions, + ...defaultBlockMarkdownAdapterMatchers, + ...InlineDeltaToMarkdownAdapterExtensions, +]; + +export const NotionHtmlAdapterExtension: ExtensionType[] = [ + ...NotionHtmlInlineToDeltaAdapterExtensions, + ...defaultBlockNotionHtmlAdapterMatchers, +]; diff --git a/blocksuite/blocks/src/_specs/preset/edgeless-specs.ts b/blocksuite/blocks/src/_specs/preset/edgeless-specs.ts index ae39863504..f97a2d7726 100644 --- a/blocksuite/blocks/src/_specs/preset/edgeless-specs.ts +++ b/blocksuite/blocks/src/_specs/preset/edgeless-specs.ts @@ -1,9 +1,9 @@ import { EdgelessFrameManager, FrameOverlay, + PresentTool, } from '@blocksuite/affine-block-frame'; import { ConnectionOverlay } from '@blocksuite/affine-block-surface'; -import { PresentTool } from '@blocksuite/affine-fragment-frame-panel'; import type { ExtensionType } from '@blocksuite/store'; import { EdgelessRootBlockSpec } from '../../root-block/edgeless/edgeless-root-spec.js'; diff --git a/blocksuite/blocks/src/_specs/register-specs.ts b/blocksuite/blocks/src/_specs/register-specs.ts index 8595d747b3..29ca74e9cb 100644 --- a/blocksuite/blocks/src/_specs/register-specs.ts +++ b/blocksuite/blocks/src/_specs/register-specs.ts @@ -1,6 +1,6 @@ import { SpecProvider } from '@blocksuite/affine-shared/utils'; -import { CommonBlockSpecs, StoreExtensions } from './common.js'; +import { StoreExtensions } from './common.js'; import { EdgelessEditorBlockSpecs } from './preset/edgeless-specs.js'; import { PageEditorBlockSpecs } from './preset/page-specs.js'; import { @@ -10,15 +10,14 @@ import { export function registerSpecs() { SpecProvider.getInstance().addSpec('store', StoreExtensions); - SpecProvider.getInstance().addSpec('common', CommonBlockSpecs); SpecProvider.getInstance().addSpec('page', PageEditorBlockSpecs); SpecProvider.getInstance().addSpec('edgeless', EdgelessEditorBlockSpecs); SpecProvider.getInstance().addSpec( - 'page:preview', + 'preview:page', PreviewPageEditorBlockSpecs ); SpecProvider.getInstance().addSpec( - 'edgeless:preview', + 'preview:edgeless', PreviewEdgelessEditorBlockSpecs ); } diff --git a/blocksuite/blocks/src/index.ts b/blocksuite/blocks/src/index.ts index eafc99426a..0b31e8a9c0 100644 --- a/blocksuite/blocks/src/index.ts +++ b/blocksuite/blocks/src/index.ts @@ -7,7 +7,6 @@ import { splitElements } from './root-block/edgeless/utils/clipboard-utils.js'; import { isCanvasElement } from './root-block/edgeless/utils/query.js'; export * from './_common/adapters/index.js'; -export * from './_common/transformers/index.js'; export * from './_specs/index.js'; export { EdgelessTemplatePanel } from './root-block/edgeless/components/toolbar/template/template-panel.js'; export type { @@ -93,31 +92,7 @@ export { export * from '@blocksuite/affine-fragment-frame-panel'; export * from '@blocksuite/affine-fragment-outline'; export * from '@blocksuite/affine-model'; -export { - AttachmentAdapter, - AttachmentAdapterFactoryExtension, - AttachmentAdapterFactoryIdentifier, - codeBlockWrapMiddleware, - FetchUtils, - HtmlAdapter, - HtmlAdapterFactoryExtension, - HtmlAdapterFactoryIdentifier, - ImageAdapter, - ImageAdapterFactoryExtension, - ImageAdapterFactoryIdentifier, - MarkdownAdapter, - MarkdownAdapterFactoryExtension, - MarkdownAdapterFactoryIdentifier, - MixTextAdapter, - MixTextAdapterFactoryExtension, - MixTextAdapterFactoryIdentifier, - NotionTextAdapter, - NotionTextAdapterFactoryExtension, - NotionTextAdapterFactoryIdentifier, - PlainTextAdapter, - PlainTextAdapterFactoryExtension, - PlainTextAdapterFactoryIdentifier, -} from '@blocksuite/affine-shared/adapters'; +export * from '@blocksuite/affine-shared/adapters'; export * from '@blocksuite/affine-shared/commands'; export { HighlightSelection } from '@blocksuite/affine-shared/selection'; export * from '@blocksuite/affine-shared/services'; diff --git a/blocksuite/blocks/src/root-block/clipboard/page-clipboard.ts b/blocksuite/blocks/src/root-block/clipboard/page-clipboard.ts index 162c4a032e..2cdbaed15f 100644 --- a/blocksuite/blocks/src/root-block/clipboard/page-clipboard.ts +++ b/blocksuite/blocks/src/root-block/clipboard/page-clipboard.ts @@ -1,6 +1,7 @@ import { deleteTextCommand } from '@blocksuite/affine-components/rich-text'; import { pasteMiddleware, + replaceIdMiddleware, surfaceRefToEmbed, } from '@blocksuite/affine-shared/adapters'; import { @@ -17,7 +18,6 @@ import type { UIEventHandler } from '@blocksuite/block-std'; import { DisposableGroup } from '@blocksuite/global/utils'; import type { BlockSnapshot, Store } from '@blocksuite/store'; -import { replaceIdMiddleware } from '../../_common/transformers/middlewares'; import { ReadOnlyClipboard } from './readonly-clipboard'; /** diff --git a/blocksuite/blocks/src/root-block/clipboard/readonly-clipboard.ts b/blocksuite/blocks/src/root-block/clipboard/readonly-clipboard.ts index f6c31fa233..78b6aee186 100644 --- a/blocksuite/blocks/src/root-block/clipboard/readonly-clipboard.ts +++ b/blocksuite/blocks/src/root-block/clipboard/readonly-clipboard.ts @@ -1,3 +1,4 @@ +import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image'; import { AttachmentAdapter, copyMiddleware, @@ -5,6 +6,7 @@ import { ImageAdapter, MixTextAdapter, NotionTextAdapter, + titleMiddleware, } from '@blocksuite/affine-shared/adapters'; import { copySelectedModelsCommand, @@ -14,10 +16,6 @@ import { import type { BlockComponent, UIEventHandler } from '@blocksuite/block-std'; import { DisposableGroup } from '@blocksuite/global/utils'; -import { - defaultImageProxyMiddleware, - titleMiddleware, -} from '../../_common/transformers/middlewares.js'; import { ClipboardAdapter } from './adapter.js'; /** diff --git a/blocksuite/blocks/src/root-block/edgeless/components/frame/frame-preview.ts b/blocksuite/blocks/src/root-block/edgeless/components/frame/frame-preview.ts index 43b4ac469e..18da693c2c 100644 --- a/blocksuite/blocks/src/root-block/edgeless/components/frame/frame-preview.ts +++ b/blocksuite/blocks/src/root-block/edgeless/components/frame/frame-preview.ts @@ -81,7 +81,7 @@ export class FramePreview extends WithDisposable(ShadowlessElement) { private _previewDoc: Store | null = null; private readonly _previewSpec = - SpecProvider.getInstance().getSpec('edgeless:preview'); + SpecProvider.getInstance().getSpec('preview:edgeless'); private readonly _updateFrameViewportWH = () => { const [, , w, h] = deserializeXYWH(this.frame.xywh); diff --git a/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts b/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts index ac50402ce4..e6ee791794 100644 --- a/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts +++ b/blocksuite/blocks/src/root-block/edgeless/edgeless-keyboard.ts @@ -31,11 +31,6 @@ import { import { IS_MAC } from '@blocksuite/global/env'; import { Bound, getCommonBound } from '@blocksuite/global/utils'; -import { - getNearestTranslation, - isElementOutsideViewport, - isSingleMindMapNode, -} from '../../_common/edgeless/mindmap/index.js'; import { PageKeyboardManager } from '../keyboard/keyboard-manager.js'; import type { EdgelessRootBlockComponent } from './edgeless-root-block.js'; import { CopilotTool } from './gfx-tool/copilot-tool.js'; @@ -48,6 +43,11 @@ import { } from './utils/consts.js'; import { deleteElements } from './utils/crud.js'; import { getNextShapeType } from './utils/hotkey-utils.js'; +import { + getNearestTranslation, + isElementOutsideViewport, + isSingleMindMapNode, +} from './utils/mindmap.js'; import { isCanvasElement } from './utils/query.js'; import { mountConnectorLabelEditor, diff --git a/blocksuite/blocks/src/root-block/edgeless/edgeless-root-block.ts b/blocksuite/blocks/src/root-block/edgeless/edgeless-root-block.ts index 7273ef2073..871ba4dd12 100644 --- a/blocksuite/blocks/src/root-block/edgeless/edgeless-root-block.ts +++ b/blocksuite/blocks/src/root-block/edgeless/edgeless-root-block.ts @@ -45,12 +45,12 @@ import { css, html } from 'lit'; import { query } from 'lit/decorators.js'; import { repeat } from 'lit/directives/repeat.js'; -import { isSingleMindMapNode } from '../../_common/edgeless/mindmap/index.js'; import type { EdgelessRootBlockWidgetName } from '../types.js'; import { EdgelessClipboardController } from './clipboard/clipboard.js'; import type { EdgelessSelectedRectWidget } from './components/rects/edgeless-selected-rect.js'; import { EdgelessPageKeyboardManager } from './edgeless-keyboard.js'; import type { EdgelessRootService } from './edgeless-root-service.js'; +import { isSingleMindMapNode } from './utils/mindmap.js'; import { isCanvasElement } from './utils/query.js'; import { mountShapeTextEditor } from './utils/text.js'; diff --git a/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool-ext/mind-map-ext/mind-map-ext.ts b/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool-ext/mind-map-ext/mind-map-ext.ts index 52d3adb89c..b99fadff27 100644 --- a/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool-ext/mind-map-ext/mind-map-ext.ts +++ b/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool-ext/mind-map-ext/mind-map-ext.ts @@ -19,7 +19,7 @@ import { } from '@blocksuite/block-std/gfx'; import type { Bound, IVec } from '@blocksuite/global/utils'; -import { isSingleMindMapNode } from '../../../../../_common/edgeless/mindmap/index.js'; +import { isSingleMindMapNode } from '../../../utils/mindmap.js'; import { isMindmapNode } from '../../../utils/query.js'; import { DefaultModeDragType, DefaultToolExt, type DragState } from '../ext.js'; import { calculateResponseArea } from './drag-utils.js'; diff --git a/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool.ts b/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool.ts index 5517c52dc8..5cd26a66b9 100644 --- a/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool.ts +++ b/blocksuite/blocks/src/root-block/edgeless/gfx-tool/default-tool.ts @@ -53,9 +53,9 @@ import { } from '@blocksuite/global/utils'; import { effect } from '@preact/signals-core'; -import { isSingleMindMapNode } from '../../../_common/edgeless/mindmap/index.js'; import type { EdgelessRootBlockComponent } from '../edgeless-root-block.js'; import { prepareCloneData } from '../utils/clone-utils.js'; +import { isSingleMindMapNode } from '../utils/mindmap.js'; import { calPanDelta } from '../utils/panning-utils.js'; import { isCanvasElement, isEdgelessTextBlock } from '../utils/query.js'; import type { EdgelessSnapManager } from '../utils/snap-manager.js'; diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/crud.ts b/blocksuite/blocks/src/root-block/edgeless/utils/crud.ts index 4afb1140aa..3a6a7033af 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/crud.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/crud.ts @@ -1,7 +1,7 @@ import { isNoteBlock } from '@blocksuite/affine-block-surface'; +import type { Connectable } from '@blocksuite/affine-model'; import type { GfxModel } from '@blocksuite/block-std/gfx'; -import type { Connectable } from '../../../_common/types.js'; import type { EdgelessRootBlockComponent } from '../index.js'; import { isConnectable } from './query.js'; diff --git a/blocksuite/blocks/src/_common/edgeless/mindmap/index.ts b/blocksuite/blocks/src/root-block/edgeless/utils/mindmap.ts similarity index 100% rename from blocksuite/blocks/src/_common/edgeless/mindmap/index.ts rename to blocksuite/blocks/src/root-block/edgeless/utils/mindmap.ts diff --git a/blocksuite/blocks/src/root-block/edgeless/utils/query.ts b/blocksuite/blocks/src/root-block/edgeless/utils/query.ts index 5f4a12ad19..980460e55c 100644 --- a/blocksuite/blocks/src/root-block/edgeless/utils/query.ts +++ b/blocksuite/blocks/src/root-block/edgeless/utils/query.ts @@ -2,6 +2,7 @@ import type { CanvasElementWithText } from '@blocksuite/affine-block-surface'; import { type AttachmentBlockModel, type BookmarkBlockModel, + type Connectable, ConnectorElementModel, type EdgelessTextBlockModel, type EmbedBlockModel, @@ -32,8 +33,6 @@ import type { PointLocation } from '@blocksuite/global/utils'; import { Bound } from '@blocksuite/global/utils'; import type { BlockModel } from '@blocksuite/store'; -import type { Connectable } from '../../../_common/types'; - export function isMindmapNode(element: GfxBlockElementModel | GfxModel | null) { return element?.group instanceof MindmapElementModel; } diff --git a/blocksuite/blocks/src/root-block/index.ts b/blocksuite/blocks/src/root-block/index.ts index 3625b4b4c8..dcf49ca3ac 100644 --- a/blocksuite/blocks/src/root-block/index.ts +++ b/blocksuite/blocks/src/root-block/index.ts @@ -11,6 +11,7 @@ export * from './page/page-root-spec.js'; export * from './preview/preview-root-block.js'; export * from './root-config.js'; export { RootService } from './root-service.js'; +export * from './transformers/index.js'; export * from './types.js'; export * from './utils/index.js'; export * from './widgets/index.js'; diff --git a/blocksuite/blocks/src/root-block/root-service.ts b/blocksuite/blocks/src/root-block/root-service.ts index 4f0501134b..2f6ea88181 100644 --- a/blocksuite/blocks/src/root-block/root-service.ts +++ b/blocksuite/blocks/src/root-block/root-service.ts @@ -8,22 +8,11 @@ import { import type { BlockComponent } from '@blocksuite/block-std'; import { BlockService } from '@blocksuite/block-std'; -import { - HtmlTransformer, - MarkdownTransformer, - ZipTransformer, -} from '../_common/transformers/index.js'; import type { RootBlockComponent } from './types.js'; export abstract class RootService extends BlockService { static override readonly flavour = RootBlockSchema.model.flavour; - transformers = { - markdown: MarkdownTransformer, - html: HtmlTransformer, - zip: ZipTransformer, - }; - get selectedBlocks() { let result: BlockComponent[] = []; this.std.command diff --git a/blocksuite/blocks/src/_common/transformers/html.ts b/blocksuite/blocks/src/root-block/transformers/html.ts similarity index 90% rename from blocksuite/blocks/src/_common/transformers/html.ts rename to blocksuite/blocks/src/root-block/transformers/html.ts index 0857f3e15e..4502bd2f5f 100644 --- a/blocksuite/blocks/src/_common/transformers/html.ts +++ b/blocksuite/blocks/src/root-block/transformers/html.ts @@ -1,20 +1,16 @@ +import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image'; import { - HtmlInlineToDeltaAdapterExtensions, - InlineDeltaToHtmlAdapterExtensions, -} from '@blocksuite/affine-components/rich-text'; -import { HtmlAdapter } from '@blocksuite/affine-shared/adapters'; + docLinkBaseURLMiddleware, + fileNameMiddleware, + HtmlAdapter, + titleMiddleware, +} 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 type { Store, Workspace } from '@blocksuite/store'; import { extMimeMap, Transformer } from '@blocksuite/store'; -import { defaultBlockHtmlAdapterMatchers } from '../adapters/html/block-matcher.js'; -import { - defaultImageProxyMiddleware, - docLinkBaseURLMiddleware, - fileNameMiddleware, - titleMiddleware, -} from './middlewares.js'; import { createAssetsArchive, download, Unzip } from './utils.js'; type ImportHTMLToDocOptions = { @@ -28,16 +24,14 @@ type ImportHTMLZipOptions = { imported: Blob; }; -const container = new Container(); -[ - ...HtmlInlineToDeltaAdapterExtensions, - ...defaultBlockHtmlAdapterMatchers, - ...InlineDeltaToHtmlAdapterExtensions, -].forEach(ext => { - ext.setup(container); -}); - -const provider = container.provider(); +function getProvider() { + const container = new Container(); + const exts = SpecProvider.getInstance().getSpec('store').value; + exts.forEach(ext => { + ext.setup(container); + }); + return container.provider(); +} /** * Exports a doc to HTML format. @@ -46,6 +40,7 @@ const provider = container.provider(); * @returns A Promise that resolves when the export is complete. */ async function exportDoc(doc: Store) { + const provider = getProvider(); const job = new Transformer({ schema: doc.schema, blobCRUD: doc.blobSync, @@ -101,6 +96,7 @@ async function importHTMLToDoc({ html, fileName, }: ImportHTMLToDocOptions) { + const provider = getProvider(); const job = new Transformer({ schema: collection.schema, blobCRUD: collection.blobSync, @@ -135,6 +131,7 @@ async function importHTMLToDoc({ * @returns A Promise that resolves to an array of IDs of the newly created docs. */ async function importHTMLZip({ collection, imported }: ImportHTMLZipOptions) { + const provider = getProvider(); const unzip = new Unzip(); await unzip.load(imported); diff --git a/blocksuite/blocks/src/root-block/transformers/index.ts b/blocksuite/blocks/src/root-block/transformers/index.ts new file mode 100644 index 0000000000..a25831dbbe --- /dev/null +++ b/blocksuite/blocks/src/root-block/transformers/index.ts @@ -0,0 +1,5 @@ +export { HtmlTransformer } from './html.js'; +export { MarkdownTransformer } from './markdown.js'; +export { NotionHtmlTransformer } from './notion-html.js'; +export { createAssetsArchive, download } from './utils.js'; +export { ZipTransformer } from './zip.js'; diff --git a/blocksuite/blocks/src/_common/transformers/markdown.ts b/blocksuite/blocks/src/root-block/transformers/markdown.ts similarity index 92% rename from blocksuite/blocks/src/_common/transformers/markdown.ts rename to blocksuite/blocks/src/root-block/transformers/markdown.ts index eb2a84be74..b31eefea01 100644 --- a/blocksuite/blocks/src/_common/transformers/markdown.ts +++ b/blocksuite/blocks/src/root-block/transformers/markdown.ts @@ -1,33 +1,27 @@ +import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image'; import { - InlineDeltaToMarkdownAdapterExtensions, - MarkdownInlineToDeltaAdapterExtensions, -} from '@blocksuite/affine-components/rich-text'; -import { MarkdownAdapter } from '@blocksuite/affine-shared/adapters'; + docLinkBaseURLMiddleware, + fileNameMiddleware, + MarkdownAdapter, + titleMiddleware, +} from '@blocksuite/affine-shared/adapters'; +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 { extMimeMap, Transformer } from '@blocksuite/store'; -import { defaultBlockMarkdownAdapterMatchers } from '../adapters/index.js'; -import { - defaultImageProxyMiddleware, - docLinkBaseURLMiddleware, - fileNameMiddleware, - titleMiddleware, -} from './middlewares.js'; import { createAssetsArchive, download, Unzip } from './utils.js'; -const container = new Container(); -[ - ...MarkdownInlineToDeltaAdapterExtensions, - ...defaultBlockMarkdownAdapterMatchers, - ...InlineDeltaToMarkdownAdapterExtensions, -].forEach(ext => { - ext.setup(container); -}); - -const provider = container.provider(); +function getProvider() { + const container = new Container(); + const exts = SpecProvider.getInstance().getSpec('store').value; + exts.forEach(ext => { + ext.setup(container); + }); + return container.provider(); +} type ImportMarkdownToBlockOptions = { doc: Store; @@ -52,6 +46,7 @@ type ImportMarkdownZipOptions = { * @returns A Promise that resolves when the export is complete */ async function exportDoc(doc: Store) { + const provider = getProvider(); const job = new Transformer({ schema: doc.schema, blobCRUD: doc.blobSync, @@ -111,6 +106,7 @@ async function importMarkdownToBlock({ markdown, blockId, }: ImportMarkdownToBlockOptions) { + const provider = getProvider(); const job = new Transformer({ schema: doc.schema, blobCRUD: doc.blobSync, @@ -156,6 +152,7 @@ async function importMarkdownToDoc({ markdown, fileName, }: ImportMarkdownToDocOptions) { + const provider = getProvider(); const job = new Transformer({ schema: collection.schema, blobCRUD: collection.blobSync, @@ -192,6 +189,7 @@ async function importMarkdownZip({ collection, imported, }: ImportMarkdownZipOptions) { + const provider = getProvider(); const unzip = new Unzip(); await unzip.load(imported); diff --git a/blocksuite/blocks/src/_common/transformers/notion-html.ts b/blocksuite/blocks/src/root-block/transformers/notion-html.ts similarity index 91% rename from blocksuite/blocks/src/_common/transformers/notion-html.ts rename to blocksuite/blocks/src/root-block/transformers/notion-html.ts index c5aa2b387d..88e69d23cd 100644 --- a/blocksuite/blocks/src/_common/transformers/notion-html.ts +++ b/blocksuite/blocks/src/root-block/transformers/notion-html.ts @@ -1,11 +1,10 @@ -import { NotionHtmlInlineToDeltaAdapterExtensions } from '@blocksuite/affine-components/rich-text'; +import { defaultImageProxyMiddleware } from '@blocksuite/affine-block-image'; 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 { defaultBlockNotionHtmlAdapterMatchers } from '../adapters/notion-html/block-matcher.js'; -import { defaultImageProxyMiddleware } from './middlewares.js'; import { Unzip } from './utils.js'; type ImportNotionZipOptions = { @@ -13,15 +12,14 @@ type ImportNotionZipOptions = { imported: Blob; }; -const container = new Container(); -[ - ...NotionHtmlInlineToDeltaAdapterExtensions, - ...defaultBlockNotionHtmlAdapterMatchers, -].forEach(ext => { - ext.setup(container); -}); - -const provider = container.provider(); +function getProvider() { + const container = new Container(); + const exts = SpecProvider.getInstance().getSpec('store').value; + exts.forEach(ext => { + ext.setup(container); + }); + return container.provider(); +} /** * Imports a Notion zip file into the BlockSuite collection. @@ -40,6 +38,7 @@ async function importNotionZip({ collection, imported, }: ImportNotionZipOptions) { + const provider = getProvider(); const pageIds: string[] = []; let isWorkspaceFile = false; let hasMarkdown = false; diff --git a/blocksuite/blocks/src/_common/transformers/utils.ts b/blocksuite/blocks/src/root-block/transformers/utils.ts similarity index 100% rename from blocksuite/blocks/src/_common/transformers/utils.ts rename to blocksuite/blocks/src/root-block/transformers/utils.ts diff --git a/blocksuite/blocks/src/_common/transformers/zip.ts b/blocksuite/blocks/src/root-block/transformers/zip.ts similarity index 97% rename from blocksuite/blocks/src/_common/transformers/zip.ts rename to blocksuite/blocks/src/root-block/transformers/zip.ts index dd5fca07ad..fdae392360 100644 --- a/blocksuite/blocks/src/_common/transformers/zip.ts +++ b/blocksuite/blocks/src/root-block/transformers/zip.ts @@ -1,9 +1,12 @@ +import { + replaceIdMiddleware, + titleMiddleware, +} from '@blocksuite/affine-shared/adapters'; import { sha } from '@blocksuite/global/utils'; import type { DocSnapshot, Store, Workspace } from '@blocksuite/store'; import { extMimeMap, getAssetName, Transformer } from '@blocksuite/store'; import { download, Unzip, Zip } from '../transformers/utils.js'; -import { replaceIdMiddleware, titleMiddleware } from './middlewares.js'; async function exportDocs(collection: Workspace, docs: Store[]) { const zip = new Zip(); diff --git a/blocksuite/blocks/src/root-block/widgets/linked-doc/import-doc/import-doc.ts b/blocksuite/blocks/src/root-block/widgets/linked-doc/import-doc/import-doc.ts index d5210ab270..196de21997 100644 --- a/blocksuite/blocks/src/root-block/widgets/linked-doc/import-doc/import-doc.ts +++ b/blocksuite/blocks/src/root-block/widgets/linked-doc/import-doc/import-doc.ts @@ -12,9 +12,9 @@ import type { Workspace } from '@blocksuite/store'; import { html, LitElement, type PropertyValues } from 'lit'; import { query, state } from 'lit/decorators.js'; -import { HtmlTransformer } from '../../../../_common/transformers/html.js'; -import { MarkdownTransformer } from '../../../../_common/transformers/markdown.js'; -import { NotionHtmlTransformer } from '../../../../_common/transformers/notion-html.js'; +import { HtmlTransformer } from '../../../transformers/html.js'; +import { MarkdownTransformer } from '../../../transformers/markdown.js'; +import { NotionHtmlTransformer } from '../../../transformers/notion-html.js'; import { styles } from './styles.js'; export type OnSuccessHandler = ( diff --git a/blocksuite/integration-test/src/__tests__/main/snapshot.spec.ts b/blocksuite/integration-test/src/__tests__/main/snapshot.spec.ts index f442873751..da513bb789 100644 --- a/blocksuite/integration-test/src/__tests__/main/snapshot.spec.ts +++ b/blocksuite/integration-test/src/__tests__/main/snapshot.spec.ts @@ -1,5 +1,4 @@ -import { BlockServiceIdentifier } from '@blocksuite/block-std'; -import type { PageRootService, SurfaceBlockModel } from '@blocksuite/blocks'; +import { type SurfaceBlockModel, ZipTransformer } from '@blocksuite/blocks'; import type { PointLocation } from '@blocksuite/global/utils'; import { beforeEach, expect, test } from 'vitest'; @@ -25,13 +24,7 @@ const fieldChecker: Record boolean> = { const skipFields = new Set(['_lastXYWH']); const snapshotTest = async (snapshotUrl: string, elementsCount: number) => { - const pageService = window.editor.host!.std.getOptional( - BlockServiceIdentifier('affine:page') - ) as PageRootService; - if (!pageService) { - throw new Error('page service not found'); - } - const transformer = pageService.transformers.zip; + const transformer = ZipTransformer; const snapshotFile = await fetch(snapshotUrl) .then(res => res.blob()) diff --git a/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts b/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts index f656355d77..9f65195d2b 100644 --- a/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts +++ b/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts @@ -209,7 +209,7 @@ export class AISlidesRenderer extends WithDisposable(LitElement) { ${new BlockStdScope({ store: this._doc, extensions: - SpecProvider.getInstance().getSpec('edgeless:preview').value, + SpecProvider.getInstance().getSpec('preview:edgeless').value, }).render()}
diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/root-block.ts b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/root-block.ts index 181b178071..350ed3986b 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/root-block.ts +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/custom/root-block.ts @@ -245,10 +245,10 @@ export const extendEdgelessPreviewSpec = (function () { return _extension; } else { _extension && - SpecProvider.getInstance().omitSpec('edgeless:preview', _extension); + SpecProvider.getInstance().omitSpec('preview:edgeless', _extension); _extension = getThemeExtension(framework); _framework = framework; - SpecProvider.getInstance().extendSpec('edgeless:preview', [_extension]); + SpecProvider.getInstance().extendSpec('preview:edgeless', [_extension]); return _extension; } }; diff --git a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/preview.ts b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/preview.ts index 7fa31ceb77..e8f0a73c5d 100644 --- a/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/preview.ts +++ b/packages/frontend/core/src/components/blocksuite/block-suite-editor/specs/preview.ts @@ -29,14 +29,17 @@ const CustomSpecs: ExtensionType[] = [ getFontConfigExtension(), ].flat(); -function patchPreviewSpec(id: string, specs: ExtensionType[]) { +function patchPreviewSpec( + id: 'preview:edgeless' | 'preview:page', + specs: ExtensionType[] +) { const specProvider = SpecProvider.getInstance(); specProvider.extendSpec(id, specs); } export function effects() { // Patch edgeless preview spec for blocksuite surface-ref and embed-synced-doc - patchPreviewSpec('edgeless:preview', CustomSpecs); + patchPreviewSpec('preview:edgeless', CustomSpecs); } export function getPagePreviewThemeExtension(framework: FrameworkProvider) { @@ -98,7 +101,7 @@ export function createPageModePreviewSpecs( framework: FrameworkProvider ): SpecBuilder { const specProvider = SpecProvider.getInstance(); - const pagePreviewSpec = specProvider.getSpec('page:preview'); + const pagePreviewSpec = specProvider.getSpec('preview:page'); // Enable theme extension, doc display meta extension and peek view service const peekViewService = framework.get(PeekViewService); pagePreviewSpec.extend([ diff --git a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx index a63e3e870c..10ccba20a6 100644 --- a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx +++ b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/editor/edgeless/snapshot.tsx @@ -92,7 +92,7 @@ export const EdgelessSnapshot = (props: Props) => { const editorHost = new BlockStdScope({ store: doc, extensions: [ - ...SpecProvider.getInstance().getSpec('edgeless:preview').value, + ...SpecProvider.getInstance().getSpec('preview:edgeless').value, getThemeExtension(framework), ], }).render();