jodit 4.18.6 → 4.18.8

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 (76) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +9 -9
  4. package/es2015/jodit.js +265 -36
  5. package/es2015/jodit.min.js +9 -9
  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 +11 -11
  18. package/es2021/jodit.js +264 -36
  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 +8 -8
  28. package/es2021.en/jodit.js +264 -36
  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 +280 -35
  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 +4 -2
  51. package/esm/core/constants.js +1 -1
  52. package/esm/core/decorators/component/component.js +12 -0
  53. package/esm/core/ui/popup/popup.js +14 -9
  54. package/esm/jodit.js +5 -1
  55. package/esm/modules/dialog/dialog.js +18 -3
  56. package/esm/modules/file-browser/ui/files/files.js +17 -2
  57. package/esm/modules/file-browser/ui/tree/tree.js +17 -2
  58. package/esm/plugins/backspace/cases/check-join-neighbors.js +81 -0
  59. package/esm/plugins/backspace/cases/check-remove-char.d.ts +2 -1
  60. package/esm/plugins/backspace/cases/check-remove-char.js +31 -9
  61. package/esm/plugins/backspace/cases/check-unwrap-list-item.d.ts +26 -0
  62. package/esm/plugins/backspace/cases/check-unwrap-list-item.js +56 -0
  63. package/esm/plugins/backspace/cases/index.js +2 -0
  64. package/esm/plugins/backspace/config.d.ts +4 -2
  65. package/esm/plugins/backspace/config.js +6 -3
  66. package/esm/plugins/enter/enter.js +1 -1
  67. package/esm/plugins/enter/helpers/check-br.js +7 -2
  68. package/esm/plugins/image-properties/image-properties.d.ts +5 -0
  69. package/esm/plugins/image-properties/image-properties.js +30 -5
  70. package/esm/plugins/mobile/mobile.js +7 -4
  71. package/package.json +1 -1
  72. package/types/config.d.ts +4 -2
  73. package/types/plugins/backspace/cases/check-remove-char.d.ts +2 -1
  74. package/types/plugins/backspace/cases/check-unwrap-list-item.d.ts +26 -0
  75. package/types/plugins/backspace/config.d.ts +4 -2
  76. package/types/plugins/image-properties/image-properties.d.ts +5 -0
