suneditor 3.0.0-beta.26 → 3.0.0-beta.28
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.
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +77 -39
- package/src/core/{section → base}/actives.js +1 -1
- package/src/core/class/component.js +2 -0
- package/src/core/class/format.js +44 -2435
- package/src/core/class/html.js +5 -4
- package/src/core/class/inline.js +1853 -0
- package/src/core/class/listFormat.js +582 -0
- package/src/core/class/nodeTransform.js +1 -3
- package/src/core/class/selection.js +4 -2
- package/src/core/class/ui.js +1 -1
- package/src/core/class/viewer.js +4 -4
- package/src/core/config/options.js +37 -18
- package/src/core/editor.js +43 -29
- package/src/core/event/actions/index.js +229 -0
- package/src/core/event/effects/common.registry.js +60 -0
- package/src/core/event/effects/keydown.registry.js +551 -0
- package/src/core/event/effects/ruleHelpers.js +145 -0
- package/src/core/{base → event}/eventManager.js +8 -124
- package/src/core/event/executor.js +21 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +1 -1
- package/src/core/event/handlers/handler_ww_input.js +77 -0
- package/src/core/event/handlers/handler_ww_key.js +228 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.js +3 -3
- package/src/core/event/ports.js +211 -0
- package/src/core/event/reducers/keydown.reducer.js +89 -0
- package/src/core/event/rules/keydown.rule.arrow.js +54 -0
- package/src/core/event/rules/keydown.rule.backspace.js +202 -0
- package/src/core/event/rules/keydown.rule.delete.js +126 -0
- package/src/core/event/rules/keydown.rule.enter.js +144 -0
- package/src/core/event/rules/keydown.rule.tab.js +29 -0
- package/src/core/section/constructor.js +57 -23
- package/src/editorInjector/_classes.js +4 -0
- package/src/editorInjector/index.js +4 -0
- package/src/helper/clipboard.js +0 -1
- package/src/helper/converter.js +6 -7
- package/src/helper/dom/domCheck.js +1 -1
- package/src/helper/dom/domQuery.js +1 -1
- package/src/helper/dom/domUtils.js +2 -2
- package/src/helper/dom/index.js +4 -0
- package/src/helper/env.js +1 -6
- package/src/helper/keyCodeMap.js +0 -1
- package/src/langs/ckb.js +1 -1
- package/src/langs/cs.js +1 -1
- package/src/langs/da.js +1 -1
- package/src/langs/de.js +1 -1
- package/src/langs/en.js +1 -1
- package/src/langs/es.js +1 -1
- package/src/langs/fa.js +1 -1
- package/src/langs/fr.js +1 -1
- package/src/langs/he.js +1 -1
- package/src/langs/hu.js +1 -1
- package/src/langs/it.js +1 -1
- package/src/langs/ja.js +1 -1
- package/src/langs/km.js +1 -1
- package/src/langs/ko.js +1 -1
- package/src/langs/lv.js +1 -1
- package/src/langs/nl.js +1 -1
- package/src/langs/pl.js +1 -1
- package/src/langs/pt_br.js +1 -1
- package/src/langs/ro.js +1 -1
- package/src/langs/ru.js +1 -1
- package/src/langs/se.js +1 -1
- package/src/langs/tr.js +1 -1
- package/src/langs/uk.js +1 -1
- package/src/langs/ur.js +1 -1
- package/src/langs/zh_cn.js +1 -1
- package/src/modules/ApiManager.js +5 -0
- package/src/modules/Figure.js +4 -10
- package/src/modules/HueSlider.js +18 -4
- package/src/modules/SelectMenu.js +1 -1
- package/src/plugins/command/fileUpload.js +1 -1
- package/src/plugins/command/list_bulleted.js +1 -1
- package/src/plugins/command/list_numbered.js +1 -1
- package/src/plugins/dropdown/backgroundColor.js +2 -2
- package/src/plugins/dropdown/font.js +2 -2
- package/src/plugins/dropdown/fontColor.js +2 -2
- package/src/plugins/dropdown/list.js +1 -1
- package/src/plugins/dropdown/table.js +1 -3
- package/src/plugins/dropdown/textStyle.js +1 -1
- package/src/plugins/field/mention.js +2 -2
- package/src/plugins/input/fontSize.js +9 -9
- package/src/plugins/modal/audio.js +5 -5
- package/src/plugins/modal/embed.js +5 -5
- package/src/plugins/modal/image.js +7 -7
- package/src/plugins/modal/link.js +23 -8
- package/src/plugins/modal/video.js +5 -5
- package/src/suneditor.js +9 -34
- package/src/typedef.js +15 -9
- package/types/core/class/format.d.ts +2 -352
- package/types/core/class/html.d.ts +2 -2
- package/types/core/class/inline.d.ts +263 -0
- package/types/core/class/listFormat.d.ts +135 -0
- package/types/core/config/options.d.ts +52 -78
- package/types/core/editor.d.ts +22 -12
- package/types/core/event/actions/index.d.ts +47 -0
- package/types/core/event/effects/common.registry.d.ts +50 -0
- package/types/core/event/effects/keydown.registry.d.ts +73 -0
- package/types/core/event/effects/ruleHelpers.d.ts +31 -0
- package/types/core/{base → event}/eventManager.d.ts +0 -42
- package/types/core/event/executor.d.ts +6 -0
- package/types/core/event/handlers/handler_ww_input.d.ts +41 -0
- package/types/core/{base/eventHandlers/handler_ww_key_input.d.ts → event/handlers/handler_ww_key.d.ts} +4 -33
- package/types/core/event/ports.d.ts +255 -0
- package/types/core/event/reducers/keydown.reducer.d.ts +75 -0
- package/types/core/event/rules/keydown.rule.arrow.d.ts +8 -0
- package/types/core/event/rules/keydown.rule.backspace.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.delete.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.enter.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.tab.d.ts +9 -0
- package/types/core/section/constructor.d.ts +165 -39
- package/types/editorInjector/_classes.d.ts +4 -0
- package/types/editorInjector/index.d.ts +4 -0
- package/types/helper/converter.d.ts +4 -20
- package/types/helper/dom/index.d.ts +86 -1
- package/types/index.d.ts +11 -121
- package/types/langs/index.d.ts +2 -2
- package/types/modules/HueSlider.d.ts +12 -0
- package/types/modules/index.d.ts +3 -3
- package/types/plugins/index.d.ts +38 -38
- package/types/plugins/modal/link.d.ts +6 -4
- package/types/suneditor.d.ts +18 -19
- package/types/typedef.d.ts +6 -2
- package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1267
- package/types/core/section/context.d.ts +0 -67
- package/types/core/section/options.d.ts +0 -1022
- package/types/langs/_Lang.d.ts +0 -194
- /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +0 -0
- /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +0 -0
- /package/types/core/{section → base}/actives.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_toolbar.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.d.ts +0 -0
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
import { dom, unicode } from '../../../helper';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} EffectContext_keydown
|
|
5
|
+
* @property {__se__EventPorts} ports - Ports for interacting with editor
|
|
6
|
+
* @property {__se__EventKeydownCtx} ctx - Reducer context
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {(ctx: EffectContext_keydown, payload?: *) => *} Effect
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** @type {Record<string, Effect>} */
|
|
14
|
+
export default {
|
|
15
|
+
// backspace and delete
|
|
16
|
+
/** @action delFormatRemoveAndMove */
|
|
17
|
+
'del.format.removeAndMove': ({ ports }, { container, formatEl }) => {
|
|
18
|
+
const rInfo = ports.html.remove();
|
|
19
|
+
if (rInfo.commonCon !== rInfo.container && formatEl.parentElement) {
|
|
20
|
+
if (formatEl.contains(container)) {
|
|
21
|
+
const focusNode = LineDelete_next(formatEl);
|
|
22
|
+
ports.selection.setRange(focusNode, focusNode.textContent.length, focusNode, focusNode.textContent.length);
|
|
23
|
+
} else {
|
|
24
|
+
const { focusNode, focusOffset } = LineDelete_prev(formatEl);
|
|
25
|
+
ports.selection.setRange(focusNode, focusOffset, focusNode, focusOffset);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
// backspace
|
|
31
|
+
/** @action backspaceFormatMaintain */
|
|
32
|
+
'backspace.format.maintain': ({ ctx }, { formatEl }) => {
|
|
33
|
+
if (formatEl.nodeName.toUpperCase() === ctx.options.get('defaultLine').toUpperCase()) {
|
|
34
|
+
formatEl.innerHTML = '<br>';
|
|
35
|
+
const attrs = formatEl.attributes;
|
|
36
|
+
while (attrs[0]) {
|
|
37
|
+
formatEl.removeAttribute(attrs[0].name);
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
formatEl.parentNode.replaceChild(dom.utils.createElement(ctx.options.get('defaultLine'), null, '<br>'), formatEl);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
/** @action backspaceComponentSelect */
|
|
44
|
+
'backspace.component.select': ({ ports }, { selectionNode, range, fileComponentInfo }) => {
|
|
45
|
+
let currentZWS = null;
|
|
46
|
+
if (dom.check.isBreak(selectionNode)) dom.utils.removeItem(selectionNode);
|
|
47
|
+
else if (dom.check.isBreak((currentZWS = range.startContainer.childNodes?.[range.startOffset]))) dom.utils.removeItem(currentZWS);
|
|
48
|
+
|
|
49
|
+
if (ports.component.select(fileComponentInfo.target, fileComponentInfo.pluginName) === false) ports.editor.blur();
|
|
50
|
+
},
|
|
51
|
+
/** @action backspaceComponentRemove */
|
|
52
|
+
'backspace.component.remove': ({ ports }, { isList, sel, formatEl, fileComponentInfo }) => {
|
|
53
|
+
if (isList) dom.utils.removeItem(sel);
|
|
54
|
+
if (formatEl.textContent.length === 0) dom.utils.removeItem(formatEl);
|
|
55
|
+
if (ports.component.select(fileComponentInfo.target, fileComponentInfo.pluginName) === false) ports.editor.blur();
|
|
56
|
+
},
|
|
57
|
+
/** @action backspaceListMergePrev */
|
|
58
|
+
'backspace.list.mergePrev': ({ ports }, { prev, formatEl, rangeEl }) => {
|
|
59
|
+
let con = prev === rangeEl.parentNode ? rangeEl.previousSibling : prev.lastChild;
|
|
60
|
+
if (!con) {
|
|
61
|
+
con = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
62
|
+
rangeEl.parentNode.insertBefore(con, rangeEl.parentNode.firstChild);
|
|
63
|
+
}
|
|
64
|
+
const offset = con.nodeType === 3 ? con.textContent.length : 1;
|
|
65
|
+
const children = formatEl.childNodes;
|
|
66
|
+
let after = con;
|
|
67
|
+
let child = children[0];
|
|
68
|
+
while ((child = children[0])) {
|
|
69
|
+
prev.insertBefore(child, after.nextSibling);
|
|
70
|
+
after = child;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
dom.utils.removeItem(formatEl);
|
|
74
|
+
if (rangeEl.children.length === 0) dom.utils.removeItem(rangeEl);
|
|
75
|
+
|
|
76
|
+
ports.selection.setRange(con, offset, con, offset);
|
|
77
|
+
},
|
|
78
|
+
/** @action backspaceListRemoveNested */
|
|
79
|
+
'backspace.list.removeNested': ({ ports }, { range }) => {
|
|
80
|
+
ports.html.remove();
|
|
81
|
+
if (range.startContainer.nodeType === 3) {
|
|
82
|
+
ports.selection.setRange(range.startContainer, range.startContainer.textContent.length, range.startContainer, range.startContainer.textContent.length);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// delete
|
|
87
|
+
/** @action deleteComponentSelect */
|
|
88
|
+
'delete.component.select': ({ ports }, { formatEl, fileComponentInfo }) => {
|
|
89
|
+
if (dom.check.isListCell(formatEl)) {
|
|
90
|
+
const prev = fileComponentInfo.container.previousSibling;
|
|
91
|
+
if (dom.check.isZeroWidth(prev)) dom.utils.removeItem(prev);
|
|
92
|
+
} else if (dom.check.isZeroWidth(formatEl)) {
|
|
93
|
+
dom.utils.removeItem(formatEl);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (ports.component.select(fileComponentInfo.target, fileComponentInfo.pluginName) === false) ports.editor.blur();
|
|
97
|
+
},
|
|
98
|
+
/** @action deleteComponentSelectNext */
|
|
99
|
+
'delete.component.selectNext': ({ ports, ctx }, { formatEl, nextEl }) => {
|
|
100
|
+
if (dom.check.isZeroWidth(formatEl)) {
|
|
101
|
+
dom.utils.removeItem(formatEl);
|
|
102
|
+
// table component
|
|
103
|
+
if (dom.check.isTable(nextEl)) {
|
|
104
|
+
let cell = /** @type {HTMLElement} */ (dom.query.getEdgeChild(nextEl, dom.check.isTableCell, false));
|
|
105
|
+
cell = /** @type {HTMLElement} */ (cell.firstElementChild || cell);
|
|
106
|
+
|
|
107
|
+
ports.selection.setRange(cell, 0, cell, 0);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// select file component
|
|
113
|
+
const fileComponentInfo = ports.component.get(nextEl);
|
|
114
|
+
if (fileComponentInfo) {
|
|
115
|
+
ctx.e.stopPropagation();
|
|
116
|
+
if (ports.component.select(fileComponentInfo.target, fileComponentInfo.pluginName) === false) ports.editor.blur();
|
|
117
|
+
} else if (ports.component.is(nextEl)) {
|
|
118
|
+
ctx.e.stopPropagation();
|
|
119
|
+
dom.utils.removeItem(nextEl);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
/** @action deleteListRemoveNested */
|
|
123
|
+
'delete.list.removeNested': ({ ports, ctx }, { range, formatEl, rangeEl }) => {
|
|
124
|
+
if (range.startContainer !== range.endContainer) ports.html.remove();
|
|
125
|
+
|
|
126
|
+
const next = /** @type {HTMLElement} */ (dom.utils.arrayFind(formatEl.children, dom.check.isList) || formatEl.nextElementSibling || rangeEl.parentElement.nextElementSibling);
|
|
127
|
+
if (next && (dom.check.isList(next) || dom.utils.arrayFind(next.children, dom.check.isList))) {
|
|
128
|
+
ctx.e.preventDefault();
|
|
129
|
+
|
|
130
|
+
let con, children;
|
|
131
|
+
if (dom.check.isList(next)) {
|
|
132
|
+
const child = next.firstElementChild;
|
|
133
|
+
children = child.childNodes;
|
|
134
|
+
con = children[0];
|
|
135
|
+
while (children[0]) {
|
|
136
|
+
formatEl.insertBefore(children[0], next);
|
|
137
|
+
}
|
|
138
|
+
dom.utils.removeItem(child);
|
|
139
|
+
} else {
|
|
140
|
+
con = next.firstChild;
|
|
141
|
+
children = next.childNodes;
|
|
142
|
+
while (children[0]) {
|
|
143
|
+
formatEl.appendChild(children[0]);
|
|
144
|
+
}
|
|
145
|
+
dom.utils.removeItem(next);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
ports.selection.setRange(con, 0, con, 0);
|
|
149
|
+
ports.history.push(true);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
// tab
|
|
154
|
+
/** @action tabFormatIndent */
|
|
155
|
+
'tab.format.indent': ({ ports, ctx }, { range, formatEl, shift }) => {
|
|
156
|
+
const selectedFormats = ports.format.getLines(null);
|
|
157
|
+
|
|
158
|
+
const cells = [];
|
|
159
|
+
const lines = [];
|
|
160
|
+
const firstCell = dom.check.isListCell(selectedFormats[0]),
|
|
161
|
+
lastCell = dom.check.isListCell(selectedFormats.at(-1));
|
|
162
|
+
let r = {
|
|
163
|
+
sc: range.startContainer,
|
|
164
|
+
so: range.startOffset,
|
|
165
|
+
ec: range.endContainer,
|
|
166
|
+
eo: range.endOffset
|
|
167
|
+
};
|
|
168
|
+
for (let i = 0, len = selectedFormats.length, f; i < len; i++) {
|
|
169
|
+
f = selectedFormats[i];
|
|
170
|
+
if (dom.check.isListCell(f)) {
|
|
171
|
+
if (!f.previousElementSibling && !shift) {
|
|
172
|
+
continue;
|
|
173
|
+
} else {
|
|
174
|
+
cells.push(f);
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
lines.push(f);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Nested list
|
|
182
|
+
if (cells.length > 0) {
|
|
183
|
+
r = ports.listFormat.applyNested(cells, shift);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Lines tab
|
|
187
|
+
if (lines.length > 0) {
|
|
188
|
+
if (!shift) {
|
|
189
|
+
if (lines.length === 1) {
|
|
190
|
+
let tabSize = ctx.status.tabSize + 1;
|
|
191
|
+
if (ctx.options.get('syncTabIndent')) {
|
|
192
|
+
const baseIndex = dom.query.findTextIndexOnLine(formatEl, range.startContainer, range.startOffset, (current) => ports.component.is(current));
|
|
193
|
+
const prevTabEndIndex = ports.format.isLine(formatEl.previousElementSibling) ? dom.query.findTabEndIndex(formatEl.previousElementSibling, baseIndex, 2) : 0;
|
|
194
|
+
if (prevTabEndIndex > baseIndex) {
|
|
195
|
+
tabSize = prevTabEndIndex - baseIndex;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const tabText = dom.utils.createTextNode(new Array(tabSize).join('\u00A0'));
|
|
200
|
+
if (!ports.html.insertNode(tabText, { afterNode: null, skipCharCount: false })) return false;
|
|
201
|
+
if (!firstCell) {
|
|
202
|
+
r.sc = tabText;
|
|
203
|
+
r.so = tabText.length;
|
|
204
|
+
}
|
|
205
|
+
if (!lastCell) {
|
|
206
|
+
r.ec = tabText;
|
|
207
|
+
r.eo = tabText.length;
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
const tabText = dom.utils.createTextNode(new Array(ctx.status.tabSize + 1).join('\u00A0'));
|
|
211
|
+
const len = lines.length - 1;
|
|
212
|
+
for (let i = 0, child; i <= len; i++) {
|
|
213
|
+
child = lines[i].firstChild;
|
|
214
|
+
if (!child) continue;
|
|
215
|
+
|
|
216
|
+
if (dom.check.isBreak(child)) {
|
|
217
|
+
lines[i].insertBefore(tabText.cloneNode(false), child);
|
|
218
|
+
} else {
|
|
219
|
+
child.textContent = tabText.textContent + child.textContent;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const firstChild = dom.query.getEdgeChild(lines[0], 'text', false);
|
|
224
|
+
const endChild = dom.query.getEdgeChild(lines[len], 'text', true);
|
|
225
|
+
if (!firstCell && firstChild) {
|
|
226
|
+
r.sc = firstChild;
|
|
227
|
+
r.so = 0;
|
|
228
|
+
}
|
|
229
|
+
if (!lastCell && endChild) {
|
|
230
|
+
r.ec = endChild;
|
|
231
|
+
r.eo = endChild.textContent.length;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
const len = lines.length - 1;
|
|
236
|
+
for (let i = 0, line; i <= len; i++) {
|
|
237
|
+
line = lines[i].childNodes;
|
|
238
|
+
for (let c = 0, cLen = line.length, child; c < cLen; c++) {
|
|
239
|
+
child = line[c];
|
|
240
|
+
if (!child) break;
|
|
241
|
+
if (dom.check.isZeroWidth(child)) continue;
|
|
242
|
+
|
|
243
|
+
if (/^\s{1,4}$/.test(child.textContent)) {
|
|
244
|
+
dom.utils.removeItem(child);
|
|
245
|
+
} else if (/^\s{1,4}/.test(child.textContent)) {
|
|
246
|
+
child.textContent = child.textContent.replace(/^\s{1,4}/, '');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const firstChild = dom.query.getEdgeChild(lines[0], 'text', false);
|
|
254
|
+
const endChild = dom.query.getEdgeChild(lines[len], 'text', true);
|
|
255
|
+
if (!firstCell && firstChild) {
|
|
256
|
+
r.sc = firstChild;
|
|
257
|
+
r.so = 0;
|
|
258
|
+
}
|
|
259
|
+
if (!lastCell && endChild) {
|
|
260
|
+
r.ec = endChild;
|
|
261
|
+
r.eo = endChild.textContent.length;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
ports.selection.setRange(r.sc, r.so, r.ec, r.eo);
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
// enter
|
|
270
|
+
/** @action enterScrollTo */
|
|
271
|
+
'enter.scrollTo': ({ ports }, { range }) => {
|
|
272
|
+
ports.enterScrollTo(range);
|
|
273
|
+
},
|
|
274
|
+
/** @action enterLineAddDefault */
|
|
275
|
+
'enter.line.addDefault': ({ ports, ctx }, { formatEl }) => {
|
|
276
|
+
const newFormat = ports.format.addLine(formatEl, ctx.options.get('defaultLine'));
|
|
277
|
+
const temp = newFormat.firstChild;
|
|
278
|
+
if (dom.check.isBreak(temp)) {
|
|
279
|
+
const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
280
|
+
temp.parentNode.insertBefore(zeroWidth, temp);
|
|
281
|
+
ports.selection.setRange(zeroWidth, 1, zeroWidth, 1);
|
|
282
|
+
} else {
|
|
283
|
+
ports.selection.setRange(temp, 0, temp, 0);
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
/** @action enterListAddItem */
|
|
287
|
+
'enter.list.addItem': ({ ports }, { formatEl, selectionNode }) => {
|
|
288
|
+
const br = dom.utils.createElement('BR');
|
|
289
|
+
const newEl = dom.utils.createElement('LI', null, br);
|
|
290
|
+
|
|
291
|
+
formatEl.parentNode.insertBefore(newEl, formatEl.nextElementSibling);
|
|
292
|
+
newEl.appendChild(selectionNode.nextSibling);
|
|
293
|
+
|
|
294
|
+
ports.selection.setRange(br, 1, br, 1);
|
|
295
|
+
},
|
|
296
|
+
/** @action enterFormatExitEmpty */
|
|
297
|
+
'enter.format.exitEmpty': ({ ports, ctx }, { formatEl, rangeEl }) => {
|
|
298
|
+
let newEl = null;
|
|
299
|
+
|
|
300
|
+
if (dom.check.isListCell(rangeEl.parentElement)) {
|
|
301
|
+
const parentLi = formatEl.parentNode.parentElement;
|
|
302
|
+
rangeEl = parentLi.parentElement;
|
|
303
|
+
const newListCell = dom.utils.createElement('LI');
|
|
304
|
+
newListCell.innerHTML = '<br>';
|
|
305
|
+
dom.utils.copyTagAttributes(newListCell, formatEl, ctx.options.get('lineAttrReset'));
|
|
306
|
+
newEl = newListCell;
|
|
307
|
+
rangeEl.insertBefore(newEl, parentLi.nextElementSibling);
|
|
308
|
+
} else {
|
|
309
|
+
let newFormat;
|
|
310
|
+
if (dom.check.isTableCell(rangeEl.parentElement)) {
|
|
311
|
+
newFormat = 'DIV';
|
|
312
|
+
} else if (dom.check.isList(rangeEl.parentElement)) {
|
|
313
|
+
newFormat = 'LI';
|
|
314
|
+
} else if (ports.format.isLine(rangeEl.nextElementSibling)) {
|
|
315
|
+
newFormat = rangeEl.nextElementSibling.nodeName;
|
|
316
|
+
} else if (ports.format.isLine(rangeEl.previousElementSibling)) {
|
|
317
|
+
newFormat = rangeEl.previousElementSibling.nodeName;
|
|
318
|
+
} else {
|
|
319
|
+
newFormat = ctx.options.get('defaultLine');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
newEl = dom.utils.createElement(newFormat);
|
|
323
|
+
const edge = ports.format.removeBlock(rangeEl, { selectedFormats: [formatEl], newBlockElement: null, shouldDelete: true, skipHistory: true });
|
|
324
|
+
edge.cc.insertBefore(newEl, edge.ec);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
newEl.innerHTML = '<br>';
|
|
328
|
+
ports.nodeTransform.removeAllParents(formatEl, null, null);
|
|
329
|
+
ports.selection.setRange(newEl, 1, newEl, 1);
|
|
330
|
+
},
|
|
331
|
+
/** @action enterFormatCleanBrAndZWS */
|
|
332
|
+
'enter.format.cleanBrAndZWS': ({ ports }, { selectionNode, selectionFormat, brBlock, children, offset }) => {
|
|
333
|
+
if (selectionFormat) dom.utils.removeItem(children[offset - 1]);
|
|
334
|
+
else dom.utils.removeItem(selectionNode);
|
|
335
|
+
const brBlockNext = /** @type {HTMLElement} */ (brBlock).nextElementSibling;
|
|
336
|
+
const newEl = ports.format.addLine(brBlock, ports.format.isLine(brBlockNext) ? brBlockNext : null);
|
|
337
|
+
dom.utils.copyFormatAttributes(newEl, brBlock);
|
|
338
|
+
ports.selection.setRange(newEl, 1, newEl, 1);
|
|
339
|
+
},
|
|
340
|
+
/** @action enterFormatInsertBrHtml */
|
|
341
|
+
'enter.format.insertBrHtml': ({ ports }, { brBlock, range, wSelection, offset }) => {
|
|
342
|
+
ports.html.insert(range.collapsed && dom.check.isBreak(range.startContainer.childNodes[range.startOffset - 1]) ? '<br>' : '<br><br>', { selectInserted: false, skipCharCount: true, skipCleaning: true });
|
|
343
|
+
|
|
344
|
+
let focusNode = wSelection.focusNode;
|
|
345
|
+
const wOffset = wSelection.focusOffset;
|
|
346
|
+
if (brBlock === focusNode) {
|
|
347
|
+
focusNode = focusNode.childNodes[wOffset - offset > 1 ? wOffset - 1 : wOffset];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
ports.selection.setRange(focusNode, 1, focusNode, 1);
|
|
351
|
+
ports.setOnShortcutKey(true);
|
|
352
|
+
},
|
|
353
|
+
/** @action enterFormatInsertBrNode */
|
|
354
|
+
'enter.format.insertBrNode': ({ ports }, { wSelection }) => {
|
|
355
|
+
const focusNext = wSelection.focusNode.nextSibling;
|
|
356
|
+
const br = dom.utils.createElement('BR');
|
|
357
|
+
ports.html.insertNode(br, { afterNode: null, skipCharCount: true });
|
|
358
|
+
|
|
359
|
+
const brPrev = br.previousSibling,
|
|
360
|
+
brNext = br.nextSibling;
|
|
361
|
+
if (!dom.check.isBreak(focusNext) && !dom.check.isBreak(brPrev) && (!brNext || dom.check.isZeroWidth(brNext))) {
|
|
362
|
+
br.parentNode.insertBefore(br.cloneNode(false), br);
|
|
363
|
+
ports.selection.setRange(br, 1, br, 1);
|
|
364
|
+
} else {
|
|
365
|
+
ports.selection.setRange(brNext, 0, brNext, 0);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
ports.setOnShortcutKey(true);
|
|
369
|
+
},
|
|
370
|
+
/** @action enterFormatBreakAtEdge */
|
|
371
|
+
'enter.format.breakAtEdge': ({ ports, ctx }, { formatEl, selectionNode, formatStartEdge, formatEndEdge }) => {
|
|
372
|
+
const focusBR = dom.utils.createElement('BR');
|
|
373
|
+
const newFormat = dom.utils.createElement(formatEl.nodeName, null, focusBR);
|
|
374
|
+
|
|
375
|
+
dom.utils.copyTagAttributes(newFormat, formatEl, ctx.options.get('lineAttrReset'));
|
|
376
|
+
|
|
377
|
+
let child = focusBR;
|
|
378
|
+
let sNode = selectionNode;
|
|
379
|
+
do {
|
|
380
|
+
if (!dom.check.isBreak(sNode) && sNode.nodeType === 1) {
|
|
381
|
+
const f = /** @type {HTMLElement} */ (sNode.cloneNode(false));
|
|
382
|
+
f.appendChild(child);
|
|
383
|
+
child = f;
|
|
384
|
+
}
|
|
385
|
+
sNode = sNode.parentElement;
|
|
386
|
+
} while (formatEl !== sNode && formatEl.contains(sNode));
|
|
387
|
+
|
|
388
|
+
newFormat.appendChild(child);
|
|
389
|
+
formatEl.parentNode.insertBefore(newFormat, formatStartEdge && !formatEndEdge ? formatEl : formatEl.nextElementSibling);
|
|
390
|
+
if (formatEndEdge) {
|
|
391
|
+
ports.selection.setRange(focusBR, 1, focusBR, 1);
|
|
392
|
+
} else {
|
|
393
|
+
const firstEl = formatEl.firstChild || formatEl;
|
|
394
|
+
ports.selection.setRange(firstEl, 0, firstEl, 0);
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
/** @action enterFormatBreakWithSelection */
|
|
398
|
+
'enter.format.breakWithSelection': ({ ports, ctx }, { formatEl, range, formatStartEdge, formatEndEdge }) => {
|
|
399
|
+
const isMultiLine = ports.format.getLine(range.startContainer, null) !== ports.format.getLine(range.endContainer, null);
|
|
400
|
+
const newFormat = /** @type {HTMLElement} */ (formatEl.cloneNode(false));
|
|
401
|
+
newFormat.innerHTML = '<br>';
|
|
402
|
+
const commonCon = /** @type {HTMLElement} */ (range.commonAncestorContainer);
|
|
403
|
+
const rcon =
|
|
404
|
+
commonCon === range.startContainer && commonCon === range.endContainer && dom.check.isZeroWidth(commonCon)
|
|
405
|
+
? { container: commonCon, offset: range.endOffset, prevContainer: commonCon.previousElementSibling, commonCon: commonCon }
|
|
406
|
+
: ports.html.remove();
|
|
407
|
+
|
|
408
|
+
let newEl = ports.format.getLine(rcon.container, null);
|
|
409
|
+
let offset = 0;
|
|
410
|
+
|
|
411
|
+
if (!newEl) {
|
|
412
|
+
if (dom.check.isWysiwygFrame(rcon.container)) {
|
|
413
|
+
ports.enterPrevent(ctx.e);
|
|
414
|
+
ctx.fc.get('wysiwyg').appendChild(newFormat);
|
|
415
|
+
newEl = newFormat;
|
|
416
|
+
dom.utils.copyTagAttributes(newEl, formatEl, ctx.options.get('lineAttrReset'));
|
|
417
|
+
ports.selection.setRange(newEl, offset, newEl, offset);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const innerRange = ports.format.getBlock(rcon.container);
|
|
424
|
+
newEl = newEl.contains(innerRange) ? dom.query.getEdgeChild(innerRange, (current) => Boolean(ports.format.getLine(current)), false) : newEl;
|
|
425
|
+
if (isMultiLine) {
|
|
426
|
+
if (formatEndEdge && !formatStartEdge) {
|
|
427
|
+
newEl.parentNode.insertBefore(newFormat, !rcon.prevContainer || rcon.container === rcon.prevContainer ? newEl.nextElementSibling : newEl);
|
|
428
|
+
newEl = newFormat;
|
|
429
|
+
offset = 0;
|
|
430
|
+
} else {
|
|
431
|
+
offset = rcon.offset;
|
|
432
|
+
if (formatStartEdge) {
|
|
433
|
+
const tempEl = newEl.parentNode.insertBefore(newFormat, newEl);
|
|
434
|
+
if (formatEndEdge) {
|
|
435
|
+
newEl = tempEl;
|
|
436
|
+
offset = 0;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
} else {
|
|
441
|
+
if (formatEndEdge && formatStartEdge) {
|
|
442
|
+
newEl.parentNode.insertBefore(newFormat, rcon.prevContainer && rcon.container === rcon.prevContainer ? newEl.nextElementSibling : newEl);
|
|
443
|
+
newEl = newFormat;
|
|
444
|
+
offset = 0;
|
|
445
|
+
} else if (formatEndEdge) {
|
|
446
|
+
newEl = newEl.parentNode.insertBefore(newFormat, newEl.nextElementSibling);
|
|
447
|
+
newEl = newFormat;
|
|
448
|
+
offset = 0;
|
|
449
|
+
} else {
|
|
450
|
+
newEl = ports.nodeTransform.split(rcon.container, rcon.offset, dom.query.getNodeDepth(formatEl));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
ports.enterPrevent(ctx.e);
|
|
455
|
+
dom.utils.copyTagAttributes(newEl, formatEl, ctx.options.get('lineAttrReset'));
|
|
456
|
+
ports.selection.setRange(newEl, offset, newEl, offset);
|
|
457
|
+
},
|
|
458
|
+
/** @action enterFormatBreakAtCursor */
|
|
459
|
+
'enter.format.breakAtCursor': ({ ports, ctx }, { formatEl, range }) => {
|
|
460
|
+
let newEl = null;
|
|
461
|
+
|
|
462
|
+
if (dom.check.isZeroWidth(formatEl)) {
|
|
463
|
+
newEl = ports.format.addLine(formatEl, formatEl.cloneNode(false));
|
|
464
|
+
} else {
|
|
465
|
+
newEl = ports.nodeTransform.split(range.endContainer, range.endOffset, dom.query.getNodeDepth(formatEl));
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
ports.enterPrevent(ctx.e);
|
|
469
|
+
dom.utils.copyTagAttributes(newEl, formatEl, ctx.options.get('lineAttrReset'));
|
|
470
|
+
ports.selection.setRange(newEl, 0, newEl, 0);
|
|
471
|
+
},
|
|
472
|
+
/** @action enterFigcaptionExitInList */
|
|
473
|
+
'enter.figcaption.exitInList': ({ ports }, { formatEl }) => {
|
|
474
|
+
const newEl = ports.format.addLine(formatEl, null);
|
|
475
|
+
ports.selection.setRange(newEl, 0, newEl, 0);
|
|
476
|
+
},
|
|
477
|
+
|
|
478
|
+
// keydown reducer
|
|
479
|
+
/** @action keydownInputInsertNbsp */
|
|
480
|
+
'keydown.input.insertNbsp': ({ ports }) => {
|
|
481
|
+
const nbsp = ports.html.insertNode(dom.utils.createTextNode('\u00a0'), { afterNode: null, skipCharCount: true });
|
|
482
|
+
if (nbsp) {
|
|
483
|
+
ports.selection.setRange(nbsp, nbsp.length, nbsp, nbsp.length);
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
/** @action keydownInputInsertZWS */
|
|
487
|
+
'keydown.input.insertZWS': ({ ports }) => {
|
|
488
|
+
const zeroWidth = dom.utils.createTextNode(unicode.zeroWidthSpace);
|
|
489
|
+
ports.html.insertNode(zeroWidth, { afterNode: null, skipCharCount: true });
|
|
490
|
+
ports.selection.setRange(zeroWidth, 1, zeroWidth, 1);
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* @param {HTMLElement} formatEl - Format element
|
|
496
|
+
* @returns {Node}
|
|
497
|
+
*/
|
|
498
|
+
function LineDelete_next(formatEl) {
|
|
499
|
+
const focusNode = formatEl.lastChild;
|
|
500
|
+
const next = formatEl.nextElementSibling;
|
|
501
|
+
|
|
502
|
+
if (!next) return focusNode;
|
|
503
|
+
|
|
504
|
+
if (dom.check.isZeroWidth(next)) {
|
|
505
|
+
dom.utils.removeItem(next);
|
|
506
|
+
return focusNode;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const nextChild = next.childNodes;
|
|
510
|
+
while (nextChild[0]) {
|
|
511
|
+
formatEl.appendChild(nextChild[0]);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
dom.utils.removeItem(next);
|
|
515
|
+
|
|
516
|
+
return focusNode;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* @param {HTMLElement} formatEl - Format element
|
|
521
|
+
* @returns {{focusNode: Node, focusOffset: number}}
|
|
522
|
+
*/
|
|
523
|
+
function LineDelete_prev(formatEl) {
|
|
524
|
+
const formatChild = formatEl.childNodes;
|
|
525
|
+
const prev = formatEl.previousElementSibling;
|
|
526
|
+
let focusNode = formatChild[0];
|
|
527
|
+
let focusOffset = 0;
|
|
528
|
+
|
|
529
|
+
if (!prev) return { focusNode, focusOffset };
|
|
530
|
+
|
|
531
|
+
if (dom.check.isZeroWidth(prev)) {
|
|
532
|
+
dom.utils.removeItem(prev);
|
|
533
|
+
return { focusNode, focusOffset };
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (formatChild.length > 1 || formatChild[0]?.textContent.length > 0) {
|
|
537
|
+
while (formatChild[0]) {
|
|
538
|
+
prev.appendChild(formatChild[0]);
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
focusNode = prev.lastChild;
|
|
542
|
+
focusOffset = focusNode.textContent.length;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
dom.utils.removeItem(formatEl);
|
|
546
|
+
|
|
547
|
+
return { focusNode, focusOffset };
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// test export
|
|
551
|
+
export { LineDelete_next, LineDelete_prev };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file effects/ruleHelpers.js
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ PATTERN COMPROMISE - Rule Helpers with Side Effects
|
|
5
|
+
*
|
|
6
|
+
* These functions are directly called from rules (not via actions/effects).
|
|
7
|
+
* This breaks pure reducer pattern but is necessary because they need to:
|
|
8
|
+
* 1. Perform atomic check + execute operations
|
|
9
|
+
* 2. Return values for rule conditional logic
|
|
10
|
+
*
|
|
11
|
+
* Categories:
|
|
12
|
+
* - QUERY (safe): isUneditableNode - reads DOM only
|
|
13
|
+
* - COMMAND (side effect): hardDelete, cleanRemovedTags - modifies DOM + returns status
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { dom } from '../../../helper';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @description Deletes specific elements such as tables in "Firefox" and media elements (image, video, audio) in "Chrome".
|
|
20
|
+
* - Handles deletion logic based on selection range and node types.
|
|
21
|
+
* @param {__se__EventPorts} ports - Reducer ports
|
|
22
|
+
* @returns {boolean} Returns `true` if an element was deleted and focus was adjusted, otherwise `false`.
|
|
23
|
+
*/
|
|
24
|
+
function hardDelete(ports) {
|
|
25
|
+
const range = ports.selection.getRange();
|
|
26
|
+
const sc = range.startContainer;
|
|
27
|
+
const ec = range.endContainer;
|
|
28
|
+
|
|
29
|
+
// table
|
|
30
|
+
const sCell = ports.format.getBlock(sc);
|
|
31
|
+
const eCell = ports.format.getBlock(ec);
|
|
32
|
+
const sIsCell = dom.check.isTableCell(sCell);
|
|
33
|
+
const eIsCell = dom.check.isTableCell(eCell);
|
|
34
|
+
if (((sIsCell && !sCell.previousElementSibling && !sCell.parentElement.previousElementSibling) || (eIsCell && !eCell.nextElementSibling && !eCell.parentElement.nextElementSibling)) && sCell !== eCell) {
|
|
35
|
+
const ancestor = dom.query.getParentElement(range.commonAncestorContainer, dom.check.isFigure)?.parentElement || range.commonAncestorContainer;
|
|
36
|
+
if (!sIsCell) {
|
|
37
|
+
dom.utils.removeItem(dom.query.getParentElement(eCell, (current) => ancestor === current.parentNode));
|
|
38
|
+
} else if (!eIsCell) {
|
|
39
|
+
dom.utils.removeItem(dom.query.getParentElement(sCell, (current) => ancestor === current.parentNode));
|
|
40
|
+
} else {
|
|
41
|
+
dom.utils.removeItem(dom.query.getParentElement(sCell, (current) => ancestor === current.parentNode));
|
|
42
|
+
ports.editor._nativeFocus();
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// component
|
|
48
|
+
const sComp = sc.nodeType === 1 ? dom.query.getParentElement(sc, '.se-component') : null;
|
|
49
|
+
const eComp = ec.nodeType === 1 ? dom.query.getParentElement(ec, '.se-component') : null;
|
|
50
|
+
if (sComp) dom.utils.removeItem(sComp);
|
|
51
|
+
if (eComp) dom.utils.removeItem(eComp);
|
|
52
|
+
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @description Cleans up removed tags and normalizes DOM structure.
|
|
58
|
+
* Removes orphaned nodes that are outside the format element's valid range.
|
|
59
|
+
* @param {__se__EventPorts} ports - Reducer ports
|
|
60
|
+
* @param {Node} startCon - Starting container node to clean
|
|
61
|
+
* @param {Element} formatEl - Parent format element containing the structure
|
|
62
|
+
* @returns {boolean|undefined} Returns true if nodes were removed, undefined otherwise
|
|
63
|
+
*/
|
|
64
|
+
function cleanRemovedTags(ports, startCon, formatEl) {
|
|
65
|
+
let prev = startCon.parentNode.previousSibling;
|
|
66
|
+
const next = startCon.parentNode.nextSibling;
|
|
67
|
+
if (!prev) {
|
|
68
|
+
if (!next) {
|
|
69
|
+
prev = dom.utils.createElement('BR');
|
|
70
|
+
formatEl.appendChild(prev);
|
|
71
|
+
} else {
|
|
72
|
+
prev = next;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let con = startCon;
|
|
77
|
+
while (formatEl.contains(con) && !con.previousSibling) {
|
|
78
|
+
con = con.parentNode;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!formatEl.contains(con)) {
|
|
82
|
+
startCon.textContent = '';
|
|
83
|
+
ports.nodeTransform.removeAllParents(startCon, null, formatEl);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @description Determines if the "range" is within an uneditable node.
|
|
90
|
+
* @param {__se__EventPorts} ports - Reducer ports
|
|
91
|
+
* @param {Range} range The range object
|
|
92
|
+
* @param {boolean} isFront Whether to check the start or end of the range
|
|
93
|
+
* @returns {Node|null} The uneditable node if found, otherwise null
|
|
94
|
+
*/
|
|
95
|
+
function isUneditableNode(ports, range, isFront) {
|
|
96
|
+
const container = isFront ? range.startContainer : range.endContainer;
|
|
97
|
+
const offset = isFront ? range.startOffset : range.endOffset;
|
|
98
|
+
const siblingKey = isFront ? 'previousSibling' : 'nextSibling';
|
|
99
|
+
const isElement = container.nodeType === 1;
|
|
100
|
+
|
|
101
|
+
let siblingNode;
|
|
102
|
+
if (isElement) {
|
|
103
|
+
siblingNode = /** @type {HTMLElement} */ (_isUneditableNode_getSibling(ports, container.childNodes[offset], siblingKey, container));
|
|
104
|
+
return dom.check.isComponentContainer(siblingNode) || dom.check.isNonEditable(siblingNode) ? siblingNode : null;
|
|
105
|
+
} else {
|
|
106
|
+
siblingNode = /** @type {HTMLElement} */ (_isUneditableNode_getSibling(ports, container, siblingKey, container));
|
|
107
|
+
return dom.check.isEdgePoint(container, offset, isFront ? 'front' : 'end') && (dom.check.isComponentContainer(siblingNode) || dom.check.isNonEditable(siblingNode)) ? siblingNode : null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @private
|
|
113
|
+
* @description Retrieves the sibling node of a selected node if it is uneditable. || component node.
|
|
114
|
+
* - Used only in `_isUneditableNode`.
|
|
115
|
+
* @param {__se__EventPorts} ports - Reducer ports
|
|
116
|
+
* @param {Node} selectNode The selected node
|
|
117
|
+
* @param {string} siblingKey The key to access the sibling (`previousSibling` or `nextSibling`)
|
|
118
|
+
* @param {Node} container The parent container node
|
|
119
|
+
* @returns {Node|null} The sibling node if found, otherwise null
|
|
120
|
+
*/
|
|
121
|
+
function _isUneditableNode_getSibling(ports, selectNode, siblingKey, container) {
|
|
122
|
+
if (!selectNode) return null;
|
|
123
|
+
let siblingNode = selectNode[siblingKey];
|
|
124
|
+
|
|
125
|
+
if (!siblingNode) {
|
|
126
|
+
siblingNode = ports.format.getLine(container);
|
|
127
|
+
siblingNode = siblingNode ? siblingNode[siblingKey] : null;
|
|
128
|
+
if (siblingNode && !ports.component.is(siblingNode)) siblingNode = siblingKey === 'previousSibling' ? siblingNode.firstChild : siblingNode.lastChild;
|
|
129
|
+
else return null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return siblingNode;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @description Excute eventManager._setDefaultLine
|
|
137
|
+
* @param {__se__EventPorts} ports - Reducer ports
|
|
138
|
+
* @param {string} lineTagName - line tag name
|
|
139
|
+
* @returns {void|null}
|
|
140
|
+
*/
|
|
141
|
+
function setDefaultLine(ports, lineTagName) {
|
|
142
|
+
return ports.setDefaultLine(lineTagName);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export { hardDelete, cleanRemovedTags, isUneditableNode, setDefaultLine };
|