suneditor 3.1.4 → 3.2.1

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 (217) hide show
  1. package/dist/suneditor-contents.min.css +1 -1
  2. package/dist/suneditor.min.css +28 -1
  3. package/dist/suneditor.min.js +1 -1
  4. package/package.json +2 -1
  5. package/src/assets/design/color.css +12 -0
  6. package/src/assets/design/size.css +9 -2
  7. package/src/assets/icons/defaultIcons.js +96 -47
  8. package/src/assets/suneditor-contents.css +3 -2
  9. package/src/assets/suneditor.css +481 -31
  10. package/src/core/config/contextProvider.js +2 -1
  11. package/src/core/config/eventManager.js +41 -2
  12. package/src/core/config/optionProvider.js +23 -2
  13. package/src/core/editor.js +32 -14
  14. package/src/core/event/actions/index.js +76 -9
  15. package/src/core/event/effects/common.registry.js +2 -1
  16. package/src/core/event/effects/keydown.registry.js +169 -33
  17. package/src/core/event/effects/ruleHelpers.js +20 -6
  18. package/src/core/event/eventOrchestrator.js +162 -30
  19. package/src/core/event/handlers/handler_toolbar.js +4 -2
  20. package/src/core/event/handlers/handler_ww_dragDrop.js +10 -0
  21. package/src/core/event/handlers/handler_ww_input.js +84 -2
  22. package/src/core/event/handlers/handler_ww_key.js +82 -21
  23. package/src/core/event/handlers/handler_ww_mouse.js +45 -8
  24. package/src/core/event/ports.js +27 -13
  25. package/src/core/event/reducers/keydown.reducer.js +33 -5
  26. package/src/core/event/rules/keydown.rule.arrow.js +12 -2
  27. package/src/core/event/rules/keydown.rule.backspace.js +110 -15
  28. package/src/core/event/rules/keydown.rule.delete.js +62 -7
  29. package/src/core/event/rules/keydown.rule.enter.js +62 -31
  30. package/src/core/event/support/defaultLineManager.js +9 -2
  31. package/src/core/event/support/selectionState.js +13 -3
  32. package/src/core/kernel/coreKernel.js +1 -0
  33. package/src/core/logic/dom/char.js +13 -3
  34. package/src/core/logic/dom/format.js +171 -39
  35. package/src/core/logic/dom/html.js +350 -72
  36. package/src/core/logic/dom/inline.js +229 -34
  37. package/src/core/logic/dom/listFormat.js +111 -20
  38. package/src/core/logic/dom/nodeTransform.js +36 -11
  39. package/src/core/logic/dom/offset.js +116 -31
  40. package/src/core/logic/dom/selection.js +147 -29
  41. package/src/core/logic/panel/blockHandle.js +785 -0
  42. package/src/core/logic/panel/blockResolver.js +278 -0
  43. package/src/core/logic/panel/finder.js +16 -6
  44. package/src/core/logic/panel/menu.js +119 -18
  45. package/src/core/logic/panel/toolbar.js +75 -19
  46. package/src/core/logic/panel/viewer.js +76 -20
  47. package/src/core/logic/shell/_commandExecutor.js +44 -9
  48. package/src/core/logic/shell/commandDispatcher.js +46 -4
  49. package/src/core/logic/shell/component.js +102 -25
  50. package/src/core/logic/shell/focusManager.js +13 -3
  51. package/src/core/logic/shell/history.js +21 -6
  52. package/src/core/logic/shell/pluginManager.js +21 -13
  53. package/src/core/logic/shell/shortcuts.js +9 -1
  54. package/src/core/logic/shell/ui.js +139 -37
  55. package/src/core/schema/frameContext.js +34 -3
  56. package/src/core/schema/options.js +46 -4
  57. package/src/core/section/constructor.js +537 -106
  58. package/src/core/section/documentType.js +35 -6
  59. package/src/helper/converter.js +24 -7
  60. package/src/helper/dom/domCheck.js +25 -5
  61. package/src/helper/dom/domQuery.js +2 -1
  62. package/src/helper/dom/domUtils.js +17 -4
  63. package/src/helper/env.js +11 -2
  64. package/src/helper/keyCodeMap.js +6 -2
  65. package/src/helper/markdown.js +24 -5
  66. package/src/helper/msOffice.js +9 -2
  67. package/src/interfaces/plugins.js +1 -1
  68. package/src/langs/ckb.js +0 -1
  69. package/src/langs/cs.js +0 -1
  70. package/src/langs/da.js +0 -1
  71. package/src/langs/de.js +0 -1
  72. package/src/langs/en.js +0 -1
  73. package/src/langs/es.js +0 -1
  74. package/src/langs/fa.js +0 -1
  75. package/src/langs/fr.js +0 -1
  76. package/src/langs/he.js +0 -1
  77. package/src/langs/hu.js +0 -1
  78. package/src/langs/index.js +27 -1
  79. package/src/langs/it.js +0 -1
  80. package/src/langs/ja.js +0 -1
  81. package/src/langs/km.js +0 -1
  82. package/src/langs/ko.js +0 -1
  83. package/src/langs/lv.js +0 -1
  84. package/src/langs/nl.js +0 -1
  85. package/src/langs/pl.js +0 -1
  86. package/src/langs/pt_br.js +0 -1
  87. package/src/langs/ro.js +0 -1
  88. package/src/langs/ru.js +0 -1
  89. package/src/langs/se.js +0 -1
  90. package/src/langs/tr.js +0 -1
  91. package/src/langs/uk.js +0 -1
  92. package/src/langs/ur.js +0 -1
  93. package/src/langs/zh_cn.js +0 -1
  94. package/src/modules/contract/Browser.js +58 -14
  95. package/src/modules/contract/ColorPicker.js +12 -4
  96. package/src/modules/contract/Controller.js +37 -7
  97. package/src/modules/contract/Figure.js +156 -36
  98. package/src/modules/contract/HueSlider.js +27 -4
  99. package/src/modules/contract/Modal.js +50 -10
  100. package/src/modules/manager/FileManager.js +50 -8
  101. package/src/modules/ui/CommandMenu.js +597 -0
  102. package/src/modules/ui/ModalAnchorEditor.js +33 -6
  103. package/src/modules/ui/SelectMenu.js +481 -36
  104. package/src/modules/ui/index.js +1 -0
  105. package/src/plugins/browser/audioGallery.js +2 -1
  106. package/src/plugins/browser/fileBrowser.js +9 -2
  107. package/src/plugins/browser/fileGallery.js +2 -1
  108. package/src/plugins/browser/imageGallery.js +18 -3
  109. package/src/plugins/browser/videoGallery.js +13 -4
  110. package/src/plugins/command/blockquote.js +6 -1
  111. package/src/plugins/command/codeBlock.js +43 -5
  112. package/src/plugins/command/exportPDF.js +20 -4
  113. package/src/plugins/command/fileUpload.js +46 -11
  114. package/src/plugins/command/list_bulleted.js +6 -1
  115. package/src/plugins/command/list_numbered.js +6 -1
  116. package/src/plugins/dropdown/align.js +21 -33
  117. package/src/plugins/dropdown/backgroundColor.js +10 -2
  118. package/src/plugins/dropdown/blockStyle.js +17 -22
  119. package/src/plugins/dropdown/font.js +34 -34
  120. package/src/plugins/dropdown/hr.js +15 -43
  121. package/src/plugins/dropdown/layout.js +10 -27
  122. package/src/plugins/dropdown/lineHeight.js +10 -33
  123. package/src/plugins/dropdown/list.js +19 -25
  124. package/src/plugins/dropdown/paragraphStyle.js +16 -24
  125. package/src/plugins/dropdown/table/index.js +72 -17
  126. package/src/plugins/dropdown/table/render/table.html.js +3 -1
  127. package/src/plugins/dropdown/table/services/table.cell.js +33 -7
  128. package/src/plugins/dropdown/table/services/table.clipboard.js +5 -1
  129. package/src/plugins/dropdown/table/services/table.grid.js +40 -9
  130. package/src/plugins/dropdown/table/services/table.resize.js +55 -11
  131. package/src/plugins/dropdown/table/services/table.selection.js +27 -7
  132. package/src/plugins/dropdown/table/services/table.style.js +120 -20
  133. package/src/plugins/dropdown/template.js +13 -29
  134. package/src/plugins/dropdown/textStyle.js +22 -35
  135. package/src/plugins/field/autocomplete.js +8 -4
  136. package/src/plugins/field/slashCommand.js +297 -0
  137. package/src/plugins/index.js +3 -0
  138. package/src/plugins/input/fontSize.js +37 -8
  139. package/src/plugins/input/pageNavigator.js +7 -1
  140. package/src/plugins/modal/audio.js +71 -17
  141. package/src/plugins/modal/drawing.js +41 -11
  142. package/src/plugins/modal/embed.js +92 -22
  143. package/src/plugins/modal/image/index.js +114 -28
  144. package/src/plugins/modal/image/services/image.size.js +9 -2
  145. package/src/plugins/modal/image/services/image.upload.js +38 -4
  146. package/src/plugins/modal/link.js +9 -2
  147. package/src/plugins/modal/math.js +10 -2
  148. package/src/plugins/modal/video/index.js +112 -26
  149. package/src/plugins/modal/video/render/video.html.js +4 -1
  150. package/src/plugins/modal/video/services/video.size.js +15 -4
  151. package/src/plugins/modal/video/services/video.upload.js +10 -2
  152. package/src/plugins/popup/anchor.js +14 -2
  153. package/src/suneditor.js +8 -2
  154. package/src/themes/cobalt.css +12 -0
  155. package/src/themes/cream.css +12 -0
  156. package/src/themes/dark.css +12 -0
  157. package/src/themes/midnight.css +12 -0
  158. package/src/typedef.js +32 -21
  159. package/types/assets/icons/defaultIcons.d.ts +1 -0
  160. package/types/core/config/contextProvider.d.ts +7 -1
  161. package/types/core/config/eventManager.d.ts +37 -4
  162. package/types/core/config/optionProvider.d.ts +5 -1
  163. package/types/core/event/actions/index.d.ts +44 -6
  164. package/types/core/event/effects/keydown.registry.d.ts +37 -7
  165. package/types/core/event/effects/ruleHelpers.d.ts +6 -1
  166. package/types/core/event/eventOrchestrator.d.ts +13 -3
  167. package/types/core/event/handlers/handler_ww_clipboard.d.ts +15 -3
  168. package/types/core/event/handlers/handler_ww_dragDrop.d.ts +14 -2
  169. package/types/core/event/handlers/handler_ww_input.d.ts +10 -2
  170. package/types/core/event/handlers/handler_ww_key.d.ts +10 -2
  171. package/types/core/event/handlers/handler_ww_mouse.d.ts +25 -5
  172. package/types/core/event/ports.d.ts +11 -4
  173. package/types/core/event/reducers/keydown.reducer.d.ts +12 -3
  174. package/types/core/event/rules/keydown.rule.backspace.d.ts +6 -1
  175. package/types/core/kernel/store.d.ts +4 -1
  176. package/types/core/logic/dom/format.d.ts +32 -14
  177. package/types/core/logic/dom/html.d.ts +11 -3
  178. package/types/core/logic/dom/nodeTransform.d.ts +6 -6
  179. package/types/core/logic/panel/blockHandle.d.ts +64 -0
  180. package/types/core/logic/panel/blockResolver.d.ts +50 -0
  181. package/types/core/logic/panel/menu.d.ts +72 -3
  182. package/types/core/logic/shell/commandDispatcher.d.ts +8 -0
  183. package/types/core/logic/shell/component.d.ts +5 -3
  184. package/types/core/logic/shell/shortcuts.d.ts +10 -1
  185. package/types/core/logic/shell/ui.d.ts +7 -1
  186. package/types/core/schema/context.d.ts +7 -1
  187. package/types/core/schema/frameContext.d.ts +36 -4
  188. package/types/core/schema/options.d.ts +83 -2
  189. package/types/core/section/constructor.d.ts +38 -1
  190. package/types/events.d.ts +208 -32
  191. package/types/helper/converter.d.ts +4 -2
  192. package/types/helper/dom/domCheck.d.ts +12 -2
  193. package/types/helper/dom/domQuery.d.ts +35 -7
  194. package/types/helper/dom/domUtils.d.ts +4 -1
  195. package/types/interfaces/plugins.d.ts +2 -2
  196. package/types/langs/_Lang.d.ts +0 -1
  197. package/types/modules/contract/ColorPicker.d.ts +2 -2
  198. package/types/modules/contract/Controller.d.ts +7 -0
  199. package/types/modules/contract/Figure.d.ts +31 -4
  200. package/types/modules/ui/CommandMenu.d.ts +262 -0
  201. package/types/modules/ui/SelectMenu.d.ts +56 -3
  202. package/types/modules/ui/index.d.ts +1 -0
  203. package/types/plugins/browser/audioGallery.d.ts +1 -1
  204. package/types/plugins/browser/fileBrowser.d.ts +1 -1
  205. package/types/plugins/browser/fileGallery.d.ts +1 -1
  206. package/types/plugins/browser/imageGallery.d.ts +1 -1
  207. package/types/plugins/browser/videoGallery.d.ts +1 -1
  208. package/types/plugins/dropdown/align.d.ts +1 -1
  209. package/types/plugins/dropdown/blockStyle.d.ts +3 -1
  210. package/types/plugins/dropdown/table/index.d.ts +4 -1
  211. package/types/plugins/dropdown/table/services/table.clipboard.d.ts +5 -1
  212. package/types/plugins/dropdown/table/services/table.grid.d.ts +10 -2
  213. package/types/plugins/field/autocomplete.d.ts +0 -1
  214. package/types/plugins/field/slashCommand.d.ts +165 -0
  215. package/types/plugins/index.d.ts +3 -0
  216. package/types/plugins/modal/link.d.ts +4 -1
  217. package/types/typedef.d.ts +48 -23
