@@ -11,7 +11,7 @@ import {
11
11
isDelete ,
12
12
isMove ,
13
13
isSimple ,
14
- isUpdate ,
14
+ isReplace ,
15
15
LitElementConstructor ,
16
16
Mixin ,
17
17
Move ,
@@ -20,7 +20,9 @@ import {
20
20
OpenDocEvent ,
21
21
SCLTag ,
22
22
SimpleAction ,
23
+ Replace ,
23
24
Update ,
25
+ isUpdate ,
24
26
} from './foundation.js' ;
25
27
26
28
/** Mixin that edits an `XML` `doc`, listening to [[`EditorActionEvent`]]s */
@@ -42,12 +44,19 @@ export function Editing<TBase extends LitElementConstructor>(Base: TBase) {
42
44
private checkCreateValidity ( create : Create ) : boolean {
43
45
if ( create . checkValidity !== undefined ) return create . checkValidity ( ) ;
44
46
47
+ if (
48
+ ! ( create . new . element instanceof Element ) ||
49
+ ! ( create . new . parent instanceof Element )
50
+ )
51
+ return true ;
52
+
45
53
const invalid =
46
54
create . new . element . hasAttribute ( 'name' ) &&
47
55
Array . from ( create . new . parent . children ) . some (
48
56
elm =>
49
- elm . tagName === create . new . element . tagName &&
50
- elm . getAttribute ( 'name' ) === create . new . element . getAttribute ( 'name' )
57
+ elm . tagName === ( < Element > create . new . element ) . tagName &&
58
+ elm . getAttribute ( 'name' ) ===
59
+ ( < Element > create . new . element ) . getAttribute ( 'name' )
51
60
) ;
52
61
53
62
if ( invalid )
@@ -74,24 +83,32 @@ export function Editing<TBase extends LitElementConstructor>(Base: TBase) {
74
83
private onCreate ( action : Create ) {
75
84
if ( ! this . checkCreateValidity ( action ) ) return false ;
76
85
77
- if ( action . new . reference === undefined )
86
+ if (
87
+ action . new . reference === undefined &&
88
+ action . new . element instanceof Element &&
89
+ action . new . parent instanceof Element
90
+ )
78
91
action . new . reference = getReference (
79
92
action . new . parent ,
80
93
< SCLTag > action . new . element . tagName
81
94
) ;
95
+ else action . new . reference = action . new . reference ?? null ;
82
96
83
97
action . new . parent . insertBefore ( action . new . element , action . new . reference ) ;
84
98
return true ;
85
99
}
86
100
87
101
private logCreate ( action : Create ) {
102
+ const name =
103
+ action . new . element instanceof Element
104
+ ? action . new . element . tagName
105
+ : get ( 'editing.node' ) ;
106
+
88
107
this . dispatchEvent (
89
108
newLogEvent ( {
90
109
kind : 'action' ,
91
- title : get ( 'editing.created' , {
92
- name : action . new . element . tagName ,
93
- } ) ,
94
- action : action ,
110
+ title : get ( 'editing.created' , { name } ) ,
111
+ action,
95
112
} )
96
113
) ;
97
114
}
@@ -100,18 +117,23 @@ export function Editing<TBase extends LitElementConstructor>(Base: TBase) {
100
117
if ( ! action . old . reference )
101
118
action . old . reference = action . old . element . nextSibling ;
102
119
103
- action . old . element . remove ( ) ;
120
+ if ( action . old . element . parentNode !== action . old . parent ) return false ;
121
+
122
+ action . old . parent . removeChild ( action . old . element ) ;
104
123
return true ;
105
124
}
106
125
107
126
private logDelete ( action : Delete ) {
127
+ const name =
128
+ action . old . element instanceof Element
129
+ ? action . old . element . tagName
130
+ : get ( 'editing.node' ) ;
131
+
108
132
this . dispatchEvent (
109
133
newLogEvent ( {
110
134
kind : 'action' ,
111
- title : get ( 'editing.deleted' , {
112
- name : action . old . element . tagName ,
113
- } ) ,
114
- action : action ,
135
+ title : get ( 'editing.deleted' , { name } ) ,
136
+ action,
115
137
} )
116
138
) ;
117
139
}
@@ -174,68 +196,118 @@ export function Editing<TBase extends LitElementConstructor>(Base: TBase) {
174
196
) ;
175
197
}
176
198
177
- private checkUpdateValidity ( update : Update ) : boolean {
178
- if ( update . checkValidity !== undefined ) return update . checkValidity ( ) ;
199
+ private checkReplaceValidity ( replace : Replace ) : boolean {
200
+ if ( replace . checkValidity !== undefined ) return replace . checkValidity ( ) ;
179
201
180
202
const invalid =
181
- update . new . element . hasAttribute ( 'name' ) &&
182
- update . new . element . getAttribute ( 'name' ) !==
183
- update . old . element . getAttribute ( 'name' ) &&
184
- Array . from ( update . old . element . parentElement ?. children ?? [ ] ) . some (
203
+ replace . new . element . hasAttribute ( 'name' ) &&
204
+ replace . new . element . getAttribute ( 'name' ) !==
205
+ replace . old . element . getAttribute ( 'name' ) &&
206
+ Array . from ( replace . old . element . parentElement ?. children ?? [ ] ) . some (
185
207
elm =>
186
- elm . tagName === update . new . element . tagName &&
187
- elm . getAttribute ( 'name' ) === update . new . element . getAttribute ( 'name' )
208
+ elm . tagName === replace . new . element . tagName &&
209
+ elm . getAttribute ( 'name' ) ===
210
+ replace . new . element . getAttribute ( 'name' )
188
211
) ;
189
212
190
213
if ( invalid )
191
214
this . dispatchEvent (
192
215
newLogEvent ( {
193
216
kind : 'error' ,
194
217
title : get ( 'editing.error.update' , {
195
- name : update . new . element . tagName ,
218
+ name : replace . new . element . tagName ,
196
219
} ) ,
197
220
message : get ( 'editing.error.nameClash' , {
198
- parent : update . old . element . parentElement ! . tagName ,
199
- child : update . new . element . tagName ,
200
- name : update . new . element . getAttribute ( 'name' ) ! ,
221
+ parent : replace . old . element . parentElement ! . tagName ,
222
+ child : replace . new . element . tagName ,
223
+ name : replace . new . element . getAttribute ( 'name' ) ! ,
201
224
} ) ,
202
225
} )
203
226
) ;
204
227
205
228
return ! invalid ;
206
229
}
207
230
208
- private onUpdate ( action : Update ) {
209
- if ( ! this . checkUpdateValidity ( action ) ) return false ;
231
+ private onReplace ( action : Replace ) {
232
+ if ( ! this . checkReplaceValidity ( action ) ) return false ;
210
233
211
234
action . new . element . append ( ...Array . from ( action . old . element . children ) ) ;
212
235
action . old . element . replaceWith ( action . new . element ) ;
213
236
return true ;
214
237
}
215
238
216
- private logUpdate ( action : Update ) {
239
+ private logUpdate ( action : Replace | Update ) {
240
+ const name = isReplace ( action )
241
+ ? action . new . element . tagName
242
+ : ( action as Update ) . element . tagName ;
243
+
217
244
this . dispatchEvent (
218
245
newLogEvent ( {
219
246
kind : 'action' ,
220
247
title : get ( 'editing.updated' , {
221
- name : action . new . element . tagName ,
248
+ name,
222
249
} ) ,
223
250
action : action ,
224
251
} )
225
252
) ;
226
253
}
227
254
255
+ private checkUpdateValidity ( update : Update ) : boolean {
256
+ if ( update . checkValidity !== undefined ) return update . checkValidity ( ) ;
257
+
258
+ const invalid = Array . from (
259
+ update . element . parentElement ?. children ?? [ ]
260
+ ) . some (
261
+ elm =>
262
+ elm . tagName === update . element . tagName &&
263
+ elm . getAttribute ( 'name' ) === update . newAttributes [ 'name' ]
264
+ ) ;
265
+
266
+ if ( invalid )
267
+ this . dispatchEvent (
268
+ newLogEvent ( {
269
+ kind : 'error' ,
270
+ title : get ( 'editing.error.update' , {
271
+ name : update . element . tagName ,
272
+ } ) ,
273
+ message : get ( 'editing.error.nameClash' , {
274
+ parent : update . element . parentElement ! . tagName ,
275
+ child : update . element . tagName ,
276
+ name : update . newAttributes [ 'name' ] ! ,
277
+ } ) ,
278
+ } )
279
+ ) ;
280
+
281
+ return ! invalid ;
282
+ }
283
+
284
+ private onUpdate ( action : Update ) {
285
+ if ( ! this . checkUpdateValidity ( action ) ) return false ;
286
+
287
+ Array . from ( action . element . attributes ) . forEach ( attr =>
288
+ action . element . removeAttributeNode ( attr )
289
+ ) ;
290
+
291
+ Object . entries ( action . newAttributes ) . forEach ( ( [ key , value ] ) => {
292
+ if ( value ) action . element . setAttribute ( key , value ) ;
293
+ } ) ;
294
+
295
+ return true ;
296
+ }
297
+
228
298
private onSimpleAction ( action : SimpleAction ) {
229
299
if ( isMove ( action ) ) return this . onMove ( action as Move ) ;
230
300
else if ( isCreate ( action ) ) return this . onCreate ( action as Create ) ;
231
301
else if ( isDelete ( action ) ) return this . onDelete ( action as Delete ) ;
302
+ else if ( isReplace ( action ) ) return this . onReplace ( action as Replace ) ;
232
303
else if ( isUpdate ( action ) ) return this . onUpdate ( action as Update ) ;
233
304
}
234
305
235
306
private logSimpleAction ( action : SimpleAction ) {
236
307
if ( isMove ( action ) ) this . logMove ( action as Move ) ;
237
308
else if ( isCreate ( action ) ) this . logCreate ( action as Create ) ;
238
309
else if ( isDelete ( action ) ) this . logDelete ( action as Delete ) ;
310
+ else if ( isReplace ( action ) ) this . logUpdate ( action as Replace ) ;
239
311
else if ( isUpdate ( action ) ) this . logUpdate ( action as Update ) ;
240
312
}
241
313
0 commit comments