suneditor 3.0.0-beta.9 → 3.0.0-rc.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 (380) hide show
  1. package/README.md +65 -57
  2. package/dist/suneditor-contents.min.css +1 -0
  3. package/dist/suneditor.min.css +1 -1
  4. package/dist/suneditor.min.js +1 -1
  5. package/package.json +110 -61
  6. package/src/assets/design/color.css +36 -17
  7. package/src/assets/design/size.css +2 -0
  8. package/src/assets/icons/defaultIcons.js +17 -2
  9. package/src/assets/suneditor-contents.css +51 -16
  10. package/src/assets/suneditor.css +116 -43
  11. package/src/core/config/contextProvider.js +288 -0
  12. package/src/core/config/eventManager.js +188 -0
  13. package/src/core/config/instanceCheck.js +59 -0
  14. package/src/core/config/optionProvider.js +452 -0
  15. package/src/core/editor.js +166 -1637
  16. package/src/core/event/actions/index.js +229 -0
  17. package/src/core/event/effects/common.registry.js +74 -0
  18. package/src/core/event/effects/keydown.registry.js +573 -0
  19. package/src/core/event/effects/ruleHelpers.js +148 -0
  20. package/src/core/event/eventOrchestrator.js +944 -0
  21. package/src/core/event/executor.js +27 -0
  22. package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +27 -28
  23. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +10 -8
  24. package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +22 -23
  25. package/src/core/event/handlers/handler_ww_input.js +75 -0
  26. package/src/core/event/handlers/handler_ww_key.js +228 -0
  27. package/src/core/event/handlers/handler_ww_mouse.js +166 -0
  28. package/src/core/event/ports.js +211 -0
  29. package/src/core/event/reducers/keydown.reducer.js +97 -0
  30. package/src/core/event/rules/keydown.rule.arrow.js +63 -0
  31. package/src/core/event/rules/keydown.rule.backspace.js +208 -0
  32. package/src/core/event/rules/keydown.rule.delete.js +132 -0
  33. package/src/core/event/rules/keydown.rule.enter.js +150 -0
  34. package/src/core/event/rules/keydown.rule.tab.js +35 -0
  35. package/src/core/event/support/defaultLineManager.js +136 -0
  36. package/src/core/event/support/selectionState.js +204 -0
  37. package/src/core/kernel/coreKernel.js +320 -0
  38. package/src/core/kernel/kernelInjector.js +19 -0
  39. package/src/core/kernel/store.js +173 -0
  40. package/src/core/{class → logic/dom}/char.js +42 -45
  41. package/src/core/logic/dom/format.js +1075 -0
  42. package/src/core/{class → logic/dom}/html.js +743 -624
  43. package/src/core/logic/dom/inline.js +1847 -0
  44. package/src/core/logic/dom/listFormat.js +601 -0
  45. package/src/core/{class → logic/dom}/nodeTransform.js +92 -72
  46. package/src/core/{class → logic/dom}/offset.js +254 -317
  47. package/src/core/logic/dom/selection.js +754 -0
  48. package/src/core/logic/panel/menu.js +389 -0
  49. package/src/core/logic/panel/toolbar.js +449 -0
  50. package/src/core/logic/panel/viewer.js +761 -0
  51. package/src/core/logic/shell/_commandExecutor.js +380 -0
  52. package/src/core/logic/shell/commandDispatcher.js +241 -0
  53. package/src/core/logic/shell/component.js +970 -0
  54. package/src/core/logic/shell/focusManager.js +110 -0
  55. package/src/core/{base → logic/shell}/history.js +110 -60
  56. package/src/core/logic/shell/pluginManager.js +363 -0
  57. package/src/core/logic/shell/shortcuts.js +130 -0
  58. package/src/core/logic/shell/ui.js +904 -0
  59. package/src/core/schema/context.js +66 -0
  60. package/src/core/schema/frameContext.js +160 -0
  61. package/src/core/schema/options.js +628 -0
  62. package/src/core/section/constructor.js +194 -500
  63. package/src/core/section/documentType.js +297 -222
  64. package/src/events.js +808 -543
  65. package/src/helper/clipboard.js +27 -16
  66. package/src/helper/converter.js +100 -78
  67. package/src/helper/dom/domCheck.js +56 -30
  68. package/src/helper/dom/domQuery.js +159 -89
  69. package/src/helper/dom/domUtils.js +114 -49
  70. package/src/helper/dom/index.js +5 -1
  71. package/src/helper/env.js +26 -26
  72. package/src/helper/index.js +1 -1
  73. package/src/helper/keyCodeMap.js +25 -28
  74. package/src/helper/numbers.js +4 -8
  75. package/src/helper/unicode.js +4 -8
  76. package/src/hooks/base.js +307 -0
  77. package/src/hooks/params.js +130 -0
  78. package/src/interfaces/contracts.js +227 -0
  79. package/src/interfaces/index.js +7 -0
  80. package/src/interfaces/plugins.js +239 -0
  81. package/src/langs/ckb.js +4 -4
  82. package/src/langs/cs.js +4 -4
  83. package/src/langs/da.js +4 -4
  84. package/src/langs/de.js +4 -4
  85. package/src/langs/en.js +4 -4
  86. package/src/langs/es.js +4 -4
  87. package/src/langs/fa.js +4 -4
  88. package/src/langs/fr.js +4 -4
  89. package/src/langs/he.js +4 -4
  90. package/src/langs/hu.js +4 -4
  91. package/src/langs/it.js +4 -4
  92. package/src/langs/ja.js +4 -4
  93. package/src/langs/km.js +4 -4
  94. package/src/langs/ko.js +4 -4
  95. package/src/langs/lv.js +4 -4
  96. package/src/langs/nl.js +4 -4
  97. package/src/langs/pl.js +4 -4
  98. package/src/langs/pt_br.js +13 -13
  99. package/src/langs/ro.js +4 -4
  100. package/src/langs/ru.js +4 -4
  101. package/src/langs/se.js +4 -4
  102. package/src/langs/tr.js +4 -4
  103. package/src/langs/uk.js +4 -4
  104. package/src/langs/ur.js +4 -4
  105. package/src/langs/zh_cn.js +4 -4
  106. package/src/modules/{Browser.js → contract/Browser.js} +119 -128
  107. package/src/modules/{ColorPicker.js → contract/ColorPicker.js} +132 -142
  108. package/src/modules/contract/Controller.js +589 -0
  109. package/src/modules/{Figure.js → contract/Figure.js} +591 -411
  110. package/src/modules/{HueSlider.js → contract/HueSlider.js} +125 -86
  111. package/src/modules/contract/Modal.js +357 -0
  112. package/src/modules/contract/index.js +9 -0
  113. package/src/modules/manager/ApiManager.js +197 -0
  114. package/src/modules/{FileManager.js → manager/FileManager.js} +128 -160
  115. package/src/modules/manager/index.js +5 -0
  116. package/src/modules/{ModalAnchorEditor.js → ui/ModalAnchorEditor.js} +108 -138
  117. package/src/modules/{SelectMenu.js → ui/SelectMenu.js} +119 -120
  118. package/src/modules/{_DragHandle.js → ui/_DragHandle.js} +1 -1
  119. package/src/modules/ui/index.js +6 -0
  120. package/src/plugins/browser/audioGallery.js +23 -26
  121. package/src/plugins/browser/fileBrowser.js +25 -28
  122. package/src/plugins/browser/fileGallery.js +20 -23
  123. package/src/plugins/browser/imageGallery.js +24 -23
  124. package/src/plugins/browser/videoGallery.js +27 -29
  125. package/src/plugins/command/blockquote.js +11 -17
  126. package/src/plugins/command/exportPDF.js +26 -26
  127. package/src/plugins/command/fileUpload.js +138 -133
  128. package/src/plugins/command/list_bulleted.js +48 -44
  129. package/src/plugins/command/list_numbered.js +48 -44
  130. package/src/plugins/dropdown/align.js +64 -50
  131. package/src/plugins/dropdown/backgroundColor.js +34 -35
  132. package/src/plugins/dropdown/{formatBlock.js → blockStyle.js} +43 -37
  133. package/src/plugins/dropdown/font.js +50 -36
  134. package/src/plugins/dropdown/fontColor.js +34 -35
  135. package/src/plugins/dropdown/hr.js +55 -50
  136. package/src/plugins/dropdown/layout.js +20 -15
  137. package/src/plugins/dropdown/lineHeight.js +46 -30
  138. package/src/plugins/dropdown/list.js +32 -33
  139. package/src/plugins/dropdown/paragraphStyle.js +40 -34
  140. package/src/plugins/dropdown/table/index.js +915 -0
  141. package/src/plugins/dropdown/table/render/table.html.js +308 -0
  142. package/src/plugins/dropdown/table/render/table.menu.js +121 -0
  143. package/src/plugins/dropdown/table/services/table.cell.js +465 -0
  144. package/src/plugins/dropdown/table/services/table.clipboard.js +414 -0
  145. package/src/plugins/dropdown/table/services/table.grid.js +504 -0
  146. package/src/plugins/dropdown/table/services/table.resize.js +463 -0
  147. package/src/plugins/dropdown/table/services/table.selection.js +466 -0
  148. package/src/plugins/dropdown/table/services/table.style.js +844 -0
  149. package/src/plugins/dropdown/table/shared/table.constants.js +109 -0
  150. package/src/plugins/dropdown/table/shared/table.utils.js +219 -0
  151. package/src/plugins/dropdown/template.js +20 -15
  152. package/src/plugins/dropdown/textStyle.js +28 -22
  153. package/src/plugins/field/mention.js +54 -49
  154. package/src/plugins/index.js +5 -5
  155. package/src/plugins/input/fontSize.js +100 -97
  156. package/src/plugins/input/pageNavigator.js +13 -10
  157. package/src/plugins/modal/audio.js +208 -219
  158. package/src/plugins/modal/drawing.js +99 -104
  159. package/src/plugins/modal/embed.js +323 -312
  160. package/src/plugins/modal/image/index.js +942 -0
  161. package/src/plugins/modal/image/render/image.html.js +150 -0
  162. package/src/plugins/modal/image/services/image.size.js +198 -0
  163. package/src/plugins/modal/image/services/image.upload.js +216 -0
  164. package/src/plugins/modal/image/shared/image.constants.js +20 -0
  165. package/src/plugins/modal/link.js +74 -54
  166. package/src/plugins/modal/math.js +126 -119
  167. package/src/plugins/modal/video/index.js +858 -0
  168. package/src/plugins/modal/video/render/video.html.js +131 -0
  169. package/src/plugins/modal/video/services/video.size.js +281 -0
  170. package/src/plugins/modal/video/services/video.upload.js +92 -0
  171. package/src/plugins/popup/anchor.js +57 -49
  172. package/src/suneditor.js +73 -61
  173. package/src/themes/cobalt.css +155 -0
  174. package/src/themes/dark.css +143 -120
  175. package/src/typedef.js +214 -63
  176. package/types/assets/icons/defaultIcons.d.ts +8 -0
  177. package/types/assets/suneditor-contents.css.d.ts +1 -0
  178. package/types/assets/suneditor.css.d.ts +1 -0
  179. package/types/core/config/contextProvider.d.ts +148 -0
  180. package/types/core/config/eventManager.d.ts +68 -0
  181. package/types/core/config/instanceCheck.d.ts +33 -0
  182. package/types/core/config/optionProvider.d.ts +147 -0
  183. package/types/core/editor.d.ts +27 -586
  184. package/types/core/event/actions/index.d.ts +50 -0
  185. package/types/core/event/effects/common.registry.d.ts +56 -0
  186. package/types/core/event/effects/keydown.registry.d.ts +80 -0
  187. package/types/core/event/effects/ruleHelpers.d.ts +36 -0
  188. package/types/core/event/eventOrchestrator.d.ts +191 -0
  189. package/types/core/event/executor.d.ts +13 -0
  190. package/types/core/event/handlers/handler_toolbar.d.ts +38 -0
  191. package/types/core/event/handlers/handler_ww_clipboard.d.ts +36 -0
  192. package/types/core/event/handlers/handler_ww_dragDrop.d.ts +26 -0
  193. package/types/core/event/handlers/handler_ww_input.d.ts +38 -0
  194. package/types/core/event/handlers/handler_ww_key.d.ts +40 -0
  195. package/types/core/event/handlers/handler_ww_mouse.d.ts +47 -0
  196. package/types/core/event/ports.d.ts +256 -0
  197. package/types/core/event/reducers/keydown.reducer.d.ts +84 -0
  198. package/types/core/event/rules/keydown.rule.arrow.d.ts +19 -0
  199. package/types/core/event/rules/keydown.rule.backspace.d.ts +18 -0
  200. package/types/core/event/rules/keydown.rule.delete.d.ts +18 -0
  201. package/types/core/event/rules/keydown.rule.enter.d.ts +18 -0
  202. package/types/core/event/rules/keydown.rule.tab.d.ts +18 -0
  203. package/types/core/event/support/defaultLineManager.d.ts +22 -0
  204. package/types/core/event/support/selectionState.d.ts +29 -0
  205. package/types/core/kernel/coreKernel.d.ts +219 -0
  206. package/types/core/kernel/kernelInjector.d.ts +16 -0
  207. package/types/core/kernel/store.d.ts +170 -0
  208. package/types/core/logic/dom/char.d.ts +46 -0
  209. package/types/core/logic/dom/format.d.ts +234 -0
  210. package/types/core/logic/dom/html.d.ts +290 -0
  211. package/types/core/logic/dom/inline.d.ts +93 -0
  212. package/types/core/logic/dom/listFormat.d.ts +101 -0
  213. package/types/core/logic/dom/nodeTransform.d.ts +110 -0
  214. package/types/core/logic/dom/offset.d.ts +335 -0
  215. package/types/core/logic/dom/selection.d.ts +165 -0
  216. package/types/core/logic/panel/menu.d.ts +93 -0
  217. package/types/core/logic/panel/toolbar.d.ts +128 -0
  218. package/types/core/logic/panel/viewer.d.ts +89 -0
  219. package/types/core/logic/shell/_commandExecutor.d.ts +18 -0
  220. package/types/core/logic/shell/commandDispatcher.d.ts +65 -0
  221. package/types/core/logic/shell/component.d.ts +182 -0
  222. package/types/core/logic/shell/focusManager.d.ts +31 -0
  223. package/types/core/{base → logic/shell}/history.d.ts +13 -12
  224. package/types/core/logic/shell/pluginManager.d.ts +115 -0
  225. package/types/core/logic/shell/shortcuts.d.ts +131 -0
  226. package/types/core/logic/shell/ui.d.ts +261 -0
  227. package/types/core/schema/context.d.ts +104 -0
  228. package/types/core/schema/frameContext.d.ts +320 -0
  229. package/types/core/schema/options.d.ts +1241 -0
  230. package/types/core/section/constructor.d.ts +117 -652
  231. package/types/core/section/documentType.d.ts +43 -61
  232. package/types/events.d.ts +796 -65
  233. package/types/helper/clipboard.d.ts +5 -4
  234. package/types/helper/converter.d.ts +55 -43
  235. package/types/helper/dom/domCheck.d.ts +27 -19
  236. package/types/helper/dom/domQuery.d.ts +76 -57
  237. package/types/helper/dom/domUtils.d.ts +62 -39
  238. package/types/helper/dom/index.d.ts +87 -1
  239. package/types/helper/env.d.ts +16 -13
  240. package/types/helper/index.d.ts +8 -2
  241. package/types/helper/keyCodeMap.d.ts +24 -23
  242. package/types/helper/numbers.d.ts +4 -6
  243. package/types/helper/unicode.d.ts +4 -3
  244. package/types/hooks/base.d.ts +239 -0
  245. package/types/hooks/params.d.ts +65 -0
  246. package/types/index.d.ts +20 -117
  247. package/types/interfaces/contracts.d.ts +183 -0
  248. package/types/interfaces/index.d.ts +3 -0
  249. package/types/interfaces/plugins.d.ts +168 -0
  250. package/types/langs/_Lang.d.ts +2 -2
  251. package/types/langs/index.d.ts +2 -2
  252. package/types/modules/contract/Browser.d.ts +262 -0
  253. package/types/modules/contract/ColorPicker.d.ts +99 -0
  254. package/types/modules/contract/Controller.d.ts +204 -0
  255. package/types/modules/contract/Figure.d.ts +529 -0
  256. package/types/modules/{HueSlider.d.ts → contract/HueSlider.d.ts} +39 -28
  257. package/types/modules/contract/Modal.d.ts +62 -0
  258. package/types/modules/contract/index.d.ts +7 -0
  259. package/types/modules/manager/ApiManager.d.ts +106 -0
  260. package/types/modules/manager/FileManager.d.ts +124 -0
  261. package/types/modules/manager/index.d.ts +3 -0
  262. package/types/modules/ui/ModalAnchorEditor.d.ts +152 -0
  263. package/types/modules/ui/SelectMenu.d.ts +107 -0
  264. package/types/modules/{_DragHandle.d.ts → ui/_DragHandle.d.ts} +1 -0
  265. package/types/modules/ui/index.d.ts +4 -0
  266. package/types/plugins/browser/audioGallery.d.ts +33 -41
  267. package/types/plugins/browser/fileBrowser.d.ts +42 -50
  268. package/types/plugins/browser/fileGallery.d.ts +33 -41
  269. package/types/plugins/browser/imageGallery.d.ts +30 -37
  270. package/types/plugins/browser/videoGallery.d.ts +33 -41
  271. package/types/plugins/command/blockquote.d.ts +4 -21
  272. package/types/plugins/command/exportPDF.d.ts +23 -33
  273. package/types/plugins/command/fileUpload.d.ts +80 -100
  274. package/types/plugins/command/list_bulleted.d.ts +9 -35
  275. package/types/plugins/command/list_numbered.d.ts +9 -35
  276. package/types/plugins/dropdown/align.d.ts +23 -46
  277. package/types/plugins/dropdown/backgroundColor.d.ts +35 -53
  278. package/types/plugins/dropdown/blockStyle.d.ts +45 -0
  279. package/types/plugins/dropdown/font.d.ts +18 -41
  280. package/types/plugins/dropdown/fontColor.d.ts +35 -53
  281. package/types/plugins/dropdown/hr.d.ts +26 -52
  282. package/types/plugins/dropdown/layout.d.ts +19 -25
  283. package/types/plugins/dropdown/lineHeight.d.ts +21 -39
  284. package/types/plugins/dropdown/list.d.ts +6 -34
  285. package/types/plugins/dropdown/paragraphStyle.d.ts +34 -45
  286. package/types/plugins/dropdown/table/index.d.ts +158 -0
  287. package/types/plugins/dropdown/table/render/table.html.d.ts +71 -0
  288. package/types/plugins/dropdown/table/render/table.menu.d.ts +59 -0
  289. package/types/plugins/dropdown/table/services/table.cell.d.ts +76 -0
  290. package/types/plugins/dropdown/table/services/table.clipboard.d.ts +26 -0
  291. package/types/plugins/dropdown/table/services/table.grid.d.ts +77 -0
  292. package/types/plugins/dropdown/table/services/table.resize.d.ts +72 -0
  293. package/types/plugins/dropdown/table/services/table.selection.d.ts +59 -0
  294. package/types/plugins/dropdown/table/services/table.style.d.ts +162 -0
  295. package/types/plugins/dropdown/table/shared/table.constants.d.ts +134 -0
  296. package/types/plugins/dropdown/table/shared/table.utils.d.ts +91 -0
  297. package/types/plugins/dropdown/template.d.ts +19 -25
  298. package/types/plugins/dropdown/textStyle.d.ts +23 -30
  299. package/types/plugins/field/mention.d.ts +66 -72
  300. package/types/plugins/index.d.ts +41 -40
  301. package/types/plugins/input/fontSize.d.ts +57 -96
  302. package/types/plugins/input/pageNavigator.d.ts +5 -8
  303. package/types/plugins/modal/audio.d.ts +60 -153
  304. package/types/plugins/modal/drawing.d.ts +16 -118
  305. package/types/plugins/modal/embed.d.ts +46 -166
  306. package/types/plugins/modal/image/index.d.ts +281 -0
  307. package/types/plugins/modal/image/render/image.html.d.ts +45 -0
  308. package/types/plugins/modal/image/services/image.size.d.ts +55 -0
  309. package/types/plugins/modal/image/services/image.upload.d.ts +24 -0
  310. package/types/plugins/modal/image/shared/image.constants.d.ts +17 -0
  311. package/types/plugins/modal/link.d.ts +46 -66
  312. package/types/plugins/modal/math.d.ts +17 -86
  313. package/types/plugins/modal/{video.d.ts → video/index.d.ts} +89 -221
  314. package/types/plugins/modal/video/render/video.html.d.ts +37 -0
  315. package/types/plugins/modal/video/services/video.size.d.ts +74 -0
  316. package/types/plugins/modal/video/services/video.upload.d.ts +19 -0
  317. package/types/plugins/popup/anchor.d.ts +8 -38
  318. package/types/suneditor.d.ts +55 -24
  319. package/types/typedef.d.ts +344 -228
  320. package/CONTRIBUTING.md +0 -186
  321. package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
  322. package/src/core/base/eventHandlers/handler_ww_mouse.js +0 -194
  323. package/src/core/base/eventManager.js +0 -1523
  324. package/src/core/class/component.js +0 -856
  325. package/src/core/class/format.js +0 -3433
  326. package/src/core/class/menu.js +0 -346
  327. package/src/core/class/selection.js +0 -610
  328. package/src/core/class/shortcuts.js +0 -98
  329. package/src/core/class/toolbar.js +0 -431
  330. package/src/core/class/ui.js +0 -424
  331. package/src/core/class/viewer.js +0 -750
  332. package/src/core/section/actives.js +0 -266
  333. package/src/core/section/context.js +0 -102
  334. package/src/editorInjector/_classes.js +0 -36
  335. package/src/editorInjector/_core.js +0 -87
  336. package/src/editorInjector/index.js +0 -73
  337. package/src/modules/ApiManager.js +0 -191
  338. package/src/modules/Controller.js +0 -474
  339. package/src/modules/Modal.js +0 -346
  340. package/src/modules/index.js +0 -14
  341. package/src/plugins/dropdown/table.js +0 -4034
  342. package/src/plugins/modal/image.js +0 -1376
  343. package/src/plugins/modal/video.js +0 -1226
  344. package/types/core/base/eventHandlers/handler_toolbar.d.ts +0 -41
  345. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +0 -40
  346. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +0 -35
  347. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +0 -45
  348. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +0 -39
  349. package/types/core/base/eventManager.d.ts +0 -401
  350. package/types/core/class/char.d.ts +0 -61
  351. package/types/core/class/component.d.ts +0 -213
  352. package/types/core/class/format.d.ts +0 -623
  353. package/types/core/class/html.d.ts +0 -430
  354. package/types/core/class/menu.d.ts +0 -126
  355. package/types/core/class/nodeTransform.d.ts +0 -93
  356. package/types/core/class/offset.d.ts +0 -522
  357. package/types/core/class/selection.d.ts +0 -188
  358. package/types/core/class/shortcuts.d.ts +0 -142
  359. package/types/core/class/toolbar.d.ts +0 -189
  360. package/types/core/class/ui.d.ts +0 -164
  361. package/types/core/class/viewer.d.ts +0 -140
  362. package/types/core/section/actives.d.ts +0 -46
  363. package/types/core/section/context.d.ts +0 -45
  364. package/types/editorInjector/_classes.d.ts +0 -41
  365. package/types/editorInjector/_core.d.ts +0 -87
  366. package/types/editorInjector/index.d.ts +0 -69
  367. package/types/modules/ApiManager.d.ts +0 -125
  368. package/types/modules/Browser.d.ts +0 -326
  369. package/types/modules/ColorPicker.d.ts +0 -135
  370. package/types/modules/Controller.d.ts +0 -251
  371. package/types/modules/Figure.d.ts +0 -517
  372. package/types/modules/FileManager.d.ts +0 -202
  373. package/types/modules/Modal.d.ts +0 -111
  374. package/types/modules/ModalAnchorEditor.d.ts +0 -236
  375. package/types/modules/SelectMenu.d.ts +0 -194
  376. package/types/modules/index.d.ts +0 -26
  377. package/types/plugins/dropdown/formatBlock.d.ts +0 -55
  378. package/types/plugins/dropdown/table.d.ts +0 -627
  379. package/types/plugins/modal/image.d.ts +0 -451
  380. /package/{LICENSE → LICENSE.txt} +0 -0
