jodit 4.12.21 → 4.12.22

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 (69) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +8 -8
  4. package/es2015/jodit.js +155 -36
  5. package/es2015/jodit.min.js +8 -8
  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 +8 -8
  13. package/es2018/jodit.min.js +24 -24
  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 +9 -9
  18. package/es2021/jodit.js +154 -35
  19. package/es2021/jodit.min.js +22 -22
  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 +9 -9
  28. package/es2021.en/jodit.js +153 -34
  29. package/es2021.en/jodit.min.js +11 -11
  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 +164 -36
  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/core/constants.js +1 -1
  51. package/esm/core/dom/dom.js +6 -4
  52. package/esm/langs/tr.js +1 -1
  53. package/esm/modules/dialog/dialog.d.ts +5 -0
  54. package/esm/modules/dialog/dialog.js +25 -2
  55. package/esm/plugins/clean-html/clean-html.js +8 -2
  56. package/esm/plugins/clean-html/helpers/visitor/filters/allow-attributes.js +9 -2
  57. package/esm/plugins/clipboard/clipboard.js +29 -1
  58. package/esm/plugins/inline-popup/inline-popup.d.ts +8 -0
  59. package/esm/plugins/inline-popup/inline-popup.js +43 -2
  60. package/esm/plugins/limit/limit.js +7 -1
  61. package/esm/plugins/paste/paste.d.ts +1 -1
  62. package/esm/plugins/paste/paste.js +7 -5
  63. package/esm/plugins/resize-handler/resize-handler.js +13 -2
  64. package/esm/plugins/resizer/resizer.js +5 -1
  65. package/esm/plugins/source/source.js +9 -0
  66. package/package.json +1 -1
  67. package/types/modules/dialog/dialog.d.ts +5 -0
  68. package/types/plugins/inline-popup/inline-popup.d.ts +8 -0
  69. package/types/plugins/paste/paste.d.ts +1 -1
