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
@@ -0,0 +1,1075 @@
1
+ import { dom, unicode, numbers } from '../../../helper';
2
+
3
+ /**
4
+ * @description Classes related to editor formats such as `line` and `block`.
5
+ */
6
+ class Format {
7
+ #$;
8
+ #store;
9
+ #options;
10
+ #frameContext;
11
+
12
+ #formatLineCheck;
13
+ #formatBrLineCheck;
14
+ #formatBlockCheck;
15
+ #formatClosureBlockCheck;
16
+ #formatClosureBrLineCheck;
17
+ #textStyleTagsCheck;
18
+
19
+ #brLineBreak = null;
20
+
21
+ /**
22
+ * @constructor
23
+ * @param {SunEditor.Kernel} kernel
24
+ */
25
+ constructor(kernel) {
26
+ this.#$ = kernel.$;
27
+ this.#store = kernel.store;
28
+
29
+ this.#options = this.#$.options;
30
+ this.#frameContext = this.#$.frameContext;
31
+
32
+ // members
33
+ this.#formatLineCheck = this.#options.get('formatLine').reg;
34
+ this.#formatBrLineCheck = this.#options.get('formatBrLine').reg;
35
+ this.#formatBlockCheck = this.#options.get('formatBlock').reg;
36
+ this.#formatClosureBlockCheck = this.#options.get('formatClosureBlock').reg;
37
+ this.#formatClosureBrLineCheck = this.#options.get('formatClosureBrLine').reg;
38
+ this.#textStyleTagsCheck = new RegExp('^(' + this.#options.get('textStyleTags') + ')$', 'i');
39
+
40
+ this.__resetBrLineBreak(this.#options.get('defaultLineBreakFormat'));
41
+ }
42
+
43
+ /**
44
+ * @description Replace the line tag of the current selection.
45
+ * @param {Node} element Line element (P, DIV..)
46
+ * @example
47
+ * // Replace the format tag of selected lines with H1
48
+ * const h1 = document.createElement('h1');
49
+ * editor.format.setLine(h1);
50
+ *
51
+ * // Replace the format tag of selected lines with DIV
52
+ * const div = document.createElement('div');
53
+ * editor.format.setLine(div);
54
+ */
55
+ setLine(element) {
56
+ if (!this.isLine(element)) {
57
+ throw new Error('[SUNEDITOR.format.setLine.fail] The "element" must satisfy "format.isLine()".');
58
+ }
59
+
60
+ const info = this.#lineWork();
61
+ const lines = info.lines;
62
+ const className = element.className;
63
+ const value = element.nodeName;
64
+ let first = info.firstNode;
65
+ let last = info.lastNode;
66
+
67
+ for (let i = 0, len = lines.length, node, newFormat; i < len; i++) {
68
+ node = lines[i];
69
+
70
+ if ((node.nodeName !== value || (node.className.match(/(\s|^)__se__format__[^\s]+/) || [''])[0].trim() !== className) && !this.#$.component.is(node)) {
71
+ newFormat = /** @type {HTMLElement} */ (element.cloneNode(false));
72
+ dom.utils.copyFormatAttributes(newFormat, node);
73
+ newFormat.innerHTML = node.innerHTML;
74
+
75
+ node.parentNode.replaceChild(newFormat, node);
76
+ }
77
+
78
+ if (i === 0) first = newFormat || node;
79
+ if (i === len - 1) last = newFormat || node;
80
+ newFormat = null;
81
+ }
82
+
83
+ this.#$.selection.setRange(dom.query.getNodeFromPath(info.firstPath, first), info.startOffset, dom.query.getNodeFromPath(info.lastPath, last), info.endOffset);
84
+ this.#$.history.push(false);
85
+
86
+ // document type
87
+ if (this.#frameContext.has('documentType_use_header')) {
88
+ this.#frameContext.get('documentType').reHeader();
89
+ }
90
+ }
91
+
92
+ /**
93
+ * @description If a parent node that contains an argument node finds a format node (`format.isLine`), it returns that node.
94
+ * @param {Node} node Reference node.
95
+ * @param {?(current: Node) => boolean} [validation] Additional validation function.
96
+ * @returns {HTMLElement|null}
97
+ */
98
+ getLine(node, validation) {
99
+ if (!node) return null;
100
+
101
+ validation ||= () => true;
102
+
103
+ while (node) {
104
+ if (dom.check.isWysiwygFrame(node)) return null;
105
+
106
+ if (this.isBlock(node)) {
107
+ if (this.isLine(node.firstElementChild)) {
108
+ return /** @type {HTMLElement} */ (node.firstElementChild);
109
+ }
110
+ if (this.isLine(node)) {
111
+ return /** @type {HTMLElement} */ (node);
112
+ }
113
+ }
114
+
115
+ if (this.isLine(node) && validation(node)) {
116
+ return /** @type {HTMLElement} */ (node);
117
+ }
118
+
119
+ node = node.parentNode;
120
+ }
121
+
122
+ return null;
123
+ }
124
+
125
+ /**
126
+ * @description Replace the br-line tag of the current selection.
127
+ * @param {Node} element BR-Line element (PRE..)
128
+ */
129
+ setBrLine(element) {
130
+ if (!this.isBrLine(element)) {
131
+ throw new Error('[SUNEDITOR.format.setBrLine.fail] The "element" must satisfy "format.isBrLine()".');
132
+ }
133
+
134
+ const lines = this.#lineWork().lines;
135
+ const len = lines.length - 1;
136
+ let parentNode = lines[len].parentNode;
137
+ let freeElement = /** @type {HTMLElement} */ (element.cloneNode(false));
138
+ const focusElement = freeElement;
139
+
140
+ for (let i = len, f, html, before, next, inner, isComp, first = true; i >= 0; i--) {
141
+ f = lines[i];
142
+ if (f === (!lines[i + 1] ? null : lines[i + 1].parentNode)) continue;
143
+
144
+ isComp = this.#$.component.is(f);
145
+ html = isComp ? '' : f.innerHTML.replace(/(?!>)\s+(?=<)|\n/g, ' ');
146
+ before = dom.query.getParentElement(f, (current) => current.parentNode === parentNode);
147
+
148
+ if (parentNode !== f.parentNode || isComp) {
149
+ if (this.isLine(parentNode)) {
150
+ parentNode.parentNode.insertBefore(freeElement, parentNode.nextSibling);
151
+ parentNode = parentNode.parentNode;
152
+ } else {
153
+ parentNode.insertBefore(freeElement, before ? before.nextSibling : null);
154
+ parentNode = f.parentNode;
155
+ }
156
+
157
+ next = /** @type {HTMLElement} */ (freeElement.nextSibling);
158
+ if (next && freeElement.nodeName === next.nodeName && dom.check.isSameAttributes(freeElement, next)) {
159
+ freeElement.innerHTML += '<BR>' + next.innerHTML;
160
+ dom.utils.removeItem(next);
161
+ }
162
+
163
+ freeElement = /** @type {HTMLElement} */ (element.cloneNode(false));
164
+ first = true;
165
+ }
166
+
167
+ inner = freeElement.innerHTML;
168
+ freeElement.innerHTML = (first || !html || !inner || /<br>$/i.test(html) ? html : html + '<BR>') + inner;
169
+
170
+ if (i === 0) {
171
+ parentNode.insertBefore(freeElement, f);
172
+ next = /** @type {HTMLElement} */ (f.nextSibling);
173
+ if (next && freeElement.nodeName === next.nodeName && dom.check.isSameAttributes(freeElement, next)) {
174
+ freeElement.innerHTML += '<BR>' + next.innerHTML;
175
+ dom.utils.removeItem(next);
176
+ }
177
+
178
+ const prev = /** @type {HTMLElement} */ (freeElement.previousSibling);
179
+ if (prev && freeElement.nodeName === prev.nodeName && dom.check.isSameAttributes(freeElement, prev)) {
180
+ prev.innerHTML += '<BR>' + freeElement.innerHTML;
181
+ dom.utils.removeItem(freeElement);
182
+ }
183
+ }
184
+
185
+ if (!isComp) dom.utils.removeItem(f);
186
+ if (html) first = false;
187
+ }
188
+
189
+ this.#$.selection.setRange(focusElement, 0, focusElement, 0);
190
+ this.#$.history.push(false);
191
+ }
192
+
193
+ /**
194
+ * @description If a parent node that contains an argument node finds a `brLine` (`format.isBrLine`), it returns that node.
195
+ * @param {Node} element Reference node.
196
+ * @param {?(current: Node) => boolean} [validation] Additional validation function.
197
+ * @returns {HTMLBRElement|null}
198
+ */
199
+ getBrLine(element, validation) {
200
+ if (!element) return null;
201
+
202
+ validation ||= () => true;
203
+
204
+ while (element) {
205
+ if (dom.check.isWysiwygFrame(element)) return null;
206
+ if (this.isBrLine(element) && validation(element)) return /** @type {HTMLBRElement} */ (element);
207
+
208
+ element = element.parentNode;
209
+ }
210
+
211
+ return null;
212
+ }
213
+
214
+ /**
215
+ * @description Append `line` element to sibling node of argument element.
216
+ * - If the `lineNode` argument value is present, the tag of that argument value is inserted,
217
+ * - If not, the currently selected format tag is inserted.
218
+ * @param {Node} element Insert as siblings of that element
219
+ * @param {?(string|Node)} [lineNode] Node name or node obejct to be inserted
220
+ * @returns {HTMLElement}
221
+ */
222
+ addLine(element, lineNode) {
223
+ if (!element || !element.parentNode) return null;
224
+
225
+ const currentFormatEl = this.getLine(this.#$.selection.getNode(), null);
226
+ let oFormat = null;
227
+ if (!this.isBrLine(element) && this.isBrLine(currentFormatEl || element.parentNode) && !this.#$.component.is(element)) {
228
+ oFormat = dom.utils.createElement('BR');
229
+ } else {
230
+ const oFormatName = lineNode ? (typeof lineNode === 'string' ? lineNode : lineNode.nodeName) : this.isNormalLine(currentFormatEl) ? currentFormatEl.nodeName : this.#options.get('defaultLine');
231
+ oFormat = dom.utils.createElement(oFormatName, null, '<br>');
232
+ if ((lineNode && typeof lineNode !== 'string') || (!lineNode && this.isLine(currentFormatEl))) {
233
+ dom.utils.copyTagAttributes(oFormat, /** @type {Node} */ (lineNode || currentFormatEl), ['id']);
234
+ }
235
+ }
236
+
237
+ if (dom.check.isTableCell(element)) element.insertBefore(oFormat, element.nextElementSibling);
238
+ else element.parentNode.insertBefore(oFormat, /** @type {HTMLElement} */ (element).nextElementSibling);
239
+
240
+ return oFormat;
241
+ }
242
+
243
+ /**
244
+ * @description If a parent node that contains an argument node finds a format node (`format.isBlock`), it returns that node.
245
+ * @param {Node} element Reference node.
246
+ * @param {?(current: Node) => boolean} [validation] Additional validation function.
247
+ * @returns {HTMLElement|null}
248
+ */
249
+ getBlock(element, validation) {
250
+ if (!element) return null;
251
+
252
+ validation ||= () => true;
253
+
254
+ while (element) {
255
+ if (dom.check.isWysiwygFrame(element)) return null;
256
+ if (this.isBlock(element) && !/^(THEAD|TBODY|TR)$/i.test(element.nodeName) && validation(element)) return element;
257
+ element = element.parentNode;
258
+ }
259
+
260
+ return null;
261
+ }
262
+
263
+ /**
264
+ * @description Appended all selected `line` element to the argument element(`block`) and insert
265
+ * @param {Node} blockElement Element of wrap the arguments (BLOCKQUOTE...)
266
+ * @example
267
+ * // Wrap selected lines in a blockquote
268
+ * const blockquote = document.createElement('blockquote');
269
+ * editor.format.applyBlock(blockquote);
270
+ */
271
+ applyBlock(blockElement) {
272
+ this.#$.selection.getRangeAndAddLine(this.#$.selection.getRange(), null);
273
+ const rangeLines = /** @type {Element[]} */ (this.getLinesAndComponents(false));
274
+ if (!rangeLines || rangeLines.length === 0) return;
275
+
276
+ linesLoop: for (let i = 0, len = rangeLines.length, line, nested, fEl, lEl, f, l; i < len; i++) {
277
+ line = rangeLines[i];
278
+ if (!dom.check.isListCell(line)) continue;
279
+
280
+ nested = line.lastElementChild;
281
+ if (nested && dom.check.isListCell(line.nextElementSibling) && rangeLines.includes(line.nextElementSibling)) {
282
+ lEl = nested.lastElementChild;
283
+ if (rangeLines.includes(lEl)) {
284
+ let list = null;
285
+ while ((list = lEl.lastElementChild)) {
286
+ if (dom.check.isList(list)) {
287
+ if (rangeLines.includes(list.lastElementChild)) {
288
+ lEl = list.lastElementChild;
289
+ } else {
290
+ continue linesLoop;
291
+ }
292
+ }
293
+ }
294
+
295
+ fEl = nested.firstElementChild;
296
+ f = rangeLines.indexOf(fEl);
297
+ l = rangeLines.indexOf(lEl);
298
+ rangeLines.splice(f, l - f + 1);
299
+ len = rangeLines.length;
300
+ continue;
301
+ }
302
+ }
303
+ }
304
+
305
+ const last = rangeLines.at(-1);
306
+ let standTag, beforeTag, pElement;
307
+
308
+ if (this.isBlock(last) || this.isLine(last)) {
309
+ standTag = last;
310
+ } else {
311
+ standTag = this.getBlock(last, null) || this.getLine(last, null);
312
+ }
313
+
314
+ if (dom.check.isTableCell(standTag)) {
315
+ beforeTag = null;
316
+ pElement = standTag;
317
+ } else {
318
+ beforeTag = standTag.nextSibling;
319
+ pElement = standTag.parentNode;
320
+ }
321
+
322
+ const block = /** @type {HTMLElement} */ (blockElement.cloneNode(false));
323
+ let parentDepth = dom.query.getNodeDepth(standTag);
324
+ let listParent = null;
325
+ const lineArr = [];
326
+ const removeItems = (parent, origin, before) => {
327
+ let cc = null;
328
+ if (parent !== origin && !dom.check.isTableElements(origin)) {
329
+ if (origin && dom.query.getNodeDepth(parent) === dom.query.getNodeDepth(origin)) return before;
330
+ cc = this.#$.nodeTransform.removeAllParents(origin, null, parent);
331
+ }
332
+
333
+ return cc ? cc.ec : before;
334
+ };
335
+
336
+ for (let i = 0, len = rangeLines.length, line, originParent, depth, before, nextLine, nextList, nested; i < len; i++) {
337
+ line = rangeLines[i];
338
+ originParent = line.parentNode;
339
+ if (!originParent || block.contains(originParent)) continue;
340
+
341
+ depth = dom.query.getNodeDepth(line);
342
+
343
+ if (dom.check.isList(originParent)) {
344
+ if (listParent === null) {
345
+ if (nextList) {
346
+ listParent = nextList;
347
+ nested = true;
348
+ nextList = null;
349
+ } else {
350
+ listParent = originParent.cloneNode(false);
351
+ }
352
+ }
353
+
354
+ lineArr.push(line);
355
+ nextLine = rangeLines[i + 1];
356
+
357
+ if (i === len - 1 || nextLine?.parentNode !== originParent) {
358
+ // nested list
359
+ if (line.contains(nextLine?.parentNode)) {
360
+ nextList = nextLine.parentNode.cloneNode(false);
361
+ }
362
+
363
+ let list = originParent.parentNode,
364
+ p;
365
+ while (dom.check.isList(list)) {
366
+ p = dom.utils.createElement(list.nodeName);
367
+ p.appendChild(listParent);
368
+ listParent = p;
369
+ list = list.parentNode;
370
+ }
371
+
372
+ const edge = this.removeBlock(originParent, { selectedFormats: lineArr, newBlockElement: null, shouldDelete: true, skipHistory: true });
373
+
374
+ if (parentDepth >= depth) {
375
+ parentDepth = depth;
376
+ pElement = edge.cc;
377
+ beforeTag = removeItems(pElement, originParent, edge.ec);
378
+ if (beforeTag) pElement = beforeTag.parentNode;
379
+ } else if (pElement === edge.cc) {
380
+ beforeTag = edge.ec;
381
+ }
382
+
383
+ if (pElement !== edge.cc) {
384
+ before = removeItems(pElement, edge.cc, before);
385
+ if (before !== undefined) beforeTag = before;
386
+ else beforeTag = edge.cc;
387
+ }
388
+
389
+ for (let c = 0, cLen = edge.removeArray.length; c < cLen; c++) {
390
+ listParent.appendChild(edge.removeArray[c]);
391
+ }
392
+
393
+ if (!nested) block.appendChild(listParent);
394
+ if (nextList) edge.removeArray.at(-1).appendChild(nextList);
395
+ listParent = null;
396
+ nested = false;
397
+ }
398
+ } else {
399
+ if (parentDepth >= depth) {
400
+ parentDepth = depth;
401
+ pElement = originParent;
402
+ beforeTag = line.nextSibling;
403
+ }
404
+
405
+ block.appendChild(line);
406
+
407
+ if (pElement !== originParent) {
408
+ before = removeItems(pElement, originParent);
409
+ if (before !== undefined) beforeTag = before;
410
+ }
411
+ }
412
+ }
413
+
414
+ this.#store.set('_lastSelectionNode', null);
415
+ this.#$.nodeTransform.mergeSameTags(block, null, false);
416
+ this.#$.nodeTransform.mergeNestedTags(block, (current) => dom.check.isList(current));
417
+
418
+ // Nested list
419
+ if (beforeTag && dom.query.getNodeDepth(beforeTag) > 0 && (dom.check.isList(beforeTag.parentNode) || dom.check.isList(beforeTag.parentNode.parentNode))) {
420
+ const depthFormat = dom.query.getParentElement(beforeTag, (current) => this.isBlock(current) && !dom.check.isList(current));
421
+ const splitRange = this.#$.nodeTransform.split(beforeTag, null, !depthFormat ? 0 : dom.query.getNodeDepth(depthFormat) + 1);
422
+ splitRange.parentNode.insertBefore(block, splitRange);
423
+ } else {
424
+ // basic
425
+ pElement.insertBefore(block, beforeTag);
426
+ removeItems(block, beforeTag);
427
+ }
428
+
429
+ const edge = dom.query.getEdgeChildNodes(block.firstElementChild, block.lastElementChild);
430
+ if (rangeLines.length > 1) {
431
+ this.#$.selection.setRange(edge.sc, 0, edge.ec, edge.ec.textContent.length);
432
+ } else {
433
+ this.#$.selection.setRange(edge.ec, edge.ec.textContent.length, edge.ec, edge.ec.textContent.length);
434
+ }
435
+
436
+ this.#$.history.push(false);
437
+ }
438
+
439
+ /**
440
+ * @description The elements of the `selectedFormats` array are detached from the `blockElement` element. (`LI` tags are converted to `P` tags)
441
+ * - When `selectedFormats` is `null`, all elements are detached and return {cc: parentNode, sc: nextSibling, ec: previousSibling, removeArray: [Array of removed elements]}.
442
+ * @param {Node} blockElement `block` element (PRE, BLOCKQUOTE, OL, UL...)
443
+ * @param {Object} [options] Options
444
+ * @param {Array<Node>} [options.selectedFormats=null] Array of `line` elements (P, DIV, LI...) to remove.
445
+ * - If `null`, Applies to all elements and return {cc: parentNode, sc: nextSibling, ec: previousSibling}
446
+ * @param {Node} [options.newBlockElement=null] The node(`blockElement`) to replace the currently wrapped node.
447
+ * @param {boolean} [options.shouldDelete=false] If `true`, deleted without detached.
448
+ * @param {boolean} [options.skipHistory=false] When `true`, it does not update the history stack and the selection object and return `EdgeNodes` (dom-query-GetEdgeChildNodes)
449
+ * @returns {{cc: Node, sc: Node, so: number, ec: Node, eo: number, removeArray: ?Array<Node>}} Node information after deletion
450
+ * - cc: Common parent container node
451
+ * - sc: Start container node
452
+ * - so: Start offset
453
+ * - ec: End container node
454
+ * - eo: End offset
455
+ * - removeArray: Array of removed elements
456
+ * @example
457
+ * // Remove all list items from a list
458
+ * const listElement = editor.selection.getNode().closest('ul');
459
+ * editor.format.removeBlock(listElement);
460
+ *
461
+ * // Remove specific list items only
462
+ * const selectedItems = [liElement1, liElement2];
463
+ * editor.format.removeBlock(listElement, { selectedFormats: selectedItems });
464
+ *
465
+ * // Replace blockquote with div
466
+ * const blockquote = editor.selection.getNode().closest('blockquote');
467
+ * const newDiv = document.createElement('div');
468
+ * editor.format.removeBlock(blockquote, { newBlockElement: newDiv });
469
+ */
470
+ removeBlock(blockElement, { selectedFormats, newBlockElement, shouldDelete, skipHistory } = {}) {
471
+ const range = this.#$.selection.getRange();
472
+ let so = range.startOffset;
473
+ let eo = range.endOffset;
474
+
475
+ let children = dom.query.getListChildNodes(blockElement, null, 1);
476
+ let parent = blockElement.parentNode;
477
+ let firstNode = null;
478
+ let lastNode = null;
479
+ let rangeEl = /** @type {HTMLElement} */ (blockElement.cloneNode(false));
480
+
481
+ const removeArray = [];
482
+ const newList = dom.check.isList(newBlockElement);
483
+ let insertedNew = false;
484
+ let reset = false;
485
+ let moveComplete = false;
486
+
487
+ const appendNode = (parentEl, insNode, sibling, originNode) => {
488
+ if (insNode.childNodes.length === 1 && dom.check.isZeroWidth(insNode)) {
489
+ insNode.innerHTML = unicode.zeroWidthSpace;
490
+ so = eo = 1;
491
+ }
492
+
493
+ if (insNode.nodeType === 3) {
494
+ parentEl.insertBefore(insNode, sibling);
495
+ return insNode;
496
+ }
497
+
498
+ const insChildren = (moveComplete ? insNode : originNode).childNodes;
499
+ let format = insNode.cloneNode(false);
500
+ let first = null;
501
+ let c = null;
502
+
503
+ while (insChildren[0]) {
504
+ c = insChildren[0];
505
+ if (this._isNotTextNode(c) && !dom.check.isBreak(c) && !dom.check.isListCell(format)) {
506
+ if (format.childNodes.length > 0) {
507
+ first ||= format;
508
+ parentEl.insertBefore(format, sibling);
509
+ format = insNode.cloneNode(false);
510
+ }
511
+ parentEl.insertBefore(c, sibling);
512
+ first ||= c;
513
+ } else {
514
+ format.appendChild(c);
515
+ }
516
+ }
517
+
518
+ if (format.childNodes.length > 0) {
519
+ if (dom.check.isListCell(parentEl) && dom.check.isListCell(format) && dom.check.isList(sibling)) {
520
+ if (newList) {
521
+ first = sibling;
522
+ while (sibling) {
523
+ format.appendChild(sibling);
524
+ sibling = sibling.nextSibling;
525
+ }
526
+ parentEl.parentNode.insertBefore(format, parentEl.nextElementSibling);
527
+ } else {
528
+ const originNext = originNode.nextElementSibling;
529
+ const detachRange = this.#$.listFormat.removeNested(originNode, false);
530
+ if (blockElement !== detachRange || originNext !== originNode.nextElementSibling) {
531
+ const fChildren = format.childNodes;
532
+ while (fChildren[0]) {
533
+ originNode.appendChild(fChildren[0]);
534
+ }
535
+
536
+ blockElement = detachRange;
537
+ reset = true;
538
+ }
539
+ }
540
+ } else {
541
+ parentEl.insertBefore(format, sibling);
542
+ }
543
+
544
+ first ||= format;
545
+ }
546
+
547
+ return first;
548
+ };
549
+
550
+ // detach loop
551
+ for (let i = 0, len = children.length, insNode, lineIndex, next; i < len; i++) {
552
+ insNode = children[i];
553
+ if (insNode.nodeType === 3 && dom.check.isList(rangeEl)) continue;
554
+
555
+ moveComplete = false;
556
+ if (shouldDelete && i === 0) {
557
+ if (!selectedFormats || selectedFormats.length === len || selectedFormats[0] === insNode) {
558
+ firstNode = blockElement.previousSibling;
559
+ } else {
560
+ firstNode = rangeEl;
561
+ }
562
+ }
563
+
564
+ if (selectedFormats) lineIndex = selectedFormats.indexOf(insNode);
565
+ if (selectedFormats && lineIndex === -1) {
566
+ rangeEl ||= /** @type {HTMLElement} */ (blockElement.cloneNode(false));
567
+ rangeEl.appendChild(insNode);
568
+ } else {
569
+ if (selectedFormats) next = selectedFormats[lineIndex + 1];
570
+ if (rangeEl && rangeEl.children.length > 0) {
571
+ parent.insertBefore(rangeEl, blockElement);
572
+ rangeEl = null;
573
+ }
574
+
575
+ if (!newList && dom.check.isListCell(insNode)) {
576
+ if (next && dom.query.getNodeDepth(insNode) !== dom.query.getNodeDepth(next) && (dom.check.isListCell(parent) || dom.utils.arrayFind(insNode.children, dom.check.isList))) {
577
+ const insNext = insNode.nextElementSibling;
578
+ const detachRange = this.#$.listFormat.removeNested(insNode, false);
579
+ if (blockElement !== detachRange || insNext !== insNode.nextElementSibling) {
580
+ blockElement = detachRange;
581
+ reset = true;
582
+ }
583
+ } else {
584
+ const inner = insNode;
585
+ insNode = dom.utils.createElement(
586
+ shouldDelete
587
+ ? inner.nodeName
588
+ : dom.check.isList(blockElement.parentNode) || dom.check.isListCell(blockElement.parentNode)
589
+ ? 'LI'
590
+ : dom.check.isTableCell(blockElement.parentNode)
591
+ ? 'DIV'
592
+ : this.#options.get('defaultLine'),
593
+ );
594
+ const isCell = dom.check.isListCell(insNode);
595
+ const innerChildren = inner.childNodes;
596
+ while (innerChildren[0]) {
597
+ if (dom.check.isList(innerChildren[0]) && !isCell) break;
598
+ insNode.appendChild(innerChildren[0]);
599
+ }
600
+ dom.utils.copyFormatAttributes(insNode, inner);
601
+ moveComplete = true;
602
+ }
603
+ } else {
604
+ insNode = insNode.cloneNode(false);
605
+ }
606
+
607
+ if (!reset) {
608
+ if (!shouldDelete) {
609
+ if (newBlockElement) {
610
+ if (!insertedNew) {
611
+ parent.insertBefore(newBlockElement, blockElement);
612
+ insertedNew = true;
613
+ }
614
+ insNode = appendNode(newBlockElement, insNode, null, children[i]);
615
+ } else {
616
+ insNode = appendNode(parent, insNode, blockElement, children[i]);
617
+ }
618
+
619
+ if (!reset) {
620
+ if (selectedFormats) {
621
+ lastNode = insNode;
622
+ firstNode ||= insNode;
623
+ } else if (!firstNode) {
624
+ firstNode = lastNode = insNode;
625
+ }
626
+ }
627
+ } else {
628
+ removeArray.push(insNode);
629
+ dom.utils.removeItem(children[i]);
630
+ }
631
+
632
+ if (reset) {
633
+ reset = moveComplete = false;
634
+ children = dom.query.getListChildNodes(blockElement, null, 1);
635
+ rangeEl = /** @type {HTMLElement} */ (blockElement.cloneNode(false));
636
+ parent = blockElement.parentNode;
637
+ i = -1;
638
+ len = children.length;
639
+ continue;
640
+ }
641
+ }
642
+ }
643
+ }
644
+
645
+ const rangeParent = blockElement.parentNode;
646
+ let rangeRight = blockElement.nextSibling;
647
+ if (rangeEl?.children.length > 0) {
648
+ rangeParent.insertBefore(rangeEl, rangeRight);
649
+ }
650
+
651
+ if (newBlockElement) firstNode = newBlockElement.previousSibling;
652
+ else firstNode ||= blockElement.previousSibling;
653
+ rangeRight = blockElement.nextSibling !== rangeEl ? blockElement.nextSibling : rangeEl ? rangeEl.nextSibling : null;
654
+
655
+ if (/** @type {HTMLElement} */ (blockElement).children.length === 0 || blockElement.textContent.length === 0) {
656
+ dom.utils.removeItem(blockElement);
657
+ } else {
658
+ this.#$.nodeTransform.removeEmptyNode(blockElement, null, false);
659
+ }
660
+
661
+ let edge = null;
662
+ this.#store.set('_lastSelectionNode', null);
663
+
664
+ if (shouldDelete) {
665
+ edge = {
666
+ cc: rangeParent,
667
+ sc: firstNode,
668
+ so: so,
669
+ ec: rangeRight,
670
+ eo: eo,
671
+ removeArray: removeArray,
672
+ };
673
+ } else {
674
+ firstNode ||= lastNode;
675
+ lastNode ||= firstNode;
676
+ const childEdge = dom.query.getEdgeChildNodes(firstNode, lastNode?.parentNode ? firstNode : lastNode);
677
+ if (!childEdge) {
678
+ this.#$.focusManager.focus();
679
+ } else {
680
+ edge = {
681
+ cc: (childEdge.sc || childEdge.ec).parentNode,
682
+ sc: childEdge.sc,
683
+ so: so,
684
+ ec: childEdge.ec,
685
+ eo: eo,
686
+ removeArray: null,
687
+ };
688
+ }
689
+ }
690
+
691
+ if (skipHistory) return edge;
692
+
693
+ if (!shouldDelete && edge) {
694
+ if (!selectedFormats) {
695
+ this.#$.selection.setRange(edge.sc, 0, edge.sc, 0);
696
+ } else {
697
+ this.#$.selection.setRange(edge.sc, so, edge.ec, eo);
698
+ }
699
+ }
700
+
701
+ this.#$.history.push(false);
702
+ }
703
+
704
+ /**
705
+ * @description Indent more the selected lines.
706
+ * - margin size : `store.get('indentSize')`
707
+ */
708
+ indent() {
709
+ const range = this.#$.selection.getRange();
710
+ const sc = range.startContainer;
711
+ const ec = range.endContainer;
712
+ const so = range.startOffset;
713
+ const eo = range.endOffset;
714
+
715
+ const lines = this.getLines(null);
716
+ const cells = SetLineMargin(lines, this.#store.get('indentSize'), this.#options.get('_rtl') ? 'marginRight' : 'marginLeft');
717
+
718
+ // list cells
719
+ if (cells.length > 0) {
720
+ this.#$.listFormat.applyNested(cells, false);
721
+ }
722
+
723
+ this.#store.set('_lastSelectionNode', null);
724
+ this.#$.selection.setRange(sc, so, ec, eo);
725
+ this.#$.history.push(false);
726
+ }
727
+
728
+ /**
729
+ * @description Indent less the selected lines.
730
+ * - margin size - `store.get('indentSize')`
731
+ */
732
+ outdent() {
733
+ const range = this.#$.selection.getRange();
734
+ const sc = range.startContainer;
735
+ const ec = range.endContainer;
736
+ const so = range.startOffset;
737
+ const eo = range.endOffset;
738
+
739
+ const lines = this.getLines(null);
740
+ const cells = SetLineMargin(lines, this.#store.get('indentSize') * -1, this.#options.get('_rtl') ? 'marginRight' : 'marginLeft');
741
+
742
+ // list cells
743
+ if (cells.length > 0) {
744
+ this.#$.listFormat.applyNested(cells, true);
745
+ }
746
+
747
+ this.#store.set('_lastSelectionNode', null);
748
+ this.#$.selection.setRange(sc, so, ec, eo);
749
+ this.#$.history.push(false);
750
+ }
751
+
752
+ /**
753
+ * @description Check if the container and offset values are the edges of the `line`
754
+ * @param {Node} node The node of the selection object. (range.startContainer..)
755
+ * @param {number} offset The offset of the selection object. (selection.getRange().startOffset...)
756
+ * @param {"front"|"end"} dir Select check point - `front`: Front edge, `end`: End edge, `undefined`: Both edge.
757
+ * @returns {node is HTMLElement}
758
+ */
759
+ isEdgeLine(node, offset, dir) {
760
+ if (!dom.check.isEdgePoint(node, offset, dir)) return false;
761
+
762
+ let result = false;
763
+ const siblingType = dir === 'front' ? 'previousSibling' : 'nextSibling';
764
+ while (node && !this.isLine(node) && !dom.check.isWysiwygFrame(node)) {
765
+ if (!node[siblingType] || (dom.check.isBreak(node[siblingType]) && !node[siblingType][siblingType])) {
766
+ result = true;
767
+ node = node.parentNode;
768
+ } else {
769
+ return false;
770
+ }
771
+ }
772
+
773
+ return result;
774
+ }
775
+
776
+ /**
777
+ * @description It is judged whether it is a node related to the text style.
778
+ * @param {Node|string} element The node to check
779
+ * @returns {element is HTMLElement}
780
+ */
781
+ isTextStyleNode(element) {
782
+ return typeof element === 'string' ? this.#textStyleTagsCheck.test(element) : element?.nodeType === 1 && this.#textStyleTagsCheck.test(element.nodeName);
783
+ }
784
+
785
+ /**
786
+ * @description It is judged whether it is the `line` element.
787
+ * - (P, DIV, H[1-6], PRE, LI | class=`__se__format__line_xxx`)
788
+ * - `line` element also contain `brLine` element
789
+ * @param {Node|string} element The node to check
790
+ * @returns {element is HTMLElement}
791
+ */
792
+ isLine(element) {
793
+ return typeof element === 'string'
794
+ ? this.#formatLineCheck.test(element)
795
+ : element?.nodeType === 1 && (this.#formatLineCheck.test(element.nodeName) || dom.utils.hasClass(element, '__se__format__line_.+|__se__format__br_line_.+')) && !this.#nonFormat(element);
796
+ }
797
+
798
+ /**
799
+ * @description It is judged whether it is the only `line` element.
800
+ * @param {Node|string} element The node to check
801
+ * @returns {element is HTMLElement}
802
+ */
803
+ isNormalLine(element) {
804
+ return this.isLine(element) && (this.#brLineBreak || !this.isBrLine(element)) && !this.isBlock(element);
805
+ }
806
+
807
+ /**
808
+ * @description It is judged whether it is the `brLine` element.
809
+ * - (PRE | class=`__se__format__br_line_xxx`)
810
+ * - `brLine` elements is included in the `line` element.
811
+ * - `brLine` elements's line break is `BR` tag.
812
+ * ※ Entering the Enter key in the space on the last line ends `brLine` and appends `line`.
813
+ * @param {Node|string} element The node to check
814
+ * @returns {element is HTMLElement}
815
+ */
816
+ isBrLine(element) {
817
+ return (
818
+ (this.#brLineBreak && this.isLine(element)) ||
819
+ (typeof element === 'string'
820
+ ? this.#formatBrLineCheck.test(element)
821
+ : element?.nodeType === 1 && (this.#formatBrLineCheck.test(element.nodeName) || dom.utils.hasClass(element, '__se__format__br_line_.+')) && !this.#nonFormat(element))
822
+ );
823
+ }
824
+
825
+ /**
826
+ * @description It is judged whether it is the `block` element.
827
+ * - (BLOCKQUOTE, OL, UL, FIGCAPTION, TABLE, THEAD, TBODY, TR, TH, TD | class=`__se__format__block_xxx`)
828
+ * - `block` is wrap the `line` and `component`
829
+ * @param {Node|string} element The node to check
830
+ * @returns {element is HTMLElement}
831
+ */
832
+ isBlock(element) {
833
+ return typeof element === 'string'
834
+ ? this.#formatBlockCheck.test(element)
835
+ : element?.nodeType === 1 && (this.#formatBlockCheck.test(element.nodeName) || dom.utils.hasClass(element, '__se__format__block_.+')) && !this.#nonFormat(element);
836
+ }
837
+
838
+ /**
839
+ * @description It is judged whether it is the `closureBlock` element.
840
+ * - (TH, TD | class=`__se__format__block_closure_xxx`)
841
+ * - `closureBlock` elements is included in the `block`.
842
+ * - `closureBlock` element is wrap the `line` and `component`
843
+ * - ※ You cannot exit this format with the Enter key or Backspace key.
844
+ * - ※ Use it only in special cases. ([ex] format of table cells)
845
+ * @param {Node|string} element The node to check
846
+ * @returns {element is HTMLElement}
847
+ */
848
+ isClosureBlock(element) {
849
+ return typeof element === 'string'
850
+ ? this.#formatClosureBlockCheck.test(element)
851
+ : element?.nodeType === 1 && (this.#formatClosureBlockCheck.test(element.nodeName) || dom.utils.hasClass(element, '__se__format__block_closure_.+')) && !this.#nonFormat(element);
852
+ }
853
+
854
+ /**
855
+ * @description It is judged whether it is the `closureBrLine` element.
856
+ * - (class=`__se__format__br_line__closure_xxx`)
857
+ * - `closureBrLine` elements is included in the `brLine`.
858
+ * - `closureBrLine` elements's line break is `BR` tag.
859
+ * - ※ You cannot exit this format with the Enter key or Backspace key.
860
+ * - ※ Use it only in special cases. ([ex] format of table cells)
861
+ * @param {Node|string} element The node to check
862
+ * @returns {element is HTMLElement}
863
+ */
864
+ isClosureBrLine(element) {
865
+ return typeof element === 'string'
866
+ ? this.#formatClosureBrLineCheck.test(element)
867
+ : element?.nodeType === 1 && (this.#formatClosureBrLineCheck.test(element.nodeName) || dom.utils.hasClass(element, '__se__format__br_line__closure_.+')) && !this.#nonFormat(element);
868
+ }
869
+
870
+ /**
871
+ * @description Returns a `line` array from selected range.
872
+ * @param {?(current: Node) => boolean} [validation] The validation function. (Replaces the default validation `format.isLine(current)`)
873
+ * @returns {Array<HTMLElement>}
874
+ */
875
+ getLines(validation) {
876
+ if (!this.#$.selection.resetRangeToTextNode()) return [];
877
+ let range = this.#$.selection.getRange();
878
+
879
+ if (dom.check.isWysiwygFrame(range.startContainer)) {
880
+ const children = this.#frameContext.get('wysiwyg').children;
881
+ const childrenLen = children.length;
882
+ if (childrenLen === 0) return [];
883
+
884
+ this.#$.selection.setRange(children[0], 0, children[childrenLen - 1], children[childrenLen - 1].textContent.trim().length);
885
+ range = this.#$.selection.getRange();
886
+ }
887
+
888
+ const startCon = range.startContainer;
889
+ const endCon = range.endContainer;
890
+ const commonCon = range.commonAncestorContainer;
891
+
892
+ // get line nodes
893
+ validation ||= this.isLine.bind(this);
894
+ const lineNodes = dom.query.getListChildren(commonCon, (current) => validation(current), null);
895
+
896
+ if (commonCon.nodeType === 3 || (!dom.check.isWysiwygFrame(commonCon) && !this.isBlock(commonCon))) lineNodes.unshift(this.getLine(commonCon, null));
897
+ if (startCon === endCon || lineNodes.length === 1) return lineNodes;
898
+
899
+ const startLine = this.getLine(startCon, null);
900
+ const endLine = this.getLine(endCon, null);
901
+ let startIdx = null;
902
+ let endIdx = null;
903
+
904
+ const onlyTable = function (current) {
905
+ return dom.check.isTableElements(current) ? /^TABLE$/i.test(current.nodeName) : true;
906
+ };
907
+
908
+ let startRangeEl = this.getBlock(startLine, onlyTable);
909
+ let endRangeEl = this.getBlock(endLine, onlyTable);
910
+ if (dom.check.isTableElements(startRangeEl) && dom.check.isListCell(startRangeEl.parentNode)) startRangeEl = startRangeEl.parentNode;
911
+ if (dom.check.isTableElements(endRangeEl) && dom.check.isListCell(endRangeEl.parentNode)) endRangeEl = endRangeEl.parentNode;
912
+
913
+ const sameRange = startRangeEl === endRangeEl;
914
+ for (let i = 0, len = lineNodes.length, line; i < len; i++) {
915
+ line = lineNodes[i];
916
+
917
+ if (startLine === line || (!sameRange && line === startRangeEl)) {
918
+ startIdx = i;
919
+ continue;
920
+ }
921
+
922
+ if (endLine === line || (!sameRange && line === endRangeEl)) {
923
+ endIdx = i;
924
+ break;
925
+ }
926
+ }
927
+
928
+ if (startIdx === null) startIdx = 0;
929
+ if (endIdx === null) endIdx = lineNodes.length - 1;
930
+
931
+ return lineNodes.slice(startIdx, endIdx + 1);
932
+ }
933
+
934
+ /**
935
+ * @description Get lines and components from the selected range. (P, DIV, H[1-6], OL, UL, TABLE..)
936
+ * - If some of the component are included in the selection, get the entire that component.
937
+ * @param {boolean} removeDuplicate If `true`, if there is a parent and child tag among the selected elements, the child tag is excluded.
938
+ * @returns {Array<HTMLElement>}
939
+ */
940
+ getLinesAndComponents(removeDuplicate) {
941
+ const commonCon = this.#$.selection.getRange().commonAncestorContainer;
942
+ const myComponent = dom.query.getParentElement(commonCon, this.#$.component.is.bind(this.#$.component));
943
+ const selectedLines = dom.check.isTableElements(commonCon)
944
+ ? this.getLines(null)
945
+ : this.getLines((current) => {
946
+ const component = dom.query.getParentElement(current, this.#$.component.is.bind(this.#$.component));
947
+ return (this.isLine(current) && (!component || component === myComponent)) || (dom.check.isComponentContainer(current) && !this.getLine(current));
948
+ });
949
+
950
+ if (removeDuplicate) {
951
+ for (let i = 0, len = selectedLines.length; i < len; i++) {
952
+ for (let j = i - 1; j >= 0; j--) {
953
+ if (selectedLines[j].contains(selectedLines[i])) {
954
+ selectedLines.splice(i, 1);
955
+ i--;
956
+ len--;
957
+ break;
958
+ }
959
+ }
960
+ }
961
+ }
962
+
963
+ return selectedLines;
964
+ }
965
+
966
+ /**
967
+ * @internal
968
+ * @description Nodes without text
969
+ * @param {Node|string} element Element to check
970
+ * @returns {boolean}
971
+ */
972
+ _isNotTextNode(element) {
973
+ if (!element) return false;
974
+ const checkRegExp = /^(br|input|select|canvas|img|iframe|audio|video)$/i;
975
+ if (typeof element === 'string') return checkRegExp.test(element);
976
+ return element.nodeType === 1 && (this.#$.component.is(element) || checkRegExp.test(element.nodeName));
977
+ }
978
+
979
+ /**
980
+ * @internal
981
+ * @description A function that distinguishes areas where `selection` should not be placed
982
+ * @param {Node} element Element
983
+ * @returns {boolean}
984
+ */
985
+ _isExcludeSelectionElement(element) {
986
+ return !/FIGCAPTION/i.test(element.nodeName) && (this.#$.component.is(element) || /FIGURE/i.test(element.nodeName));
987
+ }
988
+
989
+ /**
990
+ * @description A function that distinguishes non-formatting HTML elements or tags from formatting ones.
991
+ * @param {Node} element Element
992
+ * @returns {boolean}
993
+ */
994
+ #nonFormat(element) {
995
+ return dom.check.isExcludeFormat(element) || this.#$.component.is(element) || dom.check.isWysiwygFrame(element);
996
+ }
997
+
998
+ /**
999
+ * @description Get current selected lines and selected node info.
1000
+ * @returns {{lines: Array<HTMLElement>, firstNode: Node, lastNode: Node, firstPath: Array<number>, lastPath: Array<number>, startOffset: number, endOffset: number}}
1001
+ */
1002
+ #lineWork() {
1003
+ let range = this.#$.selection.getRange();
1004
+ let selectedFormsts = this.getLinesAndComponents(false);
1005
+
1006
+ if (selectedFormsts.length === 0) {
1007
+ range = this.#$.selection.getRangeAndAddLine(range, null);
1008
+ selectedFormsts = this.getLinesAndComponents(false);
1009
+ if (selectedFormsts.length === 0) return;
1010
+ }
1011
+
1012
+ const startOffset = range.startOffset;
1013
+ const endOffset = range.endOffset;
1014
+
1015
+ let first = /** @type {Node} */ (selectedFormsts[0]);
1016
+ let last = /** @type {Node} */ (selectedFormsts.at(-1));
1017
+ const firstPath = dom.query.getNodePath(range.startContainer, first, null);
1018
+ const lastPath = dom.query.getNodePath(range.endContainer, last, null);
1019
+
1020
+ // remove selected list
1021
+ const rlist = this.#$.listFormat.remove(selectedFormsts, false);
1022
+ if (rlist.sc) first = rlist.sc;
1023
+ if (rlist.ec) last = rlist.ec;
1024
+
1025
+ // change format tag
1026
+ this.#$.selection.setRange(dom.query.getNodeFromPath(firstPath, first), startOffset, dom.query.getNodeFromPath(lastPath, last), endOffset);
1027
+
1028
+ return {
1029
+ lines: this.getLinesAndComponents(false),
1030
+ firstNode: first,
1031
+ lastNode: last,
1032
+ firstPath: firstPath,
1033
+ lastPath: lastPath,
1034
+ startOffset: startOffset,
1035
+ endOffset: endOffset,
1036
+ };
1037
+ }
1038
+
1039
+ /**
1040
+ * @internal
1041
+ * @description Reset the line break format.
1042
+ * @param {"line"|"br"} breakFormat `options.get('defaultLineBreakFormat')`
1043
+ * @returns {boolean}
1044
+ */
1045
+ __resetBrLineBreak(breakFormat) {
1046
+ return (this.#brLineBreak = breakFormat === 'br');
1047
+ }
1048
+ }
1049
+
1050
+ /**
1051
+ * @param {Array<HTMLElement>} lines - Line elements
1052
+ * @param {number} size - Margin size
1053
+ * @param {string} dir - Direction
1054
+ * @returns
1055
+ */
1056
+ function SetLineMargin(lines, size, dir) {
1057
+ const cells = [];
1058
+
1059
+ for (let i = 0, len = lines.length, f, margin; i < len; i++) {
1060
+ f = lines[i];
1061
+ if (!dom.check.isListCell(f)) {
1062
+ margin = /\d+/.test(f.style[dir]) ? numbers.get(f.style[dir], 0) : 0;
1063
+ margin += size;
1064
+ dom.utils.setStyle(f, dir, margin <= 0 ? '' : margin + 'px');
1065
+ } else {
1066
+ if (size < 0 || f.previousElementSibling) {
1067
+ cells.push(f);
1068
+ }
1069
+ }
1070
+ }
1071
+
1072
+ return cells;
1073
+ }
1074
+
1075
+ export default Format;