jodit 4.2.12 → 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 (84) hide show
  1. package/CHANGELOG.md +11 -5
  2. package/es2015/jodit.css +115 -115
  3. package/es2015/jodit.fat.min.css +1 -1
  4. package/es2015/jodit.fat.min.js +2 -2
  5. package/es2015/jodit.js +539 -444
  6. package/es2015/jodit.min.css +1 -1
  7. package/es2015/jodit.min.js +2 -2
  8. package/es2015/plugins/debug/debug.js +1 -1
  9. package/es2015/plugins/debug/debug.min.js +1 -1
  10. package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
  11. package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
  12. package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
  13. package/es2018/jodit.css +115 -115
  14. package/es2018/jodit.fat.min.css +1 -1
  15. package/es2018/jodit.fat.min.js +2 -2
  16. package/es2018/jodit.js +539 -444
  17. package/es2018/jodit.min.css +1 -1
  18. package/es2018/jodit.min.js +2 -2
  19. package/es2018/plugins/debug/debug.js +1 -1
  20. package/es2018/plugins/debug/debug.min.js +1 -1
  21. package/es2018/plugins/speech-recognize/speech-recognize.css +1 -1
  22. package/es2018/plugins/speech-recognize/speech-recognize.js +1 -1
  23. package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
  24. package/es2021/jodit.css +115 -115
  25. package/es2021/jodit.fat.min.css +1 -1
  26. package/es2021/jodit.fat.min.js +2 -2
  27. package/es2021/jodit.js +533 -440
  28. package/es2021/jodit.min.css +1 -1
  29. package/es2021/jodit.min.js +2 -2
  30. package/es2021/plugins/debug/debug.js +1 -1
  31. package/es2021/plugins/debug/debug.min.js +1 -1
  32. package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
  33. package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
  34. package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
  35. package/es2021.en/jodit.css +115 -115
  36. package/es2021.en/jodit.fat.min.css +1 -1
  37. package/es2021.en/jodit.fat.min.js +2 -2
  38. package/es2021.en/jodit.js +533 -440
  39. package/es2021.en/jodit.min.css +1 -1
  40. package/es2021.en/jodit.min.js +2 -2
  41. package/es2021.en/plugins/debug/debug.js +1 -1
  42. package/es2021.en/plugins/debug/debug.min.js +1 -1
  43. package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
  44. package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
  45. package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
  46. package/es5/jodit.css +129 -129
  47. package/es5/jodit.fat.min.css +1 -1
  48. package/es5/jodit.fat.min.js +2 -2
  49. package/es5/jodit.js +556 -460
  50. package/es5/jodit.min.css +3 -3
  51. package/es5/jodit.min.js +2 -2
  52. package/es5/plugins/debug/debug.js +1 -1
  53. package/es5/plugins/debug/debug.min.js +1 -1
  54. package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
  55. package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
  56. package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
  57. package/esm/core/constants.js +1 -1
  58. package/esm/core/decorators/autobind/autobind.d.ts +5 -0
  59. package/esm/core/decorators/autobind/autobind.js +5 -0
  60. package/esm/core/selection/helpers/index.d.ts +9 -3
  61. package/esm/core/selection/helpers/index.js +48 -0
  62. package/esm/core/selection/selection.d.ts +6 -1
  63. package/esm/core/selection/selection.js +95 -117
  64. package/esm/index.d.ts +6 -1
  65. package/esm/index.js +3 -2
  66. package/esm/modules/table/table.d.ts +3 -1
  67. package/esm/modules/table/table.js +38 -33
  68. package/esm/modules/uploader/helpers/send-files.js +33 -29
  69. package/esm/plugins/backspace/cases/check-remove-char.js +65 -55
  70. package/esm/plugins/drag-and-drop/drag-and-drop.d.ts +2 -0
  71. package/esm/plugins/drag-and-drop/drag-and-drop.js +43 -36
  72. package/esm/plugins/inline-popup/config/items/cells.js +9 -0
  73. package/esm/plugins/link/link.js +71 -64
  74. package/esm/plugins/search/helpers/highlight-text-ranges.d.ts +0 -4
  75. package/esm/plugins/search/helpers/highlight-text-ranges.js +58 -49
  76. package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +35 -29
  77. package/package.json +1 -1
  78. package/types/core/decorators/autobind/autobind.d.ts +5 -0
  79. package/types/core/selection/helpers/index.d.ts +9 -3
  80. package/types/core/selection/selection.d.ts +6 -1
  81. package/types/index.d.ts +6 -1
  82. package/types/modules/table/table.d.ts +3 -1
  83. package/types/plugins/drag-and-drop/drag-and-drop.d.ts +2 -0
  84. package/types/plugins/search/helpers/highlight-text-ranges.d.ts +0 -4
@@ -137,6 +137,7 @@ export class Table extends ViewComponent {
137
137
  }
138
138
  /**
139
139
  * Generate formal table martix columns*rows
140
+ * @param table - Working table
140
141
  * @param callback - if return false cycle break
141
142
  */
