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.
- package/CHANGELOG.md +11 -5
- package/es2015/jodit.css +115 -115
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +2 -2
- package/es2015/jodit.js +539 -444
- package/es2015/jodit.min.css +1 -1
- package/es2015/jodit.min.js +2 -2
- package/es2015/plugins/debug/debug.js +1 -1
- package/es2015/plugins/debug/debug.min.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2018/jodit.css +115 -115
- package/es2018/jodit.fat.min.css +1 -1
- package/es2018/jodit.fat.min.js +2 -2
- package/es2018/jodit.js +539 -444
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +2 -2
- package/es2018/plugins/debug/debug.js +1 -1
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +115 -115
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +2 -2
- package/es2021/jodit.js +533 -440
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +2 -2
- package/es2021/plugins/debug/debug.js +1 -1
- package/es2021/plugins/debug/debug.min.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021.en/jodit.css +115 -115
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +2 -2
- package/es2021.en/jodit.js +533 -440
- package/es2021.en/jodit.min.css +1 -1
- package/es2021.en/jodit.min.js +2 -2
- package/es2021.en/plugins/debug/debug.js +1 -1
- package/es2021.en/plugins/debug/debug.min.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/jodit.css +129 -129
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +556 -460
- package/es5/jodit.min.css +3 -3
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.js +1 -1
- package/es5/plugins/debug/debug.min.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/esm/core/constants.js +1 -1
- package/esm/core/decorators/autobind/autobind.d.ts +5 -0
- package/esm/core/decorators/autobind/autobind.js +5 -0
- package/esm/core/selection/helpers/index.d.ts +9 -3
- package/esm/core/selection/helpers/index.js +48 -0
- package/esm/core/selection/selection.d.ts +6 -1
- package/esm/core/selection/selection.js +95 -117
- package/esm/index.d.ts +6 -1
- package/esm/index.js +3 -2
- package/esm/modules/table/table.d.ts +3 -1
- package/esm/modules/table/table.js +38 -33
- package/esm/modules/uploader/helpers/send-files.js +33 -29
- package/esm/plugins/backspace/cases/check-remove-char.js +65 -55
- package/esm/plugins/drag-and-drop/drag-and-drop.d.ts +2 -0
- package/esm/plugins/drag-and-drop/drag-and-drop.js +43 -36
- package/esm/plugins/inline-popup/config/items/cells.js +9 -0
- package/esm/plugins/link/link.js +71 -64
- package/esm/plugins/search/helpers/highlight-text-ranges.d.ts +0 -4
- package/esm/plugins/search/helpers/highlight-text-ranges.js +58 -49
- package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +35 -29
- package/package.json +1 -1
- package/types/core/decorators/autobind/autobind.d.ts +5 -0
- package/types/core/selection/helpers/index.d.ts +9 -3
- package/types/core/selection/selection.d.ts +6 -1
- package/types/index.d.ts +6 -1
- package/types/modules/table/table.d.ts +3 -1
- package/types/plugins/drag-and-drop/drag-and-drop.d.ts +2 -0
- 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
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
for (
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
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)
|
|
27
|
-
let
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
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
|
+
}
|
|
@@ -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
|
-
|
|
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.
|
|
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');
|
package/esm/plugins/link/link.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|