suneditor 3.0.0-beta.3 → 3.0.0-beta.30

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.
Files changed (241) hide show
  1. package/CONTRIBUTING.md +8 -8
  2. package/README.md +44 -49
  3. package/dist/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +1 -1
  5. package/package.json +95 -53
  6. package/src/assets/design/color.css +2 -2
  7. package/src/assets/design/size.css +2 -0
  8. package/src/assets/icons/defaultIcons.js +16 -1
  9. package/src/assets/suneditor-contents.css +9 -8
  10. package/src/assets/suneditor.css +29 -26
  11. package/src/core/{section → base}/actives.js +20 -12
  12. package/src/core/base/history.js +4 -4
  13. package/src/core/class/char.js +10 -10
  14. package/src/core/class/component.js +146 -57
  15. package/src/core/class/format.js +94 -2458
  16. package/src/core/class/html.js +187 -129
  17. package/src/core/class/inline.js +1853 -0
  18. package/src/core/class/listFormat.js +582 -0
  19. package/src/core/class/menu.js +14 -3
  20. package/src/core/class/nodeTransform.js +9 -14
  21. package/src/core/class/offset.js +162 -197
  22. package/src/core/class/selection.js +137 -34
  23. package/src/core/class/toolbar.js +73 -52
  24. package/src/core/class/ui.js +11 -11
  25. package/src/core/class/viewer.js +56 -55
  26. package/src/core/config/context.js +122 -0
  27. package/src/core/config/frameContext.js +204 -0
  28. package/src/core/config/options.js +639 -0
  29. package/src/core/editor.js +181 -108
  30. package/src/core/event/actions/index.js +229 -0
  31. package/src/core/event/effects/common.registry.js +60 -0
  32. package/src/core/event/effects/keydown.registry.js +551 -0
  33. package/src/core/event/effects/ruleHelpers.js +145 -0
  34. package/src/core/{base → event}/eventManager.js +119 -201
  35. package/src/core/event/executor.js +21 -0
  36. package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +4 -4
  37. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +2 -2
  38. package/src/core/event/handlers/handler_ww_input.js +77 -0
  39. package/src/core/event/handlers/handler_ww_key.js +228 -0
  40. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.js +3 -3
  41. package/src/core/event/ports.js +211 -0
  42. package/src/core/event/reducers/keydown.reducer.js +89 -0
  43. package/src/core/event/rules/keydown.rule.arrow.js +54 -0
  44. package/src/core/event/rules/keydown.rule.backspace.js +202 -0
  45. package/src/core/event/rules/keydown.rule.delete.js +126 -0
  46. package/src/core/event/rules/keydown.rule.enter.js +144 -0
  47. package/src/core/event/rules/keydown.rule.tab.js +29 -0
  48. package/src/core/section/constructor.js +79 -388
  49. package/src/core/section/documentType.js +47 -26
  50. package/src/core/util/instanceCheck.js +59 -0
  51. package/src/editorInjector/_classes.js +4 -0
  52. package/src/editorInjector/_core.js +17 -7
  53. package/src/editorInjector/index.js +10 -2
  54. package/src/events.js +6 -0
  55. package/src/helper/clipboard.js +24 -10
  56. package/src/helper/converter.js +17 -12
  57. package/src/helper/dom/domCheck.js +22 -3
  58. package/src/helper/dom/domQuery.js +91 -45
  59. package/src/helper/dom/domUtils.js +93 -19
  60. package/src/helper/dom/index.js +4 -0
  61. package/src/helper/env.js +11 -7
  62. package/src/helper/keyCodeMap.js +4 -3
  63. package/src/langs/ckb.js +1 -1
  64. package/src/langs/cs.js +1 -1
  65. package/src/langs/da.js +1 -1
  66. package/src/langs/de.js +1 -1
  67. package/src/langs/en.js +1 -1
  68. package/src/langs/es.js +1 -1
  69. package/src/langs/fa.js +1 -1
  70. package/src/langs/fr.js +1 -1
  71. package/src/langs/he.js +1 -1
  72. package/src/langs/hu.js +1 -1
  73. package/src/langs/it.js +1 -1
  74. package/src/langs/ja.js +1 -1
  75. package/src/langs/km.js +1 -1
  76. package/src/langs/ko.js +1 -1
  77. package/src/langs/lv.js +1 -1
  78. package/src/langs/nl.js +1 -1
  79. package/src/langs/pl.js +1 -1
  80. package/src/langs/pt_br.js +10 -10
  81. package/src/langs/ro.js +1 -1
  82. package/src/langs/ru.js +1 -1
  83. package/src/langs/se.js +1 -1
  84. package/src/langs/tr.js +1 -1
  85. package/src/langs/uk.js +1 -1
  86. package/src/langs/ur.js +1 -1
  87. package/src/langs/zh_cn.js +1 -1
  88. package/src/modules/ApiManager.js +25 -18
  89. package/src/modules/Browser.js +52 -61
  90. package/src/modules/ColorPicker.js +37 -38
  91. package/src/modules/Controller.js +85 -79
  92. package/src/modules/Figure.js +275 -187
  93. package/src/modules/FileManager.js +86 -92
  94. package/src/modules/HueSlider.js +67 -35
  95. package/src/modules/Modal.js +84 -77
  96. package/src/modules/ModalAnchorEditor.js +62 -79
  97. package/src/modules/SelectMenu.js +89 -86
  98. package/src/plugins/browser/audioGallery.js +9 -5
  99. package/src/plugins/browser/fileBrowser.js +10 -6
  100. package/src/plugins/browser/fileGallery.js +9 -5
  101. package/src/plugins/browser/imageGallery.js +9 -5
  102. package/src/plugins/browser/videoGallery.js +11 -6
  103. package/src/plugins/command/blockquote.js +1 -0
  104. package/src/plugins/command/exportPDF.js +11 -8
  105. package/src/plugins/command/fileUpload.js +41 -29
  106. package/src/plugins/command/list_bulleted.js +2 -1
  107. package/src/plugins/command/list_numbered.js +2 -1
  108. package/src/plugins/dropdown/align.js +8 -2
  109. package/src/plugins/dropdown/backgroundColor.js +19 -11
  110. package/src/plugins/dropdown/font.js +15 -9
  111. package/src/plugins/dropdown/fontColor.js +19 -11
  112. package/src/plugins/dropdown/formatBlock.js +7 -2
  113. package/src/plugins/dropdown/hr.js +7 -3
  114. package/src/plugins/dropdown/layout.js +6 -2
  115. package/src/plugins/dropdown/lineHeight.js +8 -3
  116. package/src/plugins/dropdown/list.js +2 -1
  117. package/src/plugins/dropdown/paragraphStyle.js +15 -11
  118. package/src/plugins/dropdown/{table.js → table/index.js} +514 -362
  119. package/src/plugins/dropdown/template.js +6 -2
  120. package/src/plugins/dropdown/textStyle.js +7 -3
  121. package/src/plugins/field/mention.js +33 -27
  122. package/src/plugins/input/fontSize.js +44 -37
  123. package/src/plugins/input/pageNavigator.js +3 -2
  124. package/src/plugins/modal/audio.js +90 -85
  125. package/src/plugins/modal/drawing.js +58 -66
  126. package/src/plugins/modal/embed.js +193 -180
  127. package/src/plugins/modal/image.js +441 -439
  128. package/src/plugins/modal/link.js +31 -8
  129. package/src/plugins/modal/math.js +23 -22
  130. package/src/plugins/modal/video.js +233 -230
  131. package/src/plugins/popup/anchor.js +24 -18
  132. package/src/suneditor.js +69 -24
  133. package/src/typedef.js +42 -19
  134. package/types/assets/icons/defaultIcons.d.ts +8 -0
  135. package/types/core/class/char.d.ts +1 -1
  136. package/types/core/class/component.d.ts +29 -7
  137. package/types/core/class/format.d.ts +4 -354
  138. package/types/core/class/html.d.ts +13 -4
  139. package/types/core/class/inline.d.ts +263 -0
  140. package/types/core/class/listFormat.d.ts +135 -0
  141. package/types/core/class/menu.d.ts +10 -2
  142. package/types/core/class/offset.d.ts +24 -26
  143. package/types/core/class/selection.d.ts +2 -0
  144. package/types/core/class/toolbar.d.ts +24 -11
  145. package/types/core/class/ui.d.ts +1 -1
  146. package/types/core/class/viewer.d.ts +1 -1
  147. package/types/core/config/context.d.ts +157 -0
  148. package/types/core/config/frameContext.d.ts +367 -0
  149. package/types/core/config/options.d.ts +1119 -0
  150. package/types/core/editor.d.ts +101 -66
  151. package/types/core/event/actions/index.d.ts +47 -0
  152. package/types/core/event/effects/common.registry.d.ts +50 -0
  153. package/types/core/event/effects/keydown.registry.d.ts +73 -0
  154. package/types/core/event/effects/ruleHelpers.d.ts +31 -0
  155. package/types/core/{base → event}/eventManager.d.ts +15 -46
  156. package/types/core/event/executor.d.ts +6 -0
  157. package/types/core/event/handlers/handler_ww_input.d.ts +41 -0
  158. package/types/core/{base/eventHandlers/handler_ww_key_input.d.ts → event/handlers/handler_ww_key.d.ts} +4 -6
  159. package/types/core/event/ports.d.ts +255 -0
  160. package/types/core/event/reducers/keydown.reducer.d.ts +75 -0
  161. package/types/core/event/rules/keydown.rule.arrow.d.ts +8 -0
  162. package/types/core/event/rules/keydown.rule.backspace.d.ts +9 -0
  163. package/types/core/event/rules/keydown.rule.delete.d.ts +9 -0
  164. package/types/core/event/rules/keydown.rule.enter.d.ts +9 -0
  165. package/types/core/event/rules/keydown.rule.tab.d.ts +9 -0
  166. package/types/core/section/constructor.d.ts +101 -631
  167. package/types/core/section/documentType.d.ts +14 -4
  168. package/types/core/util/instanceCheck.d.ts +50 -0
  169. package/types/editorInjector/_classes.d.ts +4 -0
  170. package/types/editorInjector/_core.d.ts +17 -7
  171. package/types/editorInjector/index.d.ts +10 -2
  172. package/types/events.d.ts +1 -0
  173. package/types/helper/clipboard.d.ts +2 -2
  174. package/types/helper/converter.d.ts +6 -9
  175. package/types/helper/dom/domCheck.d.ts +7 -0
  176. package/types/helper/dom/domQuery.d.ts +19 -8
  177. package/types/helper/dom/domUtils.d.ts +24 -2
  178. package/types/helper/dom/index.d.ts +86 -1
  179. package/types/helper/env.d.ts +6 -1
  180. package/types/helper/index.d.ts +7 -1
  181. package/types/helper/keyCodeMap.d.ts +3 -3
  182. package/types/index.d.ts +23 -117
  183. package/types/langs/index.d.ts +2 -2
  184. package/types/modules/ApiManager.d.ts +1 -8
  185. package/types/modules/Browser.d.ts +4 -62
  186. package/types/modules/ColorPicker.d.ts +4 -21
  187. package/types/modules/Controller.d.ts +8 -64
  188. package/types/modules/Figure.d.ts +54 -50
  189. package/types/modules/FileManager.d.ts +1 -13
  190. package/types/modules/HueSlider.d.ts +13 -3
  191. package/types/modules/Modal.d.ts +0 -43
  192. package/types/modules/ModalAnchorEditor.d.ts +0 -73
  193. package/types/modules/SelectMenu.d.ts +0 -85
  194. package/types/modules/index.d.ts +3 -3
  195. package/types/plugins/browser/audioGallery.d.ts +29 -18
  196. package/types/plugins/browser/fileBrowser.d.ts +38 -27
  197. package/types/plugins/browser/fileGallery.d.ts +29 -18
  198. package/types/plugins/browser/imageGallery.d.ts +24 -16
  199. package/types/plugins/browser/videoGallery.d.ts +29 -18
  200. package/types/plugins/command/blockquote.d.ts +1 -0
  201. package/types/plugins/command/exportPDF.d.ts +18 -18
  202. package/types/plugins/command/fileUpload.d.ts +65 -45
  203. package/types/plugins/command/list_bulleted.d.ts +1 -0
  204. package/types/plugins/command/list_numbered.d.ts +1 -0
  205. package/types/plugins/dropdown/align.d.ts +13 -8
  206. package/types/plugins/dropdown/backgroundColor.d.ts +30 -19
  207. package/types/plugins/dropdown/font.d.ts +13 -12
  208. package/types/plugins/dropdown/fontColor.d.ts +30 -19
  209. package/types/plugins/dropdown/formatBlock.d.ts +13 -8
  210. package/types/plugins/dropdown/hr.d.ts +15 -11
  211. package/types/plugins/dropdown/layout.d.ts +15 -11
  212. package/types/plugins/dropdown/lineHeight.d.ts +16 -11
  213. package/types/plugins/dropdown/list.d.ts +1 -0
  214. package/types/plugins/dropdown/paragraphStyle.d.ts +31 -27
  215. package/types/plugins/dropdown/table/index.d.ts +582 -0
  216. package/types/plugins/dropdown/table.d.ts +41 -86
  217. package/types/plugins/dropdown/template.d.ts +15 -11
  218. package/types/plugins/dropdown/textStyle.d.ts +19 -11
  219. package/types/plugins/field/mention.d.ts +58 -56
  220. package/types/plugins/index.d.ts +38 -38
  221. package/types/plugins/input/fontSize.d.ts +46 -50
  222. package/types/plugins/modal/audio.d.ts +26 -56
  223. package/types/plugins/modal/drawing.d.ts +0 -85
  224. package/types/plugins/modal/embed.d.ts +15 -79
  225. package/types/plugins/modal/image.d.ts +24 -136
  226. package/types/plugins/modal/link.d.ts +34 -15
  227. package/types/plugins/modal/math.d.ts +0 -16
  228. package/types/plugins/modal/video.d.ts +17 -86
  229. package/types/plugins/popup/anchor.d.ts +1 -8
  230. package/types/suneditor.d.ts +70 -19
  231. package/types/typedef.d.ts +60 -46
  232. package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
  233. package/src/core/section/context.js +0 -102
  234. package/types/core/section/context.d.ts +0 -45
  235. package/types/langs/_Lang.d.ts +0 -194
  236. /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +0 -0
  237. /package/types/core/{section → base}/actives.d.ts +0 -0
  238. /package/types/core/{base/eventHandlers → event/handlers}/handler_toolbar.d.ts +0 -0
  239. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.d.ts +0 -0
  240. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.d.ts +0 -0
  241. /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.d.ts +0 -0