@@ -1,20 +1,37 @@
1
- import EditorInjector from '../../editorInjector';
1
+ import { PluginCommand } from '../../interfaces';
2
2
  import { dom, env, numbers } from '../../helper';
3
- import { FileManager, Figure, Controller } from '../../modules';
3
+ import { Controller, Figure } from '../../modules/contract';
4
+ import { FileManager } from '../../modules/manager';
4
5
 
5
6
  const { NO_EVENT } = env;
6
7
 
8
+ /**
9
+ * @typedef FileUploadPluginOptions
10
+ * @property {string} uploadUrl - Server request URL for file upload
11
+ * @property {Object<string, string>} [uploadHeaders] - Server request headers
12
+ * @property {number} [uploadSizeLimit] - Total upload size limit in bytes
13
+ * @property {number} [uploadSingleSizeLimit] - Single file size limit in bytes
14
+ * @property {boolean} [allowMultiple=false] - Allow multiple file uploads
15
+ * @property {string} [acceptedFormats="*"] - Accepted file formats (e.g., 'image/*, .pdf')
16
+ * @property {string} [as="box"] - Specify the default form of the file component as `box` or `link`
17
+ * @property {Array<string>} [controls] - Additional controls to be added to the figure
18
+ * @property {SunEditor.ComponentInsertType} [insertBehavior] - Component insertion behavior for selection and cursor placement. [default: `options.get('componentInsertBehavior')`]
19
+ * - `auto`: Move cursor to the next line if possible, otherwise select the component.
20
+ * - `select`: Always select the inserted component.
21
+ * - `line`: Move cursor to the next line if possible, or create a new line and move there.
22
+ * - `none`: Do nothing.
23
+ */
24
+
7
25
  /**
8
26
  * @class
9
27
  * @description File upload plugin
10
28
  */
