refactor(editor): surface markdown adapter extensionalize (#9560)

[BS-2212](https://linear.app/affine-design/issue/BS-2212/adapter-extension化修复)
This commit is contained in:
donteatfriedrice
2025-01-07 03:14:08 +00:00
parent 69e9aa087e
commit 52f2e8d5d5
11 changed files with 156 additions and 117 deletions

View File

@@ -1,3 +1,4 @@
import { elementToMarkdownAdapterMatchers } from './markdown/element-adapter/elements/index.js';
import { import {
EdgelessSurfaceBlockMarkdownAdapterExtension, EdgelessSurfaceBlockMarkdownAdapterExtension,
SurfaceBlockMarkdownAdapterExtension, SurfaceBlockMarkdownAdapterExtension,
@@ -10,12 +11,14 @@ import {
export const SurfaceBlockAdapterExtensions = [ export const SurfaceBlockAdapterExtensions = [
...elementToPlainTextAdapterMatchers, ...elementToPlainTextAdapterMatchers,
...elementToMarkdownAdapterMatchers,
SurfaceBlockPlainTextAdapterExtension, SurfaceBlockPlainTextAdapterExtension,
SurfaceBlockMarkdownAdapterExtension, SurfaceBlockMarkdownAdapterExtension,
]; ];
export const EdgelessSurfaceBlockAdapterExtensions = [ export const EdgelessSurfaceBlockAdapterExtensions = [
...elementToPlainTextAdapterMatchers, ...elementToPlainTextAdapterMatchers,
...elementToMarkdownAdapterMatchers,
EdgelessSurfaceBlockPlainTextAdapterExtension, EdgelessSurfaceBlockPlainTextAdapterExtension,
EdgelessSurfaceBlockMarkdownAdapterExtension, EdgelessSurfaceBlockMarkdownAdapterExtension,
]; ];

View File

@@ -1,7 +1,6 @@
import type { ElementModelToMarkdownAdapterMatcher } from '../type.js'; import { ElementToMarkdownAdapterExtension } from '../type.js';
export const brushToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher = export const brushToMarkdownAdapterMatcher = ElementToMarkdownAdapterExtension({
{
name: 'brush', name: 'brush',
match: elementModel => elementModel.type === 'brush', match: elementModel => elementModel.type === 'brush',
toAST: () => { toAST: () => {
@@ -16,4 +15,4 @@ export const brushToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher
], ],
}; };
}, },
}; });

View File

@@ -1,8 +1,8 @@
import { getConnectorText } from '../../../utils/text.js'; import { getConnectorText } from '../../../utils/text.js';
import type { ElementModelToMarkdownAdapterMatcher } from '../type.js'; import { ElementToMarkdownAdapterExtension } from '../type.js';
export const connectorToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher = export const connectorToMarkdownAdapterMatcher =
{ ElementToMarkdownAdapterExtension({
name: 'connector', name: 'connector',
match: elementModel => elementModel.type === 'connector', match: elementModel => elementModel.type === 'connector',
toAST: elementModel => { toAST: elementModel => {
@@ -22,4 +22,4 @@ export const connectorToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMat
], ],
}; };
}, },
}; });

View File

@@ -1,8 +1,7 @@
import { getGroupTitle } from '../../../utils/text.js'; import { getGroupTitle } from '../../../utils/text.js';
import type { ElementModelToMarkdownAdapterMatcher } from '../type.js'; import { ElementToMarkdownAdapterExtension } from '../type.js';
export const groupToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher = export const groupToMarkdownAdapterMatcher = ElementToMarkdownAdapterExtension({
{
name: 'group', name: 'group',
match: elementModel => elementModel.type === 'group', match: elementModel => elementModel.type === 'group',
toAST: elementModel => { toAST: elementModel => {
@@ -22,4 +21,4 @@ export const groupToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher
], ],
}; };
}, },
}; });

View File

