jodit 4.12.21 → 4.12.23

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 (86) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/es2015/jodit.css +1 -1
  3. package/es2015/jodit.fat.min.js +11 -11
  4. package/es2015/jodit.js +362 -101
  5. package/es2015/jodit.min.js +11 -11
  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 +11 -11
  13. package/es2018/jodit.min.js +25 -25
  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 +13 -13
  18. package/es2021/jodit.js +352 -99
  19. package/es2021/jodit.min.js +23 -23
  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 +14 -14
  28. package/es2021.en/jodit.js +330 -77
  29. package/es2021.en/jodit.min.js +14 -14
  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 +415 -136
  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/component/view-component.js +8 -0
  51. package/esm/core/constants.js +1 -1
  52. package/esm/core/dom/dom.js +6 -4
  53. package/esm/core/helpers/checker/is-html-from-word.d.ts +1 -1
  54. package/esm/core/helpers/checker/is-html-from-word.js +12 -1
  55. package/esm/core/selection/style/api/wrap.js +18 -3
  56. package/esm/core/ui/popup/popup.js +4 -1
  57. package/esm/jodit.js +12 -0
  58. package/esm/langs/tr.js +1 -1
  59. package/esm/modules/dialog/dialog.d.ts +5 -0
  60. package/esm/modules/dialog/dialog.js +25 -2
  61. package/esm/modules/toolbar/button/content.d.ts +6 -0
  62. package/esm/modules/toolbar/button/content.js +26 -1
  63. package/esm/plugins/add-new-line/add-new-line.js +4 -1
  64. package/esm/plugins/ai-assistant/ai-assistant.js +7 -1
  65. package/esm/plugins/backspace/cases/check-join-neighbors.js +15 -1
  66. package/esm/plugins/clean-html/clean-html.js +8 -2
  67. package/esm/plugins/clean-html/helpers/visitor/filters/allow-attributes.js +9 -2
  68. package/esm/plugins/clipboard/clipboard.js +29 -1
  69. package/esm/plugins/color/color.js +21 -21
  70. package/esm/plugins/inline-popup/inline-popup.d.ts +15 -0
  71. package/esm/plugins/inline-popup/inline-popup.js +60 -3
  72. package/esm/plugins/limit/limit.js +7 -1
  73. package/esm/plugins/paste/config.js +11 -2
  74. package/esm/plugins/paste/paste.d.ts +1 -1
  75. package/esm/plugins/paste/paste.js +7 -5
  76. package/esm/plugins/resize-handler/resize-handler.js +13 -2
  77. package/esm/plugins/resizer/resizer.js +5 -1
  78. package/esm/plugins/search/ui/search.js +22 -12
  79. package/esm/plugins/select-cells/select-cells.js +10 -6
  80. package/esm/plugins/source/source.js +9 -0
  81. package/package.json +1 -1
  82. package/types/core/helpers/checker/is-html-from-word.d.ts +1 -1
  83. package/types/modules/dialog/dialog.d.ts +5 -0
  84. package/types/modules/toolbar/button/content.d.ts +6 -0
  85. package/types/plugins/inline-popup/inline-popup.d.ts +15 -0
  86. package/types/plugins/paste/paste.d.ts +1 -1
@@ -29,6 +29,12 @@ export class inlinePopup extends Plugin {
29
29
  constructor() {
30
30
  super(...arguments);
31
31
  this.type = null;
32
+ /**
33
+ * The user pressed a button inside the selection toolbar — after the
34
+ * command fires `closeAllPopups`, the toolbar should be shown again
35
+ * while the selection is still there. See #1238
36
+ */
37
+ this.__reopenSelectionPopup = false;
32
38
  this.snapRange = null;
33
39
  this.elmsList = keys(this.j.o.popup, false).filter(s => !this.isExcludedTarget(s));
34
40
  }
@@ -144,9 +150,52 @@ export class inlinePopup extends Plugin {
144
150
  this.previousTarget = undefined;
145
151
  }
146
152
  })