142
143
  formalMatrix(table, callback) {
@@ -205,7 +206,6 @@ export class Table extends ViewComponent {
205
206
  * @param line - Insert a new line after/before this
206
207
  * line contains the selected cell
207
208
  * @param after - Insert a new line after line contains the selected cell
208
- * @param create - Instance of Create class
209
209
  */
210
210
  appendRow(table, line, after) {
211
211
  return Table.__appendRow(table, line, after, this.j.createInside);
@@ -374,13 +374,36 @@ export class Table extends ViewComponent {
374
374
  return Table.__getSelectedBound(table, selectedCells);
375
375
  }
376
376
  static __normalizeTable(table) {
377
- let i, j, min, not;
378
377
  const __marked = [], box = Table.__formalMatrix(table);
379
- // remove extra colspans
380
- for (j = 0; j < box[0].length; j += 1) {
381
- min = 1000000;
382
- not = false;
383
- for (i = 0; i < box.length; i += 1) {
378
+ Table.__removeExtraColspans(box, __marked);
379
+ Table.__removeExtraRowspans(box, __marked);
380
+ // remove rowspans and colspans equal 1 and empty class
381
+ for (let i = 0; i < box.length; i += 1) {
382
+ for (let j = 0; j < box[i].length; j += 1) {
383
+ if (box[i][j] === undefined) {
384
+ continue; // broken table
385
+ }
386
+ if (box[i][j].hasAttribute('rowspan') &&
387
+ box[i][j].rowSpan === 1) {
388
+ attr(box[i][j], 'rowspan', null);
389
+ }
390
+ if (box[i][j].hasAttribute('colspan') &&
391
+ box[i][j].colSpan === 1) {
392
+ attr(box[i][j], 'colspan', null);
393
+ }
394
+ if (box[i][j].hasAttribute('class') &&
395
+ !attr(box[i][j], 'class')) {
396
+ attr(box[i][j], 'class', null);
397
+ }
398
+ }
399
+ }
400
+ Table.__unmark(__marked);
401
+ }
402
+ static __removeExtraColspans(box, __marked) {
403
+ for (let j = 0; j < box[0].length; j += 1) {
404
+ let min = 1000000;
405
+ let not = false;
406
+ for (let i = 0; i < box.length; i += 1) {
384
407
  if (box[i][j] === undefined) {
385
408
  continue; // broken table
386
409
  }
@@ -391,7 +414,7 @@ export class Table extends ViewComponent {
391
414
  min = Math.min(min, box[i][j].colSpan);
392
415
  }
393
416
  if (!not) {
394
- for (i = 0; i < box.length; i += 1) {
417
+ for (let i = 0; i < box.length; i += 1) {
395
418
  if (box[i][j] === undefined) {
396
419
  continue; // broken table
397
420
  }
@@ -399,10 +422,13 @@ export class Table extends ViewComponent {
399
422
  }
400
423
  }
401
424
  }
402
- // remove extra rowspans
425
+ }
426
+ static __removeExtraRowspans(box, marked) {
427
+ let i = 0;
428
+ let j = 0;
403
429
  for (i = 0; i < box.length; i += 1) {
404
- min = 1000000;
405
- not = false;
430
+ let min = 1000000;
431
+ let not = false;
406
432
  for (j = 0; j < box[i].length; j += 1) {
407
433
  if (box[i][j] === undefined) {
408
434
  continue; // broken table
@@ -418,31 +444,10 @@ export class Table extends ViewComponent {
418
444
  if (box[i][j] === undefined) {
419
445
  continue; // broken table
420
446
  }
421
- Table.__mark(box[i][j], 'rowspan', box[i][j].rowSpan - min + 1, __marked);
422
- }
423
- }
424
- }
425
- // remove rowspans and colspans equal 1 and empty class
426
- for (i = 0; i < box.length; i += 1) {
427
- for (j = 0; j < box[i].length; j += 1) {
428
- if (box[i][j] === undefined) {
429
- continue; // broken table
430
- }
431
- if (box[i][j].hasAttribute('rowspan') &&
432
- box[i][j].rowSpan === 1) {
433
- attr(box[i][j], 'rowspan', null);
434
- }
435
- if (box[i][j].hasAttribute('colspan') &&
436
- box[i][j].colSpan === 1) {
437
- attr(box[i][j], 'colspan', null);
438
- }
439
- if (box[i][j].hasAttribute('class') &&
440
- !attr(box[i][j], 'class')) {
441
- attr(box[i][j], 'class', null);
447
+ Table.__mark(box[i][j], 'rowspan', box[i][j].rowSpan - min + 1, marked);
442
448
  }
443
449
  }
444
450
  }
445
- Table.__unmark(__marked);
446
451
  }
447
452
  /**
448
453
  * Try recalculate all coluns and rows after change
@@ -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();
@@ -53,6 +53,9 @@ export default [
53
53
  if (!isJoditObject(editor)) {
54
54
  return;
55
55
  }
56
+ if (!control.args) {
57
+ return false;
58
+ }
56
59
  const command = cmd(control);
57
60
  editor.execCommand(command, false, table);
58
61
  },
@@ -68,6 +71,9 @@ export default [
68
71
  if (!isJoditObject(editor)) {
69
72
  return;
70
73
  }
74
+ if (!control.args) {
75
+ return false;
76
+ }
71
77
  const command = cmd(control);
72
78
  editor.execCommand(command, false, table);
73
79
  },
@@ -86,6 +92,9 @@ export default [
86
92
  if (!isJoditObject(editor)) {
87
93
  return;
88
94
  }
95
+ if (!control.args) {
96
+ return false;
97
+ }
89
98
  const command = cmd(control);
90
99
  editor.execCommand(command, false, table);
91
100
  editor.e.fire('hidePopup');
@@ -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;