@@ -1,10 +1,10 @@
import type { MindMapTreeNode } from '../../../types/mindmap.js'; import type { MindMapTreeNode } from '../../../types/mindmap.js';
import { buildMindMapTree } from '../../../utils/mindmap.js'; import { buildMindMapTree } from '../../../utils/mindmap.js';
import { getShapeText } from '../../../utils/text.js'; import { getShapeText } from '../../../utils/text.js';
import type { ElementModelToMarkdownAdapterMatcher } from '../type.js'; import { ElementToMarkdownAdapterExtension } from '../type.js';
export const mindmapToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher = export const mindmapToMarkdownAdapterMatcher =
{ ElementToMarkdownAdapterExtension({
name: 'mindmap', name: 'mindmap',
match: elementModel => elementModel.type === 'mindmap', match: elementModel => elementModel.type === 'mindmap',
toAST: (elementModel, context) => { toAST: (elementModel, context) => {
@@ -64,4 +64,4 @@ export const mindmapToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatch
return null; return null;
}, },
}; });

View File

@@ -1,9 +1,8 @@
import type { MindMapTreeNode } from '../../../types/mindmap.js'; import type { MindMapTreeNode } from '../../../types/mindmap.js';
import { getShapeText, getShapeType } from '../../../utils/text.js'; import { getShapeText, getShapeType } from '../../../utils/text.js';
import type { ElementModelToMarkdownAdapterMatcher } from '../type.js'; import { ElementToMarkdownAdapterExtension } from '../type.js';
export const shapeToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher = export const shapeToMarkdownAdapterMatcher = ElementToMarkdownAdapterExtension({
{
name: 'shape', name: 'shape',
match: elementModel => elementModel.type === 'shape', match: elementModel => elementModel.type === 'shape',
toAST: (elementModel, context) => { toAST: (elementModel, context) => {
@@ -43,4 +42,4 @@ export const shapeToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher
], ],
}; };
}, },
}; });

View File

@@ -1,8 +1,7 @@
import { getTextElementText } from '../../../utils/text.js'; import { getTextElementText } from '../../../utils/text.js';
import type { ElementModelToMarkdownAdapterMatcher } from '../type.js'; import { ElementToMarkdownAdapterExtension } from '../type.js';
export const textToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher = export const textToMarkdownAdapterMatcher = ElementToMarkdownAdapterExtension({
{
name: 'text', name: 'text',
match: elementModel => elementModel.type === 'text', match: elementModel => elementModel.type === 'text',
toAST: elementModel => { toAST: elementModel => {
@@ -21,4 +20,4 @@ export const textToMarkdownAdapterMatcher: ElementModelToMarkdownAdapterMatcher
], ],
}; };
}, },
}; });

View File

