jodit 4.18.4 → 4.18.7
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/CHANGELOG.md +45 -0
- package/es2015/jodit.css +13 -34
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +12 -12
- package/es2015/jodit.js +1130 -225
- package/es2015/jodit.min.css +1 -1
- package/es2015/jodit.min.js +12 -12
- package/es2015/plugins/debug/debug.css +1 -1
- package/es2015/plugins/debug/debug.js +1 -1
- package/es2015/plugins/debug/debug.min.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2018/jodit.fat.min.css +1 -1
- package/es2018/jodit.fat.min.js +12 -12
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +12 -12
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +13 -34
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +16 -16
- package/es2021/jodit.js +1121 -223
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +16 -16
- package/es2021/plugins/debug/debug.css +1 -1
- package/es2021/plugins/debug/debug.js +1 -1
- package/es2021/plugins/debug/debug.min.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021.en/jodit.css +13 -34
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +16 -16
- package/es2021.en/jodit.js +1095 -197
- package/es2021.en/jodit.min.css +1 -1
- package/es2021.en/jodit.min.js +16 -16
- package/es2021.en/plugins/debug/debug.css +1 -1
- package/es2021.en/plugins/debug/debug.js +1 -1
- package/es2021.en/plugins/debug/debug.min.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/jodit.css +14 -41
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +1260 -273
- package/es5/jodit.min.css +3 -3
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.css +1 -1
- package/es5/plugins/debug/debug.js +1 -1
- package/es5/plugins/debug/debug.min.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/polyfills.fat.min.js +1 -1
- package/es5/polyfills.js +1 -1
- package/es5/polyfills.min.js +1 -1
- package/esm/config.d.ts +5 -0
- package/esm/core/constants.js +1 -1
- package/esm/core/decorators/component/component.js +12 -0
- package/esm/core/helpers/html/apply-styles.js +3 -0
- package/esm/core/helpers/html/clean-from-word.js +3 -0
- package/esm/core/helpers/html/strip-tags.js +24 -6
- package/esm/core/helpers/html/word-lists.d.ts +29 -0
- package/esm/core/helpers/html/word-lists.js +158 -0
- package/esm/core/selection/helpers/index.d.ts +1 -0
- package/esm/core/selection/helpers/index.js +1 -0
- package/esm/core/selection/helpers/is-moved.d.ts +15 -0
- package/esm/core/selection/helpers/is-moved.js +22 -0
- package/esm/core/selection/style/api/list/toggle-ordered-list.js +40 -3
- package/esm/core/selection/style/transactions.js +5 -2
- package/esm/core/ui/popup/popup.js +14 -9
- package/esm/jodit.js +5 -1
- package/esm/langs/ar.d.ts +3 -0
- package/esm/langs/ar.js +4 -1
- package/esm/langs/az.d.ts +3 -0
- package/esm/langs/az.js +4 -1
- package/esm/langs/cs_cz.d.ts +3 -0
- package/esm/langs/cs_cz.js +4 -1
- package/esm/langs/de.d.ts +3 -0
- package/esm/langs/de.js +4 -1
- package/esm/langs/es.d.ts +3 -0
- package/esm/langs/es.js +4 -1
- package/esm/langs/fa.d.ts +3 -0
- package/esm/langs/fa.js +4 -1
- package/esm/langs/fi.d.ts +3 -0
- package/esm/langs/fi.js +4 -1
- package/esm/langs/fr.d.ts +3 -0
- package/esm/langs/fr.js +4 -1
- package/esm/langs/he.d.ts +3 -0
- package/esm/langs/he.js +4 -1
- package/esm/langs/hu.d.ts +3 -0
- package/esm/langs/hu.js +4 -1
- package/esm/langs/id.d.ts +3 -0
- package/esm/langs/id.js +4 -1
- package/esm/langs/it.d.ts +3 -0
- package/esm/langs/it.js +4 -1
- package/esm/langs/ja.d.ts +3 -0
- package/esm/langs/ja.js +4 -1
- package/esm/langs/ko.d.ts +3 -0
- package/esm/langs/ko.js +4 -1
- package/esm/langs/mn.d.ts +3 -0
- package/esm/langs/mn.js +4 -1
- package/esm/langs/nl.d.ts +3 -0
- package/esm/langs/nl.js +4 -1
- package/esm/langs/no.d.ts +3 -0
- package/esm/langs/no.js +4 -1
- package/esm/langs/pl.d.ts +3 -0
- package/esm/langs/pl.js +4 -1
- package/esm/langs/pt_br.d.ts +3 -0
- package/esm/langs/pt_br.js +4 -1
- package/esm/langs/ru.d.ts +3 -0
- package/esm/langs/ru.js +4 -1
- package/esm/langs/sk.d.ts +3 -0
- package/esm/langs/sk.js +4 -1
- package/esm/langs/sv.d.ts +3 -0
- package/esm/langs/sv.js +4 -1
- package/esm/langs/tr.d.ts +3 -0
- package/esm/langs/tr.js +4 -1
- package/esm/langs/ua.d.ts +3 -0
- package/esm/langs/ua.js +4 -1
- package/esm/langs/zh_cn.d.ts +3 -0
- package/esm/langs/zh_cn.js +4 -1
- package/esm/langs/zh_tw.d.ts +3 -0
- package/esm/langs/zh_tw.js +4 -1
- package/esm/modules/dialog/dialog.d.ts +7 -0
- package/esm/modules/dialog/dialog.js +24 -6
- package/esm/modules/file-browser/ui/files/files.js +17 -2
- package/esm/modules/file-browser/ui/tree/tree.js +17 -2
- package/esm/modules/table/table.d.ts +6 -0
- package/esm/modules/table/table.js +18 -26
- package/esm/plugins/backspace/cases/check-join-neighbors.js +90 -3
- package/esm/plugins/backspace/cases/check-remove-char.d.ts +2 -1
- package/esm/plugins/backspace/cases/check-remove-char.js +25 -4
- package/esm/plugins/backspace/config.d.ts +2 -0
- package/esm/plugins/backspace/config.js +6 -3
- package/esm/plugins/clean-html/clean-html.d.ts +8 -0
- package/esm/plugins/clean-html/clean-html.js +21 -1
- package/esm/plugins/clean-html/helpers/index.d.ts +1 -0
- package/esm/plugins/clean-html/helpers/index.js +1 -0
- package/esm/plugins/clean-html/helpers/remove-placeholder-br.d.ts +16 -0
- package/esm/plugins/clean-html/helpers/remove-placeholder-br.js +51 -0
- package/esm/plugins/delete/delete.d.ts +11 -1
- package/esm/plugins/delete/delete.js +92 -16
- package/esm/plugins/focus/focus.js +12 -1
- package/esm/plugins/iframe/config.d.ts +3 -0
- package/esm/plugins/iframe/config.js +0 -27
- package/esm/plugins/iframe/iframe.js +8 -1
- package/esm/plugins/image-processor/image-processor.js +6 -1
- package/esm/plugins/image-properties/image-properties.d.ts +5 -0
- package/esm/plugins/image-properties/image-properties.js +30 -5
- package/esm/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/esm/plugins/inline-popup/inline-popup.js +70 -1
- package/esm/plugins/mobile/mobile.js +7 -4
- package/esm/plugins/ordered-list/config.js +13 -2
- package/esm/plugins/ordered-list/start-dialog.d.ts +19 -0
- package/esm/plugins/ordered-list/start-dialog.js +58 -0
- package/esm/plugins/placeholder/placeholder.js +7 -1
- package/esm/plugins/resizer/resizer.d.ts +10 -0
- package/esm/plugins/resizer/resizer.js +76 -2
- package/esm/plugins/select-cells/select-cells.d.ts +23 -0
- package/esm/plugins/select-cells/select-cells.js +75 -1
- package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +3 -2
- package/package.json +1 -1
- package/types/config.d.ts +5 -0
- package/types/core/helpers/html/word-lists.d.ts +29 -0
- package/types/core/selection/helpers/index.d.ts +1 -0
- package/types/core/selection/helpers/is-moved.d.ts +15 -0
- package/types/langs/ar.d.ts +3 -0
- package/types/langs/az.d.ts +3 -0
- package/types/langs/cs_cz.d.ts +3 -0
- package/types/langs/de.d.ts +3 -0
- package/types/langs/es.d.ts +3 -0
- package/types/langs/fa.d.ts +3 -0
- package/types/langs/fi.d.ts +3 -0
- package/types/langs/fr.d.ts +3 -0
- package/types/langs/he.d.ts +3 -0
- package/types/langs/hu.d.ts +3 -0
- package/types/langs/id.d.ts +3 -0
- package/types/langs/it.d.ts +3 -0
- package/types/langs/ja.d.ts +3 -0
- package/types/langs/ko.d.ts +3 -0
- package/types/langs/mn.d.ts +3 -0
- package/types/langs/nl.d.ts +3 -0
- package/types/langs/no.d.ts +3 -0
- package/types/langs/pl.d.ts +3 -0
- package/types/langs/pt_br.d.ts +3 -0
- package/types/langs/ru.d.ts +3 -0
- package/types/langs/sk.d.ts +3 -0
- package/types/langs/sv.d.ts +3 -0
- package/types/langs/tr.d.ts +3 -0
- package/types/langs/ua.d.ts +3 -0
- package/types/langs/zh_cn.d.ts +3 -0
- package/types/langs/zh_tw.d.ts +3 -0
- package/types/modules/dialog/dialog.d.ts +7 -0
- package/types/modules/table/table.d.ts +6 -0
- package/types/plugins/backspace/cases/check-remove-char.d.ts +2 -1
- package/types/plugins/backspace/config.d.ts +2 -0
- package/types/plugins/clean-html/clean-html.d.ts +8 -0
- package/types/plugins/clean-html/helpers/index.d.ts +1 -0
- package/types/plugins/clean-html/helpers/remove-placeholder-br.d.ts +16 -0
- package/types/plugins/delete/delete.d.ts +11 -1
- package/types/plugins/iframe/config.d.ts +3 -0
- package/types/plugins/image-properties/image-properties.d.ts +5 -0
- package/types/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/types/plugins/ordered-list/start-dialog.d.ts +19 -0
- package/types/plugins/resizer/resizer.d.ts +10 -0
- package/types/plugins/select-cells/select-cells.d.ts +23 -0
package/esm/langs/zh_tw.d.ts
CHANGED
package/esm/langs/zh_tw.js
CHANGED
|
@@ -48,6 +48,13 @@ export declare class Dialog extends ViewWithToolbar implements IDialog {
|
|
|
48
48
|
*/
|
|
49
49
|
private minSize;
|
|
50
50
|
private __onResizerMouseDown;
|
|
51
|
+
/**
|
|
52
|
+
* The width `box` takes with its content on one line. The header and
|
|
53
|
+
* footer are flex rows as wide as the dialog, so the footer's
|
|
54
|
+
* `scrollWidth` was the dialog's width and kept it from getting any
|
|
55
|
+
* narrower
|
|
56
|
+
*/
|
|
57
|
+
private __contentWidth;
|
|
51
58
|
private __addGlobalResizeListeners;
|
|
52
59
|
private __removeGlobalResizeListeners;
|
|
53
60
|
OPTIONS: IDialogOptions;
|
|
@@ -179,7 +179,12 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
__onResizerMouseDown(e) {
|
|
182
|
-
var _a, _b
|
|
182
|
+
var _a, _b;
|
|
183
|
+
// As for the header: otherwise Safari selects the dialog's text as
|
|
184
|
+
// the pointer moves
|
|
185
|
+
if (e.cancelable) {
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
}
|
|
183
188
|
this.resizable = true;
|
|
184
189
|
this.startX = e.clientX;
|
|
185
190
|
this.startY = e.clientY;
|
|
@@ -195,11 +200,11 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
|
|
|
195
200
|
: 0;
|
|
196
201
|
this.minSize.w = isNumber(this.o.minWidth)
|
|
197
202
|
? this.o.minWidth
|
|
198
|
-
: Math.max(100,
|
|
203
|
+
: Math.max(100, header ? this.__contentWidth(header) : 0, footer ? this.__contentWidth(footer) : 0);
|
|
199
204
|
this.minSize.h = isNumber(this.o.minHeight)
|
|
200
205
|
? this.o.minHeight
|
|
201
|
-
: ((
|
|
202
|
-
((
|
|
206
|
+
: ((_a = header === null || header === void 0 ? void 0 : header.offsetHeight) !== null && _a !== void 0 ? _a : 0) +
|
|
207
|
+
((_b = footer === null || footer === void 0 ? void 0 : footer.offsetHeight) !== null && _b !== void 0 ? _b : 0) +
|
|
203
208
|
contentMinHeight +
|
|
204
209
|
this.resizer.offsetHeight;
|
|
205
210
|
this.lockSelect();
|
|
@@ -211,6 +216,19 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
|
|
|
211
216
|
this.e.fire(this, 'startResize');
|
|
212
217
|
}
|
|
213
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* The width `box` takes with its content on one line. The header and
|
|
221
|
+
* footer are flex rows as wide as the dialog, so the footer's
|
|
222
|
+
* `scrollWidth` was the dialog's width and kept it from getting any
|
|
223
|
+
* narrower
|
|
224
|
+
*/
|
|
225
|
+
__contentWidth(box) {
|
|
226
|
+
const { width } = box.style;
|
|
227
|
+
box.style.width = 'max-content';
|
|
228
|
+
const contentWidth = box.offsetWidth;
|
|
229
|
+
box.style.width = width;
|
|
230
|
+
return contentWidth;
|
|
231
|
+
}
|
|
214
232
|
__addGlobalResizeListeners() {
|
|
215
233
|
const self = this;
|
|
216
234
|
self.e
|
|
@@ -220,8 +238,8 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
|
|
|
220
238
|
__removeGlobalResizeListeners() {
|
|
221
239
|
const self = this;
|
|
222
240
|
self.e
|
|
223
|
-
.off(self.ow, '
|
|
224
|
-
.off(self.ow, '
|
|
241
|
+
.off(self.ow, 'pointermove touchmove', self.__onMouseMove)
|
|
242
|
+
.off(self.ow, 'pointerup touchend', self.__onMouseUp);
|
|
225
243
|
}
|
|
226
244
|
/**
|
|
227
245
|
* Specifies the size of the window
|
|
@@ -3,9 +3,24 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
9
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else
|
|
11
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
12
|
+
if (d = decorators[i])
|
|
13
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
import { component } from "../../../../core/decorators/index.js";
|
|
6
17
|
import { UIGroup } from "../../../../core/ui/index.js";
|
|
7
|
-
|
|
18
|
+
let FileBrowserFiles = class FileBrowserFiles extends UIGroup {
|
|
8
19
|
className() {
|
|
9
20
|
return 'FileBrowserFiles';
|
|
10
21
|
}
|
|
11
|
-
}
|
|
22
|
+
};
|
|
23
|
+
FileBrowserFiles = __decorate([
|
|
24
|
+
component
|
|
25
|
+
], FileBrowserFiles);
|
|
26
|
+
export { FileBrowserFiles };
|
|
@@ -3,9 +3,24 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
9
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
+
else
|
|
11
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
12
|
+
if (d = decorators[i])
|
|
13
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
+
};
|
|
16
|
+
import { component } from "../../../../core/decorators/index.js";
|
|
6
17
|
import { UIGroup } from "../../../../core/ui/index.js";
|
|
7
|
-
|
|
18
|
+
let FileBrowserTree = class FileBrowserTree extends UIGroup {
|
|
8
19
|
className() {
|
|
9
20
|
return 'FileBrowserTree';
|
|
10
21
|
}
|
|
11
|
-
}
|
|
22
|
+
};
|
|
23
|
+
FileBrowserTree = __decorate([
|
|
24
|
+
component
|
|
25
|
+
], FileBrowserTree);
|
|
26
|
+
export { FileBrowserTree };
|
|
@@ -15,6 +15,12 @@ export declare class Table extends ViewComponent<IJodit> {
|
|
|
15
15
|
className(): string;
|
|
16
16
|
private selected;
|
|
17
17
|
private static __selectedByTable;
|
|
18
|
+
/**
|
|
19
|
+
* Rewrite the `<style>` that marks the selected cells once for all the
|
|
20
|
+
* cells (un)selected in one go: a drag over a block of cells unmarks and
|
|
21
|
+
* marks every one of them on each move. `@debounce()` was never applied,
|
|
22
|
+
* as a Table never reaches `ready`
|
|
23
|
+
*/
|
|
18
24
|
private __recalculateStyles;
|
|
19
25
|
addSelection(td: HTMLTableCellElement): void;
|
|
20
26
|
removeSelection(td: HTMLTableCellElement): void;
|
|
@@ -3,19 +3,8 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
7
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
9
|
-
r = Reflect.decorate(decorators, target, key, desc);
|
|
10
|
-
else
|
|
11
|
-
for (var i = decorators.length - 1; i >= 0; i--)
|
|
12
|
-
if (d = decorators[i])
|
|
13
|
-
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
14
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
|
-
};
|
|
16
6
|
import { ViewComponent } from "../../core/component/index.js";
|
|
17
7
|
import * as consts from "../../core/constants.js";
|
|
18
|
-
import { debounce } from "../../core/decorators/index.js";
|
|
19
8
|
import { Dom } from "../../core/dom/index.js";
|
|
20
9
|
import { getContainer } from "../../core/global.js";
|
|
21
10
|
import { attr, css, cssPath, isNumber, toArray, trim } from "../../core/helpers/index.js";
|
|
@@ -25,23 +14,29 @@ export class Table extends ViewComponent {
|
|
|
25
14
|
constructor() {
|
|
26
15
|
super(...arguments);
|
|
27
16
|
this.selected = new Set();
|
|
17
|
+
/**
|
|
18
|
+
* Rewrite the `<style>` that marks the selected cells once for all the
|
|
19
|
+
* cells (un)selected in one go: a drag over a block of cells unmarks and
|
|
20
|
+
* marks every one of them on each move. `@debounce()` was never applied,
|
|
21
|
+
* as a Table never reaches `ready`
|
|
22
|
+
*/
|
|
23
|
+
this.__recalculateStyles = this.async.microDebounce(() => {
|
|
24
|
+
const style = getContainer(this.j, Table, 'style', true);
|
|
25
|
+
const selectors = [];
|
|
26
|
+
this.selected.forEach(td => {
|
|
27
|
+
const selector = cssPath(td);
|
|
28
|
+
selector && selectors.push(selector);
|
|
29
|
+
});
|
|
30
|
+
style.innerHTML = selectors.length
|
|
31
|
+
? selectors.join(',') +
|
|
32
|
+
`{${this.jodit.options.table.selectionCellStyle}}`
|
|
33
|
+
: '';
|
|
34
|
+
});
|
|
28
35
|
}
|
|
29
36
|
/** @override */
|
|
30
37
|
className() {
|
|
31
38
|
return 'Table';
|
|
32
39
|
}
|
|
33
|
-
__recalculateStyles() {
|
|
34
|
-
const style = getContainer(this.j, Table, 'style', true);
|
|
35
|
-
const selectors = [];
|
|
36
|
-
this.selected.forEach(td => {
|
|
37
|
-
const selector = cssPath(td);
|
|
38
|
-
selector && selectors.push(selector);
|
|
39
|
-
});
|
|
40
|
-
style.innerHTML = selectors.length
|
|
41
|
-
? selectors.join(',') +
|
|
42
|
-
`{${this.jodit.options.table.selectionCellStyle}}`
|
|
43
|
-
: '';
|
|
44
|
-
}
|
|
45
40
|
addSelection(td) {
|
|
46
41
|
this.selected.add(td);
|
|
47
42
|
this.__recalculateStyles();
|
|
@@ -701,7 +696,4 @@ export class Table extends ViewComponent {
|
|
|
701
696
|
}
|
|
702
697
|
}
|
|
703
698
|
Table.__selectedByTable = new WeakMap();
|
|
704
|
-
__decorate([
|
|
705
|
-
debounce()
|
|
706
|
-
], Table.prototype, "__recalculateStyles", null);
|
|
707
699
|
const instance = (j) => j.getInstance('Table', j.o);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
-
import { LIST_TAGS } from "../../../core/constants.js";
|
|
6
|
+
import { INSEPARABLE_TAGS, LIST_TAGS } from "../../../core/constants.js";
|
|
7
7
|
import { Dom } from "../../../core/dom/dom.js";
|
|
8
8
|
import { getMoveFilter } from "../helpers.js";
|
|
9
9
|
/**
|
|
@@ -21,6 +21,10 @@ export function checkJoinNeighbors(jodit, fakeNode, backspace) {
|
|
|
21
21
|
}
|
|
22
22
|
if (Dom.isElement(mainClosestBox) &&
|
|
23
23
|
Dom.isContentEditable(mainClosestBox, jodit.editor)) {
|
|
24
|
+
// A table cell is never joined with its neighbour
|
|
25
|
+
if (Dom.up(fakeNode, Dom.isCell, mainClosestBox, true)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
24
28
|
const sibling = Dom.findNotEmptySibling(mainClosestBox, backspace);
|
|
25
29
|
// A line break before the cursor is a single unit: remove it instead of
|
|
26
30
|
// merging the current element into the (void) `<br>`, which used to move
|
|
@@ -30,15 +34,60 @@ export function checkJoinNeighbors(jodit, fakeNode, backspace) {
|
|
|
30
34
|
jodit.s.setCursorBefore(fakeNode);
|
|
31
35
|
return true;
|
|
32
36
|
}
|
|
37
|
+
// Backspace leaves a block after a table alone, as Word does, rather
|
|
38
|
+
// than moving its text into the last cell
|
|
39
|
+
if (backspace && Dom.isTag(sibling, 'table')) {
|
|
40
|
+
jodit.s.setCursorBefore(fakeNode);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
const box = findCaretBox(fakeNode, mainClosestBox);
|
|
33
44
|
if (sibling &&
|
|
34
|
-
(
|
|
35
|
-
|
|
45
|
+
(checkPullNextLine(jodit, fakeNode, box, sibling, backspace) ||
|
|
46
|
+
checkMoveListContent(jodit, box, sibling, backspace) ||
|
|
47
|
+
moveContentAndRemoveEmpty(jodit, box, findEdgeBlock(resolveTableSibling(sibling, backspace), backspace, jodit.editor), backspace))) {
|
|
36
48
|
jodit.s.setCursorBefore(fakeNode);
|
|
37
49
|
return true;
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
return false;
|
|
41
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* The block holding the caret inside the box that has the sibling, so
|
|
56
|
+
* `<p>one</p><div><p>|two</p></div>` joins the two paragraphs instead of
|
|
57
|
+
* moving the whole `<div>` into the first one. For a list item that is its
|
|
58
|
+
* list, which the list cases handle.
|
|
59
|
+
*/
|
|
60
|
+
function findCaretBox(fakeNode, mainClosestBox) {
|
|
61
|
+
const block = Dom.up(fakeNode, Dom.isBlock, mainClosestBox);
|
|
62
|
+
if (!block) {
|
|
63
|
+
return mainClosestBox;
|
|
64
|
+
}
|
|
65
|
+
return Dom.isLeaf(block) && block.parentElement
|
|
66
|
+
? block.parentElement
|
|
67
|
+
: block;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The innermost block on the sibling's edge facing the caret, so the
|
|
71
|
+
* content is joined to text: `<div><p>one</p></div><p>|two</p>` gives
|
|
72
|
+
* `<div><p>one|two</p></div>`
|
|
73
|
+
*/
|
|
74
|
+
function findEdgeBlock(sibling, backspace, root) {
|
|
75
|
+
let block = sibling;
|
|
76
|
+
while (block) {
|
|
77
|
+
const edge = backspace ? block.lastChild : block.firstChild;
|
|
78
|
+
const child = edge && Dom.isEmptyTextNode(edge)
|
|
79
|
+
? Dom.findNotEmptySibling(edge, backspace)
|
|
80
|
+
: edge;
|
|
81
|
+
if (!Dom.isBlock(child) ||
|
|
82
|
+
Dom.isTag(child, INSEPARABLE_TAGS) ||
|
|
83
|
+
Dom.isTag(child, 'table') ||
|
|
84
|
+
!Dom.isContentEditable(child, root)) {
|
|
85
|
+
return block;
|
|
86
|
+
}
|
|
87
|
+
block = child;
|
|
88
|
+
}
|
|
89
|
+
return block;
|
|
90
|
+
}
|
|
42
91
|
/**
|
|
43
92
|
* Content cannot be merged into the `<table>` element itself — it would land
|
|
44
93
|
* between the table sections (after `</tbody>`), which is invalid HTML and
|
|
@@ -56,6 +105,44 @@ function resolveTableSibling(sibling, backspace) {
|
|
|
56
105
|
});
|
|
57
106
|
return cells.length ? cells[backspace ? cells.length - 1 : 0] : null;
|
|
58
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Delete at the edge of a list pulls the next line up to the caret, as the
|
|
110
|
+
* browsers do, instead of moving the caret's line into the next block:
|
|
111
|
+
* `<ul><li>one|</li></ul><p>two</p>` gives `<ul><li>one|two</li></ul>`, and
|
|
112
|
+
* `<p>one|</p><ul><li>two</li></ul>` gives `<p>one|two</p>`
|
|
113
|
+
* @private
|
|
114
|
+
*/
|
|
115
|
+
function checkPullNextLine(jodit, fakeNode, box, sibling, backspace) {
|
|
116
|
+
if (backspace || !(Dom.isList(box) || Dom.isList(sibling))) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const target = Dom.up(fakeNode, Dom.isBlock, box, true);
|
|
120
|
+
const source = Dom.isList(sibling) ? sibling.firstElementChild : sibling;
|
|
121
|
+
if (!target ||
|
|
122
|
+
!source ||
|
|
123
|
+
Dom.isTag(source, INSEPARABLE_TAGS) ||
|
|
124
|
+
Dom.isTag(source, 'table')) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (!Dom.isEmpty(source)) {
|
|
128
|
+
const line = [];
|
|
129
|
+
for (let node = source.firstChild; node && !Dom.isBlock(node); node = node.nextSibling) {
|
|
130
|
+
line.push(node);
|
|
131
|
+
}
|
|
132
|
+
if (!line.length) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const filter = getMoveFilter(jodit);
|
|
136
|
+
line.forEach(node => filter(node) ? Dom.append(target, node) : Dom.safeRemove(node));
|
|
137
|
+
}
|
|
138
|
+
let remove = source;
|
|
139
|
+
while (remove && remove !== jodit.editor && Dom.isEmpty(remove)) {
|
|
140
|
+
const parent = remove.parentElement;
|
|
141
|
+
Dom.safeRemove(remove);
|
|
142
|
+
remove = parent;
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
59
146
|
function checkMoveListContent(jodit, mainClosestBox, sibling, backspace) {
|
|
60
147
|
// Process UL/LI/OL cases
|
|
61
148
|
const siblingIsList = Dom.isTag(sibling, LIST_TAGS);
|
|
@@ -19,6 +19,7 @@ import type { DeleteMode } from "../interface";
|
|
|
19
19
|
* ```html
|
|
20
20
|
* t|st
|
|
21
21
|
* ```
|
|
22
|
+
* With `stopBeforeSpace`, nothing is removed when the next char is a space.
|
|
22
23
|
* @private
|
|
23
24
|
*/
|
|
24
|
-
export declare function checkRemoveChar(jodit: IJodit, fakeNode: Node, backspace: boolean, mode: DeleteMode): boolean;
|
|
25
|
+
export declare function checkRemoveChar(jodit: IJodit, fakeNode: Node, backspace: boolean, mode: DeleteMode, stopBeforeSpace?: boolean): boolean;
|
|
@@ -18,10 +18,11 @@ import { findMostNestedNeighbor } from "../helpers.js";
|
|
|
18
18
|
* ```html
|
|
19
19
|
* t|st
|
|
20
20
|
* ```
|
|
21
|
+
* With `stopBeforeSpace`, nothing is removed when the next char is a space.
|
|
21
22
|
* @private
|
|
22
23
|
*/
|
|
23
24
|
// eslint-disable-next-line complexity
|
|
24
|
-
export function checkRemoveChar(jodit, fakeNode, backspace, mode) {
|
|
25
|
+
export function checkRemoveChar(jodit, fakeNode, backspace, mode, stopBeforeSpace = false) {
|
|
25
26
|
var _a, _b;
|
|
26
27
|
const step = backspace ? -1 : 1;
|
|
27
28
|
const anotherSibling = Dom.sibling(fakeNode, !backspace);
|
|
@@ -40,6 +41,10 @@ export function checkRemoveChar(jodit, fakeNode, backspace, mode) {
|
|
|
40
41
|
break;
|
|
41
42
|
}
|
|
42
43
|
if ((_a = sibling.nodeValue) === null || _a === void 0 ? void 0 : _a.length) {
|
|
44
|
+
if (stopBeforeSpace &&
|
|
45
|
+
isSpace(nextChar(sibling.nodeValue, backspace))) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
43
48
|
removed = tryRemoveChar(sibling, backspace, step, anotherSibling);
|
|
44
49
|
if (!sibling.nodeValue.length &&
|
|
45
50
|
Dom.isInlineBlock(sibling.parentNode)) {
|
|
@@ -160,8 +165,24 @@ function replaceSpaceOnNBSP(anotherSibling, backspace, value) {
|
|
|
160
165
|
}
|
|
161
166
|
function checkRepeatRemoveCharAction(backspace, sibling, fakeNode, mode, removed, jodit) {
|
|
162
167
|
call(backspace ? Dom.after : Dom.before, sibling, fakeNode);
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
const wordChar = mode === 'word' && !isSpace(removed);
|
|
169
|
+
// Backspace by word removes the spaces before the caret, then the word, and keeps the space in front of it
|
|
170
|
+
if (mode === 'sentence' || wordChar || (mode === 'word' && backspace)) {
|
|
171
|
+
checkRemoveChar(jodit, fakeNode, backspace, mode, wordChar && backspace);
|
|
166
172
|
}
|
|
167
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* The char tryRemoveChar would remove next
|
|
176
|
+
*/
|
|
177
|
+
function nextChar(value, backspace) {
|
|
178
|
+
const chars = toArray(value);
|
|
179
|
+
const step = backspace ? -1 : 1;
|
|
180
|
+
let index = backspace ? chars.length - 1 : 0;
|
|
181
|
+
while (chars[index] === INVISIBLE_SPACE) {
|
|
182
|
+
index += step;
|
|
183
|
+
}
|
|
184
|
+
return chars[index];
|
|
185
|
+
}
|
|
186
|
+
function isSpace(char) {
|
|
187
|
+
return char === ' ' || char === NBSP_SPACE;
|
|
188
|
+
}
|
|
@@ -7,6 +7,8 @@ declare module 'jodit/config' {
|
|
|
7
7
|
interface Config {
|
|
8
8
|
/**
|
|
9
9
|
* Keyboard hotkey mappings for delete and backspace operations (character, word, sentence).
|
|
10
|
+
* On macOS the defaults leave out Cmd+Backspace, Ctrl+Backspace, Ctrl+Option+Backspace
|
|
11
|
+
* and Cmd+Option+Backspace, so the browser applies the system's own bindings to them.
|
|
10
12
|
*/
|
|
11
13
|
delete: {
|
|
12
14
|
hotkeys: {
|
|
@@ -6,14 +6,17 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* @module plugins/backspace
|
|
8
8
|
*/
|
|
9
|
+
import { IS_MAC } from "../../core/constants.js";
|
|
9
10
|
import { Config } from "../../config.js";
|
|
10
11
|
Config.prototype.delete = {
|
|
11
12
|
hotkeys: {
|
|
12
|
-
delete: ['delete', 'cmd+backspace'],
|
|
13
|
-
deleteWord:
|
|
13
|
+
delete: IS_MAC ? ['delete'] : ['delete', 'cmd+backspace'],
|
|
14
|
+
deleteWord: IS_MAC
|
|
15
|
+
? ['ctrl+delete']
|
|
16
|
+
: ['ctrl+delete', 'cmd+alt+backspace', 'ctrl+alt+backspace'],
|
|
14
17
|
deleteSentence: ['ctrl+shift+delete', 'cmd+shift+delete'],
|
|
15
18
|
backspace: ['backspace'],
|
|
16
|
-
backspaceWord: ['ctrl+backspace'],
|
|
19
|
+
backspaceWord: IS_MAC ? [] : ['ctrl+backspace'],
|
|
17
20
|
backspaceSentence: ['ctrl+shift+backspace', 'cmd+shift+backspace']
|
|
18
21
|
}
|
|
19
22
|
};
|
|
@@ -23,6 +23,14 @@ export declare class cleanHtml extends Plugin {
|
|
|
23
23
|
*/
|
|
24
24
|
protected onChangeCleanHTML(): void;
|
|
25
25
|
private currentSelectionNode;
|
|
26
|
+
/**
|
|
27
|
+
* Typing into an empty block (`<p><br></p>`) replaces its `<br>`, but the
|
|
28
|
+
* browser keeps the `<br>` when the caret is in an invisible-space text
|
|
29
|
+
* node in front of it, as Jodit leaves the caret in many of the empty
|
|
30
|
+
* blocks it makes (a cleared editor, a heading in an empty table cell).
|
|
31
|
+
* See #1632
|
|
32
|
+
*/
|
|
33
|
+
protected onInputRemovePlaceholderBr(event: InputEvent | CompositionEvent): void;
|
|
26
34
|
private walker;
|
|
27
35
|
protected startWalker(): void;
|
|
28
36
|
protected beforeCommand(command: string): void | false;
|
|
@@ -21,7 +21,7 @@ import { safeHTML } from "../../core/helpers/html/safe-html.js";
|
|
|
21
21
|
import { Plugin } from "../../core/plugin/plugin.js";
|
|
22
22
|
import "./config.js";
|
|
23
23
|
import { replaceOldTags } from "./helpers/visitor/filters/replace-old-tags.js";
|
|
24
|
-
import { getHash, removeFormatForCollapsedSelection, removeFormatForSelection, visitNodeWalker } from "./helpers/index.js";
|
|
24
|
+
import { getHash, removeFormatForCollapsedSelection, removeFormatForSelection, removePlaceholderBr, visitNodeWalker } from "./helpers/index.js";
|
|
25
25
|
/**
|
|
26
26
|
* Clean HTML after removeFormat and insertHorizontalRule command
|
|
27
27
|
*/
|
|
@@ -72,6 +72,23 @@ export class cleanHtml extends Plugin {
|
|
|
72
72
|
this.walker.setWork(editor.editor);
|
|
73
73
|
this.currentSelectionNode = editor.s.current();
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Typing into an empty block (`<p><br></p>`) replaces its `<br>`, but the
|
|
77
|
+
* browser keeps the `<br>` when the caret is in an invisible-space text
|
|
78
|
+
* node in front of it, as Jodit leaves the caret in many of the empty
|
|
79
|
+
* blocks it makes (a cleared editor, a heading in an empty table cell).
|
|
80
|
+
* See #1632
|
|
81
|
+
*/
|
|
82
|
+
onInputRemovePlaceholderBr(event) {
|
|
83
|
+
var _a;
|
|
84
|
+
if (!this.isEditMode ||
|
|
85
|
+
(event.type === 'input' &&
|
|
86
|
+
(event.isComposing ||
|
|
87
|
+
!((_a = event.inputType) === null || _a === void 0 ? void 0 : _a.startsWith('insert'))))) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
removePlaceholderBr(this.j);
|
|
91
|
+
}
|
|
75
92
|
startWalker() {
|
|
76
93
|
const { jodit } = this;
|
|
77
94
|
const allow = getHash(this.j.o.cleanHTML.allowTags);
|
|
@@ -239,6 +256,9 @@ export class cleanHtml extends Plugin {
|
|
|
239
256
|
__decorate([
|
|
240
257
|
watch([':change', ':afterSetMode', ':afterInit', ':mousedown', ':keydown'])
|
|
241
258
|
], cleanHtml.prototype, "onChangeCleanHTML", null);
|
|
259
|
+
__decorate([
|
|
260
|
+
watch([':input', 'jodit.editor:compositionend'])
|
|
261
|
+
], cleanHtml.prototype, "onInputRemovePlaceholderBr", null);
|
|
242
262
|
__decorate([
|
|
243
263
|
hook('ready')
|
|
244
264
|
], cleanHtml.prototype, "startWalker", null);
|
|
@@ -10,4 +10,5 @@ export * from "./get-hash";
|
|
|
10
10
|
export * from "./is-allowed-media-embed";
|
|
11
11
|
export * from "./remove-format/remove-format-for-collapsed-selection";
|
|
12
12
|
export * from "./remove-format/remove-format-for-selection";
|
|
13
|
+
export * from "./remove-placeholder-br";
|
|
13
14
|
export * from "./visitor/visit-node-walker";
|
|
@@ -10,4 +10,5 @@ export * from "./get-hash.js";
|
|
|
10
10
|
export * from "./is-allowed-media-embed.js";
|
|
11
11
|
export * from "./remove-format/remove-format-for-collapsed-selection.js";
|
|
12
12
|
export * from "./remove-format/remove-format-for-selection.js";
|
|
13
|
+
export * from "./remove-placeholder-br.js";
|
|
13
14
|
export * from "./visitor/visit-node-walker.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/clean-html
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Remove the `<br>` that kept the block with the caret open while it was
|
|
12
|
+
* empty, once text has gone into the block: when the block is one line of
|
|
13
|
+
* text that ends in that `<br>`, the `<br>` adds nothing to it
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export declare function removePlaceholderBr(jodit: IJodit): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { INSEPARABLE_TAGS } from "../../../core/constants.js";
|
|
7
|
+
import { Dom } from "../../../core/dom/dom.js";
|
|
8
|
+
import { trim } from "../../../core/helpers/string/trim.js";
|
|
9
|
+
function lastNode(node) {
|
|
10
|
+
let last = node.lastChild;
|
|
11
|
+
while (Dom.isText(last) && !last.nodeValue) {
|
|
12
|
+
last = last.previousSibling;
|
|
13
|
+
}
|
|
14
|
+
return last;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Remove the `<br>` that kept the block with the caret open while it was
|
|
18
|
+
* empty, once text has gone into the block: when the block is one line of
|
|
19
|
+
* text that ends in that `<br>`, the `<br>` adds nothing to it
|
|
20
|
+
* @private
|
|
21
|
+
*/
|
|
22
|
+
export function removePlaceholderBr(jodit) {
|
|
23
|
+
var _a;
|
|
24
|
+
const block = Dom.closest(jodit.s.current(), Dom.isBlock, jodit.editor);
|
|
25
|
+
if (!block || !trim((_a = block.textContent) !== null && _a !== void 0 ? _a : '')) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
let br = lastNode(block);
|
|
29
|
+
while (Dom.isElement(br) &&
|
|
30
|
+
!Dom.isTag(br, INSEPARABLE_TAGS) &&
|
|
31
|
+
!Dom.isBlock(br)) {
|
|
32
|
+
br = lastNode(br);
|
|
33
|
+
}
|
|
34
|
+
if (!Dom.isTag(br, 'br')) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Another line break, a block, an image or an embed means the `<br>` may
|
|
38
|
+
// end an empty line, or give the caret a place after the embed
|
|
39
|
+
const isOneLineOfText = Dom.each(block, (node) => {
|
|
40
|
+
if (node !== br &&
|
|
41
|
+
Dom.isElement(node) &&
|
|
42
|
+
(Dom.isTag(node, INSEPARABLE_TAGS) ||
|
|
43
|
+
Dom.isBlock(node) ||
|
|
44
|
+
(Dom.isHTMLElement(node) && !node.isContentEditable))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
if (isOneLineOfText) {
|
|
49
|
+
Dom.safeRemove(br);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -20,13 +20,23 @@ export declare class deleteCommand extends Plugin {
|
|
|
20
20
|
*/
|
|
21
21
|
private __afterDeleteCommand;
|
|
22
22
|
private __onDeleteCommand;
|
|
23
|
+
/**
|
|
24
|
+
* A selection that starts or ends in a table cell clears the selected part
|
|
25
|
+
* of each cell it covers and keeps the cells, as the browsers do.
|
|
26
|
+
* `deleteContents` would remove the cells it fully covers, and the cells
|
|
27
|
+
* it cuts would then be merged as blocks. The range is moved out of those
|
|
28
|
+
* tables, so only the content between them is left to delete.
|
|
29
|
+
*
|
|
30
|
+
* Returns where the caret goes, or null when no table is involved
|
|
31
|
+
*/
|
|
32
|
+
private __clearSelectedCells;
|
|
23
33
|
private __moveContentInLeftSibling;
|
|
24
34
|
/**
|
|
25
35
|
* If left sibling is list - return last leaf
|
|
26
36
|
*/
|
|
27
37
|
private __defineRightLeftBox;
|
|
28
38
|
/**
|
|
29
|
-
* Add BR in empty
|
|
39
|
+
* Add BR in the empty block left at the caret
|
|
30
40
|
*/
|
|
31
41
|
private __addBrInEmptyBlock;
|
|
32
42
|
private __moveCursorInEditableSibling;
|