suneditor 3.0.0-alpha.2 → 3.0.0-alpha.20

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