jodit 4.18.7 → 4.18.9

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 (145) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +9 -9
  4. package/es2015/jodit.js +215 -47
  5. package/es2015/jodit.min.js +7 -7
  6. package/es2015/plugins/debug/debug.css +1 -1
  7. package/es2015/plugins/debug/debug.js +1 -1
  8. package/es2015/plugins/debug/debug.min.js +1 -1
  9. package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
  10. package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
  11. package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
  12. package/es2018/jodit.fat.min.js +9 -9
  13. package/es2018/jodit.min.js +7 -7
  14. package/es2018/plugins/debug/debug.min.js +1 -1
  15. package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
  16. package/es2021/jodit.css +1 -1
  17. package/es2021/jodit.fat.min.js +10 -10
  18. package/es2021/jodit.js +215 -47
  19. package/es2021/jodit.min.js +7 -7
  20. package/es2021/plugins/debug/debug.css +1 -1
  21. package/es2021/plugins/debug/debug.js +1 -1
  22. package/es2021/plugins/debug/debug.min.js +1 -1
  23. package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
  24. package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
  25. package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
  26. package/es2021.en/jodit.css +1 -1
  27. package/es2021.en/jodit.fat.min.js +10 -10
  28. package/es2021.en/jodit.js +189 -21
  29. package/es2021.en/jodit.min.js +7 -7
  30. package/es2021.en/plugins/debug/debug.css +1 -1
  31. package/es2021.en/plugins/debug/debug.js +1 -1
  32. package/es2021.en/plugins/debug/debug.min.js +1 -1
  33. package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
  34. package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
  35. package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
  36. package/es5/jodit.css +2 -2
  37. package/es5/jodit.fat.min.js +2 -2
  38. package/es5/jodit.js +223 -47
  39. package/es5/jodit.min.css +2 -2
  40. package/es5/jodit.min.js +2 -2
  41. package/es5/plugins/debug/debug.css +1 -1
  42. package/es5/plugins/debug/debug.js +1 -1
  43. package/es5/plugins/debug/debug.min.js +1 -1
  44. package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
  45. package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
  46. package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
  47. package/es5/polyfills.fat.min.js +1 -1
  48. package/es5/polyfills.js +1 -1
  49. package/es5/polyfills.min.js +1 -1
  50. package/esm/config.d.ts +2 -2
  51. package/esm/core/constants.js +1 -1
  52. package/esm/core/ui/button/tooltip/tooltip.js +7 -0
  53. package/esm/langs/ar.d.ts +1 -0
  54. package/esm/langs/ar.js +2 -1
  55. package/esm/langs/az.d.ts +1 -0
  56. package/esm/langs/az.js +2 -1
  57. package/esm/langs/cs_cz.d.ts +1 -0
  58. package/esm/langs/cs_cz.js +2 -1
  59. package/esm/langs/de.d.ts +1 -0
  60. package/esm/langs/de.js +2 -1
  61. package/esm/langs/es.d.ts +1 -0
  62. package/esm/langs/es.js +2 -1
  63. package/esm/langs/fa.d.ts +1 -0
  64. package/esm/langs/fa.js +2 -1
  65. package/esm/langs/fi.d.ts +1 -0
  66. package/esm/langs/fi.js +2 -1
  67. package/esm/langs/fr.d.ts +1 -0
  68. package/esm/langs/fr.js +2 -1
  69. package/esm/langs/he.d.ts +1 -0
  70. package/esm/langs/he.js +2 -1
  71. package/esm/langs/hu.d.ts +1 -0
  72. package/esm/langs/hu.js +2 -1
  73. package/esm/langs/id.d.ts +1 -0
  74. package/esm/langs/id.js +2 -1
  75. package/esm/langs/it.d.ts +1 -0
  76. package/esm/langs/it.js +2 -1
  77. package/esm/langs/ja.d.ts +1 -0
  78. package/esm/langs/ja.js +2 -1
  79. package/esm/langs/ko.d.ts +1 -0
  80. package/esm/langs/ko.js +2 -1
  81. package/esm/langs/mn.d.ts +1 -0
  82. package/esm/langs/mn.js +2 -1
  83. package/esm/langs/nl.d.ts +1 -0
  84. package/esm/langs/nl.js +2 -1
  85. package/esm/langs/no.d.ts +1 -0
  86. package/esm/langs/no.js +2 -1
  87. package/esm/langs/pl.d.ts +1 -0
  88. package/esm/langs/pl.js +2 -1
  89. package/esm/langs/pt_br.d.ts +1 -0
  90. package/esm/langs/pt_br.js +2 -1
  91. package/esm/langs/ru.d.ts +1 -0
  92. package/esm/langs/ru.js +2 -1
  93. package/esm/langs/sk.d.ts +1 -0
  94. package/esm/langs/sk.js +2 -1
  95. package/esm/langs/sv.d.ts +1 -0
  96. package/esm/langs/sv.js +2 -1
  97. package/esm/langs/tr.d.ts +1 -0
  98. package/esm/langs/tr.js +2 -1
  99. package/esm/langs/ua.d.ts +1 -0
  100. package/esm/langs/ua.js +2 -1
  101. package/esm/langs/zh_cn.d.ts +1 -0
  102. package/esm/langs/zh_cn.js +2 -1
  103. package/esm/langs/zh_tw.d.ts +1 -0
  104. package/esm/langs/zh_tw.js +2 -1
  105. package/esm/modules/dialog/dialog.js +19 -3
  106. package/esm/plugins/ai-assistant/ui/ui-ai-assistant.js +11 -2
  107. package/esm/plugins/backspace/cases/check-join-neighbors.js +81 -0
  108. package/esm/plugins/backspace/cases/check-remove-char.js +6 -5
  109. package/esm/plugins/backspace/cases/check-unwrap-list-item.d.ts +26 -0
  110. package/esm/plugins/backspace/cases/check-unwrap-list-item.js +56 -0
  111. package/esm/plugins/backspace/cases/index.js +2 -0
  112. package/esm/plugins/backspace/config.d.ts +2 -2
  113. package/esm/plugins/bold/config.js +2 -2
  114. package/esm/plugins/enter/enter.js +1 -1
  115. package/esm/plugins/enter/helpers/check-br.js +7 -2
  116. package/package.json +1 -1
  117. package/types/config.d.ts +2 -2
  118. package/types/langs/ar.d.ts +1 -0
  119. package/types/langs/az.d.ts +1 -0
  120. package/types/langs/cs_cz.d.ts +1 -0
  121. package/types/langs/de.d.ts +1 -0
  122. package/types/langs/es.d.ts +1 -0
  123. package/types/langs/fa.d.ts +1 -0
  124. package/types/langs/fi.d.ts +1 -0
  125. package/types/langs/fr.d.ts +1 -0
  126. package/types/langs/he.d.ts +1 -0
  127. package/types/langs/hu.d.ts +1 -0
  128. package/types/langs/id.d.ts +1 -0
  129. package/types/langs/it.d.ts +1 -0
  130. package/types/langs/ja.d.ts +1 -0
  131. package/types/langs/ko.d.ts +1 -0
  132. package/types/langs/mn.d.ts +1 -0
  133. package/types/langs/nl.d.ts +1 -0
  134. package/types/langs/no.d.ts +1 -0
  135. package/types/langs/pl.d.ts +1 -0
  136. package/types/langs/pt_br.d.ts +1 -0
  137. package/types/langs/ru.d.ts +1 -0
  138. package/types/langs/sk.d.ts +1 -0
  139. package/types/langs/sv.d.ts +1 -0
  140. package/types/langs/tr.d.ts +1 -0
  141. package/types/langs/ua.d.ts +1 -0
  142. package/types/langs/zh_cn.d.ts +1 -0
  143. package/types/langs/zh_tw.d.ts +1 -0
  144. package/types/plugins/backspace/cases/check-unwrap-list-item.d.ts +26 -0
  145. package/types/plugins/backspace/config.d.ts +2 -2
