@@ -14,6 +14,14 @@ type DeepMerge = (
14
14
options ?: DeepMergeOptions ,
15
15
) => AnyElement ;
16
16
type CustomMerge = ( keyElement : Element , options : DeepMergeOptions ) => DeepMerge ;
17
+ type CustomMetaMerge = (
18
+ targetElementMeta : ObjectElement ,
19
+ sourceElementMeta : ObjectElement ,
20
+ ) => ObjectElement ;
21
+ type CustomAttributesMerge = (
22
+ targetElementAttributes : ObjectElement ,
23
+ sourceElementAttributes : ObjectElement ,
24
+ ) => ObjectElement ;
17
25
type ArrayElementMerge = (
18
26
targetElement : ArrayElement ,
19
27
sourceElement : ArrayElement ,
@@ -30,6 +38,8 @@ export type DeepMergeUserOptions = {
30
38
arrayElementMerge ?: ArrayElementMerge ;
31
39
objectElementMerge ?: ObjectElementMerge ;
32
40
customMerge ?: CustomMerge ;
41
+ customMetaMerge ?: CustomMetaMerge ;
42
+ customAttributesMerge ?: CustomAttributesMerge ;
33
43
} ;
34
44
35
45
type DeepMergeOptions = DeepMergeUserOptions & {
@@ -38,11 +48,13 @@ type DeepMergeOptions = DeepMergeUserOptions & {
38
48
arrayElementMerge : ArrayElementMerge ;
39
49
objectElementMerge : ObjectElementMerge ;
40
50
customMerge : CustomMerge | undefined ;
51
+ customMetaMerge : CustomMetaMerge | undefined ;
52
+ customAttributesMerge : CustomAttributesMerge | undefined ;
41
53
} ;
42
54
43
55
export const emptyElement = ( element : ObjectElement | ArrayElement ) => {
44
- const meta = cloneDeep ( element . meta ) ;
45
- const attributes = cloneDeep ( element . attributes ) ;
56
+ const meta = element . meta . length > 0 ? cloneDeep ( element . meta ) : undefined ;
57
+ const attributes = element . attributes . length > 0 ? cloneDeep ( element . attributes ) : undefined ;
46
58
47
59
// @ts -ignore
48
60
return new element . constructor ( undefined , meta , attributes ) ;
@@ -68,6 +80,20 @@ const getMergeFunction = (keyElement: Element, options: DeepMergeOptions): DeepM
68
80
return typeof customMerge === 'function' ? customMerge : deepmerge ;
69
81
} ;
70
82
83
+ const getMetaMergeFunction = ( options : DeepMergeOptions ) : CustomMetaMerge => {
84
+ if ( typeof options . customMetaMerge !== 'function' ) {
85
+ return ( targetMeta ) => cloneDeep ( targetMeta ) ;
86
+ }
87
+ return options . customMetaMerge ;
88
+ } ;
89
+
90
+ const getAttributesMergeFunction = ( options : DeepMergeOptions ) : CustomAttributesMerge => {
91
+ if ( typeof options . customAttributesMerge !== 'function' ) {
92
+ return ( targetAttributes ) => cloneDeep ( targetAttributes ) ;
93
+ }
94
+ return options . customAttributesMerge ;
95
+ } ;
96
+
71
97
const mergeArrayElement : ArrayElementMerge = ( targetElement , sourceElement , options ) =>
72
98
targetElement
73
99
. concat ( sourceElement )
@@ -119,6 +145,8 @@ export const defaultOptions: DeepMergeOptions = {
119
145
arrayElementMerge : mergeArrayElement ,
120
146
objectElementMerge : mergeObjectElement ,
121
147
customMerge : undefined ,
148
+ customMetaMerge : undefined ,
149
+ customAttributesMerge : undefined ,
122
150
} ;
123
151
124
152
export default function deepmerge (
@@ -142,19 +170,28 @@ export default function deepmerge(
142
170
return cloneUnlessOtherwiseSpecified ( sourceElement , mergedOptions ) ;
143
171
}
144
172
145
- if ( sourceIsArrayElement && typeof mergedOptions . arrayElementMerge === 'function' ) {
146
- return mergedOptions . arrayElementMerge (
147
- targetElement as ArrayElement ,
148
- sourceElement as ArrayElement ,
149
- mergedOptions ,
150
- ) ;
151
- }
152
-
153
- return mergedOptions . objectElementMerge (
154
- targetElement as ObjectElement ,
155
- sourceElement as ObjectElement ,
156
- mergedOptions ,
173
+ // merging two elements
174
+ const mergedElement =
175
+ sourceIsArrayElement && typeof mergedOptions . arrayElementMerge === 'function'
176
+ ? mergedOptions . arrayElementMerge (
177
+ targetElement as ArrayElement ,
178
+ sourceElement as ArrayElement ,
179
+ mergedOptions ,
180
+ )
181
+ : mergedOptions . objectElementMerge (
182
+ targetElement as ObjectElement ,
183
+ sourceElement as ObjectElement ,
184
+ mergedOptions ,
185
+ ) ;
186
+
187
+ // merging meta & attributes
188
+ mergedElement . meta = getMetaMergeFunction ( mergedOptions ) ( targetElement . meta , sourceElement . meta ) ;
189
+ mergedElement . attributes = getAttributesMergeFunction ( mergedOptions ) (
190
+ targetElement . attributes ,
191
+ sourceElement . attributes ,
157
192
) ;
193
+
194
+ return mergedElement ;
158
195
}
159
196
160
197
deepmerge . all = ( list : ObjectOrArrayElement [ ] , options ?: DeepMergeUserOptions ) => {
0 commit comments