suneditor 3.0.0-beta.2 → 3.0.0-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +186 -184
- package/LICENSE +21 -21
- package/README.md +157 -180
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +126 -123
- package/src/assets/design/color.css +131 -121
- package/src/assets/design/index.css +3 -3
- package/src/assets/design/size.css +37 -35
- package/src/assets/design/typography.css +37 -37
- package/src/assets/icons/defaultIcons.js +247 -232
- package/src/assets/suneditor-contents.css +779 -778
- package/src/assets/suneditor.css +43 -35
- package/src/core/base/eventHandlers/handler_toolbar.js +135 -135
- package/src/core/base/eventHandlers/handler_ww_clipboard.js +56 -56
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +115 -113
- package/src/core/base/eventHandlers/handler_ww_key_input.js +1200 -1200
- package/src/core/base/eventHandlers/handler_ww_mouse.js +194 -194
- package/src/core/base/eventManager.js +1550 -1484
- package/src/core/base/history.js +355 -355
- package/src/core/class/char.js +163 -162
- package/src/core/class/component.js +856 -842
- package/src/core/class/format.js +3433 -3422
- package/src/core/class/html.js +1927 -1890
- package/src/core/class/menu.js +357 -346
- package/src/core/class/nodeTransform.js +424 -424
- package/src/core/class/offset.js +858 -891
- package/src/core/class/selection.js +710 -620
- package/src/core/class/shortcuts.js +98 -98
- package/src/core/class/toolbar.js +438 -430
- package/src/core/class/ui.js +424 -422
- package/src/core/class/viewer.js +750 -750
- package/src/core/editor.js +1810 -1708
- package/src/core/section/actives.js +268 -241
- package/src/core/section/constructor.js +1348 -1661
- package/src/core/section/context.js +102 -102
- package/src/core/section/documentType.js +582 -561
- package/src/core/section/options.js +367 -0
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +36 -36
- package/src/editorInjector/_core.js +92 -92
- package/src/editorInjector/index.js +75 -75
- package/src/events.js +634 -622
- package/src/helper/clipboard.js +59 -59
- package/src/helper/converter.js +586 -564
- package/src/helper/dom/domCheck.js +304 -304
- package/src/helper/dom/domQuery.js +677 -669
- package/src/helper/dom/domUtils.js +618 -557
- package/src/helper/dom/index.js +12 -12
- package/src/helper/env.js +249 -240
- package/src/helper/index.js +25 -25
- package/src/helper/keyCodeMap.js +183 -183
- package/src/helper/numbers.js +72 -72
- package/src/helper/unicode.js +47 -47
- package/src/langs/ckb.js +231 -231
- package/src/langs/cs.js +231 -231
- package/src/langs/da.js +231 -231
- package/src/langs/de.js +231 -231
- package/src/langs/en.js +230 -230
- package/src/langs/es.js +231 -231
- package/src/langs/fa.js +231 -231
- package/src/langs/fr.js +231 -231
- package/src/langs/he.js +231 -231
- package/src/langs/hu.js +230 -230
- package/src/langs/index.js +28 -28
- package/src/langs/it.js +231 -231
- package/src/langs/ja.js +230 -230
- package/src/langs/km.js +230 -230
- package/src/langs/ko.js +230 -230
- package/src/langs/lv.js +231 -231
- package/src/langs/nl.js +231 -231
- package/src/langs/pl.js +231 -231
- package/src/langs/pt_br.js +231 -231
- package/src/langs/ro.js +231 -231
- package/src/langs/ru.js +231 -231
- package/src/langs/se.js +231 -231
- package/src/langs/tr.js +231 -231
- package/src/langs/uk.js +231 -231
- package/src/langs/ur.js +231 -231
- package/src/langs/zh_cn.js +231 -231
- package/src/modules/ApiManager.js +191 -191
- package/src/modules/Browser.js +669 -667
- package/src/modules/ColorPicker.js +364 -362
- package/src/modules/Controller.js +474 -454
- package/src/modules/Figure.js +1620 -1617
- package/src/modules/FileManager.js +359 -359
- package/src/modules/HueSlider.js +577 -565
- package/src/modules/Modal.js +346 -346
- package/src/modules/ModalAnchorEditor.js +643 -643
- package/src/modules/SelectMenu.js +549 -549
- package/src/modules/_DragHandle.js +17 -17
- package/src/modules/index.js +14 -14
- package/src/plugins/browser/audioGallery.js +83 -83
- package/src/plugins/browser/fileBrowser.js +103 -103
- package/src/plugins/browser/fileGallery.js +83 -83
- package/src/plugins/browser/imageGallery.js +81 -81
- package/src/plugins/browser/videoGallery.js +103 -103
- package/src/plugins/command/blockquote.js +61 -60
- package/src/plugins/command/exportPDF.js +134 -134
- package/src/plugins/command/fileUpload.js +456 -456
- package/src/plugins/command/list_bulleted.js +149 -148
- package/src/plugins/command/list_numbered.js +152 -151
- package/src/plugins/dropdown/align.js +157 -155
- package/src/plugins/dropdown/backgroundColor.js +108 -104
- package/src/plugins/dropdown/font.js +141 -137
- package/src/plugins/dropdown/fontColor.js +109 -105
- package/src/plugins/dropdown/formatBlock.js +170 -178
- package/src/plugins/dropdown/hr.js +152 -152
- package/src/plugins/dropdown/layout.js +83 -83
- package/src/plugins/dropdown/lineHeight.js +131 -130
- package/src/plugins/dropdown/list.js +123 -122
- package/src/plugins/dropdown/paragraphStyle.js +138 -138
- package/src/plugins/dropdown/table.js +4110 -4000
- package/src/plugins/dropdown/template.js +83 -83
- package/src/plugins/dropdown/textStyle.js +149 -149
- package/src/plugins/field/mention.js +242 -242
- package/src/plugins/index.js +120 -120
- package/src/plugins/input/fontSize.js +414 -410
- package/src/plugins/input/pageNavigator.js +71 -70
- package/src/plugins/modal/audio.js +677 -677
- package/src/plugins/modal/drawing.js +537 -531
- package/src/plugins/modal/embed.js +886 -886
- package/src/plugins/modal/image.js +1377 -1376
- package/src/plugins/modal/link.js +248 -240
- package/src/plugins/modal/math.js +563 -563
- package/src/plugins/modal/video.js +1226 -1226
- package/src/plugins/popup/anchor.js +224 -222
- package/src/suneditor.js +114 -107
- package/src/themes/dark.css +132 -122
- package/src/typedef.js +132 -130
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/base/eventManager.d.ts +29 -4
- package/types/core/class/char.d.ts +2 -1
- package/types/core/class/component.d.ts +1 -2
- package/types/core/class/format.d.ts +8 -1
- package/types/core/class/html.d.ts +8 -0
- package/types/core/class/menu.d.ts +8 -0
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +6 -0
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/editor.d.ts +34 -12
- package/types/core/section/constructor.d.ts +5 -638
- package/types/core/section/documentType.d.ts +12 -2
- package/types/core/section/options.d.ts +740 -0
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_core.d.ts +5 -5
- package/types/editorInjector/index.d.ts +2 -2
- package/types/events.d.ts +2 -0
- package/types/helper/converter.d.ts +9 -0
- package/types/helper/dom/domQuery.d.ts +5 -5
- package/types/helper/dom/domUtils.d.ts +8 -0
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +4 -1
- package/types/index.d.ts +122 -120
- package/types/langs/_Lang.d.ts +194 -194
- package/types/modules/ColorPicker.d.ts +5 -1
- package/types/modules/Controller.d.ts +8 -4
- package/types/modules/Figure.d.ts +2 -1
- package/types/modules/HueSlider.d.ts +4 -1
- package/types/modules/SelectMenu.d.ts +1 -1
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +1 -0
- package/types/plugins/dropdown/backgroundColor.d.ts +1 -0
- package/types/plugins/dropdown/font.d.ts +1 -0
- package/types/plugins/dropdown/fontColor.d.ts +1 -0
- package/types/plugins/dropdown/formatBlock.d.ts +3 -2
- package/types/plugins/dropdown/lineHeight.d.ts +1 -0
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/table.d.ts +6 -0
- package/types/plugins/input/fontSize.d.ts +1 -0
- package/types/plugins/modal/drawing.d.ts +4 -0
- package/types/plugins/modal/link.d.ts +32 -15
- package/types/suneditor.d.ts +13 -9
- package/types/typedef.d.ts +8 -0
|
@@ -1,669 +1,677 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Implements Helper for querying the DOM.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @
|
|
12
|
-
* @
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* @param {
|
|
27
|
-
* @param {?
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (
|
|
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
|
-
* @param {
|
|
80
|
-
* @
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
let
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (nodes.length
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
* @
|
|
102
|
-
* @
|
|
103
|
-
* @param {
|
|
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
|
-
* @param {
|
|
140
|
-
* @
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*
|
|
168
|
-
* -
|
|
169
|
-
*
|
|
170
|
-
* @
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
* @
|
|
189
|
-
* @param {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
* @
|
|
206
|
-
* @param {Node}
|
|
207
|
-
* @
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
* @
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
* @param {
|
|
243
|
-
*
|
|
244
|
-
* -
|
|
245
|
-
*
|
|
246
|
-
* @
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
* @
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
* @param {
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* @
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
* @
|
|
347
|
-
* @
|
|
348
|
-
* @
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
n
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
* @
|
|
363
|
-
* @
|
|
364
|
-
* @
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
* @
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
* @param {
|
|
376
|
-
* @param {boolean}
|
|
377
|
-
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
*
|
|
420
|
-
* -
|
|
421
|
-
* -
|
|
422
|
-
*
|
|
423
|
-
* @param {Node
|
|
424
|
-
* @
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (!
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
while (
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
* @
|
|
442
|
-
* @
|
|
443
|
-
* @param {
|
|
444
|
-
* @
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (parentNode
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
* @
|
|
469
|
-
* @
|
|
470
|
-
* @param {
|
|
471
|
-
* @
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (parentNode
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
* @
|
|
496
|
-
* @param {Node}
|
|
497
|
-
* @param {
|
|
498
|
-
* @param {
|
|
499
|
-
* @
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
if (!
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
let
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
if (
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
*
|
|
534
|
-
*
|
|
535
|
-
* @param {
|
|
536
|
-
* @param {number}
|
|
537
|
-
* @
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
* @
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
* @
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
let
|
|
577
|
-
let
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const
|
|
582
|
-
const
|
|
583
|
-
const
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
* @
|
|
621
|
-
* @
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Implements Helper for querying the DOM.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { _w } from '../env';
|
|
6
|
+
import { zeroWidthRegExp } from '../unicode';
|
|
7
|
+
import domUtils from './domUtils';
|
|
8
|
+
import domCheck from './domCheck';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description Returns the index compared to other sibling nodes.
|
|
12
|
+
* @param {Node} node The Node to find index
|
|
13
|
+
* @returns {number}
|
|
14
|
+
*/
|
|
15
|
+
export function getPositionIndex(node) {
|
|
16
|
+
let idx = 0;
|
|
17
|
+
while ((node = node.previousSibling)) {
|
|
18
|
+
idx += 1;
|
|
19
|
+
}
|
|
20
|
+
return idx;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @description Returns the position of the "node" in the "parentNode" in a numerical array.
|
|
25
|
+
* - e.g.) <p><span>aa</span><span>bb</span></p> : getNodePath(node: "bb", parentNode: "<P>") -> [1, 0]
|
|
26
|
+
* @param {Node} node The Node to find position path
|
|
27
|
+
* @param {?Node} parentNode Parent node. If null, wysiwyg div area
|
|
28
|
+
* @param {?{s: number, e: number}=} _newOffsets If you send an object of the form "{s: 0, e: 0}", the text nodes that are attached together are merged into one, centered on the "node" argument.
|
|
29
|
+
* "_newOffsets.s" stores the length of the combined characters after "node" and "_newOffsets.e" stores the length of the combined characters before "node".
|
|
30
|
+
* Do not use unless absolutely necessary.
|
|
31
|
+
* @returns {Array<number>}
|
|
32
|
+
*/
|
|
33
|
+
export function getNodePath(node, parentNode, _newOffsets) {
|
|
34
|
+
const path = [];
|
|
35
|
+
let finds = true;
|
|
36
|
+
|
|
37
|
+
getParentElement(node, (el) => {
|
|
38
|
+
if (el === parentNode) finds = false;
|
|
39
|
+
if (finds && !domCheck.isWysiwygFrame(el)) {
|
|
40
|
+
// merge text nodes
|
|
41
|
+
if (_newOffsets && el.nodeType === 3) {
|
|
42
|
+
let temp = null,
|
|
43
|
+
tempText = null;
|
|
44
|
+
_newOffsets.s = _newOffsets.e = 0;
|
|
45
|
+
|
|
46
|
+
let previous = el.previousSibling;
|
|
47
|
+
while (previous?.nodeType === 3) {
|
|
48
|
+
tempText = previous.textContent.replace(zeroWidthRegExp, '');
|
|
49
|
+
_newOffsets.s += tempText.length;
|
|
50
|
+
el.textContent = tempText + el.textContent;
|
|
51
|
+
temp = previous;
|
|
52
|
+
previous = previous.previousSibling;
|
|
53
|
+
domUtils.removeItem(temp);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
let next = el.nextSibling;
|
|
57
|
+
while (next?.nodeType === 3) {
|
|
58
|
+
tempText = next.textContent.replace(zeroWidthRegExp, '');
|
|
59
|
+
_newOffsets.e += tempText.length;
|
|
60
|
+
el.textContent += tempText;
|
|
61
|
+
temp = next;
|
|
62
|
+
next = next.nextSibling;
|
|
63
|
+
domUtils.removeItem(temp);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// index push
|
|
68
|
+
path.push(el);
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return path.map(getPositionIndex).reverse();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @template {Node} T
|
|
78
|
+
* @description Returns the node in the location of the path array obtained from "helper.dom.getNodePath".
|
|
79
|
+
* @param {Array<number>} offsets Position array, array obtained from "helper.dom.getNodePath"
|
|
80
|
+
* @param {Node} parentNode Base parent element
|
|
81
|
+
* @returns {T}
|
|
82
|
+
*/
|
|
83
|
+
export function getNodeFromPath(offsets, parentNode) {
|
|
84
|
+
let current = parentNode;
|
|
85
|
+
let nodes;
|
|
86
|
+
|
|
87
|
+
for (let i = 0, len = offsets.length; i < len; i++) {
|
|
88
|
+
nodes = current.childNodes;
|
|
89
|
+
if (nodes.length === 0) break;
|
|
90
|
+
if (nodes.length <= offsets[i]) {
|
|
91
|
+
current = nodes[nodes.length - 1];
|
|
92
|
+
} else {
|
|
93
|
+
current = nodes[offsets[i]];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return /** @type {T} */ (current);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @template {HTMLElement} T
|
|
102
|
+
* @description Get all "children" of the argument value element (Without text nodes)
|
|
103
|
+
* @param {Node} element element to get child node
|
|
104
|
+
* @param {?(current: *) => boolean} validation Conditional function
|
|
105
|
+
* @returns {Array<T>}
|
|
106
|
+
*/
|
|
107
|
+
export function getListChildren(element, validation) {
|
|
108
|
+
/** @type {Array<T>} */
|
|
109
|
+
const children = [];
|
|
110
|
+
if (!element) return children;
|
|
111
|
+
|
|
112
|
+
const el = /** @type {Element} */ (element);
|
|
113
|
+
if (!el.children || el.children.length === 0) return children;
|
|
114
|
+
|
|
115
|
+
validation =
|
|
116
|
+
validation ||
|
|
117
|
+
function () {
|
|
118
|
+
return true;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
(function recursionFunc(current) {
|
|
122
|
+
if (el !== current && validation(current)) {
|
|
123
|
+
children.push(/** @type {T} */ (current));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (current.children) {
|
|
127
|
+
for (let i = 0, len = current.children.length; i < len; i++) {
|
|
128
|
+
recursionFunc(current.children[i]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
})(el);
|
|
132
|
+
|
|
133
|
+
return /** @type {Array<T>} */ (children);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @template {Node} T
|
|
138
|
+
* @description Get all "childNodes" of the argument value element (Include text nodes)
|
|
139
|
+
* @param {Node} element element to get child node
|
|
140
|
+
* @param {?(current: *) => boolean} validation Conditional function
|
|
141
|
+
* @returns {Array<T>}
|
|
142
|
+
*/
|
|
143
|
+
export function getListChildNodes(element, validation) {
|
|
144
|
+
const children = [];
|
|
145
|
+
if (!element || element.childNodes.length === 0) return children;
|
|
146
|
+
|
|
147
|
+
validation =
|
|
148
|
+
validation ||
|
|
149
|
+
function () {
|
|
150
|
+
return true;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
(function recursionFunc(current) {
|
|
154
|
+
if (element !== current && validation(current)) {
|
|
155
|
+
children.push(current);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (let i = 0, len = current.childNodes.length; i < len; i++) {
|
|
159
|
+
recursionFunc(current.childNodes[i]);
|
|
160
|
+
}
|
|
161
|
+
})(element);
|
|
162
|
+
|
|
163
|
+
return /** @type {Array<T>} */ (children);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @description Returns the number of parents nodes.
|
|
168
|
+
* - "0" when the parent node is the WYSIWYG area.
|
|
169
|
+
* - '-1' when the element argument is the WYSIWYG area.
|
|
170
|
+
* @param {Node} node The element to check
|
|
171
|
+
* @returns {number}
|
|
172
|
+
*/
|
|
173
|
+
export function getNodeDepth(node) {
|
|
174
|
+
if (!node || domCheck.isWysiwygFrame(node)) return -1;
|
|
175
|
+
|
|
176
|
+
let depth = 0;
|
|
177
|
+
node = node.parentNode;
|
|
178
|
+
|
|
179
|
+
while (node && !domCheck.isWysiwygFrame(node)) {
|
|
180
|
+
depth += 1;
|
|
181
|
+
node = node.parentNode;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return depth;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @description Sort a node array by depth of element.
|
|
189
|
+
* @param {Array<Node>} array Node array
|
|
190
|
+
* @param {boolean} des true: descending order / false: ascending order
|
|
191
|
+
*/
|
|
192
|
+
export function sortNodeByDepth(array, des) {
|
|
193
|
+
const t = !des ? -1 : 1;
|
|
194
|
+
const f = t * -1;
|
|
195
|
+
|
|
196
|
+
array.sort(function (a, b) {
|
|
197
|
+
if (!domCheck.isListCell(a) || !domCheck.isListCell(b)) return 0;
|
|
198
|
+
const a_i = getNodeDepth(a);
|
|
199
|
+
const b_i = getNodeDepth(b);
|
|
200
|
+
return a_i > b_i ? t : a_i < b_i ? f : 0;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @description Compares two elements to find a common ancestor, and returns the order of the two elements.
|
|
206
|
+
* @param {Node} a Node to compare.
|
|
207
|
+
* @param {Node} b Node to compare.
|
|
208
|
+
* @returns {{ancestor: HTMLElement|null, a: Node, b: Node, result: number}} { ancesstor, a, b, result: (a > b ? 1 : a < b ? -1 : 0) };
|
|
209
|
+
*/
|
|
210
|
+
export function compareElements(a, b) {
|
|
211
|
+
let aNode = a,
|
|
212
|
+
bNode = b;
|
|
213
|
+
while (aNode && bNode && aNode.parentElement !== bNode.parentElement) {
|
|
214
|
+
aNode = aNode.parentElement;
|
|
215
|
+
bNode = bNode.parentElement;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (!aNode || !bNode)
|
|
219
|
+
return {
|
|
220
|
+
ancestor: null,
|
|
221
|
+
a: a,
|
|
222
|
+
b: b,
|
|
223
|
+
result: 0
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const children = aNode.parentNode.childNodes;
|
|
227
|
+
const aIndex = domUtils.getArrayIndex(children, aNode);
|
|
228
|
+
const bIndex = domUtils.getArrayIndex(children, bNode);
|
|
229
|
+
|
|
230
|
+
return {
|
|
231
|
+
ancestor: aNode.parentElement,
|
|
232
|
+
a: aNode,
|
|
233
|
+
b: bNode,
|
|
234
|
+
result: aIndex > bIndex ? 1 : aIndex < bIndex ? -1 : 0
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @template {HTMLElement} T
|
|
240
|
+
* @description Get the parent element of the argument value.
|
|
241
|
+
* - A tag that satisfies the query condition is imported.
|
|
242
|
+
* @param {Node} element Reference element
|
|
243
|
+
* @param {string|((current: *) => boolean)|Node} query Query String (nodeName, .className, #ID, :name) or validation function.
|
|
244
|
+
* - Not use it like jquery.
|
|
245
|
+
* - Only one condition can be entered at a time.
|
|
246
|
+
* @param {?number=} depth Number of parent levels to depth.
|
|
247
|
+
* @returns {T|null} Not found: null
|
|
248
|
+
*/
|
|
249
|
+
export function getParentElement(element, query, depth) {
|
|
250
|
+
let valid;
|
|
251
|
+
|
|
252
|
+
if (typeof query === 'function') {
|
|
253
|
+
valid = query;
|
|
254
|
+
} else if (typeof query === 'object') {
|
|
255
|
+
/** @param {Node} current */
|
|
256
|
+
valid = (current) => current === query;
|
|
257
|
+
} else {
|
|
258
|
+
let attr;
|
|
259
|
+
if (/^\./.test(query)) {
|
|
260
|
+
attr = 'className';
|
|
261
|
+
query = '(\\s|^)' + query.split('.')[1] + '(\\s|$)';
|
|
262
|
+
} else if (/^#/.test(query)) {
|
|
263
|
+
attr = 'id';
|
|
264
|
+
query = '^' + query.split('#')[1] + '$';
|
|
265
|
+
} else if (/^:/.test(query)) {
|
|
266
|
+
attr = 'name';
|
|
267
|
+
query = '^' + query.split(':')[1] + '$';
|
|
268
|
+
} else {
|
|
269
|
+
attr = 'nodeName';
|
|
270
|
+
query = '^' + query + '$';
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const regExp = new RegExp(query, 'i');
|
|
274
|
+
/** @param {Node} el */
|
|
275
|
+
valid = (el) => regExp.test(el[attr]);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (!depth) depth = Infinity;
|
|
279
|
+
let index = 0;
|
|
280
|
+
while (element && !valid(element)) {
|
|
281
|
+
if (index >= depth || domCheck.isWysiwygFrame(element)) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
element = element.parentElement;
|
|
285
|
+
index++;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return /** @type {T} */ (element);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @template {HTMLElement} T
|
|
293
|
+
* @description Gets all ancestors of the argument value.
|
|
294
|
+
* - Get all tags that satisfy the query condition.
|
|
295
|
+
* @param {Node} element Reference element
|
|
296
|
+
* @param {string|((current: *) => boolean)|Node} query Query String (nodeName, .className, #ID, :name) or validation function.
|
|
297
|
+
* Not use it like jquery.
|
|
298
|
+
* Only one condition can be entered at a time.
|
|
299
|
+
* @param {?number=} depth Number of parent levels to depth.
|
|
300
|
+
* @returns {Array<T>} Returned in an array in order.
|
|
301
|
+
*/
|
|
302
|
+
export function getParentElements(element, query, depth) {
|
|
303
|
+
let valid;
|
|
304
|
+
|
|
305
|
+
if (typeof query === 'function') {
|
|
306
|
+
valid = query;
|
|
307
|
+
} else if (typeof query === 'object') {
|
|
308
|
+
/** @param {Node} current */
|
|
309
|
+
valid = (current) => current === query;
|
|
310
|
+
} else {
|
|
311
|
+
let attr;
|
|
312
|
+
if (/^\./.test(query)) {
|
|
313
|
+
attr = 'className';
|
|
314
|
+
query = '(\\s|^)' + query.split('.')[1] + '(\\s|$)';
|
|
315
|
+
} else if (/^#/.test(query)) {
|
|
316
|
+
attr = 'id';
|
|
317
|
+
query = '^' + query.split('#')[1] + '$';
|
|
318
|
+
} else if (/^:/.test(query)) {
|
|
319
|
+
attr = 'name';
|
|
320
|
+
query = '^' + query.split(':')[1] + '$';
|
|
321
|
+
} else {
|
|
322
|
+
attr = 'nodeName';
|
|
323
|
+
query = '^' + query + '$';
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const regExp = new RegExp(query, 'i');
|
|
327
|
+
/** @param {Node} el */
|
|
328
|
+
valid = (el) => regExp.test(el[attr]);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const elementList = [];
|
|
332
|
+
if (!depth) depth = Infinity;
|
|
333
|
+
let index = 0;
|
|
334
|
+
while (index <= depth && element && !domCheck.isWysiwygFrame(element)) {
|
|
335
|
+
if (valid(element)) {
|
|
336
|
+
elementList.push(element);
|
|
337
|
+
}
|
|
338
|
+
element = element.parentElement;
|
|
339
|
+
index++;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return /** @type {Array<T>} */ (elementList);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @template {HTMLElement} T
|
|
347
|
+
* @description Gets the element with "data-command" attribute among the parent elements.
|
|
348
|
+
* @param {Node} target Target element
|
|
349
|
+
* @returns {T|null}
|
|
350
|
+
*/
|
|
351
|
+
export function getCommandTarget(target) {
|
|
352
|
+
let n = /** @type {HTMLElement} */ (target);
|
|
353
|
+
while (n && !/^(UL)$/i.test(n.nodeName) && !domUtils.hasClass(n, 'sun-editor')) {
|
|
354
|
+
if (n.hasAttribute('data-command')) return /** @type {T} */ (n);
|
|
355
|
+
n = n.parentElement;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* @template {HTMLElement} T
|
|
363
|
+
* @description Get the event.target element.
|
|
364
|
+
* @param {Event} event Event object
|
|
365
|
+
* @returns {T|null}
|
|
366
|
+
*/
|
|
367
|
+
export function getEventTarget(event) {
|
|
368
|
+
return /** @type {T} */ (event.target);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* @template {Node} T
|
|
373
|
+
* @description Get the child element of the argument value.
|
|
374
|
+
* - A tag that satisfies the query condition is imported.
|
|
375
|
+
* @param {Node} node Reference element
|
|
376
|
+
* @param {string|((current: *) => boolean)|Node} query Query String (nodeName, .className, #ID, :name) or validation function.
|
|
377
|
+
* @param {boolean} last If true returns the last node among the found child nodes. (default: first node)
|
|
378
|
+
* Not use it like jquery.
|
|
379
|
+
* Only one condition can be entered at a time.
|
|
380
|
+
* @returns {T|null} Not found: null
|
|
381
|
+
*/
|
|
382
|
+
export function getEdgeChild(node, query, last) {
|
|
383
|
+
let valid;
|
|
384
|
+
|
|
385
|
+
if (typeof query === 'function') {
|
|
386
|
+
valid = query;
|
|
387
|
+
} else if (typeof query === 'object') {
|
|
388
|
+
valid = function (current) {
|
|
389
|
+
return current === query;
|
|
390
|
+
};
|
|
391
|
+
} else {
|
|
392
|
+
let attr;
|
|
393
|
+
if (/^\./.test(query)) {
|
|
394
|
+
attr = 'className';
|
|
395
|
+
query = '(\\s|^)' + query.split('.')[1] + '(\\s|$)';
|
|
396
|
+
} else if (/^#/.test(query)) {
|
|
397
|
+
attr = 'id';
|
|
398
|
+
query = '^' + query.split('#')[1] + '$';
|
|
399
|
+
} else if (/^:/.test(query)) {
|
|
400
|
+
attr = 'name';
|
|
401
|
+
query = '^' + query.split(':')[1] + '$';
|
|
402
|
+
} else {
|
|
403
|
+
attr = 'nodeName';
|
|
404
|
+
query = '^' + (query === 'text' ? '#' + query : query) + '$';
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const regExp = new RegExp(query, 'i');
|
|
408
|
+
valid = function (el) {
|
|
409
|
+
return regExp.test(el[attr]);
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const childList = getListChildNodes(node, (current) => valid(current));
|
|
414
|
+
|
|
415
|
+
return /** @type {T} */ (childList[last ? childList.length - 1 : 0]);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* @description Get edge child nodes of the argument value.
|
|
420
|
+
* - 1. The first node of all the child nodes of the "first" element is returned.
|
|
421
|
+
* - 2. The last node of all the child nodes of the "last" element is returned.
|
|
422
|
+
* - 3. When there is no "last" element, the first and last nodes of all the children of the "first" element are returned.
|
|
423
|
+
* @param {Node} first First element
|
|
424
|
+
* @param {Node|null} last Last element
|
|
425
|
+
* @returns {{sc: Node, ec: Node}} { sc: "first", ec: "last" }
|
|
426
|
+
*/
|
|
427
|
+
export function getEdgeChildNodes(first, last) {
|
|
428
|
+
if (!first) return;
|
|
429
|
+
if (!last) last = first;
|
|
430
|
+
|
|
431
|
+
while (first && first.nodeType === 1 && first.childNodes.length > 0 && !domCheck.isBreak(first)) first = first.firstChild;
|
|
432
|
+
while (last && last.nodeType === 1 && last.childNodes.length > 0 && !domCheck.isBreak(last)) last = last.lastChild;
|
|
433
|
+
|
|
434
|
+
return {
|
|
435
|
+
sc: first,
|
|
436
|
+
ec: last || first
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* @template {Node} T
|
|
442
|
+
* @description Gets the previous sibling last child. If there is no sibling, then it'll take it from the closest ancestor with child
|
|
443
|
+
* @param {Node} node Reference element
|
|
444
|
+
* @param {?Node=} ceiling Highest boundary allowed
|
|
445
|
+
* @returns {T|null} Not found: null
|
|
446
|
+
*/
|
|
447
|
+
export function getPreviousDeepestNode(node, ceiling) {
|
|
448
|
+
let previousNode = node.previousSibling;
|
|
449
|
+
if (!previousNode) {
|
|
450
|
+
for (let parentNode = node.parentNode; parentNode; parentNode = parentNode.parentNode) {
|
|
451
|
+
if (parentNode === ceiling) return null;
|
|
452
|
+
if (parentNode.previousSibling) {
|
|
453
|
+
previousNode = parentNode.previousSibling;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (!previousNode) return null;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (domCheck.isNonEditable(previousNode)) return /** @type {T} */ (/** @type {unknown} */ (previousNode));
|
|
461
|
+
|
|
462
|
+
while (previousNode.lastChild) previousNode = previousNode.lastChild;
|
|
463
|
+
|
|
464
|
+
return /** @type {T} */ (/** @type {unknown} */ (previousNode));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* @template {Node} T
|
|
469
|
+
* @description Gets the next sibling first child. If there is no sibling, then it'll take it from the closest ancestor with child
|
|
470
|
+
* @param {Node} node Reference element
|
|
471
|
+
* @param {?Node=} ceiling Highest boundary allowed
|
|
472
|
+
* @returns {T|null} Not found: null
|
|
473
|
+
*/
|
|
474
|
+
export function getNextDeepestNode(node, ceiling) {
|
|
475
|
+
let nextNode = node.nextSibling;
|
|
476
|
+
if (!nextNode) {
|
|
477
|
+
for (let parentNode = node.parentNode; parentNode; parentNode = parentNode.parentNode) {
|
|
478
|
+
if (parentNode === ceiling) return null;
|
|
479
|
+
if (parentNode.nextSibling) {
|
|
480
|
+
nextNode = parentNode.nextSibling;
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
if (!nextNode) return null;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (domCheck.isNonEditable(nextNode)) return /** @type {T} */ (/** @type {unknown} */ (nextNode));
|
|
488
|
+
|
|
489
|
+
while (nextNode.firstChild) nextNode = nextNode.firstChild;
|
|
490
|
+
|
|
491
|
+
return /** @type {T} */ (/** @type {unknown} */ (nextNode));
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* @description Find the index of the text node in the line element.
|
|
496
|
+
* @param {Node} line Line element (p, div, etc.)
|
|
497
|
+
* @param {Node} offsetContainer Base node to start searching
|
|
498
|
+
* @param {number} offset Base offset to start searching
|
|
499
|
+
* @param {?(current: *) => boolean=} validate Validation function
|
|
500
|
+
* @returns {number}
|
|
501
|
+
*/
|
|
502
|
+
export function findTextIndexOnLine(line, offsetContainer, offset, validate) {
|
|
503
|
+
if (!line) return 0;
|
|
504
|
+
if (!validate) validate = () => true;
|
|
505
|
+
|
|
506
|
+
let index = 0;
|
|
507
|
+
let found = false;
|
|
508
|
+
|
|
509
|
+
(function recursionFunc(node) {
|
|
510
|
+
if (found || node.nodeType === 8) return;
|
|
511
|
+
if (validate(node)) return; // component.is
|
|
512
|
+
|
|
513
|
+
if (node.nodeType === 3) {
|
|
514
|
+
if (node === offsetContainer) {
|
|
515
|
+
index += offset;
|
|
516
|
+
found = true;
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
index += node.textContent.length;
|
|
520
|
+
} else if (node.nodeType === 1) {
|
|
521
|
+
const childNodes = node.childNodes;
|
|
522
|
+
for (let i = 0, len = childNodes.length; i < len; i++) {
|
|
523
|
+
recursionFunc(childNodes[i]);
|
|
524
|
+
if (found) return;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
})(line);
|
|
528
|
+
|
|
529
|
+
return index;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* @description Find the end index of a sequence of at least minTabSize consecutive non-breaking spaces or spaces
|
|
534
|
+
* - which are interpreted as a tab key, occurring after a given base index in a text string.
|
|
535
|
+
* @param {Node} line Line element (p, div, etc.)
|
|
536
|
+
* @param {number} baseIndex Base index to start searching
|
|
537
|
+
* @param {number} minTabSize Minimum number of consecutive spaces to consider as a tab
|
|
538
|
+
* @returns {number} The adjusted index within the line element accounting for non-space characters
|
|
539
|
+
*/
|
|
540
|
+
export function findTabEndIndex(line, baseIndex, minTabSize) {
|
|
541
|
+
if (!line) return 0;
|
|
542
|
+
const innerText = line.textContent;
|
|
543
|
+
const regex = new RegExp(`((\\u00A0|\\s){${minTabSize},})`, 'g');
|
|
544
|
+
let match;
|
|
545
|
+
|
|
546
|
+
regex.lastIndex = baseIndex;
|
|
547
|
+
|
|
548
|
+
while ((match = regex.exec(innerText)) !== null) {
|
|
549
|
+
if (match.index >= baseIndex) {
|
|
550
|
+
const spaceEndIndex = match.index + match[0].length - 1;
|
|
551
|
+
const precedingText = innerText.slice(0, spaceEndIndex + 1);
|
|
552
|
+
const nonSpaceCharCount = (precedingText.match(/[^\u00A0\s]/g) || []).length;
|
|
553
|
+
return spaceEndIndex + nonSpaceCharCount + minTabSize;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return 0;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* @description Finds the table cell that appears visually at the bottom-right position,
|
|
562
|
+
* considering both rowSpan and colSpan, even if smaller cells are placed after large merged cells.
|
|
563
|
+
*
|
|
564
|
+
* @param {HTMLTableCellElement[]} cells
|
|
565
|
+
* @returns {HTMLTableCellElement|null}
|
|
566
|
+
*/
|
|
567
|
+
export function findVisualLastCell(cells) {
|
|
568
|
+
if (!cells || cells.length === 0) return null;
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* @description visibility col index
|
|
572
|
+
* @type {Object<number, boolean[]>}
|
|
573
|
+
*/
|
|
574
|
+
const occupied = {};
|
|
575
|
+
|
|
576
|
+
let target = null;
|
|
577
|
+
let maxRowEnd = -1;
|
|
578
|
+
let maxColEnd = -1;
|
|
579
|
+
|
|
580
|
+
for (const cell of cells) {
|
|
581
|
+
const row = /** @type {HTMLTableRowElement} */ (cell.parentElement);
|
|
582
|
+
const rowIndex = row.rowIndex;
|
|
583
|
+
const rowSpan = cell.rowSpan || 1;
|
|
584
|
+
const colSpan = cell.colSpan || 1;
|
|
585
|
+
|
|
586
|
+
// 현재 행에서 visual column index 찾기
|
|
587
|
+
if (!occupied[rowIndex]) occupied[rowIndex] = [];
|
|
588
|
+
|
|
589
|
+
let colIndex = 0;
|
|
590
|
+
const rowOcc = occupied[rowIndex];
|
|
591
|
+
while (rowOcc[colIndex]) colIndex++;
|
|
592
|
+
|
|
593
|
+
for (let i = 0; i < colSpan; i++) {
|
|
594
|
+
rowOcc[colIndex + i] = true;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
for (let r = 1; r < rowSpan; r++) {
|
|
598
|
+
const nextRow = rowIndex + r;
|
|
599
|
+
if (!occupied[nextRow]) occupied[nextRow] = [];
|
|
600
|
+
for (let i = 0; i < colSpan; i++) {
|
|
601
|
+
occupied[nextRow][colIndex + i] = true;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const visualRowEnd = rowIndex + rowSpan - 1;
|
|
606
|
+
const visualColEnd = colIndex + colSpan - 1;
|
|
607
|
+
|
|
608
|
+
// right-bottom
|
|
609
|
+
if (visualRowEnd > maxRowEnd || (visualRowEnd === maxRowEnd && visualColEnd > maxColEnd)) {
|
|
610
|
+
maxRowEnd = visualRowEnd;
|
|
611
|
+
maxColEnd = visualColEnd;
|
|
612
|
+
target = cell;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
return target;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* @description Finds and returns parent containers that are scrollable.
|
|
621
|
+
* @param {HTMLElement} element - Element to start with
|
|
622
|
+
* @returns {HTMLElement[]} - Array (in descending order)
|
|
623
|
+
*/
|
|
624
|
+
export function getScrollParents(element) {
|
|
625
|
+
const scrollable = [];
|
|
626
|
+
let parent = element?.parentElement;
|
|
627
|
+
|
|
628
|
+
while (parent && !/^(body|html)$/i.test(parent.nodeName)) {
|
|
629
|
+
const style = _w.getComputedStyle(parent);
|
|
630
|
+
const { overflow, overflowX, overflowY } = style;
|
|
631
|
+
|
|
632
|
+
const canScroll = [overflow, overflowX, overflowY].some((prop) => ['auto', 'scroll', 'overlay'].includes(prop));
|
|
633
|
+
|
|
634
|
+
if (canScroll) {
|
|
635
|
+
scrollable.push(parent);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
parent = parent.parentElement;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
return scrollable;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* @description Get the argument iframe's document object if use the "iframe" or "fullPage" options
|
|
646
|
+
* @param {HTMLIFrameElement} iframe Iframe element (this.editor.frameContext.get('wysiwygFrame'))
|
|
647
|
+
* @returns {Document}
|
|
648
|
+
*/
|
|
649
|
+
export function getIframeDocument(iframe) {
|
|
650
|
+
return iframe.contentWindow?.document || iframe.contentDocument;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
const query = {
|
|
654
|
+
getPositionIndex,
|
|
655
|
+
getNodePath,
|
|
656
|
+
getNodeFromPath,
|
|
657
|
+
getListChildren,
|
|
658
|
+
getListChildNodes,
|
|
659
|
+
getNodeDepth,
|
|
660
|
+
sortNodeByDepth,
|
|
661
|
+
compareElements,
|
|
662
|
+
getParentElement,
|
|
663
|
+
getParentElements,
|
|
664
|
+
getCommandTarget,
|
|
665
|
+
getEventTarget,
|
|
666
|
+
getEdgeChild,
|
|
667
|
+
getEdgeChildNodes,
|
|
668
|
+
getPreviousDeepestNode,
|
|
669
|
+
getNextDeepestNode,
|
|
670
|
+
findTextIndexOnLine,
|
|
671
|
+
findTabEndIndex,
|
|
672
|
+
findVisualLastCell,
|
|
673
|
+
getScrollParents,
|
|
674
|
+
getIframeDocument
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
export default query;
|