jodit 4.2.14 → 4.2.15

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 (79) hide show
  1. package/es2015/jodit.css +115 -115
  2. package/es2015/jodit.fat.min.css +1 -1
  3. package/es2015/jodit.fat.min.js +2 -2
  4. package/es2015/jodit.js +525 -444
  5. package/es2015/jodit.min.css +1 -1
  6. package/es2015/jodit.min.js +2 -2
  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.css +115 -115
  13. package/es2018/jodit.fat.min.css +1 -1
  14. package/es2018/jodit.fat.min.js +2 -2
  15. package/es2018/jodit.js +525 -444
  16. package/es2018/jodit.min.css +1 -1
  17. package/es2018/jodit.min.js +2 -2
  18. package/es2018/plugins/debug/debug.js +1 -1
  19. package/es2018/plugins/debug/debug.min.js +1 -1
  20. package/es2018/plugins/speech-recognize/speech-recognize.css +1 -1
  21. package/es2018/plugins/speech-recognize/speech-recognize.js +1 -1
  22. package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
  23. package/es2021/jodit.css +115 -115
  24. package/es2021/jodit.fat.min.css +1 -1
  25. package/es2021/jodit.fat.min.js +2 -2
  26. package/es2021/jodit.js +519 -440
  27. package/es2021/jodit.min.css +1 -1
  28. package/es2021/jodit.min.js +2 -2
  29. package/es2021/plugins/debug/debug.js +1 -1
  30. package/es2021/plugins/debug/debug.min.js +1 -1
  31. package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
  32. package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
  33. package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
  34. package/es2021.en/jodit.css +115 -115
  35. package/es2021.en/jodit.fat.min.css +1 -1
  36. package/es2021.en/jodit.fat.min.js +2 -2
  37. package/es2021.en/jodit.js +519 -440
  38. package/es2021.en/jodit.min.css +1 -1
  39. package/es2021.en/jodit.min.js +2 -2
  40. package/es2021.en/plugins/debug/debug.js +1 -1
  41. package/es2021.en/plugins/debug/debug.min.js +1 -1
  42. package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
  43. package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
  44. package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
  45. package/es5/jodit.css +129 -129
  46. package/es5/jodit.fat.min.css +1 -1
  47. package/es5/jodit.fat.min.js +2 -2
  48. package/es5/jodit.js +542 -460
  49. package/es5/jodit.min.css +3 -3
  50. package/es5/jodit.min.js +2 -2
  51. package/es5/plugins/debug/debug.js +1 -1
  52. package/es5/plugins/debug/debug.min.js +1 -1
  53. package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
  54. package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
  55. package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
  56. package/esm/core/constants.js +1 -1
  57. package/esm/core/selection/helpers/index.d.ts +9 -3
  58. package/esm/core/selection/helpers/index.js +48 -0
  59. package/esm/core/selection/selection.d.ts +6 -1
  60. package/esm/core/selection/selection.js +95 -117
  61. package/esm/index.d.ts +6 -1
  62. package/esm/index.js +3 -2
  63. package/esm/modules/table/table.d.ts +3 -1
  64. package/esm/modules/table/table.js +38 -33
  65. package/esm/modules/uploader/helpers/send-files.js +33 -29
  66. package/esm/plugins/backspace/cases/check-remove-char.js +65 -55
  67. package/esm/plugins/drag-and-drop/drag-and-drop.d.ts +2 -0
  68. package/esm/plugins/drag-and-drop/drag-and-drop.js +43 -36
  69. package/esm/plugins/link/link.js +71 -64
  70. package/esm/plugins/search/helpers/highlight-text-ranges.d.ts +0 -4
  71. package/esm/plugins/search/helpers/highlight-text-ranges.js +58 -49
  72. package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +35 -29
  73. package/package.json +1 -1
  74. package/types/core/selection/helpers/index.d.ts +9 -3
  75. package/types/core/selection/selection.d.ts +6 -1
  76. package/types/index.d.ts +6 -1
  77. package/types/modules/table/table.d.ts +3 -1
  78. package/types/plugins/drag-and-drop/drag-and-drop.d.ts +2 -0
  79. package/types/plugins/search/helpers/highlight-text-ranges.d.ts +0 -4
@@ -19,34 +19,7 @@ export function sendFiles(uploader, files, handlerSuccess, handlerError, process
19
19
  }
20
20
  const promises = [];
