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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/.eslintrc.json +4 -3
  2. package/CONTRIBUTING.md +4 -2
  3. package/README.md +19 -11
  4. package/README_V3_TEMP.md +705 -0
  5. package/dist/suneditor.min.css +1 -0
  6. package/dist/suneditor.min.js +1 -0
  7. package/example.md +587 -0
  8. package/package.json +15 -9
  9. package/src/assets/icons/_default.js +166 -131
  10. package/src/assets/{suneditor-content.css → suneditor-contents.css} +182 -45
  11. package/src/assets/suneditor.css +1195 -556
  12. package/src/assets/variables.css +138 -0
  13. package/src/core/base/eventHandlers/handler_toolbar.js +35 -14
  14. package/src/core/base/eventHandlers/handler_ww_clipboard.js +29 -4
  15. package/src/core/base/eventHandlers/handler_ww_dragDrop.js +59 -15
  16. package/src/core/base/eventHandlers/handler_ww_key_input.js +426 -212
  17. package/src/core/base/eventHandlers/handler_ww_mouse.js +108 -32
  18. package/src/core/base/eventManager.js +540 -209
  19. package/src/core/base/events.js +616 -320
  20. package/src/core/base/history.js +93 -39
  21. package/src/core/class/char.js +29 -13
  22. package/src/core/class/component.js +332 -145
  23. package/src/core/class/format.js +671 -509
  24. package/src/core/class/html.js +504 -290
  25. package/src/core/class/menu.js +114 -47
  26. package/src/core/class/nodeTransform.js +111 -66
  27. package/src/core/class/offset.js +409 -105
  28. package/src/core/class/selection.js +220 -108
  29. package/src/core/class/shortcuts.js +68 -8
  30. package/src/core/class/toolbar.js +106 -116
  31. package/src/core/class/ui.js +330 -0
  32. package/src/core/class/viewer.js +178 -74
  33. package/src/core/editor.js +489 -384
  34. package/src/core/section/actives.js +118 -22
  35. package/src/core/section/constructor.js +504 -170
  36. package/src/core/section/context.js +28 -23
  37. package/src/core/section/documentType.js +561 -0
  38. package/src/editorInjector/_classes.js +19 -5
  39. package/src/editorInjector/_core.js +71 -7
  40. package/src/editorInjector/index.js +63 -1
  41. package/src/helper/converter.js +137 -19
  42. package/src/helper/dom/domCheck.js +294 -0
  43. package/src/helper/dom/domQuery.js +609 -0
  44. package/src/helper/dom/domUtils.js +533 -0
  45. package/src/helper/dom/index.js +12 -0
  46. package/src/helper/env.js +42 -19
  47. package/src/helper/index.js +7 -4
  48. package/src/helper/keyCodeMap.js +183 -0
  49. package/src/helper/numbers.js +8 -8
  50. package/src/helper/unicode.js +5 -5
  51. package/src/langs/ckb.js +69 -3
  52. package/src/langs/cs.js +67 -1
  53. package/src/langs/da.js +68 -2
  54. package/src/langs/de.js +68 -3
  55. package/src/langs/en.js +29 -1
  56. package/src/langs/es.js +68 -3
  57. package/src/langs/fa.js +70 -2
  58. package/src/langs/fr.js +68 -2
  59. package/src/langs/he.js +68 -3
  60. package/src/langs/hu.js +226 -0
  61. package/src/langs/index.js +3 -2
  62. package/src/langs/it.js +65 -0
  63. package/src/langs/ja.js +68 -3
  64. package/src/langs/ko.js +66 -1
  65. package/src/langs/lv.js +68 -3
  66. package/src/langs/nl.js +68 -3
  67. package/src/langs/pl.js +68 -3
  68. package/src/langs/pt_br.js +65 -0
  69. package/src/langs/ro.js +69 -4
  70. package/src/langs/ru.js +68 -3
  71. package/src/langs/se.js +68 -3
  72. package/src/langs/tr.js +68 -0
  73. package/src/langs/ua.js +68 -3
  74. package/src/langs/ur.js +71 -6
  75. package/src/langs/zh_cn.js +69 -4
  76. package/src/modules/ApiManager.js +77 -54
  77. package/src/modules/Browser.js +667 -0
  78. package/src/modules/ColorPicker.js +162 -102
  79. package/src/modules/Controller.js +233 -136
  80. package/src/modules/Figure.js +913 -489
  81. package/src/modules/FileManager.js +141 -72
  82. package/src/modules/HueSlider.js +113 -61
  83. package/src/modules/Modal.js +292 -113
  84. package/src/modules/ModalAnchorEditor.js +380 -230
  85. package/src/modules/SelectMenu.js +270 -168
  86. package/src/modules/_DragHandle.js +2 -1
  87. package/src/modules/index.js +3 -3
  88. package/src/plugins/browser/audioGallery.js +83 -0
  89. package/src/plugins/browser/fileBrowser.js +103 -0
  90. package/src/plugins/browser/fileGallery.js +83 -0
  91. package/src/plugins/browser/imageGallery.js +81 -0
  92. package/src/plugins/browser/videoGallery.js +103 -0
  93. package/src/plugins/command/blockquote.js +40 -27
  94. package/src/plugins/command/exportPDF.js +134 -0
  95. package/src/plugins/command/fileUpload.js +226 -158
  96. package/src/plugins/command/list_bulleted.js +93 -47
  97. package/src/plugins/command/list_numbered.js +93 -47
  98. package/src/plugins/dropdown/align.js +66 -54
  99. package/src/plugins/dropdown/backgroundColor.js +76 -45
  100. package/src/plugins/dropdown/font.js +71 -47
  101. package/src/plugins/dropdown/fontColor.js +78 -46
  102. package/src/plugins/dropdown/formatBlock.js +74 -33
  103. package/src/plugins/dropdown/hr.js +102 -51
  104. package/src/plugins/dropdown/layout.js +37 -26
  105. package/src/plugins/dropdown/lineHeight.js +54 -38
  106. package/src/plugins/dropdown/list.js +60 -45
  107. package/src/plugins/dropdown/paragraphStyle.js +51 -30
  108. package/src/plugins/dropdown/table.js +1269 -777
  109. package/src/plugins/dropdown/template.js +38 -26
  110. package/src/plugins/dropdown/textStyle.js +43 -31
  111. package/src/plugins/field/mention.js +144 -82
  112. package/src/plugins/index.js +32 -6
  113. package/src/plugins/input/fontSize.js +161 -108
  114. package/src/plugins/input/pageNavigator.js +70 -0
  115. package/src/plugins/modal/audio.js +341 -169
  116. package/src/plugins/modal/drawing.js +530 -0
  117. package/src/plugins/modal/embed.js +886 -0
  118. package/src/plugins/modal/image.js +673 -358
  119. package/src/plugins/modal/link.js +100 -71
  120. package/src/plugins/modal/math.js +384 -168
  121. package/src/plugins/modal/video.js +693 -336
  122. package/src/plugins/popup/anchor.js +222 -0
  123. package/src/suneditor.js +54 -12
  124. package/src/themes/dark.css +85 -0
  125. package/src/typedef.js +86 -0
  126. package/types/assets/icons/_default.d.ts +152 -0
  127. package/types/core/base/eventHandlers/handler_toolbar.d.ts +41 -0
  128. package/types/core/base/eventHandlers/handler_ww_clipboard.d.ts +40 -0
  129. package/types/core/base/eventHandlers/handler_ww_dragDrop.d.ts +35 -0
  130. package/types/core/base/eventHandlers/handler_ww_key_input.d.ts +45 -0
  131. package/types/core/base/eventHandlers/handler_ww_mouse.d.ts +39 -0
  132. package/types/core/base/eventManager.d.ts +377 -0
  133. package/types/core/base/events.d.ts +297 -0
  134. package/types/core/base/history.d.ts +81 -0
  135. package/types/core/class/char.d.ts +60 -0
  136. package/types/core/class/component.d.ts +259 -0
  137. package/types/core/class/format.d.ts +615 -0
  138. package/types/core/class/html.d.ts +377 -0
  139. package/types/core/class/menu.d.ts +118 -0
  140. package/types/core/class/nodeTransform.d.ts +93 -0
  141. package/types/core/class/offset.d.ts +512 -0
  142. package/types/core/class/selection.d.ts +188 -0
  143. package/types/core/class/shortcuts.d.ts +142 -0
  144. package/types/core/class/toolbar.d.ts +189 -0
  145. package/types/core/class/ui.d.ts +144 -0
  146. package/types/core/class/viewer.d.ts +140 -0
  147. package/types/core/editor.d.ts +606 -0
  148. package/types/core/section/actives.d.ts +46 -0
  149. package/types/core/section/constructor.d.ts +748 -0
  150. package/types/core/section/context.d.ts +45 -0
  151. package/types/core/section/documentType.d.ts +178 -0
  152. package/types/editorInjector/_classes.d.ts +41 -0
  153. package/types/editorInjector/_core.d.ts +92 -0
  154. package/types/editorInjector/index.d.ts +71 -0
  155. package/types/helper/converter.d.ts +150 -0
  156. package/types/helper/dom/domCheck.d.ts +182 -0
  157. package/types/helper/dom/domQuery.d.ts +214 -0
  158. package/types/helper/dom/domUtils.d.ts +211 -0
  159. package/types/helper/dom/index.d.ts +9 -0
  160. package/types/helper/env.d.ts +149 -0
  161. package/types/helper/index.d.ts +163 -0
  162. package/types/helper/keyCodeMap.d.ts +110 -0
  163. package/types/helper/numbers.d.ts +43 -0
  164. package/types/helper/unicode.d.ts +28 -0
  165. package/types/index.d.ts +0 -0
  166. package/{typings/Lang.d.ts → types/langs/_Lang.d.ts} +170 -103
  167. package/types/langs/ckb.d.ts +384 -0
  168. package/types/langs/cs.d.ts +384 -0
  169. package/types/langs/da.d.ts +384 -0
  170. package/types/langs/de.d.ts +384 -0
  171. package/types/langs/en.d.ts +384 -0
  172. package/types/langs/es.d.ts +384 -0
  173. package/types/langs/fa.d.ts +384 -0
  174. package/types/langs/fr.d.ts +384 -0
  175. package/types/langs/he.d.ts +384 -0
  176. package/types/langs/hu.d.ts +384 -0
  177. package/types/langs/index.d.ts +48 -0
  178. package/types/langs/it.d.ts +384 -0
  179. package/types/langs/ja.d.ts +384 -0
  180. package/types/langs/ko.d.ts +384 -0
  181. package/types/langs/lv.d.ts +384 -0
  182. package/types/langs/nl.d.ts +384 -0
  183. package/types/langs/pl.d.ts +384 -0
  184. package/types/langs/pt_br.d.ts +384 -0
  185. package/types/langs/ro.d.ts +384 -0
  186. package/types/langs/ru.d.ts +384 -0
  187. package/types/langs/se.d.ts +384 -0
  188. package/types/langs/tr.d.ts +384 -0
  189. package/types/langs/ua.d.ts +384 -0
  190. package/types/langs/ur.d.ts +384 -0
  191. package/types/langs/zh_cn.d.ts +384 -0
  192. package/types/modules/ApiManager.d.ts +125 -0
  193. package/types/modules/Browser.d.ts +326 -0
  194. package/types/modules/ColorPicker.d.ts +131 -0
  195. package/types/modules/Controller.d.ts +231 -0
  196. package/types/modules/Figure.d.ts +504 -0
  197. package/types/modules/FileManager.d.ts +202 -0
  198. package/types/modules/HueSlider.d.ts +136 -0
  199. package/types/modules/Modal.d.ts +117 -0
  200. package/types/modules/ModalAnchorEditor.d.ts +236 -0
  201. package/types/modules/SelectMenu.d.ts +194 -0
  202. package/types/modules/_DragHandle.d.ts +7 -0
  203. package/types/modules/index.d.ts +26 -0
  204. package/types/plugins/browser/audioGallery.d.ts +55 -0
  205. package/types/plugins/browser/fileBrowser.d.ts +64 -0
  206. package/types/plugins/browser/fileGallery.d.ts +55 -0
  207. package/types/plugins/browser/imageGallery.d.ts +51 -0
  208. package/types/plugins/browser/videoGallery.d.ts +57 -0
  209. package/types/plugins/command/blockquote.d.ts +28 -0
  210. package/types/plugins/command/exportPDF.d.ts +46 -0
  211. package/types/plugins/command/fileUpload.d.ts +156 -0
  212. package/types/plugins/command/list_bulleted.d.ts +56 -0
  213. package/types/plugins/command/list_numbered.d.ts +56 -0
  214. package/types/plugins/dropdown/align.d.ts +60 -0
  215. package/types/plugins/dropdown/backgroundColor.d.ts +63 -0
  216. package/types/plugins/dropdown/font.d.ts +54 -0
  217. package/types/plugins/dropdown/fontColor.d.ts +63 -0
  218. package/types/plugins/dropdown/formatBlock.d.ts +58 -0
  219. package/types/plugins/dropdown/hr.d.ts +81 -0
  220. package/types/plugins/dropdown/layout.d.ts +40 -0
  221. package/types/plugins/dropdown/lineHeight.d.ts +50 -0
  222. package/types/plugins/dropdown/list.d.ts +39 -0
  223. package/types/plugins/dropdown/paragraphStyle.d.ts +54 -0
  224. package/types/plugins/dropdown/table.d.ts +579 -0
  225. package/types/plugins/dropdown/template.d.ts +40 -0
  226. package/types/plugins/dropdown/textStyle.d.ts +41 -0
  227. package/types/plugins/field/mention.d.ts +102 -0
  228. package/types/plugins/index.d.ts +107 -0
  229. package/types/plugins/input/fontSize.d.ts +170 -0
  230. package/types/plugins/input/pageNavigator.d.ts +28 -0
  231. package/types/plugins/modal/audio.d.ts +269 -0
  232. package/types/plugins/modal/drawing.d.ts +246 -0
  233. package/types/plugins/modal/embed.d.ts +387 -0
  234. package/types/plugins/modal/image.d.ts +451 -0
  235. package/types/plugins/modal/link.d.ts +128 -0
  236. package/types/plugins/modal/math.d.ts +193 -0
  237. package/types/plugins/modal/video.d.ts +485 -0
  238. package/types/plugins/popup/anchor.d.ts +56 -0
  239. package/types/suneditor.d.ts +51 -0
  240. package/types/typedef-global.d.ts +144 -0
  241. package/src/core/class/notice.js +0 -42
  242. package/src/helper/domUtils.js +0 -1177
  243. package/src/modules/FileBrowser.js +0 -271
  244. package/src/plugins/command/exportPdf.js +0 -168
  245. package/src/plugins/fileBrowser/imageGallery.js +0 -81
  246. package/src/themes/test.css +0 -61
  247. package/typings/CommandPlugin.d.ts +0 -8
  248. package/typings/DialogPlugin.d.ts +0 -20
  249. package/typings/FileBrowserPlugin.d.ts +0 -30
  250. package/typings/Module.d.ts +0 -15
  251. package/typings/Plugin.d.ts +0 -42
  252. package/typings/SubmenuPlugin.d.ts +0 -8
  253. package/typings/_classes.d.ts +0 -17
  254. package/typings/_colorPicker.d.ts +0 -60
  255. package/typings/_core.d.ts +0 -55
  256. package/typings/align.d.ts +0 -5
  257. package/typings/audio.d.ts +0 -5
  258. package/typings/backgroundColor.d.ts +0 -5
  259. package/typings/blockquote.d.ts +0 -5
  260. package/typings/char.d.ts +0 -39
  261. package/typings/component.d.ts +0 -38
  262. package/typings/context.d.ts +0 -39
  263. package/typings/converter.d.ts +0 -33
  264. package/typings/dialog.d.ts +0 -28
  265. package/typings/domUtils.d.ts +0 -361
  266. package/typings/editor.d.ts +0 -7
  267. package/typings/editor.ts +0 -542
  268. package/typings/env.d.ts +0 -70
  269. package/typings/eventManager.d.ts +0 -37
  270. package/typings/events.d.ts +0 -262
  271. package/typings/fileBrowser.d.ts +0 -42
  272. package/typings/fileManager.d.ts +0 -67
  273. package/typings/font.d.ts +0 -5
  274. package/typings/fontColor.d.ts +0 -5
  275. package/typings/fontSize.d.ts +0 -5
  276. package/typings/format.d.ts +0 -191
  277. package/typings/formatBlock.d.ts +0 -5
  278. package/typings/history.d.ts +0 -48
  279. package/typings/horizontalRule.d.ts +0 -5
  280. package/typings/image.d.ts +0 -5
  281. package/typings/imageGallery.d.ts +0 -5
  282. package/typings/index.d.ts +0 -21
  283. package/typings/index.modules.d.ts +0 -11
  284. package/typings/index.plugins.d.ts +0 -58
  285. package/typings/lineHeight.d.ts +0 -5
  286. package/typings/link.d.ts +0 -5
  287. package/typings/list.d.ts +0 -5
  288. package/typings/math.d.ts +0 -5
  289. package/typings/mediaContainer.d.ts +0 -25
  290. package/typings/mention.d.ts +0 -5
  291. package/typings/node.d.ts +0 -57
  292. package/typings/notice.d.ts +0 -16
  293. package/typings/numbers.d.ts +0 -29
  294. package/typings/offset.d.ts +0 -24
  295. package/typings/options.d.ts +0 -589
  296. package/typings/paragraphStyle.d.ts +0 -5
  297. package/typings/resizing.d.ts +0 -141
  298. package/typings/selection.d.ts +0 -94
  299. package/typings/shortcuts.d.ts +0 -13
  300. package/typings/suneditor.d.ts +0 -9
  301. package/typings/table.d.ts +0 -5
  302. package/typings/template.d.ts +0 -5
  303. package/typings/textStyle.d.ts +0 -5
  304. package/typings/toolbar.d.ts +0 -32
  305. package/typings/unicode.d.ts +0 -25
  306. package/typings/video.d.ts +0 -5