@@ -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.12.21
4
+ * Version: v4.12.22
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -1802,7 +1802,7 @@ __webpack_require__.r(__webpack_exports__);
1802
1802
  * ```
1803
1803
  * @packageDocumentation
1804
1804
  * @module constants
1805
- */ const APP_VERSION = "4.12.21";
1805
+ */ const APP_VERSION = "4.12.22";
1806
1806
  // prettier-ignore
1807
1807
  const ES = "es2021";
1808
1808
  const IS_ES_MODERN = true;
@@ -3218,8 +3218,9 @@ function wait(condition) {
3218
3218
  if (!Dom.isNode(node)) {
3219
3219
  return false;
3220
3220
  }
3221
- const win = node.ownerDocument?.defaultView;
3222
- return Boolean(win && node.nodeType === Node.ELEMENT_NODE);
3221
+ // no `defaultView` requirement — nodes of an inert document
3222
+ // (`DOMParser`, `implementation.createHTMLDocument`) are still elements
3223
+ return node.nodeType === Node.ELEMENT_NODE;
3223
3224
  }
3224
3225
  /**
3225
3226
  * Check if element is document fragment
@@ -3236,8 +3237,10 @@ function wait(condition) {
3236
3237
  if (!Dom.isNode(node)) {
3237
3238
  return false;
3238
3239
  }
3240
+ // an inert document has no browsing context (`defaultView` is null),
3241
+ // but its nodes are same-realm HTMLElements
3239
3242
  const win = node.ownerDocument?.defaultView;
3240
- return Boolean(win && node instanceof win.HTMLElement);
3243
+ return node instanceof (win ? win.HTMLElement : HTMLElement);
3241
3244
  }
3242
3245
  /**
3243
3246
  * Check element is inline block
@@ -18410,7 +18413,7 @@ class Dialog extends jodit_core_view_view_with_toolbar__WEBPACK_IMPORTED_MODULE_
18410
18413
  e.stopImmediatePropagation();
18411
18414
  }
18412
18415
  if (this.resizable && this.o.resizable) {
18413
- this.setSize(this.startPoint.w + e.clientX - this.startX, this.startPoint.h + e.clientY - this.startY);
18416
+ this.setSize(Math.max(this.startPoint.w + e.clientX - this.startX, this.minSize.w), Math.max(this.startPoint.h + e.clientY - this.startY, this.minSize.h));
18414
18417
  if (this.e) {
18415
18418
  /**
18416
18419
  * Fired when dialog box is resized
@@ -18438,6 +18441,14 @@ class Dialog extends jodit_core_view_view_with_toolbar__WEBPACK_IMPORTED_MODULE_
18438
18441
  this.startY = e.clientY;
18439
18442
  this.startPoint.w = this.dialog.offsetWidth;
18440
18443
  this.startPoint.h = this.dialog.offsetHeight;
18444
+ const header = this.getElm('header');
18445
+ const footer = this.getElm('footer');
18446
+ const content = this.getElm('content');
18447
+ // the content area does not shrink below its CSS `min-height`,
18448
+ // so it is part of the smallest height the panel can take
18449
+ const contentMinHeight = content ? parseFloat(this.ow.getComputedStyle(content).minHeight) || 0 : 0;
18450
+ this.minSize.w = (0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_8__.isNumber)(this.o.minWidth) ? this.o.minWidth : Math.max(100, footer?.scrollWidth ?? 0);
18451
+ this.minSize.h = (0,jodit_core_helpers_checker__WEBPACK_IMPORTED_MODULE_8__.isNumber)(this.o.minHeight) ? this.o.minHeight : (header?.offsetHeight ?? 0) + (footer?.offsetHeight ?? 0) + contentMinHeight + this.resizer.offsetHeight;
18441
18452
  this.lockSelect();
18442
18453
  this.__addGlobalResizeListeners();
18443
18454
  if (this.e) {
@@ -18732,6 +18743,12 @@ class Dialog extends jodit_core_view_view_with_toolbar__WEBPACK_IMPORTED_MODULE_
18732
18743
  if (this.options && this.o.resizable && !this.moved && this.isOpened && !this.offsetX && !this.offsetY) {
18733
18744
  this.setPosition();
18734
18745
  }
18746
+ }), /**
18747
+ * Minimal size the dialog can be resized to — the header and the footer
18748
+ * (with its buttons) must always stay inside the panel
18749
+ */ (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "minSize", {
18750
+ w: 0,
18751
+ h: 0
18735
18752
  }), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "dialog", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "workplace", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "dialogbox_header", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "dialogbox_content", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "dialogbox_footer", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "dialogbox_toolbar", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "isModal", false), /**
18736
18753
  * True, if dialog was opened
18737
18754
  */ (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "isOpened", false);
@@ -27208,10 +27225,14 @@ jodit_core_ui_icon__WEBPACK_IMPORTED_MODULE_5__.Icon.set('class-span', (_class_s
27208
27225
  * Event handler when manually assigning a value to the HTML editor.
27209
27226
  */ onBeforeSetNativeEditorValue(data) {
27210
27227
  const [sandBox, iframe] = this.j.o.cleanHTML.useIframeSandbox ? this.j.createInside.sandbox() : [
27211
- this.j.createInside.div()
27228
+ // an inert document never loads sub-resources, so the
27229
+ // images in the value are not re-requested from the
27230
+ // server on every assignment (e.g. on each change in
27231
+ // jodit-react). See #1237
27232
+ this.j.od.implementation.createHTMLDocument('').body
27212
27233
  ];
27213
27234
  sandBox.innerHTML = data.value;
27214
- this.onSafeHTML(sandBox);
27235
+ this.j.e.fire('safeHTML', sandBox);
27215
27236
  data.value = sandBox.innerHTML;
27216
27237
  (0,jodit_core_helpers_html_safe_html__WEBPACK_IMPORTED_MODULE_6__.safeHTML)(sandBox, {
27217
27238
  safeJavaScriptLink: true,
@@ -27546,12 +27567,19 @@ jodit_core_ui_icon__WEBPACK_IMPORTED_MODULE_0__.Icon.set('eraser', (_eraser_svg_
27546
27567
  /**
27547
27568
  * @private
27548
27569
  */ function allowAttributes(jodit, nodeElm, hadEffect, allow) {
27549
- if (allow && jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_0__.Dom.isElement(nodeElm) && allow[nodeElm.nodeName] !== true) {
27570
+ const allowedForTag = allow && jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_0__.Dom.isElement(nodeElm) && allow[nodeElm.nodeName];
27571
+ if (allow && jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_0__.Dom.isElement(nodeElm) && allowedForTag !== true) {
27572
+ // the tag is not in the allow list at all — attributes do not matter,
27573
+ // the element itself will be removed by the tags filter. Without this
27574
+ // check `allow[nodeName][attr]` threw on e.g. `<meta charset>`. See #1224
27575
+ if (!allowedForTag) {
27576
+ return hadEffect;
27577
+ }
27550
27578
  const attrs = nodeElm.attributes;
27551
27579
  if (attrs && attrs.length) {
27552
27580
  const removeAttrs = [];
27553
27581
  for(let i = 0; i < attrs.length; i += 1){
27554
- const attr = allow[nodeElm.nodeName][attrs[i].name];
27582
+ const attr = allowedForTag[attrs[i].name];
27555
27583
  if (!attr || attr !== true && attr !== attrs[i].value) {
27556
27584
  removeAttrs.push(attrs[i].name);
27557
27585
  }
@@ -28129,9 +28157,10 @@ const keys = Object.keys(_filters__WEBPACK_IMPORTED_MODULE_1__);
28129
28157
  /* harmony import */ var _swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(25045);
28130
28158
  /* harmony import */ var jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(81937);
28131
28159
  /* harmony import */ var jodit_core_decorators_cache_cache__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(51676);
28132
- /* harmony import */ var jodit_core_global__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(28077);
28133
- /* harmony import */ var jodit_core_helpers__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(65946);
28134
- /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(81008);
28160
+ /* harmony import */ var jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(23211);
28161
+ /* harmony import */ var jodit_core_global__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(28077);
28162
+ /* harmony import */ var jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(65946);
28163
+ /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(81008);
28135
28164
  /*!
28136
28165
  * Jodit Editor (https://xdsoft.net/jodit/)
28137
28166
  * Released under MIT see LICENSE.txt in the project root for license information.
@@ -28146,16 +28175,17 @@ const keys = Object.keys(_filters__WEBPACK_IMPORTED_MODULE_1__);
28146
28175
 
28147
28176
 
28148
28177
 
28178
+
28149
28179
  /**
28150
28180
  * Clipboard plugin - cut and copy functionality
28151
28181
  */ class clipboard {
28152
28182
  init(editor) {
28153
28183
  this.buttons?.forEach((btn)=>editor.registerButton(btn));
28154
28184
  editor.e.off(`copy.${jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.CLIPBOARD_ID} cut.${jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.CLIPBOARD_ID}`).on(`copy.${jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.CLIPBOARD_ID} cut.${jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.CLIPBOARD_ID}`, (event)=>{
28155
- const selectedText = editor.s.html;
28156
- const clipboardData = (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_4__.getDataTransfer)(event) || (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_4__.getDataTransfer)(editor.ew) || (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_4__.getDataTransfer)(event.originalEvent);
28185
+ const selectedText = wrapWithInlineAncestors(editor, editor.s.html);
28186
+ const clipboardData = (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.getDataTransfer)(event) || (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.getDataTransfer)(editor.ew) || (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.getDataTransfer)(event.originalEvent);
28157
28187
  if (clipboardData) {
28158
- clipboardData.setData(jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.TEXT_PLAIN, (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_4__.stripTags)(selectedText));
28188
+ clipboardData.setData(jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.TEXT_PLAIN, (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.stripTags)(selectedText));
28159
28189
  clipboardData.setData(jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.TEXT_HTML, selectedText);
28160
28190
  }
28161
28191
  editor.buffer.set(jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.CLIPBOARD_ID, selectedText);
@@ -28197,7 +28227,30 @@ const keys = Object.keys(_filters__WEBPACK_IMPORTED_MODULE_1__);
28197
28227
  ]);
28198
28228
  }
28199
28229
  }
28200
- jodit_core_global__WEBPACK_IMPORTED_MODULE_3__.pluginSystem.add('clipboard', clipboard);
28230
+ /**
28231
+ * `Selection.html` clones only the range contents — when the selection sits
28232
+ * entirely inside the text of a formatted element (`<strong>te|st|</strong>`),
28233
+ * the clone is bare text and the formatting would be lost on paste. Native
28234
+ * browser copy keeps that context, so the interception must restore it: wrap
28235
+ * the fragment in shallow clones of the inline ancestors of the range. See #1202
28236
+ */ function wrapWithInlineAncestors(editor, html) {
28237
+ if (!html || editor.s.isCollapsed()) {
28238
+ return html;
28239
+ }
28240
+ let node = editor.s.range.commonAncestorContainer;
28241
+ if (!jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_3__.Dom.isElement(node)) {
28242
+ node = node.parentElement;
28243
+ }
28244
+ let result = html;
28245
+ while(node && node !== editor.editor && jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_3__.Dom.isElement(node) && !jodit_core_dom_dom__WEBPACK_IMPORTED_MODULE_3__.Dom.isBlock(node)){
28246
+ const shell = node.cloneNode(false);
28247
+ shell.innerHTML = result;
28248
+ result = shell.outerHTML;
28249
+ node = node.parentElement;
28250
+ }
28251
+ return result;
28252
+ }
28253
+ jodit_core_global__WEBPACK_IMPORTED_MODULE_4__.pluginSystem.add('clipboard', clipboard);
28201
28254
 
28202
28255
 
28203
28256
  /***/ }),
@@ -33724,9 +33777,34 @@ const align = {
33724
33777
  }).on([
33725
33778
  this.j.ew,
33726
33779
  this.j.ow
33727
- ], 'mouseup keyup', this.onSelectionEnd);
33780
+ ], 'mouseup keyup', this.onSelectionEnd).on([
33781
+ this.j.ew,
33782
+ this.j.ow
33783
+ ], 'mousedown touchstart', this.__onDocumentMouseDown).on('closeAllPopups', this.__onCloseAllPopups);
33728
33784
  this.addListenersForElements();
33729
33785
  }
33786
+ __onDocumentMouseDown(e) {
33787
+ if (this.popup.isOpened && this.type === 'selection' && e.target && jodit_core_ui__WEBPACK_IMPORTED_MODULE_7__.UIElement.closestElement(e.target, jodit_core_ui_popup__WEBPACK_IMPORTED_MODULE_8__.Popup)) {
33788
+ this.__reopenSelectionPopup = true;
33789
+ }
33790
+ }
33791
+ __onCloseAllPopups() {
33792
+ if (!this.__reopenSelectionPopup) {
33793
+ return;
33794
+ }
33795
+ this.__reopenSelectionPopup = false;
33796
+ if (!this.j.o.toolbarInlineForSelection) {
33797
+ return;
33798
+ }
33799
+ // a zero timeout would run synchronously — before the popup's own
33800
+ // `closeAllPopups` handler closes it; defer to the next macrotask
33801
+ this.j.async.setTimeout(()=>{
33802
+ const sel = this.j.s.sel;
33803
+ if (sel && !sel.isCollapsed) {
33804
+ this.showPopup(()=>this.j.s.range.getBoundingClientRect(), 'selection');
33805
+ }
33806
+ }, 1);
33807
+ }
33730
33808
  onSelectionStart() {
33731
33809
  this.snapRange = this.j.s.range.cloneRange();
33732
33810
  }
@@ -33775,7 +33853,10 @@ const align = {
33775
33853
  jodit.e.off('showPopup').off([
33776
33854
  this.j.ew,
33777
33855
  this.j.ow
33778
- ], 'mouseup keyup', this.onSelectionEnd);
33856
+ ], 'mouseup keyup', this.onSelectionEnd).off([
33857
+ this.j.ew,
33858
+ this.j.ow
33859
+ ], 'mousedown touchstart', this.__onDocumentMouseDown).off('closeAllPopups', this.__onCloseAllPopups);
33779
33860
  this.removeListenersForElements();
33780
33861
  }
33781
33862
  _eventsList() {
@@ -33800,7 +33881,11 @@ const align = {
33800
33881
  }, 'toolbar');
33801
33882
  }
33802
33883
  constructor(...args){
33803
- super(...args), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "type", null), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "previousTarget", void 0), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "snapRange", null), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "elmsList", (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.keys)(this.j.o.popup, false).filter((s)=>!this.isExcludedTarget(s)));
33884
+ super(...args), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "type", null), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "previousTarget", void 0), /**
33885
+ * The user pressed a button inside the selection toolbar — after the
33886
+ * command fires `closeAllPopups`, the toolbar should be shown again
33887
+ * while the selection is still there. See #1238
33888
+ */ (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "__reopenSelectionPopup", false), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "snapRange", null), (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "elmsList", (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.keys)(this.j.o.popup, false).filter((s)=>!this.isExcludedTarget(s)));
33804
33889
  }
33805
33890
  }
33806
33891
  (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(inlinePopup, "requires", [
@@ -33829,6 +33914,12 @@ const align = {
33829
33914
  (0,_swc_helpers_ts_decorate__WEBPACK_IMPORTED_MODULE_1__.__decorate)([
33830
33915
  (0,jodit_core_decorators__WEBPACK_IMPORTED_MODULE_2__.watch)(':outsideClick')
33831
33916
  ], inlinePopup.prototype, "onOutsideClick", null);
33917
+ (0,_swc_helpers_ts_decorate__WEBPACK_IMPORTED_MODULE_1__.__decorate)([
33918
+ jodit_core_decorators__WEBPACK_IMPORTED_MODULE_2__.autobind
33919
+ ], inlinePopup.prototype, "__onDocumentMouseDown", null);
33920
+ (0,_swc_helpers_ts_decorate__WEBPACK_IMPORTED_MODULE_1__.__decorate)([
33921
+ jodit_core_decorators__WEBPACK_IMPORTED_MODULE_2__.autobind
33922
+ ], inlinePopup.prototype, "__onCloseAllPopups", null);
33832
33923
  (0,_swc_helpers_ts_decorate__WEBPACK_IMPORTED_MODULE_1__.__decorate)([
33833
33924
  jodit_core_decorators__WEBPACK_IMPORTED_MODULE_2__.autobind
33834
33925
  ], inlinePopup.prototype, "onSelectionStart", null);
@@ -34114,7 +34205,10 @@ jodit_config__WEBPACK_IMPORTED_MODULE_0__.Config.prototype.limitHTML = false;
34114
34205
  jodit.e.fire('denyWords.limit limit.limit');
34115
34206
  return true;
34116
34207
  }
34117
- const should = Boolean(limitChars && isGt(words.join('').length, limitChars, strict));
34208
+ // with `countTextSpaces` enabled the limiter counts characters the
34209
+ // same way as the `stat` plugin's counter — including spaces. See #1144
34210
+ const charsCount = jodit.o.countTextSpaces ? text.replace((0,jodit_core_constants__WEBPACK_IMPORTED_MODULE_1__.INVISIBLE_SPACE_REG_EXP)(), '').replace(/[\r\n]/g, '').length : words.join('').length;
34211
+ const should = Boolean(limitChars && isGt(charsCount, limitChars, strict));
34118
34212
  if (should) {
34119
34213
  jodit.e.fire('denyChars.limit limit.limit');
34120
34214
  }
@@ -35884,9 +35978,7 @@ jodit_config__WEBPACK_IMPORTED_MODULE_1__.Config.prototype.controls.paste = {
35884
35978
  */ class paste extends jodit_core_plugin_plugin__WEBPACK_IMPORTED_MODULE_7__.Plugin {
35885
35979
  /** @override **/ afterInit(jodit) {
35886
35980
  jodit.e.on('paste.paste', this.onPaste).on('pasteStack.paste', (item)=>this.pasteStack.push(item));
35887
- if (jodit.o.nl2brInPlainText) {
35888
- this.j.e.on('processPaste.paste', this.onProcessPasteReplaceNl2Br);
35889
- }
35981
+ this.j.e.on('processPaste.paste', this.onProcessPasteReplaceNl2Br);
35890
35982
  }
35891
35983
  /** @override **/ beforeDestruct(jodit) {
35892
35984
  jodit.e.off('paste.paste', this.onPaste).off('processPaste.paste', this.onProcessPasteReplaceNl2Br).off('.paste');
@@ -36006,10 +36098,14 @@ jodit_config__WEBPACK_IMPORTED_MODULE_1__.Config.prototype.controls.paste = {
36006
36098
  (0,_helpers__WEBPACK_IMPORTED_MODULE_9__.pasteInsertHtml)(e, this.j, html);
36007
36099
  }
36008
36100
  /**
36009
- * Replace all \\n chars in plain text to br
36101
+ * Escape plain text and replace all \\n chars with br
36010
36102
  */ onProcessPasteReplaceNl2Br(ignore, text, type) {
36011
36103
  if (type === jodit_core_constants__WEBPACK_IMPORTED_MODULE_2__.TEXT_PLAIN + ';' && !(0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_6__.isHTML)(text)) {
36012
- return (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_6__.nl2br)(text);
36104
+ // the clipboard contains only plain text — escape special chars
36105
+ // so a stray `<` is not parsed as an unclosed tag and does not
36106
+ // swallow the rest of the string. See #1227
36107
+ const escaped = (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_6__.htmlspecialchars)(text);
36108
+ return this.j.o.nl2brInPlainText ? (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_6__.nl2br)(escaped) : escaped;
36013
36109
  }
36014
36110
  }
36015
36111
  constructor(...args){
@@ -36877,9 +36973,10 @@ jodit_config__WEBPACK_IMPORTED_MODULE_0__.Config.prototype.allowResizeY = true;
36877
36973
  /* harmony import */ var jodit_core_decorators__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(84839);
36878
36974
  /* harmony import */ var jodit_core_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(27795);
36879
36975
  /* harmony import */ var jodit_core_global__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(28077);
36880
- /* harmony import */ var jodit_core_plugin__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(91206);
36881
- /* harmony import */ var jodit_core_ui__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4099);
36882
- /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(58293);
36976
+ /* harmony import */ var jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(65946);
36977
+ /* harmony import */ var jodit_core_plugin__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(91206);
36978
+ /* harmony import */ var jodit_core_ui__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(4099);
36979
+ /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(58293);
36883
36980
  /*!
36884
36981
  * Jodit Editor (https://xdsoft.net/jodit/)
36885
36982
  * Released under MIT see LICENSE.txt in the project root for license information.
@@ -36896,7 +36993,8 @@ jodit_config__WEBPACK_IMPORTED_MODULE_0__.Config.prototype.allowResizeY = true;
36896
36993
 
36897
36994
 
36898
36995
 
36899
- class resizeHandler extends jodit_core_plugin__WEBPACK_IMPORTED_MODULE_5__.Plugin {
36996
+
36997
+ class resizeHandler extends jodit_core_plugin__WEBPACK_IMPORTED_MODULE_6__.Plugin {
36900
36998
  /** @override **/ afterInit(editor) {
36901
36999
  const { height, width, allowResizeX } = editor.o;
36902
37000
  let { allowResizeY } = editor.o;
@@ -36930,11 +37028,21 @@ class resizeHandler extends jodit_core_plugin__WEBPACK_IMPORTED_MODULE_5__.Plugi
36930
37028
  if (!this.isResized) {
36931
37029
  return;
36932
37030
  }
37031
+ let { clientX, clientY } = e;
37032
+ if (e.view === this.j.ew && this.j.ew !== this.j.ow) {
37033
+ // the event was proxied from the editor's iframe — its client
37034
+ // coordinates are relative to the iframe viewport, while the
37035
+ // start point was captured on the host-document handle;
37036
+ // shift them into the host coordinate space
37037
+ const workplacePosition = (0,jodit_core_helpers__WEBPACK_IMPORTED_MODULE_5__.offset)(this.j.workplace, this.j, this.j.od, true);
37038
+ clientX += workplacePosition.left;
37039
+ clientY += workplacePosition.top;
37040
+ }
36933
37041
  if (this.j.o.allowResizeY) {
36934
- this.j.e.fire('setHeight', this.start.h + e.clientY - this.start.y);
37042
+ this.j.e.fire('setHeight', this.start.h + clientY - this.start.y);
36935
37043
  }
36936
37044
  if (this.j.o.allowResizeX) {
36937
- this.j.e.fire('setWidth', this.start.w + e.clientX - this.start.x);
37045
+ this.j.e.fire('setWidth', this.start.w + clientX - this.start.x);
36938
37046
  }
36939
37047
  this.j.e.fire('resize');
36940
37048
  }
@@ -36963,7 +37071,7 @@ class resizeHandler extends jodit_core_plugin__WEBPACK_IMPORTED_MODULE_5__.Plugi
36963
37071
  h: 0
36964
37072
  }), /**
36965
37073
  * Resize handle
36966
- */ (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "handle", this.j.c.div('jodit-editor__resize', jodit_core_ui__WEBPACK_IMPORTED_MODULE_6__.Icon.get('resize_handler')));
37074
+ */ (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(this, "handle", this.j.c.div('jodit-editor__resize', jodit_core_ui__WEBPACK_IMPORTED_MODULE_7__.Icon.get('resize_handler')));
36967
37075
  }
36968
37076
  }
36969
37077
  /** @override **/ (0,_swc_helpers_define_property__WEBPACK_IMPORTED_MODULE_0__._)(resizeHandler, "requires", [
@@ -37148,7 +37256,11 @@ const keyBInd = '__jodit-resizer_binded';
37148
37256
  this.pointerX = e.clientX;
37149
37257
  this.pointerY = e.clientY;
37150
37258
  let diff_x, diff_y;
37151
- if (this.j.options.iframe) {
37259
+ if (this.j.options.iframe && e.view === this.j.ew) {
37260
+ // the event was proxied from the editor's iframe — its client
37261
+ // coordinates are relative to the iframe viewport, while
37262
+ // `startX/startY` were captured on a host-document handle;
37263
+ // shift them into the host coordinate space
37152
37264
  const workplacePosition = this.getWorkplacePosition();
37153
37265
  diff_x = e.clientX + workplacePosition.left - this.startX;
37154
37266
  diff_y = e.clientY + workplacePosition.top - this.startY;
@@ -39764,6 +39876,13 @@ class SourceEditor {
39764
39876
  this.sourceEditor?.setValue(value);
39765
39877
  }
39766
39878
  setFocusToMirror() {
39879
+ const active = this.j.od.activeElement;
39880
+ // do not steal focus from another editor or control — e.g. when the
39881
+ // mode is switched programmatically (a Vue/React wrapper re-render)
39882
+ // while the user is already typing elsewhere. See #1356
39883
+ if (active && active !== this.j.od.body && !this.j.container.contains(active)) {
39884
+ return;
39885
+ }
39767
39886
  this.sourceEditor?.focus();
39768
39887
  }
39769
39888
  saveSelection() {