jodit 4.15.5 → 4.15.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +4 -4
  4. package/es2015/jodit.js +73 -8
  5. package/es2015/jodit.min.js +4 -4
  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 +4 -4
  13. package/es2018/jodit.min.js +4 -4
  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 +4 -4
  18. package/es2021/jodit.js +72 -8
  19. package/es2021/jodit.min.js +4 -4
  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 +4 -4
  28. package/es2021.en/jodit.js +72 -8
  29. package/es2021.en/jodit.min.js +4 -4
  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 +114 -42
  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 +10 -0
  51. package/esm/core/constants.js +1 -1
  52. package/esm/plugins/clean-html/clean-html.d.ts +7 -3
  53. package/esm/plugins/clean-html/clean-html.js +37 -0
  54. package/esm/plugins/clean-html/config.d.ts +10 -0
  55. package/esm/plugins/clean-html/config.js +1 -0
  56. package/esm/plugins/drag-and-drop-element/drag-and-drop-element.d.ts +1 -0
  57. package/esm/plugins/drag-and-drop-element/drag-and-drop-element.js +19 -4
  58. package/esm/plugins/link/link.js +9 -0
  59. package/package.json +1 -1
  60. package/types/config.d.ts +10 -0
  61. package/types/plugins/clean-html/clean-html.d.ts +7 -3
  62. package/types/plugins/clean-html/config.d.ts +10 -0
  63. package/types/plugins/drag-and-drop-element/drag-and-drop-element.d.ts +1 -0
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
package/es5/polyfills.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.15.5
4
+ * Version: v4.15.7
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
package/esm/config.d.ts CHANGED
@@ -1042,6 +1042,16 @@ interface Config {
1042
1042
  * names with single quotes: `font-family: 'Open Sans', sans-serif`.
1043
1043
  */
1044
1044
  singleQuotesInFontFamily: boolean;
1045
+ /**
1046
+ * Browsers keep a trailing `<br>` inside a block after you type into an
1047
+ * empty one (`<p>test<br></p>`), and the same `<br>` ends up in the
1048
+ * editor value. It renders nothing, but confuses consumers that compare
1049
+ * or post-process the HTML. With this option the value getter drops a
1050
+ * `<br>` that is the last node of a block (or of the whole value)
1051
+ * and follows other content. `<p><br></p>` and `text<br><br>` — an empty
1052
+ * line — are kept.
1053
+ */
1054
+ removeTrailingBr: boolean;
1045
1055
  /**
1046
1056
  * Replace old tags to new eg. <i> to <em>, <b> to <strong>
1047
1057
  */
@@ -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
- export const APP_VERSION = "4.15.5";
6
+ export const APP_VERSION = "4.15.7";
7
7
  // prettier-ignore
8
8
  export const ES = "es2020";
9
9
  export const IS_ES_MODERN = true;
@@ -11,9 +11,6 @@
11
11
  import type { IJodit } from "../../types/index";
12
12
  import { Plugin } from "../../core/plugin/plugin";
13
13
  import "./config";
14
- /**
15
- * Clean HTML after removeFormat and insertHorizontalRule command
16
- */
17
14
  export declare class cleanHtml extends Plugin {
18
15
  /** @override */
19
16
  buttons: Plugin['buttons'];
@@ -50,6 +47,13 @@ export declare class cleanHtml extends Plugin {
50
47
  * survive that round trip. Names that already contain an apostrophe are
51
48
  * left alone.
52
49
  */
50
+ /**
51
+ * Drop a `<br>` that is the last node of a block (or of the value) and
52
+ * follows other content — the caret placeholder browsers leave behind
53
+ * after typing into an empty block. An empty block (`<p><br></p>`) and a
54
+ * deliberate empty line (`text<br><br>`) are kept.
55
+ */
56
+ private __removeTrailingBr;
53
57
  private __singleQuotesInFontFamily;
54
58
  protected onSafeHTML(sandBox: HTMLElement): void;
55
59
  /** @override */
@@ -24,6 +24,7 @@ import { getHash, removeFormatForCollapsedSelection, removeFormatForSelection, v
24
24
  /**
25
25
  * Clean HTML after removeFormat and insertHorizontalRule command
26
26
  */
27
+ const TRAILING_BR_BLOCKS = 'p, div, li, td, th, h1, h2, h3, h4, h5, h6, blockquote';
27
28
  export class cleanHtml extends Plugin {
28
29
  constructor() {
29
30
  super(...arguments);
@@ -107,6 +108,7 @@ export class cleanHtml extends Plugin {
107
108
  */
108
109
  onAfterGetValueFromEditor(data) {
109
110
  this.__singleQuotesInFontFamily(data);
111
+ this.__removeTrailingBr(data);
110
112
  if (!this.j.o.cleanHTML.collapseEmptyValueToEmptyString) {
111
113
  return;
112
114
  }
@@ -122,6 +124,41 @@ export class cleanHtml extends Plugin {
122
124
  * survive that round trip. Names that already contain an apostrophe are
123
125
  * left alone.
124
126
  */
127
+ /**
128
+ * Drop a `<br>` that is the last node of a block (or of the value) and
129
+ * follows other content — the caret placeholder browsers leave behind
130
+ * after typing into an empty block. An empty block (`<p><br></p>`) and a
131
+ * deliberate empty line (`text<br><br>`) are kept.
132
+ */
133
+ __removeTrailingBr(data) {
134
+ if (!this.j.o.cleanHTML.removeTrailingBr || !/<br/i.test(data.value)) {
135
+ return;
136
+ }
137
+ const box = this.j.c.div();
138
+ box.innerHTML = data.value;
139
+ const blocks = [
140
+ box,
141
+ ...box.querySelectorAll(TRAILING_BR_BLOCKS)
142
+ ];
143
+ blocks.forEach(block => {
144
+ var _a;
145
+ const last = block.lastChild;
146
+ if (!Dom.isTag(last, 'br')) {
147
+ return;
148
+ }
149
+ const prev = last.previousSibling;
150
+ if (!prev || Dom.isTag(prev, 'br')) {
151
+ return;
152
+ }
153
+ if (Dom.isText(prev) &&
154
+ !((_a = prev.nodeValue) === null || _a === void 0 ? void 0 : _a.trim()) &&
155
+ !prev.previousSibling) {
156
+ return;
157
+ }
158
+ Dom.safeRemove(last);
159
+ });
160
+ data.value = box.innerHTML;
161
+ }
125
162
  __singleQuotesInFontFamily(data) {
126
163
  if (!this.j.o.cleanHTML.singleQuotesInFontFamily ||
127
164
  !data.value.includes('&quot;')) {
@@ -41,6 +41,16 @@ declare module 'jodit/config' {
41
41
  * names with single quotes: `font-family: 'Open Sans', sans-serif`.
42
42
  */
43
43
  singleQuotesInFontFamily: boolean;
44
+ /**
45
+ * Browsers keep a trailing `<br>` inside a block after you type into an
46
+ * empty one (`<p>test<br></p>`), and the same `<br>` ends up in the
47
+ * editor value. It renders nothing, but confuses consumers that compare
48
+ * or post-process the HTML. With this option the value getter drops a
49
+ * `<br>` that is the last node of a block (or of the whole value)
50
+ * and follows other content. `<p><br></p>` and `text<br><br>` — an empty
51
+ * line — are kept.
52
+ */
53
+ removeTrailingBr: boolean;
44
54
  /**
45
55
  * Replace old tags to new eg. <i> to <em>, <b> to <strong>
46
56
  */
@@ -12,6 +12,7 @@ Config.prototype.cleanHTML = {
12
12
  fillEmptyParagraph: true,
13
13
  collapseEmptyValueToEmptyString: false,
14
14
  singleQuotesInFontFamily: true,
15
+ removeTrailingBr: false,
15
16
  replaceNBSP: true,
16
17
  replaceOldTags: {
17
18
  i: 'em',
@@ -50,6 +50,7 @@ export declare class dragAndDropElement extends Plugin {
50
50
  * Mouse move handler handler
51
51
  */
52
52
  private onDrag;
53
+ private __ghostOffset;
53
54
  /**
54
55
  * Mouseup handler in any place
55
56
  */
@@ -136,6 +136,11 @@ export class dragAndDropElement extends Plugin {
136
136
  this.state = DragState.DRAGGING;
137
137
  }
138
138
  this.j.e.fire('hidePopup hideResizer');
139
+ // The ghost lives in the top document (position: fixed), but the
140
+ // mousemove comes from the editor document. In iframe mode those are
141
+ // different viewports, so the iframe's own offset has to be added or
142
+ // the ghost trails the pointer by exactly that distance (#1455).
143
+ const offset = this.__ghostOffset();
139
144
  if (!this.draggable.parentNode) {
140
145
  const target = dataBind(this.draggable, 'target');
141
146
  css(this.draggable, {
@@ -145,19 +150,29 @@ export class dragAndDropElement extends Plugin {
145
150
  position: 'fixed',
146
151
  opacity: 0.7,
147
152
  display: 'inline-block',
148
- left: event.clientX,
149
- top: event.clientY,
153
+ left: event.clientX + offset.left,
154
+ top: event.clientY + offset.top,
150
155
  width: (_a = target === null || target === void 0 ? void 0 : target.offsetWidth) !== null && _a !== void 0 ? _a : 100,
151
156
  height: (_b = target === null || target === void 0 ? void 0 : target.offsetHeight) !== null && _b !== void 0 ? _b : 100
152
157
  });
153
158
  Dom.append(getContainer(this.j, dragAndDropElement), this.draggable);
154
159
  }
155
160
  css(this.draggable, {
156
- left: event.clientX,
157
- top: event.clientY
161
+ left: event.clientX + offset.left,
162
+ top: event.clientY + offset.top
158
163
  });
164
+ // The caret goes into the editor document, so it keeps the raw
165
+ // (iframe-relative) coordinates.
159
166
  this.j.s.insertCursorAtPoint(event.clientX, event.clientY);
160
167
  }
168
+ __ghostOffset() {
169
+ const iframe = this.j.iframe;
170
+ if (!iframe) {
171
+ return { left: 0, top: 0 };
172
+ }
173
+ const rect = iframe.getBoundingClientRect();
174
+ return { left: rect.left, top: rect.top };
175
+ }
161
176
  /**
162
177
  * Mouseup handler in any place
163
178
  */
@@ -204,6 +204,7 @@ export class link extends Plugin {
204
204
  jodit.history.snapshot.restore(snapshot);
205
205
  const textWasChanged = getSelectionText() !== content_input.value.trim();
206
206
  const ci = jodit.createInside;
207
+ let caretAfter = null;
207
208
  if (!link || !Dom.isOrContains(jodit.editor, link)) {
208
209
  if (!jodit.s.isCollapsed()) {
209
210
  const node = jodit.s.current();
@@ -218,6 +219,7 @@ export class link extends Plugin {
218
219
  const a = ci.element('a');
219
220
  jodit.s.insertNode(a, false, false);
220
221
  links = [a];
222
+ caretAfter = a;
221
223
  }
222
224
  links.forEach(link => jodit.s.select(link));
223
225
  }
@@ -252,6 +254,13 @@ export class link extends Plugin {
252
254
  }
253
255
  jodit.e.fire('applyLink', jodit, a, form);
254
256
  });
257
+ // A brand-new link inserted at a collapsed caret used to stay
258
+ // *selected*. Safari does not paint that selection, so the next
259
+ // Enter silently replaced the link instead of starting a new line.
260
+ // Put the caret right after the link instead.
261
+ if (caretAfter) {
262
+ jodit.s.setCursorAfter(caretAfter);
263
+ }
255
264
  jodit.synchronizeValues();
256
265
  close();
257
266
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jodit",
3
- "version": "4.15.5",
3
+ "version": "4.15.7",
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
@@ -1042,6 +1042,16 @@ interface Config {
1042
1042
  * names with single quotes: `font-family: 'Open Sans', sans-serif`.
1043
1043
  */
1044
1044
  singleQuotesInFontFamily: boolean;
1045
+ /**
1046
+ * Browsers keep a trailing `<br>` inside a block after you type into an
1047
+ * empty one (`<p>test<br></p>`), and the same `<br>` ends up in the
1048
+ * editor value. It renders nothing, but confuses consumers that compare
1049
+ * or post-process the HTML. With this option the value getter drops a
1050
+ * `<br>` that is the last node of a block (or of the whole value)
1051
+ * and follows other content. `<p><br></p>` and `text<br><br>` — an empty
1052
+ * line — are kept.
1053
+ */
1054
+ removeTrailingBr: boolean;
1045
1055
  /**
1046
1056
  * Replace old tags to new eg. <i> to <em>, <b> to <strong>
1047
1057
  */
@@ -11,9 +11,6 @@
11
11
  import type { IJodit } from "../../types/index";
12
12
  import { Plugin } from "../../core/plugin/plugin";
13
13
  import "./config";
14
- /**
15
- * Clean HTML after removeFormat and insertHorizontalRule command
16
- */
17
14
  export declare class cleanHtml extends Plugin {
18
15
  /** @override */
19
16
  buttons: Plugin['buttons'];
@@ -50,6 +47,13 @@ export declare class cleanHtml extends Plugin {
50
47
  * survive that round trip. Names that already contain an apostrophe are
51
48
  * left alone.
52
49
  */
50
+ /**
51
+ * Drop a `<br>` that is the last node of a block (or of the value) and
52
+ * follows other content — the caret placeholder browsers leave behind
53
+ * after typing into an empty block. An empty block (`<p><br></p>`) and a
54
+ * deliberate empty line (`text<br><br>`) are kept.
55
+ */
56
+ private __removeTrailingBr;
53
57
  private __singleQuotesInFontFamily;
54
58
  protected onSafeHTML(sandBox: HTMLElement): void;
55
59
  /** @override */
@@ -41,6 +41,16 @@ declare module 'jodit/config' {
41
41
  * names with single quotes: `font-family: 'Open Sans', sans-serif`.
42
42
  */
43
43
  singleQuotesInFontFamily: boolean;
44
+ /**
45
+ * Browsers keep a trailing `<br>` inside a block after you type into an
46
+ * empty one (`<p>test<br></p>`), and the same `<br>` ends up in the
47
+ * editor value. It renders nothing, but confuses consumers that compare
48
+ * or post-process the HTML. With this option the value getter drops a
49
+ * `<br>` that is the last node of a block (or of the whole value)
50
+ * and follows other content. `<p><br></p>` and `text<br><br>` — an empty
51
+ * line — are kept.
52
+ */
53
+ removeTrailingBr: boolean;
44
54
  /**
45
55
  * Replace old tags to new eg. <i> to <em>, <b> to <strong>
46
56
  */
@@ -50,6 +50,7 @@ export declare class dragAndDropElement extends Plugin {
50
50
  * Mouse move handler handler
51
51
  */
52
52
  private onDrag;
53
+ private __ghostOffset;
53
54
  /**
54
55
  * Mouseup handler in any place
55
56
  */