@atlaskit/editor-plugin-card
Version:
Card plugin for @atlaskit/editor-core
84 lines (81 loc) • 3.69 kB
JavaScript
import { canRenderDatasource, hasDocAsParent } from '@atlaskit/editor-common/utils';
import { setProvider } from '../actions';
import { handleFallbackWithAnalytics, replaceQueuedUrlWithCard } from '../doc';
const isFreshlyPastedOnNewLine = view => {
const {
selection
} = view.state;
const {
$cursor,
$anchor
} = selection;
if (!$cursor) {
return false;
}
if (!hasDocAsParent($anchor)) {
return false;
}
const node = $cursor.node();
if (!node) {
return false;
}
if (node.type.name !== 'paragraph') {
return false;
}
return node.childCount === 1; // The pasted blue link itself
};
// ============================================================================ //
// ============================== PROVIDER UTILS ============================== //
// ============================================================================ //
// Used for all interactions with the EditorCardProvider.
// ============================================================================ //
export const resolveWithProvider = (view, provider, request, options, editorAnalyticsApi, createAnalyticsEvent, embedCardNodeTransformer) => {
const isEmbedFriendlyLocation = isFreshlyPastedOnNewLine(view);
// When user manually changes appearance from blue link to smart link, we should respect that,
const shouldForceAppearance =
// This flag is set to true only in one place atm:
// packages/editor/editor-core/src/plugins/card/pm-plugins/doc.ts @ convertHyperlinkToSmartCard
// Which is used when user switching from URL to smart link appearance.
!!request.shouldReplaceLink;
const handleResolve = provider.resolve(request.url, request.appearance, shouldForceAppearance, isEmbedFriendlyLocation).then(handleResolved(view, request, editorAnalyticsApi, createAnalyticsEvent, options, embedCardNodeTransformer), handleRejected(view, request, editorAnalyticsApi));
return handleResolve;
};
const updateCardType = (resolvedCard, options) => {
if (resolvedCard.type === 'blockCard' && 'datasource' in resolvedCard.attrs) {
const datasourceId = resolvedCard.attrs.datasource.id;
if (!options.allowDatasource || !canRenderDatasource(datasourceId)) {
delete resolvedCard.attrs.datasource;
resolvedCard.type = 'inlineCard';
return;
}
}
if ((resolvedCard === null || resolvedCard === void 0 ? void 0 : resolvedCard.type) === 'blockCard' && !options.allowBlockCards || (resolvedCard === null || resolvedCard === void 0 ? void 0 : resolvedCard.type) === 'embedCard' && !options.allowEmbeds) {
// clean out the 'layout' attr from an embedCard type that should be transformed into the inlineCard type.
if (resolvedCard.type === 'embedCard') {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete resolvedCard.attrs.layout;
}
resolvedCard.type = 'inlineCard';
}
};
const handleResolved = (view, request, editorAnalyticsApi, createAnalyticsEvent, options, embedCardNodeTransformer) => resolvedCard => {
updateCardType(resolvedCard, options);
replaceQueuedUrlWithCard(request.url, resolvedCard, request.analyticsAction, editorAnalyticsApi, createAnalyticsEvent, embedCardNodeTransformer)(view.state, view.dispatch);
return resolvedCard;
};
const handleRejected = (view, request, editorAnalyticsApi) => () => {
handleFallbackWithAnalytics(request, editorAnalyticsApi)(view.state, view.dispatch);
};
// listen for card provider changes
export const handleProvider = (_, provider, view) => {
if (!provider) {
return;
}
provider.then(cardProvider => {
const {
state,
dispatch
} = view;
dispatch(setProvider(cardProvider)(state.tr));
});
};