11
- class FileUpload extends EditorInjector {
29
+ class FileUpload extends PluginCommand {
12
30
  static key = 'fileUpload';
13
- static type = 'command';
14
31
  static className = '';
15
32
  static options = { eventIndex: 10000 };
33
+
16
34
  /**
17
- * @this {FileUpload}
18
35
  * @param {HTMLElement} node - The node to check.
19
36
  * @returns {HTMLElement|null} Returns a node if the node is a valid component.
20
37
  */
@@ -22,23 +39,18 @@ class FileUpload extends EditorInjector {
22
39
  return dom.check.isAnchor(node) && node.hasAttribute('data-se-file-download') ? node : null;
23
40
  }
24
41
 
42
+ #acceptedCheck;
43
+ #element = null;
44
+
25
45
  /**
26
46
  * @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
47
+ * @param {SunEditor.Kernel} editor - The core kernel
48
+ * @param {FileUploadPluginOptions} pluginOptions - plugin options
37
49
  */
38
50
  constructor(editor, pluginOptions) {
39
51
  super(editor);
40
52
  // plugin basic properties
41
- this.title = this.lang.fileUpload;
53
+ this.title = this.$.lang.fileUpload;
42
54
  this.icon = 'file_upload';
43
55
 
44
56
  if (!pluginOptions.uploadUrl) console.warn('[SUNEDITOR.fileUpload.warn] "fileUpload" plugin must be have "uploadUrl" option.');
@@ -50,100 +62,75 @@ class FileUpload extends EditorInjector {
50
62
  this.uploadSingleSizeLimit = numbers.get(pluginOptions.uploadSingleSizeLimit, 0);
51
63
  this.allowMultiple = !!pluginOptions.allowMultiple;
52
64
  this.acceptedFormats = typeof pluginOptions.acceptedFormats !== 'string' ? '*' : pluginOptions.acceptedFormats.trim() || '*';
53
- this._acceptedCheck = this.acceptedFormats.split(', ');
54
65
  this.as = pluginOptions.as || 'box';
66
+ this.insertBehavior = pluginOptions.insertBehavior;
55
67
  this.input = dom.utils.createElement('input', { type: 'file', accept: this.acceptedFormats });
56
68
  if (this.allowMultiple) {
57
69
  this.input.setAttribute('multiple', 'multiple');
58
70
  }
59
- this._element = null;
71
+
72
+ this.#acceptedCheck = this.acceptedFormats.split(', ');
60
73
 
61
74
  // figure
62
75
  const customItems = {
63
76
  'custom-download': {
64
77
  command: 'download',
65
- title: this.lang.download,
78
+ title: this.$.lang.download,
66
79
  icon: 'download',
67
80
  action: (target) => {
68
81
  const url = target.getAttribute('href');
69
82
  if (url) dom.utils.createElement('A', { href: url }, null).click();
70
- }
83
+ },
71
84
  },
72
85
  'custom-as': {
73
86
  command: 'as',
74
87
  value: 'link', // 'block' or 'link'
75
- title: this.lang.asLink,
88
+ title: this.$.lang.asLink,
76
89
  icon: 'reduction',
77
90
  action: (target, value) => {
78
91
  this.convertFormat(target, value);
79
- }
80
- }
92
+ },
93
+ },
81
94
  };
82
95
 
83
96
  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, {});
