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,
};
}