@@ -4,15 +4,14 @@ import {
ElementModelAdapter, ElementModelAdapter,
type ElementModelAdapterContext, type ElementModelAdapterContext,
} from '../../type.js'; } from '../../type.js';
import { elementToMarkdownAdapterMatchers } from './elements/index.js'; import type { ElementToMarkdownAdapterMatcher } from './type.js';
import type { ElementModelToMarkdownAdapterMatcher } from './type.js';
export class MarkdownElementModelAdapter extends ElementModelAdapter< export class MarkdownElementModelAdapter extends ElementModelAdapter<
MarkdownAST, MarkdownAST,
MarkdownAST MarkdownAST
> { > {
constructor( constructor(
readonly elementModelMatchers: ElementModelToMarkdownAdapterMatcher[] = elementToMarkdownAdapterMatchers readonly elementModelMatchers: ElementToMarkdownAdapterMatcher[]
) { ) {
super(); super();
} }

View File

@@ -1,6 +1,29 @@
import type { ExtensionType } from '@blocksuite/affine/store';
import type { MarkdownAST } from '@blocksuite/affine-shared/adapters'; import type { MarkdownAST } from '@blocksuite/affine-shared/adapters';
import {
createIdentifier,
type ServiceIdentifier,
} from '@blocksuite/global/di';
import type { ElementModelMatcher } from '../../type.js'; import type { ElementModelMatcher } from '../../type.js';
export type ElementModelToMarkdownAdapterMatcher = export type ElementToMarkdownAdapterMatcher = ElementModelMatcher<MarkdownAST>;
ElementModelMatcher<MarkdownAST>;
export const ElementToMarkdownAdapterMatcherIdentifier =
createIdentifier<ElementToMarkdownAdapterMatcher>(
'elementToMarkdownAdapterMatcher'
);
export function ElementToMarkdownAdapterExtension(
matcher: ElementToMarkdownAdapterMatcher
): ExtensionType & {
identifier: ServiceIdentifier<ElementToMarkdownAdapterMatcher>;
} {
const identifier = ElementToMarkdownAdapterMatcherIdentifier(matcher.name);
return {
setup: di => {
di.addImpl(identifier, () => matcher);
},
identifier,
};
}

View File

@@ -5,6 +5,7 @@ import {
import { getMindMapNodeMap } from '../utils/mindmap.js'; import { getMindMapNodeMap } from '../utils/mindmap.js';
import { MarkdownElementModelAdapter } from './element-adapter/index.js'; import { MarkdownElementModelAdapter } from './element-adapter/index.js';
import { ElementToMarkdownAdapterMatcherIdentifier } from './element-adapter/type.js';
export const surfaceBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = { export const surfaceBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = {
flavour: 'affine:surface', flavour: 'affine:surface',
@@ -29,8 +30,18 @@ export const edgelessSurfaceBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMat
toBlockSnapshot: {}, toBlockSnapshot: {},
fromBlockSnapshot: { fromBlockSnapshot: {
enter: (o, context) => { enter: (o, context) => {
const { walkerContext } = context; const { walkerContext, provider } = context;
const markdownElementModelAdapter = new MarkdownElementModelAdapter(); if (!provider) {
context.walkerContext.skipAllChildren();
return;
}
const elementModelMatchers = Array.from(
provider.getAll(ElementToMarkdownAdapterMatcherIdentifier).values()
);
const markdownElementModelAdapter = new MarkdownElementModelAdapter(
elementModelMatchers
);
if ('elements' in o.node.props) { if ('elements' in o.node.props) {
const elements = o.node.props.elements as Record< const elements = o.node.props.elements as Record<
string, string,

View File

@@ -72,6 +72,7 @@ export class MarkdownAdapter extends BaseAdapter<Markdown> {
configs: this.configs, configs: this.configs,
job: this.job, job: this.job,
deltaConverter: this.deltaConverter, deltaConverter: this.deltaConverter,
provider: this.provider,
textBuffer: { content: '' }, textBuffer: { content: '' },
assets, assets,
}; };
@@ -92,6 +93,7 @@ export class MarkdownAdapter extends BaseAdapter<Markdown> {
configs: this.configs, configs: this.configs,
job: this.job, job: this.job,
deltaConverter: this.deltaConverter, deltaConverter: this.deltaConverter,
provider: this.provider,
textBuffer: { content: '' }, textBuffer: { content: '' },
assets, assets,
}; };
@@ -126,6 +128,7 @@ export class MarkdownAdapter extends BaseAdapter<Markdown> {
configs: this.configs, configs: this.configs,
job: this.job, job: this.job,
deltaConverter: this.deltaConverter, deltaConverter: this.deltaConverter,
provider: this.provider,
textBuffer: { content: '' }, textBuffer: { content: '' },
assets, assets,
updateAssetIds: (assetsId: string) => { updateAssetIds: (assetsId: string) => {
@@ -149,6 +152,7 @@ export class MarkdownAdapter extends BaseAdapter<Markdown> {
configs: this.configs, configs: this.configs,
job: this.job, job: this.job,
deltaConverter: this.deltaConverter, deltaConverter: this.deltaConverter,
provider: this.provider,
textBuffer: { content: '' }, textBuffer: { content: '' },
assets, assets,
}; };
@@ -166,7 +170,10 @@ export class MarkdownAdapter extends BaseAdapter<Markdown> {
readonly blockMatchers: BlockMarkdownAdapterMatcher[]; readonly blockMatchers: BlockMarkdownAdapterMatcher[];
constructor(job: Job, provider: ServiceProvider) { constructor(
job: Job,
readonly provider: ServiceProvider
) {
super(job); super(job);
const blockMatchers = Array.from( const blockMatchers = Array.from(
provider.getAll(BlockMarkdownAdapterMatcherIdentifier).values() provider.getAll(BlockMarkdownAdapterMatcherIdentifier).values()