suneditor 2.46.2 → 3.0.0-alpha.1

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 (290) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.json +64 -0
  3. package/CONTRIBUTING.md +36 -0
  4. package/LICENSE.txt +1 -1
  5. package/README.md +174 -805
  6. package/dist/suneditor.min.css +1 -0
  7. package/dist/suneditor.min.js +1 -2
  8. package/package.json +96 -69
  9. package/src/assets/icons/_default.js +194 -0
  10. package/src/assets/suneditor-content.css +646 -0
  11. package/src/assets/suneditor.css +3378 -0
  12. package/src/core/base/eventHandlers/handler_toolbar.js +114 -0
  13. package/src/core/base/eventHandlers/handler_ww_clipboard.js +31 -0
  14. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +69 -0
  15. package/src/core/base/eventHandlers/handler_ww_key_input.js +975 -0
  16. package/src/core/base/eventHandlers/handler_ww_mouse.js +118 -0
  17. package/src/core/base/eventManager.js +1115 -0
  18. package/src/core/base/events.js +320 -0
  19. package/src/core/base/history.js +301 -0
  20. package/src/core/class/char.js +146 -0
  21. package/src/core/class/component.js +627 -0
  22. package/src/core/class/format.js +3255 -0
  23. package/src/core/class/html.js +1621 -0
  24. package/src/core/class/menu.js +260 -0
  25. package/src/core/class/nodeTransform.js +379 -0
  26. package/src/core/class/notice.js +42 -0
  27. package/src/core/class/offset.js +578 -0
  28. package/src/core/class/selection.js +508 -0
  29. package/src/core/class/shortcuts.js +38 -0
  30. package/src/core/class/toolbar.js +440 -0
  31. package/src/core/class/viewer.js +646 -0
  32. package/src/core/editor.js +1593 -0
  33. package/src/core/section/actives.js +107 -0
  34. package/src/core/section/constructor.js +1237 -0
  35. package/src/core/section/context.js +97 -0
  36. package/src/editorInjector/_classes.js +22 -0
  37. package/src/editorInjector/_core.js +28 -0
  38. package/src/editorInjector/index.js +13 -0
  39. package/src/helper/converter.js +313 -0
  40. package/src/helper/domUtils.js +1177 -0
  41. package/src/helper/env.js +250 -0
  42. package/src/helper/index.js +19 -0
  43. package/src/helper/numbers.js +68 -0
  44. package/src/helper/unicode.js +43 -0
  45. package/src/langs/ckb.js +161 -0
  46. package/src/langs/cs.js +161 -0
  47. package/src/langs/da.js +161 -0
  48. package/src/langs/de.js +162 -0
  49. package/src/langs/en.js +199 -0
  50. package/src/langs/es.js +162 -0
  51. package/src/langs/fa.js +159 -0
  52. package/src/langs/fr.js +161 -0
  53. package/src/langs/he.js +162 -0
  54. package/src/{lang → langs}/index.js +0 -2
  55. package/src/langs/it.js +162 -0
  56. package/src/langs/ja.js +162 -0
  57. package/src/langs/ko.js +162 -0
  58. package/src/langs/lv.js +162 -0
  59. package/src/langs/nl.js +162 -0
  60. package/src/langs/pl.js +162 -0
  61. package/src/langs/pt_br.js +162 -0
  62. package/src/langs/ro.js +162 -0
  63. package/src/langs/ru.js +162 -0
  64. package/src/langs/se.js +162 -0
  65. package/src/langs/tr.js +159 -0
  66. package/src/langs/ua.js +162 -0
  67. package/src/langs/ur.js +162 -0
  68. package/src/langs/zh_cn.js +162 -0
  69. package/src/modules/ApiManager.js +168 -0
  70. package/src/modules/ColorPicker.js +302 -0
  71. package/src/modules/Controller.js +315 -0
  72. package/src/modules/Figure.js +1160 -0
  73. package/src/modules/FileBrowser.js +271 -0
  74. package/src/modules/FileManager.js +290 -0
  75. package/src/modules/HueSlider.js +513 -0
  76. package/src/modules/Modal.js +177 -0
  77. package/src/modules/ModalAnchorEditor.js +494 -0
  78. package/src/modules/SelectMenu.js +447 -0
  79. package/src/modules/_DragHandle.js +16 -0
  80. package/src/modules/index.js +14 -0
  81. package/src/plugins/command/blockquote.js +47 -47
  82. package/src/plugins/command/exportPdf.js +168 -0
  83. package/src/plugins/command/fileUpload.js +389 -0
  84. package/src/plugins/command/list_bulleted.js +112 -0
  85. package/src/plugins/command/list_numbered.js +115 -0
  86. package/src/plugins/dropdown/align.js +143 -0
  87. package/src/plugins/dropdown/backgroundColor.js +73 -0
  88. package/src/plugins/dropdown/font.js +113 -0
  89. package/src/plugins/dropdown/fontColor.js +73 -0
  90. package/src/plugins/dropdown/formatBlock.js +141 -0
  91. package/src/plugins/dropdown/hr.js +111 -0
  92. package/src/plugins/dropdown/layout.js +72 -0
  93. package/src/plugins/dropdown/lineHeight.js +114 -0
  94. package/src/plugins/dropdown/list.js +107 -0
  95. package/src/plugins/dropdown/paragraphStyle.js +117 -0
  96. package/src/plugins/dropdown/table.js +2810 -0
  97. package/src/plugins/dropdown/template.js +71 -0
  98. package/src/plugins/dropdown/textStyle.js +137 -0
  99. package/src/plugins/field/mention.js +172 -0
  100. package/src/plugins/fileBrowser/imageGallery.js +76 -59
  101. package/src/plugins/index.js +86 -24
  102. package/src/plugins/input/fontSize.js +357 -0
  103. package/src/plugins/modal/audio.js +510 -0
  104. package/src/plugins/modal/image.js +1062 -0
  105. package/src/plugins/modal/link.js +211 -0
  106. package/src/plugins/modal/math.js +347 -0
  107. package/src/plugins/modal/video.js +870 -0
  108. package/src/suneditor.js +62 -67
  109. package/src/themes/test.css +61 -0
  110. package/typings/CommandPlugin.d.ts +8 -0
  111. package/typings/DialogPlugin.d.ts +20 -0
  112. package/typings/FileBrowserPlugin.d.ts +30 -0
  113. package/typings/Lang.d.ts +124 -0
  114. package/typings/Module.d.ts +15 -0
  115. package/typings/Plugin.d.ts +42 -0
  116. package/typings/SubmenuPlugin.d.ts +8 -0
  117. package/typings/_classes.d.ts +17 -0
  118. package/typings/_colorPicker.d.ts +60 -0
  119. package/typings/_core.d.ts +55 -0
  120. package/typings/align.d.ts +5 -0
  121. package/{src/plugins/dialog → typings}/audio.d.ts +1 -1
  122. package/typings/backgroundColor.d.ts +5 -0
  123. package/{src/plugins/command → typings}/blockquote.d.ts +1 -1
  124. package/typings/char.d.ts +39 -0
  125. package/typings/component.d.ts +38 -0
  126. package/typings/context.d.ts +39 -0
  127. package/typings/converter.d.ts +33 -0
  128. package/typings/dialog.d.ts +28 -0
  129. package/typings/domUtils.d.ts +361 -0
  130. package/typings/editor.d.ts +7 -0
  131. package/typings/editor.ts +542 -0
  132. package/typings/env.d.ts +70 -0
  133. package/typings/eventManager.d.ts +37 -0
  134. package/typings/events.d.ts +262 -0
  135. package/typings/fileBrowser.d.ts +42 -0
  136. package/typings/fileManager.d.ts +67 -0
  137. package/typings/font.d.ts +5 -0
  138. package/typings/fontColor.d.ts +5 -0
  139. package/typings/fontSize.d.ts +5 -0
  140. package/typings/format.d.ts +191 -0
  141. package/typings/formatBlock.d.ts +5 -0
  142. package/typings/history.d.ts +48 -0
  143. package/typings/horizontalRule.d.ts +5 -0
  144. package/{src/plugins/dialog → typings}/image.d.ts +1 -1
  145. package/{src/plugins/fileBrowser → typings}/imageGallery.d.ts +1 -1
  146. package/typings/index.d.ts +21 -0
  147. package/{src/plugins/modules/index.d.ts → typings/index.modules.d.ts} +3 -3
  148. package/typings/index.plugins.d.ts +58 -0
  149. package/typings/lineHeight.d.ts +5 -0
  150. package/{src/plugins/dialog → typings}/link.d.ts +1 -1
  151. package/typings/list.d.ts +5 -0
  152. package/{src/plugins/dialog → typings}/math.d.ts +1 -1
  153. package/typings/mediaContainer.d.ts +25 -0
  154. package/typings/node.d.ts +57 -0
  155. package/typings/notice.d.ts +16 -0
  156. package/typings/numbers.d.ts +29 -0
  157. package/typings/offset.d.ts +24 -0
  158. package/typings/options.d.ts +589 -0
  159. package/typings/paragraphStyle.d.ts +5 -0
  160. package/typings/resizing.d.ts +141 -0
  161. package/typings/selection.d.ts +94 -0
  162. package/typings/shortcuts.d.ts +13 -0
  163. package/typings/suneditor.d.ts +9 -0
  164. package/typings/table.d.ts +5 -0
  165. package/typings/template.d.ts +5 -0
  166. package/typings/textStyle.d.ts +5 -0
  167. package/typings/toolbar.d.ts +32 -0
  168. package/typings/unicode.d.ts +25 -0
  169. package/{src/plugins/dialog → typings}/video.d.ts +1 -1
  170. package/dist/css/suneditor.min.css +0 -1
  171. package/src/assets/css/suneditor-contents.css +0 -562
  172. package/src/assets/css/suneditor.css +0 -566
  173. package/src/assets/defaultIcons.js +0 -103
  174. package/src/lang/Lang.d.ts +0 -144
  175. package/src/lang/ckb.d.ts +0 -5
  176. package/src/lang/ckb.js +0 -188
  177. package/src/lang/cs.d.ts +0 -5
  178. package/src/lang/cs.js +0 -188
  179. package/src/lang/da.d.ts +0 -5
  180. package/src/lang/da.js +0 -191
  181. package/src/lang/de.d.ts +0 -5
  182. package/src/lang/de.js +0 -188
  183. package/src/lang/en.d.ts +0 -5
  184. package/src/lang/en.js +0 -188
  185. package/src/lang/es.d.ts +0 -5
  186. package/src/lang/es.js +0 -188
  187. package/src/lang/fa.d.ts +0 -5
  188. package/src/lang/fa.js +0 -188
  189. package/src/lang/fr.d.ts +0 -5
  190. package/src/lang/fr.js +0 -188
  191. package/src/lang/he.d.ts +0 -5
  192. package/src/lang/he.js +0 -188
  193. package/src/lang/index.d.ts +0 -23
  194. package/src/lang/it.d.ts +0 -5
  195. package/src/lang/it.js +0 -188
  196. package/src/lang/ja.d.ts +0 -5
  197. package/src/lang/ja.js +0 -188
  198. package/src/lang/ko.d.ts +0 -5
  199. package/src/lang/ko.js +0 -188
  200. package/src/lang/lv.d.ts +0 -5
  201. package/src/lang/lv.js +0 -188
  202. package/src/lang/nl.d.ts +0 -5
  203. package/src/lang/nl.js +0 -188
  204. package/src/lang/pl.d.ts +0 -5
  205. package/src/lang/pl.js +0 -188
  206. package/src/lang/pt_br.d.ts +0 -5
  207. package/src/lang/pt_br.js +0 -189
  208. package/src/lang/ro.d.ts +0 -5
  209. package/src/lang/ro.js +0 -188
  210. package/src/lang/ru.d.ts +0 -5
  211. package/src/lang/ru.js +0 -188
  212. package/src/lang/se.d.ts +0 -5
  213. package/src/lang/se.js +0 -191
  214. package/src/lang/tr.d.ts +0 -5
  215. package/src/lang/tr.js +0 -191
  216. package/src/lang/ua.d.ts +0 -5
  217. package/src/lang/ua.js +0 -188
  218. package/src/lang/ur.d.ts +0 -5
  219. package/src/lang/ur.js +0 -188
  220. package/src/lang/zh_cn.d.ts +0 -5
  221. package/src/lang/zh_cn.js +0 -187
  222. package/src/lib/constructor.js +0 -954
  223. package/src/lib/context.d.ts +0 -42
  224. package/src/lib/context.js +0 -71
  225. package/src/lib/core.d.ts +0 -1135
  226. package/src/lib/core.js +0 -9395
  227. package/src/lib/history.d.ts +0 -48
  228. package/src/lib/history.js +0 -219
  229. package/src/lib/util.d.ts +0 -678
  230. package/src/lib/util.js +0 -2131
  231. package/src/options.d.ts +0 -608
  232. package/src/plugins/CommandPlugin.d.ts +0 -8
  233. package/src/plugins/DialogPlugin.d.ts +0 -20
  234. package/src/plugins/FileBrowserPlugin.d.ts +0 -30
  235. package/src/plugins/Module.d.ts +0 -15
  236. package/src/plugins/Plugin.d.ts +0 -42
  237. package/src/plugins/SubmenuPlugin.d.ts +0 -8
  238. package/src/plugins/dialog/audio.js +0 -559
  239. package/src/plugins/dialog/image.js +0 -1126
  240. package/src/plugins/dialog/link.js +0 -223
  241. package/src/plugins/dialog/math.js +0 -295
  242. package/src/plugins/dialog/mention.js +0 -242
  243. package/src/plugins/dialog/video.js +0 -979
  244. package/src/plugins/index.d.ts +0 -79
  245. package/src/plugins/modules/_anchor.js +0 -461
  246. package/src/plugins/modules/_colorPicker.d.ts +0 -60
  247. package/src/plugins/modules/_colorPicker.js +0 -201
  248. package/src/plugins/modules/_notice.d.ts +0 -21
  249. package/src/plugins/modules/_notice.js +0 -72
  250. package/src/plugins/modules/_selectMenu.js +0 -119
  251. package/src/plugins/modules/component.d.ts +0 -25
  252. package/src/plugins/modules/component.js +0 -81
  253. package/src/plugins/modules/dialog.d.ts +0 -28
  254. package/src/plugins/modules/dialog.js +0 -175
  255. package/src/plugins/modules/fileBrowser.d.ts +0 -42
  256. package/src/plugins/modules/fileBrowser.js +0 -374
  257. package/src/plugins/modules/fileManager.d.ts +0 -67
  258. package/src/plugins/modules/fileManager.js +0 -326
  259. package/src/plugins/modules/index.js +0 -9
  260. package/src/plugins/modules/resizing.d.ts +0 -154
  261. package/src/plugins/modules/resizing.js +0 -903
  262. package/src/plugins/submenu/align.d.ts +0 -5
  263. package/src/plugins/submenu/align.js +0 -160
  264. package/src/plugins/submenu/font.d.ts +0 -5
  265. package/src/plugins/submenu/font.js +0 -123
  266. package/src/plugins/submenu/fontColor.d.ts +0 -5
  267. package/src/plugins/submenu/fontColor.js +0 -101
  268. package/src/plugins/submenu/fontSize.d.ts +0 -5
  269. package/src/plugins/submenu/fontSize.js +0 -112
  270. package/src/plugins/submenu/formatBlock.d.ts +0 -5
  271. package/src/plugins/submenu/formatBlock.js +0 -273
  272. package/src/plugins/submenu/hiliteColor.d.ts +0 -5
  273. package/src/plugins/submenu/hiliteColor.js +0 -102
  274. package/src/plugins/submenu/horizontalRule.d.ts +0 -5
  275. package/src/plugins/submenu/horizontalRule.js +0 -98
  276. package/src/plugins/submenu/lineHeight.d.ts +0 -5
  277. package/src/plugins/submenu/lineHeight.js +0 -104
  278. package/src/plugins/submenu/list.d.ts +0 -5
  279. package/src/plugins/submenu/list.js +0 -456
  280. package/src/plugins/submenu/paragraphStyle.d.ts +0 -5
  281. package/src/plugins/submenu/paragraphStyle.js +0 -135
  282. package/src/plugins/submenu/table.d.ts +0 -5
  283. package/src/plugins/submenu/table.js +0 -1431
  284. package/src/plugins/submenu/template.d.ts +0 -5
  285. package/src/plugins/submenu/template.js +0 -72
  286. package/src/plugins/submenu/textStyle.d.ts +0 -5
  287. package/src/plugins/submenu/textStyle.js +0 -167
  288. package/src/suneditor.d.ts +0 -9
  289. package/src/suneditor_build.js +0 -18
  290. /package/{src/plugins/dialog → typings}/mention.d.ts +0 -0