97
+ this.figure = new Figure(this, this.$, figureControls, {});
85
98
 
86
99
  // file manager
87
- this.fileManager = new FileManager(this, {
100
+ this.fileManager = new FileManager(this, this.$, {
88
101
  query: 'a[download][data-se-file-download]',
89
- loadHandler: this.events.onFileLoad,
90
- eventHandler: this.events.onFileAction
102
+ loadEventName: 'onFileLoad',
103
+ actionEventName: 'onFileAction',
91
104
  });
92
105
 
93
106
  // controller
94
107
  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);
108
+ const controllerEl = CreateHTML_controller(this.$);
109
+ this.controller = new Controller(this, this.$, controllerEl, { position: 'bottom', disabled: true }, FileUpload.key);
97
110
  this.editInput = controllerEl.querySelector('input');
98
111
  }
99
112
 
100
113
  // init
101
- this.eventManager.addEvent(this.input, 'change', this.#OnChangeFile.bind(this));
114
+ this.$.eventManager.addEvent(this.input, 'change', this.#OnChangeFile.bind(this));
102
115
  }
103
116
 
104
117
  /**
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.
118
+ * @override
119
+ * @type {PluginCommand['action']}
108
120
  */
109
121
  action() {
110
- this.editor._preventBlur = true;
122
+ this.$.store.set('_preventBlur', true);
111
123
  this.input.click();
112
124
  }
113
125
 
114
126
  /**
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
118
- */
119
- select(target) {
120
- this._element = target;
121
- const asBtn = this.figure.controller.form.querySelector('[data-command="__c__as"]');
122
- if (dom.check.isFigure(target.parentElement)) {
123
- asBtn.innerHTML = this.icons.reduction + dom.utils.createTooltipInner(this.lang.asLink);
124
- asBtn.setAttribute('data-value', 'link');
125
- this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, __fileManagerInfo: false });
126
- } else {
127
- asBtn.innerHTML = this.icons.expansion + dom.utils.createTooltipInner(this.lang.asBlock);
128
- asBtn.setAttribute('data-value', 'box');
129
- this.figure.controllerOpen(target, { isWWTarget: true });
130
- return true;
131
- }
132
- }
133
-
134
- /**
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
127
+ * @hook Editor.EventManager
128
+ * @type {SunEditor.Hook.Event.OnFilePasteAndDrop}
142
129
  */
