refactor(editor): extensionalize plain text adapter (#9330)

This commit is contained in:
donteatfriedrice
2024-12-26 07:27:07 +00:00
parent 45acdbda04
commit cadb9211a6
27 changed files with 226 additions and 120 deletions
@@ -2,17 +2,20 @@ import {
EdgelessSurfaceBlockMarkdownAdapterExtension,
SurfaceBlockMarkdownAdapterExtension,
} from './markdown/markdown.js';
import { elementToPlainTextAdapterMatchers } from './plain-text/element-adapter/elements/index.js';
import {
EdgelessSurfaceBlockPlainTextAdapterExtension,
SurfaceBlockPlainTextAdapterExtension,
} from './plain-text/plain-text.js';
export const SurfaceBlockAdapterExtensions = [
...elementToPlainTextAdapterMatchers,
SurfaceBlockPlainTextAdapterExtension,
SurfaceBlockMarkdownAdapterExtension,
];
export const EdgelessSurfaceBlockAdapterExtensions = [
...elementToPlainTextAdapterMatchers,
EdgelessSurfaceBlockPlainTextAdapterExtension,
EdgelessSurfaceBlockMarkdownAdapterExtension,
];
@@ -0,0 +1,4 @@
export {
EdgelessSurfaceBlockAdapterExtensions,
SurfaceBlockAdapterExtensions,
} from './extension.js';
@@ -1,11 +1,11 @@
import type { ElementModelToPlainTextAdapterMatcher } from '../type.js';
import { ElementToPlainTextAdapterExtension } from '../type.js';
export const brushToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatcher =
{
export const brushToPlainTextAdapterMatcher =
ElementToPlainTextAdapterExtension({
name: 'brush',
match: elementModel => elementModel.type === 'brush',
toAST: () => {
const content = `Brush Stroke`;
return { content };
},
};
});
@@ -1,8 +1,8 @@
import { getConnectorText } from '../../../utils/text.js';
import type { ElementModelToPlainTextAdapterMatcher } from '../type.js';
import { ElementToPlainTextAdapterExtension } from '../type.js';
export const connectorToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatcher =
{
export const connectorToPlainTextAdapterMatcher =
ElementToPlainTextAdapterExtension({
name: 'connector',
match: elementModel => elementModel.type === 'connector',
toAST: elementModel => {
@@ -10,4 +10,4 @@ export const connectorToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterM
const content = `Connector, with text label "${text}"`;
return { content };
},
};
});
@@ -1,8 +1,8 @@
import { getGroupTitle } from '../../../utils/text.js';
import type { ElementModelToPlainTextAdapterMatcher } from '../type.js';
import { ElementToPlainTextAdapterExtension } from '../type.js';
export const groupToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatcher =
{
export const groupToPlainTextAdapterMatcher =
ElementToPlainTextAdapterExtension({
name: 'group',
match: elementModel => elementModel.type === 'group',
toAST: elementModel => {
@@ -10,4 +10,4 @@ export const groupToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatch
const content = `Group, with title "${title}"`;
return { content };
},
};
});
@@ -5,7 +5,7 @@ import { mindmapToPlainTextAdapterMatcher } from './mindmap.js';
import { shapeToPlainTextAdapterMatcher } from './shape.js';
import { textToPlainTextAdapterMatcher } from './text.js';
export const elementModelToPlainTextAdapterMatchers = [
export const elementToPlainTextAdapterMatchers = [
groupToPlainTextAdapterMatcher,
shapeToPlainTextAdapterMatcher,
connectorToPlainTextAdapterMatcher,
@@ -1,12 +1,12 @@
import { getMindMapTreeText } from '../../../utils/text.js';
import type { ElementModelToPlainTextAdapterMatcher } from '../type.js';
import { ElementToPlainTextAdapterExtension } from '../type.js';
export const mindmapToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatcher =
{
export const mindmapToPlainTextAdapterMatcher =
ElementToPlainTextAdapterExtension({
name: 'mindmap',
match: elementModel => elementModel.type === 'mindmap',
toAST: (elementModel, context) => {
const mindMapContent = getMindMapTreeText(elementModel, context.elements);
return { content: mindMapContent };
},
};
});
@@ -1,9 +1,9 @@
import type { MindMapTreeNode } from '../../../types/mindmap.js';
import { getShapeText, getShapeType } from '../../../utils/text.js';
import type { ElementModelToPlainTextAdapterMatcher } from '../type.js';
import { ElementToPlainTextAdapterExtension } from '../type.js';
export const shapeToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatcher =
{
export const shapeToPlainTextAdapterMatcher =
ElementToPlainTextAdapterExtension({
name: 'shape',
match: elementModel => elementModel.type === 'shape',
toAST: (elementModel, context) => {
@@ -31,4 +31,4 @@ export const shapeToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatch
content = `${shapeType}, with text label "${text}"`;
return { content };
},
};
});
@@ -1,7 +1,7 @@
import { getTextElementText } from '../../../utils/text.js';
import type { ElementModelToPlainTextAdapterMatcher } from '../type.js';
import { ElementToPlainTextAdapterExtension } from '../type.js';
export const textToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatcher =
export const textToPlainTextAdapterMatcher = ElementToPlainTextAdapterExtension(
{
name: 'text',
match: elementModel => elementModel.type === 'text',
@@ -9,4 +9,5 @@ export const textToPlainTextAdapterMatcher: ElementModelToPlainTextAdapterMatche
const content = getTextElementText(elementModel);
return { content };
},
};
}
);
@@ -4,15 +4,14 @@ import {
ElementModelAdapter,
type ElementModelAdapterContext,
} from '../../type.js';
import { elementModelToPlainTextAdapterMatchers } from './elements/index.js';
import type { ElementModelToPlainTextAdapterMatcher } from './type.js';
import type { ElementToPlainTextAdapterMatcher } from './type.js';
export class PlainTextElementModelAdapter extends ElementModelAdapter<
string,
TextBuffer
> {
constructor(
readonly elementModelMatchers: ElementModelToPlainTextAdapterMatcher[] = elementModelToPlainTextAdapterMatchers
readonly elementModelMatchers: ElementToPlainTextAdapterMatcher[]
) {
super();
}
@@ -1,6 +1,29 @@
import type { TextBuffer } from '@blocksuite/affine-shared/adapters';
import type { ExtensionType } from '@blocksuite/block-std';
import {
createIdentifier,
type ServiceIdentifier,
} from '@blocksuite/global/di';
import type { ElementModelMatcher } from '../../type.js';
export type ElementModelToPlainTextAdapterMatcher =
ElementModelMatcher<TextBuffer>;
export type ElementToPlainTextAdapterMatcher = ElementModelMatcher<TextBuffer>;
export const ElementToPlainTextAdapterMatcherIdentifier =
createIdentifier<ElementToPlainTextAdapterMatcher>(
'elementToPlainTextAdapterMatcher'
);
export function ElementToPlainTextAdapterExtension(
matcher: ElementToPlainTextAdapterMatcher
): ExtensionType & {
identifier: ServiceIdentifier<ElementToPlainTextAdapterMatcher>;
} {
const identifier = ElementToPlainTextAdapterMatcherIdentifier(matcher.name);
return {
setup: di => {
di.addImpl(identifier, () => matcher);
},
identifier,
};
}
@@ -5,6 +5,7 @@ import {
import { getMindMapNodeMap } from '../utils/mindmap.js';
import { PlainTextElementModelAdapter } from './element-adapter/index.js';
import { ElementToPlainTextAdapterMatcherIdentifier } from './element-adapter/type.js';
export const surfaceBlockPlainTextAdapterMatcher: BlockPlainTextAdapterMatcher =
{
@@ -30,8 +31,18 @@ export const edgelessSurfaceBlockPlainTextAdapterMatcher: BlockPlainTextAdapterM
toBlockSnapshot: {},
fromBlockSnapshot: {
enter: (o, context) => {
const { walkerContext } = context;
const plainTextElementModelAdapter = new PlainTextElementModelAdapter();
const { walkerContext, provider } = context;
if (!provider) {
context.walkerContext.skipAllChildren();
return;
}
const elementModelMatchers = Array.from(
provider.getAll(ElementToPlainTextAdapterMatcherIdentifier).values()
);
const plainTextElementModelAdapter = new PlainTextElementModelAdapter(
elementModelMatchers
);
if ('elements' in o.node.props) {
const elements = o.node.props.elements as Record<
string,
@@ -44,6 +44,10 @@ import {
isSameFontFamily,
wrapFontFamily,
} from './utils/font.js';
export {
EdgelessSurfaceBlockAdapterExtensions,
SurfaceBlockAdapterExtensions,
} from './adapters/index.js';
export type { SurfaceContext } from './surface-block.js';
export { SurfaceBlockComponent } from './surface-block.js';
export { SurfaceBlockModel, SurfaceBlockSchema } from './surface-model.js';