forked from alibaba/lowcode-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.ts
More file actions
140 lines (124 loc) · 3.52 KB
/
schema.ts
File metadata and controls
140 lines (124 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import * as _ from 'lodash';
import {
JSExpression,
NodeData,
NodeSchema,
isJSExpression,
isJSSlot,
isDOMText,
ContainerSchema,
NpmInfo,
CompositeValue,
isNodeSchema,
isJSFunction,
} from '@alilc/lowcode-types';
import { CodeGeneratorError } from '../types/error';
export function isContainerSchema(x: any): x is ContainerSchema {
return (
typeof x === 'object' &&
x &&
typeof x.componentName === 'string' &&
typeof x.fileName === 'string'
);
}
export function isNpmInfo(x: any): x is NpmInfo {
return typeof x === 'object' && x && typeof x.package === 'string';
}
const noop = () => undefined;
const handleChildrenDefaultOptions = {
rerun: false,
};
const DEFAULT_MAX_DEPTH = 100000;
/**
* 遍历并处理所有的子节点
* @param children
* @param handlers
* @param options
* @returns
*/
export function handleSubNodes<T>(
children: NodeSchema['children'],
handlers: {
string?: (i: string) => T;
expression?: (i: JSExpression) => T;
node?: (i: NodeSchema) => T;
},
options?: {
rerun?: boolean;
maxDepth?: number; // 防止出现死循环无穷递归
},
): T[] {
const opt = {
...handleChildrenDefaultOptions,
...(options || {}),
};
const maxDepth = opt.maxDepth ?? DEFAULT_MAX_DEPTH;
if (maxDepth <= 0) {
throw new Error('handleSubNodes maxDepth reached');
}
if (Array.isArray(children)) {
const list: NodeData[] = children as NodeData[];
return list
.map((child) => handleSubNodes(child, handlers, { ...opt, maxDepth: maxDepth - 1 }))
.reduce((p, c) => p.concat(c), []);
}
let result: T | undefined;
const childrenRes: T[] = [];
if (children === null || children === undefined) {
return [];
} else if (isDOMText(children)) {
const handler = handlers.string || noop;
result = handler(children);
} else if (isJSExpression(children)) {
const handler = handlers.expression || noop;
result = handler(children);
} else if (isJSSlot(children)) {
return handleSubNodes(children.value, handlers, { ...opt, maxDepth: maxDepth - 1 });
} else if (isNodeSchema(children)) {
const handler = handlers.node || noop;
const child = children as NodeSchema;
result = handler(child);
if (child.children) {
const childRes = handleSubNodes(child.children, handlers, opt);
childrenRes.push(...childRes);
}
if (child.props) {
if (Array.isArray(child.props)) {
child.props.forEach(({ value }) => {
const childRes = handleCompositeValueInProps(value);
childrenRes.push(...childRes);
});
} else {
Object.values(child.props).forEach((value) => {
const childRes = handleCompositeValueInProps(value);
childrenRes.push(...childRes);
});
}
}
} else {
throw new CodeGeneratorError('handleSubNodes got invalid NodeData', children);
}
if (result !== undefined) {
childrenRes.unshift(result);
}
return childrenRes;
function handleCompositeValueInProps(value: CompositeValue): T[] {
if (isJSSlot(value)) {
return handleSubNodes(value.value, handlers, { ...opt, maxDepth: maxDepth - 1 });
}
// CompositeArray
if (Array.isArray(value)) {
return _.flatMap(value, (v) => handleCompositeValueInProps(v));
}
// CompositeObject
if (
!isJSExpression(value) &&
!isJSFunction(value) &&
typeof value === 'object' &&
value !== null
) {
return _.flatMap(Object.values(value), (v) => handleCompositeValueInProps(v));
}
return [];
}
}