@@ -1,21 +1,92 @@
1
- import { domUtils, env, unicode } from '../../../helper';
1
+ import { dom, env, unicode, keyCodeMap } from '../../../helper';
2
2
 
3
3
  const { _w, isOSX_IOS } = env;
4
- const DIRECTION_KEYCODE = /^(8|3[2-9]|40|46)$/;
5
- const DIR_KEYCODE = /^(3[7-9]|40)$/;
6
- const DELETE_KEYCODE = /^(8|46)$/;
7
- const NON_TEXT_KEYCODE = /^(8|13|1[6-9]|20|27|3[3-9]|40|45|46|11[2-9]|12[0-3]|144|145|229)$/;
8
- const HISTORY_IGNORE_KEYCODE = /^(1[6-9]|20|27|3[3-9]|40|45|11[2-9]|12[0-3]|144|145|229)$/;
9
4
  const FRONT_ZEROWIDTH = new RegExp(unicode.zeroWidthSpace + '+', '');
10
5
  let _styleNodes = null;
11
6
 
12
- export function OnInput_wysiwyg(frameContext, e) {
13
- if (frameContext.get('isReadOnly') || frameContext.get('isDisabled')) {
7
+ /**
8
+ * @typedef {Omit<import('../eventManager').default & Partial<__se__EditorInjector>, 'eventManager'>} EventManagerThis
9
+ */
10
+
11
+ /**
12
+ * @private
13
+ * @param {HTMLElement} formatEl - Format element
14
+ * @returns {Node}
15
+ */
16
+ function LineDelete_next(formatEl) {
17
+ const focusNode = formatEl.lastChild;
18
+ const next = formatEl.nextElementSibling;
19
+
20
+ if (!next) return focusNode;
21
+
22
+ if (dom.check.isZeroWidth(next)) {
23
+ dom.utils.removeItem(next);
24
+ return focusNode;
25
+ }
26
+
27
+ const nextChild = next.childNodes;
28
+ while (nextChild[0]) {
29
+ formatEl.appendChild(nextChild[0]);
30
+ }
31
+
32
+ dom.utils.removeItem(next);
33
+
34
+ return focusNode;
35
+ }
36
+
37
+ /**
38
+ * @private
39
+ * @param {HTMLElement} formatEl - Format element
40
+ * @returns {{focusNode: Node, focusOffset: number}}
41
+ */
42
+ function LineDelete_prev(formatEl) {
43
+ const formatChild = formatEl.childNodes;
44
+ const prev = formatEl.previousElementSibling;
45
+ let focusNode = formatChild[0];
46
+ let focusOffset = 0;
47
+
48
+ if (!prev) return { focusNode, focusOffset };
49
+
50
+ if (dom.check.isZeroWidth(prev)) {
51
+ dom.utils.removeItem(prev);
52
+ return { focusNode, focusOffset };
53
+ }
54
+
55
+ if (formatChild.length > 1 || formatChild[0]?.textContent.length > 0) {
56
+ while (formatChild[0]) {
57
+ prev.appendChild(formatChild[0]);
58
+ }
59
+ } else {
60
+ focusNode = prev.lastChild;
61
+ focusOffset = focusNode.textContent.length;
62
+ }
63
+
64
+ dom.utils.removeItem(formatEl);
65
+
66
+ return { focusNode, focusOffset };
67
+ }
68
+
69
+ /**
70
+ * @private
71
+ * @this {EventManagerThis}
72
+ * @param {__se__FrameContext} fc - Frame context object
73
+ * @param {InputEvent} e - Event object
74
+ */
75
+ export async function OnInput_wysiwyg(fc, e) {
76
+ if (fc.get('isReadOnly') || fc.get('isDisabled')) {
14
77
  e.preventDefault();
15
78
  e.stopPropagation();
16
79
  return false;
17
80
  }
18
81
 
82
+ const range = this.selection.getRange();
83
+ const selectionNode = this.selection.getNode();
84
+ const formatEl = this.format.getLine(selectionNode, null);
85
+ if (!formatEl && range.collapsed && !this.component.is(selectionNode) && !dom.check.isList(selectionNode)) {
86
+ const rangeEl = this.format.getBlock(selectionNode, null);
87
+ this._setDefaultLine(this.format.isBlock(rangeEl) ? 'DIV' : this.options.get('defaultLine'));
88
+ }
89
+
19
90
  this.selection._init();
20
91
 
21
92
  const data = (e.data === null ? '' : e.data === undefined ? ' ' : e.data) || '';
@@ -26,27 +97,33 @@ export function OnInput_wysiwyg(frameContext, e) {
26
97
  }
27
98
 
28
99
  // user event
29
- if (this.triggerEvent('onInput', { frameContext, event: e, data }) === false) return;
100
+ if ((await this.triggerEvent('onInput', { frameContext: fc, event: e, data })) === false) return;
30
101
  // plugin event
31
- if (this._callPluginEvent('onInput', { frameContext, event: e, data }) === false) return;
102
+ if (this._callPluginEvent('onInput', { frameContext: fc, event: e, data }) === false) return;
32
103
 
33
104
  this.history.push(true);
34
105
  }
35
106
 
36
- export function OnKeyDown_wysiwyg(frameContext, e) {
107
+ /**
108
+ * @private
109
+ * @this {EventManagerThis}
110
+ * @param {__se__FrameContext} fc - Frame context object
111
+ * @param {KeyboardEvent} e - Event object
112
+ */
113
+ export async function OnKeyDown_wysiwyg(fc, e) {
37
114
  if (this.editor.selectMenuOn || !e.isTrusted) return;
38
115
 
39
116
  let selectionNode = this.selection.getNode();
40
- if (domUtils.isInputElement(selectionNode)) return;
117
+ if (dom.check.isInputElement(selectionNode)) return;
41
118
  if (this.menu.currentDropdownName) return;
42
119
 
43
- const keyCode = e.keyCode;
44
- const shift = e.shiftKey;
45
- const ctrl = e.ctrlKey || e.metaKey || keyCode === 91 || keyCode === 92 || keyCode === 224;
46
- const alt = e.altKey;
47
- this.isComposing = keyCode === 229;
120
+ const keyCode = e.code;
121
+ const shift = keyCodeMap.isShift(e);
122
+ const ctrl = keyCodeMap.isCtrl(e);
123
+ const alt = keyCodeMap.isAlt(e);
124
+ this.isComposing = keyCodeMap.isComposing(e);
48
125
 
49
- if (!ctrl && frameContext.get('isReadOnly') && !DIRECTION_KEYCODE.test(keyCode)) {
126
+ if (!ctrl && fc.get('isReadOnly') && !keyCodeMap.isDirectionKey(keyCode)) {
50
127
  e.preventDefault();
51
128
  return false;
52
129
  }
@@ -60,29 +137,42 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
60
137
  }
61
138
 
62
139
  // user event
63
- if (this.triggerEvent('onKeyDown', { frameContext, event: e }) === false) return;
140
+ if ((await this.triggerEvent('onKeyDown', { frameContext: fc, event: e })) === false) return;
141
+
142
+ /** default key action */
143
+ if (keyCodeMap.isEnter(keyCode) && this.format.isLine(this.selection.getRange()?.startContainer)) {
144
+ this.selection._resetRangeToTextNode();
145
+ selectionNode = this.selection.getNode();
146
+ }
147
+
148
+ const range = this.selection.getRange();
149
+ const selectRange = !range.collapsed || range.startContainer !== range.endContainer;
150
+ let formatEl = /** @type {HTMLElement} */ (this.format.getLine(selectionNode, null) || selectionNode);
151
+ let rangeEl = this.format.getBlock(formatEl, null);
64
152
 
65
153
  /** Shortcuts */
66
- if (ctrl && this.shortcuts.command(keyCode, shift)) {
154
+ if (ctrl && !keyCodeMap.isNonTextKey(keyCode) && this.shortcuts.command(e, ctrl, shift, keyCode, '', false, null, null)) {
67
155
  this._onShortcutKey = true;
68
156
  e.preventDefault();
69
157
  e.stopPropagation();
70
158
  return false;
159
+ } else if (!ctrl && !keyCodeMap.isNonTextKey(keyCode) && this.format.isLine(formatEl) && range.collapsed && dom.check.isEdgePoint(range.startContainer, 0, 'front')) {
160
+ const keyword = /** @type {Text} */ (range.startContainer).substringData?.(0, range.startOffset);
161
+ if (keyword && this.shortcuts.command(e, false, shift, keyCode, keyword, true, formatEl, range)) {
162
+ this._onShortcutKey = true;
163
+ e.preventDefault();
164
+ e.stopPropagation();
165
+ return false;
166
+ }
71
167
  } else if (this._onShortcutKey) {
72
168
  this._onShortcutKey = false;
73
169
  }
74
170
 
75
- /** default key action */
76
- const range = this.selection.getRange();
77
- const selectRange = !range.collapsed || range.startContainer !== range.endContainer;
78
- let formatEl = this.format.getLine(selectionNode, null) || selectionNode;
79
- let rangeEl = this.format.getBlock(formatEl, null);
80
-
81
171
  // plugin event
82
- if (this._callPluginEvent('onKeyDown', { frameContext, event: e, range, line: formatEl }) === false) return;
172
+ if (this._callPluginEvent('onKeyDown', { frameContext: fc, event: e, range, line: formatEl }) === false) return;
83
173
 
84
174
  switch (keyCode) {
85
- case 8 /** backspace key */: {
175
+ case 'Backspace' /** backspace key */: {
86
176
  this.component.deselect();
87
177
  _styleNodes = this.__cacheStyleNodes;
88
178
  if (selectRange && this._hardDelete()) {
@@ -91,18 +181,46 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
91
181
  break;
92
182
  }
93
183
 
94
- if (!this.format.isLine(formatEl) && !frameContext.get('wysiwyg').firstElementChild && !this.component.is(selectionNode) && this._setDefaultLine(this.options.get('defaultLine')) !== null) {
184
+ if (!this.format.isLine(formatEl) && !fc.get('wysiwyg').firstElementChild && !this.component.is(selectionNode) && this._setDefaultLine(this.options.get('defaultLine')) !== null) {
95
185
  e.preventDefault();
96
186
  e.stopPropagation();
97
187
  return false;
98
188
  }
99
189
 
190
+ // line delete
191
+ if (this.format.isLine(formatEl) && (!range.collapsed || dom.check.isEdgePoint(range.endContainer, range.endOffset, 'front')) && !range.endContainer.previousSibling && this.format.isLine(formatEl.previousElementSibling)) {
192
+ e.preventDefault();
193
+ e.stopPropagation();
194
+
195
+ let focusNode;
196
+ if (!range.collapsed) {
197
+ const rInfo = this.html.remove();
198
+ if (rInfo.commonCon !== rInfo.container && formatEl.parentElement) {
199
+ if (formatEl.contains(range.startContainer)) {
200
+ focusNode = LineDelete_next(formatEl);
201
+ this.selection.setRange(focusNode, focusNode.textContent.length, focusNode, focusNode.textContent.length);
202
+ } else {
203
+ const prevInfo = LineDelete_prev(formatEl);
204
+ this.selection.setRange(prevInfo.focusNode, prevInfo.focusOffset, prevInfo.focusNode, prevInfo.focusOffset);
205
+ }
206
+ }
207
+ this.history.push(true);
208
+ return;
209
+ }
210
+
211
+ const prevInfo = LineDelete_prev(formatEl);
212
+ this.selection.setRange(prevInfo.focusNode, prevInfo.focusOffset, prevInfo.focusNode, prevInfo.focusOffset);
213
+ this.history.push(true);
214
+
215
+ return;
216
+ }
217
+
100
218
  if (
101
219
  !selectRange &&
102
220
  !formatEl.previousElementSibling &&
103
221
  range.startOffset === 0 &&
104
222
  !selectionNode.previousSibling &&
105
- !domUtils.isListCell(formatEl) &&
223
+ !dom.check.isListCell(formatEl) &&
106
224
  this.format.isLine(formatEl) &&
107
225
  (!this.format.isBrLine(formatEl) || this.format.isClosureBrLine(formatEl))
108
226
  ) {
@@ -113,7 +231,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
113
231
  return false;
114
232
  }
115
233
  // maintain default format
116
- if (domUtils.isWysiwygFrame(formatEl.parentNode) && formatEl.childNodes.length <= 1 && (!formatEl.firstChild || domUtils.isZeroWith(formatEl.textContent))) {
234
+ if (dom.check.isWysiwygFrame(formatEl.parentNode) && formatEl.childNodes.length <= 1 && (!formatEl.firstChild || dom.check.isZeroWidth(formatEl.textContent))) {
117
235
  e.preventDefault();
118
236
  e.stopPropagation();
119
237
 
@@ -124,7 +242,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
124
242
  formatEl.removeAttribute(attrs[0].name);
125
243
  }
126
244
  } else {
127
- formatEl.parentElement.replaceChild(domUtils.createElement(this.options.get('defaultLine'), null, '<br>'), formatEl);
245
+ formatEl.parentNode.replaceChild(dom.utils.createElement(this.options.get('defaultLine'), null, '<br>'), formatEl);
128
246
  }
129
247
 
130
248
  this.editor._nativeFocus();
@@ -134,12 +252,12 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
134
252
 
135
253
  // clean remove tag
136
254
  const startCon = range.startContainer;
137
- if (formatEl && !formatEl.previousElementSibling && range.startOffset === 0 && startCon.nodeType === 3 && domUtils.isZeroWith(startCon)) {
255
+ if (formatEl && !formatEl.previousElementSibling && range.startOffset === 0 && startCon.nodeType === 3 && dom.check.isZeroWidth(startCon)) {
138
256
  let prev = startCon.parentNode.previousSibling;
139
257
  const next = startCon.parentNode.nextSibling;
140
258
  if (!prev) {
141
259
  if (!next) {
142
- prev = domUtils.createElement('BR');
260
+ prev = dom.utils.createElement('BR');
143
261
  formatEl.appendChild(prev);
144
262
  } else {
145
263
  prev = next;
@@ -160,7 +278,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
160
278
 
161
279
  // line component
162
280
  if (!selectRange && formatEl && (range.startOffset === 0 || selectionNode === formatEl)) {
163
- const sel = selectionNode === formatEl ? this._isUneditableNode(range, true) : domUtils.isEdgePoint(range.startContainer, range.startOffset) ? domUtils.getPreviousDeepestNode(range.startContainer) : null;
281
+ const sel = selectionNode === formatEl ? this._isUneditableNode(range, true) : dom.check.isEdgePoint(range.startContainer, range.startOffset) ? dom.query.getPreviousDeepestNode(range.startContainer) : null;
164
282
  if (this.component.is(sel)) {
165
283
  const fileComponentInfo = this.component.get(sel);
166
284
  if (fileComponentInfo) {
@@ -180,7 +298,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
180
298
  }
181
299
 
182
300
  // format attributes
183
- if (!selectRange && this.format.isEdgeLine(range.startContainer, range.startOffset, 'start')) {
301
+ if (!selectRange && this.format.isEdgeLine(range.startContainer, range.startOffset, 'front')) {
184
302
  if (this.format.isLine(formatEl.previousElementSibling)) {
185
303
  this._formatAttrsTemp = formatEl.previousElementSibling.attributes;
186
304
  }
@@ -190,12 +308,12 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
190
308
  const commonCon = range.commonAncestorContainer;
191
309
  formatEl = this.format.getLine(range.startContainer, null);
192
310
  rangeEl = this.format.getBlock(formatEl, null);
193
- if (rangeEl && formatEl && !domUtils.isTableCell(rangeEl) && !/^FIGCAPTION$/i.test(rangeEl.nodeName)) {
311
+ if (rangeEl && formatEl && !dom.check.isTableCell(rangeEl) && !/^FIGCAPTION$/i.test(rangeEl.nodeName)) {
194
312
  if (
195
- domUtils.isListCell(formatEl) &&
196
- domUtils.isList(rangeEl) &&
197
- (domUtils.isListCell(rangeEl.parentNode) || formatEl.previousElementSibling) &&
198
- (selectionNode === formatEl || (selectionNode.nodeType === 3 && (!selectionNode.previousSibling || domUtils.isList(selectionNode.previousSibling)))) &&
313
+ dom.check.isListCell(formatEl) &&
314
+ dom.check.isList(rangeEl) &&
315
+ (dom.check.isListCell(rangeEl.parentElement) || formatEl.previousElementSibling) &&
316
+ (selectionNode === formatEl || (selectionNode.nodeType === 3 && (!selectionNode.previousSibling || dom.check.isList(selectionNode.previousSibling)))) &&
199
317
  (this.format.getLine(range.startContainer, null) !== this.format.getLine(range.endContainer, null) ? rangeEl.contains(range.startContainer) : range.startOffset === 0 && range.collapsed)
200
318
  ) {
201
319
  if (range.startContainer !== range.endContainer) {
@@ -208,22 +326,22 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
208
326
 
209
327
  this.history.push(true);
210
328
  } else {
211
- let prev = formatEl.previousElementSibling || rangeEl.parentNode;
212
- if (domUtils.isListCell(prev)) {
329
+ let prev = formatEl.previousElementSibling || rangeEl.parentElement;
330
+ if (dom.check.isListCell(prev)) {
213
331
  e.preventDefault();
214
332
 
215
333
  let prevLast = prev;
216
- if (!prev.contains(formatEl) && domUtils.isListCell(prevLast) && domUtils.isList(prevLast.lastElementChild)) {
217
- prevLast = prevLast.lastElementChild.lastElementChild;
218
- while (domUtils.isListCell(prevLast) && domUtils.isList(prevLast.lastElementChild)) {
219
- prevLast = prevLast.lastElementChild && prevLast.lastElementChild.lastElementChild;
334
+ if (!prev.contains(formatEl) && dom.check.isListCell(prevLast) && dom.check.isList(prevLast.lastElementChild)) {
335
+ prevLast = /** @type {HTMLLIElement} */ (prevLast.lastElementChild.lastElementChild);
336
+ while (dom.check.isListCell(prevLast) && dom.check.isList(prevLast.lastElementChild)) {
337
+ prevLast = /** @type {HTMLLIElement} */ (prevLast.lastElementChild && prevLast.lastElementChild.lastElementChild);
220
338
  }
221
339
  prev = prevLast;
222
340
  }
223
341
 
224
342
  let con = prev === rangeEl.parentNode ? rangeEl.previousSibling : prev.lastChild;
225
343
  if (!con) {
226
- con = domUtils.createTextNode(unicode.zeroWidthSpace);
344
+ con = dom.utils.createTextNode(unicode.zeroWidthSpace);
227
345
  rangeEl.parentNode.insertBefore(con, rangeEl.parentNode.firstChild);
228
346
  }
229
347
  const offset = con.nodeType === 3 ? con.textContent.length : 1;
@@ -235,8 +353,8 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
235
353
  after = child;
236
354
  }
237
355
 
238
- domUtils.removeItem(formatEl);
239
- if (rangeEl.children.length === 0) domUtils.removeItem(rangeEl);
356
+ dom.utils.removeItem(formatEl);
357
+ if (rangeEl.children.length === 0) dom.utils.removeItem(rangeEl);
240
358
 
241
359
  this.selection.setRange(con, offset, con, offset);
242
360
  this.history.push(true);
@@ -250,9 +368,9 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
250
368
  if (!selectRange && range.startOffset === 0) {
251
369
  let detach = true;
252
370
  let comm = commonCon;
253
- while (comm && comm !== rangeEl && !domUtils.isWysiwygFrame(comm)) {
371
+ while (comm && comm !== rangeEl && !dom.check.isWysiwygFrame(comm)) {
254
372
  if (comm.previousSibling) {
255
- if (comm.previousSibling.nodeType === 1 || !domUtils.isZeroWith(comm.previousSibling.textContent.trim())) {
373
+ if (comm.previousSibling.nodeType === 1 || !dom.check.isZeroWidth(comm.previousSibling.textContent.trim())) {
256
374
  detach = false;
257
375
  break;
258
376
  }
@@ -262,7 +380,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
262
380
 
263
381
  if (detach && rangeEl.parentNode) {
264
382
  e.preventDefault();
265
- this.format.removeBlock(rangeEl, domUtils.isListCell(formatEl) ? [formatEl] : null, null, false, false);
383
+ this.format.removeBlock(rangeEl, { selectedFormats: dom.check.isListCell(formatEl) ? [formatEl] : null, newBlockElement: null, shouldDelete: false, skipHistory: false });
266
384
  this.history.push(true);
267
385
  break;
268
386
  }
@@ -274,33 +392,33 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
274
392
  const sel = selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : selectionNode;
275
393
  const prev = formatEl.previousSibling;
276
394
  // select file component
277
- const ignoreZWS = (commonCon.nodeType === 3 || domUtils.isBreak(commonCon)) && !commonCon.previousSibling && range.startOffset === 0;
395
+ const ignoreZWS = (commonCon.nodeType === 3 || dom.check.isBreak(commonCon)) && !commonCon.previousSibling && range.startOffset === 0;
278
396
  if (sel && !sel.previousSibling && ((commonCon && this.component.is(commonCon.previousSibling)) || (ignoreZWS && this.component.is(prev)))) {
279
397
  const fileComponentInfo = this.component.get(prev);
280
398
  if (fileComponentInfo) {
281
399
  e.preventDefault();
282
400
  e.stopPropagation();
283
- if (formatEl.textContent.length === 0) domUtils.removeItem(formatEl);
401
+ if (formatEl.textContent.length === 0) dom.utils.removeItem(formatEl);
284
402
  if (this.component.select(fileComponentInfo.target, fileComponentInfo.pluginName, false) === false) this.editor.blur();
285
403
  } else if (this.component.is(prev)) {
286
404
  e.preventDefault();
287
405
  e.stopPropagation();
288
- domUtils.removeItem(prev);
406
+ dom.utils.removeItem(prev);
289
407
  }
290
408
  break;
291
409
  }
292
410
  // delete nonEditable
293
- if (sel && domUtils.isNonEditable(sel.previousSibling)) {
411
+ if (sel && dom.check.isNonEditable(sel.previousSibling)) {
294
412
  e.preventDefault();
295
413
  e.stopPropagation();
296
- domUtils.removeItem(sel.previousSibling);
414
+ dom.utils.removeItem(sel.previousSibling);
297
415
  break;
298
416
  }
299
417
  }
300
418
 
301
419
  break;
302
420
  }
303
- case 46 /** delete key */: {
421
+ case 'Delete' /** delete key */: {
304
422
  this.component.deselect();
305
423
  _styleNodes = this.__cacheStyleNodes;
306
424
  if (selectRange && this._hardDelete()) {
@@ -309,14 +427,48 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
309
427
  break;
310
428
  }
311
429
 
430
+ if (!selectRange && this.format.isEdgeLine(range.endContainer, range.endOffset, 'end') && !formatEl.nextSibling) {
431
+ e.preventDefault();
432
+ e.stopPropagation();
433
+ return;
434
+ }
435
+
436
+ // line delete
437
+ if (this.format.isLine(formatEl) && (!range.collapsed || dom.check.isEdgePoint(range.startContainer, range.endOffset, 'end')) && !range.startContainer.nextSibling && this.format.isLine(formatEl.nextElementSibling)) {
438
+ e.preventDefault();
439
+ e.stopPropagation();
440
+
441
+ let focusNode;
442
+ if (!range.collapsed) {
443
+ const rInfo = this.html.remove();
444
+ if (rInfo.commonCon !== rInfo.container && formatEl.parentElement) {
445
+ if (formatEl.contains(range.startContainer)) {
446
+ focusNode = LineDelete_next(formatEl);
447
+ this.selection.setRange(focusNode, focusNode.textContent.length, focusNode, focusNode.textContent.length);
448
+ } else {
449
+ const prevInfo = LineDelete_prev(formatEl);
450
+ this.selection.setRange(prevInfo.focusNode, prevInfo.focusOffset, prevInfo.focusNode, prevInfo.focusOffset);
451
+ }
452
+ }
453
+ this.history.push(true);
454
+ return;
455
+ }
456
+
457
+ LineDelete_next(formatEl);
458
+ this.history.push(true);
459
+
460
+ return;
461
+ }
462
+
312
463
  // line component
313
464
  if (!selectRange && formatEl && (range.endOffset === range.endContainer.textContent.length || selectionNode === formatEl)) {
314
- const sel = selectionNode === formatEl ? this._isUneditableNode(range, false) : domUtils.isEdgePoint(range.endContainer, range.endOffset) ? domUtils.getNextDeepestNode(range.endContainer, null) : null;
465
+ const sel = selectionNode === formatEl ? this._isUneditableNode(range, false) : dom.check.isEdgePoint(range.endContainer, range.endOffset) ? dom.query.getNextDeepestNode(range.endContainer, null) : null;
315
466
  if (this.component.is(sel)) {
316
467
  const fileComponentInfo = this.component.get(sel);
317
468
  if (fileComponentInfo) {
318
469
  e.preventDefault();
319
470
  e.stopPropagation();
471
+ if (dom.check.isZeroWidth(formatEl.textContent)) dom.utils.removeItem(formatEl);
320
472
  if (this.component.select(fileComponentInfo.target, fileComponentInfo.pluginName, false) === false) this.editor.blur();
321
473
  break;
322
474
  }
@@ -332,7 +484,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
332
484
 
333
485
  // component
334
486
  if (
335
- (this.format.isLine(selectionNode) || selectionNode.nextSibling === null || (domUtils.isZeroWith(selectionNode.nextSibling) && selectionNode.nextSibling.nextSibling === null)) &&
487
+ (this.format.isLine(selectionNode) || selectionNode.nextSibling === null || (dom.check.isZeroWidth(selectionNode.nextSibling) && selectionNode.nextSibling.nextSibling === null)) &&
336
488
  range.startOffset === selectionNode.textContent.length
337
489
  ) {
338
490
  const nextEl = formatEl.nextElementSibling;
@@ -340,12 +492,12 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
340
492
  if (this.component.is(nextEl)) {
341
493
  e.preventDefault();
342
494
 
343
- if (domUtils.isZeroWith(formatEl)) {
344
- domUtils.removeItem(formatEl);
495
+ if (dom.check.isZeroWidth(formatEl)) {
496
+ dom.utils.removeItem(formatEl);
345
497
  // table component
346
- if (domUtils.isTable(nextEl)) {
347
- let cell = domUtils.getEdgeChild(nextEl, domUtils.isTableCell, false);
348
- cell = cell.firstElementChild || cell;
498
+ if (dom.check.isTable(nextEl)) {
499
+ let cell = /** @type {HTMLElement} */ (dom.query.getEdgeChild(nextEl, dom.check.isTableCell, false));
500
+ cell = /** @type {HTMLElement} */ (cell.firstElementChild || cell);
349
501
  this.selection.setRange(cell, 0, cell, 0);
350
502
  break;
351
503
  }
@@ -358,25 +510,25 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
358
510
  if (this.component.select(fileComponentInfo.target, fileComponentInfo.pluginName, false) === false) this.editor.blur();
359
511
  } else if (this.component.is(nextEl)) {
360
512
  e.stopPropagation();
361
- domUtils.removeItem(nextEl);
513
+ dom.utils.removeItem(nextEl);
362
514
  }
363
515
 
364
516
  break;
365
517
  }
366
518
  }
367
519
 
368
- if (!selectRange && (domUtils.isEdgePoint(range.endContainer, range.endOffset) || (selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : false))) {
520
+ if (!selectRange && (dom.check.isEdgePoint(range.endContainer, range.endOffset) || (selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : false))) {
369
521
  const sel = selectionNode === formatEl ? formatEl.childNodes[range.startOffset] || selectionNode : selectionNode;
370
522
  // delete nonEditable
371
- if (sel && domUtils.isNonEditable(sel.nextSibling)) {
523
+ if (sel && dom.check.isNonEditable(sel.nextSibling)) {
372
524
  e.preventDefault();
373
525
  e.stopPropagation();
374
- domUtils.removeItem(sel.nextSibling);
526
+ dom.utils.removeItem(sel.nextSibling);
375
527
  break;
376
528
  } else if (this.component.is(sel)) {
377
529
  e.preventDefault();
378
530
  e.stopPropagation();
379
- domUtils.removeItem(sel);
531
+ dom.utils.removeItem(sel);
380
532
  break;
381
533
  }
382
534
  }
@@ -392,36 +544,35 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
392
544
  formatEl = this.format.getLine(range.startContainer, null);
393
545
  rangeEl = this.format.getBlock(formatEl, null);
394
546
  if (
395
- domUtils.isListCell(formatEl) &&
396
- domUtils.isList(rangeEl) &&
547
+ dom.check.isListCell(formatEl) &&
548
+ dom.check.isList(rangeEl) &&
397
549
  (selectionNode === formatEl ||
398
550
  (selectionNode.nodeType === 3 &&
399
- (!selectionNode.nextSibling || domUtils.isList(selectionNode.nextSibling)) &&
551
+ (!selectionNode.nextSibling || dom.check.isList(selectionNode.nextSibling)) &&
400
552
  (this.format.getLine(range.startContainer, null) !== this.format.getLine(range.endContainer, null) ? rangeEl.contains(range.endContainer) : range.endOffset === selectionNode.textContent.length && range.collapsed)))
401
553
  ) {
402
554
  if (range.startContainer !== range.endContainer) this.html.remove();
403
555
 
404
- let next = domUtils.getArrayItem(formatEl.children, domUtils.isList, false);
405
- next = next || formatEl.nextElementSibling || rangeEl.parentNode.nextElementSibling;
406
- if (next && (domUtils.isList(next) || domUtils.getArrayItem(next.children, domUtils.isList, false))) {
556
+ const next = /** @type {HTMLElement} */ (dom.utils.arrayFind(formatEl.children, dom.check.isList) || formatEl.nextElementSibling || rangeEl.parentElement.nextElementSibling);
557
+ if (next && (dom.check.isList(next) || dom.utils.arrayFind(next.children, dom.check.isList))) {
407
558
  e.preventDefault();
408
559
 
409
560
  let con, children;
410
- if (domUtils.isList(next)) {
561
+ if (dom.check.isList(next)) {
411
562
  const child = next.firstElementChild;
412
563
  children = child.childNodes;
413
564
  con = children[0];
414
565
  while (children[0]) {
415
566
  formatEl.insertBefore(children[0], next);
416
567
  }
417
- domUtils.removeItem(child);
568
+ dom.utils.removeItem(child);
418
569
  } else {
419
570
  con = next.firstChild;
420
571
  children = next.childNodes;
421
572
  while (children[0]) {
422
573
  formatEl.appendChild(children[0]);
423
574
  }
424
- domUtils.removeItem(next);
575
+ dom.utils.removeItem(next);
425
576
  }
426
577
  this.selection.setRange(con, 0, con, 0);
427
578
  this.history.push(true);
@@ -431,18 +582,18 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
431
582
 
432
583
  break;
433
584
  }
434
- case 9 /** tab key */: {
585
+ case 'Tab' /** tab key */: {
435
586
  if (this.options.get('tabDisable')) break;
436
587
  e.preventDefault();
437
- if (ctrl || alt || domUtils.isWysiwygFrame(selectionNode)) break;
588
+ if (ctrl || alt || dom.check.isWysiwygFrame(selectionNode)) break;
438
589
 
439
- const isEdge = !range.collapsed || domUtils.isEdgePoint(range.startContainer, range.startOffset);
590
+ const isEdge = !range.collapsed || dom.check.isEdgePoint(range.startContainer, range.startOffset);
440
591
  const selectedFormats = this.format.getLines(null);
441
592
  selectionNode = this.selection.getNode();
442
593
  const cells = [];
443
594
  const lines = [];
444
- const fc = domUtils.isListCell(selectedFormats[0]),
445
- lc = domUtils.isListCell(selectedFormats[selectedFormats.length - 1]);
595
+ const firstCell = dom.check.isListCell(selectedFormats[0]),
596
+ lastCell = dom.check.isListCell(selectedFormats[selectedFormats.length - 1]);
446
597
  let r = {
447
598
  sc: range.startContainer,
448
599
  so: range.startOffset,
@@ -451,7 +602,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
451
602
  };
452
603
  for (let i = 0, len = selectedFormats.length, f; i < len; i++) {
453
604
  f = selectedFormats[i];
454
- if (domUtils.isListCell(f)) {
605
+ if (dom.check.isListCell(f)) {
455
606
  if (!f.previousElementSibling && !shift) {
456
607
  continue;
457
608
  } else {
@@ -467,41 +618,50 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
467
618
  r = this.format._applyNestedList(cells, shift);
468
619
  }
469
620
 
470
- // Lines tab(4)
621
+ // Lines tab
471
622
  if (lines.length > 0) {
472
623
  if (!shift) {
473
- const tabText = domUtils.createTextNode(new Array(this.status.tabSize + 1).join('\u00A0'));
474
624
  if (lines.length === 1) {
475
- const textRange = this.html.insertNode(tabText, null, false);
476
- if (!textRange) return false;
477
- if (!fc) {
625
+ let tabSize = this.status.tabSize + 1;
626
+ if (this.options.get('syncTabIndent')) {
627
+ const baseIndex = dom.query.findTextIndexOnLine(formatEl, range.startContainer, range.startOffset, this.component.is.bind(this.component));
628
+ const prevTabEndIndex = this.format.isLine(formatEl.previousElementSibling) ? dom.query.findTabEndIndex(formatEl.previousElementSibling, baseIndex, 2) : 0;
629
+ if (prevTabEndIndex > baseIndex) {
630
+ tabSize = prevTabEndIndex - baseIndex + 1;
631
+ }
632
+ }
633
+
634
+ const tabText = dom.utils.createTextNode(new Array(tabSize).join('\u00A0'));
635
+ if (!this.html.insertNode(tabText, { afterNode: null, skipCharCount: false })) return false;
636
+ if (!firstCell) {
478
637
  r.sc = tabText;
479
- r.so = textRange.endOffset;
638
+ r.so = tabText.length;
480
639
  }
481
- if (!lc) {
640
+ if (!lastCell) {
482
641
  r.ec = tabText;
483
- r.eo = textRange.endOffset;
642
+ r.eo = tabText.length;
484
643
  }
485
644
  } else {
645
+ const tabText = dom.utils.createTextNode(new Array(this.status.tabSize + 1).join('\u00A0'));
486
646
  const len = lines.length - 1;
487
647
  for (let i = 0, child; i <= len; i++) {
488
648
  child = lines[i].firstChild;
489
649
  if (!child) continue;
490
650
 
491
- if (domUtils.isBreak(child)) {
651
+ if (dom.check.isBreak(child)) {
492
652
  lines[i].insertBefore(tabText.cloneNode(false), child);
493
653
  } else {
494
654
  child.textContent = tabText.textContent + child.textContent;
495
655
  }
496
656
  }
497
657
 
498
- const firstChild = domUtils.getEdgeChild(lines[0], 'text', false);
499
- const endChild = domUtils.getEdgeChild(lines[len], 'text', true);
500
- if (!fc && firstChild) {
658
+ const firstChild = dom.query.getEdgeChild(lines[0], 'text', false);
659
+ const endChild = dom.query.getEdgeChild(lines[len], 'text', true);
660
+ if (!firstCell && firstChild) {
501
661
  r.sc = firstChild;
502
662
  r.so = 0;
503
663
  }
504
- if (!lc && endChild) {
664
+ if (!lastCell && endChild) {
505
665
  r.ec = endChild;
506
666
  r.eo = endChild.textContent.length;
507
667
  }
@@ -513,10 +673,10 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
513
673
  for (let c = 0, cLen = line.length, child; c < cLen; c++) {
514
674
  child = line[c];
515
675
  if (!child) break;
516
- if (domUtils.isZeroWith(child)) continue;
676
+ if (dom.check.isZeroWidth(child)) continue;
517
677
 
518
678
  if (/^\s{1,4}$/.test(child.textContent)) {
519
- domUtils.removeItem(child);
679
+ dom.utils.removeItem(child);
520
680
  } else if (/^\s{1,4}/.test(child.textContent)) {
521
681
  child.textContent = child.textContent.replace(/^\s{1,4}/, '');
522
682
  }
@@ -525,13 +685,13 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
525
685
  }
526
686
  }
527
687
 
528
- const firstChild = domUtils.getEdgeChild(lines[0], 'text', false);
529
- const endChild = domUtils.getEdgeChild(lines[len], 'text', true);
530
- if (!fc && firstChild) {
688
+ const firstChild = dom.query.getEdgeChild(lines[0], 'text', false);
689
+ const endChild = dom.query.getEdgeChild(lines[len], 'text', true);
690
+ if (!firstCell && firstChild) {
531
691
  r.sc = firstChild;
532
692
  r.so = 0;
533
693
  }
534
- if (!lc && endChild) {
694
+ if (!lastCell && endChild) {
535
695
  r.ec = endChild;
536
696
  r.eo = endChild.textContent.length;
537
697
  }
@@ -543,7 +703,7 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
543
703
 
544
704
  break;
545
705
  }
546
- case 13 /** enter key */: {
706
+ case 'Enter' /** enter key */: {
547
707
  this.component.deselect();
548
708
  const brBlock = this.format.getBrLine(selectionNode, null);
549
709
 
@@ -562,79 +722,74 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
562
722
  }
563
723
 
564
724
  if (!shift) {
565
- const formatEndEdge = this.format.isEdgeLine(range.endContainer, range.endOffset, 'end');
566
- const formatStartEdge = this.format.isEdgeLine(range.startContainer, range.startOffset, 'start');
725
+ const formatEndEdge = !range.endContainer.nextSibling && this.format.isEdgeLine(range.endContainer, range.endOffset, 'end');
726
+ const formatStartEdge = !range.startContainer.previousSibling && this.format.isEdgeLine(range.startContainer, range.startOffset, 'front');
567
727
 
568
728
  // add default format line
569
729
  if (formatEndEdge && (/^H[1-6]$/i.test(formatEl.nodeName) || /^HR$/i.test(formatEl.nodeName))) {
570
730
  this.__enterPrevent(e);
571
- let temp = null;
572
731
  const newFormat = this.format.addLine(formatEl, this.options.get('defaultLine'));
573
-
574
- if (formatEndEdge && formatEndEdge.length > 0) {
575
- temp = formatEndEdge.pop();
576
- const innerNode = temp;
577
- while (formatEndEdge.length > 0) {
578
- temp = temp.appendChild(formatEndEdge.pop());
579
- }
580
- newFormat.appendChild(innerNode);
581
- }
582
-
583
- temp = !temp ? newFormat.firstChild : temp.appendChild(newFormat.firstChild);
584
- if (domUtils.isBreak(temp)) {
585
- const zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
732
+ const temp = newFormat.firstChild;
733
+ if (dom.check.isBreak(temp)) {
734
+ const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
586
735
  temp.parentNode.insertBefore(zeroWidth, temp);
587
736
  this.selection.setRange(zeroWidth, 1, zeroWidth, 1);
588
737
  } else {
589
738
  this.selection.setRange(temp, 0, temp, 0);
590
739
  }
740
+
741
+ // enter scroll
742
+ this.selection.scrollTo(range);
591
743
  break;
592
- } else if (rangeEl && formatEl && !domUtils.isTableCell(rangeEl) && !/^FIGCAPTION$/i.test(rangeEl.nodeName)) {
744
+ } else if (rangeEl && formatEl && !dom.check.isTableCell(rangeEl) && !/^FIGCAPTION$/i.test(rangeEl.nodeName)) {
593
745
  const rangeEnt = this.selection.getRange();
594
- if (domUtils.isEdgePoint(rangeEnt.endContainer, rangeEnt.endOffset) && domUtils.isList(selectionNode.nextSibling)) {
746
+ if (dom.check.isEdgePoint(rangeEnt.endContainer, rangeEnt.endOffset) && dom.check.isList(selectionNode.nextSibling)) {
595
747
  this.__enterPrevent(e);
596
- const br = domUtils.createElement('BR');
597
- const newEl = domUtils.createElement('LI', null, br);
748
+ const br = dom.utils.createElement('BR');
749
+ const newEl = dom.utils.createElement('LI', null, br);
598
750
 
599
751
  formatEl.parentNode.insertBefore(newEl, formatEl.nextElementSibling);
600
752
  newEl.appendChild(selectionNode.nextSibling);
601
753
 
602
754
  this.selection.setRange(br, 1, br, 1);
755
+
756
+ // enter scroll
757
+ this.selection.scrollTo(range);
603
758
  break;
604
759
  }
605
760
 
606
761
  if (
607
- (rangeEnt.commonAncestorContainer.nodeType === 3 ? !rangeEnt.commonAncestorContainer.nextElementSibling : true) &&
608
- domUtils.isZeroWith(formatEl.innerText.trim()) &&
609
- !domUtils.isListCell(formatEl.nextElementSibling)
762
+ (rangeEnt.commonAncestorContainer.nodeType === 3 ? !(/** @type {HTMLElement} */ (rangeEnt.commonAncestorContainer).nextElementSibling) : true) &&
763
+ dom.check.isZeroWidth(formatEl.innerText.trim()) &&
764
+ !dom.check.isListCell(formatEl.nextElementSibling)
610
765
  ) {
611
766
  this.__enterPrevent(e);
612
767
  let newEl = null;
613
768
 
614
- if (domUtils.isListCell(rangeEl.parentNode)) {
615
- const parentLi = formatEl.parentNode.parentNode;
616
- rangeEl = parentLi.parentNode;
617
- const newListCell = domUtils.createElement('LI');
769
+ if (dom.check.isListCell(rangeEl.parentElement)) {
770
+ const parentLi = formatEl.parentNode.parentElement;
771
+ rangeEl = parentLi.parentElement;
772
+ const newListCell = dom.utils.createElement('LI');
618
773
  newListCell.innerHTML = '<br>';
619
- domUtils.copyTagAttributes(newListCell, formatEl, this.options.get('lineAttrReset'));
774
+ dom.utils.copyTagAttributes(newListCell, formatEl, this.options.get('lineAttrReset'));
620
775
  newEl = newListCell;
621
776
  rangeEl.insertBefore(newEl, parentLi.nextElementSibling);
622
777
  } else {
623
778
  let newFormat;
624
- if (domUtils.isTableCell(rangeEl.parentNode)) {
779
+ if (dom.check.isTableCell(rangeEl.parentElement)) {
625
780
  newFormat = 'DIV';
626
- } else if (domUtils.isList(rangeEl.parentNode)) {
781
+ } else if (dom.check.isList(rangeEl.parentElement)) {
627
782
  newFormat = 'LI';
628
- } else if (this.format.isLine(rangeEl.nextElementSibling) && !this.format.isBlock(rangeEl.nextElementSibling)) {
783
+ } else if (this.format.isLine(rangeEl.nextElementSibling)) {
629
784
  newFormat = rangeEl.nextElementSibling.nodeName;
630
- } else if (this.format.isLine(rangeEl.previousElementSibling) && !this.format.isBlock(rangeEl.previousElementSibling)) {
785
+ } else if (this.format.isLine(rangeEl.previousElementSibling)) {
631
786
  newFormat = rangeEl.previousElementSibling.nodeName;
632
787
  } else {
633
788
  newFormat = this.options.get('defaultLine');
634
789
  }
635
790
 
636
- newEl = domUtils.createElement(newFormat);
637
- const edge = this.format.removeBlock(rangeEl, [formatEl], null, true, true);
791
+ newEl = dom.utils.createElement(newFormat);
792
+ const edge = this.format.removeBlock(rangeEl, { selectedFormats: [formatEl], newBlockElement: null, shouldDelete: true, skipHistory: true });
638
793
  edge.cc.insertBefore(newEl, edge.ec);
639
794
  }
640
795
 
@@ -660,26 +815,30 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
660
815
  ((selectionFormat &&
661
816
  range.collapsed &&
662
817
  children.length - 1 <= offset + 1 &&
663
- domUtils.isBreak(children[offset]) &&
664
- (!children[offset + 1] || ((!children[offset + 2] || domUtils.isZeroWith(children[offset + 2].textContent)) && children[offset + 1].nodeType === 3 && domUtils.isZeroWith(children[offset + 1].textContent))) &&
818
+ dom.check.isBreak(children[offset]) &&
819
+ (!children[offset + 1] || ((!children[offset + 2] || dom.check.isZeroWidth(children[offset + 2].textContent)) && children[offset + 1].nodeType === 3 && dom.check.isZeroWidth(children[offset + 1].textContent))) &&
665
820
  offset > 0 &&
666
- domUtils.isBreak(children[offset - 1])) ||
821
+ dom.check.isBreak(children[offset - 1])) ||
667
822
  (!selectionFormat &&
668
- domUtils.isZeroWith(selectionNode.textContent) &&
669
- domUtils.isBreak(prev) &&
670
- (domUtils.isBreak(prev.previousSibling) || !domUtils.isZeroWith(prev.previousSibling.textContent)) &&
671
- (!next || (!domUtils.isBreak(next) && domUtils.isZeroWith(next.textContent)))))
823
+ dom.check.isZeroWidth(selectionNode.textContent) &&
824
+ dom.check.isBreak(prev) &&
825
+ (dom.check.isBreak(prev.previousSibling) || !dom.check.isZeroWidth(prev.previousSibling.textContent)) &&
826
+ (!next || (!dom.check.isBreak(next) && dom.check.isZeroWidth(next.textContent)))))
672
827
  ) {
673
- if (selectionFormat) domUtils.removeItem(children[offset - 1]);
674
- else domUtils.removeItem(selectionNode);
675
- const newEl = this.format.addLine(brBlock, this.format.isLine(brBlock.nextElementSibling) && !this.format.isBlock(brBlock.nextElementSibling) ? brBlock.nextElementSibling : null);
676
- domUtils.copyFormatAttributes(newEl, brBlock);
828
+ if (selectionFormat) dom.utils.removeItem(children[offset - 1]);
829
+ else dom.utils.removeItem(selectionNode);
830
+ const brBlockNext = /** @type {HTMLElement} */ (brBlock).nextElementSibling;
831
+ const newEl = this.format.addLine(brBlock, this.format.isLine(brBlockNext) ? brBlockNext : null);
832
+ dom.utils.copyFormatAttributes(newEl, brBlock);
677
833
  this.selection.setRange(newEl, 1, newEl, 1);
834
+
835
+ // enter scroll
836
+ this.selection.scrollTo(range);
678
837
  break;
679
838
  }
680
839
 
681
840
  if (selectionFormat) {
682
- this.html.insert(range.collapsed && domUtils.isBreak(range.startContainer.childNodes[range.startOffset - 1]) ? '<br>' : '<br><br>', false, true, true);
841
+ this.html.insert(range.collapsed && dom.check.isBreak(range.startContainer.childNodes[range.startOffset - 1]) ? '<br>' : '<br><br>', { selectInserted: false, skipCharCount: true, skipCleaning: true });
683
842
 
684
843
  let focusNode = wSelection.focusNode;
685
844
  const wOffset = wSelection.focusOffset;
@@ -690,12 +849,12 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
690
849
  this.selection.setRange(focusNode, 1, focusNode, 1);
691
850
  } else {
692
851
  const focusNext = wSelection.focusNode.nextSibling;
693
- const br = domUtils.createElement('BR');
694
- this.html.insertNode(br, null, true);
852
+ const br = dom.utils.createElement('BR');
853
+ this.html.insertNode(br, { afterNode: null, skipCharCount: true });
695
854
 
696
855
  const brPrev = br.previousSibling,
697
856
  brNext = br.nextSibling;
698
- if (!domUtils.isBreak(focusNext) && !domUtils.isBreak(brPrev) && (!brNext || domUtils.isZeroWith(brNext))) {
857
+ if (!dom.check.isBreak(focusNext) && !dom.check.isBreak(brPrev) && (!brNext || dom.check.isZeroWidth(brNext))) {
699
858
  br.parentNode.insertBefore(br.cloneNode(false), br);
700
859
  this.selection.setRange(br, 1, br, 1);
701
860
  } else {
@@ -704,25 +863,28 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
704
863
  }
705
864
 
706
865
  this._onShortcutKey = true;
866
+
867
+ // enter scroll
868
+ this.selection.scrollTo(range);
707
869
  break;
708
870
  }
709
871
 
710
872
  // set format attrs - edge
711
873
  if (range.collapsed && (formatStartEdge || formatEndEdge)) {
712
874
  this.__enterPrevent(e);
713
- const focusBR = domUtils.createElement('BR');
714
- const newFormat = domUtils.createElement(formatEl.nodeName, null, focusBR);
875
+ const focusBR = dom.utils.createElement('BR');
876
+ const newFormat = dom.utils.createElement(formatEl.nodeName, null, focusBR);
715
877
 
716
- domUtils.copyTagAttributes(newFormat, formatEl, this.options.get('lineAttrReset'));
878
+ dom.utils.copyTagAttributes(newFormat, formatEl, this.options.get('lineAttrReset'));
717
879
 
718
880
  let child = focusBR;
719
881
  do {
720
- if (!domUtils.isBreak(selectionNode) && selectionNode.nodeType === 1) {
721
- const f = selectionNode.cloneNode(false);
882
+ if (!dom.check.isBreak(selectionNode) && selectionNode.nodeType === 1) {
883
+ const f = /** @type {HTMLElement} */ (selectionNode.cloneNode(false));
722
884
  f.appendChild(child);
723
885
  child = f;
724
886
  }
725
- selectionNode = selectionNode.parentNode;
887
+ selectionNode = selectionNode.parentElement;
726
888
  } while (formatEl !== selectionNode && formatEl.contains(selectionNode));
727
889
 
728
890
  newFormat.appendChild(child);
@@ -734,33 +896,43 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
734
896
  this.selection.setRange(firstEl, 0, firstEl, 0);
735
897
  }
736
898
 
899
+ // enter scroll
900
+ this.selection.scrollTo(range);
737
901
  break;
738
902
  }
739
903
 
740
904
  if (formatEl) {
741
905
  e.stopPropagation();
742
906
 
907
+ /** @type {HTMLElement} */
743
908
  let newEl;
744
909
  let offset = 0;
745
910
  if (!range.collapsed) {
746
911
  const isMultiLine = this.format.getLine(range.startContainer, null) !== this.format.getLine(range.endContainer, null);
747
- const newFormat = formatEl.cloneNode(false);
912
+ const newFormat = /** @type {HTMLElement} */ (formatEl.cloneNode(false));
748
913
  newFormat.innerHTML = '<br>';
749
- const rcon = this.html.remove();
914
+ const commonCon = /** @type {HTMLElement} */ (range.commonAncestorContainer);
915
+ const rcon =
916
+ commonCon === range.startContainer && commonCon === range.endContainer && dom.check.isZeroWidth(commonCon)
917
+ ? { container: commonCon, offset: range.endOffset, prevContainer: commonCon.previousElementSibling, commonCon: commonCon }
918
+ : this.html.remove();
750
919
  newEl = this.format.getLine(rcon.container, null);
751
920
  if (!newEl) {
752
- if (domUtils.isWysiwygFrame(rcon.container)) {
921
+ if (dom.check.isWysiwygFrame(rcon.container)) {
753
922
  this.__enterPrevent(e);
754
- frameContext.get('wysiwyg').appendChild(newFormat);
923
+ fc.get('wysiwyg').appendChild(newFormat);
755
924
  newEl = newFormat;
756
- domUtils.copyTagAttributes(newEl, formatEl, this.options.get('lineAttrReset'));
925
+ dom.utils.copyTagAttributes(newEl, formatEl, this.options.get('lineAttrReset'));
757
926
  this.selection.setRange(newEl, offset, newEl, offset);
758
927
  }
928
+
929
+ // enter scroll
930
+ this.selection.scrollTo(range);
759
931
  break;
760
932
  }
761
933
 
762
934
  const innerRange = this.format.getBlock(rcon.container);
763
- newEl = newEl.contains(innerRange) ? domUtils.getEdgeChild(innerRange, this.format.getLine.bind(this.format)) : newEl;
935
+ newEl = newEl.contains(innerRange) ? dom.query.getEdgeChild(innerRange, this.format.getLine.bind(this.format), false) : newEl;
764
936
  if (isMultiLine) {
765
937
  if (formatEndEdge && !formatStartEdge) {
766
938
  newEl.parentNode.insertBefore(newFormat, !rcon.prevContainer || rcon.container === rcon.prevContainer ? newEl.nextElementSibling : newEl);
@@ -781,87 +953,103 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
781
953
  newEl.parentNode.insertBefore(newFormat, rcon.prevContainer && rcon.container === rcon.prevContainer ? newEl.nextElementSibling : newEl);
782
954
  newEl = newFormat;
783
955
  offset = 0;
956
+ } else if (formatEndEdge) {
957
+ newEl = newEl.parentNode.insertBefore(newFormat, newEl.nextElementSibling);
958
+ newEl = newFormat;
959
+ offset = 0;
784
960
  } else {
785
- newEl = this.nodeTransform.split(rcon.container, rcon.offset, domUtils.getNodeDepth(formatEl));
961
+ newEl = this.nodeTransform.split(rcon.container, rcon.offset, dom.query.getNodeDepth(formatEl));
786
962
  }
787
963
  }
788
964
  } else {
789
- if (domUtils.isZeroWith(formatEl)) {
965
+ if (dom.check.isZeroWidth(formatEl)) {
790
966
  newEl = this.format.addLine(formatEl, formatEl.cloneNode(false));
791
967
  } else {
792
- newEl = this.nodeTransform.split(range.endContainer, range.endOffset, domUtils.getNodeDepth(formatEl));
968
+ newEl = this.nodeTransform.split(range.endContainer, range.endOffset, dom.query.getNodeDepth(formatEl));
793
969
  }
794
970
  }
795
971
 
796
972
  this.__enterPrevent(e);
797
- domUtils.copyTagAttributes(newEl, formatEl, this.options.get('lineAttrReset'));
973
+ dom.utils.copyTagAttributes(newEl, formatEl, this.options.get('lineAttrReset'));
798
974
  this.selection.setRange(newEl, offset, newEl, offset);
799
975
 
976
+ // enter scroll
977
+ this.selection.scrollTo(range);
800
978
  break;
801
979
  }
802
980
  }
803
981
 
804
- if (selectRange) break;
982
+ if (selectRange) {
983
+ // enter scroll
984
+ this.selection.scrollTo(range);
985
+ break;
986
+ }
805
987
 
806
- if (rangeEl && domUtils.getParentElement(rangeEl, 'FIGCAPTION') && domUtils.getParentElement(rangeEl, domUtils.isList)) {
988
+ if (rangeEl && dom.query.getParentElement(rangeEl, 'FIGCAPTION') && dom.query.getParentElement(rangeEl, dom.check.isList)) {
807
989
  this.__enterPrevent(e);
808
990
  formatEl = this.format.addLine(formatEl, null);
809
991
  this.selection.setRange(formatEl, 0, formatEl, 0);
992
+
993
+ // enter scroll
994
+ this.selection.scrollTo(range);
810
995
  }
811
996
 
812
997
  break;
813
998
  }
814
999
  }
815
1000
 
816
- if (shift && (isOSX_IOS ? alt : ctrl) && keyCode === 32) {
1001
+ if (shift && (isOSX_IOS ? alt : ctrl) && keyCodeMap.isSpace(keyCode)) {
817
1002
  e.preventDefault();
818
1003
  e.stopPropagation();
819
- const nbsp = this.html.insertNode(domUtils.createTextNode('\u00a0'), null, true);
820
- if (nbsp && nbsp.container) {
821
- this.selection.setRange(nbsp.container, nbsp.endOffset, nbsp.container, nbsp.endOffset);
1004
+ const nbsp = this.html.insertNode(dom.utils.createTextNode('\u00a0'), { afterNode: null, skipCharCount: true });
1005
+ if (nbsp) {
1006
+ this.selection.setRange(nbsp, nbsp.length, nbsp, nbsp.length);
822
1007
  return;
823
1008
  }
824
1009
  }
825
1010
 
826
- if (!ctrl && !alt && !selectRange && !NON_TEXT_KEYCODE.test(keyCode) && domUtils.isBreak(range.commonAncestorContainer)) {
827
- const zeroWidth = domUtils.createTextNode(unicode.zeroWidthSpace);
828
- this.html.insertNode(zeroWidth, null, true);
1011
+ if (!ctrl && !alt && !selectRange && !keyCodeMap.isNonTextKey(keyCode) && dom.check.isBreak(range.commonAncestorContainer)) {
1012
+ const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
1013
+ this.html.insertNode(zeroWidth, { afterNode: null, skipCharCount: true });
829
1014
  this.selection.setRange(zeroWidth, 1, zeroWidth, 1);
830
1015
  }
831
1016
 
832
- // enter scroll
833
- if (keyCode === 13) this.selection.scrollTo(range);
1017
+ // document type
1018
+ if (fc.has('documentType-use-header') && !range.collapsed && !ctrl && !alt && !shift && !keyCodeMap.isDirectionKey(keyCode)) {
1019
+ _w.setTimeout(() => {
1020
+ fc.get('documentType').reHeader();
1021
+ }, 0);
1022
+ return;
1023
+ }
834
1024
 
835
1025
  // next component
836
- if (!DIR_KEYCODE.test(keyCode)) return;
837
-
838
1026
  let cmponentInfo = null;
839
1027
  switch (keyCode) {
840
- case 38 /** up key */:
1028
+ case 'ArrowUp' /** up key */:
841
1029
  if (this.component.is(formatEl.previousElementSibling)) {
842
1030
  cmponentInfo = this.component.get(formatEl.previousElementSibling);
843
1031
  }
844
1032
  break;
845
- case 37 /** left key */:
846
- if (domUtils.isEdgePoint(selectionNode, range.startOffset, 'front')) {
847
- const prevEl = selectionNode.previousElementSibling;
848
- if (prevEl && this.component.is(prevEl)) {
849
- cmponentInfo = this.component.get(prevEl);
1033
+ case 'ArrowLeft' /** left key */:
1034
+ if (dom.check.isEdgePoint(selectionNode, range.startOffset, 'front')) {
1035
+ const prevEl = selectionNode.previousElementSibling || dom.query.getPreviousDeepestNode(selectionNode);
1036
+ if (prevEl) {
1037
+ if (this.component.is(prevEl)) cmponentInfo = this.component.get(prevEl);
850
1038
  } else if (this.component.is(formatEl.previousElementSibling)) {
851
1039
  cmponentInfo = this.component.get(formatEl.previousElementSibling);
852
1040
  }
853
1041
  }
854
1042
  break;
855
- case 40 /** down key */:
1043
+ case 'ArrowDown' /** down key */:
856
1044
  if (this.component.is(formatEl.nextElementSibling)) {
857
1045
  cmponentInfo = this.component.get(formatEl.nextElementSibling);
858
1046
  }
859
1047
  break;
860
- case 39 /** right key */:
861
- if (domUtils.isEdgePoint(selectionNode, range.endOffset, 'end')) {
862
- const nextEl = selectionNode.nextElementSibling;
863
- if (nextEl && this.component.is(nextEl)) {
864
- cmponentInfo = this.component.get(nextEl);
1048
+ case 'ArrowRight' /** right key */:
1049
+ if (dom.check.isEdgePoint(selectionNode, range.endOffset, 'end')) {
1050
+ const nextEl = selectionNode.nextElementSibling || dom.query.getNextDeepestNode(selectionNode);
1051
+ if (nextEl) {
1052
+ if (this.component.is(nextEl)) cmponentInfo = this.component.get(nextEl);
865
1053
  } else if (this.component.is(formatEl.nextElementSibling)) {
866
1054
  cmponentInfo = this.component.get(formatEl.nextElementSibling);
867
1055
  }
@@ -875,21 +1063,27 @@ export function OnKeyDown_wysiwyg(frameContext, e) {
875
1063
  }
876
1064
  }
877
1065
 
878
- export function OnKeyUp_wysiwyg(frameContext, e) {
1066
+ /**
1067
+ * @private
1068
+ * @this {EventManagerThis}
1069
+ * @param {__se__FrameContext} fc - Frame context object
1070
+ * @param {KeyboardEvent} e - Event object
1071
+ */
1072
+ export async function OnKeyUp_wysiwyg(fc, e) {
879
1073
  if (this._onShortcutKey || this.menu.currentDropdownName) return;
880
1074
 
881
- const keyCode = e.keyCode;
882
- const ctrl = e.ctrlKey || e.metaKey || keyCode === 91 || keyCode === 92 || keyCode === 224;
883
- const alt = e.altKey;
1075
+ const keyCode = e.code;
1076
+ const ctrl = keyCodeMap.isCtrl(e);
1077
+ const alt = keyCodeMap.isAlt(e);
884
1078
 
885
- if (frameContext.get('isReadOnly')) return;
1079
+ if (fc.get('isReadOnly')) return;
886
1080
 
887
1081
  const range = this.selection.getRange();
888
1082
  let selectionNode = this.selection.getNode();
889
1083
 
890
- if ((this.editor.isBalloon || this.editor.isSubBalloon) && (((this.editor.isBalloonAlways || this.editor.isSubBalloonAlways) && keyCode !== 27) || !range.collapsed)) {
1084
+ if ((this.editor.isBalloon || this.editor.isSubBalloon) && (((this.editor.isBalloonAlways || this.editor.isSubBalloonAlways) && !keyCodeMap.isEsc(keyCode)) || !range.collapsed)) {
891
1085
  if (this.editor.isBalloonAlways || this.editor.isSubBalloonAlways) {
892
- if (keyCode !== 27) this._showToolbarBalloonDelay();
1086
+ if (!keyCodeMap.isEsc(keyCode)) this._showToolbarBalloonDelay();
893
1087
  } else {
894
1088
  if (this.editor.isSubBalloon) this.subToolbar._showBalloon();
895
1089
  else this.toolbar._showBalloon();
@@ -898,18 +1092,26 @@ export function OnKeyUp_wysiwyg(frameContext, e) {
898
1092
  }
899
1093
 
900
1094
  /** when format tag deleted */
901
- if (keyCode === 8 && domUtils.isWysiwygFrame(selectionNode) && selectionNode.textContent === '' && selectionNode.children.length === 0) {
1095
+ if (keyCodeMap.isBackspace(keyCode) && dom.check.isWysiwygFrame(selectionNode) && selectionNode.textContent === '' && selectionNode.children.length === 0) {
902
1096
  e.preventDefault();
903
1097
  e.stopPropagation();
904
1098
 
905
1099
  selectionNode.innerHTML = '';
906
1100
 
907
- const oFormatTag = domUtils.createElement(this.format.isLine(this.status.currentNodes[0]) && !domUtils.isListCell(this.status.currentNodes[0]) ? this.status.currentNodes[0] : this.options.get('defaultLine'), null, '<br>');
1101
+ const oFormatTag = dom.utils.createElement(this.format.isLine(this.status.currentNodes[0]) && !dom.check.isListCell(this.status.currentNodes[0]) ? this.status.currentNodes[0] : this.options.get('defaultLine'), null, '<br>');
908
1102
  selectionNode.appendChild(oFormatTag);
909
1103
  this.selection.setRange(oFormatTag, 0, oFormatTag, 0);
910
1104
  this.applyTagEffect();
911
1105
 
912
1106
  this.history.push(false);
1107
+
1108
+ // document type
1109
+ if (fc.has('documentType-use-header')) {
1110
+ if (keyCodeMap.isDocumentTypeObserverKey(keyCode)) {
1111
+ fc.get('documentType').reHeader();
1112
+ }
1113
+ }
1114
+
913
1115
  return;
914
1116
  }
915
1117
 
@@ -919,7 +1121,7 @@ export function OnKeyUp_wysiwyg(frameContext, e) {
919
1121
 
920
1122
  if (formatEl && attrs) {
921
1123
  for (let i = 0, len = attrs.length; i < len; i++) {
922
- if (keyCode === 13 && /^id$/i.test(attrs[i].name)) {
1124
+ if (keyCodeMap.isEnter(keyCode) && /^id$/i.test(attrs[i].name)) {
923
1125
  formatEl.removeAttribute('id');
924
1126
  continue;
925
1127
  }
@@ -928,11 +1130,11 @@ export function OnKeyUp_wysiwyg(frameContext, e) {
928
1130
  this._formatAttrsTemp = null;
929
1131
  }
930
1132
 
931
- if (!formatEl && range.collapsed && !this.component.is(selectionNode) && !domUtils.isList(selectionNode) && this._setDefaultLine(this.format.isBlock(rangeEl) ? 'DIV' : this.options.get('defaultLine')) !== null) {
1133
+ if (!formatEl && range.collapsed && !this.component.is(selectionNode) && !dom.check.isList(selectionNode) && this._setDefaultLine(this.format.isBlock(rangeEl) ? 'DIV' : this.options.get('defaultLine')) !== null) {
932
1134
  selectionNode = this.selection.getNode();
933
1135
  }
934
1136
 
935
- const textKey = !ctrl && !alt && !NON_TEXT_KEYCODE.test(keyCode);
1137
+ const textKey = !ctrl && !alt && !keyCodeMap.isNonTextKey(keyCode);
936
1138
  if (textKey && selectionNode.nodeType === 3 && unicode.zeroWidthRegExp.test(selectionNode.textContent) && !(e.isComposing !== undefined ? e.isComposing : this.isComposing)) {
937
1139
  let so = range.startOffset,
938
1140
  eo = range.endOffset;
@@ -943,7 +1145,7 @@ export function OnKeyUp_wysiwyg(frameContext, e) {
943
1145
  this.selection.setRange(selectionNode, so < 0 ? 0 : so, selectionNode, eo < 0 ? 0 : eo);
944
1146
  }
945
1147
 
946
- if (DELETE_KEYCODE.test(keyCode) && domUtils.isZeroWith(formatEl?.textContent) && !formatEl.previousElementSibling) {
1148
+ if (keyCodeMap.isRemoveKey(keyCode) && dom.check.isZeroWidth(formatEl?.textContent) && !formatEl.previousElementSibling) {
947
1149
  const rsMode = this.options.get('retainStyleMode');
948
1150
  if (rsMode !== 'none' && _styleNodes?.length > 0) {
949
1151
  if (rsMode === 'repeat') {
@@ -967,12 +1169,24 @@ export function OnKeyUp_wysiwyg(frameContext, e) {
967
1169
 
968
1170
  this.char.test('', false);
969
1171
 
1172
+ // document type
1173
+ if (fc.has('documentType-use-header')) {
1174
+ if (keyCodeMap.isDocumentTypeObserverKey(keyCode)) {
1175
+ fc.get('documentType').reHeader();
1176
+ const el = dom.query.getParentElement(this.selection.selectionNode, this.format.isLine.bind(this.format));
1177
+ fc.get('documentType').on(el);
1178
+ } else {
1179
+ const el = dom.query.getParentElement(selectionNode, (current) => current.nodeType === 1);
1180
+ fc.get('documentType').onChangeText(el);
1181
+ }
1182
+ }
1183
+
970
1184
  // user event
971
- if (this.triggerEvent('onKeyUp', { frameContext, event: e }) === false) return;
1185
+ if ((await this.triggerEvent('onKeyUp', { frameContext: fc, event: e })) === false) return;
972
1186
  // plugin event
973
- if (this._callPluginEvent('onKeyUp', { frameContext, event: e, range, line: formatEl }) === false) return;
1187
+ if (this._callPluginEvent('onKeyUp', { frameContext: fc, event: e, range, line: formatEl }) === false) return;
974
1188
 
975
- if (!ctrl && !alt && !HISTORY_IGNORE_KEYCODE.test(keyCode)) {
1189
+ if (!ctrl && !alt && !keyCodeMap.isHistoryIgnoreKey(keyCode)) {
976
1190
  this.history.push(true);
977
1191
  }
978
1192
  }