147
- .on([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd);
153
+ .on([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd)
154
+ .on([this.j.ew, this.j.ow], 'mousedown touchstart', this.__onDocumentMouseDown)
155
+ .on('closeAllPopups', this.__onCloseAllPopups);
148
156
  this.addListenersForElements();
149
157
  }
158
+ __onDocumentMouseDown(e) {
159
+ if (this.popup.isOpened &&
160
+ this.type === 'selection' &&
161
+ e.target &&
162
+ UIElement.closestElement(e.target, Popup)) {
163
+ this.__reopenSelectionPopup = true;
164
+ }
165
+ }
166
+ __onCloseAllPopups() {
167
+ if (!this.__reopenSelectionPopup) {
168
+ return;
169
+ }
170
+ this.__reopenSelectionPopup = false;
171
+ if (!this.j.o.toolbarInlineForSelection) {
172
+ return;
173
+ }
174
+ // a zero timeout would run synchronously — before the popup's own
175
+ // `closeAllPopups` handler closes it; defer to the next macrotask
176
+ this.j.async.setTimeout(() => {
177
+ const sel = this.j.s.sel;
178
+ if (sel && !sel.isCollapsed) {
179
+ this.showPopup(() => this.__selectionBound(), 'selection');
180
+ }
181
+ }, 1);
182
+ }
183
+ /**
184
+ * The selection rect comes from the editor document — in iframe mode its
185
+ * coordinates are iframe-local, while the popup lives in the host
186
+ * document, so the iframe offset must be added. See
187
+ * https://github.com/xdan/jodit/issues/1058
188
+ */
189
+ __selectionBound() {
190
+ const rect = this.j.s.range.getBoundingClientRect();
191
+ let { left, top } = rect;
192
+ if (this.j.iframe) {
193
+ const offset = position(this.j.iframe, this.j, true);
194
+ left += offset.left;
195
+ top += offset.top;
196
+ }
197
+ return { left, top, width: rect.width, height: rect.height };
198
+ }
150
199
  onSelectionStart() {
151
200
  this.snapRange = this.j.s.range.cloneRange();
152
201
  }
@@ -186,7 +235,7 @@ export class inlinePopup extends Plugin {
186
235
  if (!node) {
187
236
  return;
188
237
  }
189
- this.showPopup(() => range.getBoundingClientRect(), type);
238
+ this.showPopup(() => this.__selectionBound(), type);
190
239
  }
191
240
  /**
192
241
  * In not collapsed selection - only one image
@@ -208,7 +257,9 @@ export class inlinePopup extends Plugin {
208
257
  beforeDestruct(jodit) {
209
258
  jodit.e
210
259
  .off('showPopup')
211
- .off([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd);
260
+ .off([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd)
261
+ .off([this.j.ew, this.j.ow], 'mousedown touchstart', this.__onDocumentMouseDown)
262
+ .off('closeAllPopups', this.__onCloseAllPopups);
212
263
  this.removeListenersForElements();
213
264
  }
214
265
  _eventsList() {
@@ -257,6 +308,12 @@ __decorate([
257
308
  __decorate([
258
309
  watch(':outsideClick')
259
310
  ], inlinePopup.prototype, "onOutsideClick", null);
311
+ __decorate([
312
+ autobind
313
+ ], inlinePopup.prototype, "__onDocumentMouseDown", null);
314
+ __decorate([
315
+ autobind
316
+ ], inlinePopup.prototype, "__onCloseAllPopups", null);
260
317
  __decorate([
261
318
  autobind
262
319
  ], inlinePopup.prototype, "onSelectionStart", null);
@@ -62,7 +62,13 @@ export class limit extends Plugin {
62
62
  jodit.e.fire('denyWords.limit limit.limit');
63
63
  return true;
64
64
  }
65
- const should = Boolean(limitChars && isGt(words.join('').length, limitChars, strict));
65
+ // with `countTextSpaces` enabled the limiter counts characters the
66
+ // same way as the `stat` plugin's counter — including spaces. See #1144
67
+ const charsCount = jodit.o.countTextSpaces
68
+ ? text.replace(INVISIBLE_SPACE_REG_EXP(), '').replace(/[\r\n]/g, '')
69
+ .length
70
+ : words.join('').length;
71
+ const should = Boolean(limitChars && isGt(charsCount, limitChars, strict));
66
72
  if (should) {
67
73
  jodit.e.fire('denyChars.limit limit.limit');
68
74
  }
@@ -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
- import { CLIPBOARD_ID, INSERT_AS_HTML, INSERT_AS_TEXT, INSERT_ONLY_TEXT, IS_PROD, TEXT_PLAIN } from "../../core/constants.js";
6
+ import { CLIPBOARD_ID, INSERT_AS_HTML, INSERT_AS_TEXT, INSERT_ONLY_TEXT, IS_PROD, TEXT_HTML, TEXT_PLAIN } from "../../core/constants.js";
7
7
  import { Config } from "../../config.js";
8
8
  import { pasteInsertHtml } from "./helpers.js";
9
9
  Config.prototype.askBeforePasteHTML = true;
@@ -21,6 +21,7 @@ const psKey = 'pasteStorage';
21
21
  Config.prototype.controls.paste = {
22
22
  tooltip: 'Paste from clipboard',
23
23
  async exec(editor, _, { control }) {
24
+ var _a;
24
25
  if (control.name === psKey) {
25
26
  editor.execCommand('showPasteStorage');
26
27
  return;
@@ -31,7 +32,15 @@ Config.prototype.controls.paste = {
31
32
  try {
32
33
  const items = await navigator.clipboard.read();
33
34
  if (items && items.length) {
34
- const textBlob = await items[0].getType(TEXT_PLAIN);
35
+ const item = items[0];
36
+ // Prefer the HTML flavor so the button behaves like the
37
+ // Ctrl+V shortcut (which receives text/html from the
38
+ // native paste event). See
39
+ // https://github.com/xdan/jodit/issues/1061
40
+ const type = ((_a = item.types) === null || _a === void 0 ? void 0 : _a.includes(TEXT_HTML))
41
+ ? TEXT_HTML
42
+ : TEXT_PLAIN;
43
+ const textBlob = await item.getType(type);
35
44
  text = await new Response(textBlob).text();
36
45
  }
37
46
  error = false;
@@ -45,7 +45,7 @@ export declare class paste extends Plugin {
45
45
  */
46
46
  private __insertByType;
47
47
  /**
48
- * Replace all \\n chars in plain text to br
48
+ * Escape plain text and replace all \\n chars with br
49
49
  */
50
50
  private onProcessPasteReplaceNl2Br;
51
51
  }
