jodit 4.18.3 → 4.18.6
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 +52 -0
- package/es2015/jodit.css +72 -34
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +35 -10
- package/es2015/jodit.js +1967 -327
- package/es2015/jodit.min.css +1 -1
- package/es2015/jodit.min.js +41 -16
- package/es2015/plugins/debug/debug.css +1 -1
- 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.fat.min.css +1 -1
- package/es2018/jodit.fat.min.js +35 -10
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +35 -10
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +72 -34
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +42 -17
- package/es2021/jodit.js +1949 -323
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +42 -17
- package/es2021/plugins/debug/debug.css +1 -1
- 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 +72 -34
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +42 -17
- package/es2021.en/jodit.js +1923 -297
- package/es2021.en/jodit.min.css +1 -1
- package/es2021.en/jodit.min.js +51 -26
- package/es2021.en/plugins/debug/debug.css +1 -1
- 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 +85 -38
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +2225 -379
- package/es5/jodit.min.css +3 -3
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.css +1 -1
- 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/es5/polyfills.fat.min.js +1 -1
- package/es5/polyfills.js +1 -1
- package/es5/polyfills.min.js +1 -1
- package/esm/config.d.ts +28 -26
- package/esm/config.js +19 -21
- package/esm/core/constants.js +1 -1
- package/esm/core/helpers/html/apply-styles.js +3 -0
- package/esm/core/helpers/html/clean-from-word.js +3 -0
- package/esm/core/helpers/html/strip-tags.js +24 -6
- package/esm/core/helpers/html/word-lists.d.ts +29 -0
- package/esm/core/helpers/html/word-lists.js +158 -0
- package/esm/core/helpers/utils/align.d.ts +1 -1
- package/esm/core/helpers/utils/align.js +2 -3
- package/esm/core/selection/helpers/index.d.ts +1 -0
- package/esm/core/selection/helpers/index.js +1 -0
- package/esm/core/selection/helpers/is-moved.d.ts +15 -0
- package/esm/core/selection/helpers/is-moved.js +22 -0
- package/esm/core/selection/style/api/list/toggle-ordered-list.js +40 -3
- package/esm/core/selection/style/transactions.js +5 -2
- package/esm/jodit.js +14 -4
- package/esm/langs/ar.d.ts +10 -0
- package/esm/langs/ar.js +11 -1
- package/esm/langs/az.d.ts +10 -0
- package/esm/langs/az.js +11 -1
- package/esm/langs/cs_cz.d.ts +10 -0
- package/esm/langs/cs_cz.js +12 -1
- package/esm/langs/de.d.ts +10 -0
- package/esm/langs/de.js +11 -1
- package/esm/langs/es.d.ts +10 -0
- package/esm/langs/es.js +11 -1
- package/esm/langs/fa.d.ts +10 -0
- package/esm/langs/fa.js +11 -1
- package/esm/langs/fi.d.ts +10 -0
- package/esm/langs/fi.js +11 -1
- package/esm/langs/fr.d.ts +10 -0
- package/esm/langs/fr.js +11 -1
- package/esm/langs/he.d.ts +10 -0
- package/esm/langs/he.js +11 -1
- package/esm/langs/hu.d.ts +10 -0
- package/esm/langs/hu.js +11 -1
- package/esm/langs/id.d.ts +10 -0
- package/esm/langs/id.js +11 -1
- package/esm/langs/it.d.ts +10 -0
- package/esm/langs/it.js +11 -1
- package/esm/langs/ja.d.ts +10 -0
- package/esm/langs/ja.js +11 -1
- package/esm/langs/ko.d.ts +10 -0
- package/esm/langs/ko.js +11 -1
- package/esm/langs/mn.d.ts +10 -0
- package/esm/langs/mn.js +11 -1
- package/esm/langs/nl.d.ts +10 -0
- package/esm/langs/nl.js +11 -1
- package/esm/langs/no.d.ts +10 -0
- package/esm/langs/no.js +11 -1
- package/esm/langs/pl.d.ts +10 -0
- package/esm/langs/pl.js +11 -1
- package/esm/langs/pt_br.d.ts +10 -0
- package/esm/langs/pt_br.js +11 -1
- package/esm/langs/ru.d.ts +10 -0
- package/esm/langs/ru.js +11 -1
- package/esm/langs/sk.d.ts +10 -0
- package/esm/langs/sk.js +11 -1
- package/esm/langs/sv.d.ts +10 -0
- package/esm/langs/sv.js +11 -1
- package/esm/langs/tr.d.ts +10 -0
- package/esm/langs/tr.js +11 -1
- package/esm/langs/ua.d.ts +10 -0
- package/esm/langs/ua.js +11 -1
- package/esm/langs/zh_cn.d.ts +10 -0
- package/esm/langs/zh_cn.js +11 -1
- package/esm/langs/zh_tw.d.ts +10 -0
- package/esm/langs/zh_tw.js +11 -1
- package/esm/modules/dialog/dialog.d.ts +7 -0
- package/esm/modules/dialog/dialog.js +24 -6
- package/esm/modules/table/table.d.ts +6 -0
- package/esm/modules/table/table.js +18 -26
- package/esm/plugins/all.d.ts +1 -0
- package/esm/plugins/all.js +1 -0
- package/esm/plugins/backspace/cases/check-join-neighbors.js +90 -3
- package/esm/plugins/clean-html/clean-html.d.ts +8 -0
- package/esm/plugins/clean-html/clean-html.js +21 -1
- package/esm/plugins/clean-html/helpers/index.d.ts +1 -0
- package/esm/plugins/clean-html/helpers/index.js +1 -0
- package/esm/plugins/clean-html/helpers/remove-placeholder-br.d.ts +16 -0
- package/esm/plugins/clean-html/helpers/remove-placeholder-br.js +51 -0
- package/esm/plugins/delete/delete.d.ts +11 -1
- package/esm/plugins/delete/delete.js +92 -16
- package/esm/plugins/focus/focus.js +12 -1
- package/esm/plugins/iframe/config.d.ts +3 -0
- package/esm/plugins/iframe/config.js +0 -27
- package/esm/plugins/iframe/iframe.js +8 -1
- package/esm/plugins/image-processor/image-processor.d.ts +4 -1
- package/esm/plugins/image-processor/image-processor.js +15 -4
- package/esm/plugins/image-properties/readers/align.d.ts +2 -2
- package/esm/plugins/index.d.ts +1 -0
- package/esm/plugins/inline-popup/config/items/iframe.d.ts +9 -1
- package/esm/plugins/inline-popup/config/items/iframe.js +15 -0
- package/esm/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/esm/plugins/inline-popup/inline-popup.js +70 -1
- package/esm/plugins/media/media.js +16 -7
- package/esm/plugins/ordered-list/config.js +13 -2
- package/esm/plugins/ordered-list/start-dialog.d.ts +19 -0
- package/esm/plugins/ordered-list/start-dialog.js +58 -0
- package/esm/plugins/placeholder/placeholder.js +7 -1
- package/esm/plugins/resizer/config.d.ts +5 -3
- package/esm/plugins/resizer/config.js +8 -2
- package/esm/plugins/resizer/resizer.d.ts +20 -0
- package/esm/plugins/resizer/resizer.js +140 -17
- package/esm/plugins/select-cells/select-cells.d.ts +23 -0
- package/esm/plugins/select-cells/select-cells.js +75 -1
- package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +3 -2
- package/esm/plugins/video/config.d.ts +6 -0
- package/esm/plugins/video/config.js +77 -65
- package/esm/plugins/video-properties/interface.d.ts +31 -0
- package/esm/plugins/video-properties/interface.js +6 -0
- package/esm/plugins/video-properties/readers.d.ts +26 -0
- package/esm/plugins/video-properties/readers.js +65 -0
- package/esm/plugins/video-properties/replace.d.ts +15 -0
- package/esm/plugins/video-properties/replace.js +97 -0
- package/esm/plugins/video-properties/ui/ui-video-form.d.ts +41 -0
- package/esm/plugins/video-properties/ui/ui-video-form.js +228 -0
- package/esm/plugins/video-properties/video-properties.d.ts +37 -0
- package/esm/plugins/video-properties/video-properties.js +175 -0
- package/esm/plugins/video-properties/writers.d.ts +15 -0
- package/esm/plugins/video-properties/writers.js +73 -0
- package/esm/types/types.d.ts +1 -1
- package/package.json +1 -1
- package/types/config.d.ts +28 -26
- package/types/core/helpers/html/word-lists.d.ts +29 -0
- package/types/core/helpers/utils/align.d.ts +1 -1
- package/types/core/selection/helpers/index.d.ts +1 -0
- package/types/core/selection/helpers/is-moved.d.ts +15 -0
- package/types/langs/ar.d.ts +10 -0
- package/types/langs/az.d.ts +10 -0
- package/types/langs/cs_cz.d.ts +10 -0
- package/types/langs/de.d.ts +10 -0
- package/types/langs/es.d.ts +10 -0
- package/types/langs/fa.d.ts +10 -0
- package/types/langs/fi.d.ts +10 -0
- package/types/langs/fr.d.ts +10 -0
- package/types/langs/he.d.ts +10 -0
- package/types/langs/hu.d.ts +10 -0
- package/types/langs/id.d.ts +10 -0
- package/types/langs/it.d.ts +10 -0
- package/types/langs/ja.d.ts +10 -0
- package/types/langs/ko.d.ts +10 -0
- package/types/langs/mn.d.ts +10 -0
- package/types/langs/nl.d.ts +10 -0
- package/types/langs/no.d.ts +10 -0
- package/types/langs/pl.d.ts +10 -0
- package/types/langs/pt_br.d.ts +10 -0
- package/types/langs/ru.d.ts +10 -0
- package/types/langs/sk.d.ts +10 -0
- package/types/langs/sv.d.ts +10 -0
- package/types/langs/tr.d.ts +10 -0
- package/types/langs/ua.d.ts +10 -0
- package/types/langs/zh_cn.d.ts +10 -0
- package/types/langs/zh_tw.d.ts +10 -0
- package/types/modules/dialog/dialog.d.ts +7 -0
- package/types/modules/table/table.d.ts +6 -0
- package/types/plugins/clean-html/clean-html.d.ts +8 -0
- package/types/plugins/clean-html/helpers/index.d.ts +1 -0
- package/types/plugins/clean-html/helpers/remove-placeholder-br.d.ts +16 -0
- package/types/plugins/delete/delete.d.ts +11 -1
- package/types/plugins/iframe/config.d.ts +3 -0
- package/types/plugins/image-processor/image-processor.d.ts +4 -1
- package/types/plugins/image-properties/readers/align.d.ts +2 -2
- package/types/plugins/index.d.ts +1 -0
- package/types/plugins/inline-popup/config/items/iframe.d.ts +9 -1
- package/types/plugins/inline-popup/inline-popup.d.ts +19 -0
- package/types/plugins/ordered-list/start-dialog.d.ts +19 -0
- package/types/plugins/resizer/config.d.ts +5 -3
- package/types/plugins/resizer/resizer.d.ts +20 -0
- package/types/plugins/select-cells/select-cells.d.ts +23 -0
- package/types/plugins/video/config.d.ts +6 -0
- package/types/plugins/video-properties/interface.d.ts +31 -0
- package/types/plugins/video-properties/readers.d.ts +26 -0
- package/types/plugins/video-properties/replace.d.ts +15 -0
- package/types/plugins/video-properties/ui/ui-video-form.d.ts +41 -0
- package/types/plugins/video-properties/video-properties.d.ts +37 -0
- package/types/plugins/video-properties/writers.d.ts +15 -0
- package/types/types/types.d.ts +1 -1
|
@@ -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 { LIST_TAGS } from "../../../core/constants.js";
|
|
6
|
+
import { INSEPARABLE_TAGS, LIST_TAGS } from "../../../core/constants.js";
|
|
7
7
|
import { Dom } from "../../../core/dom/dom.js";
|
|
8
8
|
import { getMoveFilter } from "../helpers.js";
|
|
9
9
|
/**
|
|
@@ -21,6 +21,10 @@ export function checkJoinNeighbors(jodit, fakeNode, backspace) {
|
|
|
21
21
|
}
|
|
22
22
|
if (Dom.isElement(mainClosestBox) &&
|
|
23
23
|
Dom.isContentEditable(mainClosestBox, jodit.editor)) {
|
|
24
|
+
// A table cell is never joined with its neighbour
|
|
25
|
+
if (Dom.up(fakeNode, Dom.isCell, mainClosestBox, true)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
24
28
|
const sibling = Dom.findNotEmptySibling(mainClosestBox, backspace);
|
|
25
29
|
// A line break before the cursor is a single unit: remove it instead of
|
|
26
30
|
// merging the current element into the (void) `<br>`, which used to move
|
|
@@ -30,15 +34,60 @@ export function checkJoinNeighbors(jodit, fakeNode, backspace) {
|
|
|
30
34
|
jodit.s.setCursorBefore(fakeNode);
|
|
31
35
|
return true;
|
|
32
36
|
}
|
|
37
|
+
// Backspace leaves a block after a table alone, as Word does, rather
|
|
38
|
+
// than moving its text into the last cell
|
|
39
|
+
if (backspace && Dom.isTag(sibling, 'table')) {
|
|
40
|
+
jodit.s.setCursorBefore(fakeNode);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
const box = findCaretBox(fakeNode, mainClosestBox);
|
|
33
44
|
if (sibling &&
|
|
34
|
-
(
|
|
35
|
-
|
|
45
|
+
(checkPullNextLine(jodit, fakeNode, box, sibling, backspace) ||
|
|
46
|
+
checkMoveListContent(jodit, box, sibling, backspace) ||
|
|
47
|
+
moveContentAndRemoveEmpty(jodit, box, findEdgeBlock(resolveTableSibling(sibling, backspace), backspace, jodit.editor), backspace))) {
|
|
36
48
|
jodit.s.setCursorBefore(fakeNode);
|
|
37
49
|
return true;
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
return false;
|
|
41
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* The block holding the caret inside the box that has the sibling, so
|
|
56
|
+
* `<p>one</p><div><p>|two</p></div>` joins the two paragraphs instead of
|
|
57
|
+
* moving the whole `<div>` into the first one. For a list item that is its
|
|
58
|
+
* list, which the list cases handle.
|
|
59
|
+
*/
|
|
60
|
+
function findCaretBox(fakeNode, mainClosestBox) {
|
|
61
|
+
const block = Dom.up(fakeNode, Dom.isBlock, mainClosestBox);
|
|
62
|
+
if (!block) {
|
|
63
|
+
return mainClosestBox;
|
|
64
|
+
}
|
|
65
|
+
return Dom.isLeaf(block) && block.parentElement
|
|
66
|
+
? block.parentElement
|
|
67
|
+
: block;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The innermost block on the sibling's edge facing the caret, so the
|
|
71
|
+
* content is joined to text: `<div><p>one</p></div><p>|two</p>` gives
|
|
72
|
+
* `<div><p>one|two</p></div>`
|
|
73
|
+
*/
|
|
74
|
+
function findEdgeBlock(sibling, backspace, root) {
|
|
75
|
+
let block = sibling;
|
|
76
|
+
while (block) {
|
|
77
|
+
const edge = backspace ? block.lastChild : block.firstChild;
|
|
78
|
+
const child = edge && Dom.isEmptyTextNode(edge)
|
|
79
|
+
? Dom.findNotEmptySibling(edge, backspace)
|
|
80
|
+
: edge;
|
|
81
|
+
if (!Dom.isBlock(child) ||
|
|
82
|
+
Dom.isTag(child, INSEPARABLE_TAGS) ||
|
|
83
|
+
Dom.isTag(child, 'table') ||
|
|
84
|
+
!Dom.isContentEditable(child, root)) {
|
|
85
|
+
return block;
|
|
86
|
+
}
|
|
87
|
+
block = child;
|
|
88
|
+
}
|
|
89
|
+
return block;
|
|
90
|
+
}
|
|
42
91
|
/**
|
|
43
92
|
* Content cannot be merged into the `<table>` element itself — it would land
|
|
44
93
|
* between the table sections (after `</tbody>`), which is invalid HTML and
|
|
@@ -56,6 +105,44 @@ function resolveTableSibling(sibling, backspace) {
|
|
|
56
105
|
});
|
|
57
106
|
return cells.length ? cells[backspace ? cells.length - 1 : 0] : null;
|
|
58
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Delete at the edge of a list pulls the next line up to the caret, as the
|
|
110
|
+
* browsers do, instead of moving the caret's line into the next block:
|
|
111
|
+
* `<ul><li>one|</li></ul><p>two</p>` gives `<ul><li>one|two</li></ul>`, and
|
|
112
|
+
* `<p>one|</p><ul><li>two</li></ul>` gives `<p>one|two</p>`
|
|
113
|
+
* @private
|
|
114
|
+
*/
|
|
115
|
+
function checkPullNextLine(jodit, fakeNode, box, sibling, backspace) {
|
|
116
|
+
if (backspace || !(Dom.isList(box) || Dom.isList(sibling))) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const target = Dom.up(fakeNode, Dom.isBlock, box, true);
|
|
120
|
+
const source = Dom.isList(sibling) ? sibling.firstElementChild : sibling;
|
|
121
|
+
if (!target ||
|
|
122
|
+
!source ||
|
|
123
|
+
Dom.isTag(source, INSEPARABLE_TAGS) ||
|
|
124
|
+
Dom.isTag(source, 'table')) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (!Dom.isEmpty(source)) {
|
|
128
|
+
const line = [];
|
|
129
|
+
for (let node = source.firstChild; node && !Dom.isBlock(node); node = node.nextSibling) {
|
|
130
|
+
line.push(node);
|
|
131
|
+
}
|
|
132
|
+
if (!line.length) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const filter = getMoveFilter(jodit);
|
|
136
|
+
line.forEach(node => filter(node) ? Dom.append(target, node) : Dom.safeRemove(node));
|
|
137
|
+
}
|
|
138
|
+
let remove = source;
|
|
139
|
+
while (remove && remove !== jodit.editor && Dom.isEmpty(remove)) {
|
|
140
|
+
const parent = remove.parentElement;
|
|
141
|
+
Dom.safeRemove(remove);
|
|
142
|
+
remove = parent;
|
|
143
|
+
}
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
59
146
|
function checkMoveListContent(jodit, mainClosestBox, sibling, backspace) {
|
|
60
147
|
// Process UL/LI/OL cases
|
|
61
148
|
const siblingIsList = Dom.isTag(sibling, LIST_TAGS);
|
|
@@ -23,6 +23,14 @@ export declare class cleanHtml extends Plugin {
|
|
|
23
23
|
*/
|
|
24
24
|
protected onChangeCleanHTML(): void;
|
|
25
25
|
private currentSelectionNode;
|
|
26
|
+
/**
|
|
27
|
+
* Typing into an empty block (`<p><br></p>`) replaces its `<br>`, but the
|
|
28
|
+
* browser keeps the `<br>` when the caret is in an invisible-space text
|
|
29
|
+
* node in front of it, as Jodit leaves the caret in many of the empty
|
|
30
|
+
* blocks it makes (a cleared editor, a heading in an empty table cell).
|
|
31
|
+
* See #1632
|
|
32
|
+
*/
|
|
33
|
+
protected onInputRemovePlaceholderBr(event: InputEvent | CompositionEvent): void;
|
|
26
34
|
private walker;
|
|
27
35
|
protected startWalker(): void;
|
|
28
36
|
protected beforeCommand(command: string): void | false;
|
|
@@ -21,7 +21,7 @@ import { safeHTML } from "../../core/helpers/html/safe-html.js";
|
|
|
21
21
|
import { Plugin } from "../../core/plugin/plugin.js";
|
|
22
22
|
import "./config.js";
|
|
23
23
|
import { replaceOldTags } from "./helpers/visitor/filters/replace-old-tags.js";
|
|
24
|
-
import { getHash, removeFormatForCollapsedSelection, removeFormatForSelection, visitNodeWalker } from "./helpers/index.js";
|
|
24
|
+
import { getHash, removeFormatForCollapsedSelection, removeFormatForSelection, removePlaceholderBr, visitNodeWalker } from "./helpers/index.js";
|
|
25
25
|
/**
|
|
26
26
|
* Clean HTML after removeFormat and insertHorizontalRule command
|
|
27
27
|
*/
|
|
@@ -72,6 +72,23 @@ export class cleanHtml extends Plugin {
|
|
|
72
72
|
this.walker.setWork(editor.editor);
|
|
73
73
|
this.currentSelectionNode = editor.s.current();
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Typing into an empty block (`<p><br></p>`) replaces its `<br>`, but the
|
|
77
|
+
* browser keeps the `<br>` when the caret is in an invisible-space text
|
|
78
|
+
* node in front of it, as Jodit leaves the caret in many of the empty
|
|
79
|
+
* blocks it makes (a cleared editor, a heading in an empty table cell).
|
|
80
|
+
* See #1632
|
|
81
|
+
*/
|
|
82
|
+
onInputRemovePlaceholderBr(event) {
|
|
83
|
+
var _a;
|
|
84
|
+
if (!this.isEditMode ||
|
|
85
|
+
(event.type === 'input' &&
|
|
86
|
+
(event.isComposing ||
|
|
87
|
+
!((_a = event.inputType) === null || _a === void 0 ? void 0 : _a.startsWith('insert'))))) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
removePlaceholderBr(this.j);
|
|
91
|
+
}
|
|
75
92
|
startWalker() {
|
|
76
93
|
const { jodit } = this;
|
|
77
94
|
const allow = getHash(this.j.o.cleanHTML.allowTags);
|
|
@@ -239,6 +256,9 @@ export class cleanHtml extends Plugin {
|
|
|
239
256
|
__decorate([
|
|
240
257
|
watch([':change', ':afterSetMode', ':afterInit', ':mousedown', ':keydown'])
|
|
241
258
|
], cleanHtml.prototype, "onChangeCleanHTML", null);
|
|
259
|
+
__decorate([
|
|
260
|
+
watch([':input', 'jodit.editor:compositionend'])
|
|
261
|
+
], cleanHtml.prototype, "onInputRemovePlaceholderBr", null);
|
|
242
262
|
__decorate([
|
|
243
263
|
hook('ready')
|
|
244
264
|
], cleanHtml.prototype, "startWalker", null);
|
|
@@ -10,4 +10,5 @@ export * from "./get-hash";
|
|
|
10
10
|
export * from "./is-allowed-media-embed";
|
|
11
11
|
export * from "./remove-format/remove-format-for-collapsed-selection";
|
|
12
12
|
export * from "./remove-format/remove-format-for-selection";
|
|
13
|
+
export * from "./remove-placeholder-br";
|
|
13
14
|
export * from "./visitor/visit-node-walker";
|
|
@@ -10,4 +10,5 @@ export * from "./get-hash.js";
|
|
|
10
10
|
export * from "./is-allowed-media-embed.js";
|
|
11
11
|
export * from "./remove-format/remove-format-for-collapsed-selection.js";
|
|
12
12
|
export * from "./remove-format/remove-format-for-selection.js";
|
|
13
|
+
export * from "./remove-placeholder-br.js";
|
|
13
14
|
export * from "./visitor/visit-node-walker.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @module plugins/clean-html
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Remove the `<br>` that kept the block with the caret open while it was
|
|
12
|
+
* empty, once text has gone into the block: when the block is one line of
|
|
13
|
+
* text that ends in that `<br>`, the `<br>` adds nothing to it
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export declare function removePlaceholderBr(jodit: IJodit): void;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
import { INSEPARABLE_TAGS } from "../../../core/constants.js";
|
|
7
|
+
import { Dom } from "../../../core/dom/dom.js";
|
|
8
|
+
import { trim } from "../../../core/helpers/string/trim.js";
|
|
9
|
+
function lastNode(node) {
|
|
10
|
+
let last = node.lastChild;
|
|
11
|
+
while (Dom.isText(last) && !last.nodeValue) {
|
|
12
|
+
last = last.previousSibling;
|
|
13
|
+
}
|
|
14
|
+
return last;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Remove the `<br>` that kept the block with the caret open while it was
|
|
18
|
+
* empty, once text has gone into the block: when the block is one line of
|
|
19
|
+
* text that ends in that `<br>`, the `<br>` adds nothing to it
|
|
20
|
+
* @private
|
|
21
|
+
*/
|
|
22
|
+
export function removePlaceholderBr(jodit) {
|
|
23
|
+
var _a;
|
|
24
|
+
const block = Dom.closest(jodit.s.current(), Dom.isBlock, jodit.editor);
|
|
25
|
+
if (!block || !trim((_a = block.textContent) !== null && _a !== void 0 ? _a : '')) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
let br = lastNode(block);
|
|
29
|
+
while (Dom.isElement(br) &&
|
|
30
|
+
!Dom.isTag(br, INSEPARABLE_TAGS) &&
|
|
31
|
+
!Dom.isBlock(br)) {
|
|
32
|
+
br = lastNode(br);
|
|
33
|
+
}
|
|
34
|
+
if (!Dom.isTag(br, 'br')) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// Another line break, a block, an image or an embed means the `<br>` may
|
|
38
|
+
// end an empty line, or give the caret a place after the embed
|
|
39
|
+
const isOneLineOfText = Dom.each(block, (node) => {
|
|
40
|
+
if (node !== br &&
|
|
41
|
+
Dom.isElement(node) &&
|
|
42
|
+
(Dom.isTag(node, INSEPARABLE_TAGS) ||
|
|
43
|
+
Dom.isBlock(node) ||
|
|
44
|
+
(Dom.isHTMLElement(node) && !node.isContentEditable))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
if (isOneLineOfText) {
|
|
49
|
+
Dom.safeRemove(br);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -20,13 +20,23 @@ export declare class deleteCommand extends Plugin {
|
|
|
20
20
|
*/
|
|
21
21
|
private __afterDeleteCommand;
|
|
22
22
|
private __onDeleteCommand;
|
|
23
|
+
/**
|
|
24
|
+
* A selection that starts or ends in a table cell clears the selected part
|
|
25
|
+
* of each cell it covers and keeps the cells, as the browsers do.
|
|
26
|
+
* `deleteContents` would remove the cells it fully covers, and the cells
|
|
27
|
+
* it cuts would then be merged as blocks. The range is moved out of those
|
|
28
|
+
* tables, so only the content between them is left to delete.
|
|
29
|
+
*
|
|
30
|
+
* Returns where the caret goes, or null when no table is involved
|
|
31
|
+
*/
|
|
32
|
+
private __clearSelectedCells;
|
|
23
33
|
private __moveContentInLeftSibling;
|
|
24
34
|
/**
|
|
25
35
|
* If left sibling is list - return last leaf
|
|
26
36
|
*/
|
|
27
37
|
private __defineRightLeftBox;
|
|
28
38
|
/**
|
|
29
|
-
* Add BR in empty
|
|
39
|
+
* Add BR in the empty block left at the caret
|
|
30
40
|
*/
|
|
31
41
|
private __addBrInEmptyBlock;
|
|
32
42
|
private __moveCursorInEditableSibling;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Dom } from "../../core/dom/index.js";
|
|
7
7
|
import { pluginSystem } from "../../core/global.js";
|
|
8
|
-
import {
|
|
8
|
+
import { toArray } from "../../core/helpers/index.js";
|
|
9
9
|
import { trim } from "../../core/helpers/string/trim.js";
|
|
10
10
|
import { Plugin } from "../../core/plugin/index.js";
|
|
11
11
|
import "./interface.js";
|
|
@@ -56,6 +56,11 @@ export class deleteCommand extends Plugin {
|
|
|
56
56
|
}
|
|
57
57
|
jodit.s.expandSelection();
|
|
58
58
|
const range = jodit.s.range;
|
|
59
|
+
const caret = this.__clearSelectedCells(range);
|
|
60
|
+
if (caret && range.collapsed) {
|
|
61
|
+
jodit.s.selectRange(caret);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
59
64
|
range.deleteContents();
|
|
60
65
|
const fake = jodit.createInside.fake();
|
|
61
66
|
range.insertNode(fake);
|
|
@@ -65,13 +70,78 @@ export class deleteCommand extends Plugin {
|
|
|
65
70
|
range.setStartBefore(fake);
|
|
66
71
|
range.collapse(true);
|
|
67
72
|
this.__moveCursorInEditableSibling(jodit, leftSibling, fake, range);
|
|
68
|
-
this.__addBrInEmptyBlock(fake,
|
|
73
|
+
this.__addBrInEmptyBlock(fake, range);
|
|
69
74
|
Dom.safeRemove(fake);
|
|
70
|
-
jodit.s.selectRange(range);
|
|
75
|
+
jodit.s.selectRange(caret !== null && caret !== void 0 ? caret : range);
|
|
71
76
|
return false;
|
|
72
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* A selection that starts or ends in a table cell clears the selected part
|
|
80
|
+
* of each cell it covers and keeps the cells, as the browsers do.
|
|
81
|
+
* `deleteContents` would remove the cells it fully covers, and the cells
|
|
82
|
+
* it cuts would then be merged as blocks. The range is moved out of those
|
|
83
|
+
* tables, so only the content between them is left to delete.
|
|
84
|
+
*
|
|
85
|
+
* Returns where the caret goes, or null when no table is involved
|
|
86
|
+
*/
|
|
87
|
+
__clearSelectedCells(range) {
|
|
88
|
+
const { editor, createInside } = this.j;
|
|
89
|
+
const startCell = Dom.closest(range.startContainer, Dom.isCell, editor);
|
|
90
|
+
const endCell = Dom.closest(range.endContainer, Dom.isCell, editor);
|
|
91
|
+
if (startCell === endCell) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const startTable = Dom.closest(startCell, 'table', editor);
|
|
95
|
+
const endTable = Dom.closest(endCell, 'table', editor);
|
|
96
|
+
const caret = range.cloneRange();
|
|
97
|
+
caret.collapse(true);
|
|
98
|
+
const parts = [];
|
|
99
|
+
const addParts = (table) => {
|
|
100
|
+
toArray(table.rows)
|
|
101
|
+
.flatMap(row => toArray(row.cells))
|
|
102
|
+
.filter(cell => range.intersectsNode(cell))
|
|
103
|
+
.forEach(cell => {
|
|
104
|
+
const part = range.cloneRange();
|
|
105
|
+
if (!Dom.isOrContains(cell, range.startContainer)) {
|
|
106
|
+
part.setStart(cell, 0);
|
|
107
|
+
}
|
|
108
|
+
if (!Dom.isOrContains(cell, range.endContainer)) {
|
|
109
|
+
part.setEnd(cell, cell.childNodes.length);
|
|
110
|
+
}
|
|
111
|
+
parts.push([cell, part]);
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
if (startTable) {
|
|
115
|
+
addParts(startTable);
|
|
116
|
+
if (startTable === endTable) {
|
|
117
|
+
range.collapse(true);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
range.setStartAfter(startTable);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (endTable && endTable !== startTable) {
|
|
124
|
+
addParts(endTable);
|
|
125
|
+
range.setEndBefore(endTable);
|
|
126
|
+
}
|
|
127
|
+
parts.forEach(([cell, part]) => {
|
|
128
|
+
part.deleteContents();
|
|
129
|
+
if (Dom.isEmpty(cell)) {
|
|
130
|
+
Dom.detach(cell);
|
|
131
|
+
Dom.append(cell, createInside.element('br'));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
return startTable ? caret : null;
|
|
135
|
+
}
|
|
73
136
|
__moveContentInLeftSibling(fake, leftSibling, rightSibling) {
|
|
74
137
|
leftSibling = this.__defineRightLeftBox(leftSibling);
|
|
138
|
+
// Nothing is moved into a table, and a block left empty after it goes
|
|
139
|
+
if (Dom.isTag(leftSibling, 'table')) {
|
|
140
|
+
if (Dom.isBlock(rightSibling) && Dom.isEmpty(rightSibling)) {
|
|
141
|
+
Dom.safeRemove(rightSibling);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
75
145
|
if (!Dom.isList(rightSibling) &&
|
|
76
146
|
!Dom.isTag(rightSibling, 'table') &&
|
|
77
147
|
Dom.isBlock(rightSibling) &&
|
|
@@ -80,11 +150,24 @@ export class deleteCommand extends Plugin {
|
|
|
80
150
|
Dom.moveContent(rightSibling, leftSibling);
|
|
81
151
|
Dom.safeRemove(rightSibling);
|
|
82
152
|
}
|
|
83
|
-
// Remove empty right LI
|
|
84
153
|
if (Dom.isList(rightSibling) &&
|
|
85
|
-
Dom.isLeaf(rightSibling.firstElementChild)
|
|
86
|
-
|
|
87
|
-
|
|
154
|
+
Dom.isLeaf(rightSibling.firstElementChild)) {
|
|
155
|
+
const item = rightSibling.firstElementChild;
|
|
156
|
+
// What's left of the right list's first item joins the left block,
|
|
157
|
+
// up to a list nested in the item
|
|
158
|
+
if (!Dom.isEmpty(item) && Dom.isBlock(leftSibling)) {
|
|
159
|
+
Dom.append(leftSibling, fake);
|
|
160
|
+
while (item.firstChild && !Dom.isBlock(item.firstChild)) {
|
|
161
|
+
Dom.append(leftSibling, item.firstChild);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Remove empty right LI
|
|
165
|
+
if (Dom.isEmpty(item)) {
|
|
166
|
+
Dom.safeRemove(item);
|
|
167
|
+
}
|
|
168
|
+
if (Dom.isEmpty(rightSibling)) {
|
|
169
|
+
Dom.safeRemove(rightSibling);
|
|
170
|
+
}
|
|
88
171
|
}
|
|
89
172
|
}
|
|
90
173
|
/**
|
|
@@ -102,9 +185,9 @@ export class deleteCommand extends Plugin {
|
|
|
102
185
|
return lastLeaf;
|
|
103
186
|
}
|
|
104
187
|
/**
|
|
105
|
-
* Add BR in empty
|
|
188
|
+
* Add BR in the empty block left at the caret
|
|
106
189
|
*/
|
|
107
|
-
__addBrInEmptyBlock(fake,
|
|
190
|
+
__addBrInEmptyBlock(fake, range) {
|
|
108
191
|
const jodit = this.j;
|
|
109
192
|
if (fake.isConnected &&
|
|
110
193
|
Dom.isBlock(fake.parentNode) &&
|
|
@@ -115,13 +198,6 @@ export class deleteCommand extends Plugin {
|
|
|
115
198
|
range.setStartBefore(br);
|
|
116
199
|
range.collapse(true);
|
|
117
200
|
}
|
|
118
|
-
// Add BR in the right empty table cell
|
|
119
|
-
if (Dom.isTag(rightSibling, 'table')) {
|
|
120
|
-
const firstCell = $$('td,th', rightSibling).shift();
|
|
121
|
-
if (Dom.isCell(firstCell) && Dom.isEmpty(firstCell)) {
|
|
122
|
-
Dom.append(firstCell, jodit.createInside.element('br'));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
201
|
}
|
|
126
202
|
__moveCursorInEditableSibling(jodit, leftSibling, fake, range) {
|
|
127
203
|
var _a;
|
|
@@ -67,7 +67,18 @@ export function focus(editor) {
|
|
|
67
67
|
editor.e.on('afterInit', () => {
|
|
68
68
|
if (editor.o.autofocus) {
|
|
69
69
|
if (editor.defaultTimeout) {
|
|
70
|
-
editor
|
|
70
|
+
// A click or key in the editor during the delay has put the
|
|
71
|
+
// caret where the user wants it, so autofocus leaves it there
|
|
72
|
+
const userInput = 'mousedown touchstart keydown';
|
|
73
|
+
const cancel = () => {
|
|
74
|
+
editor.async.clearTimeout(timeout);
|
|
75
|
+
editor.e.off(userInput, cancel);
|
|
76
|
+
};
|
|
77
|
+
const timeout = editor.async.setTimeout(() => {
|
|
78
|
+
editor.e.off(userInput, cancel);
|
|
79
|
+
focus();
|
|
80
|
+
}, 300);
|
|
81
|
+
editor.e.on(userInput, cancel);
|
|
71
82
|
}
|
|
72
83
|
else {
|
|
73
84
|
focus();
|
|
@@ -37,6 +37,9 @@ declare module 'jodit/config' {
|
|
|
37
37
|
iframeDoctype: string;
|
|
38
38
|
/**
|
|
39
39
|
* Custom style to be used inside the iframe to display content.
|
|
40
|
+
* It goes in after `iframeCSSLinks`. The rules Jodit's own plugins need
|
|
41
|
+
* in the editing document are added apart from it, so a value of your
|
|
42
|
+
* own doesn't have to repeat them.
|
|
40
43
|
*
|
|
41
44
|
* ```javascript
|
|
42
45
|
* Jodit.make('#editor', {
|
|
@@ -51,33 +51,6 @@ Config.prototype.iframeStyle =
|
|
|
51
51
|
'p{' +
|
|
52
52
|
'margin-top:0;' +
|
|
53
53
|
'}' +
|
|
54
|
-
'[data-jodit_iframe_wrapper]{' +
|
|
55
|
-
'display: block;' +
|
|
56
|
-
'user-select: none;' +
|
|
57
|
-
'position: relative;' +
|
|
58
|
-
'}' +
|
|
59
|
-
'[data-jodit_iframe_wrapper] iframe{' +
|
|
60
|
-
'position: relative;' +
|
|
61
|
-
'}' +
|
|
62
|
-
'[data-jodit_iframe_wrapper]:after {' +
|
|
63
|
-
'position:absolute;' +
|
|
64
|
-
'content:"";' +
|
|
65
|
-
'z-index:1;' +
|
|
66
|
-
'top:0;' +
|
|
67
|
-
'left:0;' +
|
|
68
|
-
'right: 0;' +
|
|
69
|
-
'bottom: 0;' +
|
|
70
|
-
'cursor: pointer;' +
|
|
71
|
-
'display: block;' +
|
|
72
|
-
'background: rgba(0, 0, 0, 0);' +
|
|
73
|
-
'} ' +
|
|
74
|
-
'[data-jodit_iframe_wrapper][data-jodit-wrapper_active=true] iframe{' +
|
|
75
|
-
'z-index: 2;' +
|
|
76
|
-
'}' +
|
|
77
|
-
'.jodit-wysiwyg_image-selected::selection,' +
|
|
78
|
-
'.jodit-wysiwyg_image-selected *:not(img)::selection{' +
|
|
79
|
-
'background:transparent' +
|
|
80
|
-
'}' +
|
|
81
54
|
'.jodit_disabled{' +
|
|
82
55
|
'user-select: none;' +
|
|
83
56
|
'-o-user-select: none;' +
|
|
@@ -7,7 +7,7 @@ import { MODE_SOURCE } from "../../core/constants.js";
|
|
|
7
7
|
import { Dom } from "../../core/dom/dom.js";
|
|
8
8
|
import { pluginSystem } from "../../core/global.js";
|
|
9
9
|
import { error } from "../../core/helpers/index.js";
|
|
10
|
-
import { attr, callPromise, css, defaultLanguage } from "../../core/helpers/index.js";
|
|
10
|
+
import { $$, attr, callPromise, css, defaultLanguage } from "../../core/helpers/index.js";
|
|
11
11
|
import "./config.js";
|
|
12
12
|
/**
|
|
13
13
|
* Iframe plugin - use `iframe` instead of DIV in editor. It can be need when you want to attach custom styles in editor
|
|
@@ -43,6 +43,8 @@ export function iframe(editor) {
|
|
|
43
43
|
attr(link, 'rel', 'stylesheet');
|
|
44
44
|
attr(link, 'href', href);
|
|
45
45
|
doc.head && Dom.append(doc.head, link);
|
|
46
|
+
// What plugins measured in the editing document changes once it's styled
|
|
47
|
+
jodit.e.on(link, 'load', () => jodit.e.fire('resize'));
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
50
|
if (opt.iframeStyle) {
|
|
@@ -83,6 +85,8 @@ export function iframe(editor) {
|
|
|
83
85
|
null);
|
|
84
86
|
};
|
|
85
87
|
const clearMarkers = (html) => {
|
|
88
|
+
// The plugins' own styles, from `getContainer`, aren't part of the value
|
|
89
|
+
html = html.replace(/<style[^>]+jodit-box[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
86
90
|
const bodyReg = /<body.*<\/body>/im, bodyMarker = '{%%BODY%%}', body = bodyReg.exec(html);
|
|
87
91
|
if (body) {
|
|
88
92
|
// remove markers
|
|
@@ -119,7 +123,10 @@ export function iframe(editor) {
|
|
|
119
123
|
const replaceDocument = (html) => {
|
|
120
124
|
const inert = new DOMParser().parseFromString(html, 'text/html');
|
|
121
125
|
editor.e.fire('safeHTML', inert.documentElement);
|
|
126
|
+
// The plugins' own styles stay, as the value leaves them out
|
|
127
|
+
const styles = $$('style.jodit-box', doc.head);
|
|
122
128
|
doc.replaceChild(doc.adoptNode(inert.documentElement), doc.documentElement);
|
|
129
|
+
styles.forEach(style => Dom.append(doc.head, style));
|
|
123
130
|
};
|
|
124
131
|
if (docMode) {
|
|
125
132
|
const tag = editor.element.tagName;
|
|
@@ -25,7 +25,10 @@ export declare class imageProcessor extends Plugin {
|
|
|
25
25
|
}): void;
|
|
26
26
|
/**
|
|
27
27
|
* While the selection is an image, only the image is highlighted: Safari
|
|
28
|
-
* paints the rest of a block image's line with its parent's highlight. See #1528
|
|
28
|
+
* paints the rest of a block image's line with its parent's highlight. See #1528.
|
|
29
|
+
* Media in a wrapper (`jodit-media`, the resizer's `jodit` for an embed, or
|
|
30
|
+
* one from `mediaWrappers`) isn't highlighted either, as Safari paints its
|
|
31
|
+
* wrapper's whole line, and its resize frame shows it's selected
|
|
29
32
|
*/
|
|
30
33
|
private onSelectionChange;
|
|
31
34
|
protected afterChange(data: {
|
|
@@ -16,20 +16,26 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
16
16
|
import { INVISIBLE_SPACE_REG_EXP, SOURCE_CONSUMER } from "../../core/constants.js";
|
|
17
17
|
import { autobind, cached, debounce, watch } from "../../core/decorators/index.js";
|
|
18
18
|
import { Dom } from "../../core/dom/dom.js";
|
|
19
|
-
import { pluginSystem } from "../../core/global.js";
|
|
20
|
-
import { $$, dataBind } from "../../core/helpers/index.js";
|
|
19
|
+
import { getContainer, pluginSystem } from "../../core/global.js";
|
|
20
|
+
import { $$, dataBind, getWrappedMedia } from "../../core/helpers/index.js";
|
|
21
21
|
import { Plugin } from "../../core/plugin/index.js";
|
|
22
22
|
import { dataURItoBlob } from "../../modules/uploader/helpers/data-uri-to-blob.js";
|
|
23
23
|
import "./config.js";
|
|
24
24
|
const JODIT_IMAGE_PROCESSOR_BINDED = '__jodit_imageprocessor_binded';
|
|
25
25
|
const JODIT_IMAGE_BLOB_ID = JODIT_IMAGE_PROCESSOR_BINDED + 'blob-id';
|
|
26
26
|
const IMAGE_SELECTED = 'jodit-wysiwyg_image-selected';
|
|
27
|
+
const SELECTED_TAGS = new Set(['img', 'jodit', 'jodit-media']);
|
|
27
28
|
/**
|
|
28
29
|
* Change editor's size after load all images
|
|
29
30
|
*/
|
|
30
31
|
export class imageProcessor extends Plugin {
|
|
31
32
|
afterInit(jodit) {
|
|
32
33
|
jodit.e.on(jodit.ed, 'selectionchange', this.onSelectionChange);
|
|
34
|
+
// Over the highlight in `styles/reset.less`; the image keeps its own. It goes
|
|
35
|
+
// in the editing document, so iframe mode has it whatever `iframeStyle` holds
|
|
36
|
+
getContainer(jodit, 'image-processor', 'style', true).textContent =
|
|
37
|
+
`.jodit-wysiwyg.${IMAGE_SELECTED}::selection,` +
|
|
38
|
+
`.jodit-wysiwyg.${IMAGE_SELECTED} *:not(img)::selection{background:transparent}`;
|
|
33
39
|
}
|
|
34
40
|
beforeDestruct(jodit) {
|
|
35
41
|
jodit.e.off(jodit.ed, 'selectionchange', this.onSelectionChange);
|
|
@@ -66,7 +72,10 @@ export class imageProcessor extends Plugin {
|
|
|
66
72
|
}
|
|
67
73
|
/**
|
|
68
74
|
* While the selection is an image, only the image is highlighted: Safari
|
|
69
|
-
* paints the rest of a block image's line with its parent's highlight. See #1528
|
|
75
|
+
* paints the rest of a block image's line with its parent's highlight. See #1528.
|
|
76
|
+
* Media in a wrapper (`jodit-media`, the resizer's `jodit` for an embed, or
|
|
77
|
+
* one from `mediaWrappers`) isn't highlighted either, as Safari paints its
|
|
78
|
+
* wrapper's whole line, and its resize frame shows it's selected
|
|
70
79
|
*/
|
|
71
80
|
onSelectionChange() {
|
|
72
81
|
const { jodit } = this;
|
|
@@ -117,9 +126,11 @@ function isImageSelected(jodit) {
|
|
|
117
126
|
return false;
|
|
118
127
|
}
|
|
119
128
|
const { startContainer, startOffset, endContainer, endOffset } = sel.getRangeAt(0);
|
|
129
|
+
const node = startContainer.childNodes[startOffset];
|
|
120
130
|
return (startContainer === endContainer &&
|
|
121
131
|
endOffset === startOffset + 1 &&
|
|
122
|
-
Dom.isTag(
|
|
132
|
+
(Dom.isTag(node, SELECTED_TAGS) ||
|
|
133
|
+
Boolean(getWrappedMedia(jodit, node))) &&
|
|
123
134
|
Dom.isOrContains(jodit.editor, startContainer));
|
|
124
135
|
}
|
|
125
136
|
/**
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* @module plugins/image-properties
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type { HAlignClasses, Nullable } from "../../../types/index";
|
|
10
10
|
import type { EditValues } from "../interface";
|
|
11
11
|
/**
|
|
12
12
|
* @private
|
|
13
13
|
*/
|
|
14
|
-
export declare function readAlign(image: HTMLImageElement, values: EditValues, classes?: Nullable<
|
|
14
|
+
export declare function readAlign(image: HTMLImageElement, values: EditValues, classes?: Nullable<HAlignClasses>): void;
|
package/esm/plugins/index.d.ts
CHANGED
|
@@ -68,6 +68,7 @@ import "./table/table";
|
|
|
68
68
|
import "./table-keyboard-navigation/table-keyboard-navigation";
|
|
69
69
|
import "./toolbar-navigation/toolbar-navigation";
|
|
70
70
|
import "./video/video";
|
|
71
|
+
import "./video-properties/video-properties";
|
|
71
72
|
import "./wrap-nodes/wrap-nodes";
|
|
72
73
|
import "./dtd/dtd";
|
|
73
74
|
import "./xpath/xpath";
|
|
@@ -6,10 +6,18 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* @module plugins/inline-popup
|
|
8
8
|
*/
|
|
9
|
-
import type { IJodit } from "../../../../types/index";
|
|
9
|
+
import type { IJodit, Nullable } from "../../../../types/index";
|
|
10
10
|
declare const _default: (import("../../../../types/index").IControlType<IJodit, import("../../../../types/index").IToolbarButton> | {
|
|
11
|
+
name: string;
|
|
12
|
+
icon: string;
|
|
13
|
+
tooltip: string;
|
|
14
|
+
popup: (editor: IJodit, target: Nullable<Node>, close: () => void) => HTMLElement | void;
|
|
15
|
+
exec?: undefined;
|
|
16
|
+
} | {
|
|
11
17
|
name: string;
|
|
12
18
|
tooltip: string;
|
|
13
19
|
exec: (editor: IJodit, image: HTMLImageElement) => void;
|
|
20
|
+
icon?: undefined;
|
|
21
|
+
popup?: undefined;
|
|
14
22
|
})[];
|
|
15
23
|
export default _default;
|