fix: FlowNodeRegistry.extendChildRegistries extend nested, add document.isExtend (#269)

This commit is contained in:
xiamidaxia 2025-05-23 18:21:51 +08:00 committed by GitHub
parent bac29feb3a
commit 755aaf2223
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 159 additions and 0 deletions

View File

@ -0,0 +1,116 @@
import { beforeEach, describe, expect, it } from 'vitest';
import { createDocumentContainer } from './flow-document-container.mock';
import { FlowDocument, FlowNodeRegistry } from '../src';
function registerNode(doc: FlowDocument, newRegistry: FlowNodeRegistry): FlowNodeRegistry {
doc.registerFlowNodes(newRegistry);
return doc.getNodeRegistry(newRegistry.type);
}
const mockRegistries: FlowNodeRegistry[] = [
{
type: 'dynamicSplit',
meta: {},
onCreate(node, json) {
return node.document.addInlineBlocks(node, json.blocks || []);
},
extendChildRegistries: [
{
type: 'blockIcon',
customKey: 'blockIcon_base',
},
{
type: 'inlineBlocks',
customKey: 'inlineBlocks_base',
},
],
onAdd: () => {},
},
{
type: 'a',
extend: 'dynamicSplit',
},
{
type: 'b',
extend: 'a',
extendChildRegistries: [
{
type: 'blockIcon',
customKey: 'blockIcon_from_b',
},
],
},
{
type: 'c',
extend: 'b',
extendChildRegistries: [
{
type: 'blockIcon',
customKey: 'blockIcon_from_c',
},
{
type: 'inlineBlocks',
customKey: 'inlineBlocks_from_c',
},
],
},
];
describe('flow-node-registry', () => {
let doc: FlowDocument;
beforeEach(() => {
const container = createDocumentContainer();
doc = container.get<FlowDocument>(FlowDocument);
doc.registerFlowNodes(...mockRegistries);
});
it('extend check', () => {
expect(doc.getNodeRegistry('dynamicSplit').__extends__).toEqual(undefined);
expect(doc.getNodeRegistry('a').__extends__).toEqual(['dynamicSplit']);
expect(doc.getNodeRegistry('b').__extends__).toEqual(['a', 'dynamicSplit']);
expect(doc.getNodeRegistry('c').__extends__).toEqual(['b', 'a', 'dynamicSplit']);
expect(doc.isExtend('dynamicSplit', 'dynamicSplit')).toBeFalsy();
expect(doc.isExtend('a', 'b')).toBeFalsy();
expect(doc.isExtend('a', 'dynamicSplit')).toBeTruthy();
expect(doc.isExtend('b', 'dynamicSplit')).toBeTruthy();
expect(doc.isExtend('b', 'a')).toBeTruthy();
expect(doc.isExtend('c', 'dynamicSplit')).toBeTruthy();
expect(doc.isExtend('c', 'b')).toBeTruthy();
expect(doc.isExtend('c', 'a')).toBeTruthy();
});
it('base extend', () => {
expect(doc.getNodeRegistry('a').onAdd).toBeTypeOf('function');
doc.addNode({
id: 'a',
type: 'a',
parent: doc.root,
});
expect(doc.toString()).toEqual(`root
|-- a
|---- $blockIcon$a
|---- $inlineBlocks$a`);
expect(doc.getNode('$blockIcon$a').getNodeRegistry().customKey).toBe('blockIcon_base');
});
it('extend nested', () => {
expect(doc.getNodeRegistry('b').onAdd).toBeTypeOf('function');
doc.addNode({
id: 'b',
type: 'b',
parent: doc.root,
});
doc.addNode({
id: 'c',
type: 'c',
parent: doc.root,
});
expect(doc.toString()).toEqual(`root
|-- b
|---- $blockIcon$b
|---- $inlineBlocks$b
|-- c
|---- $blockIcon$c
|---- $inlineBlocks$c`);
expect(doc.getNode('$blockIcon$b').getNodeRegistry().customKey).toBe('blockIcon_from_b');
expect(doc.getNode('$inlineBlocks$b').getNodeRegistry().customKey).toBe('inlineBlocks_base');
expect(doc.getNode('$blockIcon$c').getNodeRegistry().customKey).toBe('blockIcon_from_c');
expect(doc.getNode('$inlineBlocks$c').getNodeRegistry().customKey).toBe('inlineBlocks_from_c');
});
});

View File

@ -433,10 +433,23 @@ export class FlowDocument<T = FlowDocumentJSON> implements Disposable {
...preRegistry?.meta, ...preRegistry?.meta,
...newRegistry?.meta, ...newRegistry?.meta,
}, },
extendChildRegistries: FlowNodeRegistry.mergeChildRegistries(
preRegistry?.extendChildRegistries,
newRegistry?.extendChildRegistries
),
}); });
}); });
} }
/**
* Check node extend
* @param currentType
* @param parentType
*/
isExtend(currentType: FlowNodeType, parentType: FlowNodeType): boolean {
return (this.getNodeRegistry(currentType).__extends__ || []).includes(parentType);
}
/** /**
* *
*/ */

View File

@ -276,6 +276,10 @@ export interface FlowNodeRegistry<M extends FlowNodeMeta = FlowNodeMeta> {
} }
) => FlowNodeEntity; ) => FlowNodeEntity;
/**
* 使
*/
__extends__?: FlowNodeType[];
/** /**
* *
*/ */
@ -283,17 +287,43 @@ export interface FlowNodeRegistry<M extends FlowNodeMeta = FlowNodeMeta> {
} }
export namespace FlowNodeRegistry { export namespace FlowNodeRegistry {
export function mergeChildRegistries(
r1: FlowNodeRegistry[] = [],
r2: FlowNodeRegistry[] = []
): FlowNodeRegistry[] {
if (r1.length === 0 || r2.length === 0) {
return [...r1, ...r2];
}
const r1Filter = r1.map((r1Current) => {
const r2Current = r2.find((n) => n.type === r1Current.type);
if (r2Current) {
return merge(r1Current, r2Current, r1Current.type);
}
return r1Current;
});
const r2Filter = r2.filter((n) => !r1.some((r) => r.type === n.type));
return [...r1Filter, ...r2Filter];
}
export function merge( export function merge(
registry1: FlowNodeRegistry, registry1: FlowNodeRegistry,
registry2: FlowNodeRegistry, registry2: FlowNodeRegistry,
finalType: FlowNodeType finalType: FlowNodeType
): FlowNodeRegistry { ): FlowNodeRegistry {
const extendKeys = registry1.__extends__ ? registry1.__extends__.slice() : [];
if (registry1.type !== registry2.type) {
extendKeys.unshift(registry1.type);
}
return { return {
...registry1, ...registry1,
...registry2, ...registry2,
extendChildRegistries: mergeChildRegistries(
registry1.extendChildRegistries,
registry2.extendChildRegistries
),
meta: { ...registry1.meta, ...registry2.meta }, meta: { ...registry1.meta, ...registry2.meta },
extend: undefined, extend: undefined,
type: finalType, type: finalType,
__extends__: extendKeys,
}; };
} }