jodit 3.19.4 → 3.20.2
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/build/jodit.css +45 -42
- package/build/jodit.es2018.css +38 -36
- package/build/jodit.es2018.en.css +38 -36
- package/build/jodit.es2018.en.js +22562 -25637
- package/build/jodit.es2018.en.min.css +1 -1
- package/build/jodit.es2018.en.min.js +1 -1
- package/build/jodit.es2018.js +23105 -26181
- package/build/jodit.es2018.min.css +1 -1
- package/build/jodit.es2018.min.js +1 -1
- package/build/jodit.js +797 -386
- package/build/jodit.min.css +2 -2
- package/build/jodit.min.js +1 -1
- package/build/plugins/debug/debug.es2018.en.js +97 -0
- package/build/plugins/debug/debug.es2018.en.min.js +1 -0
- package/build/plugins/debug/debug.es2018.js +97 -0
- package/build/plugins/debug/debug.es2018.min.js +1 -0
- package/build/plugins/debug/debug.js +96 -0
- package/build/plugins/debug/debug.min.js +1 -0
- package/build/plugins/speech-recognize/speech-recognize.css +1 -1
- package/build/plugins/speech-recognize/speech-recognize.es2018.css +1 -1
- package/build/plugins/speech-recognize/speech-recognize.es2018.en.css +1 -1
- package/build/plugins/speech-recognize/speech-recognize.es2018.en.js +331 -398
- package/build/plugins/speech-recognize/speech-recognize.es2018.en.min.js +1 -1
- package/build/plugins/speech-recognize/speech-recognize.es2018.js +331 -398
- package/build/plugins/speech-recognize/speech-recognize.es2018.min.js +1 -1
- package/build/plugins/speech-recognize/speech-recognize.js +1 -1
- package/build/vdom.css +1 -1
- package/build/vdom.js +1 -1
- package/index.html +2 -2
- package/package.json +9 -4
- package/src/config.ts +4 -2
- package/src/core/constants.ts +7 -7
- package/src/core/decorators/derive/README.md +71 -0
- package/src/core/decorators/derive/derive.ts +48 -0
- package/src/core/decorators/index.ts +1 -0
- package/src/core/decorators/spy/spy.ts +5 -0
- package/src/core/dom/dom.test.js +0 -1
- package/src/core/dom/dom.ts +28 -13
- package/src/core/event-emitter/observable.ts +3 -3
- package/src/core/helpers/helpers.test.js +0 -170
- package/src/core/plugin/plugin-system.ts +20 -0
- package/src/core/selection/select.ts +27 -9
- package/src/core/selection/style/api/toggle/toggle-ordered-list.ts +5 -1
- package/src/core/selection/style/api/wrap-ordered-list.ts +5 -1
- package/src/core/selection/style/api/wrap-unwrapped-text.ts +1 -1
- package/src/core/selection/style/style.test.js +1 -1
- package/src/core/{view/panel.ts → traits/dlgs.ts} +17 -9
- package/src/core/traits/elms.ts +4 -8
- package/src/core/traits/index.ts +1 -0
- package/src/core/traits/mods.ts +17 -10
- package/src/core/ui/button/index.ts +1 -0
- package/src/{plugins → core/ui/button}/tooltip/README.md +0 -0
- package/src/{plugins → core/ui/button}/tooltip/tooltip.less +4 -4
- package/src/{plugins → core/ui/button}/tooltip/tooltip.test.js +3 -2
- package/src/core/ui/button/tooltip/tooltip.ts +132 -0
- package/src/core/ui/element.ts +5 -27
- package/src/core/ui/group/group.test.js +44 -0
- package/src/core/ui/group/group.ts +4 -4
- package/src/core/view/view-with-toolbar.ts +2 -2
- package/src/core/view/view.ts +11 -33
- package/src/jodit.ts +20 -8
- package/src/langs/ar.js +1 -1
- package/src/langs/cs_cz.js +1 -1
- package/src/langs/de.js +1 -1
- package/src/langs/es.js +1 -1
- package/src/langs/fa.js +1 -1
- package/src/langs/fr.js +1 -1
- package/src/langs/he.js +1 -1
- package/src/langs/hu.js +1 -1
- package/src/langs/i18n.test.js +170 -0
- package/src/langs/id.js +1 -1
- package/src/langs/it.js +1 -1
- package/src/langs/ja.js +1 -1
- package/src/langs/ko.js +1 -1
- package/src/langs/nl.js +1 -1
- package/src/langs/pl.js +1 -1
- package/src/langs/pt_br.js +1 -1
- package/src/langs/ru.js +1 -1
- package/src/langs/tr.js +1 -1
- package/src/langs/zh_cn.js +1 -1
- package/src/langs/zh_tw.js +1 -1
- package/src/modules/dialog/dialog.less +2 -0
- package/src/modules/dialog/dialog.ts +27 -50
- package/src/modules/file-browser/README.md +10 -10
- package/src/modules/file-browser/__image_snapshots__/file-browser-test-screenshot-js-filebrowser-screenshot-testing-open-filebrowser-works-1-snap.png +0 -0
- package/src/modules/file-browser/builders/context-menu.ts +1 -1
- package/src/modules/file-browser/file-browser.test.js +26 -13
- package/src/modules/file-browser/file-browser.test.screenshot.js +23 -0
- package/src/modules/file-browser/file-browser.ts +9 -5
- package/src/modules/history/snapshot.ts +12 -3
- package/src/modules/image-editor/__image_snapshots__/image-editor-test-screenshot-js-image-editor-screenshot-testing-open-image-editor-works-1-snap.png +0 -0
- package/src/modules/image-editor/image-editor.test.screenshot.js +25 -0
- package/src/modules/image-editor/image-editor.ts +7 -6
- package/src/modules/status-bar/status-bar.ts +5 -16
- package/src/modules/table/table.test.js +2 -1
- package/src/modules/toolbar/collection/collection.ts +6 -1
- package/src/modules/uploader/README.md +1 -1
- package/src/modules/uploader/config.ts +1 -1
- package/src/modules/uploader/uploader.test.js +96 -46
- package/src/plugins/about/about.ts +1 -1
- package/src/plugins/add-new-line/add-new-line.ts +5 -4
- package/src/plugins/backspace/backspace.test.js +33 -39
- package/src/plugins/backspace/backspace.ts +10 -4
- package/src/plugins/backspace/cases/check-remove-char.ts +36 -14
- package/src/plugins/backspace/cases/check-remove-unbreakable-element.ts +8 -0
- package/src/plugins/backspace/config.ts +1 -1
- package/src/plugins/backspace/interface.d.ts +1 -1
- package/src/plugins/clean-html/clean-html.test.js +240 -164
- package/src/plugins/clean-html/config.ts +10 -2
- package/src/plugins/clean-html/helpers/remove-format/remove-format-for-collapsed-selection.ts +3 -2
- package/src/plugins/clean-html/helpers/remove-format/remove-format-for-selection.ts +2 -2
- package/src/plugins/clean-html/helpers/visitor/filters/index.ts +1 -0
- package/src/plugins/clean-html/helpers/visitor/filters/remove-empty-text-node.ts +35 -0
- package/src/plugins/clean-html/helpers/visitor/filters/remove-inv-text-nodes.ts +2 -6
- package/src/plugins/clean-html/helpers/visitor/visit-node-walker.ts +5 -0
- package/src/plugins/debug/debug.ts +68 -0
- package/src/plugins/drag-and-drop/drag-and-drop.ts +0 -1
- package/src/plugins/drag-and-drop-element/drag-and-drop-element.test.js +37 -34
- package/src/plugins/dtd/README.md +52 -0
- package/{types/plugins/tooltip/tooltip.d.ts → src/plugins/dtd/after-insert/index.ts} +5 -4
- package/src/plugins/dtd/after-insert/remove-extra-br.ts +39 -0
- package/src/plugins/dtd/before-insert/check-block-nesting.ts +40 -0
- package/src/plugins/dtd/before-insert/index.ts +12 -0
- package/src/plugins/dtd/config.ts +67 -0
- package/src/plugins/dtd/dtd.test.js +128 -0
- package/src/plugins/dtd/dtd.ts +48 -0
- package/src/plugins/enter/enter.test.js +89 -193
- package/src/plugins/enter/enter.ts +14 -11
- package/src/plugins/enter/helpers/check-br.ts +11 -1
- package/src/plugins/enter/helpers/index.ts +1 -0
- package/src/plugins/enter/helpers/move-cursor-out-from-specal-tags.ts +32 -0
- package/src/plugins/enter/helpers/split-fragment.ts +1 -0
- package/src/plugins/fullsize/config.ts +1 -1
- package/src/plugins/fullsize/fullsize.test.js +77 -12
- package/src/plugins/fullsize/fullsize.ts +12 -1
- package/src/plugins/iframe/config.ts +1 -1
- package/src/plugins/image-properties/README.md +7 -0
- package/src/plugins/image-properties/image-properties.ts +1 -1
- package/src/plugins/index.ts +1 -1
- package/src/plugins/limit/limit.test.js +27 -0
- package/src/plugins/limit/limit.ts +4 -2
- package/src/plugins/line-height/line-height.svg +1 -1
- package/src/plugins/link/README.md +5 -0
- package/src/plugins/link/link.test.js +11 -12
- package/src/plugins/link/link.ts +1 -1
- package/src/plugins/mobile/mobile.ts +1 -1
- package/src/plugins/ordered-list/ordered-list.test.js +3 -14
- package/src/plugins/paste/config.ts +0 -7
- package/src/plugins/paste/paste.test.js +3 -3
- package/src/plugins/paste-storage/paste-storage.ts +1 -1
- package/src/plugins/preview/preview.ts +1 -1
- package/src/plugins/search/search.ts +1 -1
- package/src/plugins/select/config.ts +1 -1
- package/src/plugins/spellcheck/config.ts +1 -1
- package/src/plugins/symbols/symbols.test.js +5 -4
- package/src/plugins/table/config.ts +4 -17
- package/src/plugins/table/table.test.js +2 -2
- package/src/plugins/wrap-nodes/wrap-nodes.test.js +34 -5
- package/src/plugins/wrap-nodes/wrap-nodes.ts +59 -16
- package/src/styles/variables.less +1 -1
- package/src/types/ajax.d.ts +2 -2
- package/src/types/file-browser.d.ts +4 -2
- package/src/types/jodit.d.ts +3 -2
- package/src/types/plugin.d.ts +1 -0
- package/src/types/toolbar.d.ts +12 -6
- package/src/types/traits.d.ts +30 -1
- package/src/types/types.d.ts +1 -0
- package/src/types/view.d.ts +9 -34
- package/src/typings.d.ts +1 -0
- package/types/config.d.ts +3 -2
- package/types/core/constants.d.ts +7 -7
- package/types/core/decorators/derive/derive.d.ts +6 -0
- package/types/core/decorators/index.d.ts +1 -0
- package/types/core/dom/dom.d.ts +5 -4
- package/types/core/plugin/plugin-system.d.ts +4 -0
- package/types/core/traits/dlgs.d.ts +15 -0
- package/types/core/traits/elms.d.ts +2 -4
- package/types/core/traits/index.d.ts +1 -0
- package/types/core/traits/mods.d.ts +5 -8
- package/types/core/ui/button/index.d.ts +1 -0
- package/types/core/ui/button/tooltip/tooltip.d.ts +29 -0
- package/types/core/ui/element.d.ts +3 -9
- package/types/core/ui/group/group.d.ts +2 -2
- package/types/core/view/view-with-toolbar.d.ts +2 -2
- package/types/core/view/view.d.ts +5 -10
- package/types/jodit.d.ts +7 -4
- package/types/modules/dialog/dialog.d.ts +8 -10
- package/types/modules/file-browser/file-browser.d.ts +5 -2
- package/types/modules/history/snapshot.d.ts +3 -2
- package/types/modules/image-editor/image-editor.d.ts +4 -4
- package/types/modules/status-bar/status-bar.d.ts +3 -4
- package/types/modules/toolbar/collection/collection.d.ts +1 -0
- package/types/plugins/clean-html/config.d.ts +7 -1
- package/types/plugins/clean-html/helpers/visitor/filters/index.d.ts +1 -0
- package/types/plugins/clean-html/helpers/visitor/filters/remove-empty-text-node.d.ts +13 -0
- package/types/plugins/dtd/after-insert/index.d.ts +10 -0
- package/types/plugins/dtd/after-insert/remove-extra-br.d.ts +16 -0
- package/types/plugins/dtd/before-insert/check-block-nesting.d.ts +16 -0
- package/types/plugins/dtd/before-insert/index.d.ts +10 -0
- package/types/plugins/dtd/config.d.ts +27 -0
- package/types/plugins/dtd/dtd.d.ts +6 -0
- package/types/plugins/enter/helpers/index.d.ts +1 -0
- package/types/plugins/enter/helpers/move-cursor-out-from-specal-tags.d.ts +13 -0
- package/types/plugins/iframe/config.d.ts +1 -1
- package/types/plugins/index.d.ts +1 -1
- package/types/plugins/paste/config.d.ts +0 -4
- package/types/plugins/spellcheck/config.d.ts +1 -1
- package/types/types/ajax.d.ts +2 -2
- package/types/types/file-browser.d.ts +4 -2
- package/types/types/jodit.d.ts +3 -2
- package/types/types/plugin.d.ts +1 -0
- package/types/types/toolbar.d.ts +12 -6
- package/types/types/traits.d.ts +30 -1
- package/types/types/types.d.ts +1 -0
- package/types/types/view.d.ts +9 -34
- package/src/plugins/tooltip/tooltip.ts +0 -114
- package/types/core/view/panel.d.ts +0 -13
|
@@ -12,24 +12,25 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
12
12
|
return item.split('|');
|
|
13
13
|
})
|
|
14
14
|
.forEach(function (events) {
|
|
15
|
+
const defaultValue =
|
|
16
|
+
'<p style="height: 24px;">1111</p>' +
|
|
17
|
+
'<p style="height: 24px;">2222</p>' +
|
|
18
|
+
'<p><img style="width: 100px;height: 100px;" src="tests/artio.jpg" alt=""/></p>' +
|
|
19
|
+
'<p style="height: 24px;">3333</p>' +
|
|
20
|
+
'<p style="height: 24px;">4444</p>';
|
|
15
21
|
describe(
|
|
16
22
|
events[0] + ' and move image inside the editor',
|
|
17
23
|
function () {
|
|
18
24
|
it('Should ' + events[1] + ' dom element', function () {
|
|
19
|
-
const editor = getJodit();
|
|
20
|
-
editor.value =
|
|
21
|
-
'<p>1111</p>' +
|
|
22
|
-
'<p>2222</p>' +
|
|
23
|
-
'<img style="width: 100px" src="https://xdsoft.net/jodit/files/artio.jpg" alt="">' +
|
|
24
|
-
'<p>3333</p>' +
|
|
25
|
-
'<p>4444</p>';
|
|
25
|
+
const editor = getJodit({ disablePlugins: ['sticky'] });
|
|
26
|
+
editor.value = defaultValue;
|
|
26
27
|
|
|
27
28
|
simulateEvent(
|
|
28
29
|
events[0],
|
|
29
30
|
editor.editor.getElementsByTagName('img')[0]
|
|
30
31
|
);
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
editor.editor.scrollIntoView();
|
|
33
34
|
|
|
34
35
|
const box = position(
|
|
35
36
|
editor.editor.querySelectorAll('p')[1],
|
|
@@ -47,35 +48,36 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
const result =
|
|
50
|
-
'<p>1111</p>' +
|
|
51
|
-
'<p>22<img alt="" src="
|
|
52
|
-
'<p>3333</p>' +
|
|
53
|
-
'<p>4444</p>';
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
sortAttributes(editor.value).
|
|
57
|
-
)
|
|
51
|
+
'<p style="height:24px">1111</p>' +
|
|
52
|
+
'<p style="height:24px">22<img alt="" src="tests/artio.jpg" style="height:100px;width:100px">22</p>' +
|
|
53
|
+
'<p style="height:24px">3333</p>' +
|
|
54
|
+
'<p style="height:24px">4444</p>';
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
expect(sortAttributes(editor.value)).equals(result);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
drawElement(editor.editor);
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
);
|
|
61
65
|
|
|
62
66
|
describe(events[1] + ' image inside anchor', function () {
|
|
63
67
|
it('Should ' + events[1] + ' anchor with image', function () {
|
|
64
|
-
const editor = getJodit();
|
|
68
|
+
const editor = getJodit({ disablePlugins: ['sticky'] });
|
|
65
69
|
|
|
66
|
-
editor.value =
|
|
67
|
-
|
|
68
|
-
'<
|
|
69
|
-
|
|
70
|
-
'<p>3333</p>' +
|
|
71
|
-
'<p>4444</p>';
|
|
70
|
+
editor.value = defaultValue.replace(
|
|
71
|
+
/(<img[^>]+>)/,
|
|
72
|
+
'<a href="#test">$1</a>'
|
|
73
|
+
);
|
|
72
74
|
|
|
73
75
|
simulateEvent(
|
|
74
76
|
events[0],
|
|
75
77
|
editor.editor.getElementsByTagName('img')[0]
|
|
76
78
|
);
|
|
77
79
|
|
|
78
|
-
|
|
80
|
+
editor.editor.scrollIntoView();
|
|
79
81
|
|
|
80
82
|
const box = position(
|
|
81
83
|
editor.editor.querySelectorAll('p')[1],
|
|
@@ -88,22 +90,22 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
88
90
|
});
|
|
89
91
|
|
|
90
92
|
simulateEvent(events[2], editor.editor, function (options) {
|
|
91
|
-
options.clientX = box.left +
|
|
93
|
+
options.clientX = box.left + 15;
|
|
92
94
|
options.clientY = box.top + 5;
|
|
93
95
|
});
|
|
94
96
|
|
|
95
|
-
expect(editor.value
|
|
96
|
-
'<p
|
|
97
|
-
/
|
|
98
|
-
'
|
|
99
|
-
|
|
97
|
+
expect(sortAttributes(editor.value)).equals(
|
|
98
|
+
'<p style="height:24px">1111</p>' +
|
|
99
|
+
'<p style="height:24px">22<a href="#test"><img alt="" src="tests/artio.jpg" style="height:100px;width:100px"></a>22</p>' +
|
|
100
|
+
'<p style="height:24px">3333</p>' +
|
|
101
|
+
'<p style="height:24px">4444</p>'
|
|
100
102
|
);
|
|
101
103
|
});
|
|
102
104
|
});
|
|
103
105
|
|
|
104
106
|
describe(events[1] + ' image inside table cell', function () {
|
|
105
107
|
it('Should move only image', function () {
|
|
106
|
-
const editor = getJodit();
|
|
108
|
+
const editor = getJodit({ disablePlugins: ['sticky'] });
|
|
107
109
|
|
|
108
110
|
editor.value = `<table>
|
|
109
111
|
<tbody>
|
|
@@ -119,7 +121,7 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
119
121
|
editor.editor.getElementsByTagName('img')[0]
|
|
120
122
|
);
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
editor.editor.scrollIntoView();
|
|
123
125
|
|
|
124
126
|
const box = position(
|
|
125
127
|
editor.editor.querySelectorAll('td')[1],
|
|
@@ -132,7 +134,7 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
132
134
|
});
|
|
133
135
|
|
|
134
136
|
simulateEvent(events[2], editor.editor, function (options) {
|
|
135
|
-
options.clientX = box.left +
|
|
137
|
+
options.clientX = box.left + 15;
|
|
136
138
|
options.clientY = box.top + 5;
|
|
137
139
|
});
|
|
138
140
|
|
|
@@ -147,6 +149,7 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
147
149
|
describe('Disable dragging', function () {
|
|
148
150
|
it('Should not move image', function () {
|
|
149
151
|
const editor = getJodit({
|
|
152
|
+
disablePlugins: ['sticky'],
|
|
150
153
|
draggableTags: []
|
|
151
154
|
});
|
|
152
155
|
|
|
@@ -175,7 +178,7 @@ describe('Drag and drop element inside Editor', function () {
|
|
|
175
178
|
});
|
|
176
179
|
|
|
177
180
|
simulateEvent(events[2], editor.editor, function (options) {
|
|
178
|
-
options.clientX = box.left +
|
|
181
|
+
options.clientX = box.left + 15;
|
|
179
182
|
options.clientY = box.top + 5;
|
|
180
183
|
});
|
|
181
184
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Responsible for HTML compliance with Document Type Definition standards
|
|
2
|
+
|
|
3
|
+
For example, a TABLE block element cannot be nested inside a P block element.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
Jodit.make('#editor', {
|
|
7
|
+
dtd: {
|
|
8
|
+
/**
|
|
9
|
+
* Remove extra br element inside block element after pasting
|
|
10
|
+
*/
|
|
11
|
+
removeExtraBr: true,
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Check when inserting a block element if it can be inside another block element (according `blockLimits`)
|
|
15
|
+
*/
|
|
16
|
+
checkBlockNesting: true,
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* List of elements that contain other blocks
|
|
20
|
+
*/
|
|
21
|
+
blockLimits: {
|
|
22
|
+
article: 1,
|
|
23
|
+
aside: 1,
|
|
24
|
+
audio: 1,
|
|
25
|
+
body: 1,
|
|
26
|
+
caption: 1,
|
|
27
|
+
details: 1,
|
|
28
|
+
dir: 1,
|
|
29
|
+
div: 1,
|
|
30
|
+
dl: 1,
|
|
31
|
+
fieldset: 1,
|
|
32
|
+
figcaption: 1,
|
|
33
|
+
figure: 1,
|
|
34
|
+
footer: 1,
|
|
35
|
+
form: 1,
|
|
36
|
+
header: 1,
|
|
37
|
+
hgroup: 1,
|
|
38
|
+
main: 1,
|
|
39
|
+
menu: 1,
|
|
40
|
+
nav: 1,
|
|
41
|
+
ol: 1,
|
|
42
|
+
section: 1,
|
|
43
|
+
table: 1,
|
|
44
|
+
td: 1,
|
|
45
|
+
th: 1,
|
|
46
|
+
tr: 1,
|
|
47
|
+
ul: 1,
|
|
48
|
+
video: 1
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
```
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
+
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @
|
|
9
|
-
* @module plugins/tooltip
|
|
8
|
+
* @module plugins/dtd
|
|
9
|
+
* @internal
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
export * from './remove-extra-br';
|
|
@@ -0,0 +1,39 @@
|
|
|
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-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module plugins/dtd
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { IJodit } from 'jodit/types';
|
|
13
|
+
import { Dom } from 'jodit/core/dom/dom';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Checks if there is a tag in the block element after the inserted br node,
|
|
17
|
+
* if so, removes it
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export function removeExtraBr(jodit: IJodit, node: Node): void {
|
|
21
|
+
if (!jodit.o.dtd.removeExtraBr || Dom.isTag(node, 'br')) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const parent = Dom.furthest(node, Dom.isBlock, jodit.editor);
|
|
26
|
+
|
|
27
|
+
if (parent && !Dom.isTag(parent, ['table', 'pre', 'blockquote', 'code'])) {
|
|
28
|
+
const br = Dom.isTag(node, 'br')
|
|
29
|
+
? node
|
|
30
|
+
: Dom.findNotEmptySibling(node, false);
|
|
31
|
+
|
|
32
|
+
if (!Dom.isTag(br, 'br')) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
jodit.s.setCursorBefore(br);
|
|
37
|
+
Dom.safeRemove(br);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
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-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module plugins/dtd
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { IJodit, Nullable } from 'jodit/types';
|
|
13
|
+
import { Dom } from 'jodit/core/dom/dom';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Checks whether the insertion of an element at the current location is allowed,
|
|
17
|
+
* if it is not allowed, it deletes an empty block element or moves the cursor after it
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
export function checkBlockNesting(jodit: IJodit, node: Nullable<Node>): void {
|
|
21
|
+
if (Dom.isFragment(node)) {
|
|
22
|
+
node = node.firstChild;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (jodit.o.dtd.checkBlockNesting && Dom.isBlock(node)) {
|
|
26
|
+
const parent = Dom.furthest(
|
|
27
|
+
jodit.s.current(),
|
|
28
|
+
Dom.isBlock,
|
|
29
|
+
jodit.editor
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (parent && !jodit.o.dtd.blockLimits[parent.tagName.toLowerCase()]) {
|
|
33
|
+
jodit.s.setCursorAfter(parent);
|
|
34
|
+
|
|
35
|
+
if (Dom.isEmpty(parent)) {
|
|
36
|
+
Dom.safeRemove(parent);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
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-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module plugins/dtd
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export * from './check-block-nesting';
|
|
@@ -0,0 +1,67 @@
|
|
|
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-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module plugins/dtd
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { IDictionary } from 'jodit/types';
|
|
12
|
+
import { Config } from 'jodit/config';
|
|
13
|
+
|
|
14
|
+
declare module 'jodit/config' {
|
|
15
|
+
interface Config {
|
|
16
|
+
dtd: {
|
|
17
|
+
/**
|
|
18
|
+
* Remove extra br element inside block element after pasting
|
|
19
|
+
*/
|
|
20
|
+
removeExtraBr: boolean;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check when inserting a block element if it can be inside another block element (according `blockLimits`)
|
|
24
|
+
*/
|
|
25
|
+
checkBlockNesting: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* List of elements that contain other blocks
|
|
29
|
+
*/
|
|
30
|
+
blockLimits: IDictionary<1>;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Config.prototype.dtd = {
|
|
36
|
+
removeExtraBr: true,
|
|
37
|
+
checkBlockNesting: true,
|
|
38
|
+
blockLimits: {
|
|
39
|
+
article: 1,
|
|
40
|
+
aside: 1,
|
|
41
|
+
audio: 1,
|
|
42
|
+
body: 1,
|
|
43
|
+
caption: 1,
|
|
44
|
+
details: 1,
|
|
45
|
+
dir: 1,
|
|
46
|
+
div: 1,
|
|
47
|
+
dl: 1,
|
|
48
|
+
fieldset: 1,
|
|
49
|
+
figcaption: 1,
|
|
50
|
+
figure: 1,
|
|
51
|
+
footer: 1,
|
|
52
|
+
form: 1,
|
|
53
|
+
header: 1,
|
|
54
|
+
hgroup: 1,
|
|
55
|
+
main: 1,
|
|
56
|
+
menu: 1,
|
|
57
|
+
nav: 1,
|
|
58
|
+
ol: 1,
|
|
59
|
+
section: 1,
|
|
60
|
+
table: 1,
|
|
61
|
+
td: 1,
|
|
62
|
+
th: 1,
|
|
63
|
+
tr: 1,
|
|
64
|
+
ul: 1,
|
|
65
|
+
video: 1
|
|
66
|
+
}
|
|
67
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
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-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
describe('Test dtd plugin', () => {
|
|
8
|
+
describe('Before insertNode', () => {
|
|
9
|
+
describe('Enable dtd.checkBlockNesting', () => {
|
|
10
|
+
describe('Not empty parent block', () => {
|
|
11
|
+
it('should move new block after parent', () => {
|
|
12
|
+
const editor = getJodit();
|
|
13
|
+
editor.value = '<p>test|</p>';
|
|
14
|
+
setCursorToChar(editor);
|
|
15
|
+
editor.s.insertHTML(
|
|
16
|
+
'<table><tbody><tr><td>1</td></tr></tbody></table>'
|
|
17
|
+
);
|
|
18
|
+
expect(sortAttributes(editor.value)).eq(
|
|
19
|
+
'<p>test</p><table><tbody><tr><td>1</td></tr></tbody></table>'
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('Empty parent block', () => {
|
|
25
|
+
it('should replace parent block', () => {
|
|
26
|
+
const editor = getJodit();
|
|
27
|
+
editor.value = '<p>|<br></p>';
|
|
28
|
+
setCursorToChar(editor);
|
|
29
|
+
editor.s.insertHTML(
|
|
30
|
+
'<table><tbody><tr><td>1</td></tr></tbody></table>'
|
|
31
|
+
);
|
|
32
|
+
expect(sortAttributes(editor.value)).eq(
|
|
33
|
+
'<table><tbody><tr><td>1</td></tr></tbody></table>'
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('Disable dtd.checkBlockNesting', () => {
|
|
40
|
+
it('should not check nesting', () => {
|
|
41
|
+
const editor = getJodit({
|
|
42
|
+
dtd: {
|
|
43
|
+
checkBlockNesting: false
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
editor.value = '<p>test|</p>';
|
|
47
|
+
setCursorToChar(editor);
|
|
48
|
+
editor.s.insertHTML(
|
|
49
|
+
'<table><tbody><tr><td>1</td></tr></tbody></table>'
|
|
50
|
+
);
|
|
51
|
+
expect(sortAttributes(editor.value)).eq(
|
|
52
|
+
'<p>test<table><tbody><tr><td>1</td></tr></tbody></table></p>'
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('Add to dtd.blockLimits', () => {
|
|
58
|
+
it('should not check nesting', () => {
|
|
59
|
+
const editor = getJodit({
|
|
60
|
+
dtd: {
|
|
61
|
+
blockLimits: {
|
|
62
|
+
p: 1
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
editor.value = '<p>test|</p>';
|
|
67
|
+
setCursorToChar(editor);
|
|
68
|
+
editor.s.insertHTML(
|
|
69
|
+
'<table><tbody><tr><td>1</td></tr></tbody></table>'
|
|
70
|
+
);
|
|
71
|
+
expect(sortAttributes(editor.value)).eq(
|
|
72
|
+
'<p>test<table><tbody><tr><td>1</td></tr></tbody></table></p>'
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('After insertNode', () => {
|
|
79
|
+
describe('Enable dtd.removeExtraBr', () => {
|
|
80
|
+
[
|
|
81
|
+
[
|
|
82
|
+
'<p>test|<br></p>',
|
|
83
|
+
'<img src="tests/artio.jpg">',
|
|
84
|
+
'<p>test<img src="tests/artio.jpg">|</p>',
|
|
85
|
+
'<p>test<img src="tests/artio.jpg">|<br></p>'
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
'<p>|<br></p>',
|
|
89
|
+
'<img src="tests/artio.jpg">',
|
|
90
|
+
'<p><img src="tests/artio.jpg">|</p>',
|
|
91
|
+
'<p><img src="tests/artio.jpg">|<br></p>'
|
|
92
|
+
]
|
|
93
|
+
].forEach(([value, insert, result1, result2]) => {
|
|
94
|
+
describe(`for value ${value} and inserting ${insert}`, () => {
|
|
95
|
+
describe('Enable removeExtraBr', () => {
|
|
96
|
+
it('should move new block after parent', () => {
|
|
97
|
+
const editor = getJodit({
|
|
98
|
+
dtd: {
|
|
99
|
+
removeExtraBr: true
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
editor.value = value;
|
|
103
|
+
setCursorToChar(editor);
|
|
104
|
+
editor.s.insertHTML(insert);
|
|
105
|
+
replaceCursorToChar(editor);
|
|
106
|
+
expect(sortAttributes(editor.value)).eq(result1);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('Disable removeExtraBr', () => {
|
|
111
|
+
it('should move new block after parent', () => {
|
|
112
|
+
const editor = getJodit({
|
|
113
|
+
dtd: {
|
|
114
|
+
removeExtraBr: false
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
editor.value = value;
|
|
118
|
+
setCursorToChar(editor);
|
|
119
|
+
editor.s.insertHTML(insert);
|
|
120
|
+
replaceCursorToChar(editor);
|
|
121
|
+
expect(sortAttributes(editor.value)).eq(result2);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
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-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* [[include:plugins/dtd/README.md]]
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
* @module plugins/dtd
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { IJodit } from 'jodit/types';
|
|
14
|
+
import { Plugin } from 'jodit/core/plugin';
|
|
15
|
+
import { pluginSystem } from 'jodit/core/global';
|
|
16
|
+
import { watch } from 'jodit/core/decorators/watch/watch';
|
|
17
|
+
|
|
18
|
+
import './config';
|
|
19
|
+
import * as beforeInsertCases from './before-insert';
|
|
20
|
+
import * as afterInsertCases from './after-insert';
|
|
21
|
+
|
|
22
|
+
class dtd extends Plugin {
|
|
23
|
+
protected afterInit(jodit: IJodit): void {}
|
|
24
|
+
|
|
25
|
+
protected beforeDestruct(jodit: IJodit): void {}
|
|
26
|
+
|
|
27
|
+
@watch(':beforeInsertNode')
|
|
28
|
+
protected __onBeforeInsertNode(node: Node): void {
|
|
29
|
+
const casesKeys = Object.keys(beforeInsertCases) as Array<
|
|
30
|
+
keyof typeof beforeInsertCases
|
|
31
|
+
>;
|
|
32
|
+
casesKeys.forEach(key => {
|
|
33
|
+
beforeInsertCases[key](this.j, node);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@watch(':afterInsertNode')
|
|
38
|
+
protected __onAfterInsertNode(node: Node): void {
|
|
39
|
+
const casesKeys = Object.keys(afterInsertCases) as Array<
|
|
40
|
+
keyof typeof afterInsertCases
|
|
41
|
+
>;
|
|
42
|
+
casesKeys.forEach(key => {
|
|
43
|
+
afterInsertCases[key](this.j, node);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pluginSystem.add('dtd', dtd);
|