jodit 3.9.6 → 3.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/.idea/dictionaries/v_chupurnov.xml +1 -0
  2. package/.idea/workspace.xml +197 -179
  3. package/CHANGELOG.MD +279 -133
  4. package/build/jodit.css +185 -130
  5. package/build/jodit.es2018.css +175 -126
  6. package/build/jodit.es2018.en.css +175 -126
  7. package/build/jodit.es2018.en.js +709 -367
  8. package/build/jodit.es2018.en.min.css +1 -1
  9. package/build/jodit.es2018.en.min.js +1 -1
  10. package/build/jodit.es2018.js +709 -367
  11. package/build/jodit.es2018.min.css +1 -1
  12. package/build/jodit.es2018.min.js +1 -1
  13. package/build/jodit.js +1362 -900
  14. package/build/jodit.min.css +2 -2
  15. package/build/jodit.min.js +1 -1
  16. package/package.json +22 -11
  17. package/src/core/async.ts +4 -0
  18. package/src/core/component/statuses.ts +6 -6
  19. package/src/core/dom.ts +25 -5
  20. package/src/core/events/event-emitter.ts +4 -2
  21. package/src/core/global.ts +15 -4
  22. package/src/core/helpers/append-script.ts +14 -0
  23. package/src/core/helpers/selector.ts +8 -3
  24. package/src/core/request/ajax.ts +5 -2
  25. package/src/core/request/response.ts +8 -4
  26. package/src/core/selection/style/api/toggle/toggle-css.ts +1 -1
  27. package/src/core/ui/button/button/button.less +8 -8
  28. package/src/core/ui/button/button/button.ts +9 -9
  29. package/src/core/ui/button/group/group.ts +2 -2
  30. package/src/core/ui/element.ts +4 -3
  31. package/src/core/ui/form/block/block.ts +1 -1
  32. package/src/core/ui/form/form.ts +8 -0
  33. package/src/core/ui/form/inputs/area/area.less +5 -0
  34. package/src/core/ui/form/inputs/area/area.ts +22 -1
  35. package/src/core/ui/form/inputs/checkbox/checkbox.less +50 -0
  36. package/src/core/ui/form/inputs/checkbox/checkbox.ts +48 -4
  37. package/src/core/ui/form/inputs/input/input.less +1 -1
  38. package/src/core/ui/form/inputs/input/input.ts +14 -4
  39. package/src/core/ui/icon.ts +2 -1
  40. package/src/core/ui/list/group.ts +2 -2
  41. package/src/core/ui/popup/popup.ts +59 -3
  42. package/src/jodit.ts +17 -14
  43. package/src/modules/dialog/dialog.less +0 -1
  44. package/src/modules/dialog/dialog.ts +2 -2
  45. package/src/modules/toolbar/collection/collection.ts +1 -6
  46. package/src/modules/toolbar/collection/editor-collection.ts +5 -1
  47. package/src/modules/widget/file-selector/file-selector.ts +1 -1
  48. package/src/modules/widget/tabs/tabs.less +1 -1
  49. package/src/modules/widget/tabs/tabs.ts +5 -3
  50. package/src/plugins/add-new-line/add-new-line.ts +1 -0
  51. package/src/plugins/clipboard/paste/paste.ts +1 -1
  52. package/src/plugins/image/image-properties/image-properties.ts +7 -0
  53. package/src/plugins/index.ts +1 -1
  54. package/src/plugins/keyboard/backspace/backspace.ts +183 -0
  55. package/src/plugins/keyboard/backspace/cases/check-join-neighbors.ts +117 -0
  56. package/src/plugins/keyboard/backspace/cases/check-join-two-lists.ts +55 -0
  57. package/src/plugins/keyboard/backspace/cases/check-not-collapsed.ts +27 -0
  58. package/src/plugins/keyboard/backspace/cases/check-remove-char.ts +191 -0
  59. package/src/plugins/keyboard/backspace/cases/check-remove-content-not-editable.ts +46 -0
  60. package/src/plugins/keyboard/backspace/cases/check-remove-empty-neighbor.ts +43 -0
  61. package/src/plugins/keyboard/backspace/cases/check-remove-empty-parent.ts +80 -0
  62. package/src/plugins/keyboard/backspace/cases/check-remove-unbreakable-element.ts +46 -0
  63. package/src/plugins/keyboard/backspace/cases/check-table-cell.ts +30 -0
  64. package/src/plugins/keyboard/backspace/cases/check-unwrap-first-list-item.ts +57 -0
  65. package/src/plugins/keyboard/backspace/cases/index.ts +27 -0
  66. package/src/plugins/keyboard/backspace/config.ts +33 -0
  67. package/src/plugins/keyboard/backspace/interface.d.ts +7 -0
  68. package/src/plugins/keyboard/helpers.ts +7 -3
  69. package/src/plugins/link/template.ts +2 -2
  70. package/src/plugins/print/preview.ts +103 -55
  71. package/src/plugins/resizer/resizer.ts +7 -2
  72. package/src/plugins/select.ts +0 -1
  73. package/src/plugins/source/const.ts +7 -0
  74. package/src/plugins/source/editor/engines/ace.ts +5 -0
  75. package/src/plugins/source/source.ts +19 -7
  76. package/src/styles/jodit.less +6 -0
  77. package/src/types/ajax.d.ts +3 -0
  78. package/src/types/async.d.ts +2 -0
  79. package/src/types/jodit.d.ts +5 -8
  80. package/src/types/popup.d.ts +1 -0
  81. package/src/types/ui.d.ts +23 -4
  82. package/types/core/async.d.ts +1 -0
  83. package/types/core/component/component.d.ts +6 -2
  84. package/types/core/component/statuses.d.ts +6 -6
  85. package/types/core/dom.d.ts +6 -2
  86. package/types/core/global.d.ts +1 -1
  87. package/types/core/helpers/append-script.d.ts +1 -0
  88. package/types/core/helpers/selector.d.ts +2 -3
  89. package/types/core/request/response.d.ts +2 -1
  90. package/types/core/ui/button/button/button.d.ts +3 -3
  91. package/types/core/ui/form/form.d.ts +1 -0
  92. package/types/core/ui/form/inputs/area/area.d.ts +7 -1
  93. package/types/core/ui/form/inputs/checkbox/checkbox.d.ts +10 -3
  94. package/types/core/ui/icon.d.ts +1 -1
  95. package/types/core/ui/list/group.d.ts +2 -1
  96. package/types/core/ui/popup/popup.d.ts +2 -1
  97. package/types/jodit.d.ts +6 -6
  98. package/types/modules/toolbar/button/button.d.ts +1 -1
  99. package/types/modules/widget/tabs/tabs.d.ts +2 -1
  100. package/types/plugins/index.d.ts +1 -1
  101. package/types/plugins/keyboard/backspace/backspace.d.ts +28 -0
  102. package/types/plugins/keyboard/backspace/cases/check-join-neighbors.d.ts +10 -0
  103. package/types/plugins/keyboard/backspace/cases/check-join-two-lists.d.ts +19 -0
  104. package/types/plugins/keyboard/backspace/cases/check-not-collapsed.d.ts +19 -0
  105. package/types/plugins/keyboard/backspace/cases/check-remove-char.d.ts +20 -0
  106. package/types/plugins/keyboard/backspace/cases/check-remove-content-not-editable.d.ts +10 -0
  107. package/types/plugins/keyboard/backspace/cases/check-remove-empty-neighbor.d.ts +19 -0
  108. package/types/plugins/keyboard/backspace/cases/check-remove-empty-parent.d.ts +19 -0
  109. package/types/plugins/keyboard/backspace/cases/check-remove-unbreakable-element.d.ts +19 -0
  110. package/types/plugins/keyboard/backspace/cases/check-table-cell.d.ts +19 -0
  111. package/types/plugins/keyboard/backspace/cases/check-unwrap-first-list-item.d.ts +19 -0
  112. package/types/plugins/keyboard/backspace/cases/index.d.ts +8 -0
  113. package/types/plugins/keyboard/backspace/config.d.ts +20 -0
  114. package/types/plugins/keyboard/helpers.d.ts +2 -2
  115. package/types/plugins/select.d.ts +0 -1
  116. package/types/plugins/source/const.d.ts +6 -0
  117. package/types/plugins/source/editor/engines/ace.d.ts +1 -0
  118. package/types/plugins/source/source.d.ts +1 -0
  119. package/types/types/{ajax.d.ts → types/ajax.d.ts} +3 -0
  120. package/types/types/{async.d.ts → types/async.d.ts} +2 -0
  121. package/types/types/{context.d.ts → types/context.d.ts} +0 -0
  122. package/types/types/{core.ts → types/core.ts} +0 -0
  123. package/types/types/{create.d.ts → types/create.d.ts} +0 -0
  124. package/types/types/{dialog.d.ts → types/dialog.d.ts} +0 -0
  125. package/types/types/{events.d.ts → types/events.d.ts} +0 -0
  126. package/types/types/{file-browser.d.ts → types/file-browser.d.ts} +0 -0
  127. package/types/types/{form.d.ts → types/form.d.ts} +0 -0
  128. package/types/types/{index.d.ts → types/index.d.ts} +0 -0
  129. package/types/types/{jodit.d.ts → types/jodit.d.ts} +5 -8
  130. package/types/types/{observe.d.ts → types/observe.d.ts} +0 -0
  131. package/types/types/{plugin.d.ts → types/plugin.d.ts} +0 -0
  132. package/types/types/{popup.d.ts → types/popup.d.ts} +1 -0
  133. package/types/types/{select.d.ts → types/select.d.ts} +0 -0
  134. package/types/types/{source.d.ts → types/source.d.ts} +0 -0
  135. package/types/types/{storage.ts → types/storage.ts} +0 -0
  136. package/types/types/{style.d.ts → types/style.d.ts} +0 -0
  137. package/types/types/{toolbar.d.ts → types/toolbar.d.ts} +0 -0
  138. package/types/types/{traits.d.ts → types/traits.d.ts} +0 -0
  139. package/types/types/{types.d.ts → types/types.d.ts} +0 -0
  140. package/types/types/{ui.d.ts → types/ui.d.ts} +23 -4
  141. package/types/types/{uploader.d.ts → types/uploader.d.ts} +0 -0
  142. package/types/types/{view.d.ts → types/view.d.ts} +0 -0
  143. package/src/plugins/keyboard/delete.ts +0 -746
  144. package/types/plugins/keyboard/delete.d.ts +0 -161