@@ -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: {
@@ -22,8 +24,8 @@ declare module 'jodit/config' {
22
24
  * key, so the plugin no longer applies that particular behavior.
23
25
  * Available keys: `remove-unbreakable`, `remove-not-editable`,
24
26
  * `remove-char`, `table-cell`, `remove-empty-parent`,
25
- * `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
26
- * `unwrap-first-list-item`.
27
+ * `remove-empty-neighbor`, `join-two-lists`, `unwrap-list-item`,
28
+ * `join-neighbors`, `unwrap-first-list-item`.
27
29
  *
28
30
  * ```javascript
29
31
  * Jodit.make('#editor', {
@@ -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: ['ctrl+delete', 'cmd+alt+backspace', 'ctrl+alt+backspace'],
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
  };
@@ -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) ||
@@ -52,6 +52,11 @@ export declare class imageProperties extends Plugin {
52
52
  * ```
53
53
  */
54
54
  protected open(): void | false;
55
+ /**
56
+ * Keys typed while the dialog is open must not reach the editor behind it,
57
+ * so focus the active tab's first field, or else the first field shown
58
+ */
59
+ private __focusFirstField;
55
60
  private __lock;
56
61
  private __unlock;
57
62
  /** @override **/
@@ -16,7 +16,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
16
16
  import { cache, cached, watch } from "../../core/decorators/index.js";
17
17
  import { Dom } from "../../core/dom/dom.js";
18
18
  import { pluginSystem } from "../../core/global.js";
19
- import { isAbortError, isNumeric, markOwner } from "../../core/helpers/index.js";
19
+ import { isAbortError, isNumeric, markOwner, toArray } from "../../core/helpers/index.js";
20
20
  import { Plugin } from "../../core/plugin/plugin.js";
21
21
  import { Button } from "../../core/ui/button/index.js";
22
22
  import "./config.js";
@@ -99,8 +99,12 @@ export class imageProperties extends Plugin {
99
99
  dialog.close();
100
100
  });
101
101
  buttons.remove.onAction(() => {
102
+ const caret = j.s.createRange();
103
+ caret.setStartBefore(this.state.sourceImage);
104
+ caret.collapse(true);
102
105
  j.s.removeNode(this.state.sourceImage);
103
106
  dialog.close();
107
+ j.s.selectRange(caret);
104
108
  });
105
109
  buttons.cancel.onAction(() => {
106
110
  dialog.close();
@@ -108,11 +112,20 @@ export class imageProperties extends Plugin {
108
112
  dialog.setHeader(j.i18n('Image properties'));
109
113
  dialog.setContent(this.form);
110
114
  dialog.setFooter([[buttons.cancel, buttons.remove], buttons.check]);
111
- j.e.on(dialog, 'afterClose', () => {
112
- if (this.state.image.parentNode &&
113
- j.o.image.selectImageAfterClose) {
114
- j.s.select(this.state.sourceImage);
115
+ // The dialog fires `afterClose` on its own emitter, not the editor's
116
+ dialog.e.on(dialog, 'afterClose', () => {
117
+ const { sourceImage } = this.state;
118
+ if (j.isInDestruct || !Dom.isOrContains(j.editor, sourceImage)) {
119
+ return;
115
120
  }
121
+ if (j.o.image.selectImageAfterClose) {
122
+ j.s.select(sourceImage);
123
+ return;
124
+ }
125
+ const caret = j.s.createRange();
126
+ caret.setStartAfter(sourceImage);
127
+ caret.collapse(true);
128
+ j.s.selectRange(caret);
116
129
  });
117
130
  dialog.setSize(j.o.image.dialogWidth);
118
131
  markOwner(j, dialog.container);
@@ -144,6 +157,7 @@ export class imageProperties extends Plugin {
144
157
  this.activeTabState.activeTab = 'Image';
145
158
  this.__lock();
146
159
  this.dialog.open().setModal(true).setPosition();
160
+ this.__focusFirstField();
147
161
  this.async
148
162
  .promise((resolve, reject) => readValuesFromImage(this.j, this.state).then(resolve, reject))
149
163
  .catch((e) => {
@@ -154,6 +168,17 @@ export class imageProperties extends Plugin {
154
168
  .finally(() => this.__unlock());
155
169
  return false;
156
170
  }
171
+ /**
172
+ * Keys typed while the dialog is open must not reach the editor behind it,
173
+ * so focus the active tab's first field, or else the first field shown
174
+ */
175
+ __focusFirstField() {
176
+ var _a;
177
+ const fields = (box) => toArray(box.querySelectorAll('input, select, textarea'));
178
+ (_a = fields(this.form.getElm('tabsBox'))
179
+ .concat(fields(this.form.container))
180
+ .find(field => field.offsetParent != null)) === null || _a === void 0 ? void 0 : _a.focus();
181
+ }
157
182
  __lock() {
158
183
  this.dialog.lock();
159
184
  this.form.setMod('lock', true);
@@ -78,9 +78,11 @@ function fitToButtons(list, editor) {
78
78
  return cleaned;
79
79
  }
80
80
  /**
81
- * The width that decides which breakpoint set the toolbar uses. A toolbar
82
- * rendered into an external container (`toolbar` set to an element or a
83
- * selector) lays out in that container, so its width is what matters there.
81
+ * The width that decides which breakpoint set the toolbar uses: the editor's
82
+ * own width, or its parent's while the editor has none yet (for example
83
+ * while hidden at init). A toolbar rendered into an external container
84
+ * (`toolbar` set to an element or a selector) lays out in that container, so
85
+ * its width is what matters there.
84
86
  */
85
87
  function adaptiveWidth(editor) {
86
88
  var _a;
@@ -91,7 +93,8 @@ function adaptiveWidth(editor) {
91
93
  return width;
92
94
  }
93
95
  }
94
- return ((_a = editor.container.parentElement) !== null && _a !== void 0 ? _a : editor.container).offsetWidth;
96
+ return (editor.container.offsetWidth ||
97
+ ((_a = editor.container.parentElement) !== null && _a !== void 0 ? _a : editor.container).offsetWidth);
95
98
  }
96
99
  /**
97
100
  * Rebuild toolbar in depends on editor's width
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jodit",
3
- "version": "4.18.6",
3
+ "version": "4.18.8",
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
@@ -1034,6 +1034,8 @@ interface Config {
1034
1034
  interface Config {
1035
1035
  /**
1036
1036
  * Keyboard hotkey mappings for delete and backspace operations (character, word, sentence).
1037
+ * On macOS the defaults leave out Cmd+Backspace, Ctrl+Backspace, Ctrl+Option+Backspace
1038
+ * and Cmd+Option+Backspace, so the browser applies the system's own bindings to them.
1037
1039
  */
1038
1040
  delete: {
1039
1041
  hotkeys: {
@@ -1049,8 +1051,8 @@ interface Config {
1049
1051
  * key, so the plugin no longer applies that particular behavior.
1050
1052
  * Available keys: `remove-unbreakable`, `remove-not-editable`,
1051
1053
  * `remove-char`, `table-cell`, `remove-empty-parent`,
1052
- * `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
1053
- * `unwrap-first-list-item`.
1054
+ * `remove-empty-neighbor`, `join-two-lists`, `unwrap-list-item`,
1055
+ * `join-neighbors`, `unwrap-first-list-item`.
1054
1056
  *
1055
1057
  * ```javascript
1056
1058
  * Jodit.make('#editor', {
@@ -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;
@@ -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;
@@ -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: {
@@ -22,8 +24,8 @@ declare module 'jodit/config' {
22
24
  * key, so the plugin no longer applies that particular behavior.
23
25
  * Available keys: `remove-unbreakable`, `remove-not-editable`,
24
26
  * `remove-char`, `table-cell`, `remove-empty-parent`,
25
- * `remove-empty-neighbor`, `join-two-lists`, `join-neighbors`,
26
- * `unwrap-first-list-item`.
27
+ * `remove-empty-neighbor`, `join-two-lists`, `unwrap-list-item`,
28
+ * `join-neighbors`, `unwrap-first-list-item`.
27
29
  *
28
30
  * ```javascript
29
31
  * Jodit.make('#editor', {
@@ -52,6 +52,11 @@ export declare class imageProperties extends Plugin {
52
52
  * ```
53
53
  */
54
54
  protected open(): void | false;
55
+ /**
56
+ * Keys typed while the dialog is open must not reach the editor behind it,
57
+ * so focus the active tab's first field, or else the first field shown
58
+ */
59
+ private __focusFirstField;
55
60
  private __lock;
56
61
  private __unlock;
57
62
  /** @override **/