@@ -0,0 +1,260 @@
1
+ /**
2
+ * @fileoverview Menu class
3
+ */
4
+
5
+ import CoreInjector from '../../editorInjector/_core';
6
+ import { domUtils, converter } from '../../helper';
7
+
8
+ const Menu = function (editor) {
9
+ CoreInjector.call(this, editor);
10
+
11
+ // members--
12
+ this.targetMap = {};
13
+ this.index = -1;
14
+ this.menus = [];
15
+ // dropdown
16
+ this.currentDropdown = null;
17
+ this.currentDropdownActiveButton = null;
18
+ this.currentDropdownName = '';
19
+ this.currentDropdownType = '';
20
+ // container
21
+ this.currentContainer = null;
22
+ this.currentContainerActiveButton = null;
23
+ // event
24
+ this._dropdownCommands = [];
25
+ this.__globalEventHandler = {
26
+ mousedown: OnMouseDown_dropdown.bind(this),
27
+ containerDown: this.containerOff.bind(this),
28
+ keydown: OnKeyDown_dropdown.bind(this),
29
+ mousemove: OnMousemove_dropdown.bind(this),
30
+ mouseout: OnMouseout_dropdown.bind(this)
31
+ };
32
+ this._bindClose_dropdown_mouse = null;
33
+ this._bindClose_dropdown_key = null;
34
+ this._bindClose_cons_mouse = null;
35
+ this.currentDropdownPlugin = null;
36
+ };
37
+
38
+ Menu.prototype = {
39
+ /**
40
+ * @description Method for managing dropdown element.
41
+ * You must add the "dropdown" element using the this method at custom plugin.
42
+ * @param {{key: string, type: string}} classObj Class object
43
+ * @param {Element} menu Dropdown element
44
+ */
45
+ initDropdownTarget({ key, type }, menu) {
46
+ if (key) {
47
+ if (!/free$/.test(type)) {
48
+ menu.setAttribute('data-key', key);
49
+ this._dropdownCommands.push(key);
50
+ }
51
+ this.context.get('menuTray').appendChild(menu);
52
+ this.targetMap[key] = menu;
53
+ } else {
54
+ throw Error("[SUNEDITOR.init.fail] The plugin's key is not added.");
55
+ }
56
+ },
57
+
58
+ /**
59
+ * @description On dropdown
60
+ * @param {Element} button Dropdown's button element to call
61
+ */
62
+ dropdownOn(button) {
63
+ this.__removeGlobalEvent();
64
+ const moreBtn = this._checkMoreLayer(button);
65
+ if (moreBtn) {
66
+ const target = domUtils.getParentElement(moreBtn, '.se-btn-tray').querySelector('[data-command="' + moreBtn.getAttribute('data-ref') + '"]');
67
+ if (target) {
68
+ this.editor.runFromTarget(target);
69
+ this.dropdownOn(button);
70
+ return;
71
+ }
72
+ }
73
+
74
+ const dropdownName = (this.currentDropdownName = button.getAttribute('data-command'));
75
+ this.currentDropdownType = button.getAttribute('data-type');
76
+ const menu = (this.currentDropdown = this.targetMap[dropdownName]);
77
+ this.currentDropdownActiveButton = button;
78
+ this._setMenuPosition(button, menu);
79
+
80
+ this._bindClose_dropdown_mouse = this.eventManager.addGlobalEvent('mousedown', this.__globalEventHandler.mousedown, false);
81
+ if (this._dropdownCommands.includes(dropdownName)) {
82
+ this.menus = converter.nodeListToArray(menu.querySelectorAll('.se-toolbar-btn[data-command]'));
83
+ if (this.menus.length > 0) {
84
+ this._bindClose_dropdown_key = this.eventManager.addGlobalEvent('keydown', this.__globalEventHandler.keydown, false);
85
+ menu.addEventListener('mousemove', this.__globalEventHandler.mousemove, false);
86
+ menu.addEventListener('mouseout', this.__globalEventHandler.mouseout, false);
87
+ }
88
+ }
89
+
90
+ this.currentDropdownPlugin = this.plugins[dropdownName];
91
+ if (typeof this.currentDropdownPlugin?.on === 'function') this.currentDropdownPlugin.on(button);
92
+ this.editor._antiBlur = true;
93
+ },
94
+
95
+ /**
96
+ * @description Off dropdown
97
+ */
98
+ dropdownOff() {
99
+ this.__removeGlobalEvent();
100
+ this.index = -1;
101
+ this.menus = [];
102
+
103
+ if (this.currentDropdown) {
104
+ this.currentDropdownName = '';
105
+ this.currentDropdownType = '';
106
+ this.currentDropdown.style.display = 'none';
107
+ this.currentDropdown = null;
108
+ if (this.currentDropdownActiveButton) {
109
+ domUtils.removeClass(this.currentDropdownActiveButton.parentElement.children, 'on');
110
+ }
111
+ this.currentDropdownActiveButton = null;
112
+ this.editor._notHideToolbar = false;
113
+ }
114
+
115
+ this.editor._antiBlur = false;
116
+
117
+ if (typeof this.currentDropdownPlugin?.off === 'function') this.currentDropdownPlugin.off();
118
+ this.currentDropdownPlugin = null;
119
+ },
120
+
121
+ /**
122
+ * @description On menu container
123
+ * @param {Element} button Container's button element to call
124
+ */
125
+ containerOn(button) {
126
+ this.__removeGlobalEvent();
127
+
128
+ const containerName = (this._containerName = button.getAttribute('data-command'));
129
+ this.currentContainerActiveButton = button;
130
+ this._setMenuPosition(button, (this.currentContainer = this.targetMap[containerName]));
131
+
132
+ this._bindClose_cons_mouse = this.eventManager.addGlobalEvent('mousedown', this.__globalEventHandler.containerDown, false);
133
+
134
+ if (this.plugins[containerName].on) this.plugins[containerName].on(button);
135
+ this.editor._antiBlur = true;
136
+ },
137
+
138
+ /**
139
+ * @description Off menu container
140
+ */
141
+ containerOff() {
142
+ this.__removeGlobalEvent();
143
+
144
+ if (this.currentContainer) {
145
+ this._containerName = '';
146
+ this.currentContainer.style.display = 'none';
147
+ this.currentContainer = null;
148
+ domUtils.removeClass(this.currentContainerActiveButton, 'on');
149
+ this.currentContainerActiveButton = null;
150
+ this.editor._notHideToolbar = false;
151
+ }
152
+
153
+ this.editor._antiBlur = false;
154
+ },
155
+
156
+ /**
157
+ * @description Set the menu position. (dropdown, container)
158
+ * @param {*} element Button element
159
+ * @param {*} menu Menu element
160
+ * @private
161
+ */
162
+ _setMenuPosition(element, menu) {
163
+ menu.style.visibility = 'hidden';
164
+ menu.style.display = 'block';
165
+ menu.style.height = '';
166
+ domUtils.addClass(element.parentElement.children, 'on');
167
+
168
+ this.offset.setRelPosition(menu, this.carrierWrapper, element.parentElement, domUtils.getParentElement(element, '.se-toolbar'), false);
169
+
170
+ menu.style.visibility = '';
171
+ },
172
+
173
+ _checkMoreLayer(element) {
174
+ const more = domUtils.getParentElement(element, '.se-more-layer');
175
+ if (more && more.style.display !== 'block') {
176
+ return more.getAttribute('data-ref') ? more : null;
177
+ } else {
178
+ return null;
179
+ }
180
+ },
181
+
182
+ _moveItem(num) {
183
+ domUtils.removeClass(this.currentDropdown, 'se-select-menu-mouse-move');
184
+ domUtils.addClass(this.currentDropdown, 'se-select-menu-key-action');
185
+ num = this.index + num;
186
+ const len = this.menus.length;
187
+ const selectIndex = (this.index = num >= len ? 0 : num < 0 ? len - 1 : num);
188
+
189
+ for (let i = 0; i < len; i++) {
190
+ if (i === selectIndex) {
191
+ domUtils.addClass(this.menus[i], 'on');
192
+ } else {
193
+ domUtils.removeClass(this.menus[i], 'on');
194
+ }
195
+ }
196
+ },
197
+
198
+ __removeGlobalEvent() {
199
+ if (this._bindClose_dropdown_mouse) this._bindClose_dropdown_mouse = this.eventManager.removeGlobalEvent(this._bindClose_dropdown_mouse);
200
+ if (this._bindClose_cons_mouse) this._bindClose_cons_mouse = this.eventManager.removeGlobalEvent(this._bindClose_cons_mouse);
201
+ if (this._bindClose_dropdown_key) {
202
+ this._bindClose_dropdown_key = this.eventManager.removeGlobalEvent(this._bindClose_dropdown_key);
203
+ domUtils.removeClass(this.menus, 'on');
204
+ domUtils.removeClass(this.currentDropdown, 'se-select-menu-key-action|se-select-menu-mouse-move');
205
+ this.currentDropdown.removeEventListener('mousemove', this.__globalEventHandler.mousemove, false);
206
+ this.currentDropdown.removeEventListener('mouseout', this.__globalEventHandler.mouseout, false);
207
+ }
208
+ },
209
+
210
+ constructor: Menu
211
+ };
212
+
213
+ function OnMouseDown_dropdown(e) {
214
+ if (domUtils.getParentElement(e.target, '.se-dropdown')) return;
215
+ this.dropdownOff();
216
+ }
217
+
218
+ function OnMouseout_dropdown() {
219
+ this.index = -1;
220
+ }
221
+
222
+ function OnKeyDown_dropdown(e) {
223
+ const keyCode = e.keyCode;
224
+ switch (keyCode) {
225
+ case 38: // up
226
+ e.preventDefault();
227
+ e.stopPropagation();
228
+ this._moveItem(-1);
229
+ break;
230
+ case 40: // down
231
+ e.preventDefault();
232
+ e.stopPropagation();
233
+ this._moveItem(1);
234
+ break;
235
+ case 13:
236
+ case /* enter, space */ 32: {
237
+ if (this.index < 0) break;
238
+
239
+ const target = this.menus[this.index];
240
+ if (!target || typeof this.plugins[this.currentDropdownName].action !== 'function') return;
241
+
242
+ e.preventDefault();
243
+ e.stopPropagation();
244
+ this.plugins[this.currentDropdownName].action(target);
245
+ this.dropdownOff();
246
+ break;
247
+ }
248
+ }
249
+ }
250
+
251
+ function OnMousemove_dropdown(e) {
252
+ domUtils.addClass(this.currentDropdown, 'se-select-menu-mouse-move');
253
+ domUtils.removeClass(this.currentDropdown, 'se-select-menu-key-action');
254
+
255
+ const index = this.menus.indexOf(e.target);
256
+ if (index === -1) return;
257
+ this.index = index * 1;
258
+ }
259
+
260
+ export default Menu;
@@ -0,0 +1,379 @@
1
+ /**
2
+ * @fileoverview Node util class
3
+ */
4
+
5
+ import CoreInjector from '../../editorInjector/_core';
6
+ import { domUtils, unicode, env, numbers } from '../../helper';
7
+
8
+ const NodeTransform = function (editor) {
9
+ CoreInjector.call(this, editor);
10
+ };
11
+
12
+ NodeTransform.prototype = {
13
+ /**
14
+ * @description Split all tags based on "baseNode"
15
+ * Returns the last element of the splited tag.
16
+ * @param {Node} baseNode Element or text node on which to base
17
+ * @param {Number|Node|null} offset Text offset of "baseNode" (Only valid when "baseNode" is a text node)
18
+ * @param {number} depth The nesting depth of the element being split. (default: 0)
19
+ * @returns {Element}
20
+ */
21
+ split(baseNode, offset, depth) {
22
+ if (domUtils.isWysiwygFrame(baseNode) || this.component.is(baseNode) || !baseNode) return baseNode;
23
+
24
+ if (offset && !numbers.is(offset)) {
25
+ const children = baseNode.childNodes;
26
+ let index = domUtils.getPositionIndex(offset);
27
+ const prev = baseNode.cloneNode(false);
28
+ const next = baseNode.cloneNode(false);
29
+ for (let i = 0, len = children.length; i < len; i++) {
30
+ if (i < index) prev.appendChild(children[i]);
31
+ else if (i > index) next.appendChild(children[i]);
32
+ else continue;
33
+ i--;
34
+ len--;
35
+ index--;
36
+ }
37
+
38
+ if (prev.childNodes.length > 0) baseNode.parentNode.insertBefore(prev, baseNode);
39
+ if (next.childNodes.length > 0) baseNode.parentNode.insertBefore(next, baseNode.nextElementSibling);
40
+
41
+ return baseNode;
42
+ }
43
+
44
+ const bp = baseNode.parentNode;
45
+ let index = 0;
46
+ let suffixIndex = 1;
47
+ let next = true;
48
+ let newEl, children, temp;
49
+ if (!depth || depth < 0) depth = 0;
50
+
51
+ if (baseNode.nodeType === 3) {
52
+ index = domUtils.getPositionIndex(baseNode);
53
+ if (offset >= 0 && baseNode.length !== offset) {
54
+ baseNode.splitText(offset);
55
+ const after = domUtils.getNodeFromPath([index + 1], bp);
56
+ if (domUtils.isZeroWith(after)) after.data = unicode.zeroWidthSpace;
57
+ }
58
+ } else if (baseNode.nodeType === 1) {
59
+ if (offset === 0) {
60
+ while (baseNode.firstChild) {
61
+ baseNode = baseNode.firstChild;
62
+ }
63
+ if (baseNode.nodeType === 3) {
64
+ const after = domUtils.createTextNode(unicode.zeroWidthSpace);
65
+ baseNode.parentNode.insertBefore(after, baseNode);
66
+ baseNode = after;
67
+ }
68
+ }
69
+
70
+ if (!baseNode.previousSibling) {
71
+ if (domUtils.getNodeDepth(baseNode) === depth) next = false;
72
+ } else {
73
+ baseNode = baseNode.previousSibling;
74
+ }
75
+ }
76
+
77
+ if (baseNode.nodeType === 1) suffixIndex = 0;
78
+ let depthEl = baseNode;
79
+ while (domUtils.getNodeDepth(depthEl) > depth) {
80
+ index = domUtils.getPositionIndex(depthEl) + suffixIndex;
81
+ depthEl = depthEl.parentNode;
82
+
83
+ temp = newEl;
84
+ newEl = depthEl.cloneNode(false);
85
+ children = depthEl.childNodes;
86
+
87
+ if (temp) {
88
+ if (domUtils.isListCell(newEl) && domUtils.isList(temp) && temp.firstElementChild) {
89
+ newEl.innerHTML = temp.firstElementChild.innerHTML;
90
+ domUtils.removeItem(temp.firstElementChild);
91
+ if (temp.children.length > 0) newEl.appendChild(temp);
92
+ } else {
93
+ newEl.appendChild(temp);
94
+ }
95
+ }
96
+
97
+ while (children[index]) {
98
+ newEl.appendChild(children[index]);
99
+ }
100
+ }
101
+
102
+ if (depthEl.childNodes.length <= 1 && (!depthEl.firstChild || depthEl.firstChild.textContent.length === 0)) depthEl.innerHTML = '<br>';
103
+
104
+ const pElement = depthEl.parentNode;
105
+ if (next) depthEl = depthEl.nextSibling;
106
+ if (!newEl) return depthEl;
107
+
108
+ this.mergeSameTags(newEl, null, false);
109
+ this.mergeNestedTags(newEl, domUtils.isList);
110
+
111
+ if (newEl.childNodes.length > 0) pElement.insertBefore(newEl, depthEl);
112
+ else newEl = depthEl;
113
+
114
+ if (domUtils.isListCell(newEl) && newEl.children && domUtils.isList(newEl.children[0])) {
115
+ newEl.insertBefore(domUtils.createElement('BR'), newEl.children[0]);
116
+ }
117
+
118
+ if (bp.childNodes.length === 0) domUtils.removeItem(bp);
119
+
120
+ return newEl;
121
+ },
122
+
123
+ /**
124
+ * @description Use with "npdePath (domUtils.getNodePath)" to merge the same attributes and tags if they are present and modify the nodepath.
125
+ * If "offset" has been changed, it will return as much "offset" as it has been modified.
126
+ * An array containing change offsets is returned in the order of the "nodePathArray" array.
127
+ * @param {Element} element Element
128
+ * @param {Array|null} nodePathArray Array of NodePath object ([domUtils.getNodePath(), ..])
129
+ * @param {boolean} onlyText If true, non-text nodes like 'span', 'strong'.. are ignored.
130
+ * @returns {Array} [offset, ..]
131
+ */
132
+ mergeSameTags(element, nodePathArray, onlyText) {
133
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
134
+ const inst = this;
135
+ const nodePathLen = nodePathArray ? nodePathArray.length : 0;
136
+ let offsets = null;
137
+
138
+ if (nodePathLen) {
139
+ offsets = Array.apply(null, new Array(nodePathLen)).map(Number.prototype.valueOf, 0);
140
+ }
141
+
142
+ (function recursionFunc(current, depth, depthIndex) {
143
+ const children = current.childNodes;
144
+
145
+ for (let i = 0, len = children.length, child, next; i < len; i++) {
146
+ child = children[i];
147
+ next = children[i + 1];
148
+ if (!child) break;
149
+ if ((onlyText && inst.format._isIgnoreNodeChange(child)) || (!onlyText && (domUtils.isTableElements(child) || domUtils.isListCell(child) || (inst.format.isLine(child) && !inst.format.isBrLine(child))))) {
150
+ if (domUtils.isTableElements(child) || domUtils.isListCell(child)) {
151
+ recursionFunc(child, depth + 1, i);
152
+ }
153
+ continue;
154
+ }
155
+ if (len === 1 && current.nodeName === child.nodeName && current.parentNode) {
156
+ // update nodePath
157
+ if (nodePathLen) {
158
+ let path, c, p, cDepth, spliceDepth;
159
+ for (let n = 0; n < nodePathLen; n++) {
160
+ path = nodePathArray[n];
161
+ if (path && path[depth] === i) {
162
+ c = child;
163
+ p = current;
164
+ cDepth = depth;
165
+ spliceDepth = true;
166
+ while (cDepth >= 0) {
167
+ if (domUtils.getArrayIndex(p.childNodes, c) !== path[cDepth]) {
168
+ spliceDepth = false;
169
+ break;
170
+ }
171
+ c = child.parentNode;
172
+ p = c.parentNode;
173
+ cDepth--;
174
+ }
175
+ if (spliceDepth) {
176
+ path.splice(depth, 1);
177
+ path[depth] = i;
178
+ }
179
+ }
180
+ }
181
+ }
182
+
183
+ // merge tag
184
+ domUtils.copyTagAttributes(child, current);
185
+ current.parentNode.insertBefore(child, current);
186
+ domUtils.removeItem(current);
187
+ }
188
+ if (!next) {
189
+ if (child.nodeType === 1) recursionFunc(child, depth + 1, i);
190
+ break;
191
+ }
192
+
193
+ if (child.nodeName === next.nodeName && domUtils.isSameAttributes(child, next) && child.href === next.href) {
194
+ const childs = child.childNodes;
195
+ let childLength = 0;
196
+ for (let n = 0, nLen = childs.length; n < nLen; n++) {
197
+ if (childs[n].textContent.length > 0) childLength++;
198
+ }
199
+
200
+ const l = child.lastChild;
201
+ const r = next.firstChild;
202
+ let addOffset = 0;
203
+ if (l && r) {
204
+ const textOffset = l.nodeType === 3 && r.nodeType === 3;
205
+ addOffset = l.textContent.length;
206
+ let tempL = l.previousSibling;
207
+ while (tempL && tempL.nodeType === 3) {
208
+ addOffset += tempL.textContent.length;
209
+ tempL = tempL.previousSibling;
210
+ }
211
+
212
+ if (childLength > 0 && l.nodeType === 3 && r.nodeType === 3 && (l.textContent.length > 0 || r.textContent.length > 0)) childLength--;
213
+
214
+ if (nodePathLen) {
215
+ let path = null;
216
+ for (let n = 0; n < nodePathLen; n++) {
217
+ path = nodePathArray[n];
218
+ if (path && path[depth] > i) {
219
+ if (depth > 0 && path[depth - 1] !== depthIndex) continue;
220
+
221
+ path[depth] -= 1;
222
+ if (path[depth + 1] >= 0 && path[depth] === i) {
223
+ path[depth + 1] += childLength;
224
+ if (textOffset) {
225
+ if (l && l.nodeType === 3 && r && r.nodeType === 3) {
226
+ offsets[n] += addOffset;
227
+ }
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+
235
+ if (child.nodeType === 3) {
236
+ addOffset = child.textContent.length;
237
+ child.textContent += next.textContent;
238
+ if (nodePathLen) {
239
+ let path = null;
240
+ for (let n = 0; n < nodePathLen; n++) {
241
+ path = nodePathArray[n];
242
+ if (path && path[depth] > i) {
243
+ if (depth > 0 && path[depth - 1] !== depthIndex) continue;
244
+
245
+ path[depth] -= 1;
246
+ if (path[depth + 1] >= 0 && path[depth] === i) {
247
+ path[depth + 1] += childLength;
248
+ offsets[n] += addOffset;
249
+ }
250
+ }
251
+ }
252
+ }
253
+ } else {
254
+ child.innerHTML += next.innerHTML;
255
+ }
256
+
257
+ domUtils.removeItem(next);
258
+ i--;
259
+ } else if (child.nodeType === 1) {
260
+ recursionFunc(child, depth + 1, i);
261
+ }
262
+ }
263
+ })(element, 0, 0);
264
+
265
+ return offsets;
266
+ },
267
+
268
+ /**
269
+ * @description Remove nested tags without other child nodes.
270
+ * @param {Element} element Element object
271
+ * @param {Function|String|null} validation Validation function / String("tag1|tag2..") / If null, all tags are applicable.
272
+ */
273
+ mergeNestedTags(element, validation) {
274
+ if (typeof validation === 'string') {
275
+ validation = function (current) {
276
+ return this.test(current.tagName);
277
+ }.bind(new RegExp(`^(${validation ? validation : '.+'})$`, 'i'));
278
+ } else if (typeof validation !== 'function') {
279
+ validation = () => true;
280
+ }
281
+
282
+ (function recursionFunc(current) {
283
+ let children = current.children;
284
+ if (children.length === 1 && children[0].nodeName === current.nodeName && validation(current)) {
285
+ const temp = children[0];
286
+ children = temp.children;
287
+ while (children[0]) {
288
+ current.appendChild(children[0]);
289
+ }
290
+ current.removeChild(temp);
291
+ }
292
+
293
+ for (let i = 0, len = current.children.length; i < len; i++) {
294
+ recursionFunc(current.children[i]);
295
+ }
296
+ })(element);
297
+ },
298
+
299
+ /**
300
+ * @description Delete itself and all parent nodes that match the condition.
301
+ * Returns an {sc: previousSibling, ec: nextSibling}(the deleted node reference) or null.
302
+ * @param {Node} item Node to be remove
303
+ * @param {Function|null} validation Validation function. default(Deleted if it only have breakLine and blanks)
304
+ * @param {Element|null} stopParent Stop when the parent node reaches stopParent
305
+ * @returns {Object|null} {sc: previousSibling, ec: nextSibling}
306
+ */
307
+ removeAllParents(item, validation, stopParent) {
308
+ if (!item) return null;
309
+ let cc = null;
310
+ if (!validation) {
311
+ validation = (current) => {
312
+ if (current === stopParent || this.component.is(current)) return false;
313
+ const text = current.textContent.trim();
314
+ return text.length === 0 || /^(\n|\u200B)+$/.test(text);
315
+ };
316
+ }
317
+
318
+ (function recursionFunc(element) {
319
+ if (!domUtils.isWysiwygFrame(element)) {
320
+ const parent = element.parentNode;
321
+ if (parent && validation(element)) {
322
+ cc = {
323
+ sc: element.previousElementSibling,
324
+ ec: element.nextElementSibling
325
+ };
326
+ domUtils.removeItem(element);
327
+ recursionFunc(parent);
328
+ }
329
+ }
330
+ })(item);
331
+
332
+ return cc;
333
+ },
334
+
335
+ /**
336
+ * @description Delete a empty child node of argument element
337
+ * @param {Element} element Element node
338
+ * @param {Node|null} notRemoveNode Do not remove node
339
+ * @param {boolean} forceDelete When all child nodes are deleted, the parent node is also deleted.
340
+ */
341
+ removeEmptyNode(element, notRemoveNode, forceDelete) {
342
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
343
+ const inst = this;
344
+
345
+ if (notRemoveNode) {
346
+ notRemoveNode = domUtils.getParentElement(notRemoveNode, (current) => element === current.parentElement);
347
+ }
348
+
349
+ (function recursionFunc(current) {
350
+ if (inst.format._notTextNode(current) || current === notRemoveNode || domUtils.isNonEditable(current)) return 0;
351
+ if (current !== element && domUtils.isZeroWith(current.textContent) && (!current.firstChild || !domUtils.isBreak(current.firstChild)) && !current.querySelector(env._allowedEmptyNodeList)) {
352
+ if (current.parentNode) {
353
+ current.parentNode.removeChild(current);
354
+ return -1;
355
+ }
356
+ } else {
357
+ const children = current.children;
358
+ for (let i = 0, len = children.length, r = 0; i < len; i++) {
359
+ if (!children[i + r] || inst.component.is(children[i + r])) continue;
360
+ r += recursionFunc(children[i + r]);
361
+ }
362
+ }
363
+
364
+ return 0;
365
+ })(element);
366
+
367
+ if (element.childNodes.length === 0) {
368
+ if (forceDelete) {
369
+ domUtils.removeItem(element);
370
+ } else {
371
+ element.innerHTML = '<br>';
372
+ }
373
+ }
374
+ },
375
+
376
+ constructor: NodeTransform
377
+ };
378
+
379
+ export default NodeTransform;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @fileoverview Menu class
3
+ */
4
+
5
+ import Modal from '../../modules/Modal';
6
+ import { domUtils } from '../../helper';
7
+
8
+ const Notice = function (editor) {
9
+ const modalEl = CreateHTML(editor);
10
+
11
+ // members
12
+ this.editor = editor;
13
+ this.modal = new Modal(this, modalEl);
14
+ this.message = modalEl.querySelector('span');
15
+ };
16
+
17
+ Notice.prototype = {
18
+ /**
19
+ * @description Open the notice panel
20
+ * @param {string} text Notice message
21
+ */
22
+ open(text) {
23
+ this.message.textContent = text;
24
+ this.modal.open();
25
+ },
26
+
27
+ /**
28
+ * @description Close the notice panel
29
+ */
30
+ close() {
31
+ this.modal.close();
32
+ },
33
+
34
+ constructor: Notice
35
+ };
36
+
37
+ function CreateHTML({ lang, icons }) {
38
+ const html = '<div><button class="close" data-command="close" title="' + lang.close + '">' + icons.cancel + '</button></div><div><span></span></div>';
39
+ return domUtils.createElement('DIV', { class: 'se-notice' }, html);
40
+ }
41
+
42
+ export default Notice;