@@ -38,9 +38,7 @@ export class paste extends Plugin {
38
38
  jodit.e
39
39
  .on('paste.paste', this.onPaste)
40
40
  .on('pasteStack.paste', (item) => this.pasteStack.push(item));
41
- if (jodit.o.nl2brInPlainText) {
42
- this.j.e.on('processPaste.paste', this.onProcessPasteReplaceNl2Br);
43
- }
41
+ this.j.e.on('processPaste.paste', this.onProcessPasteReplaceNl2Br);
44
42
  }
45
43
  /** @override **/
46
44
  beforeDestruct(jodit) {
@@ -169,11 +167,15 @@ export class paste extends Plugin {
169
167
  pasteInsertHtml(e, this.j, html);
170
168
  }
171
169
  /**
172
- * Replace all \\n chars in plain text to br
170
+ * Escape plain text and replace all \\n chars with br
173
171
  */
174
172
  onProcessPasteReplaceNl2Br(ignore, text, type) {
175
173
  if (type === TEXT_PLAIN + ';' && !isHTML(text)) {
176
- return nl2br(text);
174
+ // the clipboard contains only plain text — escape special chars
175
+ // so a stray `<` is not parsed as an unclosed tag and does not
176
+ // swallow the rest of the string. See #1227
177
+ const escaped = htmlspecialchars(text);
178
+ return this.j.o.nl2brInPlainText ? nl2br(escaped) : escaped;
177
179
  }
178
180
  }
179
181
  }
