diff --git a/blocksuite/affine/block-embed/src/embed-figma-block/adapters/extension.ts b/blocksuite/affine/block-embed/src/embed-figma-block/adapters/extension.ts index 831deba680..7c6917be7a 100644 --- a/blocksuite/affine/block-embed/src/embed-figma-block/adapters/extension.ts +++ b/blocksuite/affine/block-embed/src/embed-figma-block/adapters/extension.ts @@ -2,12 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std'; import { EmbedFigmaBlockHtmlAdapterExtension } from './html.js'; import { EmbedFigmaMarkdownAdapterExtension } from './markdown.js'; -import { EmbedFigmaNotionHtmlAdapterExtension } from './notion-html.js'; +import { EmbedFigmaBlockNotionHtmlAdapterExtension } from './notion-html.js'; import { EmbedFigmaBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedFigmaBlockAdapterExtensions: ExtensionType[] = [ EmbedFigmaBlockHtmlAdapterExtension, EmbedFigmaMarkdownAdapterExtension, EmbedFigmaBlockPlainTextAdapterExtension, - EmbedFigmaNotionHtmlAdapterExtension, + EmbedFigmaBlockNotionHtmlAdapterExtension, ]; diff --git a/blocksuite/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts b/blocksuite/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts index 53119d9579..b02edcfa4d 100644 --- a/blocksuite/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts +++ b/blocksuite/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts @@ -10,5 +10,5 @@ export const embedFigmaBlockNotionHtmlAdapterMatcher = figmaUrlRegex ); -export const EmbedFigmaNotionHtmlAdapterExtension = +export const EmbedFigmaBlockNotionHtmlAdapterExtension = BlockNotionHtmlAdapterExtension(embedFigmaBlockNotionHtmlAdapterMatcher); diff --git a/blocksuite/affine/block-embed/src/embed-github-block/adapters/extension.ts b/blocksuite/affine/block-embed/src/embed-github-block/adapters/extension.ts index 3f548aedcb..586b0d5d8f 100644 --- a/blocksuite/affine/block-embed/src/embed-github-block/adapters/extension.ts +++ b/blocksuite/affine/block-embed/src/embed-github-block/adapters/extension.ts @@ -2,12 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std'; import { EmbedGithubBlockHtmlAdapterExtension } from './html.js'; import { EmbedGithubMarkdownAdapterExtension } from './markdown.js'; -import { EmbedGithubNotionHtmlAdapterExtension } from './notion-html.js'; +import { EmbedGithubBlockNotionHtmlAdapterExtension } from './notion-html.js'; import { EmbedGithubBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedGithubBlockAdapterExtensions: ExtensionType[] = [ EmbedGithubBlockHtmlAdapterExtension, EmbedGithubMarkdownAdapterExtension, EmbedGithubBlockPlainTextAdapterExtension, - EmbedGithubNotionHtmlAdapterExtension, + EmbedGithubBlockNotionHtmlAdapterExtension, ]; diff --git a/blocksuite/affine/block-embed/src/embed-github-block/adapters/notion-html.ts b/blocksuite/affine/block-embed/src/embed-github-block/adapters/notion-html.ts index 20022c2345..e02a945868 100644 --- a/blocksuite/affine/block-embed/src/embed-github-block/adapters/notion-html.ts +++ b/blocksuite/affine/block-embed/src/embed-github-block/adapters/notion-html.ts @@ -10,5 +10,5 @@ export const embedGithubBlockNotionHtmlAdapterMatcher = githubUrlRegex ); -export const EmbedGithubNotionHtmlAdapterExtension = +export const EmbedGithubBlockNotionHtmlAdapterExtension = BlockNotionHtmlAdapterExtension(embedGithubBlockNotionHtmlAdapterMatcher); diff --git a/blocksuite/affine/block-embed/src/embed-loom-block/adapters/extension.ts b/blocksuite/affine/block-embed/src/embed-loom-block/adapters/extension.ts index d742f5c575..99be14e2ad 100644 --- a/blocksuite/affine/block-embed/src/embed-loom-block/adapters/extension.ts +++ b/blocksuite/affine/block-embed/src/embed-loom-block/adapters/extension.ts @@ -2,12 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std'; import { EmbedLoomBlockHtmlAdapterExtension } from './html.js'; import { EmbedLoomMarkdownAdapterExtension } from './markdown.js'; -import { EmbedLoomNotionHtmlAdapterExtension } from './notion-html.js'; +import { EmbedLoomBlockNotionHtmlAdapterExtension } from './notion-html.js'; import { EmbedLoomBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedLoomBlockAdapterExtensions: ExtensionType[] = [ EmbedLoomBlockHtmlAdapterExtension, EmbedLoomMarkdownAdapterExtension, EmbedLoomBlockPlainTextAdapterExtension, - EmbedLoomNotionHtmlAdapterExtension, + EmbedLoomBlockNotionHtmlAdapterExtension, ]; diff --git a/blocksuite/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts b/blocksuite/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts index db06ca0b57..f0f4d7c619 100644 --- a/blocksuite/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts +++ b/blocksuite/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts @@ -10,5 +10,5 @@ export const embedLoomBlockNotionHtmlAdapterMatcher = loomUrlRegex ); -export const EmbedLoomNotionHtmlAdapterExtension = +export const EmbedLoomBlockNotionHtmlAdapterExtension = BlockNotionHtmlAdapterExtension(embedLoomBlockNotionHtmlAdapterMatcher); diff --git a/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/extension.ts b/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/extension.ts index f3f6bb2489..f6acd32d17 100644 --- a/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/extension.ts +++ b/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/extension.ts @@ -2,12 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std'; import { EmbedYoutubeBlockHtmlAdapterExtension } from './html.js'; import { EmbedYoutubeMarkdownAdapterExtension } from './markdown.js'; -import { EmbedYoutubeNotionHtmlAdapterExtension } from './notion-html.js'; +import { EmbedYoutubeBlockNotionHtmlAdapterExtension } from './notion-html.js'; import { EmbedYoutubeBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedYoutubeBlockAdapterExtensions: ExtensionType[] = [ EmbedYoutubeBlockHtmlAdapterExtension, EmbedYoutubeMarkdownAdapterExtension, EmbedYoutubeBlockPlainTextAdapterExtension, - EmbedYoutubeNotionHtmlAdapterExtension, + EmbedYoutubeBlockNotionHtmlAdapterExtension, ]; diff --git a/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts b/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts index e4da1a9e3c..c7ed95a0e7 100644 --- a/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts +++ b/blocksuite/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts @@ -10,5 +10,5 @@ export const embedYoutubeBlockNotionHtmlAdapterMatcher = youtubeUrlRegex ); -export const EmbedYoutubeNotionHtmlAdapterExtension = +export const EmbedYoutubeBlockNotionHtmlAdapterExtension = BlockNotionHtmlAdapterExtension(embedYoutubeBlockNotionHtmlAdapterMatcher); diff --git a/blocksuite/affine/shared/src/adapters/index.ts b/blocksuite/affine/shared/src/adapters/index.ts index ae19f8fcfe..64e0727bb9 100644 --- a/blocksuite/affine/shared/src/adapters/index.ts +++ b/blocksuite/affine/shared/src/adapters/index.ts @@ -30,6 +30,7 @@ export { BlockNotionHtmlAdapterMatcherIdentifier, type InlineDeltaToNotionHtmlAdapterMatcher, type NotionHtml, + NotionHtmlASTToDeltaExtension, type NotionHtmlASTToDeltaMatcher, NotionHtmlASTToDeltaMatcherIdentifier, NotionHtmlDeltaConverter, diff --git a/blocksuite/blocks/src/__tests__/adapters/notion-html.unit.spec.ts b/blocksuite/blocks/src/__tests__/adapters/notion-html.unit.spec.ts index e2a0409025..3807f00d33 100644 --- a/blocksuite/blocks/src/__tests__/adapters/notion-html.unit.spec.ts +++ b/blocksuite/blocks/src/__tests__/adapters/notion-html.unit.spec.ts @@ -2,6 +2,7 @@ import { DEFAULT_NOTE_BACKGROUND_COLOR, NoteDisplayMode, } from '@blocksuite/affine-model'; +import { Container } from '@blocksuite/global/di'; import { AssetsManager, type BlockSnapshot, @@ -9,10 +10,22 @@ import { } from '@blocksuite/store'; import { describe, expect, test } from 'vitest'; +import { defaultBlockNotionHtmlAdapterMatchers } from '../../_common/adapters/notion-html/block-matcher.js'; +import { notionHtmlInlineToDeltaMatchers } from '../../_common/adapters/notion-html/delta-converter/html-inline.js'; import { NotionHtmlAdapter } from '../../_common/adapters/notion-html/notion-html.js'; import { nanoidReplacement } from '../../_common/test-utils/test-utils.js'; import { createJob } from '../utils/create-job.js'; +const container = new Container(); +[ + ...notionHtmlInlineToDeltaMatchers, + ...defaultBlockNotionHtmlAdapterMatchers, +].forEach(ext => { + ext.setup(container); +}); + +const provider = container.provider(); + describe('notion html to snapshot', () => { test('code', async () => { const html = `
@@ -56,7 +69,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -179,7 +192,7 @@ describe('notion html to snapshot', () => { }, ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -259,7 +272,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -776,7 +789,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -914,7 +927,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1018,7 +1031,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1069,7 +1082,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1139,7 +1152,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1187,7 +1200,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1225,7 +1238,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, assets: new AssetsManager({ blob: new MemoryBlobCRUD() }), @@ -1277,7 +1290,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1319,7 +1332,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const blobCRUD = new MemoryBlobCRUD(); const key = await blobCRUD.set(new File([], 'README.pdf')); const assestsManager = new AssetsManager({ blob: blobCRUD }); @@ -1683,7 +1696,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1872,7 +1885,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1912,7 +1925,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -1967,7 +1980,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); @@ -2052,7 +2065,7 @@ describe('notion html to snapshot', () => { ], }; - const adapter = new NotionHtmlAdapter(createJob()); + const adapter = new NotionHtmlAdapter(createJob(), provider); const rawBlockSnapshot = await adapter.toBlockSnapshot({ file: html, }); diff --git a/blocksuite/blocks/src/_common/adapters/extension.ts b/blocksuite/blocks/src/_common/adapters/extension.ts index 7135e10d22..09c87f20fa 100644 --- a/blocksuite/blocks/src/_common/adapters/extension.ts +++ b/blocksuite/blocks/src/_common/adapters/extension.ts @@ -7,6 +7,7 @@ import { HtmlAdapterFactoryExtension } from './html/html.js'; import { ImageAdapterFactoryExtension } from './image.js'; import { MarkdownAdapterFactoryExtension } from './markdown/markdown.js'; import { MixTextAdapterFactoryExtension } from './mix-text.js'; +import { notionHtmlInlineToDeltaMatchers } from './notion-html/delta-converter/html-inline.js'; import { NotionHtmlAdapterFactoryExtension } from './notion-html/notion-html.js'; import { NotionTextAdapterFactoryExtension } from './notion-text.js'; import { PlainTextAdapterFactoryExtension } from './plain-text/plain-text.js'; @@ -14,6 +15,7 @@ import { PlainTextAdapterFactoryExtension } from './plain-text/plain-text.js'; export const AdapterFactoryExtensions: ExtensionType[] = [ ...htmlInlineToDeltaMatchers, ...inlineDeltaToHtmlAdapterMatchers, + ...notionHtmlInlineToDeltaMatchers, AttachmentAdapterFactoryExtension, ImageAdapterFactoryExtension, MarkdownAdapterFactoryExtension, diff --git a/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts b/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts index 8578f7d99a..dd657bf59a 100644 --- a/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts +++ b/blocksuite/blocks/src/_common/adapters/notion-html/block-matcher.ts @@ -1,36 +1,35 @@ -import { attachmentBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-attachment'; -import { bookmarkBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-bookmark'; +import { AttachmentBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-attachment'; +import { BookmarkBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-bookmark'; import { - embedFigmaBlockNotionHtmlAdapterMatcher, - embedGithubBlockNotionHtmlAdapterMatcher, - embedLoomBlockNotionHtmlAdapterMatcher, - embedYoutubeBlockNotionHtmlAdapterMatcher, + EmbedFigmaBlockNotionHtmlAdapterExtension, + EmbedGithubBlockNotionHtmlAdapterExtension, + EmbedLoomBlockNotionHtmlAdapterExtension, + EmbedYoutubeBlockNotionHtmlAdapterExtension, } from '@blocksuite/affine-block-embed'; -import { imageBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-image'; -import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list'; -import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph'; -import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters'; +import { ImageBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-image'; +import { ListBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-list'; +import { ParagraphBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-paragraph'; +import type { ExtensionType } from '@blocksuite/block-std'; -import { codeBlockNotionHtmlAdapterMatcher } from '../../../code-block/adapters/notion-html.js'; -import { databaseBlockNotionHtmlAdapterMatcher } from '../../../database-block/adapters/notion-html.js'; -import { dividerBlockNotionHtmlAdapterMatcher } from '../../../divider-block/adapters/notion-html.js'; -import { latexBlockNotionHtmlAdapterMatcher } from '../../../latex-block/adapters/notion-html.js'; -import { rootBlockNotionHtmlAdapterMatcher } from '../../../root-block/adapters/notion-html.js'; +import { CodeBlockNotionHtmlAdapterExtension } from '../../../code-block/adapters/notion-html.js'; +import { DatabaseBlockNotionHtmlAdapterExtension } from '../../../database-block/adapters/notion-html.js'; +import { DividerBlockNotionHtmlAdapterExtension } from '../../../divider-block/adapters/notion-html.js'; +import { LatexBlockNotionHtmlAdapterExtension } from '../../../latex-block/adapters/notion-html.js'; +import { RootBlockNotionHtmlAdapterExtension } from '../../../root-block/adapters/notion-html.js'; -export const defaultBlockNotionHtmlAdapterMatchers: BlockNotionHtmlAdapterMatcher[] = - [ - listBlockNotionHtmlAdapterMatcher, - paragraphBlockNotionHtmlAdapterMatcher, - codeBlockNotionHtmlAdapterMatcher, - dividerBlockNotionHtmlAdapterMatcher, - imageBlockNotionHtmlAdapterMatcher, - rootBlockNotionHtmlAdapterMatcher, - bookmarkBlockNotionHtmlAdapterMatcher, - databaseBlockNotionHtmlAdapterMatcher, - latexBlockNotionHtmlAdapterMatcher, - embedYoutubeBlockNotionHtmlAdapterMatcher, - embedFigmaBlockNotionHtmlAdapterMatcher, - embedGithubBlockNotionHtmlAdapterMatcher, - embedLoomBlockNotionHtmlAdapterMatcher, - attachmentBlockNotionHtmlAdapterMatcher, - ]; +export const defaultBlockNotionHtmlAdapterMatchers: ExtensionType[] = [ + ListBlockNotionHtmlAdapterExtension, + ParagraphBlockNotionHtmlAdapterExtension, + CodeBlockNotionHtmlAdapterExtension, + DividerBlockNotionHtmlAdapterExtension, + ImageBlockNotionHtmlAdapterExtension, + RootBlockNotionHtmlAdapterExtension, + BookmarkBlockNotionHtmlAdapterExtension, + DatabaseBlockNotionHtmlAdapterExtension, + LatexBlockNotionHtmlAdapterExtension, + EmbedYoutubeBlockNotionHtmlAdapterExtension, + EmbedFigmaBlockNotionHtmlAdapterExtension, + EmbedGithubBlockNotionHtmlAdapterExtension, + EmbedLoomBlockNotionHtmlAdapterExtension, + AttachmentBlockNotionHtmlAdapterExtension, +]; diff --git a/blocksuite/blocks/src/_common/adapters/notion-html/delta-converter/html-inline.ts b/blocksuite/blocks/src/_common/adapters/notion-html/delta-converter/html-inline.ts index 0b5c9afc61..3dfc151bf0 100644 --- a/blocksuite/blocks/src/_common/adapters/notion-html/delta-converter/html-inline.ts +++ b/blocksuite/blocks/src/_common/adapters/notion-html/delta-converter/html-inline.ts @@ -1,8 +1,9 @@ import { HastUtils, type HtmlAST, - type NotionHtmlASTToDeltaMatcher, + NotionHtmlASTToDeltaExtension, } from '@blocksuite/affine-shared/adapters'; +import type { ExtensionType } from '@blocksuite/block-std'; import { collapseWhiteSpace } from 'collapse-white-space'; import type { Element, Text } from 'hast'; @@ -21,7 +22,7 @@ const italicElementTags = new Set(['i', 'em']); const NotionInlineEquationToken = 'notion-text-equation-token'; const NotionUnderlineStyleToken = 'border-bottom:0.05em solid'; -export const notionHtmlTextToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { +export const notionHtmlTextToDeltaMatcher = NotionHtmlASTToDeltaExtension({ name: 'text', match: ast => isText(ast), toDelta: (ast, context) => { @@ -45,10 +46,10 @@ export const notionHtmlTextToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { } return []; }, -}; +}); -export const notionHtmlSpanElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { +export const notionHtmlSpanElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'span-element', match: ast => isElement(ast) && ast.tagName === 'span', toDelta: (ast, context) => { @@ -82,18 +83,18 @@ export const notionHtmlSpanElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = return ast.children.flatMap(child => toDelta(child, options)); }, - }; + }); -export const notionHtmlListToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { +export const notionHtmlListToDeltaMatcher = NotionHtmlASTToDeltaExtension({ name: 'list-element', match: ast => isElement(ast) && listElementTags.has(ast.tagName), toDelta: () => { return []; }, -}; +}); -export const notionHtmlStrongElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { +export const notionHtmlStrongElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'strong-element', match: ast => isElement(ast) && strongElementTags.has(ast.tagName), toDelta: (ast, context) => { @@ -109,10 +110,10 @@ export const notionHtmlStrongElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher }) ); }, - }; + }); -export const notionHtmlItalicElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { +export const notionHtmlItalicElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'italic-element', match: ast => isElement(ast) && italicElementTags.has(ast.tagName), toDelta: (ast, context) => { @@ -127,9 +128,10 @@ export const notionHtmlItalicElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher }) ); }, - }; -export const notionHtmlCodeElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { + }); + +export const notionHtmlCodeElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'code-element', match: ast => isElement(ast) && ast.tagName === 'code', toDelta: (ast, context) => { @@ -144,27 +146,29 @@ export const notionHtmlCodeElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = }) ); }, - }; + }); -export const notionHtmlDelElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { - name: 'del-element', - match: ast => isElement(ast) && ast.tagName === 'del', - toDelta: (ast, context) => { - if (!isElement(ast)) { - return []; - } - const { toDelta, options } = context; - return ast.children.flatMap(child => - toDelta(child, options).map(delta => { - delta.attributes = { ...delta.attributes, strike: true }; - return delta; - }) - ); - }, -}; - -export const notionHtmlUnderlineElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = +export const notionHtmlDelElementToDeltaMatcher = NotionHtmlASTToDeltaExtension( { + name: 'del-element', + match: ast => isElement(ast) && ast.tagName === 'del', + toDelta: (ast, context) => { + if (!isElement(ast)) { + return []; + } + const { toDelta, options } = context; + return ast.children.flatMap(child => + toDelta(child, options).map(delta => { + delta.attributes = { ...delta.attributes, strike: true }; + return delta; + }) + ); + }, + } +); + +export const notionHtmlUnderlineElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'underline-element', match: ast => isElement(ast) && ast.tagName === 'u', toDelta: (ast, context) => { @@ -179,10 +183,10 @@ export const notionHtmlUnderlineElementToDeltaMatcher: NotionHtmlASTToDeltaMatch }) ); }, - }; + }); -export const notionHtmlLinkElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { +export const notionHtmlLinkElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'link-element', match: ast => isElement(ast) && ast.tagName === 'a', toDelta: (ast, context) => { @@ -222,10 +226,10 @@ export const notionHtmlLinkElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = }) ); }, - }; + }); -export const notionHtmlMarkElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { +export const notionHtmlMarkElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'mark-element', match: ast => isElement(ast) && ast.tagName === 'mark', toDelta: (ast, context) => { @@ -240,9 +244,9 @@ export const notionHtmlMarkElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = }) ); }, - }; + }); -export const notionHtmlLiElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { +export const notionHtmlLiElementToDeltaMatcher = NotionHtmlASTToDeltaExtension({ name: 'li-element', match: ast => isElement(ast) && @@ -260,26 +264,26 @@ export const notionHtmlLiElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { .slice(checkBoxIndex + 2) .flatMap(child => toDelta(child, options)); }, -}; +}); -export const notionHtmlBrElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = { +export const notionHtmlBrElementToDeltaMatcher = NotionHtmlASTToDeltaExtension({ name: 'br-element', match: ast => isElement(ast) && ast.tagName === 'br', toDelta: () => { return [{ insert: '\n' }]; }, -}; +}); -export const notionHtmlStyleElementToDeltaMatcher: NotionHtmlASTToDeltaMatcher = - { +export const notionHtmlStyleElementToDeltaMatcher = + NotionHtmlASTToDeltaExtension({ name: 'style-element', match: ast => isElement(ast) && ast.tagName === 'style', toDelta: () => { return []; }, - }; + }); -export const notionHtmlInlineToDeltaMatchers: NotionHtmlASTToDeltaMatcher[] = [ +export const notionHtmlInlineToDeltaMatchers: ExtensionType[] = [ notionHtmlTextToDeltaMatcher, notionHtmlSpanElementToDeltaMatcher, notionHtmlStrongElementToDeltaMatcher, diff --git a/blocksuite/blocks/src/_common/adapters/notion-html/notion-html.ts b/blocksuite/blocks/src/_common/adapters/notion-html/notion-html.ts index 885da785cc..3abd966275 100644 --- a/blocksuite/blocks/src/_common/adapters/notion-html/notion-html.ts +++ b/blocksuite/blocks/src/_common/adapters/notion-html/notion-html.ts @@ -9,9 +9,11 @@ import { HastUtils, type HtmlAST, type NotionHtml, + NotionHtmlASTToDeltaMatcherIdentifier, NotionHtmlDeltaConverter, } from '@blocksuite/affine-shared/adapters'; import type { ExtensionType } from '@blocksuite/block-std'; +import type { ServiceProvider } from '@blocksuite/global/di'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { type AssetsManager, @@ -33,8 +35,6 @@ import rehypeParse from 'rehype-parse'; import { unified } from 'unified'; import { AdapterFactoryIdentifier } from '../type.js'; -import { defaultBlockNotionHtmlAdapterMatchers } from './block-matcher.js'; -import { notionHtmlInlineToDeltaMatchers } from './delta-converter/html-inline.js'; type NotionHtmlToSliceSnapshotPayload = { file: NotionHtml; @@ -112,11 +112,17 @@ export class NotionHtmlAdapter extends BaseAdapter { deltaConverter: NotionHtmlDeltaConverter; - constructor( - job: Job, - readonly blockMatchers: BlockNotionHtmlAdapterMatcher[] = defaultBlockNotionHtmlAdapterMatchers - ) { + readonly blockMatchers: BlockNotionHtmlAdapterMatcher[]; + + constructor(job: Job, provider: ServiceProvider) { super(job); + const blockMatchers = Array.from( + provider.getAll(BlockNotionHtmlAdapterMatcherIdentifier).values() + ); + const notionHtmlInlineToDeltaMatchers = Array.from( + provider.getAll(NotionHtmlASTToDeltaMatcherIdentifier).values() + ); + this.blockMatchers = blockMatchers; this.deltaConverter = new NotionHtmlDeltaConverter( job.adapterConfigs, [], @@ -287,13 +293,7 @@ export const NotionHtmlAdapterFactoryIdentifier = export const NotionHtmlAdapterFactoryExtension: ExtensionType = { setup: di => { di.addImpl(NotionHtmlAdapterFactoryIdentifier, provider => ({ - get: (job: Job) => - new NotionHtmlAdapter( - job, - Array.from( - provider.getAll(BlockNotionHtmlAdapterMatcherIdentifier).values() - ) - ), + get: (job: Job) => new NotionHtmlAdapter(job, provider), })); }, }; diff --git a/blocksuite/blocks/src/_common/transformers/notion-html.ts b/blocksuite/blocks/src/_common/transformers/notion-html.ts index bdddd16bb1..aeecb097f6 100644 --- a/blocksuite/blocks/src/_common/transformers/notion-html.ts +++ b/blocksuite/blocks/src/_common/transformers/notion-html.ts @@ -1,6 +1,9 @@ +import { Container } from '@blocksuite/global/di'; import { sha } from '@blocksuite/global/utils'; import { type DocCollection, extMimeMap, Job } from '@blocksuite/store'; +import { defaultBlockNotionHtmlAdapterMatchers } from '../adapters/notion-html/block-matcher.js'; +import { notionHtmlInlineToDeltaMatchers } from '../adapters/notion-html/delta-converter/html-inline.js'; import { NotionHtmlAdapter } from '../adapters/notion-html/notion-html.js'; import { defaultImageProxyMiddleware } from './middlewares.js'; import { Unzip } from './utils.js'; @@ -10,6 +13,16 @@ type ImportNotionZipOptions = { imported: Blob; }; +const container = new Container(); +[ + ...notionHtmlInlineToDeltaMatchers, + ...defaultBlockNotionHtmlAdapterMatchers, +].forEach(ext => { + ext.setup(container); +}); + +const provider = container.provider(); + /** * Imports a Notion zip file into the BlockSuite collection. * @@ -109,7 +122,7 @@ async function importNotionZip({ collection: collection, middlewares: [defaultImageProxyMiddleware], }); - const htmlAdapter = new NotionHtmlAdapter(job); + const htmlAdapter = new NotionHtmlAdapter(job, provider); const assets = job.assetsManager.getAssets(); const pathBlobIdMap = job.assetsManager.getPathBlobIdMap(); for (const [key, value] of pendingAssets.entries()) { diff --git a/tsconfig.project.json b/tsconfig.project.json index c5c59a86e2..b5c5893da0 100644 --- a/tsconfig.project.json +++ b/tsconfig.project.json @@ -12,6 +12,7 @@ { "path": "./blocksuite/affine/block-embed" }, { "path": "./blocksuite/affine/block-image" }, { "path": "./blocksuite/affine/block-list" }, + { "path": "./blocksuite/affine/block-note" }, { "path": "./blocksuite/affine/block-paragraph" }, { "path": "./blocksuite/affine/block-surface" }, { "path": "./blocksuite/affine/components" },