@@ -0,0 +1,582 @@
1
+ /**
2
+ * @fileoverview Format class
3
+ */
4
+
5
+ import CoreInjector from '../../editorInjector/_core';
6
+ import { dom } from '../../helper';
7
+
8
+ /**
9
+ * @typedef {Omit<ListFormat & Partial<__se__EditorInjector>, 'ListFormat'>} ListFormatThis
10
+ */
11
+
12
+ /**
13
+ * @constructor
14
+ * @this {ListFormatThis}
15
+ * @description Classes related to editor formats such as "list" (ol, ul, li)
16
+ * - "list" is a special "line", "block" format.
17
+ * @param {__se__EditorCore} editor - The root editor instance
18
+ */
19
+ function ListFormat(editor) {
20
+ CoreInjector.call(this, editor);
21
+ }
22
+
23
+ ListFormat.prototype = {
24
+ /**
25
+ * @this {ListFormatThis}
26
+ * @description Append all selected "line" element to the list and insert.
27
+ * @param {string} type List type. (ol | ul):[listStyleType]
28
+ * @param {Array<Node>} selectedCells "line" elements or list cells.
29
+ * @param {boolean} nested If true, indenting existing list cells.
30
+ */
31
+ apply(type, selectedCells, nested) {
32
+ const listTag = (type.split(':')[0] || 'ol').toUpperCase();
33
+ const listStyle = type.split(':')[1] || '';
34
+
35
+ let range = this.selection.getRange();
36
+ let selectedFormats = /** @type {Array<HTMLElement>} */ (!selectedCells ? this.format.getLinesAndComponents(false) : selectedCells);
37
+
38
+ if (selectedFormats.length === 0) {
39
+ if (selectedCells) return;
40
+ range = this.selection.getRangeAndAddLine(range, null);
41
+ selectedFormats = this.format.getLinesAndComponents(false);
42
+ if (selectedFormats.length === 0) return;
43
+ }
44
+
45
+ dom.query.sortNodeByDepth(selectedFormats, true);
46
+
47
+ // merge
48
+ const firstSel = selectedFormats[0];
49
+ const lastSel = selectedFormats.at(-1);
50
+ let topEl = (dom.check.isListCell(firstSel) || this.component.is(firstSel)) && !firstSel.previousElementSibling ? firstSel.parentElement.previousElementSibling : firstSel.previousElementSibling;
51
+ let bottomEl = (dom.check.isListCell(lastSel) || this.component.is(lastSel)) && !lastSel.nextElementSibling ? lastSel.parentElement.nextElementSibling : lastSel.nextElementSibling;
52
+
53
+ const isCollapsed = range.collapsed;
54
+ const originRange = {
55
+ sc: range.startContainer,
56
+ so: range.startContainer === range.endContainer && dom.check.isZeroWidth(range.startContainer) && range.startOffset === 0 && range.endOffset === 1 ? range.endOffset : range.startOffset,
57
+ ec: range.endContainer,
58
+ eo: range.endOffset
59
+ };
60
+ let afterRange = null;
61
+ let isRemove = true;
62
+
63
+ for (let i = 0, len = selectedFormats.length; i < len; i++) {
64
+ if (!dom.check.isList(this.format.getBlock(selectedFormats[i], (current) => this.format.getBlock(current) && current !== selectedFormats[i]))) {
65
+ isRemove = false;
66
+ break;
67
+ }
68
+ }
69
+
70
+ if (isRemove && (!topEl || firstSel.tagName !== topEl.tagName || listTag !== topEl.tagName.toUpperCase()) && (!bottomEl || lastSel.tagName !== bottomEl.tagName || listTag !== bottomEl.tagName.toUpperCase())) {
71
+ if (nested) {
72
+ for (let i = 0, len = selectedFormats.length; i < len; i++) {
73
+ for (let j = i - 1; j >= 0; j--) {
74
+ if (selectedFormats[j].contains(selectedFormats[i])) {
75
+ selectedFormats.splice(i, 1);
76
+ i--;
77
+ len--;
78
+ break;
79
+ }
80
+ }
81
+ }
82
+ }
83
+
84
+ const currentFormat = this.format.getBlock(firstSel);
85
+ const cancel = currentFormat?.tagName === listTag;
86
+ let rangeArr, tempList;
87
+ const passComponent = (current) => {
88
+ return !dom.check.isComponentContainer(current);
89
+ };
90
+
91
+ if (!cancel) {
92
+ tempList = dom.utils.createElement(listTag, { style: 'list-style-type: ' + listStyle });
93
+ }
94
+
95
+ for (let i = 0, len = selectedFormats.length, r, o; i < len; i++) {
96
+ o = this.format.getBlock(selectedFormats[i], passComponent);
97
+ if (!o || !dom.check.isList(o)) continue;
98
+
99
+ if (!r) {
100
+ r = o;
101
+ rangeArr = {
102
+ r: r,
103
+ f: [dom.query.getParentElement(selectedFormats[i], 'LI')]
104
+ };
105
+ } else {
106
+ if (r !== o) {
107
+ if (nested && dom.check.isListCell(o.parentNode)) {
108
+ this._detachNested(rangeArr.f);
109
+ } else {
110
+ afterRange = this.format.removeBlock(rangeArr.f[0].parentElement, { selectedFormats: rangeArr.f, newBlockElement: tempList, shouldDelete: false, skipHistory: true });
111
+ }
112
+
113
+ o = selectedFormats[i].parentNode;
114
+ if (!cancel) {
115
+ tempList = dom.utils.createElement(listTag, { style: 'list-style-type: ' + listStyle });
116
+ }
117
+
118
+ r = o;
119
+ rangeArr = {
120
+ r: r,
121
+ f: [dom.query.getParentElement(selectedFormats[i], 'LI')]
122
+ };
123
+ } else {
124
+ rangeArr.f.push(dom.query.getParentElement(selectedFormats[i], 'LI'));
125
+ }
126
+ }
127
+
128
+ if (i === len - 1) {
129
+ if (nested && dom.check.isListCell(o.parentNode)) {
130
+ this._detachNested(rangeArr.f);
131
+ } else {
132
+ afterRange = this.format.removeBlock(rangeArr.f[0].parentElement, { selectedFormats: rangeArr.f, newBlockElement: tempList, shouldDelete: false, skipHistory: true });
133
+ }
134
+ }
135
+ }
136
+ } else {
137
+ const topElParent = topEl ? topEl.parentNode : topEl;
138
+ const bottomElParent = bottomEl ? bottomEl.parentNode : bottomEl;
139
+ topEl = /** @type {HTMLElement} */ (topElParent && !dom.check.isWysiwygFrame(topElParent) && topElParent.nodeName === listTag ? topElParent : topEl);
140
+ bottomEl = /** @type {HTMLElement} */ (bottomElParent && !dom.check.isWysiwygFrame(bottomElParent) && bottomElParent.nodeName === listTag ? bottomElParent : bottomEl);
141
+
142
+ const mergeTop = topEl?.tagName === listTag;
143
+ const mergeBottom = bottomEl?.tagName === listTag;
144
+
145
+ let list = mergeTop ? topEl : dom.utils.createElement(listTag, { style: 'list-style-type: ' + listStyle });
146
+ let firstList = null;
147
+ let topNumber = null;
148
+ // let lastList = null;
149
+ // let bottomNumber = null;
150
+
151
+ const passComponent = (current) => {
152
+ return !dom.check.isComponentContainer(current) && !dom.check.isList(current);
153
+ };
154
+
155
+ for (let i = 0, len = selectedFormats.length, newCell, fTag, isCell, next, originParent, nextParent, parentTag, siblingTag, rangeTag; i < len; i++) {
156
+ fTag = selectedFormats[i];
157
+ if (fTag.childNodes.length === 0 && !this.inline._isIgnoreNodeChange(fTag)) {
158
+ dom.utils.removeItem(fTag);
159
+ continue;
160
+ }
161
+ next = selectedFormats[i + 1];
162
+ originParent = fTag.parentNode;
163
+ nextParent = next ? next.parentNode : null;
164
+ isCell = dom.check.isListCell(fTag);
165
+ rangeTag = this.format.isBlock(originParent) ? originParent : null;
166
+ parentTag = isCell && !dom.check.isWysiwygFrame(originParent) ? originParent.parentNode : originParent;
167
+ siblingTag = isCell && !dom.check.isWysiwygFrame(originParent) ? (!next || dom.check.isListCell(parentTag) ? originParent : originParent.nextSibling) : fTag.nextSibling;
168
+
169
+ newCell = dom.utils.createElement('LI');
170
+
171
+ if (this.component.is(fTag)) {
172
+ const isHR = /^HR$/i.test(fTag.nodeName);
173
+ if (!isHR) newCell.innerHTML = '<br>';
174
+ newCell.innerHTML += fTag.outerHTML;
175
+ if (isHR) newCell.innerHTML += '<br>';
176
+ } else {
177
+ dom.utils.copyFormatAttributes(newCell, fTag);
178
+ const fChildren = fTag.childNodes;
179
+ while (fChildren[0]) {
180
+ newCell.appendChild(fChildren[0]);
181
+ }
182
+ }
183
+ list.appendChild(newCell);
184
+
185
+ // if (!next) lastList = list;
186
+ if (!next || parentTag !== nextParent || this.format.isBlock(siblingTag)) {
187
+ firstList ||= list;
188
+ if ((!mergeTop || !next || parentTag !== nextParent) && !(next && dom.check.isList(nextParent) && nextParent === originParent)) {
189
+ if (list.parentNode !== parentTag) parentTag.insertBefore(list, siblingTag);
190
+ }
191
+ }
192
+
193
+ dom.utils.removeItem(fTag);
194
+ if (mergeTop && topNumber === null) topNumber = list.children.length - 1;
195
+ if (
196
+ next &&
197
+ (this.format.getBlock(nextParent, passComponent) !== this.format.getBlock(originParent, passComponent) ||
198
+ (dom.check.isList(nextParent) && dom.check.isList(originParent) && dom.query.getNodeDepth(nextParent) !== dom.query.getNodeDepth(originParent)))
199
+ ) {
200
+ list = dom.utils.createElement(listTag, { style: 'list-style-type: ' + listStyle });
201
+ }
202
+
203
+ if (rangeTag?.children.length === 0) dom.utils.removeItem(rangeTag);
204
+ }
205
+
206
+ if (topNumber) {
207
+ firstList = firstList.children[topNumber];
208
+ }
209
+
210
+ if (mergeBottom) {
211
+ // bottomNumber = list.children.length - 1;
212
+ list.innerHTML += bottomEl.innerHTML;
213
+ // lastList = list.children[bottomNumber] || lastList;
214
+ dom.utils.removeItem(bottomEl);
215
+ }
216
+ }
217
+
218
+ this.editor.effectNode = null;
219
+ return !isRemove || !isCollapsed ? originRange : afterRange || originRange;
220
+ },
221
+
222
+ /**
223
+ * @this {ListFormatThis}
224
+ * @description "selectedCells" array are detached from the list element.
225
+ * - The return value is applied when the first and last lines of "selectedFormats" are "LI" respectively.
226
+ * @param {Array<Node>} selectedCells Array of ["line", li] elements(LI, P...) to remove.
227
+ * @param {boolean} shouldDelete If true, It does not just remove the list, it deletes the content.
228
+ * @returns {{sc: Node, ec: Node}} Node information after deletion
229
+ * - sc: Start container node
230
+ * - ec: End container node
231
+ */
232
+ remove(selectedCells, shouldDelete) {
233
+ let rangeArr = {};
234
+ let listFirst = false;
235
+ let listLast = false;
236
+ let first = null;
237
+ let last = null;
238
+ const passComponent = (current) => {
239
+ return !dom.check.isComponentContainer(current);
240
+ };
241
+
242
+ for (let i = 0, len = selectedCells.length, r, o, lastIndex, isList; i < len; i++) {
243
+ lastIndex = i === len - 1;
244
+ o = this.format.getBlock(selectedCells[i], passComponent);
245
+ isList = dom.check.isList(o);
246
+ if (!r && isList) {
247
+ r = o;
248
+ rangeArr = {
249
+ r: r,
250
+ f: [dom.query.getParentElement(selectedCells[i], 'LI')]
251
+ };
252
+ if (i === 0) listFirst = true;
253
+ } else if (r && isList) {
254
+ if (r !== o) {
255
+ const edge = this.format.removeBlock(rangeArr.f[0].parentNode, { selectedFormats: rangeArr.f, newBlockElement: null, shouldDelete, skipHistory: true });
256
+ o = selectedCells[i].parentNode;
257
+ if (listFirst) {
258
+ first = edge.sc;
259
+ listFirst = false;
260
+ }
261
+ if (lastIndex) last = edge.ec;
262
+
263
+ if (isList) {
264
+ r = o;
265
+ rangeArr = {
266
+ r: r,
267
+ f: [dom.query.getParentElement(selectedCells[i], 'LI')]
268
+ };
269
+ if (lastIndex) listLast = true;
270
+ } else {
271
+ r = null;
272
+ }
273
+ } else {
274
+ rangeArr.f.push(dom.query.getParentElement(selectedCells[i], 'LI'));
275
+ if (lastIndex) listLast = true;
276
+ }
277
+ }
278
+
279
+ if (lastIndex && dom.check.isList(r)) {
280
+ const edge = this.format.removeBlock(rangeArr.f[0].parentNode, { selectedFormats: rangeArr.f, newBlockElement: null, shouldDelete, skipHistory: true });
281
+ if (listLast || len === 1) last = edge.ec;
282
+ if (listFirst) first = edge.sc || last;
283
+ }
284
+ }
285
+
286
+ return {
287
+ sc: first,
288
+ ec: last
289
+ };
290
+ },
291
+
292
+ /**
293
+ * @this {ListFormatThis}
294
+ * @description Nest list cells or cancel nested cells.
295
+ * @param {Array<HTMLElement>} selectedCells List cells.
296
+ * @param {boolean} nested Nested or cancel nested.
297
+ */
298
+ applyNested(selectedCells, nested) {
299
+ selectedCells = !selectedCells
300
+ ? this.format.getLines().filter(function (el) {
301
+ return dom.check.isListCell(el);
302
+ })
303
+ : selectedCells;
304
+ const cellsLen = selectedCells.length;
305
+ if (cellsLen === 0 || (!nested && !dom.check.isListCell(selectedCells[0].previousElementSibling) && !dom.check.isListCell(selectedCells.at(-1).nextElementSibling))) {
306
+ return {
307
+ sc: selectedCells[0],
308
+ so: 0,
309
+ ec: selectedCells.at(-1),
310
+ eo: 1
311
+ };
312
+ }
313
+
314
+ let originList = selectedCells[0].parentElement;
315
+ let lastCell = selectedCells.at(-1);
316
+ let range = null;
317
+
318
+ if (nested) {
319
+ if (originList !== lastCell.parentElement && dom.check.isList(lastCell.parentElement.parentElement) && lastCell.nextElementSibling) {
320
+ lastCell = /** @type {HTMLElement} */ (lastCell.nextElementSibling);
321
+ while (lastCell) {
322
+ selectedCells.push(lastCell);
323
+ lastCell = /** @type {HTMLElement} */ (lastCell.nextElementSibling);
324
+ }
325
+ }
326
+ range = this.apply(originList.nodeName + ':' + originList.style.listStyleType, selectedCells, true);
327
+ } else {
328
+ let innerList = dom.utils.createElement(originList.nodeName);
329
+ let prev = selectedCells[0].previousElementSibling;
330
+ let next = lastCell.nextElementSibling;
331
+ const nodePath = {
332
+ s: null,
333
+ e: null,
334
+ sl: originList,
335
+ el: originList
336
+ };
337
+
338
+ const { startContainer, startOffset, endContainer, endOffset } = this.selection.getRange();
339
+ for (let i = 0, len = cellsLen, c; i < len; i++) {
340
+ c = selectedCells[i];
341
+ if (c.parentElement !== originList) {
342
+ this._attachNested(originList, innerList, prev, next, nodePath);
343
+ originList = c.parentElement;
344
+ innerList = dom.utils.createElement(originList.nodeName);
345
+ }
346
+
347
+ prev = c.previousElementSibling;
348
+ next = c.nextElementSibling;
349
+ innerList.appendChild(c);
350
+ }
351
+
352
+ this._attachNested(originList, innerList, prev, next, nodePath);
353
+
354
+ if (cellsLen > 1) {
355
+ const sc = dom.query.getNodeFromPath(nodePath.s, nodePath.sl);
356
+ const ec = dom.query.getNodeFromPath(nodePath.e, nodePath.el);
357
+ range = {
358
+ sc: sc,
359
+ so: 0,
360
+ ec: ec,
361
+ eo: ec.textContent.length
362
+ };
363
+ } else {
364
+ range = {
365
+ sc: startContainer,
366
+ so: startOffset,
367
+ ec: endContainer,
368
+ eo: endOffset
369
+ };
370
+ }
371
+ }
372
+
373
+ return range;
374
+ },
375
+
376
+ /**
377
+ * @this {ListFormatThis}
378
+ * @description Detach Nested all nested lists under the "baseNode".
379
+ * - Returns a list with nested removed.
380
+ * @param {HTMLElement} baseNode Element on which to base.
381
+ * @param {boolean} all If true, it also detach all nested lists of a returned list.
382
+ * @returns {Node} Result element
383
+ */
384
+ removeNested(baseNode, all) {
385
+ const rNode = DeleteNestedList(baseNode);
386
+ let rangeElement, cNodes;
387
+
388
+ if (rNode) {
389
+ rangeElement = rNode.cloneNode(false);
390
+ cNodes = rNode.childNodes;
391
+ const index = dom.query.getPositionIndex(baseNode);
392
+ while (cNodes[index]) {
393
+ rangeElement.appendChild(cNodes[index]);
394
+ }
395
+ } else {
396
+ rangeElement = baseNode;
397
+ }
398
+
399
+ let rChildren;
400
+ if (!all) {
401
+ const depth = dom.query.getNodeDepth(baseNode) + 2;
402
+ rChildren = dom.query.getListChildren(
403
+ baseNode,
404
+ (current) => {
405
+ return dom.check.isListCell(current) && !current.previousElementSibling && dom.query.getNodeDepth(current) === depth;
406
+ },
407
+ null
408
+ );
409
+ } else {
410
+ rChildren = dom.query.getListChildren(
411
+ rangeElement,
412
+ (current) => {
413
+ return dom.check.isListCell(current) && !current.previousElementSibling;
414
+ },
415
+ null
416
+ );
417
+ }
418
+
419
+ for (let i = 0, len = rChildren.length; i < len; i++) {
420
+ DeleteNestedList(rChildren[i]);
421
+ }
422
+
423
+ if (rNode) {
424
+ rNode.parentNode.insertBefore(rangeElement, rNode.nextSibling);
425
+ if (cNodes?.length === 0) dom.utils.removeItem(rNode);
426
+ }
427
+
428
+ return rangeElement === baseNode ? rangeElement.parentNode : rangeElement;
429
+ },
430
+
431
+ /**
432
+ * @private
433
+ * @this {ListFormatThis}
434
+ * @description Attaches a nested list structure by merging adjacent lists if applicable.
435
+ * - Ensures that the nested list is placed correctly in the document structure.
436
+ * @param {Element} originList The original list element where the nested list is inserted.
437
+ * @param {Element} innerList The nested list element.
438
+ * @param {Element} prev The previous sibling element.
439
+ * @param {Element} next The next sibling element.
440
+ * @param {{s: Array<number> | null, e: Array<number> | null, sl: Node | null, el: Node | null}} nodePath Object storing the start and end node paths.
441
+ * - s : Start node path.
442
+ * - e : End node path.
443
+ * - sl : Start node's parent element.
444
+ * - el : End node's parent element.
445
+ * @returns {Node} The attached inner list.
446
+ */
447
+ _attachNested(originList, innerList, prev, next, nodePath) {
448
+ let insertPrev = false;
449
+
450
+ if (innerList.tagName === prev?.tagName) {
451
+ const children = innerList.children;
452
+ while (children[0]) {
453
+ prev.appendChild(children[0]);
454
+ }
455
+
456
+ innerList = prev;
457
+ insertPrev = true;
458
+ }
459
+
460
+ if (innerList.tagName === next?.tagName) {
461
+ const children = next.children;
462
+ while (children[0]) {
463
+ innerList.appendChild(children[0]);
464
+ }
465
+
466
+ const temp = next.nextElementSibling;
467
+ next.parentNode.removeChild(next);
468
+ next = temp;
469
+ }
470
+
471
+ if (!insertPrev) {
472
+ if (dom.check.isListCell(prev)) {
473
+ originList = prev;
474
+ next = null;
475
+ }
476
+
477
+ originList.insertBefore(innerList, next);
478
+
479
+ if (!nodePath.s) {
480
+ nodePath.s = dom.query.getNodePath(innerList.firstElementChild.firstChild, originList, null);
481
+ nodePath.sl = originList;
482
+ }
483
+
484
+ const slPath = originList.contains(nodePath.sl) ? dom.query.getNodePath(nodePath.sl, originList) : null;
485
+ nodePath.e = dom.query.getNodePath(innerList.lastElementChild.firstChild, originList, null);
486
+ nodePath.el = originList;
487
+
488
+ this.nodeTransform.mergeSameTags(originList, [nodePath.s, nodePath.e, slPath], false);
489
+ this.nodeTransform.mergeNestedTags(originList);
490
+ if (slPath) nodePath.sl = dom.query.getNodeFromPath(slPath, originList);
491
+ }
492
+
493
+ return innerList;
494
+ },
495
+
496
+ /**
497
+ * @private
498
+ * @this {ListFormatThis}
499
+ * @description Detaches a nested list structure by extracting list items from their parent list.
500
+ * - Ensures proper restructuring of the list elements.
501
+ * @param {Array<HTMLElement>} cells The list items to be detached.
502
+ * @returns {{cc: Node, sc: Node, ec: Node}} An object containing reference nodes for repositioning.
503
+ * - cc : The parent node of the first list item.
504
+ * - sc : The first list item.
505
+ * - ec : The last list item.
506
+ */
507
+ _detachNested(cells) {
508
+ const first = cells[0];
509
+ const last = cells.at(-1);
510
+ const next = last.nextElementSibling;
511
+ const originList = first.parentElement;
512
+ const sibling = originList.parentElement.nextElementSibling;
513
+ const parentNode = originList.parentElement.parentElement;
514
+
515
+ for (let c = 0, cLen = cells.length; c < cLen; c++) {
516
+ parentNode.insertBefore(cells[c], sibling);
517
+ }
518
+
519
+ if (next && originList.children.length > 0) {
520
+ const newList = originList.cloneNode(false);
521
+ const children = originList.childNodes;
522
+ const index = dom.query.getPositionIndex(next);
523
+ while (children[index]) {
524
+ newList.appendChild(children[index]);
525
+ }
526
+ last.appendChild(newList);
527
+ }
528
+
529
+ if (originList.children.length === 0) dom.utils.removeItem(originList);
530
+ this.nodeTransform.mergeSameTags(parentNode);
531
+
532
+ const edge = dom.query.getEdgeChildNodes(first, last);
533
+
534
+ return {
535
+ cc: first.parentNode,
536
+ sc: edge.sc,
537
+ ec: edge.ec
538
+ };
539
+ },
540
+
541
+ constructor: ListFormat
542
+ };
543
+
544
+ /**
545
+ * @private
546
+ * @param {Node} baseNode Node
547
+ */
548
+ function DeleteNestedList(baseNode) {
549
+ const baseParent = baseNode.parentNode;
550
+ let parent = baseParent.parentNode;
551
+ let siblingNode = /** @type {*} */ (baseParent);
552
+ let liSibling, liParent, child, index, c;
553
+
554
+ while (dom.check.isListCell(parent)) {
555
+ index = dom.query.getPositionIndex(baseNode);
556
+ liSibling = parent.nextElementSibling;
557
+ liParent = parent.parentNode;
558
+ child = siblingNode;
559
+
560
+ while (child) {
561
+ siblingNode = siblingNode.nextSibling;
562
+ if (dom.check.isList(child)) {
563
+ c = child.childNodes;
564
+ while (c[index]) {
565
+ liParent.insertBefore(c[index], liSibling);
566
+ }
567
+ if (c.length === 0) dom.utils.removeItem(child);
568
+ } else {
569
+ liParent.appendChild(child);
570
+ }
571
+ child = siblingNode;
572
+ }
573
+
574
+ parent = liParent.parentNode;
575
+ }
576
+
577
+ if (baseParent.children.length === 0) dom.utils.removeItem(baseParent);
578
+
579
+ return liParent;
580
+ }
581
+
582
+ export default ListFormat;
@@ -190,7 +190,7 @@ Menu.prototype = {
190
190
  menu.style.height = '';
191
191
  dom.utils.addClass(element.parentElement.children, 'on');
192
192
 
193
- this.offset.setRelPosition(menu, this.carrierWrapper, element.parentElement, dom.query.getParentElement(element, '.se-toolbar'), false);
193
+ this.offset.setRelPosition(menu, this.carrierWrapper, element.parentElement, dom.query.getParentElement(element, '.se-toolbar'));
194
194
 
195
195
  menu.style.visibility = '';
196
196
 
@@ -198,6 +198,17 @@ Menu.prototype = {
198
198
  this.__menuContainer = menu;
199
199
  },
200
200
 
201
+ /**
202
+ * @private
203
+ * @this {MenuThis}
204
+ * @description Reset the menu position.
205
+ * @param {Node} element Button element
206
+ * @param {HTMLElement} menu Menu element
207
+ */
208
+ _resetMenuPosition(element, menu) {
209
+ this.offset.setRelPosition(menu, this.carrierWrapper, element.parentElement, dom.query.getParentElement(element, '.se-toolbar'));
210
+ },
211
+
201
212
  /**
202
213
  * @private
203
214
  * @this {MenuThis}
@@ -252,8 +263,8 @@ Menu.prototype = {
252
263
  * @description Remove global event listeners
253
264
  */
254
265
  __removeGlobalEvent() {
255
- if (this._bindClose_dropdown_mouse) this._bindClose_dropdown_mouse = this.eventManager.removeGlobalEvent(this._bindClose_dropdown_mouse);
256
- if (this._bindClose_cons_mouse) this._bindClose_cons_mouse = this.eventManager.removeGlobalEvent(this._bindClose_cons_mouse);
266
+ this._bindClose_dropdown_mouse &&= this.eventManager.removeGlobalEvent(this._bindClose_dropdown_mouse);
267
+ this._bindClose_cons_mouse &&= this.eventManager.removeGlobalEvent(this._bindClose_cons_mouse);
257
268
  if (this._bindClose_dropdown_key) {
258
269
  this._bindClose_dropdown_key = this.eventManager.removeGlobalEvent(this._bindClose_dropdown_key);
259
270
  dom.utils.removeClass(this.menus, 'on');
@@ -111,7 +111,7 @@ NodeTransform.prototype = {
111
111
  }
112
112
  }
113
113
 
114
- if (depthEl.childNodes.length <= 1 && (!depthEl.firstChild || depthEl.firstChild.textContent.length === 0)) /** @type {HTMLElement} */ (depthEl).innerHTML = '<br>';
114
+ if (depthEl.nodeType === 1 && depthEl.childNodes.length <= 1 && !depthEl.firstChild?.textContent?.length) /** @type {HTMLElement} */ (depthEl).innerHTML = '<br>';
115
115
 
116
116
  const pElement = depthEl.parentNode;
117
117
  if (next) depthEl = depthEl.nextSibling;
@@ -143,7 +143,6 @@ NodeTransform.prototype = {
143
143
  * @returns {Array<number>} [offset, ..]
144
144
  */
145
145
  mergeSameTags(element, nodePathArray, onlyText) {
146
- // eslint-disable-next-line @typescript-eslint/no-this-alias
147
146
  const inst = this;
148
147
  const nodePathLen = nodePathArray ? nodePathArray.length : 0;
149
148
  let offsets = null;
@@ -160,7 +159,7 @@ NodeTransform.prototype = {
160
159
  next = /** @type {HTMLElement} */ (children[i + 1]);
161
160
  if (!child) break;
162
161
  if (dom.check.isBreak(child) || dom.check.isMedia(child) || dom.check.isInputElement(child)) continue;
163
- if ((onlyText && inst.format._isIgnoreNodeChange(child)) || (!onlyText && (dom.check.isTableElements(child) || dom.check.isListCell(child) || (inst.format.isLine(child) && !inst.format.isBrLine(child))))) {
162
+ if ((onlyText && inst.inline._isIgnoreNodeChange(child)) || (!onlyText && (dom.check.isTableElements(child) || dom.check.isListCell(child) || (inst.format.isLine(child) && !inst.format.isBrLine(child))))) {
164
163
  if (dom.check.isTableElements(child) || dom.check.isListCell(child)) {
165
164
  recursionFunc(child, depth + 1, i);
166
165
  }
@@ -323,13 +322,12 @@ NodeTransform.prototype = {
323
322
  removeAllParents(item, validation, stopParent) {
324
323
  if (!item) return null;
325
324
  let cc = null;
326
- if (!validation) {
327
- validation = (current) => {
328
- if (current === stopParent || this.component.is(current)) return false;
329
- const text = current.textContent.trim();
330
- return text.length === 0 || /^(\n|\u200B)+$/.test(text);
331
- };
332
- }
325
+
326
+ validation ||= (current) => {
327
+ if (current === stopParent || this.component.is(current)) return false;
328
+ const text = current.textContent.trim();
329
+ return text.length === 0 || /^(\n|\u200B)+$/.test(text);
330
+ };
333
331
 
334
332
  (function recursionFunc(element) {
335
333
  if (!dom.check.isWysiwygFrame(element)) {
@@ -356,13 +354,10 @@ NodeTransform.prototype = {
356
354
  * @param {boolean} forceDelete When all child nodes are deleted, the parent node is also deleted.
357
355
  */
358
356
  removeEmptyNode(element, notRemoveNode, forceDelete) {
359
- // eslint-disable-next-line @typescript-eslint/no-this-alias
360
357
  const inst = this;
361
358
  const allowedEmptyTags = this.options.get('allowedEmptyTags');
362
359
 
363
- if (notRemoveNode) {
364
- notRemoveNode = dom.query.getParentElement(notRemoveNode, (current) => element === current.parentElement);
365
- }
360
+ notRemoveNode &&= dom.query.getParentElement(notRemoveNode, (current) => element === current.parentElement);
366
361
 
367
362
  (function recursionFunc(current) {
368
363
  if (inst.format._notTextNode(current) || current === notRemoveNode || dom.check.isNonEditable(current)) return 0;