@@ -23,7 +23,11 @@ export function reduceDeleteDown(actions, ports, ctx) {
23
23
 
24
24
  const selectRange = !range.collapsed || range.startContainer !== range.endContainer;
25
25
  // RTL bidi guard: if offset=length is actually at the visual start due to LTR text in RTL line, skip end-edge handling
26
- const bidiNotEnd = ctx.options.get('_rtl') && !selectRange && range.endOffset >= (range.endContainer.textContent?.length || 0) && isRtlBidiMismatch(range, formatEl, 'end', fc.get('_wd'));
26
+ const bidiNotEnd =
27
+ ctx.options.get('_rtl') &&
28
+ !selectRange &&
29
+ range.endOffset >= (range.endContainer.textContent?.length || 0) &&
30
+ isRtlBidiMismatch(range, formatEl, 'end', fc.get('_wd'));
27
31
 
28
32
  actions.push(A.componentDeselect());
29
33
  actions.push(A.cacheStyleNode());
@@ -33,7 +37,12 @@ export function reduceDeleteDown(actions, ports, ctx) {
33
37
  return true;
34
38
  }
35
39
 
36
- if (!selectRange && !bidiNotEnd && format.isEdgeLine(range.endContainer, range.endOffset, 'end') && !formatEl.nextSibling) {
40
+ if (
41
+ !selectRange &&
42
+ !bidiNotEnd &&
43
+ format.isEdgeLine(range.endContainer, range.endOffset, 'end') &&
44
+ !formatEl.nextSibling
45
+ ) {
37
46
  actions.push(A.preventStop());
38
47
  return false;
39
48
  }
@@ -54,7 +63,11 @@ export function reduceDeleteDown(actions, ports, ctx) {
54
63
  }
55
64
 
56
65
  // line component
57
- if (!selectRange && formatEl && (range.endOffset === range.endContainer.textContent.length || selectionNode === formatEl)) {
66
+ if (
67
+ !selectRange &&
68
+ formatEl &&
69
+ (range.endOffset === range.endContainer.textContent.length || selectionNode === formatEl)
70
+ ) {
58
71
  const sel =
59
72
  selectionNode === formatEl
60
73
  ? isUneditableNode(ports, range, false)
@@ -81,7 +94,9 @@ export function reduceDeleteDown(actions, ports, ctx) {
81
94
 
82
95
  // component
83
96
  if (
84
- (format.isLine(selectionNode) || selectionNode.nextSibling === null || (dom.check.isZeroWidth(selectionNode.nextSibling) && selectionNode.nextSibling.nextSibling === null)) &&
97
+ (format.isLine(selectionNode) ||
98
+ selectionNode.nextSibling === null ||
99
+ (dom.check.isZeroWidth(selectionNode.nextSibling) && selectionNode.nextSibling.nextSibling === null)) &&
85
100
  range.startOffset === selectionNode.textContent.length
86
101
  ) {
87
102
  const nextEl = formatEl.nextElementSibling;
@@ -94,8 +109,13 @@ export function reduceDeleteDown(actions, ports, ctx) {
94
109
  }
95
110
  }
96
111
 
97
- if (!selectRange && (dom.check.isEdgePoint(range.endContainer, range.endOffset) || (selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : false))) {
98
- const sel = selectionNode === formatEl ? formatEl.childNodes[range.startOffset] || selectionNode : selectionNode;
112
+ if (
113
+ !selectRange &&
114
+ (dom.check.isEdgePoint(range.endContainer, range.endOffset) ||
115
+ (selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : false))
116
+ ) {
117
+ const sel =
118
+ selectionNode === formatEl ? formatEl.childNodes[range.startOffset] || selectionNode : selectionNode;
99
119
  // delete nonEditable
100
120
  if (sel && dom.check.isNonEditable(sel.nextSibling)) {
101
121
  actions.push(A.preventStop());
@@ -124,11 +144,46 @@ export function reduceDeleteDown(actions, ports, ctx) {
124
144
  (selectionNode === formatEl ||
125
145
  (selectionNode.nodeType === 3 &&
126
146
  (!selectionNode.nextSibling || dom.check.isList(selectionNode.nextSibling)) &&
127
- (format.getLine(range.startContainer, null) !== format.getLine(range.endContainer, null) ? rangeEl.contains(range.endContainer) : range.endOffset === selectionNode.textContent.length && range.collapsed && !bidiNotEnd)))
147
+ (format.getLine(range.startContainer, null) !== format.getLine(range.endContainer, null)
148
+ ? rangeEl.contains(range.endContainer)
149
+ : range.endOffset === selectionNode.textContent.length && range.collapsed && !bidiNotEnd)))
128
150
  ) {
129
151
  actions.push(A.deleteListRemoveNested(range, formatEl, rangeEl));
130
152
  return true;
131
153
  }
132
154
 
155
+ // empty row inside a brLine (PRE): Enter leaves the caret on a bare <br> that ends an empty row
156
+ if (
157
+ !selectRange &&
158
+ format.isBrLine(formatEl) &&
159
+ dom.check.isBreak(range.startContainer) &&
160
+ range.startOffset === 0
161
+ ) {
162
+ let rowStartBr = range.startContainer.previousSibling;
163
+ if (rowStartBr?.nodeType === 3 && dom.check.isZeroWidth(rowStartBr)) rowStartBr = rowStartBr.previousSibling;
164
+ if (dom.check.isBreak(rowStartBr)) {
165
+ actions.push(A.preventStop());
166
+ actions.push(A.deleteBrLineRowMerge(range.startContainer));
167
+ actions.push(A.historyPush(true));
168
+ return false;
169
+ }
170
+ }
171
+
172
+ // empty line
173
+ const emptyLineNext = formatEl?.nextElementSibling;
174
+ if (
175
+ !selectRange &&
176
+ formatEl &&
177
+ format.isNormalLine(formatEl) &&
178
+ !dom.check.isListCell(formatEl) &&
179
+ dom.check.isEmptyLine(formatEl) &&
180
+ (format.isNormalLine(emptyLineNext) || format.isBrLine(emptyLineNext))
181
+ ) {
182
+ actions.push(A.preventStop());
183
+ actions.push(A.deleteEmptyLineMergeNext(formatEl, emptyLineNext));
184
+ actions.push(A.historyPush(true));
185
+ return false;
186
+ }
187
+
133
188
  return true;
134
189
  }
@@ -2,6 +2,42 @@ import { dom } from '../../../helper';
2
2
  import { isRtlBidiMismatch } from '../effects/ruleHelpers';
3
3
  import { A } from '../actions';
4
4
 
5
+ /**
6
+ * @description Decide what an Enter should do inside a normal brLine
7
+ * @param {Node} brBlock The brLine element (e.g. `PRE`).
8
+ * @param {Selection} sel The live DOM selection.
9
+ * @returns {{ shouldExit: boolean }}
10
+ */
11
+ function analyzeBrLineEnter(brBlock, sel) {
12
+ const kids = Array.from(brBlock.childNodes);
13
+
14
+ // Split into rows by <br>; drop the trailing placeholder row (last child is a <br>).
15
+ const rows = [[]];
16
+ for (const n of kids) {
17
+ if (dom.check.isBreak(n)) rows.push([]);
18
+ else rows[rows.length - 1].push(n);
19
+ }
20
+ if (kids.length && dom.check.isBreak(kids[kids.length - 1])) rows.pop();
21
+ const rowEmpty = (row) => !row || row.every((n) => dom.check.isZeroWidth(n.textContent));
22
+
23
+ // Caret's row = number of <br>s strictly before the caret anchor.
24
+ const a = sel.anchorNode;
25
+ let brBefore = 0;
26
+ if (a === brBlock) {
27
+ for (let i = 0; i < sel.anchorOffset && i < kids.length; i++) if (dom.check.isBreak(kids[i])) brBefore++;
28
+ } else {
29
+ for (const n of kids) {
30
+ if (n === a || (n.nodeType === 1 && n.contains(a))) break;
31
+ if (dom.check.isBreak(n)) brBefore++;
32
+ }
33
+ }
34
+
35
+ const N = Math.max(rows.length, 1);
36
+ const R = Math.min(brBefore, N - 1);
37
+ const shouldExit = R === N - 1 && rowEmpty(rows[R]) && R >= 1 && rowEmpty(rows[R - 1]);
38
+ return { shouldExit };
39
+ }
40
+
5
41
  /**
6
42
  * @typedef {import('../actions').Action[]} EventActions
7
43
  * @typedef {import('../ports').EventReducerPorts} EventPorts
@@ -69,7 +105,10 @@ export function reduceEnterDown(actions, ports, ctx) {
69
105
  } else if (rangeEl && formatEl && !dom.check.isTableCell(rangeEl) && !/^FIGCAPTION$/i.test(rangeEl.nodeName)) {
70
106
  // add default List line
71
107
  const rangeEnt = selection.getRange();
72
- if (dom.check.isEdgePoint(rangeEnt.endContainer, rangeEnt.endOffset) && dom.check.isList(selectionNode.nextSibling)) {
108
+ if (
109
+ dom.check.isEdgePoint(rangeEnt.endContainer, rangeEnt.endOffset) &&
110
+ dom.check.isList(selectionNode.nextSibling)
111
+ ) {
73
112
  ports.enterPrevent(e);
74
113
  actions.push(A.enterListAddItem(formatEl, selectionNode));
75
114
  actions.push(A.enterScrollTo(range));
@@ -77,7 +116,9 @@ export function reduceEnterDown(actions, ports, ctx) {
77
116
  }
78
117
 
79
118
  if (
80
- (rangeEnt.commonAncestorContainer.nodeType === 3 ? !(/** @type {HTMLElement} */ (rangeEnt.commonAncestorContainer).nextElementSibling) : true) &&
119
+ (rangeEnt.commonAncestorContainer.nodeType === 3
120
+ ? !(/** @type {HTMLElement} */ (rangeEnt.commonAncestorContainer).nextElementSibling)
121
+ : true) &&
81
122
  dom.check.isZeroWidth(formatEl.innerText.trim()) &&
82
123
  !dom.check.isListCell(formatEl.nextElementSibling)
83
124
  ) {
@@ -91,40 +132,24 @@ export function reduceEnterDown(actions, ports, ctx) {
91
132
  if (brBlock || (rangeEl === formatEl && format.isClosureBlock(rangeEl) && format.isLine(formatEl))) {
92
133
  ports.enterPrevent(e);
93
134
 
94
- const selectionFormat = selectionNode === brBlock;
95
- const wSelection = selection.get();
96
- const children = selectionNode.childNodes,
97
- offset = wSelection.focusOffset,
98
- prev = selectionNode.previousElementSibling,
99
- next = selectionNode.nextSibling;
100
-
101
- if (
102
- !format.isClosureBrLine(brBlock) &&
103
- children &&
104
- ((selectionFormat &&
105
- range.collapsed &&
106
- children.length - 1 <= offset + 1 &&
107
- dom.check.isBreak(children[offset]) &&
108
- (!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))) &&
109
- offset > 0 &&
110
- dom.check.isBreak(children[offset - 1])) ||
111
- (!selectionFormat &&
112
- dom.check.isZeroWidth(selectionNode.textContent) &&
113
- dom.check.isBreak(prev) &&
114
- (dom.check.isBreak(prev.previousSibling) || !dom.check.isZeroWidth(prev.previousSibling?.textContent)) &&
115
- (!next || (!dom.check.isBreak(next) && dom.check.isZeroWidth(next.textContent)))))
116
- ) {
117
- actions.push(A.enterFormatCleanBrAndZWS(selectionNode, selectionFormat, brBlock, children, offset));
135
+ // Normal brLine (e.g. PRE)
136
+ if (brBlock && !format.isClosureBrLine(brBlock)) {
137
+ if (analyzeBrLineEnter(brBlock, selection.get()).shouldExit) {
138
+ actions.push(A.enterBrLineExit(brBlock));
139
+ } else {
140
+ actions.push(A.enterBrLineInsert(range));
141
+ }
118
142
  actions.push(A.enterScrollTo(range));
119
143
  return true;
120
144
  }
121
145
 
122
- if (selectionFormat) {
123
- actions.push(A.enterFormatInsertBrHtml(brBlock, range, wSelection, offset));
146
+ // Closure brLine / closure block
147
+ const wSelection = selection.get();
148
+ if (selectionNode === brBlock) {
149
+ actions.push(A.enterFormatInsertBrHtml(brBlock, range, wSelection, wSelection.focusOffset));
124
150
  } else {
125
151
  actions.push(A.enterFormatInsertBrNode(wSelection));
126
152
  }
127
-
128
153
  actions.push(A.enterScrollTo(range));
129
154
  return true;
130
155
  }
@@ -132,7 +157,9 @@ export function reduceEnterDown(actions, ports, ctx) {
132
157
  // set format attrs - edge
133
158
  if (range.collapsed && (formatStartEdge || formatEndEdge)) {
134
159
  ports.enterPrevent(e);
135
- actions.push(A.enterFormatBreakAtEdge(formatEl, selectionNode, formatStartEdge, formatEndEdge, bidiSwapped));
160
+ actions.push(
161
+ A.enterFormatBreakAtEdge(formatEl, selectionNode, formatStartEdge, formatEndEdge, bidiSwapped),
162
+ );
136
163
  actions.push(A.enterScrollTo(range));
137
164
  return true;
138
165
  }
@@ -170,7 +197,11 @@ export function reduceEnterDown(actions, ports, ctx) {
170
197
  return true;
171
198
  }
172
199
 
173
- if (rangeEl && dom.query.getParentElement(rangeEl, 'FIGCAPTION') && dom.query.getParentElement(rangeEl, dom.check.isList)) {
200
+ if (
201
+ rangeEl &&
202
+ dom.query.getParentElement(rangeEl, 'FIGCAPTION') &&
203
+ dom.query.getParentElement(rangeEl, dom.check.isList)
204
+ ) {
174
205
  ports.enterPrevent(e);
175
206
  actions.push(A.enterFigcaptionExitInList(formatEl));
176
207
  actions.push(A.enterScrollTo(range));
@@ -79,7 +79,12 @@ export default class DefaultLineManager {
79
79
  return;
80
80
  }
81
81
 
82
- if ((this.#$.format.isBlock(startCon) || dom.check.isWysiwygFrame(startCon)) && (this.#$.component.is(startCon.children[range.startOffset]) || this.#$.component.is(startCon.children[range.startOffset - 1]))) return;
82
+ if (
83
+ (this.#$.format.isBlock(startCon) || dom.check.isWysiwygFrame(startCon)) &&
84
+ (this.#$.component.is(startCon.children[range.startOffset]) ||
85
+ this.#$.component.is(startCon.children[range.startOffset - 1]))
86
+ )
87
+ return;
83
88
  if (dom.query.getParentElement(commonCon, dom.check.isExcludeFormat)) return null;
84
89
 
85
90
  if (this.#$.format.isBlock(commonCon) && commonCon.childNodes.length <= 1) {
@@ -110,7 +115,9 @@ export default class DefaultLineManager {
110
115
  focusNode = zeroWidth;
111
116
  }
112
117
  } catch {
113
- this.#$.frameContext.get('_wd').execCommand('formatBlock', false, `<${formatName || this.#$.options.get('defaultLine')}>`);
118
+ this.#$.frameContext
119
+ .get('_wd')
120
+ .execCommand('formatBlock', false, `<${formatName || this.#$.options.get('defaultLine')}>`);
114
121
  this.#$.store.set('_lastSelectionNode', null);
115
122
  this.#$.selection.init();
116
123
  return;
@@ -19,7 +19,10 @@ export default class SelectionState {
19
19
  constructor(eventOrchestrator) {
20
20
  this.#eventOrchestrator = eventOrchestrator;
21
21
  this.#$ = eventOrchestrator.$;
22
- this.#onButtonsCheck = new RegExp(`^(${Object.keys(this.#$.options.get('_defaultStyleTagMap')).join('|')})$`, 'i');
22
+ this.#onButtonsCheck = new RegExp(
23
+ `^(${Object.keys(this.#$.options.get('_defaultStyleTagMap')).join('|')})$`,
24
+ 'i',
25
+ );
23
26
  }
24
27
 
25
28
  /**
@@ -101,7 +104,12 @@ export default class SelectionState {
101
104
  /** indent, outdent */
102
105
  if (this.#$.format.isLine(element)) {
103
106
  /* Outdent */
104
- if (!commandMapNodes.includes('outdent') && commandTargets.has('outdent') && (dom.check.isListCell(element) || (element.style[marginDir] && numbers.get(element.style[marginDir], 0) > 0))) {
107
+ if (
108
+ !commandMapNodes.includes('outdent') &&
109
+ commandTargets.has('outdent') &&
110
+ (dom.check.isListCell(element) ||
111
+ (element.style[marginDir] && numbers.get(element.style[marginDir], 0) > 0))
112
+ ) {
105
113
  if (
106
114
  commandTargets.get('outdent').filter((e) => {
107
115
  if (dom.check.isImportantDisabled(e)) return false;
@@ -148,7 +156,9 @@ export default class SelectionState {
148
156
 
149
157
  /** Displays the current node structure to statusbar */
150
158
  if (this.#$.frameOptions.get('statusbar_showPathLabel') && fc.get('navigation')) {
151
- fc.get('navigation').textContent = this.#$.options.get('_rtl') ? this.#$.store.get('currentNodes').reverse().join(' < ') : this.#$.store.get('currentNodes').join(' > ');
159
+ fc.get('navigation').textContent = this.#$.options.get('_rtl')
160
+ ? this.#$.store.get('currentNodes').reverse().join(' < ')
161
+ : this.#$.store.get('currentNodes').join(' > ');
152
162
  }
153
163
 
154
164
  return selectionNode;
@@ -129,6 +129,7 @@ class CoreKernel {
129
129
 
130
130
  // Event orchestrator
131
131
  this._eventOrchestrator = new EventOrchestrator(this);
132
+ this.#config.get('eventManager')._bindOrchestrator(this._eventOrchestrator);
132
133
  }
133
134
 
134
135
  /**
@@ -33,7 +33,13 @@ class Char {
33
33
  check(html) {
34
34
  const maxCharCount = this.#frameOptions.get('charCounter_max');
35
35
  if (maxCharCount) {
36
- const length = this.getLength(typeof html === 'string' ? html : this.#frameOptions.get('charCounter_type') === 'byte-html' && html.nodeType === 1 ? /** @type {HTMLElement} */ (html).outerHTML : html.textContent);
36
+ const length = this.getLength(
37
+ typeof html === 'string'
38
+ ? html
39
+ : this.#frameOptions.get('charCounter_type') === 'byte-html' && html.nodeType === 1
40
+ ? /** @type {HTMLElement} */ (html).outerHTML
41
+ : html.textContent,
42
+ );
37
43
  if (length > 0 && length + this.getLength() > maxCharCount) {
38
44
  CounterBlink(this.#frameContext.get('charWrapper'));
39
45
  return false;
@@ -53,7 +59,10 @@ class Char {
53
59
  */
54
60
  getLength(content) {
55
61
  if (typeof content !== 'string') {
56
- content = this.#frameOptions.get('charCounter_type') === 'byte-html' ? this.#frameContext.get('wysiwyg').innerHTML : this.#frameContext.get('wysiwyg').textContent;
62
+ content =
63
+ this.#frameOptions.get('charCounter_type') === 'byte-html'
64
+ ? this.#frameContext.get('wysiwyg').innerHTML
65
+ : this.#frameContext.get('wysiwyg').textContent;
57
66
  }
58
67
  return /byte/.test(this.#frameOptions.get('charCounter_type')) ? this.getByteLength(content) : content.length;
59
68
  }
@@ -160,7 +169,8 @@ class Char {
160
169
  const text = this.#$.selection.getNode().textContent;
161
170
  const slicePosition = range.endOffset - 1; // (count - maxCharCount);
162
171
 
163
- this.#$.selection.getNode().textContent = text.slice(0, slicePosition < 0 ? 0 : slicePosition) + text.slice(range.endOffset, text.length);
172
+ this.#$.selection.getNode().textContent =
173
+ text.slice(0, slicePosition < 0 ? 0 : slicePosition) + text.slice(range.endOffset, text.length);
164
174
  this.#$.selection.setRange(range.endContainer, endOff, range.endContainer, endOff);
165
175
  }
166
176
  } else if (count + nextCharCount > maxCharCount) {