suneditor 3.0.0-alpha.9 → 3.0.0-beta.2

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 (315) hide show
  1. package/CONTRIBUTING.md +170 -22
  2. package/{LICENSE.txt → LICENSE} +9 -9
  3. package/README.md +168 -30
  4. package/dist/suneditor.min.css +1 -1
  5. package/dist/suneditor.min.js +1 -1
  6. package/package.json +47 -21
  7. package/src/assets/design/color.css +121 -0
  8. package/src/assets/design/index.css +3 -0
  9. package/src/assets/design/size.css +35 -0
  10. package/src/assets/design/typography.css +37 -0
  11. package/src/assets/icons/defaultIcons.js +232 -0
  12. package/src/assets/suneditor-contents.css +181 -46
  13. package/src/assets/suneditor.css +1403 -650
  14. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  15. package/src/core/base/eventHandlers/handler_ww_clipboard.js +23 -4
  16. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +49 -10
  17. package/src/core/base/eventHandlers/handler_ww_key_input.js +422 -224
  18. package/src/core/base/eventHandlers/handler_ww_mouse.js +83 -36
  19. package/src/core/base/eventManager.js +520 -179
  20. package/src/core/base/history.js +95 -41
  21. package/src/core/class/char.js +26 -11
  22. package/src/core/class/component.js +345 -137
  23. package/src/core/class/format.js +683 -519
  24. package/src/core/class/html.js +485 -305
  25. package/src/core/class/menu.js +133 -47
  26. package/src/core/class/nodeTransform.js +90 -71
  27. package/src/core/class/offset.js +408 -92
  28. package/src/core/class/selection.js +216 -106
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +422 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +496 -389
  34. package/src/core/section/actives.js +123 -27
  35. package/src/core/section/constructor.js +615 -206
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/events.js +622 -0
  42. package/src/helper/clipboard.js +59 -0
  43. package/src/helper/converter.js +202 -26
  44. package/src/helper/dom/domCheck.js +304 -0
  45. package/src/helper/dom/domQuery.js +669 -0
  46. package/src/helper/dom/domUtils.js +557 -0
  47. package/src/helper/dom/index.js +12 -0
  48. package/src/helper/env.js +46 -56
  49. package/src/helper/index.js +10 -4
  50. package/src/helper/keyCodeMap.js +183 -0
  51. package/src/helper/numbers.js +12 -8
  52. package/src/helper/unicode.js +9 -5
  53. package/src/langs/ckb.js +74 -4
  54. package/src/langs/cs.js +72 -2
  55. package/src/langs/da.js +73 -3
  56. package/src/langs/de.js +73 -4
  57. package/src/langs/en.js +23 -3
  58. package/src/langs/es.js +73 -4
  59. package/src/langs/fa.js +75 -3
  60. package/src/langs/fr.js +73 -3
  61. package/src/langs/he.js +73 -4
  62. package/src/langs/hu.js +230 -0
  63. package/src/langs/index.js +7 -3
  64. package/src/langs/it.js +70 -1
  65. package/src/langs/ja.js +72 -4
  66. package/src/langs/km.js +230 -0
  67. package/src/langs/ko.js +22 -2
  68. package/src/langs/lv.js +74 -5
  69. package/src/langs/nl.js +73 -4
  70. package/src/langs/pl.js +73 -4
  71. package/src/langs/pt_br.js +70 -1
  72. package/src/langs/ro.js +74 -5
  73. package/src/langs/ru.js +73 -4
  74. package/src/langs/se.js +73 -4
  75. package/src/langs/tr.js +73 -1
  76. package/src/langs/{ua.js → uk.js} +75 -6
  77. package/src/langs/ur.js +77 -8
  78. package/src/langs/zh_cn.js +74 -5
  79. package/src/modules/ApiManager.js +77 -54
  80. package/src/modules/Browser.js +667 -0
  81. package/src/modules/ColorPicker.js +162 -102
  82. package/src/modules/Controller.js +273 -142
  83. package/src/modules/Figure.js +925 -484
  84. package/src/modules/FileManager.js +121 -69
  85. package/src/modules/HueSlider.js +113 -61
  86. package/src/modules/Modal.js +291 -122
  87. package/src/modules/ModalAnchorEditor.js +383 -234
  88. package/src/modules/SelectMenu.js +270 -168
  89. package/src/modules/_DragHandle.js +2 -1
  90. package/src/modules/index.js +3 -3
  91. package/src/plugins/browser/audioGallery.js +83 -0
  92. package/src/plugins/browser/fileBrowser.js +103 -0
  93. package/src/plugins/browser/fileGallery.js +83 -0
  94. package/src/plugins/browser/imageGallery.js +81 -0
  95. package/src/plugins/browser/videoGallery.js +103 -0
  96. package/src/plugins/command/blockquote.js +40 -27
  97. package/src/plugins/command/exportPDF.js +134 -0
  98. package/src/plugins/command/fileUpload.js +229 -162
  99. package/src/plugins/command/list_bulleted.js +83 -47
  100. package/src/plugins/command/list_numbered.js +83 -47
  101. package/src/plugins/dropdown/align.js +66 -54
  102. package/src/plugins/dropdown/backgroundColor.js +63 -49
  103. package/src/plugins/dropdown/font.js +71 -47
  104. package/src/plugins/dropdown/fontColor.js +63 -48
  105. package/src/plugins/dropdown/formatBlock.js +70 -33
  106. package/src/plugins/dropdown/hr.js +92 -51
  107. package/src/plugins/dropdown/layout.js +37 -26
  108. package/src/plugins/dropdown/lineHeight.js +54 -38
  109. package/src/plugins/dropdown/list.js +60 -45
  110. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  111. package/src/plugins/dropdown/table.js +2003 -813
  112. package/src/plugins/dropdown/template.js +38 -26
  113. package/src/plugins/dropdown/textStyle.js +43 -31
  114. package/src/plugins/field/mention.js +147 -86
  115. package/src/plugins/index.js +32 -6
  116. package/src/plugins/input/fontSize.js +161 -108
  117. package/src/plugins/input/pageNavigator.js +70 -0
  118. package/src/plugins/modal/audio.js +358 -173
  119. package/src/plugins/modal/drawing.js +531 -0
  120. package/src/plugins/modal/embed.js +886 -0
  121. package/src/plugins/modal/image.js +674 -362
  122. package/src/plugins/modal/link.js +100 -71
  123. package/src/plugins/modal/math.js +367 -167
  124. package/src/plugins/modal/video.js +691 -335
  125. package/src/plugins/popup/anchor.js +222 -0
  126. package/src/suneditor.js +50 -13
  127. package/src/themes/dark.css +122 -0
  128. package/src/typedef.js +130 -0
  129. package/types/assets/icons/defaultIcons.d.ts +153 -0
  130. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  131. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  132. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  133. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  134. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  135. package/types/core/base/eventManager.d.ts +385 -0
  136. package/types/core/base/history.d.ts +81 -0
  137. package/types/core/class/char.d.ts +60 -0
  138. package/types/core/class/component.d.ts +212 -0
  139. package/types/core/class/format.d.ts +616 -0
  140. package/types/core/class/html.d.ts +422 -0
  141. package/types/core/class/menu.d.ts +126 -0
  142. package/types/core/class/nodeTransform.d.ts +93 -0
  143. package/types/core/class/offset.d.ts +522 -0
  144. package/types/core/class/selection.d.ts +188 -0
  145. package/types/core/class/shortcuts.d.ts +142 -0
  146. package/types/core/class/toolbar.d.ts +189 -0
  147. package/types/core/class/ui.d.ts +164 -0
  148. package/types/core/class/viewer.d.ts +140 -0
  149. package/types/core/editor.d.ts +610 -0
  150. package/types/core/section/actives.d.ts +46 -0
  151. package/types/core/section/constructor.d.ts +777 -0
  152. package/types/core/section/context.d.ts +45 -0
  153. package/types/core/section/documentType.d.ts +178 -0
  154. package/types/editorInjector/_classes.d.ts +41 -0
  155. package/types/editorInjector/_core.d.ts +92 -0
  156. package/types/editorInjector/index.d.ts +71 -0
  157. package/types/events.d.ts +273 -0
  158. package/types/helper/clipboard.d.ts +12 -0
  159. package/types/helper/converter.d.ts +197 -0
  160. package/types/helper/dom/domCheck.d.ts +189 -0
  161. package/types/helper/dom/domQuery.d.ts +223 -0
  162. package/types/helper/dom/domUtils.d.ts +226 -0
  163. package/types/helper/dom/index.d.ts +9 -0
  164. package/types/helper/env.d.ts +132 -0
  165. package/types/helper/index.d.ts +174 -0
  166. package/types/helper/keyCodeMap.d.ts +110 -0
  167. package/types/helper/numbers.d.ts +46 -0
  168. package/types/helper/unicode.d.ts +28 -0
  169. package/types/index.d.ts +120 -0
  170. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +173 -103
  171. package/types/langs/ckb.d.ts +3 -0
  172. package/types/langs/cs.d.ts +3 -0
  173. package/types/langs/da.d.ts +3 -0
  174. package/types/langs/de.d.ts +3 -0
  175. package/types/langs/en.d.ts +3 -0
  176. package/types/langs/es.d.ts +3 -0
  177. package/types/langs/fa.d.ts +3 -0
  178. package/types/langs/fr.d.ts +3 -0
  179. package/types/langs/he.d.ts +3 -0
  180. package/types/langs/hu.d.ts +3 -0
  181. package/types/langs/index.d.ts +54 -0
  182. package/types/langs/it.d.ts +3 -0
  183. package/types/langs/ja.d.ts +3 -0
  184. package/types/langs/km.d.ts +3 -0
  185. package/types/langs/ko.d.ts +3 -0
  186. package/types/langs/lv.d.ts +3 -0
  187. package/types/langs/nl.d.ts +3 -0
  188. package/types/langs/pl.d.ts +3 -0
  189. package/types/langs/pt_br.d.ts +3 -0
  190. package/types/langs/ro.d.ts +3 -0
  191. package/types/langs/ru.d.ts +3 -0
  192. package/types/langs/se.d.ts +3 -0
  193. package/types/langs/tr.d.ts +3 -0
  194. package/types/langs/uk.d.ts +3 -0
  195. package/types/langs/ur.d.ts +3 -0
  196. package/types/langs/zh_cn.d.ts +3 -0
  197. package/types/modules/ApiManager.d.ts +125 -0
  198. package/types/modules/Browser.d.ts +326 -0
  199. package/types/modules/ColorPicker.d.ts +131 -0
  200. package/types/modules/Controller.d.ts +251 -0
  201. package/types/modules/Figure.d.ts +517 -0
  202. package/types/modules/FileManager.d.ts +202 -0
  203. package/types/modules/HueSlider.d.ts +136 -0
  204. package/types/modules/Modal.d.ts +111 -0
  205. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  206. package/types/modules/SelectMenu.d.ts +194 -0
  207. package/types/modules/_DragHandle.d.ts +7 -0
  208. package/types/modules/index.d.ts +26 -0
  209. package/types/plugins/browser/audioGallery.d.ts +55 -0
  210. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  211. package/types/plugins/browser/fileGallery.d.ts +55 -0
  212. package/types/plugins/browser/imageGallery.d.ts +51 -0
  213. package/types/plugins/browser/videoGallery.d.ts +57 -0
  214. package/types/plugins/command/blockquote.d.ts +28 -0
  215. package/types/plugins/command/exportPDF.d.ts +46 -0
  216. package/types/plugins/command/fileUpload.d.ts +156 -0
  217. package/types/plugins/command/list_bulleted.d.ts +46 -0
  218. package/types/plugins/command/list_numbered.d.ts +46 -0
  219. package/types/plugins/dropdown/align.d.ts +60 -0
  220. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  221. package/types/plugins/dropdown/font.d.ts +54 -0
  222. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  223. package/types/plugins/dropdown/formatBlock.d.ts +54 -0
  224. package/types/plugins/dropdown/hr.d.ts +71 -0
  225. package/types/plugins/dropdown/layout.d.ts +40 -0
  226. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  227. package/types/plugins/dropdown/list.d.ts +39 -0
  228. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  229. package/types/plugins/dropdown/table.d.ts +627 -0
  230. package/types/plugins/dropdown/template.d.ts +40 -0
  231. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  232. package/types/plugins/field/mention.d.ts +102 -0
  233. package/types/plugins/index.d.ts +107 -0
  234. package/types/plugins/input/fontSize.d.ts +170 -0
  235. package/types/plugins/input/pageNavigator.d.ts +28 -0
  236. package/types/plugins/modal/audio.d.ts +269 -0
  237. package/types/plugins/modal/drawing.d.ts +246 -0
  238. package/types/plugins/modal/embed.d.ts +387 -0
  239. package/types/plugins/modal/image.d.ts +451 -0
  240. package/types/plugins/modal/link.d.ts +128 -0
  241. package/types/plugins/modal/math.d.ts +193 -0
  242. package/types/plugins/modal/video.d.ts +485 -0
  243. package/types/plugins/popup/anchor.d.ts +56 -0
  244. package/types/suneditor.d.ts +51 -0
  245. package/types/typedef.d.ts +233 -0
  246. package/.eslintignore +0 -7
  247. package/.eslintrc.json +0 -64
  248. package/src/assets/icons/_default.js +0 -194
  249. package/src/core/base/events.js +0 -320
  250. package/src/core/class/notice.js +0 -42
  251. package/src/helper/domUtils.js +0 -1177
  252. package/src/modules/FileBrowser.js +0 -271
  253. package/src/plugins/command/exportPdf.js +0 -168
  254. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  255. package/src/themes/test.css +0 -61
  256. package/typings/CommandPlugin.d.ts +0 -8
  257. package/typings/DialogPlugin.d.ts +0 -20
  258. package/typings/FileBrowserPlugin.d.ts +0 -30
  259. package/typings/Module.d.ts +0 -15
  260. package/typings/Plugin.d.ts +0 -42
  261. package/typings/SubmenuPlugin.d.ts +0 -8
  262. package/typings/_classes.d.ts +0 -17
  263. package/typings/_colorPicker.d.ts +0 -60
  264. package/typings/_core.d.ts +0 -55
  265. package/typings/align.d.ts +0 -5
  266. package/typings/audio.d.ts +0 -5
  267. package/typings/backgroundColor.d.ts +0 -5
  268. package/typings/blockquote.d.ts +0 -5
  269. package/typings/char.d.ts +0 -39
  270. package/typings/component.d.ts +0 -38
  271. package/typings/context.d.ts +0 -39
  272. package/typings/converter.d.ts +0 -33
  273. package/typings/dialog.d.ts +0 -28
  274. package/typings/domUtils.d.ts +0 -361
  275. package/typings/editor.d.ts +0 -7
  276. package/typings/editor.ts +0 -542
  277. package/typings/env.d.ts +0 -70
  278. package/typings/eventManager.d.ts +0 -37
  279. package/typings/events.d.ts +0 -262
  280. package/typings/fileBrowser.d.ts +0 -42
  281. package/typings/fileManager.d.ts +0 -67
  282. package/typings/font.d.ts +0 -5
  283. package/typings/fontColor.d.ts +0 -5
  284. package/typings/fontSize.d.ts +0 -5
  285. package/typings/format.d.ts +0 -191
  286. package/typings/formatBlock.d.ts +0 -5
  287. package/typings/history.d.ts +0 -48
  288. package/typings/horizontalRule.d.ts +0 -5
  289. package/typings/image.d.ts +0 -5
  290. package/typings/imageGallery.d.ts +0 -5
  291. package/typings/index.d.ts +0 -21
  292. package/typings/index.modules.d.ts +0 -11
  293. package/typings/index.plugins.d.ts +0 -58
  294. package/typings/lineHeight.d.ts +0 -5
  295. package/typings/link.d.ts +0 -5
  296. package/typings/list.d.ts +0 -5
  297. package/typings/math.d.ts +0 -5
  298. package/typings/mediaContainer.d.ts +0 -25
  299. package/typings/mention.d.ts +0 -5
  300. package/typings/node.d.ts +0 -57
  301. package/typings/notice.d.ts +0 -16
  302. package/typings/numbers.d.ts +0 -29
  303. package/typings/offset.d.ts +0 -24
  304. package/typings/options.d.ts +0 -589
  305. package/typings/paragraphStyle.d.ts +0 -5
  306. package/typings/resizing.d.ts +0 -141
  307. package/typings/selection.d.ts +0 -94
  308. package/typings/shortcuts.d.ts +0 -13
  309. package/typings/suneditor.d.ts +0 -9
  310. package/typings/table.d.ts +0 -5
  311. package/typings/template.d.ts +0 -5
  312. package/typings/textStyle.d.ts +0 -5
  313. package/typings/toolbar.d.ts +0 -32
  314. package/typings/unicode.d.ts +0 -25
  315. package/typings/video.d.ts +0 -5