143
130
  onFilePasteAndDrop({ file }) {
144
131
  const fileType = file.type;
145
132
  if (
146
- !this._acceptedCheck.some((format) => {
133
+ !this.#acceptedCheck.some((format) => {
147
134
  if (format.startsWith('*')) return true;
148
135
  if (format.startsWith(fileType)) return true;
149
136
  })
@@ -152,27 +139,12 @@ class FileUpload extends EditorInjector {
152
139
  }
153
140
 
154
141
  this.submitFile([file]);
155
- this.editor.focus();
156
-
157
- return false;
142
+ this.$.focusManager.focus();
158
143
  }
159
144
 
160
145
  /**
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
164
- */
165
- edit(target) {
166
- this.editInput.value = target.textContent;
167
- this.figure.controllerHide();
168
- this.controller.open(target, null, { isWWTarget: !dom.check.isFigure(target.parentElement), initMethod: null, addOffset: null });
169
- this.editInput.focus();
170
- }
171
-
172
- /**
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
146
+ * @hook Modules.Controller
147
+ * @type {SunEditor.Hook.Controller.Action}
176
148
  */
177
149
  controllerAction(target) {
178
150
  const command = target.getAttribute('data-command');
@@ -180,39 +152,70 @@ class FileUpload extends EditorInjector {
180
152
 
181
153
  if (command === 'edit') {
182
154
  if (this.editInput.value.trim().length === 0) return;
183
- this._element.textContent = this.editInput.value;
155
+ this.#element.textContent = this.editInput.value;
184
156
  }
185
157
 
186
158
  this.controller.close();
187
- this.component.select(this._element, FileUpload.key);
159
+ this.$.component.select(this.#element, FileUpload.key);
188
160
  }
189
161
 
190
162
  /**
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>}
163
+ * @hook Editor.Component
164
+ * @type {SunEditor.Hook.Component.Select}
165
+ */
166
+ componentSelect(target) {
167
+ this.#element = target;
168
+
169
+ const asBtn = this.figure.controller.form.querySelector('[data-command="__c__as"]');
170
+ if (!asBtn) return;
171
+
172
+ if (dom.check.isFigure(target.parentElement)) {
173
+ asBtn.innerHTML = this.$.icons.reduction + dom.utils.createTooltipInner(this.$.lang.asLink);
174
+ asBtn.setAttribute('data-value', 'link');
175
+ this.figure.open(target, { nonResizing: true, nonSizeInfo: true, nonBorder: true, figureTarget: true, infoOnly: false });
176
+ } else {
177
+ asBtn.innerHTML = this.$.icons.expansion + dom.utils.createTooltipInner(this.$.lang.asBlock);
178
+ asBtn.setAttribute('data-value', 'box');
179
+ this.figure.controllerOpen(target, { isWWTarget: true });
180
+ return true;
181
+ }
182
+ }
183
+
184
+ /**
185
+ * @hook Editor.Component
186
+ * @type {SunEditor.Hook.Component.Edit}
187
+ */
188
+ componentEdit(target) {
189
+ this.editInput.value = target.textContent;
190
+ this.figure.controllerHide();
191
+ this.controller.open(target, null, { isWWTarget: !dom.check.isFigure(target.parentElement), initMethod: null, addOffset: null });
192
+ this.editInput.focus();
193
+ }
194
+
195
+ /**
196
+ * @hook Editor.Component
197
+ * @type {SunEditor.Hook.Component.Destroy}
195
198
  */
196
- async destroy(target) {
199
+ async componentDestroy(target) {
197
200
  if (!target) return;
198
201
 
199
202
  const figure = Figure.GetContainer(target);
200
203
  const containerTarget = dom.query.getParentElement(target, '.se-component') || target;
201
204
 
202
- const message = await this.triggerEvent('onFileDeleteBefore', { element: figure.target, container: figure, url: figure.target.getAttribute('href') });
205
+ const message = await this.$.eventManager.triggerEvent('onFileDeleteBefore', { element: figure.target, container: figure, url: figure.target.getAttribute('href') });
203
206
  if (message === false) return;
204
207
 
205
- const isInlineComp = this.component.isInline(containerTarget);
208
+ const isInlineComp = this.$.component.isInline(containerTarget);
206
209
  const focusEl = isInlineComp ? containerTarget.previousSibling || containerTarget.nextSibling : containerTarget.previousElementSibling || containerTarget.nextElementSibling;
207
210
  dom.utils.removeItem(containerTarget);
208
- this.ui._offCurrentController();
211
+ this.$.ui.offCurrentController();
209
212
 
210
- this.editor.focusEdge(focusEl);
211
- this.history.push(false);
213
+ this.$.focusManager.focusEdge(focusEl);
214
+ this.$.history.push(false);
212
215
  }
213
216
 
214
217
  /**
215
- * @description Create an "file" component using the provided files.
218
+ * @description Create a `file` component using the provided files.
216
219
  * @param {File[]|FileList} fileList File object list
217
220
  * @returns {Promise<boolean>} If return false, the file upload will be canceled
218
221
  */
@@ -225,16 +228,16 @@ class FileUpload extends EditorInjector {
225
228
  for (let i = 0, len = fileList.length, f, s; i < len; i++) {
226
229
  f = fileList[i];
227
230
  s = f.size;
228
- if (slngleSizeLimit && slngleSizeLimit > s) {
231
+ if (slngleSizeLimit > 0 && s > slngleSizeLimit) {
229
232
  const err = '[SUNEDITOR.fileUpload.fail] Size of uploadable single file: ' + slngleSizeLimit / 1000 + 'KB';
230
- const message = await this.triggerEvent('onFileUploadError', {
233
+ const message = await this.$.eventManager.triggerEvent('onFileUploadError', {
231
234
  error: err,
232
235
  limitSize: slngleSizeLimit,
233
236
  uploadSize: s,
234
- file: f
237
+ file: f,
235
238
  });
236
239
 
237
- this.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
240
+ this.$.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
238
241
 
239
242
  return false;
240
243
  }
@@ -247,14 +250,14 @@ class FileUpload extends EditorInjector {
247
250
  const currentSize = this.fileManager.getSize();
248
251
  if (limitSize > 0 && fileSize + currentSize > limitSize) {
249
252
  const err = '[SUNEDITOR.fileUpload.fail] Size of uploadable total files: ' + limitSize / 1000 + 'KB';
250
- const message = await this.triggerEvent('onFileUploadError', {
253
+ const message = await this.$.eventManager.triggerEvent('onFileUploadError', {
251
254
  error: err,
252
255
  limitSize,
253
256
  currentSize,
254
- uploadSize: fileSize
257
+ uploadSize: fileSize,
255
258
  });
256
259
 
257
- this.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
260
+ this.$.ui.alertOpen(message === NO_EVENT ? err : message || err, 'error');
258
261
 
259
262
  return false;
260
263
  }
@@ -262,18 +265,18 @@ class FileUpload extends EditorInjector {
262
265
  const fileInfo = {
263
266
  url: this.uploadUrl,
264
267
  uploadHeaders: this.uploadHeaders,
265
- files
268
+ files,
266
269
  };
267
270
 
268
271
  const handler = async function (uploadCallback, infos, newInfos) {
269
272
  infos = newInfos || infos;
270
273
  const xmlHttp = await this.fileManager.asyncUpload(infos.url, infos.uploadHeaders, infos.files);
271
274
  uploadCallback(xmlHttp);
272
- }.bind(this, this.#_uploadCallBack.bind(this), fileInfo);
275
+ }.bind(this, this.#uploadCallBack.bind(this), fileInfo);
273
276
 
274
- const result = await this.triggerEvent('onFileUploadBefore', {
277
+ const result = await this.$.eventManager.triggerEvent('onFileUploadBefore', {
275
278
  info: fileInfo,
276
- handler
279
+ handler,
277
280
  });
278
281
 
279
282
  if (result === undefined) return true;
@@ -284,9 +287,9 @@ class FileUpload extends EditorInjector {
284
287
  }
285
288
 
286
289
  /**
287
- * @description Convert format to link or block
290
+ * @description Convert format to `link` or `block`
288
291
  * @param {HTMLElement} target Target element
289
- * @param {string} value 'link' or 'block'
292
+ * @param {string} value `link` or `block`
290
293
  */
291
294
  convertFormat(target, value) {
292
295
  if (value === 'link') {
@@ -299,14 +302,14 @@ class FileUpload extends EditorInjector {
299
302
  target.setAttribute('contenteditable', 'false');
300
303
  dom.utils.addClass(target, 'se-component|se-inline-component');
301
304
 
302
- const line = dom.utils.createElement(this.options.get('defaultLine'), null, target);
305
+ const line = dom.utils.createElement(this.$.options.get('defaultLine'), null, target);
303
306
  parent.insertBefore(line, next);
304
307
  dom.utils.removeItem(container);
305
308
  } else {
306
309
  // block
307
- this.selection.setRange(target, 0, target, 1);
308
- const r = this.html.remove();
309
- const s = this.nodeTransform.split(r.container, r.offset, 0);
310
+ this.$.selection.setRange(target, 0, target, 1);
311
+ const r = this.$.html.remove();
312
+ const s = this.$.nodeTransform.split(r.container, r.offset, 0);
310
313
 
311
314
  if (s?.previousElementSibling && dom.check.isZeroWidth(s.previousElementSibling)) {
312
315
  dom.utils.removeItem(s.previousElementSibling);
@@ -320,15 +323,15 @@ class FileUpload extends EditorInjector {
320
323
  (s || r.container).parentElement.insertBefore(figure.container, s);
321
324
  }
322
325
 
323
- this.history.push(false);
324
- this.component.select(target, FileUpload.key);
326
+ this.$.history.push(false);
327
+ this.$.component.select(target, FileUpload.key);
325
328
  }
326
329
 
327
330
  /**
328
331
  * @description Create file element
329
332
  * @param {string} url File URL
330
333
  * @param {File|{name: string, size: number}} file File object
331
- * @param {boolean} isLast Is last file
334
+ * @param {boolean} isLast Indicates whether this is the last file in the batch (used for scroll and insert actions).
332
335
  */
333
336
  create(url, file, isLast) {
334
337
  const name = file.name || url;
@@ -341,68 +344,66 @@ class FileUpload extends EditorInjector {
341
344
  'data-se-file-download': '',
342
345
  contenteditable: 'false',
343
346
  'data-se-non-focus': 'true',
344
- 'data-se-non-link': 'true'
347
+ 'data-se-non-link': 'true',
345
348
  },
346
- name
349
+ name,
347
350
  );
348
351
 
349
352
  this.fileManager.setFileData(a, file);
350
353
 
351
354
  if (this.as === 'link') {
352
355
  a.className = 'se-component se-inline-component';
353
- this.component.insert(a, { skipCharCount: false, skipSelection: false, skipHistory: false });
356
+ this.$.component.insert(a, { scrollTo: isLast ? true : false, insertBehavior: isLast ? this.insertBehavior : null });
354
357
  return;
355
358
  }
356
359
 
357
360
  const figure = Figure.CreateContainer(a);
358
361
  dom.utils.addClass(figure.container, 'se-file-figure|se-flex-component');
359
362
 
360
- if (!this.component.insert(figure.container, { skipCharCount: false, skipSelection: isLast ? !this.options.get('componentAutoSelect') : true, skipHistory: false })) {
361
- this.editor.focus();
363
+ if (!this.$.component.insert(figure.container, { scrollTo: isLast ? true : false, insertBehavior: isLast ? this.insertBehavior : null })) {
364
+ this.$.focusManager.focus();
362
365
  return;
363
366
  }
364
367
 
365
368
  if (!isLast) return;
366
369
 
367
- if (!this.options.get('componentAutoSelect')) {
368
- const line = this.format.addLine(figure.container, null);
369
- if (line) this.selection.setRange(line, 0, line, 0);
370
+ if (!this.$.options.get('componentInsertBehavior')) {
371
+ const line = this.$.format.addLine(figure.container, null);
372
+ if (line) this.$.selection.setRange(line, 0, line, 0);
370
373
  } else {
371
- this.component.select(a, FileUpload.key);
374
+ this.$.component.select(a, FileUpload.key);
372
375
  }
373
376
  }
374
377
 
375
378
  /**
376
- * @private
377
379
  * @description Processes the server response after file upload.
378
380
  * - Registers the uploaded files in the editor.
379
381
  * @param {Object<string, *>} response - The response object from the server.
380
382
  */
381
- _register(response) {
383
+ #register(response) {
382
384
  response.result.forEach((file, i, a) => {
383
385
  this.create(
384
386
  file.url,
385
387
  {
386
388
  name: file.name,
387
- size: file.size
389
+ size: file.size,
388
390
  },
389
- i === a.length - 1
391
+ i === a.length - 1,
390
392
  );
391
393
  });
392
394
  }
393
395
 
394
396
  /**
395
- * @private
396
397
  * @description Handles file upload errors.
397
398
  * - Displays an error message if the upload fails.
398
399
  * @param {Object<string, *>} response - The error response from the server.
399
400
  * @returns {Promise<void>}
400
401
  */
401
- async _error(response) {
402
- const message = await this.triggerEvent('onFileUploadError', { error: response });
402
+ async #error(response) {
403
+ const message = await this.$.eventManager.triggerEvent('onFileUploadError', { error: response });
403
404
  if (message === false) return;
404
405
  const err = message === NO_EVENT ? response.errorMessage : message || response.errorMessage;
405
- this.ui.alertOpen(err, 'error');
406
+ this.$.ui.alertOpen(err, 'error');
406
407
  console.error('[SUNEDITOR.plugin.fileUpload.error]', err);
407
408
  }
408
409
 
@@ -411,12 +412,12 @@ class FileUpload extends EditorInjector {
411
412
  * - Parses the response and registers the uploaded file.
412
413
  * @param {XMLHttpRequest} xmlHttp - The completed XHR request.
413
414
  */
414
- #_uploadCallBack(xmlHttp) {
415
+ #uploadCallBack(xmlHttp) {
415
416
  const response = JSON.parse(xmlHttp.responseText);
416
417
  if (response.errorMessage) {
417
- this._error(response);
418
+ this.#error(response);
418
419
  } else {
419
- this._register(response);
420
+ this.#register(response);
420
421
  }
421
422
  }
422
423
 
@@ -432,6 +433,10 @@ class FileUpload extends EditorInjector {
432
433
  }
433
434
  }
434
435
 
436
+ /**
437
+ * @param {SunEditor.Deps} $ - Kernel dependencies
438
+ * @returns {HTMLElement}
439
+ */
435
440
  function CreateHTML_controller({ lang, icons }) {
436
441
  const html = /*html*/ `
437
442
  <div class="se-arrow se-arrow-up"></div>