@@ -16,6 +16,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
16
16
  import { autobind } from "../../core/decorators/index.js";
17
17
  import { Dom } from "../../core/dom/index.js";
18
18
  import { pluginSystem } from "../../core/global.js";
19
+ import { offset } from "../../core/helpers/index.js";
19
20
  import { Plugin } from "../../core/plugin/index.js";
20
21
  import { Icon } from "../../core/ui/index.js";
21
22
  import "./config.js";
@@ -82,11 +83,21 @@ export class resizeHandler extends Plugin {
82
83
  if (!this.isResized) {
83
84
  return;
84
85
  }
86
+ let { clientX, clientY } = e;
87
+ if (e.view === this.j.ew && this.j.ew !== this.j.ow) {
88
+ // the event was proxied from the editor's iframe — its client
89
+ // coordinates are relative to the iframe viewport, while the
90
+ // start point was captured on the host-document handle;
91
+ // shift them into the host coordinate space
92
+ const workplacePosition = offset(this.j.workplace, this.j, this.j.od, true);
93
+ clientX += workplacePosition.left;
94
+ clientY += workplacePosition.top;
95
+ }
85
96
  if (this.j.o.allowResizeY) {
86
- this.j.e.fire('setHeight', this.start.h + e.clientY - this.start.y);
97
+ this.j.e.fire('setHeight', this.start.h + clientY - this.start.y);
87
98
  }
88
99
  if (this.j.o.allowResizeX) {
89
- this.j.e.fire('setWidth', this.start.w + e.clientX - this.start.x);
100
+ this.j.e.fire('setWidth', this.start.w + clientX - this.start.x);
90
101
  }
91
102
  this.j.e.fire('resize');
92
103
  }