@@ -28,6 +28,10 @@ import { Icon } from "../../core/ui/index.js";
28
28
  import { View } from "../../core/view/view.js";
29
29
  import { ViewWithToolbar } from "../../core/view/view-with-toolbar.js";
30
30
  import { Config } from "../../config.js";
31
+ /**
32
+ * A position from 0 up to `max`, or 0 when the panel is larger than the window
33
+ */
34
+ const clampToWindow = (value, max) => Math.max(0, Math.min(value, max));
31
35
  Config.prototype.dialog = {
32
36
  namespace: '',
33
37
  extraButtons: [],
@@ -47,6 +51,7 @@ Config.prototype.dialog = {
47
51
  Config.prototype.controls.dialog = {
48
52
  close: {
49
53
  icon: 'cancel',
54
+ tooltip: 'Close',
50
55
  exec: dialog => {
51
56
  dialog.close();
52
57
  }
@@ -126,6 +131,11 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
126
131
  this.startY = e.clientY;
127
132
  this.startPoint.x = css(this.dialog, 'left');
128
133
  this.startPoint.y = css(this.dialog, 'top');
134
+ // Rounded up: at the right edge a fraction of a pixel less room would
135
+ // wrap the header of a panel that has no width of its own
136
+ const { width, height } = this.dialog.getBoundingClientRect();
137
+ this.startPoint.w = Math.ceil(width);
138
+ this.startPoint.h = Math.ceil(height);
129
139
  this.setMaxZIndex();
130
140
  if (e.cancelable) {
131
141
  e.preventDefault();
@@ -142,7 +152,13 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
142
152
  }
143
153
  __onMouseMove(e) {
144
154
  if (this.draggable && this.o.draggable) {
145
- this.setPosition(this.startPoint.x + e.clientX - this.startX, this.startPoint.y + e.clientY - this.startY);
155
+ const { documentElement } = this.od;
156
+ // Keep the whole panel in the window at the size it had when the
157
+ // drag began. A panel with no width of its own would otherwise
158
+ // shrink as it neared the right edge, and then leave the window
159
+ this.setPosition(clampToWindow(this.startPoint.x + e.clientX - this.startX, (documentElement.clientWidth || this.ow.innerWidth) -
160
+ this.startPoint.w), clampToWindow(this.startPoint.y + e.clientY - this.startY, (documentElement.clientHeight || this.ow.innerHeight) -
161
+ this.startPoint.h));
146
162
  if (this.e) {
147
163
  /**
148
164
  * Fired when dialog box is moved
@@ -291,8 +307,8 @@ let Dialog = Dialog_1 = class Dialog extends ViewWithToolbar {
291
307
  }
292
308
  // strings on purpose: `css()` would truncate fractional pixels
293
309
  css(this.dialog, {
294
- left: (x || left) + 'px',
295
- top: (y || top) + 'px'
310
+ left: (x !== null && x !== void 0 ? x : left) + 'px',
311
+ top: (y !== null && y !== void 0 ? y : top) + 'px'
296
312
  });
297
313
  return this;
298
314
  }
@@ -40,8 +40,17 @@ let UiAiAssistant = class UiAiAssistant extends UIElement {
40
40
  this.__toggleSubmitButton(true);
41
41
  }
42
42
  };
43
- this.__submitButton = Button(jodit, 'ai-assistant', '').onAction(onSubmit);
44
- this.__tryAgainButton = Button(jodit, 'update', '', 'initial').onAction(onSubmit);
43
+ this.__submitButton = Button(jodit, {
44
+ icon: { name: 'ai-assistant' },
45
+ name: 'ai-assistant',
46
+ tooltip: 'Submit'
47
+ }).onAction(onSubmit);
48
+ this.__tryAgainButton = Button(jodit, {
49
+ icon: { name: 'update' },
50
+ name: 'update',
51
+ tooltip: 'Try Again',
52
+ variant: 'initial'
53
+ }).onAction(onSubmit);
45
54
  this.promptInput = new UITextArea(jodit, {
46
55
  name: 'prompt',
47
56
  required: true,
@@ -11,6 +11,9 @@ import { getMoveFilter } from "../helpers.js";
11
11
  * @private
12
12
  */
13
13
  export function checkJoinNeighbors(jodit, fakeNode, backspace) {
14
+ if (checkJoinBareText(jodit, fakeNode, backspace)) {
15
+ return true;
16
+ }
14
17
  let nextBox = fakeNode, mainClosestBox = nextBox;
15
18
  // Find the main big closest element
16
19
  while (nextBox &&
@@ -44,6 +47,7 @@ export function checkJoinNeighbors(jodit, fakeNode, backspace) {
44
47
  if (sibling &&
45
48
  (checkPullNextLine(jodit, fakeNode, box, sibling, backspace) ||
46
49
  checkMoveListContent(jodit, box, sibling, backspace) ||
50
+ checkJoinInlineSibling(jodit, box, sibling, backspace) ||
47
51
  moveContentAndRemoveEmpty(jodit, box, findEdgeBlock(resolveTableSibling(sibling, backspace), backspace, jodit.editor), backspace))) {
48
52
  jodit.s.setCursorBefore(fakeNode);
49
53
  return true;
@@ -143,6 +147,83 @@ function checkPullNextLine(jodit, fakeNode, box, sibling, backspace) {
143
147
  }
144
148
  return true;
145
149
  }
150
+ /**
151
+ * A block next to bare text in the same parent joins that text, as the
152
+ * browsers do: `<li>one<p>|two</p></li>` gives `<li>one|two</li>`, and
153
+ * `<li><p>one|</p>two</li>` gives `<li><p>one|two</p></li>`
154
+ * @private
155
+ */
156
+ function checkJoinInlineSibling(jodit, box, sibling, backspace) {
157
+ if (Dom.isBlock(sibling) ||
158
+ !Dom.isBlock(box) ||
159
+ Dom.isList(box) ||
160
+ // The caret's block is nested deeper than the text: `text<div><p>|x</p></div>`
161
+ box.parentNode !== sibling.parentNode ||
162
+ Array.from(box.childNodes).some(node => Dom.isBlock(node))) {
163
+ return false;
164
+ }
165
+ if (backspace) {
166
+ // Text after the block keeps its own line
167
+ const next = Dom.findNotEmptySibling(box, false);
168
+ if (next && !Dom.isBlock(next) && !Dom.isTag(next, 'br')) {
169
+ Dom.after(box, jodit.createInside.element('br'));
170
+ }
171
+ Dom.unwrap(box);
172
+ return true;
173
+ }
174
+ const filter = getMoveFilter(jodit);
175
+ for (let node = sibling; node && !Dom.isBlock(node);) {
176
+ const next = node.nextSibling;
177
+ if (Dom.isTag(node, 'br')) {
178
+ Dom.safeRemove(node);
179
+ break;
180
+ }
181
+ filter(node) ? Dom.append(box, node) : Dom.safeRemove(node);
182
+ node = next;
183
+ }
184
+ return true;
185
+ }
186
+ /**
187
+ * Bare text next to a block in the same parent, as the browsers join them:
188
+ * Backspace in `<div><p>a</p>|b</div>` gives `<div><p>a|b</p></div>`, Delete
189
+ * in `<div>a|<p>b</p>c</div>` gives `<div>a|b<br>c</div>`
190
+ */
191
+ function checkJoinBareText(jodit, fakeNode, backspace) {
192
+ const block = Dom.findNotEmptySibling(fakeNode, backspace);
193
+ if (!Dom.isElement(block) ||
194
+ !Dom.isBlock(block) ||
195
+ Dom.isList(block) ||
196
+ Dom.isTag(block, 'table') ||
197
+ Dom.isCell(block) ||
198
+ !Dom.isContentEditable(block, jodit.editor) ||
199
+ Array.from(block.childNodes).some(node => Dom.isBlock(node))) {
200
+ return false;
201
+ }
202
+ const filter = getMoveFilter(jodit);
203
+ if (backspace) {
204
+ // The caret's line goes to the end of the block before it
205
+ for (let node = fakeNode; node && !Dom.isBlock(node);) {
206
+ const next = node.nextSibling;
207
+ if (Dom.isTag(node, 'br')) {
208
+ Dom.safeRemove(node);
209
+ break;
210
+ }
211
+ filter(node) ? Dom.append(block, node) : Dom.safeRemove(node);
212
+ node = next;
213
+ }
214
+ }
215
+ else {
216
+ // The block's content joins the caret's line, and text after the
217
+ // block keeps its own line
218
+ const next = Dom.findNotEmptySibling(block, false);
219
+ if (next && !Dom.isBlock(next) && !Dom.isTag(next, 'br')) {
220
+ Dom.after(block, jodit.createInside.element('br'));
221
+ }
222
+ Dom.unwrap(block);
223
+ }
224
+ jodit.s.setCursorBefore(fakeNode);
225
+ return true;
226
+ }
146
227
  function checkMoveListContent(jodit, mainClosestBox, sibling, backspace) {
147
228
  // Process UL/LI/OL cases
148
229
  const siblingIsList = Dom.isTag(sibling, LIST_TAGS);
@@ -84,12 +84,13 @@ function getNextInlineSibling(sibling, backspace, root) {
84
84
  let nextSibling = Dom.sibling(sibling, backspace);
85
85
  if (!nextSibling && sibling.parentNode && sibling.parentNode !== root) {
86
86
  nextSibling = findMostNestedNeighbor(sibling, !backspace, root, true);
87
- // Do not cross a list-item boundary. At the start of a list item the
88
- // neighbor can be the text of the parent/previous item; deleting a char
89
- // there is wrong — the list cases must handle the outdent/merge (#1277).
87
+ // Do not cross a block boundary. At the start of a list item the
88
+ // neighbor can be the text of the parent/previous item (#1277), and at
89
+ // the start of a paragraph the text before it in the same parent
90
+ // (#1693); deleting a char there is wrong — the join cases handle them.
90
91
  if (nextSibling &&
91
- Dom.closest(sibling, 'li', root) !==
92
- Dom.closest(nextSibling, 'li', root)) {
92
+ Dom.closest(sibling, Dom.isBlock, root) !==
93
+ Dom.closest(nextSibling, Dom.isBlock, root)) {
93
94
  return null;
94
95
  }
95
96
  }
@@ -0,0 +1,26 @@
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/backspace
8
+ */
9
+ import type { IJodit } from "../../../types/index";
10
+ /**
11
+ * Backspace at the start of a later list item takes the bullet off, as Word
12
+ * does: the item becomes a paragraph where it was, and the list is split
13
+ * around it. A split `<ol>` carries its numbering on with `start`.
14
+ *
15
+ * @example
16
+ * ```html
17
+ * <ol><li>first</li><li>|second</li><li>third</li></ol>
18
+ * ```
19
+ * Result
20
+ * ```html
21
+ * <ol><li>first</li></ol><p>|second</p><ol start="2"><li>third</li></ol>
22
+ * ```
23
+ *
24
+ * @private
25
+ */
26
+ export declare function checkUnwrapListItem(jodit: IJodit, fakeNode: Node, backspace: boolean): boolean;
@@ -0,0 +1,56 @@
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 { Dom } from "../../../core/dom/dom.js";
7
+ /**
8
+ * Backspace at the start of a later list item takes the bullet off, as Word
9
+ * does: the item becomes a paragraph where it was, and the list is split
10
+ * around it. A split `<ol>` carries its numbering on with `start`.
11
+ *
12
+ * @example
13
+ * ```html
14
+ * <ol><li>first</li><li>|second</li><li>third</li></ol>
15
+ * ```
16
+ * Result
17
+ * ```html
18
+ * <ol><li>first</li></ol><p>|second</p><ol start="2"><li>third</li></ol>
19
+ * ```
20
+ *
21
+ * @private
22
+ */
23
+ export function checkUnwrapListItem(jodit, fakeNode, backspace) {
24
+ if (!backspace) {
25
+ return false;
26
+ }
27
+ const li = Dom.closest(fakeNode, 'li', jodit.editor);
28
+ const list = li ? li.parentElement : null;
29
+ if (!li ||
30
+ !Dom.isList(list) ||
31
+ !li.previousElementSibling ||
32
+ Dom.isEmpty(li) ||
33
+ Array.from(li.childNodes).some(node => Dom.isBlock(node)) ||
34
+ !jodit.s.cursorInTheEdge(true, li)) {
35
+ return false;
36
+ }
37
+ const p = jodit.createInside.element(jodit.o.enterBlock);
38
+ Dom.after(list, p);
39
+ if (li.nextElementSibling) {
40
+ const rest = list.cloneNode(false);
41
+ // Two lists cannot share one id
42
+ rest.removeAttribute('id');
43
+ while (li.nextSibling) {
44
+ Dom.append(rest, li.nextSibling);
45
+ }
46
+ if (Dom.isTag(list, 'ol')) {
47
+ const start = parseInt(list.getAttribute('start') || '1', 10) || 1;
48
+ rest.setAttribute('start', String(start + list.children.length - 1));
49
+ }
50
+ Dom.after(p, rest);
51
+ }
52
+ Dom.moveContent(li, p);
53
+ Dom.safeRemove(li);
54
+ jodit.s.setCursorBefore(fakeNode);
55
+ return true;
56
+ }
@@ -12,6 +12,7 @@ import { checkRemoveEmptyParent } from "./check-remove-empty-parent.js";
12
12
  import { checkRemoveUnbreakableElement } from "./check-remove-unbreakable-element.js";
13
13
  import { checkTableCell } from "./check-table-cell.js";
14
14
  import { checkUnwrapFirstListItem } from "./check-unwrap-first-list-item.js";
15
+ import { checkUnwrapListItem } from "./check-unwrap-list-item.js";
15
16
  /**
16
17
  * Ordered delete/backspace cases with stable keys. The first one returning
17
18
  * `true` wins. The keys are stable across minified builds (function names are
@@ -26,6 +27,7 @@ export const casesMap = [
26
27
  ['remove-empty-parent', checkRemoveEmptyParent],
27
28
  ['remove-empty-neighbor', checkRemoveEmptyNeighbor],
28
29
  ['join-two-lists', checkJoinTwoLists],
30
+ ['unwrap-list-item', checkUnwrapListItem],
29
31
  ['join-neighbors', checkJoinNeighbors],
30
32
  ['unwrap-first-list-item', checkUnwrapFirstListItem]
31
33
  ];
@@ -24,8 +24,8 @@ declare module 'jodit/config' {
24
24
  * key, so the plugin no longer applies that particular behavior.
25
25
  * Available keys: `remove-unbreakable`, `remove-not-editable`,
26
26
  * `remove-char`, `table-cell`, `remove-empty-parent`,
27
- * `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
28
- * `unwrap-first-list-item`.
27
+ * `remove-empty-neighbor`, `join-two-lists`, `unwrap-list-item`,
28
+ * `join-neighbors`, `unwrap-first-list-item`.
29
29
  *
30
30
  * ```javascript
31
31
  * Jodit.make('#editor', {
@@ -6,11 +6,11 @@
6
6
  import { Config } from "../../config.js";
7
7
  Config.prototype.controls.subscript = {
8
8
  tags: ['sub'],
9
- tooltip: 'subscript'
9
+ tooltip: 'Subscript'
10
10
  };
11
11
  Config.prototype.controls.superscript = {
12
12
  tags: ['sup'],
13
- tooltip: 'superscript'
13
+ tooltip: 'Superscript'
14
14
  };
15
15
  Config.prototype.controls.bold = {
16
16
  tagRegExp: /^(strong|b)$/i,
@@ -68,7 +68,7 @@ export class enter extends Plugin {
68
68
  moveCursorOutFromSpecialTags(jodit, fake, ['a']);
69
69
  let block = getBlockWrapper(fake, jodit);
70
70
  const isLi = Dom.isLeaf(block);
71
- // if use <br> defaultTag for break line or when was entered SHIFt key or in <td> or <th> or <blockquote>
71
+ // if use <br> defaultTag for break line or when was entered SHIFt key or in <td>, <th> or <blockquote> without an inner block
72
72
  if ((!isLi || (event === null || event === void 0 ? void 0 : event.shiftKey)) &&
73
73
  checkBR(fake, jodit, event === null || event === void 0 ? void 0 : event.shiftKey, block)) {
74
74
  return false;
@@ -11,7 +11,12 @@ import { scrollIntoViewIfNeeded } from "../../../core/helpers/utils/scroll-into-
11
11
  * @private
12
12
  */
13
13
  export function checkBR(fake, jodit, shiftKeyPressed, block) {
14
- const isMultiLineBlock = Boolean(Dom.closest(fake, ['pre', 'blockquote'], jodit.editor));
14
+ // Text in a <pre>, or bare text in a quote, gets a BR. A real block inside
15
+ // a quote (<p>, <h3>, ...) is split like anywhere else, as in a cell below.
16
+ const isMultiLineBlock = Boolean(Dom.closest(fake, 'pre', jodit.editor)) ||
17
+ (block
18
+ ? Dom.isTag(block, 'blockquote')
19
+ : Boolean(Dom.closest(fake, 'blockquote', jodit.editor)));
15
20
  // A cell itself can't be split into two cells, so bare cell content gets
16
21
  // a BR. But when the cell already holds a real block (<p>, <h3>, ...) that
17
22
  // block is split like anywhere else, otherwise every line of the cell
@@ -21,7 +26,7 @@ export function checkBR(fake, jodit, shiftKeyPressed, block) {
21
26
  ? Dom.isCell(block)
22
27
  : Boolean(Dom.closest(fake, ['td', 'th'], jodit.editor)));
23
28
  const isBRMode = jodit.o.enter.toLowerCase() === BR.toLowerCase();
24
- // if you use <br> defaultTag for break line or when was entered SHIFt key or in <td> or <th> or <blockquote>
29
+ // if you use <br> defaultTag for break line or when was entered SHIFt key or in <td>, <th> or <blockquote> without an inner block
25
30
  if (isBRMode ||
26
31
  isCell ||
27
32
  (shiftKeyPressed && !isMultiLineBlock) ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jodit",
3
- "version": "4.18.7",
3
+ "version": "4.18.9",
4
4
  "description": "Jodit is an awesome and useful wysiwyg editor with filebrowser",
5
5
  "main": "esm/index.js",
6
6
  "types": "types/index.d.ts",
package/types/config.d.ts CHANGED
@@ -1051,8 +1051,8 @@ interface Config {
1051
1051
  * key, so the plugin no longer applies that particular behavior.
1052
1052
  * Available keys: `remove-unbreakable`, `remove-not-editable`,
1053
1053
  * `remove-char`, `table-cell`, `remove-empty-parent`,
1054
- * `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
1055
- * `unwrap-first-list-item`.
1054
+ * `remove-empty-neighbor`, `join-two-lists`, `unwrap-list-item`,
1055
+ * `join-neighbors`, `unwrap-first-list-item`.
1056
1056
  *
1057
1057
  * ```javascript
1058
1058
  * Jodit.make('#editor', {
@@ -223,5 +223,6 @@ declare const _exports: {
223
223
  'Start at...': string;
224
224
  'Start numbering at': string;
225
225
  'Number for the first item': string;
226
+ Close: string;
226
227
  };
227
228
  export = _exports;
@@ -229,5 +229,6 @@ declare const _exports: {
229
229
  'Start at...': string;
230
230
  'Start numbering at': string;
231
231
  'Number for the first item': string;
232
+ Close: string;
232
233
  };
233
234
  export = _exports;
@@ -221,5 +221,6 @@ declare const _exports: {
221
221
  'Start at...': string;
222
222
  'Start numbering at': string;
223
223
  'Number for the first item': string;
224
+ Close: string;
224
225
  };
225
226
  export = _exports;
@@ -225,5 +225,6 @@ declare const _exports: {
225
225
  'Start at...': string;
226
226
  'Start numbering at': string;
227
227
  'Number for the first item': string;
228
+ Close: string;
228
229
  };
229
230
  export = _exports;
@@ -225,5 +225,6 @@ declare const _exports: {
225
225
  'Start at...': string;
226
226
  'Start numbering at': string;
227
227
  'Number for the first item': string;
228
+ Close: string;
228
229
  };
229
230
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -226,5 +226,6 @@ declare const _exports: {
226
226
  'Start at...': string;
227
227
  'Start numbering at': string;
228
228
  'Number for the first item': string;
229
+ Close: string;
229
230
  };
230
231
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -222,5 +222,6 @@ declare const _exports: {
222
222
  'Start at...': string;
223
223
  'Start numbering at': string;
224
224
  'Number for the first item': string;
225
+ Close: string;
225
226
  };
226
227
  export = _exports;
@@ -221,5 +221,6 @@ declare const _exports: {
221
221
  'Start at...': string;
222
222
  'Start numbering at': string;
223
223
  'Number for the first item': string;
224
+ Close: string;
224
225
  };
225
226
  export = _exports;
@@ -225,5 +225,6 @@ declare const _exports: {
225
225
  'Start at...': string;
226
226
  'Start numbering at': string;
227
227
  'Number for the first item': string;
228
+ Close: string;
228
229
  };
229
230
  export = _exports;
@@ -225,5 +225,6 @@ declare const _exports: {
225
225
  'Start at...': string;
226
226
  'Start numbering at': string;
227
227
  'Number for the first item': string;
228
+ Close: string;
228
229
  };
229
230
  export = _exports;
@@ -219,5 +219,6 @@ declare const _exports: {
219
219
  'Start at...': string;
220
220
  'Start numbering at': string;
221
221
  'Number for the first item': string;
222
+ Close: string;
222
223
  };
223
224
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -221,5 +221,6 @@ declare const _exports: {
221
221
  'Start at...': string;
222
222
  'Start numbering at': string;
223
223
  'Number for the first item': string;
224
+ Close: string;
224
225
  };
225
226
  export = _exports;
@@ -229,5 +229,6 @@ declare const _exports: {
229
229
  'Start at...': string;
230
230
  'Start numbering at': string;
231
231
  'Number for the first item': string;
232
+ Close: string;
232
233
  };
233
234
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -225,5 +225,6 @@ declare const _exports: {
225
225
  'Start at...': string;
226
226
  'Start numbering at': string;
227
227
  'Number for the first item': string;
228
+ Close: string;
228
229
  };
229
230
  export = _exports;
@@ -219,5 +219,6 @@ declare const _exports: {
219
219
  'Start at...': string;
220
220
  'Start numbering at': string;
221
221
  'Number for the first item': string;
222
+ Close: string;
222
223
  };
223
224
  export = _exports;
@@ -227,5 +227,6 @@ declare const _exports: {
227
227
  'Start at...': string;
228
228
  'Start numbering at': string;
229
229
  'Number for the first item': string;
230
+ Close: string;
230
231
  };
231
232
  export = _exports;
@@ -228,5 +228,6 @@ declare const _exports: {
228
228
  'Start at...': string;
229
229
  'Start numbering at': string;
230
230
  'Number for the first item': string;
231
+ Close: string;
231
232
  };
232
233
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -219,5 +219,6 @@ declare const _exports: {
219
219
  'Start at...': string;
220
220
  'Start numbering at': string;
221
221
  'Number for the first item': string;
222
+ Close: string;
222
223
  };
223
224
  export = _exports;
@@ -221,5 +221,6 @@ declare const _exports: {
221
221
  'Start at...': string;
222
222
  'Start numbering at': string;
223
223
  'Number for the first item': string;
224
+ Close: string;
224
225
  };
225
226
  export = _exports;
@@ -220,5 +220,6 @@ declare const _exports: {
220
220
  'Start at...': string;
221
221
  'Start numbering at': string;
222
222
  'Number for the first item': string;
223
+ Close: string;
223
224
  };
224
225
  export = _exports;
@@ -0,0 +1,26 @@
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/backspace
8
+ */
9
+ import type { IJodit } from "../../../types/index";
10
+ /**
11
+ * Backspace at the start of a later list item takes the bullet off, as Word
12
+ * does: the item becomes a paragraph where it was, and the list is split
13
+ * around it. A split `<ol>` carries its numbering on with `start`.
14
+ *
15
+ * @example
16
+ * ```html
17
+ * <ol><li>first</li><li>|second</li><li>third</li></ol>
18
+ * ```
19
+ * Result
20
+ * ```html
21
+ * <ol><li>first</li></ol><p>|second</p><ol start="2"><li>third</li></ol>
22
+ * ```
23
+ *
24
+ * @private
25
+ */
26
+ export declare function checkUnwrapListItem(jodit: IJodit, fakeNode: Node, backspace: boolean): boolean;
@@ -24,8 +24,8 @@ declare module 'jodit/config' {
24
24
  * key, so the plugin no longer applies that particular behavior.
25
25
  * Available keys: `remove-unbreakable`, `remove-not-editable`,
26
26
  * `remove-char`, `table-cell`, `remove-empty-parent`,
27
- * `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
28
- * `unwrap-first-list-item`.
27
+ * `remove-empty-neighbor`, `join-two-lists`, `unwrap-list-item`,
28
+ * `join-neighbors`, `unwrap-first-list-item`.
29
29
  *
30
30
  * ```javascript
31
31
  * Jodit.make('#editor', {