suneditor 3.1.4 → 3.2.0
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-contents.min.css +1 -1
- package/dist/suneditor.min.css +28 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +2 -1
- package/src/assets/design/color.css +12 -0
- package/src/assets/design/size.css +9 -2
- package/src/assets/icons/defaultIcons.js +96 -47
- package/src/assets/suneditor-contents.css +3 -2
- package/src/assets/suneditor.css +480 -31
- package/src/core/config/contextProvider.js +2 -1
- package/src/core/config/eventManager.js +41 -2
- package/src/core/config/optionProvider.js +23 -2
- package/src/core/editor.js +32 -14
- package/src/core/event/actions/index.js +76 -9
- package/src/core/event/effects/common.registry.js +2 -1
- package/src/core/event/effects/keydown.registry.js +169 -33
- package/src/core/event/effects/ruleHelpers.js +20 -6
- package/src/core/event/eventOrchestrator.js +136 -23
- package/src/core/event/handlers/handler_toolbar.js +4 -2
- package/src/core/event/handlers/handler_ww_dragDrop.js +10 -0
- package/src/core/event/handlers/handler_ww_input.js +9 -2
- package/src/core/event/handlers/handler_ww_key.js +86 -17
- package/src/core/event/handlers/handler_ww_mouse.js +45 -8
- package/src/core/event/ports.js +23 -5
- package/src/core/event/reducers/keydown.reducer.js +15 -2
- package/src/core/event/rules/keydown.rule.arrow.js +12 -2
- package/src/core/event/rules/keydown.rule.backspace.js +110 -15
- package/src/core/event/rules/keydown.rule.delete.js +62 -7
- package/src/core/event/rules/keydown.rule.enter.js +62 -31
- package/src/core/event/support/defaultLineManager.js +9 -2
- package/src/core/event/support/selectionState.js +13 -3
- package/src/core/kernel/coreKernel.js +1 -0
- package/src/core/logic/dom/char.js +13 -3
- package/src/core/logic/dom/format.js +171 -39
- package/src/core/logic/dom/html.js +350 -72
- package/src/core/logic/dom/inline.js +229 -34
- package/src/core/logic/dom/listFormat.js +111 -20
- package/src/core/logic/dom/nodeTransform.js +36 -11
- package/src/core/logic/dom/offset.js +116 -31
- package/src/core/logic/dom/selection.js +147 -29
- package/src/core/logic/panel/blockHandle.js +785 -0
- package/src/core/logic/panel/blockResolver.js +278 -0
- package/src/core/logic/panel/finder.js +16 -6
- package/src/core/logic/panel/menu.js +119 -18
- package/src/core/logic/panel/toolbar.js +75 -19
- package/src/core/logic/panel/viewer.js +76 -20
- package/src/core/logic/shell/_commandExecutor.js +44 -9
- package/src/core/logic/shell/commandDispatcher.js +46 -4
- package/src/core/logic/shell/component.js +102 -25
- package/src/core/logic/shell/focusManager.js +13 -3
- package/src/core/logic/shell/history.js +21 -6
- package/src/core/logic/shell/pluginManager.js +21 -13
- package/src/core/logic/shell/shortcuts.js +9 -1
- package/src/core/logic/shell/ui.js +139 -37
- package/src/core/schema/frameContext.js +34 -3
- package/src/core/schema/options.js +46 -4
- package/src/core/section/constructor.js +537 -93
- package/src/core/section/documentType.js +35 -6
- package/src/helper/converter.js +24 -7
- package/src/helper/dom/domCheck.js +25 -5
- package/src/helper/dom/domQuery.js +2 -1
- package/src/helper/dom/domUtils.js +17 -4
- package/src/helper/env.js +11 -2
- package/src/helper/keyCodeMap.js +6 -2
- package/src/helper/markdown.js +24 -5
- package/src/helper/msOffice.js +9 -2
- package/src/interfaces/plugins.js +1 -1
- package/src/langs/ckb.js +0 -1
- package/src/langs/cs.js +0 -1
- package/src/langs/da.js +0 -1
- package/src/langs/de.js +0 -1
- package/src/langs/en.js +0 -1
- package/src/langs/es.js +0 -1
- package/src/langs/fa.js +0 -1
- package/src/langs/fr.js +0 -1
- package/src/langs/he.js +0 -1
- package/src/langs/hu.js +0 -1
- package/src/langs/index.js +27 -1
- package/src/langs/it.js +0 -1
- package/src/langs/ja.js +0 -1
- package/src/langs/km.js +0 -1
- package/src/langs/ko.js +0 -1
- package/src/langs/lv.js +0 -1
- package/src/langs/nl.js +0 -1
- package/src/langs/pl.js +0 -1
- package/src/langs/pt_br.js +0 -1
- package/src/langs/ro.js +0 -1
- package/src/langs/ru.js +0 -1
- package/src/langs/se.js +0 -1
- package/src/langs/tr.js +0 -1
- package/src/langs/uk.js +0 -1
- package/src/langs/ur.js +0 -1
- package/src/langs/zh_cn.js +0 -1
- package/src/modules/contract/Browser.js +58 -14
- package/src/modules/contract/ColorPicker.js +12 -4
- package/src/modules/contract/Controller.js +37 -7
- package/src/modules/contract/Figure.js +156 -36
- package/src/modules/contract/HueSlider.js +27 -4
- package/src/modules/contract/Modal.js +50 -10
- package/src/modules/manager/FileManager.js +50 -8
- package/src/modules/ui/CommandMenu.js +597 -0
- package/src/modules/ui/ModalAnchorEditor.js +33 -6
- package/src/modules/ui/SelectMenu.js +481 -36
- package/src/modules/ui/index.js +1 -0
- package/src/plugins/browser/audioGallery.js +2 -1
- package/src/plugins/browser/fileBrowser.js +9 -2
- package/src/plugins/browser/fileGallery.js +2 -1
- package/src/plugins/browser/imageGallery.js +18 -3
- package/src/plugins/browser/videoGallery.js +13 -4
- package/src/plugins/command/blockquote.js +6 -1
- package/src/plugins/command/codeBlock.js +43 -5
- package/src/plugins/command/exportPDF.js +20 -4
- package/src/plugins/command/fileUpload.js +46 -11
- package/src/plugins/command/list_bulleted.js +6 -1
- package/src/plugins/command/list_numbered.js +6 -1
- package/src/plugins/dropdown/align.js +21 -33
- package/src/plugins/dropdown/backgroundColor.js +10 -2
- package/src/plugins/dropdown/blockStyle.js +17 -22
- package/src/plugins/dropdown/font.js +34 -34
- package/src/plugins/dropdown/hr.js +15 -43
- package/src/plugins/dropdown/layout.js +10 -27
- package/src/plugins/dropdown/lineHeight.js +10 -33
- package/src/plugins/dropdown/list.js +19 -25
- package/src/plugins/dropdown/paragraphStyle.js +16 -24
- package/src/plugins/dropdown/table/index.js +72 -17
- package/src/plugins/dropdown/table/render/table.html.js +3 -1
- package/src/plugins/dropdown/table/services/table.cell.js +33 -7
- package/src/plugins/dropdown/table/services/table.clipboard.js +5 -1
- package/src/plugins/dropdown/table/services/table.grid.js +40 -9
- package/src/plugins/dropdown/table/services/table.resize.js +55 -11
- package/src/plugins/dropdown/table/services/table.selection.js +27 -7
- package/src/plugins/dropdown/table/services/table.style.js +120 -20
- package/src/plugins/dropdown/template.js +13 -29
- package/src/plugins/dropdown/textStyle.js +22 -35
- package/src/plugins/field/autocomplete.js +8 -4
- package/src/plugins/field/slashCommand.js +297 -0
- package/src/plugins/index.js +3 -0
- package/src/plugins/input/fontSize.js +37 -8
- package/src/plugins/input/pageNavigator.js +7 -1
- package/src/plugins/modal/audio.js +71 -17
- package/src/plugins/modal/drawing.js +41 -11
- package/src/plugins/modal/embed.js +92 -22
- package/src/plugins/modal/image/index.js +114 -28
- package/src/plugins/modal/image/services/image.size.js +9 -2
- package/src/plugins/modal/image/services/image.upload.js +38 -4
- package/src/plugins/modal/link.js +9 -2
- package/src/plugins/modal/math.js +10 -2
- package/src/plugins/modal/video/index.js +112 -26
- package/src/plugins/modal/video/render/video.html.js +4 -1
- package/src/plugins/modal/video/services/video.size.js +15 -4
- package/src/plugins/modal/video/services/video.upload.js +10 -2
- package/src/plugins/popup/anchor.js +14 -2
- package/src/suneditor.js +8 -2
- package/src/themes/cobalt.css +12 -0
- package/src/themes/cream.css +12 -0
- package/src/themes/dark.css +12 -0
- package/src/themes/midnight.css +12 -0
- package/src/typedef.js +32 -21
- package/types/assets/icons/defaultIcons.d.ts +1 -0
- package/types/core/config/contextProvider.d.ts +7 -1
- package/types/core/config/eventManager.d.ts +37 -4
- package/types/core/config/optionProvider.d.ts +5 -1
- package/types/core/event/actions/index.d.ts +44 -6
- package/types/core/event/effects/keydown.registry.d.ts +37 -7
- package/types/core/event/effects/ruleHelpers.d.ts +6 -1
- package/types/core/event/eventOrchestrator.d.ts +6 -1
- package/types/core/event/handlers/handler_ww_clipboard.d.ts +15 -3
- package/types/core/event/handlers/handler_ww_dragDrop.d.ts +14 -2
- package/types/core/event/handlers/handler_ww_input.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_key.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_mouse.d.ts +25 -5
- package/types/core/event/ports.d.ts +7 -2
- package/types/core/event/rules/keydown.rule.backspace.d.ts +6 -1
- package/types/core/kernel/store.d.ts +4 -1
- package/types/core/logic/dom/format.d.ts +32 -14
- package/types/core/logic/dom/html.d.ts +11 -3
- package/types/core/logic/dom/nodeTransform.d.ts +6 -6
- package/types/core/logic/panel/blockHandle.d.ts +64 -0
- package/types/core/logic/panel/blockResolver.d.ts +50 -0
- package/types/core/logic/panel/menu.d.ts +72 -3
- package/types/core/logic/shell/commandDispatcher.d.ts +8 -0
- package/types/core/logic/shell/component.d.ts +5 -3
- package/types/core/logic/shell/shortcuts.d.ts +10 -1
- package/types/core/logic/shell/ui.d.ts +7 -1
- package/types/core/schema/context.d.ts +7 -1
- package/types/core/schema/frameContext.d.ts +36 -4
- package/types/core/schema/options.d.ts +83 -2
- package/types/core/section/constructor.d.ts +38 -1
- package/types/events.d.ts +208 -32
- package/types/helper/converter.d.ts +4 -2
- package/types/helper/dom/domCheck.d.ts +12 -2
- package/types/helper/dom/domQuery.d.ts +35 -7
- package/types/helper/dom/domUtils.d.ts +4 -1
- package/types/interfaces/plugins.d.ts +2 -2
- package/types/langs/_Lang.d.ts +0 -1
- package/types/modules/contract/ColorPicker.d.ts +2 -2
- package/types/modules/contract/Controller.d.ts +7 -0
- package/types/modules/contract/Figure.d.ts +31 -4
- package/types/modules/ui/CommandMenu.d.ts +262 -0
- package/types/modules/ui/SelectMenu.d.ts +56 -3
- package/types/modules/ui/index.d.ts +1 -0
- package/types/plugins/browser/audioGallery.d.ts +1 -1
- package/types/plugins/browser/fileBrowser.d.ts +1 -1
- package/types/plugins/browser/fileGallery.d.ts +1 -1
- package/types/plugins/browser/imageGallery.d.ts +1 -1
- package/types/plugins/browser/videoGallery.d.ts +1 -1
- package/types/plugins/dropdown/align.d.ts +1 -1
- package/types/plugins/dropdown/blockStyle.d.ts +3 -1
- package/types/plugins/dropdown/table/index.d.ts +4 -1
- package/types/plugins/dropdown/table/services/table.clipboard.d.ts +5 -1
- package/types/plugins/dropdown/table/services/table.grid.d.ts +10 -2
- package/types/plugins/field/autocomplete.d.ts +0 -1
- package/types/plugins/field/slashCommand.d.ts +165 -0
- package/types/plugins/index.d.ts +3 -0
- package/types/plugins/modal/link.d.ts +4 -1
- package/types/typedef.d.ts +48 -23
package/src/core/event/ports.js
CHANGED
|
@@ -37,6 +37,7 @@ import { isMobile } from '../../helper/env';
|
|
|
37
37
|
* @property {(...args: Parameters<Format['isEdgeLine']>) => ReturnType<Format['isEdgeLine']>} isEdgeLine
|
|
38
38
|
* @property {(...args: Parameters<Format['removeBlock']>) => ReturnType<Format['removeBlock']>} removeBlock
|
|
39
39
|
* @property {(...args: Parameters<Format['addLine']>) => ReturnType<Format['addLine']>} addLine
|
|
40
|
+
* @property {(...args: Parameters<Format['addLineAfter']>) => ReturnType<Format['addLineAfter']>} addLineAfter
|
|
40
41
|
*/
|
|
41
42
|
|
|
42
43
|
/**
|
|
@@ -82,7 +83,20 @@ import { isMobile } from '../../helper/env';
|
|
|
82
83
|
* @param {*} param1._styleNodes - Style nodes reference object
|
|
83
84
|
*/
|
|
84
85
|
export function makePorts(inst, { _styleNodes }) {
|
|
85
|
-
const {
|
|
86
|
+
const {
|
|
87
|
+
frameContext,
|
|
88
|
+
ui,
|
|
89
|
+
focusManager,
|
|
90
|
+
selection,
|
|
91
|
+
format,
|
|
92
|
+
listFormat,
|
|
93
|
+
component,
|
|
94
|
+
html,
|
|
95
|
+
nodeTransform,
|
|
96
|
+
history,
|
|
97
|
+
char,
|
|
98
|
+
menu,
|
|
99
|
+
} = inst.$;
|
|
86
100
|
|
|
87
101
|
return {
|
|
88
102
|
// focusManager
|
|
@@ -112,6 +126,7 @@ export function makePorts(inst, { _styleNodes }) {
|
|
|
112
126
|
isEdgeLine: (node, offset, dir) => format.isEdgeLine(node, offset, dir),
|
|
113
127
|
removeBlock: (n, p) => format.removeBlock(n, p),
|
|
114
128
|
addLine: (el, nextOrTag) => format.addLine(el, nextOrTag),
|
|
129
|
+
addLineAfter: (el) => format.addLineAfter(el),
|
|
115
130
|
},
|
|
116
131
|
|
|
117
132
|
listFormat: {
|
|
@@ -159,14 +174,17 @@ export function makePorts(inst, { _styleNodes }) {
|
|
|
159
174
|
// === enter event specific ===
|
|
160
175
|
/**
|
|
161
176
|
* @description Scrolls the editor view to the caret position after pressing `Enter`.
|
|
162
|
-
* @param {Range} range
|
|
177
|
+
* @param {Range} range Pre-Enter snapshot range (fallback only).
|
|
163
178
|
*/
|
|
164
179
|
enterScrollTo(range) {
|
|
165
180
|
ui._iframeAutoHeight(frameContext);
|
|
166
181
|
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
// Scroll to the *live* post-Enter caret, not the pre-Enter `range` snapshot.
|
|
183
|
+
selection.scrollTo(selection.getRange() || range, {
|
|
184
|
+
behavior: 'auto',
|
|
185
|
+
block: 'nearest',
|
|
186
|
+
inline: 'nearest',
|
|
187
|
+
});
|
|
170
188
|
},
|
|
171
189
|
/**
|
|
172
190
|
* @description Prevents the default behavior of the `Enter` key and refocuses the editor.
|
|
@@ -79,13 +79,26 @@ export async function reduceKeydown(ports, ctx) {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const selectRange = !range.collapsed || range.startContainer !== range.endContainer;
|
|
82
|
-
if (
|
|
82
|
+
if (
|
|
83
|
+
!ctrl &&
|
|
84
|
+
!alt &&
|
|
85
|
+
!selectRange &&
|
|
86
|
+
!keyCodeMap.isNonTextKey(keyCode) &&
|
|
87
|
+
dom.check.isBreak(range.commonAncestorContainer)
|
|
88
|
+
) {
|
|
83
89
|
actions.push(A.keydownInputInsertZWS());
|
|
84
90
|
return actions;
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
// document type
|
|
88
|
-
if (
|
|
94
|
+
if (
|
|
95
|
+
fc.has('documentType_use_header') &&
|
|
96
|
+
selectRange &&
|
|
97
|
+
!ctrl &&
|
|
98
|
+
!alt &&
|
|
99
|
+
!shift &&
|
|
100
|
+
!keyCodeMap.isDirectionKey(keyCode)
|
|
101
|
+
) {
|
|
89
102
|
actions.push(A.documentTypeRefreshHeader());
|
|
90
103
|
return actions;
|
|
91
104
|
}
|
|
@@ -23,7 +23,16 @@ export function reduceArrowDown(actions, ports, ctx) {
|
|
|
23
23
|
const rtl = ctx.options.get('_rtl');
|
|
24
24
|
|
|
25
25
|
// In RTL, ArrowLeft is forward (toward end on the left), ArrowRight is backward (toward start on the right)
|
|
26
|
-
const hDir =
|
|
26
|
+
const hDir =
|
|
27
|
+
keyCode === 'ArrowLeft'
|
|
28
|
+
? rtl
|
|
29
|
+
? 'forward'
|
|
30
|
+
: 'back'
|
|
31
|
+
: keyCode === 'ArrowRight'
|
|
32
|
+
? rtl
|
|
33
|
+
? 'back'
|
|
34
|
+
: 'forward'
|
|
35
|
+
: null;
|
|
27
36
|
|
|
28
37
|
// next component
|
|
29
38
|
let cmponentInfo = null;
|
|
@@ -46,7 +55,8 @@ export function reduceArrowDown(actions, ports, ctx) {
|
|
|
46
55
|
}
|
|
47
56
|
} else if (hDir === 'back') {
|
|
48
57
|
if (dom.check.isEdgePoint(selectionNode, range.startOffset, 'front')) {
|
|
49
|
-
const prevEl =
|
|
58
|
+
const prevEl =
|
|
59
|
+
selectionNode.previousElementSibling || dom.query.getPreviousDeepestNode(selectionNode);
|
|
50
60
|
if (prevEl) {
|
|
51
61
|
if (component.is(prevEl)) cmponentInfo = component.get(prevEl);
|
|
52
62
|
} else if (component.is(formatEl.previousElementSibling)) {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { dom } from '../../../helper';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
cleanRemovedTags,
|
|
4
|
+
hardDelete,
|
|
5
|
+
isUneditableNode,
|
|
6
|
+
setDefaultLine,
|
|
7
|
+
isRtlBidiMismatch,
|
|
8
|
+
} from '../effects/ruleHelpers';
|
|
3
9
|
import { A } from '../actions';
|
|
4
10
|
|
|
5
11
|
/**
|
|
@@ -23,7 +29,11 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
23
29
|
|
|
24
30
|
const selectRange = !range.collapsed || range.startContainer !== range.endContainer;
|
|
25
31
|
// RTL bidi guard: if offset 0 is actually at the visual end due to LTR text in RTL line, skip front-edge handling
|
|
26
|
-
const bidiNotFront =
|
|
32
|
+
const bidiNotFront =
|
|
33
|
+
options.get('_rtl') &&
|
|
34
|
+
!selectRange &&
|
|
35
|
+
range.startOffset === 0 &&
|
|
36
|
+
isRtlBidiMismatch(range, formatEl, 'front', fc.get('_wd'));
|
|
27
37
|
|
|
28
38
|
actions.push(A.componentDeselect());
|
|
29
39
|
actions.push(A.cacheStyleNode());
|
|
@@ -33,7 +43,13 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
33
43
|
return true;
|
|
34
44
|
}
|
|
35
45
|
|
|
36
|
-
if (
|
|
46
|
+
if (
|
|
47
|
+
!format.isNormalLine(formatEl) &&
|
|
48
|
+
!format.isBrLine(formatEl) &&
|
|
49
|
+
!fc.get('wysiwyg').firstElementChild &&
|
|
50
|
+
!component.is(selectionNode) &&
|
|
51
|
+
setDefaultLine(ports, options.get('defaultLine')) !== null
|
|
52
|
+
) {
|
|
37
53
|
actions.push(A.preventStop());
|
|
38
54
|
return false;
|
|
39
55
|
}
|
|
@@ -62,7 +78,9 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
62
78
|
!selectionNode.previousSibling &&
|
|
63
79
|
!dom.check.isListCell(formatEl) &&
|
|
64
80
|
format.isLine(formatEl) &&
|
|
65
|
-
(!format.isBrLine(formatEl) ||
|
|
81
|
+
(!format.isBrLine(formatEl) ||
|
|
82
|
+
format.isClosureBrLine(formatEl) ||
|
|
83
|
+
dom.check.isWysiwygFrame(formatEl.parentNode))
|
|
66
84
|
) {
|
|
67
85
|
// closure range
|
|
68
86
|
if (format.isClosureBlock(formatEl.parentNode)) {
|
|
@@ -79,7 +97,11 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
79
97
|
}
|
|
80
98
|
|
|
81
99
|
// maintain default format
|
|
82
|
-
if (
|
|
100
|
+
if (
|
|
101
|
+
dom.check.isWysiwygFrame(formatEl.parentNode) &&
|
|
102
|
+
formatEl.childNodes.length <= 1 &&
|
|
103
|
+
(!formatEl.firstChild || dom.check.isZeroWidth(formatEl.textContent))
|
|
104
|
+
) {
|
|
83
105
|
actions.push(A.preventStop());
|
|
84
106
|
actions.push(A.backspaceFormatMaintain(formatEl));
|
|
85
107
|
}
|
|
@@ -90,7 +112,14 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
90
112
|
|
|
91
113
|
// clean remove tag
|
|
92
114
|
const startCon = range.startContainer;
|
|
93
|
-
if (
|
|
115
|
+
if (
|
|
116
|
+
formatEl &&
|
|
117
|
+
!bidiNotFront &&
|
|
118
|
+
!formatEl.previousElementSibling &&
|
|
119
|
+
range.startOffset === 0 &&
|
|
120
|
+
startCon.nodeType === 3 &&
|
|
121
|
+
dom.check.isZeroWidth(startCon)
|
|
122
|
+
) {
|
|
94
123
|
if (cleanRemovedTags(ports, startCon, formatEl) === true) return true;
|
|
95
124
|
}
|
|
96
125
|
|
|
@@ -136,8 +165,12 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
136
165
|
dom.check.isListCell(formatEl) &&
|
|
137
166
|
dom.check.isList(rangeEl) &&
|
|
138
167
|
(dom.check.isListCell(rangeEl.parentElement) || formatEl.previousElementSibling) &&
|
|
139
|
-
(selectionNode === formatEl ||
|
|
140
|
-
|
|
168
|
+
(selectionNode === formatEl ||
|
|
169
|
+
(selectionNode.nodeType === 3 &&
|
|
170
|
+
(!selectionNode.previousSibling || dom.check.isList(selectionNode.previousSibling)))) &&
|
|
171
|
+
(format.getLine(range.startContainer, null) !== format.getLine(range.endContainer, null)
|
|
172
|
+
? rangeEl.contains(range.startContainer)
|
|
173
|
+
: range.startOffset === 0 && range.collapsed && !bidiNotFront)
|
|
141
174
|
) {
|
|
142
175
|
if (range.startContainer !== range.endContainer) {
|
|
143
176
|
actions.push(A.prevent());
|
|
@@ -149,10 +182,16 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
149
182
|
actions.push(A.prevent());
|
|
150
183
|
|
|
151
184
|
let prevLast = prev;
|
|
152
|
-
if (
|
|
185
|
+
if (
|
|
186
|
+
!prev.contains(formatEl) &&
|
|
187
|
+
dom.check.isListCell(prevLast) &&
|
|
188
|
+
dom.check.isList(prevLast.lastElementChild)
|
|
189
|
+
) {
|
|
153
190
|
prevLast = /** @type {HTMLLIElement} */ (prevLast.lastElementChild.lastElementChild);
|
|
154
191
|
while (dom.check.isListCell(prevLast) && dom.check.isList(prevLast.lastElementChild)) {
|
|
155
|
-
prevLast = /** @type {HTMLLIElement} */ (
|
|
192
|
+
prevLast = /** @type {HTMLLIElement} */ (
|
|
193
|
+
prevLast.lastElementChild && prevLast.lastElementChild.lastElementChild
|
|
194
|
+
);
|
|
156
195
|
}
|
|
157
196
|
prev = prevLast;
|
|
158
197
|
}
|
|
@@ -171,7 +210,10 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
171
210
|
let comm = commonCon;
|
|
172
211
|
while (comm && comm !== rangeEl && !dom.check.isWysiwygFrame(comm)) {
|
|
173
212
|
if (comm.previousSibling) {
|
|
174
|
-
if (
|
|
213
|
+
if (
|
|
214
|
+
comm.previousSibling.nodeType === 1 ||
|
|
215
|
+
!dom.check.isZeroWidth(comm.previousSibling.textContent.trim())
|
|
216
|
+
) {
|
|
175
217
|
detach = false;
|
|
176
218
|
break;
|
|
177
219
|
}
|
|
@@ -181,7 +223,15 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
181
223
|
|
|
182
224
|
if (detach && rangeEl.parentNode) {
|
|
183
225
|
actions.push(A.prevent());
|
|
184
|
-
actions.push(
|
|
226
|
+
actions.push(
|
|
227
|
+
A.formatRemoveBlock(
|
|
228
|
+
rangeEl,
|
|
229
|
+
dom.check.isListCell(formatEl) ? [formatEl] : null,
|
|
230
|
+
null,
|
|
231
|
+
false,
|
|
232
|
+
false,
|
|
233
|
+
),
|
|
234
|
+
);
|
|
185
235
|
actions.push(A.historyPush(true));
|
|
186
236
|
return true;
|
|
187
237
|
}
|
|
@@ -199,13 +249,25 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
199
249
|
}
|
|
200
250
|
|
|
201
251
|
// component
|
|
202
|
-
if (
|
|
252
|
+
if (
|
|
253
|
+
!selectRange &&
|
|
254
|
+
formatEl &&
|
|
255
|
+
(range.startOffset === 0 || (selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : false))
|
|
256
|
+
) {
|
|
203
257
|
const isList = dom.check.isListCell(formatEl);
|
|
204
258
|
const sel = selectionNode === formatEl ? formatEl.childNodes[range.startOffset] : selectionNode;
|
|
205
259
|
const prev = (isList ? sel : formatEl).previousSibling;
|
|
206
260
|
// select file component
|
|
207
|
-
const ignoreZWS =
|
|
208
|
-
|
|
261
|
+
const ignoreZWS =
|
|
262
|
+
isList ||
|
|
263
|
+
((commonCon.nodeType === 3 || dom.check.isBreak(commonCon)) &&
|
|
264
|
+
!commonCon.previousSibling &&
|
|
265
|
+
range.startOffset === 0);
|
|
266
|
+
if (
|
|
267
|
+
sel &&
|
|
268
|
+
(isList || !sel.previousSibling) &&
|
|
269
|
+
((commonCon && component.is(commonCon.previousSibling)) || (ignoreZWS && component.is(prev)))
|
|
270
|
+
) {
|
|
209
271
|
const fileComponentInfo = component.get(prev);
|
|
210
272
|
if (fileComponentInfo) {
|
|
211
273
|
actions.push(A.preventStop());
|
|
@@ -225,5 +287,38 @@ export function reduceBackspaceDown(actions, ports, ctx) {
|
|
|
225
287
|
}
|
|
226
288
|
}
|
|
227
289
|
|
|
290
|
+
// empty row inside a brLine (PRE): Enter leaves the caret on a bare <br> that begins an empty row
|
|
291
|
+
if (
|
|
292
|
+
!selectRange &&
|
|
293
|
+
format.isBrLine(formatEl) &&
|
|
294
|
+
dom.check.isBreak(range.startContainer) &&
|
|
295
|
+
range.startOffset === 0
|
|
296
|
+
) {
|
|
297
|
+
let rowStartBr = range.startContainer.previousSibling;
|
|
298
|
+
if (rowStartBr?.nodeType === 3 && dom.check.isZeroWidth(rowStartBr)) rowStartBr = rowStartBr.previousSibling;
|
|
299
|
+
if (dom.check.isBreak(rowStartBr)) {
|
|
300
|
+
actions.push(A.preventStop());
|
|
301
|
+
actions.push(A.backspaceBrLineRowMerge(range.startContainer, rowStartBr));
|
|
302
|
+
actions.push(A.historyPush(true));
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// empty line: merge into the previous line
|
|
308
|
+
const emptyLinePrev = formatEl?.previousElementSibling;
|
|
309
|
+
if (
|
|
310
|
+
!selectRange &&
|
|
311
|
+
formatEl &&
|
|
312
|
+
format.isNormalLine(formatEl) &&
|
|
313
|
+
!dom.check.isListCell(formatEl) &&
|
|
314
|
+
dom.check.isEmptyLine(formatEl) &&
|
|
315
|
+
(format.isNormalLine(emptyLinePrev) || format.isBrLine(emptyLinePrev))
|
|
316
|
+
) {
|
|
317
|
+
actions.push(A.preventStop());
|
|
318
|
+
actions.push(A.backspaceEmptyLineMergePrev(formatEl, emptyLinePrev));
|
|
319
|
+
actions.push(A.historyPush(true));
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
|
|
228
323
|
return true;
|
|
229
324
|
}
|
|
@@ -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 =
|
|
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 (
|
|
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 (
|
|
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) ||
|
|
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 (
|
|
98
|
-
|
|
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)
|
|
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 (
|
|
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
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
123
|
-
|
|
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(
|
|
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 (
|
|
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 (
|
|
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
|
|
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(
|
|
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 (
|
|
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')
|
|
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;
|