@@ -202,7 +202,11 @@ export class resizer extends Plugin {
202
202
  this.pointerX = e.clientX;
203
203
  this.pointerY = e.clientY;
204
204
  let diff_x, diff_y;
205
- if (this.j.options.iframe) {
205
+ if (this.j.options.iframe && e.view === this.j.ew) {
206
+ // the event was proxied from the editor's iframe — its client
207
+ // coordinates are relative to the iframe viewport, while
208
+ // `startX/startY` were captured on a host-document handle;
209
+ // shift them into the host coordinate space
206
210
  const workplacePosition = this.getWorkplacePosition();
207
211
  diff_x = e.clientX + workplacePosition.left - this.startX;
208
212
  diff_y = e.clientY + workplacePosition.top - this.startY;
@@ -101,20 +101,30 @@ let UISearch = class UISearch extends UIElement {
101
101
  .on(this.queryInput, 'input', () => {
102
102
  this.setMod('empty-query', !trim(this.queryInput.value).length);
103
103
  })
104
- .on(this.queryInput, 'keydown', this.j.async.debounce(async (e) => {
105
- switch (e.key) {
106
- case consts.KEY_ENTER:
104
+ .on(this.queryInput, 'keydown', (() => {
105
+ const debounced = this.j.async.debounce(async (e) => {
106
+ switch (e.key) {
107
+ case consts.KEY_ENTER:
108
+ if (await jodit.e.fire('searchNext')) {
109
+ this.close();
110
+ }
111
+ break;
112
+ default:
113
+ jodit.e.fire(this, 'needUpdateCounters');
114
+ break;
115
+ }
116
+ }, this.j.defaultTimeout);
117
+ return (e) => {
118
+ // Must be canceled synchronously — inside the debounced
119
+ // handler the browser has already submitted the parent
120
+ // form. See https://github.com/xdan/jodit/issues/918
121
+ if (e.key === consts.KEY_ENTER) {
107
122
  e.preventDefault();
108
123
  e.stopImmediatePropagation();
109
- if (await jodit.e.fire('searchNext')) {
110
- this.close();
111
- }
112
- break;
113
- default:
114
- jodit.e.fire(this, 'needUpdateCounters');
115
- break;
116
- }
117
- }, this.j.defaultTimeout));
124
+ }
125
+ debounced(e);
126
+ };
127
+ })());
118
128
  }
119
129
  onEditorKeyDown(e) {
120
130
  if (!this.isOpened) {
@@ -120,14 +120,16 @@ export class selectCells extends Plugin {
120
120
  * Mouse move inside the table
121
121
  */
122
122
  __onMove(table, e) {
123
- var _a;
123
+ var _a, _b;
124
124
  if (this.j.o.readonly && !this.j.isLocked) {
125
125
  return;
126
126
  }
127
127
  if (this.j.isLockedNotBy(key)) {
128
128
  return;
129
129
  }
130
- const node = this.j.ed.elementFromPoint(e.clientX, e.clientY);
130
+ // Inside Shadow DOM `document.elementFromPoint` returns the shadow
131
+ // host, so the lookup must start from the shadow root
132
+ const node = ((_a = this.j.o.shadowRoot) !== null && _a !== void 0 ? _a : this.j.ed).elementFromPoint(e.clientX, e.clientY);
131
133
  if (!node) {
132
134
  return;
133
135
  }
@@ -150,7 +152,7 @@ export class selectCells extends Plugin {
150
152
  }
151
153
  const cellsCount = this.__tableModule.getAllSelectedCells().length;
152
154
  if (cellsCount > 1) {
153
- (_a = this.j.s.sel) === null || _a === void 0 ? void 0 : _a.removeAllRanges();
155
+ (_b = this.j.s.sel) === null || _b === void 0 ? void 0 : _b.removeAllRanges();
154
156
  }
155
157
  this.j.e.fire('hidePopup');
156
158
  e.stopPropagation();
@@ -184,13 +186,15 @@ export class selectCells extends Plugin {
184
186
  * Stop a selection process
185
187
  */
186
188
  __onStopSelection(table, e) {
187
- var _a, _b;
189
+ var _a, _b, _c;
188
190
  if (!this.__selectedCell) {
189
191
  return;
190
192
  }
191
193
  this.__isSelectionMode = false;
192
194
  this.j.unlock();
193
- const node = this.j.ed.elementFromPoint(e.clientX, e.clientY);
195
+ // Inside Shadow DOM `document.elementFromPoint` returns the shadow
196
+ // host, so the lookup must start from the shadow root
197
+ const node = ((_a = this.j.o.shadowRoot) !== null && _a !== void 0 ? _a : this.j.ed).elementFromPoint(e.clientX, e.clientY);
194
198
  if (!node) {
195
199
  return;
196
200
  }
@@ -206,7 +210,7 @@ export class selectCells extends Plugin {
206
210
  cell,
207
211
  this.__selectedCell
208
212
  ]), box = this.__tableModule.formalMatrix(table);
209
- const max = (_a = box[bound[1][0]]) === null || _a === void 0 ? void 0 : _a[bound[1][1]], min = (_b = box[bound[0][0]]) === null || _b === void 0 ? void 0 : _b[bound[0][1]];
213
+ const max = (_b = box[bound[1][0]]) === null || _b === void 0 ? void 0 : _b[bound[1][1]], min = (_c = box[bound[0][0]]) === null || _c === void 0 ? void 0 : _c[bound[0][1]];
210
214
  // `getSelectedBound` keeps its `Infinity` sentinel when none of the
211
215
  // selected cells belong to this table's matrix — e.g. after a
212
216
  // drag-and-drop that moved/removed the cells, leaving a stale anchor and
@@ -134,6 +134,15 @@ export class source extends Plugin {
134
134
  }
135
135
  setFocusToMirror() {
136
136
  var _a;
137
+ const active = this.j.od.activeElement;
138
+ // do not steal focus from another editor or control — e.g. when the
139
+ // mode is switched programmatically (a Vue/React wrapper re-render)
140
+ // while the user is already typing elsewhere. See #1356
141
+ if (active &&
142
+ active !== this.j.od.body &&
143
+ !this.j.container.contains(active)) {
144
+ return;
145
+ }
137
146
  (_a = this.sourceEditor) === null || _a === void 0 ? void 0 : _a.focus();
138
147
  }
139
148
  saveSelection() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jodit",
3
- "version": "4.12.21",
3
+ "version": "4.12.23",
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",
@@ -7,6 +7,6 @@
7
7
  * @module helpers/checker
8
8
  */
9
9
  /**
10
- * Detect if string is HTML from MS Word or Excel
10
+ * Detect if string is HTML from MS Word, Excel or LibreOffice/OpenOffice
11
11
  */
12
12
  export declare function isHtmlFromWord(data: string): boolean;
@@ -42,6 +42,11 @@ export declare class Dialog extends ViewWithToolbar implements IDialog {
42
42
  private __onMouseMove;
43
43
  private __onEsc;
44
44
  private __onResize;
45
+ /**
46
+ * Minimal size the dialog can be resized to — the header and the footer
47
+ * (with its buttons) must always stay inside the panel
48
+ */
49
+ private minSize;
45
50
  private __onResizerMouseDown;
46
51
  private __addGlobalResizeListeners;
47
52
  private __removeGlobalResizeListeners;
@@ -15,6 +15,12 @@ export declare class ToolbarContent<T extends IViewBased = IViewBased> extends U
15
15
  className(): string;
16
16
  /** @override */
17
17
  update(): void;
18
+ /**
19
+ * The content is arbitrary HTML — propagate the disabled state to the
20
+ * nested form controls (e.g. the file input of the Upload button),
21
+ * otherwise they stay interactive.
22
+ */
23
+ protected onChangeDisabled(): void;
18
24
  /** @override */
19
25
  protected createContainer(): HTMLElement;
20
26
  constructor(jodit: T, control: IControlTypeContent, target?: Nullable<HTMLElement>);
@@ -42,6 +42,21 @@ export declare class inlinePopup extends Plugin {
42
42
  private isExcludedTarget;
43
43
  /** @override **/
44
44
  protected afterInit(jodit: IJodit): void;
45
+ /**
46
+ * The user pressed a button inside the selection toolbar — after the
47
+ * command fires `closeAllPopups`, the toolbar should be shown again
48
+ * while the selection is still there. See #1238
49
+ */
50
+ private __reopenSelectionPopup;
51
+ private __onDocumentMouseDown;
52
+ private __onCloseAllPopups;
53
+ /**
54
+ * The selection rect comes from the editor document — in iframe mode its
55
+ * coordinates are iframe-local, while the popup lives in the host
56
+ * document, so the iframe offset must be added. See
57
+ * https://github.com/xdan/jodit/issues/1058
58
+ */
59
+ private __selectionBound;
45
60
  private snapRange;
46
61
  private onSelectionStart;
47
62
  private onSelectionEnd;
@@ -45,7 +45,7 @@ export declare class paste extends Plugin {
45
45
  */
46
46
  private __insertByType;
47
47
  /**
48
- * Replace all \\n chars in plain text to br
48
+ * Escape plain text and replace all \\n chars with br
49
49
  */
50
50
  private onProcessPasteReplaceNl2Br;
51
51
  }