21
21
  if (o.insertImageAsBase64URI) {
22
- let file, i;
23
- for (i = 0; i < fileList.length; i += 1) {
24
- file = fileList[i];
25
- if (file && file.type) {
26
- const mime = file.type.match(/\/([a-z0-9]+)/i);
27
- const extension = mime[1] ? mime[1].toLowerCase() : '';
28
- if (o.imagesExtensions.includes(extension)) {
29
- const reader = new FileReader();
30
- promises.push(uploader.j.async.promise((resolve, reject) => {
31
- reader.onerror = reject;
32
- reader.onloadend = () => {
33
- const resp = {
34
- baseurl: '',
35
- files: [reader.result],
36
- isImages: [true]
37
- };
38
- const handler = isFunction(handlerSuccess)
39
- ? handlerSuccess
40
- : o.defaultHandlerSuccess;
41
- handler.call(uploader, resp);
42
- resolve(resp);
43
- };
44
- reader.readAsDataURL(file);
45
- }));
46
- fileList[i] = null;
47
- }
48
- }
49
- }
22
+ readImagesWithReader(fileList, o.imagesExtensions, promises, uploader, handlerSuccess, o.defaultHandlerSuccess);
50
23
  }
51
24
  fileList = fileList.filter(a => a);
52
25
  if (fileList.length) {
@@ -57,7 +30,7 @@ export function sendFiles(uploader, files, handlerSuccess, handlerError, process
57
30
  for (let i = 0; i < fileList.length; i += 1) {
58
31
  file = fileList[i];
59
32
  if (file) {
60
- const hasRealExtension = /\.[\d\w]+$/.test(file.name);
33
+ const hasRealExtension = /\.\w+$/.test(file.name);
61
34
  const mime = file.type.match(/\/([a-z0-9]+)/i);
62
35
  const extension = mime && mime[1] ? mime[1].toLowerCase() : '';
63
36
  let newName = fileList[i].name ||
@@ -106,3 +79,34 @@ export function sendFiles(uploader, files, handlerSuccess, handlerError, process
106
79
  }
107
80
  return Promise.all(promises);
108
81
  }
82
+ function readImagesWithReader(fileList, imagesExtensions, promises, uploader, handlerSuccess, defaultHandlerSuccess) {
83
+ let file, i;
84
+ for (i = 0; i < fileList.length; i += 1) {
85
+ file = fileList[i];
86
+ if (file && file.type) {
87
+ const mime = file.type.match(/\/([a-z0-9]+)/i);
88
+ const extension = mime[1] ? mime[1].toLowerCase() : '';
89
+ if (!imagesExtensions.includes(extension)) {
90
+ continue;
91
+ }
92
+ const reader = new FileReader();
93
+ promises.push(uploader.j.async.promise((resolve, reject) => {
94
+ reader.onerror = reject;
95
+ reader.onloadend = () => {
96
+ const resp = {
97
+ baseurl: '',
98
+ files: [reader.result],
99
+ isImages: [true]
100
+ };
101
+ const handler = isFunction(handlerSuccess)
102
+ ? handlerSuccess
103
+ : defaultHandlerSuccess;
104
+ handler.call(uploader, resp);
105
+ resolve(resp);
106
+ };
107
+ reader.readAsDataURL(file);
108
+ }));
109
+ fileList[i] = null;
110
+ }
111
+ }
112
+ }
@@ -23,19 +23,12 @@ import { findMostNestedNeighbor } from "../helpers.js";
23
23
  export function checkRemoveChar(jodit, fakeNode, backspace, mode) {
24
24
  const step = backspace ? -1 : 1;
25
25
  const anotherSibling = Dom.sibling(fakeNode, !backspace);
26
- let sibling = Dom.sibling(fakeNode, backspace), removeNeighbor = null;
27
- let charRemoved = false, removed;
28
- const getNextInlineSibling = (sibling) => {
29
- let nextSibling = Dom.sibling(sibling, backspace);
30
- if (!nextSibling &&
31
- sibling.parentNode &&
32
- sibling.parentNode !== jodit.editor) {
33
- nextSibling = findMostNestedNeighbor(sibling, !backspace, jodit.editor, true);
34
- }
35
- return nextSibling;
36
- };
26
+ let sibling = Dom.sibling(fakeNode, backspace);
27
+ let removeNeighbor = null;
28
+ let charRemoved = false;
29
+ let removed;
37
30
  if (!sibling) {
38
- sibling = getNextInlineSibling(fakeNode);
31
+ sibling = getNextInlineSibling(fakeNode, backspace, jodit.editor);
39
32
  }
40
33
  while (sibling && (Dom.isText(sibling) || Dom.isInlineBlock(sibling))) {
41
34
  while (Dom.isInlineBlock(sibling)) {
@@ -45,57 +38,17 @@ export function checkRemoveChar(jodit, fakeNode, backspace, mode) {
45
38
  break;
46
39
  }
47
40
  if (sibling.nodeValue?.length) {
48
- // For Unicode escapes
49
- let value = toArray(sibling.nodeValue);
50
- const length = value.length;
51
- let index = backspace ? length - 1 : 0;
52
- if (value[index] === INVISIBLE_SPACE) {
53
- while (value[index] === INVISIBLE_SPACE) {
54
- index += step;
55
- }
56
- }
57
- removed = value[index];
58
- if (value[index + step] === INVISIBLE_SPACE) {
59
- index += step;
60
- while (value[index] === INVISIBLE_SPACE) {
61
- index += step;
62
- }
63
- index += backspace ? 1 : -1;
64
- }
65
- if (backspace && index < 0) {
66
- value = [];
67
- }
68
- else {
69
- value = value.slice(backspace ? 0 : index + 1, backspace ? index : length);
70
- }
71
- if (!anotherSibling ||
72
- !Dom.isText(anotherSibling) ||
73
- (!backspace ? / $/ : /^ /).test(anotherSibling.nodeValue ?? '') ||
74
- !trimInv(anotherSibling.nodeValue || '').length) {
75
- for (let i = backspace ? value.length - 1 : 0; backspace ? i >= 0 : i < value.length; i += backspace ? -1 : 1) {
76
- if (value[i] === ' ') {
77
- value[i] = NBSP_SPACE;
78
- }
79
- else {
80
- break;
81
- }
82
- }
83
- }
84
- sibling.nodeValue = value.join('');
41
+ removed = tryRemoveChar(sibling, backspace, step, anotherSibling);
85
42
  }
86
43
  if (!sibling.nodeValue?.length) {
87
44
  removeNeighbor = sibling;
88
45
  }
89
46
  if (!isVoid(removed) && removed !== INVISIBLE_SPACE) {
47
+ checkRepeatRemoveCharAction(backspace, sibling, fakeNode, mode, removed, jodit);
90
48
  charRemoved = true;
91
- call(backspace ? Dom.after : Dom.before, sibling, fakeNode);
92
- if (mode === 'sentence' ||
93
- (mode === 'word' && removed !== ' ' && removed !== NBSP_SPACE)) {
94
- checkRemoveChar(jodit, fakeNode, backspace, mode);
95
- }
96
49
  break;
97
50
  }
98
- const nextSibling = getNextInlineSibling(sibling);
51
+ const nextSibling = getNextInlineSibling(sibling, backspace, jodit.editor);
99
52
  if (removeNeighbor) {
100
53
  Dom.safeRemove(removeNeighbor);
101
54
  removeNeighbor = null;
@@ -117,6 +70,13 @@ export function checkRemoveChar(jodit, fakeNode, backspace, mode) {
117
70
  }
118
71
  return charRemoved;
119
72
  }
73
+ function getNextInlineSibling(sibling, backspace, root) {
74
+ let nextSibling = Dom.sibling(sibling, backspace);
75
+ if (!nextSibling && sibling.parentNode && sibling.parentNode !== root) {
76
+ nextSibling = findMostNestedNeighbor(sibling, !backspace, root, true);
77
+ }
78
+ return nextSibling;
79
+ }
120
80
  /**
121
81
  * Helper removes all empty inline parents
122
82
  */
@@ -141,3 +101,53 @@ function addBRInsideEmptyBlock(jodit, node) {
141
101
  Dom.after(node, jodit.createInside.element('br'));
142
102
  }
143
103
  }
104
+ function tryRemoveChar(sibling, backspace, step, anotherSibling) {
105
+ // For Unicode escapes
106
+ let value = toArray(sibling.nodeValue);
107
+ const length = value.length;
108
+ let index = backspace ? length - 1 : 0;
109
+ if (value[index] === INVISIBLE_SPACE) {
110
+ while (value[index] === INVISIBLE_SPACE) {
111
+ index += step;
112
+ }
113
+ }
114
+ const removed = value[index];
115
+ if (value[index + step] === INVISIBLE_SPACE) {
116
+ index += step;
117
+ while (value[index] === INVISIBLE_SPACE) {
118
+ index += step;
119
+ }
120
+ index += backspace ? 1 : -1;
121
+ }
122
+ if (backspace && index < 0) {
123
+ value = [];
124
+ }
125
+ else {
126
+ value = value.slice(backspace ? 0 : index + 1, backspace ? index : length);
127
+ }
128
+ replaceSpaceOnNBSP(anotherSibling, backspace, value);
129
+ sibling.nodeValue = value.join('');
130
+ return removed;
131
+ }
132
+ function replaceSpaceOnNBSP(anotherSibling, backspace, value) {
133
+ if (!anotherSibling ||
134
+ !Dom.isText(anotherSibling) ||
135
+ (!backspace ? / $/ : /^ /).test(anotherSibling.nodeValue ?? '') ||
136
+ !trimInv(anotherSibling.nodeValue || '').length) {
137
+ for (let i = backspace ? value.length - 1 : 0; backspace ? i >= 0 : i < value.length; i += backspace ? -1 : 1) {
138
+ if (value[i] === ' ') {
139
+ value[i] = NBSP_SPACE;
140
+ }
141
+ else {
142
+ break;
143
+ }
144
+ }
145
+ }
146
+ }
147
+ function checkRepeatRemoveCharAction(backspace, sibling, fakeNode, mode, removed, jodit) {
148
+ call(backspace ? Dom.after : Dom.before, sibling, fakeNode);
149
+ if (mode === 'sentence' ||
150
+ (mode === 'word' && removed !== ' ' && removed !== NBSP_SPACE)) {
151
+ checkRemoveChar(jodit, fakeNode, backspace, mode);
152
+ }
153
+ }
@@ -21,6 +21,8 @@ export declare class dragAndDrop extends Plugin {
21
21
  private onDrag;
22
22
  private onDragEnd;
23
23
  private onDrop;
24
+ private __getWorkFragment;
25
+ private __insertFragment;
24
26
  private getText;
25
27
  /** @override */
26
28
  beforeDestruct(): void;
@@ -107,45 +107,11 @@ export class dragAndDrop extends Plugin {
107
107
  const sel = this.j.s.sel;
108
108
  const range = this.bufferRange ||
109
109
  (sel && sel.rangeCount ? sel.getRangeAt(0) : null);
110
- let fragment = null;
111
- if (!this.draggable && range) {
112
- fragment = this.isCopyMode
113
- ? range.cloneContents()
114
- : range.extractContents();
115
- }
116
- else if (this.draggable) {
117
- if (this.isCopyMode) {
118
- const [tagName, field] = attr(this.draggable, '-is-file') === '1'
119
- ? ['a', 'href']
120
- : ['img', 'src'];
121
- fragment = this.j.createInside.element(tagName);
122
- fragment.setAttribute(field, attr(this.draggable, 'data-src') ||
123
- attr(this.draggable, 'src') ||
124
- '');
125
- if (tagName === 'a') {
126
- fragment.textContent = attr(fragment, field) || '';
127
- }
128
- }
129
- else {
130
- fragment = dataBind(this.draggable, 'target');
131
- }
132
- }
133
- else if (this.getText(event)) {
134
- fragment = this.j.createInside.fromHTML(this.getText(event));
135
- }
110
+ const fragment = this.__getWorkFragment(range, event);
136
111
  sel && sel.removeAllRanges();
137
112
  this.j.s.insertCursorAtPoint(event.clientX, event.clientY);
138
113
  if (fragment) {
139
- this.j.s.insertNode(fragment, false, false);
140
- if (range && fragment.firstChild && fragment.lastChild) {
141
- range.setStartBefore(fragment.firstChild);
142
- range.setEndAfter(fragment.lastChild);
143
- this.j.s.selectRange(range);
144
- this.j.e.fire('synchro');
145
- }
146
- if (Dom.isTag(fragment, 'img') && this.j.events) {
147
- this.j.e.fire('afterInsertImage', fragment);
148
- }
114
+ this.__insertFragment.call(this, fragment, range);
149
115
  }
150
116
  event.preventDefault();
151
117
  event.stopPropagation();
@@ -153,6 +119,47 @@ export class dragAndDrop extends Plugin {
153
119
  this.isFragmentFromEditor = false;
154
120
  this.removeDragListeners();
155
121
  }
122
+ __getWorkFragment(range, event) {
123
+ let fragment = null;
124
+ if (!this.draggable && range) {
125
+ fragment = this.isCopyMode
126
+ ? range.cloneContents()
127
+ : range.extractContents();
128
+ }
129
+ else if (this.draggable) {
130
+ if (this.isCopyMode) {
131
+ const [tagName, field] = attr(this.draggable, '-is-file') === '1'
132
+ ? ['a', 'href']
133
+ : ['img', 'src'];
134
+ fragment = this.j.createInside.element(tagName);
135
+ fragment.setAttribute(field, attr(this.draggable, 'data-src') ||
136
+ attr(this.draggable, 'src') ||
137
+ '');
138
+ if (tagName === 'a') {
139
+ fragment.textContent = attr(fragment, field) || '';
140
+ }
141
+ }
142
+ else {
143
+ fragment = dataBind(this.draggable, 'target');
144
+ }
145
+ }
146
+ else if (this.getText(event)) {
147
+ fragment = this.j.createInside.fromHTML(this.getText(event));
148
+ }
149
+ return fragment;
150
+ }
151
+ __insertFragment(fragment, range) {
152
+ this.j.s.insertNode(fragment, false, false);
153
+ if (range && fragment.firstChild && fragment.lastChild) {
154
+ range.setStartBefore(fragment.firstChild);
155
+ range.setEndAfter(fragment.lastChild);
156
+ this.j.s.selectRange(range);
157
+ this.j.e.fire('synchro');
158
+ }
159
+ if (Dom.isTag(fragment, 'img') && this.j.events) {
160
+ this.j.e.fire('afterInsertImage', fragment);
161
+ }
162
+ }
156
163
  /** @override */
157
164
  beforeDestruct() {
158
165
  this.onDragEnd();
@@ -138,35 +138,7 @@ export class link extends Plugin {
138
138
  if (link) {
139
139
  url_input.value = attr(link, 'href') || '';
140
140
  if (modeClassName) {
141
- switch (modeClassName) {
142
- case 'input':
143
- if (className_input) {
144
- className_input.value = attr(link, 'class') || '';
145
- }
146
- break;
147
- case 'select':
148
- if (className_select) {
149
- for (let i = 0; i < className_select.selectedOptions.length; i++) {
150
- const option = className_select.options.item(i);
151
- if (option) {
152
- option.selected = false;
153
- }
154
- }
155
- const classNames = attr(link, 'class') || '';
156
- classNames.split(' ').forEach(className => {
157
- if (className) {
158
- for (let i = 0; i < className_select.options.length; i++) {
159
- const option = className_select.options.item(i);
160
- if (option?.value &&
161
- option.value === className) {
162
- option.selected = true;
163
- }
164
- }
165
- }
166
- });
167
- }
168
- break;
169
- }
141
+ readClassnames(modeClassName, className_input, link, className_select);
170
142
  }
171
143
  if (openInNewTabCheckbox && target_checkbox) {
172
144
  target_checkbox.checked = attr(link, 'target') === '_blank';
@@ -228,42 +200,9 @@ export class link extends Plugin {
228
200
  }
229
201
  links.forEach(a => {
230
202
  attr(a, 'href', url_input.value);
231
- if (modeClassName && (className_input ?? className_select)) {
232
- if (modeClassName === 'input') {
233
- if (className_input.value === '' &&
234
- a.hasAttribute('class')) {
235
- attr(a, 'class', null);
236
- }
237
- if (className_input.value !== '') {
238
- attr(a, 'class', className_input.value);
239
- }
240
- }
241
- else if (modeClassName === 'select') {
242
- if (a.hasAttribute('class')) {
243
- attr(a, 'class', null);
244
- }
245
- for (let i = 0; i < className_select.selectedOptions.length; i++) {
246
- const className = className_select.selectedOptions.item(i)?.value;
247
- if (className) {
248
- a.classList.add(className);
249
- }
250
- }
251
- }
252
- }
203
+ writeClasses(modeClassName, className_input, className_select, a);
253
204
  if (!isImageContent) {
254
- let newContent = a.textContent;
255
- if (content_input.value.trim().length) {
256
- if (textWasChanged) {
257
- newContent = content_input.value;
258
- }
259
- }
260
- else {
261
- newContent = url_input.value;
262
- }
263
- const content = a.textContent;
264
- if (newContent !== content) {
265
- a.textContent = newContent;
266
- }
205
+ writeImage(a, content_input, textWasChanged, url_input);
267
206
  }
268
207
  if (openInNewTabCheckbox && target_checkbox) {
269
208
  attr(a, 'target', target_checkbox.checked ? '_blank' : null);
@@ -308,3 +247,71 @@ __decorate([
308
247
  autobind
309
248
  ], link.prototype, "__generateForm", null);
310
249
  pluginSystem.add('link', link);
250
+ function writeClasses(modeClassName, className_input, className_select, a) {
251
+ if (modeClassName && (className_input ?? className_select)) {
252
+ if (modeClassName === 'input') {
253
+ if (className_input.value === '' && a.hasAttribute('class')) {
254
+ attr(a, 'class', null);
255
+ }
256
+ if (className_input.value !== '') {
257
+ attr(a, 'class', className_input.value);
258
+ }
259
+ }
260
+ else if (modeClassName === 'select') {
261
+ if (a.hasAttribute('class')) {
262
+ attr(a, 'class', null);
263
+ }
264
+ for (let i = 0; i < className_select.selectedOptions.length; i++) {
265
+ const className = className_select.selectedOptions.item(i)?.value;
266
+ if (className) {
267
+ a.classList.add(className);
268
+ }
269
+ }
270
+ }
271
+ }
272
+ }
273
+ function readClassnames(modeClassName, className_input, link, className_select) {
274
+ switch (modeClassName) {
275
+ case 'input':
276
+ if (className_input) {
277
+ className_input.value = attr(link, 'class') || '';
278
+ }
279
+ break;
280
+ case 'select':
281
+ if (className_select) {
282
+ for (let i = 0; i < className_select.selectedOptions.length; i++) {
283
+ const option = className_select.options.item(i);
284
+ if (option) {
285
+ option.selected = false;
286
+ }
287
+ }
288
+ const classNames = attr(link, 'class') || '';
289
+ classNames.split(' ').forEach(className => {
290
+ if (className) {
291
+ for (let i = 0; i < className_select.options.length; i++) {
292
+ const option = className_select.options.item(i);
293
+ if (option?.value && option.value === className) {
294
+ option.selected = true;
295
+ }
296
+ }
297
+ }
298
+ });
299
+ }
300
+ break;
301
+ }
302
+ }
303
+ function writeImage(a, content_input, textWasChanged, url_input) {
304
+ let newContent = a.textContent;
305
+ if (content_input.value.trim().length) {
306
+ if (textWasChanged) {
307
+ newContent = content_input.value;
308
+ }
309
+ }
310
+ else {
311
+ newContent = url_input.value;
312
+ }
313
+ const content = a.textContent;
314
+ if (newContent !== content) {
315
+ a.textContent = newContent;
316
+ }
317
+ }
@@ -23,7 +23,3 @@ export declare function clearSelectionWrappers(root: HTMLElement): void;
23
23
  * @private
24
24
  */
25
25
  export declare function clearSelectionWrappersFromHTML(root: string): string;
26
- /**
27
- * @private
28
- */
29
- export declare function isSelectionWrapper(node: unknown): boolean;
@@ -17,60 +17,14 @@ export function highlightTextRanges(jodit, rng, restRanges, ci, root) {
17
17
  rng.endContainer.nodeValue == null) {
18
18
  return;
19
19
  }
20
- if (jodit.o.search.useCustomHighlightAPI &&
21
- // @ts-ignore Because Highlight is not defined in the types TS 5.3.3
22
- typeof window.Highlight !== 'undefined') {
23
- const ranges = [rng, ...restRanges].map(rng => {
24
- const range = jodit.selection.createRange();
25
- range.setStart(rng.startContainer, rng.startOffset);
26
- range.setEnd(rng.endContainer, rng.endOffset);
27
- return range;
28
- });
29
- // @ts-ignore Because Highlight is not defined in the types TS 5.3.3
30
- const searchHighlight = new Highlight(...ranges);
31
- // @ts-ignore
32
- CSS.highlights.clear();
33
- // @ts-ignore
34
- CSS.highlights.set('jodit-search-result', searchHighlight);
35
- restRanges.length = 0;
20
+ if (checkNativeSelectionMethod(jodit, rng, restRanges)) {
36
21
  return;
37
22
  }
38
23
  const span = ci.element('span', {
39
24
  [TMP_ATTR]: true
40
25
  });
41
26
  Dom.markTemporary(span);
42
- const startText = rng.startContainer.nodeValue;
43
- let diff = 0;
44
- if (rng.startOffset !== 0) {
45
- const text = ci.text(startText.substring(0, rng.startOffset));
46
- rng.startContainer.nodeValue = startText.substring(rng.startOffset);
47
- Dom.before(rng.startContainer, text);
48
- if (rng.startContainer === rng.endContainer) {
49
- diff = rng.startOffset;
50
- rng.endOffset -= diff;
51
- }
52
- rng.startOffset = 0;
53
- }
54
- const endText = rng.endContainer.nodeValue;
55
- if (rng.endOffset !== endText.length) {
56
- const text = ci.text(endText.substring(rng.endOffset));
57
- rng.endContainer.nodeValue = endText.substring(0, rng.endOffset);
58
- Dom.after(rng.endContainer, text);
59
- for (const range of restRanges) {
60
- if (range.startContainer === rng.endContainer) {
61
- range.startContainer = text;
62
- range.startOffset = range.startOffset - rng.endOffset - diff;
63
- if (range.endContainer === rng.endContainer) {
64
- range.endContainer = text;
65
- range.endOffset = range.endOffset - rng.endOffset - diff;
66
- }
67
- }
68
- else {
69
- break;
70
- }
71
- }
72
- rng.endOffset = rng.endContainer.nodeValue.length;
73
- }
27
+ normalizeRanges(rng, restRanges, ci);
74
28
  let next = rng.startContainer;
75
29
  do {
76
30
  if (!next) {
@@ -113,6 +67,61 @@ export function clearSelectionWrappersFromHTML(root) {
113
67
  /**
114
68
  * @private
115
69
  */
116
- export function isSelectionWrapper(node) {
70
+ function isSelectionWrapper(node) {
117
71
  return Dom.isElement(node) && node.hasAttribute(TMP_ATTR);
118
72
  }
73
+ function checkNativeSelectionMethod(jodit, rng, restRanges) {
74
+ if (jodit.o.search.useCustomHighlightAPI &&
75
+ // @ts-ignore Because Highlight is not defined in the types TS 5.3.3
76
+ typeof window.Highlight !== 'undefined') {
77
+ const ranges = [rng, ...restRanges].map(rng => {
78
+ const range = jodit.selection.createRange();
79
+ range.setStart(rng.startContainer, rng.startOffset);
80
+ range.setEnd(rng.endContainer, rng.endOffset);
81
+ return range;
82
+ });
83
+ // @ts-ignore Because Highlight is not defined in the types TS 5.3.3
84
+ const searchHighlight = new Highlight(...ranges);
85
+ // @ts-ignore
86
+ CSS.highlights.clear();
87
+ // @ts-ignore
88
+ CSS.highlights.set('jodit-search-result', searchHighlight);
89
+ restRanges.length = 0;
90
+ return true;
91
+ }
92
+ return false;
93
+ }
94
+ function normalizeRanges(rng, restRanges, ci) {
95
+ const startText = rng.startContainer.nodeValue;
96
+ let diff = 0;
97
+ if (rng.startOffset !== 0) {
98
+ const text = ci.text(startText.substring(0, rng.startOffset));
99
+ rng.startContainer.nodeValue = startText.substring(rng.startOffset);
100
+ Dom.before(rng.startContainer, text);
101
+ if (rng.startContainer === rng.endContainer) {
102
+ diff = rng.startOffset;
103
+ rng.endOffset -= diff;
104
+ }
105
+ rng.startOffset = 0;
106
+ }
107
+ const endText = rng.endContainer.nodeValue;
108
+ if (rng.endOffset !== endText.length) {
109
+ const text = ci.text(endText.substring(rng.endOffset));
110
+ rng.endContainer.nodeValue = endText.substring(0, rng.endOffset);
111
+ Dom.after(rng.endContainer, text);
112
+ for (const range of restRanges) {
113
+ if (range.startContainer === rng.endContainer) {
114
+ range.startContainer = text;
115
+ range.startOffset = range.startOffset - rng.endOffset - diff;
116
+ if (range.endContainer === rng.endContainer) {
117
+ range.endContainer = text;
118
+ range.endOffset = range.endOffset - rng.endOffset - diff;
119
+ }
120
+ }
121
+ else {
122
+ break;
123
+ }
124
+ }
125
+ rng.endOffset = rng.endContainer.nodeValue.length;
126
+ }
127
+ }