@@ -1,116 +1,146 @@
1
1
  import EditorInjector from '../../editorInjector';
2
- import { CreateTooltipInner } from '../../core/section/constructor';
3
- import { domUtils, env, numbers } from '../../helper';
2
+ import { dom, env, numbers } from '../../helper';
4
3
  import { FileManager, Figure, Controller } from '../../modules';
5
4
 
6
5
  const { NO_EVENT } = env;
7
6
 
8
- const FileUpload = function (editor, pluginOptions) {
9
- EditorInjector.call(this, editor);
10
- // plugin basic properties
11
- this.title = this.lang.fileUpload;
12
- this.icon = 'file_upload';
13
-
14
- if (!pluginOptions.uploadUrl) console.warn('[SUNEDITOR.fileUpload.warn] "fileUpload" plugin must be have "uploadUrl" option.');
15
-
16
- // members
17
- this.uploadUrl = pluginOptions.uploadUrl;
18
- this.uploadHeaders = pluginOptions.uploadHeaders;
19
- this.uploadSizeLimit = /\d+/.test(pluginOptions.uploadSizeLimit) ? numbers.get(pluginOptions.uploadSizeLimit, 0) : null;
20
- this.uploadSingleSizeLimit = /\d+/.test(pluginOptions.uploadSingleSizeLimit) ? numbers.get(pluginOptions.uploadSingleSizeLimit, 0) : null;
21
- this.allowMultiple = !!pluginOptions.allowMultiple;
22
- this.acceptedFormats = typeof pluginOptions.acceptedFormats !== 'string' ? '*' : pluginOptions.acceptedFormats.trim() || '*';
23
- this._acceptedCheck = this.acceptedFormats.split(', ');
24
- this.as = pluginOptions.as || 'box';
25
- this.input = domUtils.createElement('input', { type: 'file', accept: this.acceptedFormats });
26
- if (this.allowMultiple) {
27
- this.input.setAttribute('multiple', 'multiple');
7
+ /**
8
+ * @class
9
+ * @description File upload plugin
10
+ */
11
+ class FileUpload extends EditorInjector {
12
+ static key = 'fileUpload';
13
+ static type = 'command';
14
+ static className = '';
15
+ static options = { eventIndex: 10000 };
16
+ /**
17
+ * @this {FileUpload}
18
+ * @param {HTMLElement} node - The node to check.
19
+ * @returns {HTMLElement|null} Returns a node if the node is a valid component.
20
+ */
21
+ static component(node) {
22
+ return dom.check.isAnchor(node) && node.hasAttribute('data-se-file-download') ? node : null;
28
23
  }
29
- this._element = null;
30
-
31
- // figure
32
- const customItems = {
33
- 'custom-download': {
34
- command: 'download',
35
- title: this.lang.download,
36
- icon: 'download',
37
- action: (target) => {
38
- const url = target.getAttribute('href');
39
- if (url) domUtils.createElement('A', { href: url }, null).click();
40
- }
41
- },
42
- 'custom-as': {
43
- command: 'as',
44
- value: 'link', // 'block' or 'link'
45
- title: this.lang.asLink,
46
- icon: 'reduction',
47
- action: (target, value) => {
48
- this.convertFormat(target, value);
24
+
25
+ /**
26
+ * @constructor
27
+ * @param {__se__EditorCore} editor - The root editor instance
28
+ * @param {Object} pluginOptions - plugin options
29
+ * @param {string} pluginOptions.uploadUrl - server request url
30
+ * @param {Object<string, string>=} pluginOptions.uploadHeaders - server request headers
31
+ * @param {string=} pluginOptions.uploadSizeLimit - upload size limit
32
+ * @param {string=} pluginOptions.uploadSingleSizeLimit - upload single size limit
33
+ * @param {boolean=} pluginOptions.allowMultiple - allow multiple files
34
+ * @param {string=} pluginOptions.acceptedFormats - accepted formats
35
+ * @param {string=} pluginOptions.as - Whether to use the 'Box' or 'Link' conversion button
36
+ * @param {Array<string>} pluginOptions.controls - Additional controls to be added to the figure
37
+ */
38
+ constructor(editor, pluginOptions) {
39
+ super(editor);
40
+ // plugin basic properties
41
+ this.title = this.lang.fileUpload;
42
+ this.icon = 'file_upload';
43
+
44
+ if (!pluginOptions.uploadUrl) console.warn('[SUNEDITOR.fileUpload.warn] "fileUpload" plugin must be have "uploadUrl" option.');
45
+
46
+ // members
47
+ this.uploadUrl = pluginOptions.uploadUrl;
48
+ this.uploadHeaders = pluginOptions.uploadHeaders;
49
+ this.uploadSizeLimit = numbers.get(pluginOptions.uploadSizeLimit, 0);
50
+ this.uploadSingleSizeLimit = numbers.get(pluginOptions.uploadSingleSizeLimit, 0);
51
+ this.allowMultiple = !!pluginOptions.allowMultiple;
52
+ this.acceptedFormats = typeof pluginOptions.acceptedFormats !== 'string' ? '*' : pluginOptions.acceptedFormats.trim() || '*';
53
+ this._acceptedCheck = this.acceptedFormats.split(', ');
54
+ this.as = pluginOptions.as || 'box';
55
+ this.input = dom.utils.createElement('input', { type: 'file', accept: this.acceptedFormats });
56
+ if (this.allowMultiple) {
57
+ this.input.setAttribute('multiple', 'multiple');
58
+ }
59
+ this._element = null;
60
+
61
+ // figure
62
+ const customItems = {
63
+ 'custom-download': {
64
+ command: 'download',
65
+ title: this.lang.download,
66
+ icon: 'download',
67
+ action: (target) => {
68
+ const url = target.getAttribute('href');
69
+ if (url) dom.utils.createElement('A', { href: url }, null).click();
70
+ }
71
+ },
72
+ 'custom-as': {
73
+ command: 'as',
74
+ value: 'link', // 'block' or 'link'
75
+ title: this.lang.asLink,
76
+ icon: 'reduction',
77
+ action: (target, value) => {
78
+ this.convertFormat(target, value);
79
+ }
49
80
  }
81
+ };
82
+
83
+ const figureControls = (pluginOptions.controls || [['custom-as', 'align', 'edit', 'custom-download', 'copy', 'remove']]).map((subArray) => subArray.map((item) => (item.startsWith('custom-') ? customItems[item] : item)));
84
+ this.figure = new Figure(this, figureControls, {});
85
+
86
+ // file manager
87
+ this.fileManager = new FileManager(this, {
88
+ query: 'a[download][data-se-file-download]',
89
+ loadHandler: this.events.onFileLoad,
90
+ eventHandler: this.events.onFileAction
91
+ });
92
+
93
+ // controller
94
+ if (/\bedit\b/.test(JSON.stringify(figureControls))) {
95
+ const controllerEl = CreateHTML_controller(this);
96
+ this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true }, FileUpload.key);
97
+ this.editInput = controllerEl.querySelector('input');
50
98
  }
51
- };
52
- let figureControls = pluginOptions.controls || [['custom-as', 'edit', 'align', 'remove', 'custom-download']];
53
- figureControls = figureControls.map((subArray) => subArray.map((item) => (item.startsWith('custom-') ? customItems[item] : item)));
54
- this.figure = new Figure(this, figureControls, {});
55
-
56
- // file manager
57
- this.fileManager = new FileManager(this, {
58
- query: 'a[download][data-se-file-download]',
59
- loadHandler: this.events.onFileLoad,
60
- eventHandler: this.events.onFileAction
61
- });
62
-
63
- // controller
64
- if (/\bedit\b/.test(JSON.stringify(figureControls))) {
65
- const controllerEl = CreateHTML_controller(this);
66
- this.controller = new Controller(this, controllerEl, { position: 'bottom', disabled: true }, FileUpload.key);
67
- this.editInput = controllerEl.querySelector('input');
99
+
100
+ // init
101
+ this.eventManager.addEvent(this.input, 'change', this.#OnChangeFile.bind(this));
68
102
  }
69
103
 
70
- // init
71
- this.eventManager.addEvent(this.input, 'change', OnChangeFile.bind(this));
72
- };
73
-
74
- FileUpload.key = 'fileUpload';
75
- FileUpload.type = 'command';
76
- FileUpload.className = '';
77
- FileUpload.options = { eventIndex: 10000 };
78
- FileUpload.component = function (node) {
79
- return domUtils.isAnchor(node) && node.hasAttribute('data-se-file-download') ? node : null;
80
- };
81
- FileUpload.prototype = {
82
104
  /**
83
- * @override core
84
- * @param {Element} target Target command button
105
+ * @editorMethod Editor.core
106
+ * @description Executes the main execution method of the plugin.
107
+ * - It is executed by clicking a toolbar "command" button or calling an API.
85
108
  */
86
109
  action() {
110
+ this.editor._preventBlur = true;
87
111
  this.input.click();
88
- },
112
+ }
89
113
 
90
114
  /**
91
- * @override fileManager
92
- * @param {Element} target Target element
115
+ * @editorMethod Editor.Component
116
+ * @description Executes the method that is called when a component of a plugin is selected.
117
+ * @param {HTMLElement} target Target component element
93
118
  */
94
119
  select(target) {
95
120
  this._element = target;
96
121
  const asBtn = this.figure.controller.form.querySelector('[data-command="__c__as"]');
97
- if (domUtils.isFigure(target.parentElement)) {
98
- asBtn.innerHTML = this.icons.reduction + CreateTooltipInner(this.lang.asLink);
122
+ if (dom.check.isFigure(target.parentElement)) {
123
+ asBtn.innerHTML = this.icons.reduction + dom.utils.createTooltipInner(this.lang.asLink);
99
124
  asBtn.setAttribute('data-value', 'link');
100
125
  this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, __fileManagerInfo: false });
101
126
  } else {
102
- asBtn.innerHTML = this.icons.expansion + CreateTooltipInner(this.lang.asBlock);
127
+ asBtn.innerHTML = this.icons.expansion + dom.utils.createTooltipInner(this.lang.asBlock);
103
128
  asBtn.setAttribute('data-value', 'box');
104
129
  this.figure.controllerOpen(target, { isWWTarget: true });
105
130
  return true;
106
131
  }
107
- },
132
+ }
108
133
 
109
134
  /**
110
- * @description On paste or drop
111
- * @param {*} params { frameContext, event, file }
135
+ * @editorMethod Editor.EventManager
136
+ * @description Executes the event function of "paste" or "drop".
137
+ * @param {Object} params { frameContext, event, file }
138
+ * @param {__se__FrameContext} params.frameContext Frame context
139
+ * @param {ClipboardEvent} params.event Event object
140
+ * @param {File} params.file File object
141
+ * @returns {boolean} - If return false, the file upload will be canceled
112
142
  */
113
- onPastAndDrop({ file }) {
143
+ onFilePasteAndDrop({ file }) {
114
144
  const fileType = file.type;
115
145
  if (
116
146
  !this._acceptedCheck.some((format) => {
@@ -125,23 +155,24 @@ FileUpload.prototype = {
125
155
  this.editor.focus();
126
156
 
127
157
  return false;
128
- },
158
+ }
129
159
 
130
160
  /**
131
- * @override Figure
132
- * @param {Element} target Target element
161
+ * @editorMethod Modules.Controller
162
+ * @description Executes the method that is called when a target component is edited.
163
+ * @param {HTMLElement|Text} target Target element
133
164
  */
134
165
  edit(target) {
135
166
  this.editInput.value = target.textContent;
136
167
  this.figure.controllerHide();
137
- this.controller.open(target, null, { isWWTarget: !domUtils.isFigure(target.parentElement), initMethod: null, addOffset: null });
168
+ this.controller.open(target, null, { isWWTarget: !dom.check.isFigure(target.parentElement), initMethod: null, addOffset: null });
138
169
  this.editInput.focus();
139
- },
170
+ }
140
171
 
141
172
  /**
142
- * @override controller
143
- * @param {Element} target Target button element
144
- * @returns
173
+ * @editorMethod Modules.Controller
174
+ * @description Executes the method that is called when a button is clicked in the "controller".
175
+ * @param {HTMLButtonElement} target Target button element
145
176
  */
146
177
  controllerAction(target) {
147
178
  const command = target.getAttribute('data-command');
@@ -153,9 +184,38 @@ FileUpload.prototype = {
153
184
  }
154
185
 
155
186
  this.controller.close();
156
- this.component.select(this._element, FileUpload.key, false);
157
- },
187
+ this.component.select(this._element, FileUpload.key);
188
+ }
189
+
190
+ /**
191
+ * @editorMethod Editor.Component
192
+ * @description Method to delete a component of a plugin, called by the "FileManager", "Controller" module.
193
+ * @param {HTMLElement} target Target element
194
+ * @returns {Promise<void>}
195
+ */
196
+ async destroy(target) {
197
+ if (!target) return;
198
+
199
+ const figure = Figure.GetContainer(target);
200
+ const containerTarget = dom.query.getParentElement(target, '.se-component') || target;
201
+
202
+ const message = await this.triggerEvent('onFileDeleteBefore', { element: figure.target, container: figure, url: figure.target.getAttribute('href') });
203
+ if (message === false) return;
204
+
205
+ const isInlineComp = this.component.isInline(containerTarget);
206
+ const focusEl = isInlineComp ? containerTarget.previousSibling || containerTarget.nextSibling : containerTarget.previousElementSibling || containerTarget.nextElementSibling;
207
+ dom.utils.removeItem(containerTarget);
208
+ this.ui._offCurrentController();
209
+
210
+ this.editor.focusEdge(focusEl);
211
+ this.history.push(false);
212
+ }
158
213
 
214
+ /**
215
+ * @description Create an "file" component using the provided files.
216
+ * @param {File[]|FileList} fileList File object list
217
+ * @returns {Promise<boolean>} If return false, the file upload will be canceled
218
+ */
159
219
  async submitFile(fileList) {
160
220
  if (fileList.length === 0) return;
161
221
 
@@ -174,7 +234,7 @@ FileUpload.prototype = {
174
234
  file: f
175
235
  });
176
236
 
177
- this.notice.open(message === NO_EVENT ? err : message || err);
237
+ this.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
178
238
 
179
239
  return false;
180
240
  }
@@ -194,7 +254,7 @@ FileUpload.prototype = {
194
254
  uploadSize: fileSize
195
255
  });
196
256
 
197
- this.notice.open(message === NO_EVENT ? err : message || err);
257
+ this.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
198
258
 
199
259
  return false;
200
260
  }
@@ -205,14 +265,14 @@ FileUpload.prototype = {
205
265
  files
206
266
  };
207
267
 
208
- const handler = async function (infos, newInfos) {
268
+ const handler = async function (uploadCallback, infos, newInfos) {
209
269
  infos = newInfos || infos;
210
270
  const xmlHttp = await this.fileManager.asyncUpload(infos.url, infos.uploadHeaders, infos.files);
211
- this._uploadCallBack(xmlHttp);
212
- }.bind(this, fileInfo);
271
+ uploadCallback(xmlHttp);
272
+ }.bind(this, this.#_uploadCallBack.bind(this), fileInfo);
213
273
 
214
274
  const result = await this.triggerEvent('onFileUploadBefore', {
215
- ...fileInfo,
275
+ info: fileInfo,
216
276
  handler
217
277
  });
218
278
 
@@ -221,33 +281,11 @@ FileUpload.prototype = {
221
281
  if (result !== null && typeof result === 'object') handler(result);
222
282
 
223
283
  if (result === true || result === NO_EVENT) handler(null);
224
- },
225
-
226
- /**
227
- * @override fileManager, Figure
228
- * @param {Element} target Target element
229
- */
230
- async destroy(target) {
231
- if (!target) return;
232
-
233
- const figure = Figure.GetContainer(target);
234
- target = domUtils.getParentElement(target, '.se-component') || target;
235
-
236
- const message = await this.triggerEvent('onFileDeleteBefore', { target: figure.target, container: figure, url: figure.target.getAttribute('href') });
237
- if (message === false) return;
238
-
239
- const isInlineComp = this.component.isInline(target);
240
- const focusEl = isInlineComp ? target.previousSibling || target.nextSibling : target.previousElementSibling || target.nextElementSibling;
241
- domUtils.removeItem(target);
242
- this.editor._offCurrentController();
243
-
244
- this.editor.focusEdge(focusEl);
245
- this.history.push(false);
246
- },
284
+ }
247
285
 
248
286
  /**
249
287
  * @description Convert format to link or block
250
- * @param {Element} target Target element
288
+ * @param {HTMLElement} target Target element
251
289
  * @param {string} value 'link' or 'block'
252
290
  */
253
291
  convertFormat(target, value) {
@@ -258,50 +296,43 @@ FileUpload.prototype = {
258
296
  const parent = container.parentElement;
259
297
 
260
298
  target.removeAttribute('data-se-non-focus');
261
- target.setAttribute('contenteditable', false);
262
- domUtils.addClass(target, 'se-component|se-inline-component');
299
+ target.setAttribute('contenteditable', 'false');
300
+ dom.utils.addClass(target, 'se-component|se-inline-component');
263
301
 
264
- const line = domUtils.createElement(this.options.get('defaultLine'), null, target);
302
+ const line = dom.utils.createElement(this.options.get('defaultLine'), null, target);
265
303
  parent.insertBefore(line, next);
266
- domUtils.removeItem(container);
304
+ dom.utils.removeItem(container);
267
305
  } else {
268
306
  // block
269
307
  this.selection.setRange(target, 0, target, 1);
270
308
  const r = this.html.remove();
271
309
  const s = this.nodeTransform.split(r.container, r.offset, 0);
272
310
 
273
- if (s?.previousElementSibling && domUtils.isZeroWith(s.previousElementSibling)) {
274
- domUtils.removeItem(s.previousElementSibling);
311
+ if (s?.previousElementSibling && dom.check.isZeroWidth(s.previousElementSibling)) {
312
+ dom.utils.removeItem(s.previousElementSibling);
275
313
  }
276
314
 
277
315
  target.setAttribute('data-se-non-focus', 'true');
278
316
  target.removeAttribute('contenteditable');
279
- domUtils.removeClass(target, 'se-component|se-component-selected|se-inline-component');
317
+ dom.utils.removeClass(target, 'se-component|se-component-selected|se-inline-component');
280
318
 
281
319
  const figure = Figure.CreateContainer(target, 'se-file-figure se-flex-component');
282
320
  (s || r.container).parentElement.insertBefore(figure.container, s);
283
321
  }
284
322
 
285
323
  this.history.push(false);
286
- this.component.select(target, FileUpload.key, false);
287
- },
288
-
289
- _register(response) {
290
- response.result.forEach((file, i, a) => {
291
- this._create(
292
- file.url,
293
- {
294
- name: file.name,
295
- size: file.size
296
- },
297
- i === a.length - 1
298
- );
299
- });
300
- },
324
+ this.component.select(target, FileUpload.key);
325
+ }
301
326
 
302
- _create(url, file, isLast) {
327
+ /**
328
+ * @description Create file element
329
+ * @param {string} url File URL
330
+ * @param {File|{name: string, size: number}} file File object
331
+ * @param {boolean} isLast Is last file
332
+ */
333
+ create(url, file, isLast) {
303
334
  const name = file.name || url;
304
- const a = domUtils.createElement(
335
+ const a = dom.utils.createElement(
305
336
  'A',
306
337
  {
307
338
  href: url,
@@ -319,14 +350,14 @@ FileUpload.prototype = {
319
350
 
320
351
  if (this.as === 'link') {
321
352
  a.className = 'se-component se-inline-component';
322
- this.component.insert(a, false, false);
353
+ this.component.insert(a, { skipCharCount: false, skipSelection: false, skipHistory: false });
323
354
  return;
324
355
  }
325
356
 
326
357
  const figure = Figure.CreateContainer(a);
327
- domUtils.addClass(figure.container, 'se-file-figure|se-flex-component');
358
+ dom.utils.addClass(figure.container, 'se-file-figure|se-flex-component');
328
359
 
329
- if (!this.component.insert(figure.container, false, isLast ? !this.options.get('componentAutoSelect') : true)) {
360
+ if (!this.component.insert(figure.container, { skipCharCount: false, skipSelection: isLast ? !this.options.get('componentAutoSelect') : true, skipHistory: false })) {
330
361
  this.editor.focus();
331
362
  return;
332
363
  }
@@ -337,32 +368,68 @@ FileUpload.prototype = {
337
368
  const line = this.format.addLine(figure.container, null);
338
369
  if (line) this.selection.setRange(line, 0, line, 0);
339
370
  } else {
340
- this.component.select(a, FileUpload.key, false);
371
+ this.component.select(a, FileUpload.key);
341
372
  }
342
- },
373
+ }
374
+
375
+ /**
376
+ * @private
377
+ * @description Processes the server response after file upload.
378
+ * - Registers the uploaded files in the editor.
379
+ * @param {Object<string, *>} response - The response object from the server.
380
+ */
381
+ _register(response) {
382
+ response.result.forEach((file, i, a) => {
383
+ this.create(
384
+ file.url,
385
+ {
386
+ name: file.name,
387
+ size: file.size
388
+ },
389
+ i === a.length - 1
390
+ );
391
+ });
392
+ }
343
393
 
394
+ /**
395
+ * @private
396
+ * @description Handles file upload errors.
397
+ * - Displays an error message if the upload fails.
398
+ * @param {Object<string, *>} response - The error response from the server.
399
+ * @returns {Promise<void>}
400
+ */
344
401
  async _error(response) {
345
402
  const message = await this.triggerEvent('onFileUploadError', { error: response });
346
403
  if (message === false) return;
347
404
  const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
348
- this.notice.open(err);
405
+ this.ui.alertOpen(err, 'error');
349
406
  console.error('[SUNEDITOR.plugin.fileUpload.error]', err);
350
- },
407
+ }
351
408
 
352
- _uploadCallBack(xmlHttp) {
409
+ /**
410
+ * @description Handles the file upload completion callback.
411
+ * - Parses the response and registers the uploaded file.
412
+ * @param {XMLHttpRequest} xmlHttp - The completed XHR request.
413
+ */
414
+ #_uploadCallBack(xmlHttp) {
353
415
  const response = JSON.parse(xmlHttp.responseText);
354
416
  if (response.errorMessage) {
355
417
  this._error(response);
356
418
  } else {
357
419
  this._register(response);
358
420
  }
359
- },
360
-
361
- constructor: FileUpload
362
- };
421
+ }
363
422
 
364
- async function OnChangeFile(e) {
365
- await this.submitFile(e.target.files);
423
+ /**
424
+ * @description Handles the change event when a file is selected.
425
+ * - Triggers the file upload process.
426
+ * @param {InputEvent} e - The change event object.
427
+ */
428
+ async #OnChangeFile(e) {
429
+ /** @type {HTMLInputElement} */
430
+ const eventTarget = dom.query.getEventTarget(e);
431
+ await this.submitFile(eventTarget.files);
432
+ }
366
433
  }
367
434
 
368
435
  function CreateHTML_controller({ lang, icons }) {
@@ -383,7 +450,7 @@ function CreateHTML_controller({ lang, icons }) {
383
450
  </form>
384
451
  `;
385
452
 
386
- return domUtils.createElement('DIV', { class: 'se-controller se-controller-resizing' }, html);
453
+ return dom.utils.createElement('DIV', { class: 'se-controller se-controller-simple-input' }, html);
387
454
  }
388
455
 
389
456
  export default FileUpload;