From b029b59d2330b39492f55cfa6f90c432874d4e53 Mon Sep 17 00:00:00 2001 From: Chen <99816898+donteatfriedrice@users.noreply.github.com> Date: Fri, 20 Dec 2024 15:58:58 +0800 Subject: [PATCH] fix(blocks): notion html embed youtube support --- .../src/common/adapters/notion-html.ts | 84 +++++++++++++++++++ .../embed-figma-block/adapters/extension.ts | 2 + .../src/embed-figma-block/adapters/index.ts | 1 + .../embed-figma-block/adapters/notion-html.ts | 14 ++++ .../embed-github-block/adapters/extension.ts | 2 + .../src/embed-github-block/adapters/index.ts | 1 + .../adapters/notion-html.ts | 14 ++++ .../embed-loom-block/adapters/extension.ts | 2 + .../src/embed-loom-block/adapters/index.ts | 1 + .../embed-loom-block/adapters/notion-html.ts | 14 ++++ .../embed-youtube-block/adapters/extension.ts | 2 + .../src/embed-youtube-block/adapters/index.ts | 1 + .../adapters/notion-html.ts | 14 ++++ .../adapters/notion-html/block-matcher.ts | 12 ++- 14 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 packages/affine/block-embed/src/common/adapters/notion-html.ts create mode 100644 packages/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts create mode 100644 packages/affine/block-embed/src/embed-github-block/adapters/notion-html.ts create mode 100644 packages/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts create mode 100644 packages/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts diff --git a/packages/affine/block-embed/src/common/adapters/notion-html.ts b/packages/affine/block-embed/src/common/adapters/notion-html.ts new file mode 100644 index 000000000000..1caa773b92aa --- /dev/null +++ b/packages/affine/block-embed/src/common/adapters/notion-html.ts @@ -0,0 +1,84 @@ +import { + type BlockNotionHtmlAdapterMatcher, + HastUtils, +} from '@blocksuite/affine-shared/adapters'; +import { nanoid } from '@blocksuite/store'; + +export function createEmbedBlockNotionHtmlAdapterMatcher( + flavour: string, + urlRegex: RegExp, + { + toMatch = o => { + const isFigure = + HastUtils.isElement(o.node) && o.node.tagName === 'figure'; + const embededFigureWrapper = HastUtils.querySelector(o.node, '.source'); + if (!isFigure || !embededFigureWrapper) { + return false; + } + const embededURL = HastUtils.querySelector(embededFigureWrapper, 'a') + ?.properties.href; + return ( + !!embededURL && + typeof embededURL === 'string' && + urlRegex.test(embededURL) + ); + }, + fromMatch = o => o.node.flavour === flavour, + toBlockSnapshot = { + enter: (o, context) => { + if (!HastUtils.isElement(o.node)) { + return; + } + const { assets, walkerContext } = context; + if (!assets) { + return; + } + + const embededFigureWrapper = HastUtils.querySelector(o.node, '.source'); + if (!embededFigureWrapper) { + return; + } + + let embededURL = ''; + const embedA = HastUtils.querySelector(embededFigureWrapper, 'a'); + embededURL = + typeof embedA?.properties.href === 'string' + ? embedA.properties.href + : ''; + if (!embededURL) { + return; + } + + walkerContext + .openNode( + { + type: 'block', + id: nanoid(), + flavour, + props: { + url: embededURL, + }, + children: [], + }, + 'children' + ) + .closeNode(); + walkerContext.skipAllChildren(); + }, + }, + fromBlockSnapshot = {}, + }: { + toMatch?: BlockNotionHtmlAdapterMatcher['toMatch']; + fromMatch?: BlockNotionHtmlAdapterMatcher['fromMatch']; + toBlockSnapshot?: BlockNotionHtmlAdapterMatcher['toBlockSnapshot']; + fromBlockSnapshot?: BlockNotionHtmlAdapterMatcher['fromBlockSnapshot']; + } = Object.create(null) +): BlockNotionHtmlAdapterMatcher { + return { + flavour, + toMatch, + fromMatch, + toBlockSnapshot, + fromBlockSnapshot, + }; +} diff --git a/packages/affine/block-embed/src/embed-figma-block/adapters/extension.ts b/packages/affine/block-embed/src/embed-figma-block/adapters/extension.ts index 1b8017c5a4e8..831deba68046 100644 --- a/packages/affine/block-embed/src/embed-figma-block/adapters/extension.ts +++ b/packages/affine/block-embed/src/embed-figma-block/adapters/extension.ts @@ -2,10 +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 { EmbedFigmaBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedFigmaBlockAdapterExtensions: ExtensionType[] = [ EmbedFigmaBlockHtmlAdapterExtension, EmbedFigmaMarkdownAdapterExtension, EmbedFigmaBlockPlainTextAdapterExtension, + EmbedFigmaNotionHtmlAdapterExtension, ]; diff --git a/packages/affine/block-embed/src/embed-figma-block/adapters/index.ts b/packages/affine/block-embed/src/embed-figma-block/adapters/index.ts index c1d476903d99..b4dd5a6d2a7e 100644 --- a/packages/affine/block-embed/src/embed-figma-block/adapters/index.ts +++ b/packages/affine/block-embed/src/embed-figma-block/adapters/index.ts @@ -1,3 +1,4 @@ export * from './html.js'; export * from './markdown.js'; +export * from './notion-html.js'; export * from './plain-text.js'; diff --git a/packages/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts b/packages/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts new file mode 100644 index 000000000000..53119d95792d --- /dev/null +++ b/packages/affine/block-embed/src/embed-figma-block/adapters/notion-html.ts @@ -0,0 +1,14 @@ +import { EmbedFigmaBlockSchema } from '@blocksuite/affine-model'; +import { BlockNotionHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters'; + +import { createEmbedBlockNotionHtmlAdapterMatcher } from '../../common/adapters/notion-html.js'; +import { figmaUrlRegex } from '../embed-figma-model.js'; + +export const embedFigmaBlockNotionHtmlAdapterMatcher = + createEmbedBlockNotionHtmlAdapterMatcher( + EmbedFigmaBlockSchema.model.flavour, + figmaUrlRegex + ); + +export const EmbedFigmaNotionHtmlAdapterExtension = + BlockNotionHtmlAdapterExtension(embedFigmaBlockNotionHtmlAdapterMatcher); diff --git a/packages/affine/block-embed/src/embed-github-block/adapters/extension.ts b/packages/affine/block-embed/src/embed-github-block/adapters/extension.ts index 5c6fa5cb57be..3f548aedcb91 100644 --- a/packages/affine/block-embed/src/embed-github-block/adapters/extension.ts +++ b/packages/affine/block-embed/src/embed-github-block/adapters/extension.ts @@ -2,10 +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 { EmbedGithubBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedGithubBlockAdapterExtensions: ExtensionType[] = [ EmbedGithubBlockHtmlAdapterExtension, EmbedGithubMarkdownAdapterExtension, EmbedGithubBlockPlainTextAdapterExtension, + EmbedGithubNotionHtmlAdapterExtension, ]; diff --git a/packages/affine/block-embed/src/embed-github-block/adapters/index.ts b/packages/affine/block-embed/src/embed-github-block/adapters/index.ts index c1d476903d99..b4dd5a6d2a7e 100644 --- a/packages/affine/block-embed/src/embed-github-block/adapters/index.ts +++ b/packages/affine/block-embed/src/embed-github-block/adapters/index.ts @@ -1,3 +1,4 @@ export * from './html.js'; export * from './markdown.js'; +export * from './notion-html.js'; export * from './plain-text.js'; diff --git a/packages/affine/block-embed/src/embed-github-block/adapters/notion-html.ts b/packages/affine/block-embed/src/embed-github-block/adapters/notion-html.ts new file mode 100644 index 000000000000..20022c2345ab --- /dev/null +++ b/packages/affine/block-embed/src/embed-github-block/adapters/notion-html.ts @@ -0,0 +1,14 @@ +import { EmbedGithubBlockSchema } from '@blocksuite/affine-model'; +import { BlockNotionHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters'; + +import { createEmbedBlockNotionHtmlAdapterMatcher } from '../../common/adapters/notion-html.js'; +import { githubUrlRegex } from '../embed-github-model.js'; + +export const embedGithubBlockNotionHtmlAdapterMatcher = + createEmbedBlockNotionHtmlAdapterMatcher( + EmbedGithubBlockSchema.model.flavour, + githubUrlRegex + ); + +export const EmbedGithubNotionHtmlAdapterExtension = + BlockNotionHtmlAdapterExtension(embedGithubBlockNotionHtmlAdapterMatcher); diff --git a/packages/affine/block-embed/src/embed-loom-block/adapters/extension.ts b/packages/affine/block-embed/src/embed-loom-block/adapters/extension.ts index 13afbf167caf..d742f5c575f9 100644 --- a/packages/affine/block-embed/src/embed-loom-block/adapters/extension.ts +++ b/packages/affine/block-embed/src/embed-loom-block/adapters/extension.ts @@ -2,10 +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 { EmbedLoomBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedLoomBlockAdapterExtensions: ExtensionType[] = [ EmbedLoomBlockHtmlAdapterExtension, EmbedLoomMarkdownAdapterExtension, EmbedLoomBlockPlainTextAdapterExtension, + EmbedLoomNotionHtmlAdapterExtension, ]; diff --git a/packages/affine/block-embed/src/embed-loom-block/adapters/index.ts b/packages/affine/block-embed/src/embed-loom-block/adapters/index.ts index c1d476903d99..b4dd5a6d2a7e 100644 --- a/packages/affine/block-embed/src/embed-loom-block/adapters/index.ts +++ b/packages/affine/block-embed/src/embed-loom-block/adapters/index.ts @@ -1,3 +1,4 @@ export * from './html.js'; export * from './markdown.js'; +export * from './notion-html.js'; export * from './plain-text.js'; diff --git a/packages/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts b/packages/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts new file mode 100644 index 000000000000..db06ca0b5719 --- /dev/null +++ b/packages/affine/block-embed/src/embed-loom-block/adapters/notion-html.ts @@ -0,0 +1,14 @@ +import { EmbedLoomBlockSchema } from '@blocksuite/affine-model'; +import { BlockNotionHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters'; + +import { createEmbedBlockNotionHtmlAdapterMatcher } from '../../common/adapters/notion-html.js'; +import { loomUrlRegex } from '../embed-loom-model.js'; + +export const embedLoomBlockNotionHtmlAdapterMatcher = + createEmbedBlockNotionHtmlAdapterMatcher( + EmbedLoomBlockSchema.model.flavour, + loomUrlRegex + ); + +export const EmbedLoomNotionHtmlAdapterExtension = + BlockNotionHtmlAdapterExtension(embedLoomBlockNotionHtmlAdapterMatcher); diff --git a/packages/affine/block-embed/src/embed-youtube-block/adapters/extension.ts b/packages/affine/block-embed/src/embed-youtube-block/adapters/extension.ts index 8ef9c011bb6e..f3f6bb2489ed 100644 --- a/packages/affine/block-embed/src/embed-youtube-block/adapters/extension.ts +++ b/packages/affine/block-embed/src/embed-youtube-block/adapters/extension.ts @@ -2,10 +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 { EmbedYoutubeBlockPlainTextAdapterExtension } from './plain-text.js'; export const EmbedYoutubeBlockAdapterExtensions: ExtensionType[] = [ EmbedYoutubeBlockHtmlAdapterExtension, EmbedYoutubeMarkdownAdapterExtension, EmbedYoutubeBlockPlainTextAdapterExtension, + EmbedYoutubeNotionHtmlAdapterExtension, ]; diff --git a/packages/affine/block-embed/src/embed-youtube-block/adapters/index.ts b/packages/affine/block-embed/src/embed-youtube-block/adapters/index.ts index c1d476903d99..b4dd5a6d2a7e 100644 --- a/packages/affine/block-embed/src/embed-youtube-block/adapters/index.ts +++ b/packages/affine/block-embed/src/embed-youtube-block/adapters/index.ts @@ -1,3 +1,4 @@ export * from './html.js'; export * from './markdown.js'; +export * from './notion-html.js'; export * from './plain-text.js'; diff --git a/packages/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts b/packages/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts new file mode 100644 index 000000000000..e4da1a9e3c03 --- /dev/null +++ b/packages/affine/block-embed/src/embed-youtube-block/adapters/notion-html.ts @@ -0,0 +1,14 @@ +import { EmbedYoutubeBlockSchema } from '@blocksuite/affine-model'; +import { BlockNotionHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters'; + +import { createEmbedBlockNotionHtmlAdapterMatcher } from '../../common/adapters/notion-html.js'; +import { youtubeUrlRegex } from '../embed-youtube-model.js'; + +export const embedYoutubeBlockNotionHtmlAdapterMatcher = + createEmbedBlockNotionHtmlAdapterMatcher( + EmbedYoutubeBlockSchema.model.flavour, + youtubeUrlRegex + ); + +export const EmbedYoutubeNotionHtmlAdapterExtension = + BlockNotionHtmlAdapterExtension(embedYoutubeBlockNotionHtmlAdapterMatcher); diff --git a/packages/blocks/src/_common/adapters/notion-html/block-matcher.ts b/packages/blocks/src/_common/adapters/notion-html/block-matcher.ts index 6cbd74a5d975..e3879b771f95 100644 --- a/packages/blocks/src/_common/adapters/notion-html/block-matcher.ts +++ b/packages/blocks/src/_common/adapters/notion-html/block-matcher.ts @@ -1,5 +1,11 @@ import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters'; +import { + embedFigmaBlockNotionHtmlAdapterMatcher, + embedGithubBlockNotionHtmlAdapterMatcher, + embedLoomBlockNotionHtmlAdapterMatcher, + embedYoutubeBlockNotionHtmlAdapterMatcher, +} from '@blocksuite/affine-block-embed'; import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list'; import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph'; @@ -22,6 +28,10 @@ export const defaultBlockNotionHtmlAdapterMatchers: BlockNotionHtmlAdapterMatche rootBlockNotionHtmlAdapterMatcher, bookmarkBlockNotionHtmlAdapterMatcher, databaseBlockNotionHtmlAdapterMatcher, - attachmentBlockNotionHtmlAdapterMatcher, latexBlockNotionHtmlAdapterMatcher, + embedYoutubeBlockNotionHtmlAdapterMatcher, + embedFigmaBlockNotionHtmlAdapterMatcher, + embedGithubBlockNotionHtmlAdapterMatcher, + embedLoomBlockNotionHtmlAdapterMatcher, + attachmentBlockNotionHtmlAdapterMatcher, ];