fix(editor): notion html adapter for embed link block (#9279)
[BS-1745](https://linear.app/affine-design/issue/BS-1745/[bug]-导入的notion-youtube-embed-错误)
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
if (!embededURL || typeof embededURL !== 'string') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// To avoid polynomial regular expression used on uncontrolled data
|
||||||
|
// https://codeql.github.com/codeql-query-help/javascript/js-polynomial-redos/
|
||||||
|
if (embededURL.length > 1000) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return 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,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std';
|
|||||||
|
|
||||||
import { EmbedFigmaBlockHtmlAdapterExtension } from './html.js';
|
import { EmbedFigmaBlockHtmlAdapterExtension } from './html.js';
|
||||||
import { EmbedFigmaMarkdownAdapterExtension } from './markdown.js';
|
import { EmbedFigmaMarkdownAdapterExtension } from './markdown.js';
|
||||||
|
import { EmbedFigmaNotionHtmlAdapterExtension } from './notion-html.js';
|
||||||
import { EmbedFigmaBlockPlainTextAdapterExtension } from './plain-text.js';
|
import { EmbedFigmaBlockPlainTextAdapterExtension } from './plain-text.js';
|
||||||
|
|
||||||
export const EmbedFigmaBlockAdapterExtensions: ExtensionType[] = [
|
export const EmbedFigmaBlockAdapterExtensions: ExtensionType[] = [
|
||||||
EmbedFigmaBlockHtmlAdapterExtension,
|
EmbedFigmaBlockHtmlAdapterExtension,
|
||||||
EmbedFigmaMarkdownAdapterExtension,
|
EmbedFigmaMarkdownAdapterExtension,
|
||||||
EmbedFigmaBlockPlainTextAdapterExtension,
|
EmbedFigmaBlockPlainTextAdapterExtension,
|
||||||
|
EmbedFigmaNotionHtmlAdapterExtension,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './html.js';
|
export * from './html.js';
|
||||||
export * from './markdown.js';
|
export * from './markdown.js';
|
||||||
|
export * from './notion-html.js';
|
||||||
export * from './plain-text.js';
|
export * from './plain-text.js';
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -2,10 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std';
|
|||||||
|
|
||||||
import { EmbedGithubBlockHtmlAdapterExtension } from './html.js';
|
import { EmbedGithubBlockHtmlAdapterExtension } from './html.js';
|
||||||
import { EmbedGithubMarkdownAdapterExtension } from './markdown.js';
|
import { EmbedGithubMarkdownAdapterExtension } from './markdown.js';
|
||||||
|
import { EmbedGithubNotionHtmlAdapterExtension } from './notion-html.js';
|
||||||
import { EmbedGithubBlockPlainTextAdapterExtension } from './plain-text.js';
|
import { EmbedGithubBlockPlainTextAdapterExtension } from './plain-text.js';
|
||||||
|
|
||||||
export const EmbedGithubBlockAdapterExtensions: ExtensionType[] = [
|
export const EmbedGithubBlockAdapterExtensions: ExtensionType[] = [
|
||||||
EmbedGithubBlockHtmlAdapterExtension,
|
EmbedGithubBlockHtmlAdapterExtension,
|
||||||
EmbedGithubMarkdownAdapterExtension,
|
EmbedGithubMarkdownAdapterExtension,
|
||||||
EmbedGithubBlockPlainTextAdapterExtension,
|
EmbedGithubBlockPlainTextAdapterExtension,
|
||||||
|
EmbedGithubNotionHtmlAdapterExtension,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './html.js';
|
export * from './html.js';
|
||||||
export * from './markdown.js';
|
export * from './markdown.js';
|
||||||
|
export * from './notion-html.js';
|
||||||
export * from './plain-text.js';
|
export * from './plain-text.js';
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -2,10 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std';
|
|||||||
|
|
||||||
import { EmbedLoomBlockHtmlAdapterExtension } from './html.js';
|
import { EmbedLoomBlockHtmlAdapterExtension } from './html.js';
|
||||||
import { EmbedLoomMarkdownAdapterExtension } from './markdown.js';
|
import { EmbedLoomMarkdownAdapterExtension } from './markdown.js';
|
||||||
|
import { EmbedLoomNotionHtmlAdapterExtension } from './notion-html.js';
|
||||||
import { EmbedLoomBlockPlainTextAdapterExtension } from './plain-text.js';
|
import { EmbedLoomBlockPlainTextAdapterExtension } from './plain-text.js';
|
||||||
|
|
||||||
export const EmbedLoomBlockAdapterExtensions: ExtensionType[] = [
|
export const EmbedLoomBlockAdapterExtensions: ExtensionType[] = [
|
||||||
EmbedLoomBlockHtmlAdapterExtension,
|
EmbedLoomBlockHtmlAdapterExtension,
|
||||||
EmbedLoomMarkdownAdapterExtension,
|
EmbedLoomMarkdownAdapterExtension,
|
||||||
EmbedLoomBlockPlainTextAdapterExtension,
|
EmbedLoomBlockPlainTextAdapterExtension,
|
||||||
|
EmbedLoomNotionHtmlAdapterExtension,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './html.js';
|
export * from './html.js';
|
||||||
export * from './markdown.js';
|
export * from './markdown.js';
|
||||||
|
export * from './notion-html.js';
|
||||||
export * from './plain-text.js';
|
export * from './plain-text.js';
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -2,10 +2,12 @@ import type { ExtensionType } from '@blocksuite/block-std';
|
|||||||
|
|
||||||
import { EmbedYoutubeBlockHtmlAdapterExtension } from './html.js';
|
import { EmbedYoutubeBlockHtmlAdapterExtension } from './html.js';
|
||||||
import { EmbedYoutubeMarkdownAdapterExtension } from './markdown.js';
|
import { EmbedYoutubeMarkdownAdapterExtension } from './markdown.js';
|
||||||
|
import { EmbedYoutubeNotionHtmlAdapterExtension } from './notion-html.js';
|
||||||
import { EmbedYoutubeBlockPlainTextAdapterExtension } from './plain-text.js';
|
import { EmbedYoutubeBlockPlainTextAdapterExtension } from './plain-text.js';
|
||||||
|
|
||||||
export const EmbedYoutubeBlockAdapterExtensions: ExtensionType[] = [
|
export const EmbedYoutubeBlockAdapterExtensions: ExtensionType[] = [
|
||||||
EmbedYoutubeBlockHtmlAdapterExtension,
|
EmbedYoutubeBlockHtmlAdapterExtension,
|
||||||
EmbedYoutubeMarkdownAdapterExtension,
|
EmbedYoutubeMarkdownAdapterExtension,
|
||||||
EmbedYoutubeBlockPlainTextAdapterExtension,
|
EmbedYoutubeBlockPlainTextAdapterExtension,
|
||||||
|
EmbedYoutubeNotionHtmlAdapterExtension,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from './html.js';
|
export * from './html.js';
|
||||||
export * from './markdown.js';
|
export * from './markdown.js';
|
||||||
|
export * from './notion-html.js';
|
||||||
export * from './plain-text.js';
|
export * from './plain-text.js';
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
import {
|
||||||
|
embedFigmaBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedGithubBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedLoomBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedYoutubeBlockNotionHtmlAdapterMatcher,
|
||||||
|
} from '@blocksuite/affine-block-embed';
|
||||||
import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list';
|
import { listBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-list';
|
||||||
import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph';
|
import { paragraphBlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-block-paragraph';
|
||||||
import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters';
|
import type { BlockNotionHtmlAdapterMatcher } from '@blocksuite/affine-shared/adapters';
|
||||||
@@ -21,6 +27,10 @@ export const defaultBlockNotionHtmlAdapterMatchers: BlockNotionHtmlAdapterMatche
|
|||||||
rootBlockNotionHtmlAdapterMatcher,
|
rootBlockNotionHtmlAdapterMatcher,
|
||||||
bookmarkBlockNotionHtmlAdapterMatcher,
|
bookmarkBlockNotionHtmlAdapterMatcher,
|
||||||
databaseBlockNotionHtmlAdapterMatcher,
|
databaseBlockNotionHtmlAdapterMatcher,
|
||||||
attachmentBlockNotionHtmlAdapterMatcher,
|
|
||||||
latexBlockNotionHtmlAdapterMatcher,
|
latexBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedYoutubeBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedFigmaBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedGithubBlockNotionHtmlAdapterMatcher,
|
||||||
|
embedLoomBlockNotionHtmlAdapterMatcher,
|
||||||
|
attachmentBlockNotionHtmlAdapterMatcher,
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user