@@ -0,0 +1,117 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit, Nullable } from '../../../../types';
8
+ import { findNotEmptySibling } from '../../helpers';
9
+ import { Dom } from '../../../../core/dom';
10
+
11
+ /**
12
+ * Check if two separate elements can be connected
13
+ */
14
+ export function checkJoinNeighbors(
15
+ jodit: IJodit,
16
+ fakeNode: Node,
17
+ backspace: boolean
18
+ ): boolean {
19
+ let nextBox: Nullable<Node> = fakeNode,
20
+ mainClosestBox: Nullable<Node> = nextBox;
21
+
22
+ // Find main big closest element
23
+ while (
24
+ nextBox &&
25
+ !findNotEmptySibling(nextBox, backspace) &&
26
+ nextBox.parentElement !== jodit.editor
27
+ ) {
28
+ nextBox = nextBox.parentElement;
29
+ mainClosestBox = nextBox;
30
+ }
31
+
32
+ if (
33
+ Dom.isElement(mainClosestBox) &&
34
+ Dom.isContentEditable(mainClosestBox, jodit.editor)
35
+ ) {
36
+ const sibling = findNotEmptySibling(
37
+ mainClosestBox,
38
+ backspace
39
+ ) as Nullable<Element>;
40
+
41
+ if (
42
+ sibling &&
43
+ (checkMoveListContent(jodit, mainClosestBox, sibling, backspace) ||
44
+ moveContentAndRemoveEmpty(
45
+ jodit,
46
+ mainClosestBox,
47
+ sibling,
48
+ backspace
49
+ ))
50
+ ) {
51
+ jodit.s.setCursorBefore(fakeNode);
52
+ return true;
53
+ }
54
+ }
55
+
56
+ return false;
57
+ }
58
+
59
+ function checkMoveListContent(
60
+ jodit: IJodit,
61
+ mainClosestBox: Element,
62
+ sibling: Element,
63
+ backspace: boolean
64
+ ): boolean {
65
+ // Process UL/LI/OL cases
66
+ const siblingIsList = Dom.isTag(sibling, ['ol', 'ul']);
67
+ const boxIsList = Dom.isTag(mainClosestBox, ['ol', 'ul']);
68
+ const elementChild = (elm: Element, side: boolean) =>
69
+ side ? elm.firstElementChild : elm.lastElementChild;
70
+
71
+ if (boxIsList) {
72
+ sibling = jodit.createInside.element(jodit.o.enterBlock);
73
+ Dom.before(mainClosestBox, sibling);
74
+
75
+ return moveContentAndRemoveEmpty(
76
+ jodit,
77
+ elementChild(mainClosestBox, backspace),
78
+ sibling,
79
+ backspace
80
+ );
81
+ }
82
+
83
+ if (sibling && siblingIsList && !boxIsList) {
84
+ return moveContentAndRemoveEmpty(
85
+ jodit,
86
+ mainClosestBox,
87
+ elementChild(sibling, !backspace),
88
+ backspace
89
+ );
90
+ }
91
+
92
+ return false;
93
+ }
94
+
95
+ function moveContentAndRemoveEmpty(
96
+ jodit: IJodit,
97
+ mainClosestBox: Nullable<Node>,
98
+ sibling: Nullable<Node>,
99
+ backspace: boolean
100
+ ): boolean {
101
+ // Move content and remove empty nodes
102
+ if (mainClosestBox && Dom.isElement(sibling)) {
103
+ Dom.moveContent(mainClosestBox, sibling, !backspace);
104
+
105
+ let remove: Nullable<Node> = mainClosestBox;
106
+
107
+ while (remove && remove !== jodit.editor && Dom.isEmpty(remove)) {
108
+ const parent: Nullable<Node> = remove.parentElement;
109
+ Dom.safeRemove(remove);
110
+ remove = parent;
111
+ }
112
+
113
+ return true;
114
+ }
115
+
116
+ return false;
117
+ }
@@ -0,0 +1,55 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit } from '../../../../types';
8
+ import { Dom } from '../../../../core/dom';
9
+ import { call } from '../../../../core/helpers';
10
+
11
+ /**
12
+ * Try join two UL elements
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <ul><li>one</li></ul>|<ol><li>two</li></ol>
17
+ * ```
18
+ * Result
19
+ * ```html
20
+ * <ul><li>one|</li><li>two</li></ul>
21
+ * ```
22
+ */
23
+ export function checkJoinTwoLists(
24
+ jodit: IJodit,
25
+ fakeNode: Node,
26
+ backspace: boolean
27
+ ): boolean {
28
+ const next = Dom.findSibling(fakeNode, backspace),
29
+ prev = Dom.findSibling(fakeNode, !backspace);
30
+
31
+ if (
32
+ !Dom.closest(fakeNode, Dom.isElement, jodit.editor) &&
33
+ Dom.isTag(next, ['ul', 'ol']) &&
34
+ Dom.isTag(prev, ['ul', 'ol']) &&
35
+ Dom.isTag(next.lastElementChild, 'li') &&
36
+ Dom.isTag(prev.firstElementChild, 'li')
37
+ ) {
38
+ const { setCursorBefore, setCursorAfter } = jodit.s;
39
+
40
+ const target = next.lastElementChild,
41
+ second = prev.firstElementChild;
42
+
43
+ call(!backspace ? Dom.append : Dom.prepend, second, fakeNode);
44
+
45
+ Dom.moveContent(prev, next, !backspace);
46
+ Dom.safeRemove(prev);
47
+
48
+ call(backspace ? Dom.append : Dom.prepend, target, fakeNode);
49
+ call(backspace ? setCursorBefore : setCursorAfter, fakeNode);
50
+
51
+ return true;
52
+ }
53
+
54
+ return false;
55
+ }
@@ -0,0 +1,27 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+ import type { IJodit } from '../../../../types';
7
+
8
+ /**
9
+ * On Not collapsed selection - should only remove whole selected content
10
+ *
11
+ * @example
12
+ * ```html
13
+ * <p>first | stop</p><p>second | stop</p>
14
+ * ```
15
+ * result
16
+ * ```html
17
+ * <p>first | stop</p>
18
+ * ```
19
+ */
20
+ export function checkNotCollapsed(jodit: IJodit): boolean {
21
+ if (!jodit.s.isCollapsed()) {
22
+ jodit.execCommand('Delete');
23
+ return true;
24
+ }
25
+
26
+ return false;
27
+ }
@@ -0,0 +1,191 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { CanUndef, IJodit, Nullable } from '../../../../types';
8
+ import type { DeleteMode } from '../interface';
9
+ import { findMostNestedNeighbor, getSibling } from '../../helpers';
10
+ import { Dom } from '../../../../core/dom';
11
+ import { call, isVoid, toArray, trimInv } from '../../../../core/helpers';
12
+ import { INVISIBLE_SPACE, NBSP_SPACE } from '../../../../core/constants';
13
+
14
+ /**
15
+ * Check possibility the char can be removed
16
+ *
17
+ * @example
18
+ * ```html
19
+ * te|st
20
+ * ```
21
+ * result
22
+ * ```html
23
+ * t|st
24
+ * ```
25
+ */
26
+ export function checkRemoveChar(
27
+ jodit: IJodit,
28
+ fakeNode: Node,
29
+ backspace: boolean,
30
+ mode: DeleteMode
31
+ ): boolean {
32
+ const step = backspace ? -1 : 1;
33
+ const anotherSibling: Nullable<Node> = getSibling(fakeNode, !backspace);
34
+
35
+ let sibling: Nullable<Node> = getSibling(fakeNode, backspace),
36
+ removeNeighbor: Nullable<Node> = null;
37
+
38
+ let charRemoved: boolean = false,
39
+ removed: CanUndef<string>;
40
+
41
+ while (sibling && (Dom.isText(sibling) || Dom.isInlineBlock(sibling))) {
42
+ while (Dom.isInlineBlock(sibling)) {
43
+ sibling = (
44
+ backspace ? sibling?.lastChild : sibling?.firstChild
45
+ ) as Nullable<Node>;
46
+ }
47
+
48
+ if (!sibling) {
49
+ break;
50
+ }
51
+
52
+ if (sibling.nodeValue?.length) {
53
+ // For Unicode escapes
54
+ let value = toArray(sibling.nodeValue);
55
+
56
+ const length = value.length;
57
+
58
+ let index = backspace ? length - 1 : 0;
59
+
60
+ if (value[index] === INVISIBLE_SPACE) {
61
+ while (value[index] === INVISIBLE_SPACE) {
62
+ index += step;
63
+ }
64
+ }
65
+
66
+ removed = value[index];
67
+
68
+ if (value[index + step] === INVISIBLE_SPACE) {
69
+ index += step;
70
+
71
+ while (value[index] === INVISIBLE_SPACE) {
72
+ index += step;
73
+ }
74
+
75
+ index += backspace ? 1 : -1;
76
+ }
77
+
78
+ if (backspace && index < 0) {
79
+ value = [];
80
+ } else {
81
+ value = value.slice(
82
+ backspace ? 0 : index + 1,
83
+ backspace ? index : length
84
+ );
85
+ }
86
+
87
+ if (
88
+ !anotherSibling ||
89
+ !Dom.isText(anotherSibling) ||
90
+ (!backspace ? / $/ : /^ /).test(
91
+ anotherSibling.nodeValue ?? ''
92
+ ) ||
93
+ !trimInv(anotherSibling.nodeValue || '').length
94
+ ) {
95
+ for (
96
+ let i = backspace ? value.length - 1 : 0;
97
+ backspace ? i >= 0 : i < value.length;
98
+ i += backspace ? -1 : 1
99
+ ) {
100
+ if (value[i] === ' ') {
101
+ value[i] = NBSP_SPACE;
102
+ } else {
103
+ break;
104
+ }
105
+ }
106
+ }
107
+
108
+ sibling.nodeValue = value.join('');
109
+ }
110
+
111
+ if (!sibling.nodeValue?.length) {
112
+ removeNeighbor = sibling;
113
+ }
114
+
115
+ if (!isVoid(removed) && removed !== INVISIBLE_SPACE) {
116
+ charRemoved = true;
117
+
118
+ call(backspace ? Dom.after : Dom.before, sibling, fakeNode);
119
+
120
+ if (
121
+ mode === 'sentence' ||
122
+ (mode === 'word' && removed !== ' ' && removed !== NBSP_SPACE)
123
+ ) {
124
+ checkRemoveChar(jodit, fakeNode, backspace, mode);
125
+ }
126
+
127
+ break;
128
+ }
129
+
130
+ let nextSibling = getSibling(sibling, backspace);
131
+
132
+ if (
133
+ !nextSibling &&
134
+ sibling.parentNode &&
135
+ sibling.parentNode !== jodit.editor
136
+ ) {
137
+ nextSibling = findMostNestedNeighbor(
138
+ sibling,
139
+ !backspace,
140
+ jodit.editor,
141
+ true
142
+ );
143
+ }
144
+
145
+ if (removeNeighbor) {
146
+ Dom.safeRemove(removeNeighbor);
147
+ removeNeighbor = null;
148
+ }
149
+
150
+ sibling = nextSibling;
151
+ }
152
+
153
+ if (charRemoved) {
154
+ removeEmptyInlineParent(fakeNode);
155
+ addBRInsideEmptyBlock(jodit, fakeNode);
156
+ jodit.s.setCursorBefore(fakeNode);
157
+ }
158
+
159
+ return charRemoved;
160
+ }
161
+
162
+ /**
163
+ * Helper remove all empty inline parents
164
+ */
165
+ function removeEmptyInlineParent(node: Node): void {
166
+ let parent = node.parentElement;
167
+
168
+ while (parent && Dom.isInlineBlock(parent)) {
169
+ const p = parent.parentElement;
170
+
171
+ if (Dom.isEmpty(parent)) {
172
+ Dom.after(parent, node);
173
+ Dom.safeRemove(parent);
174
+ }
175
+
176
+ parent = p;
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Helper add BR element inside empty block element
182
+ */
183
+ function addBRInsideEmptyBlock(jodit: IJodit, node: Node): void {
184
+ if (
185
+ node.parentElement !== jodit.editor &&
186
+ Dom.isBlock(node.parentElement) &&
187
+ Dom.each(node.parentElement, Dom.isEmptyTextNode)
188
+ ) {
189
+ Dom.after(node, jodit.createInside.element('br'));
190
+ }
191
+ }
@@ -0,0 +1,46 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+ import type { IJodit } from '../../../../types';
7
+ import { Dom } from '../../../../core/dom';
8
+ import { call } from '../../../../core/helpers';
9
+ import { normalizeCursorPosition } from '../../helpers';
10
+
11
+ /**
12
+ * Проверяет возможность удаления не редактируемго элемента
13
+ */
14
+ export function checkRemoveContentNotEditable(
15
+ jodit: IJodit,
16
+ fakeNode: Text,
17
+ backspace: boolean
18
+ ): boolean {
19
+ let neighbor = Dom.findSibling(fakeNode, backspace);
20
+
21
+ if (
22
+ !neighbor &&
23
+ fakeNode.parentElement &&
24
+ fakeNode.parentElement !== jodit.editor
25
+ ) {
26
+ neighbor = Dom.findSibling(fakeNode.parentElement, backspace);
27
+ }
28
+
29
+ if (
30
+ Dom.isElement(neighbor) &&
31
+ !Dom.isContentEditable(neighbor, jodit.editor)
32
+ ) {
33
+ call(backspace ? Dom.before : Dom.after, neighbor, fakeNode);
34
+ Dom.safeRemove(neighbor);
35
+ normalizeCursorPosition(jodit, fakeNode, backspace);
36
+
37
+ call(
38
+ backspace ? jodit.s.setCursorBefore : jodit.s.setCursorAfter,
39
+ fakeNode
40
+ );
41
+
42
+ return true;
43
+ }
44
+
45
+ return false;
46
+ }
@@ -0,0 +1,43 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit } from '../../../../types';
8
+ import { Dom } from '../../../../core/dom';
9
+ import { findNotEmptySibling } from '../../helpers';
10
+
11
+ /**
12
+ * Check if it is possible to remove an empty adjacent element.
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <p><br></p><p>|second stop</p>
17
+ * ```
18
+ * result
19
+ * ```html
20
+ * <p>|second stop</p>
21
+ * ```
22
+ */
23
+ export function checkRemoveEmptyNeighbor(
24
+ jodit: IJodit,
25
+ fakeNode: Node,
26
+ backspace: boolean
27
+ ): boolean {
28
+ const parent = Dom.closest(fakeNode, Dom.isElement, jodit.editor);
29
+
30
+ if (!parent) {
31
+ return false;
32
+ }
33
+
34
+ const neighbor = findNotEmptySibling(parent, backspace);
35
+
36
+ if (neighbor && Dom.isEmpty(neighbor)) {
37
+ Dom.safeRemove(neighbor);
38
+ jodit.s.setCursorBefore(fakeNode);
39
+ return true;
40
+ }
41
+
42
+ return false;
43
+ }
@@ -0,0 +1,80 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit, Nullable } from '../../../../types';
8
+ import { Dom } from '../../../../core/dom';
9
+ import { findNotEmptyNeighbor } from '../../helpers';
10
+ import { INSEPARABLE_TAGS } from '../../../../core/constants';
11
+ import { checkJoinTwoLists } from './check-join-two-lists';
12
+
13
+ /**
14
+ * Check if the current empty item can be removed
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <p>first stop</p><p>|<br></p>
19
+ * ```
20
+ * result
21
+ * ```html
22
+ * <p>first stop|</p>
23
+ * ```
24
+ */
25
+ export function checkRemoveEmptyParent(
26
+ jodit: IJodit,
27
+ fakeNode: Node,
28
+ backspace: boolean
29
+ ): boolean {
30
+ let found: boolean = false;
31
+ const { setCursorBefore, setCursorIn } = jodit.s;
32
+
33
+ let prn: Nullable<Node> = Dom.closest(
34
+ fakeNode,
35
+ Dom.isElement,
36
+ jodit.editor
37
+ );
38
+
39
+ if (!prn || !Dom.isEmpty(prn)) {
40
+ return false;
41
+ }
42
+
43
+ const neighbor = findNotEmptyNeighbor(fakeNode, backspace, jodit.editor);
44
+
45
+ do {
46
+ if (prn && Dom.isEmpty(prn) && !Dom.isCell(prn)) {
47
+ Dom.after(prn, fakeNode);
48
+
49
+ const tmp: Nullable<Node> = Dom.closest(
50
+ prn,
51
+ n => Dom.isElement(n) && n !== prn,
52
+ jodit.editor
53
+ );
54
+
55
+ Dom.safeRemove(prn);
56
+
57
+ found = true;
58
+
59
+ prn = tmp;
60
+ } else {
61
+ break;
62
+ }
63
+ } while (prn);
64
+
65
+ if (found && checkJoinTwoLists(jodit, fakeNode, backspace)) {
66
+ return true;
67
+ }
68
+
69
+ if (
70
+ neighbor &&
71
+ !Dom.isText(neighbor) &&
72
+ !Dom.isTag(neighbor, INSEPARABLE_TAGS)
73
+ ) {
74
+ setCursorIn(neighbor, !backspace);
75
+ } else {
76
+ setCursorBefore(fakeNode);
77
+ }
78
+
79
+ return found;
80
+ }
@@ -0,0 +1,46 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit } from '../../../../types';
8
+ import { Dom } from '../../../../core/dom';
9
+ import { INSEPARABLE_TAGS } from '../../../../core/constants';
10
+ import { checkRemoveEmptyParent } from './check-remove-empty-parent';
11
+
12
+ /**
13
+ * Check possibility inseparable Element can be removed (img, hr etc.)
14
+ *
15
+ * @example
16
+ * ```html
17
+ * <p>first second <img>| stop</p>
18
+ * ```
19
+ * result
20
+ * ```html
21
+ * <p>first second | stop</p>
22
+ * ```
23
+ */
24
+ export function checkRemoveUnbreakableElement(
25
+ jodit: IJodit,
26
+ fakeNode: Node,
27
+ backspace: boolean
28
+ ): boolean {
29
+ const neighbor = Dom.findSibling(fakeNode, backspace);
30
+
31
+ if (
32
+ Dom.isElement(neighbor) &&
33
+ (Dom.isTag(neighbor, INSEPARABLE_TAGS) || Dom.isEmpty(neighbor))
34
+ ) {
35
+ Dom.safeRemove(neighbor);
36
+ jodit.s.setCursorBefore(fakeNode);
37
+
38
+ if (Dom.isTag(neighbor, 'br')) {
39
+ checkRemoveEmptyParent(jodit, fakeNode, backspace);
40
+ }
41
+
42
+ return true;
43
+ }
44
+
45
+ return false;
46
+ }
@@ -0,0 +1,30 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import { Dom } from '../../../../core/dom';
8
+ import type { IJodit } from '../../../../types';
9
+
10
+ /**
11
+ * Inside the CELL table - nothing to do
12
+ *
13
+ * @example
14
+ * ```html
15
+ * <table><tr><td>|test</td></tr></table>
16
+ * ```
17
+ * result
18
+ * ```html
19
+ * <table><tr><td>|test</td></tr></table>
20
+ * ```
21
+ */
22
+ export function checkTableCell(jodit: IJodit, fakeNode: Node): boolean {
23
+ const cell = fakeNode.parentElement;
24
+
25
+ if (Dom.isCell(cell)) {
26
+ return true;
27
+ }
28
+
29
+ return false;
30
+ }
@@ -0,0 +1,57 @@
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-2021 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
5
+ */
6
+
7
+ import type { IJodit } from '../../../../types';
8
+ import { Dom } from '../../../../core/dom';
9
+ import { call } from '../../../../core/helpers';
10
+
11
+ /**
12
+ * For first item in list on backspace try move his content in new P
13
+ *
14
+ * @example
15
+ * ```html
16
+ * <ul><li>|first</li><li>second</li></ul>
17
+ * ```
18
+ * Result
19
+ * ```html
20
+ * <p>|first</p><ul><li>second</li></ul>
21
+ * ```
22
+ */
23
+ export function checkUnwrapFirstListItem(
24
+ jodit: IJodit,
25
+ fakeNode: Node,
26
+ backspace: boolean
27
+ ): boolean {
28
+ const li = Dom.closest(fakeNode, Dom.isElement, jodit.editor);
29
+
30
+ const { s } = jodit;
31
+
32
+ if (
33
+ Dom.isTag(li, 'li') &&
34
+ li?.parentElement?.[
35
+ backspace ? 'firstElementChild' : 'lastElementChild'
36
+ ] === li &&
37
+ s.cursorInTheEdge(backspace, li)
38
+ ) {
39
+ const ul = li.parentElement;
40
+ const p = jodit.createInside.element(jodit.o.enterBlock);
41
+
42
+ call(backspace ? Dom.before : Dom.after, ul, p);
43
+
44
+ Dom.moveContent(li, p);
45
+ Dom.safeRemove(li);
46
+
47
+ if (Dom.isEmpty(ul)) {
48
+ Dom.safeRemove(ul);
49
+ }
50
+
51
+ call(backspace ? s.setCursorBefore : s.setCursorAfter, fakeNode);
52
+
53
+ return true;
54
+ }
55
+
56
+ return false;
57
+ }