jodit 4.18.2 → 4.18.4
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 +41 -0
- package/es2015/jodit.css +66 -6
- package/es2015/jodit.fat.min.css +1 -1
- package/es2015/jodit.fat.min.js +36 -11
- package/es2015/jodit.js +1435 -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 +36 -11
- package/es2018/jodit.min.css +1 -1
- package/es2018/jodit.min.js +36 -11
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +66 -6
- package/es2021/jodit.fat.min.css +1 -1
- package/es2021/jodit.fat.min.js +45 -20
- package/es2021/jodit.js +1365 -271
- package/es2021/jodit.min.css +1 -1
- package/es2021/jodit.min.js +45 -20
- 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 +66 -6
- package/es2021.en/jodit.fat.min.css +1 -1
- package/es2021.en/jodit.fat.min.js +51 -26
- package/es2021.en/jodit.js +1339 -245
- 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 +82 -7
- package/es5/jodit.fat.min.css +1 -1
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +1629 -354
- 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 +29 -28
- package/esm/config.js +19 -21
- package/esm/core/constants.js +1 -1
- package/esm/core/helpers/utils/align.d.ts +1 -1
- package/esm/core/helpers/utils/align.js +2 -3
- package/esm/core/helpers/utils/index.d.ts +1 -0
- package/esm/core/helpers/utils/index.js +1 -0
- package/esm/core/helpers/utils/prepare-media.d.ts +19 -0
- package/esm/core/helpers/utils/prepare-media.js +31 -0
- package/esm/core/selection/style/api/wrap-unwrapped-text.js +3 -2
- package/esm/jodit.js +14 -4
- package/esm/langs/ar.d.ts +7 -0
- package/esm/langs/ar.js +8 -1
- package/esm/langs/az.d.ts +7 -0
- package/esm/langs/az.js +8 -1
- package/esm/langs/cs_cz.d.ts +7 -0
- package/esm/langs/cs_cz.js +9 -1
- package/esm/langs/de.d.ts +7 -0
- package/esm/langs/de.js +8 -1
- package/esm/langs/es.d.ts +7 -0
- package/esm/langs/es.js +8 -1
- package/esm/langs/fa.d.ts +7 -0
- package/esm/langs/fa.js +8 -1
- package/esm/langs/fi.d.ts +7 -0
- package/esm/langs/fi.js +8 -1
- package/esm/langs/fr.d.ts +7 -0
- package/esm/langs/fr.js +8 -1
- package/esm/langs/he.d.ts +7 -0
- package/esm/langs/he.js +8 -1
- package/esm/langs/hu.d.ts +7 -0
- package/esm/langs/hu.js +8 -1
- package/esm/langs/id.d.ts +7 -0
- package/esm/langs/id.js +8 -1
- package/esm/langs/it.d.ts +7 -0
- package/esm/langs/it.js +8 -1
- package/esm/langs/ja.d.ts +7 -0
- package/esm/langs/ja.js +8 -1
- package/esm/langs/ko.d.ts +7 -0
- package/esm/langs/ko.js +8 -1
- package/esm/langs/mn.d.ts +7 -0
- package/esm/langs/mn.js +8 -1
- package/esm/langs/nl.d.ts +7 -0
- package/esm/langs/nl.js +8 -1
- package/esm/langs/no.d.ts +7 -0
- package/esm/langs/no.js +8 -1
- package/esm/langs/pl.d.ts +7 -0
- package/esm/langs/pl.js +8 -1
- package/esm/langs/pt_br.d.ts +7 -0
- package/esm/langs/pt_br.js +8 -1
- package/esm/langs/ru.d.ts +7 -0
- package/esm/langs/ru.js +8 -1
- package/esm/langs/sk.d.ts +7 -0
- package/esm/langs/sk.js +8 -1
- package/esm/langs/sv.d.ts +7 -0
- package/esm/langs/sv.js +8 -1
- package/esm/langs/tr.d.ts +7 -0
- package/esm/langs/tr.js +8 -1
- package/esm/langs/ua.d.ts +7 -0
- package/esm/langs/ua.js +8 -1
- package/esm/langs/zh_cn.d.ts +7 -0
- package/esm/langs/zh_cn.js +8 -1
- package/esm/langs/zh_tw.d.ts +7 -0
- package/esm/langs/zh_tw.js +8 -1
- package/esm/modules/history/history.d.ts +17 -2
- package/esm/modules/history/history.js +41 -19
- package/esm/modules/table/table.js +7 -2
- package/esm/modules/widget/file-selector/file-selector.js +2 -2
- package/esm/plugins/all.d.ts +1 -0
- package/esm/plugins/all.js +1 -0
- package/esm/plugins/backspace/backspace.js +4 -0
- package/esm/plugins/clean-html/clean-html.d.ts +7 -0
- package/esm/plugins/clean-html/clean-html.js +17 -0
- package/esm/plugins/clean-html/helpers/visitor/filters/replace-old-tags.js +26 -1
- package/esm/plugins/dtd/before-insert/check-block-nesting.d.ts +2 -1
- package/esm/plugins/dtd/before-insert/check-block-nesting.js +26 -5
- package/esm/plugins/enter/helpers/move-cursor-out-from-specal-tags.js +8 -0
- package/esm/plugins/focus/focus.js +3 -0
- package/esm/plugins/hr/hr.js +21 -5
- package/esm/plugins/iframe/config.js +8 -3
- package/esm/plugins/image-processor/image-processor.d.ts +4 -1
- package/esm/plugins/image-processor/image-processor.js +9 -3
- 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 +5 -0
- package/esm/plugins/inline-popup/inline-popup.js +26 -2
- package/esm/plugins/link/link.js +5 -2
- package/esm/plugins/media/config.d.ts +2 -1
- package/esm/plugins/media/media.js +37 -9
- package/esm/plugins/paste/helpers.d.ts +8 -0
- package/esm/plugins/paste/helpers.js +18 -1
- package/esm/plugins/paste/paste.js +2 -2
- package/esm/plugins/resizer/config.d.ts +5 -3
- package/esm/plugins/resizer/config.js +8 -2
- package/esm/plugins/resizer/resizer.d.ts +10 -0
- package/esm/plugins/resizer/resizer.js +72 -18
- package/esm/plugins/select-cells/select-cells.d.ts +10 -0
- package/esm/plugins/select-cells/select-cells.js +54 -6
- package/esm/plugins/table/config.js +51 -1
- package/esm/plugins/table-keyboard-navigation/table-keyboard-navigation.js +1 -1
- package/esm/plugins/video/config.d.ts +6 -0
- package/esm/plugins/video/config.js +78 -82
- 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 +29 -28
- package/types/core/helpers/utils/align.d.ts +1 -1
- package/types/core/helpers/utils/index.d.ts +1 -0
- package/types/core/helpers/utils/prepare-media.d.ts +19 -0
- package/types/langs/ar.d.ts +7 -0
- package/types/langs/az.d.ts +7 -0
- package/types/langs/cs_cz.d.ts +7 -0
- package/types/langs/de.d.ts +7 -0
- package/types/langs/es.d.ts +7 -0
- package/types/langs/fa.d.ts +7 -0
- package/types/langs/fi.d.ts +7 -0
- package/types/langs/fr.d.ts +7 -0
- package/types/langs/he.d.ts +7 -0
- package/types/langs/hu.d.ts +7 -0
- package/types/langs/id.d.ts +7 -0
- package/types/langs/it.d.ts +7 -0
- package/types/langs/ja.d.ts +7 -0
- package/types/langs/ko.d.ts +7 -0
- package/types/langs/mn.d.ts +7 -0
- package/types/langs/nl.d.ts +7 -0
- package/types/langs/no.d.ts +7 -0
- package/types/langs/pl.d.ts +7 -0
- package/types/langs/pt_br.d.ts +7 -0
- package/types/langs/ru.d.ts +7 -0
- package/types/langs/sk.d.ts +7 -0
- package/types/langs/sv.d.ts +7 -0
- package/types/langs/tr.d.ts +7 -0
- package/types/langs/ua.d.ts +7 -0
- package/types/langs/zh_cn.d.ts +7 -0
- package/types/langs/zh_tw.d.ts +7 -0
- package/types/modules/history/history.d.ts +17 -2
- package/types/plugins/clean-html/clean-html.d.ts +7 -0
- package/types/plugins/dtd/before-insert/check-block-nesting.d.ts +2 -1
- 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 +5 -0
- package/types/plugins/media/config.d.ts +2 -1
- package/types/plugins/paste/helpers.d.ts +8 -0
- package/types/plugins/resizer/config.d.ts +5 -3
- package/types/plugins/resizer/resizer.d.ts +10 -0
- package/types/plugins/select-cells/select-cells.d.ts +10 -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
|
@@ -53,3 +53,9 @@ declare module 'jodit/config' {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* The video popup's tabs: Upload, when the uploader is configured, then Link
|
|
58
|
+
* and Code. `insert` runs what a tab inserts, which by default goes in at the
|
|
59
|
+
* selection the popup was opened with.
|
|
60
|
+
*/
|
|
61
|
+
export declare function videoTabs(jodit: IJodit, close: () => void, insert?: (run: () => void) => void): HTMLElement;
|
|
@@ -3,23 +3,13 @@
|
|
|
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 { call, convertMediaUrlToVideoEmbed,
|
|
6
|
+
import { call, convertMediaUrlToVideoEmbed, prepareEmbedCode, prepareMedia } from "../../core/helpers/index.js";
|
|
7
7
|
import { Button } from "../../core/ui/button/index.js";
|
|
8
8
|
import { UIBlock, UIForm, UIInput, UITextArea } from "../../core/ui/form/index.js";
|
|
9
9
|
import { Icon } from "../../core/ui/icon.js";
|
|
10
10
|
import { Config } from "../../config.js";
|
|
11
11
|
import { TabsWidget, UploadTab } from "../../modules/widget/index.js";
|
|
12
12
|
import videoIcon from "./video.svg.js";
|
|
13
|
-
// Media the popup inserts go in their wrapper (see `mediaWrappers`), aligned
|
|
14
|
-
// with `mediaDefaultAlign`
|
|
15
|
-
function prepareMedia(jodit, element) {
|
|
16
|
-
const media = wrapMedia(jodit, element);
|
|
17
|
-
const { mediaDefaultAlign } = jodit.o;
|
|
18
|
-
if (mediaDefaultAlign && mediaDefaultAlign !== 'normal') {
|
|
19
|
-
hAlignElement(media, mediaDefaultAlign, getAlignClasses(jodit, media));
|
|
20
|
-
}
|
|
21
|
-
return media;
|
|
22
|
-
}
|
|
23
13
|
function insertVideos(data) {
|
|
24
14
|
var _a;
|
|
25
15
|
(_a = data.files) === null || _a === void 0 ? void 0 : _a.forEach(file => {
|
|
@@ -29,16 +19,6 @@ function insertVideos(data) {
|
|
|
29
19
|
})));
|
|
30
20
|
});
|
|
31
21
|
}
|
|
32
|
-
// Embed code that is one element is prepared as media; other code goes in as
|
|
33
|
-
// it is
|
|
34
|
-
function prepareEmbedCode(jodit, code) {
|
|
35
|
-
const box = jodit.createInside.div();
|
|
36
|
-
box.innerHTML = code.trim();
|
|
37
|
-
const element = box.firstElementChild;
|
|
38
|
-
return element && box.childNodes.length === 1
|
|
39
|
-
? prepareMedia(jodit, element)
|
|
40
|
-
: code;
|
|
41
|
-
}
|
|
42
22
|
Config.prototype.video = {
|
|
43
23
|
parseUrlToVideoEmbed: convertMediaUrlToVideoEmbed,
|
|
44
24
|
defaultWidth: 400,
|
|
@@ -46,69 +26,85 @@ Config.prototype.video = {
|
|
|
46
26
|
defaultHandlerSuccess: insertVideos
|
|
47
27
|
};
|
|
48
28
|
Icon.set('video', videoIcon);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
new
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
29
|
+
/**
|
|
30
|
+
* The video popup's tabs: Upload, when the uploader is configured, then Link
|
|
31
|
+
* and Code. `insert` runs what a tab inserts, which by default goes in at the
|
|
32
|
+
* selection the popup was opened with.
|
|
33
|
+
*/
|
|
34
|
+
export function videoTabs(jodit, close, insert) {
|
|
35
|
+
const run = insert !== null && insert !== void 0 ? insert : ((fn) => {
|
|
36
|
+
jodit.s.restore();
|
|
37
|
+
fn();
|
|
38
|
+
});
|
|
39
|
+
const formLink = new UIForm(jodit, [
|
|
40
|
+
new UIBlock(jodit, [
|
|
41
|
+
new UIInput(jodit, {
|
|
42
|
+
name: 'url',
|
|
43
|
+
required: true,
|
|
44
|
+
label: 'URL',
|
|
45
|
+
placeholder: 'https://',
|
|
46
|
+
validators: ['url']
|
|
47
|
+
})
|
|
48
|
+
]),
|
|
49
|
+
new UIBlock(jodit, [
|
|
50
|
+
Button(jodit, '', 'Insert', 'primary').onAction(() => formLink.submit())
|
|
51
|
+
])
|
|
52
|
+
]), formCode = new UIForm(jodit, [
|
|
53
|
+
new UIBlock(jodit, [
|
|
54
|
+
new UITextArea(jodit, {
|
|
55
|
+
name: 'code',
|
|
56
|
+
required: true,
|
|
57
|
+
label: 'Embed code'
|
|
58
|
+
})
|
|
59
|
+
]),
|
|
60
|
+
new UIBlock(jodit, [
|
|
61
|
+
Button(jodit, '', 'Insert', 'primary').onAction(() => formCode.submit())
|
|
62
|
+
])
|
|
63
|
+
]), tabs = [], insertCode = (code) => {
|
|
64
|
+
run(() => jodit.s.insertHTML(prepareEmbedCode(jodit, code)));
|
|
65
|
+
close();
|
|
66
|
+
};
|
|
67
|
+
if (!insert) {
|
|
80
68
|
jodit.s.save();
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
69
|
+
}
|
|
70
|
+
const { uploader } = jodit.o;
|
|
71
|
+
// Base64 alone would put whole video files into the content
|
|
72
|
+
if (uploader.showTabInFileSelector !== false &&
|
|
73
|
+
(uploader.url || uploader.customUploadFunction)) {
|
|
74
|
+
tabs.push(UploadTab(jodit, data => {
|
|
75
|
+
run(() => {
|
|
86
76
|
var _a, _b;
|
|
87
|
-
jodit.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
77
|
+
return ((_b = (_a = jodit.o.video) === null || _a === void 0 ? void 0 : _a.defaultHandlerSuccess) !== null && _b !== void 0 ? _b : insertVideos).call(jodit, data);
|
|
78
|
+
});
|
|
79
|
+
}, { label: 'Drop file', accept: 'video/*' }));
|
|
80
|
+
}
|
|
81
|
+
tabs.push({
|
|
82
|
+
icon: 'link',
|
|
83
|
+
name: 'Link',
|
|
84
|
+
content: formLink.container
|
|
85
|
+
}, {
|
|
86
|
+
icon: 'source',
|
|
87
|
+
name: 'Code',
|
|
88
|
+
content: formCode.container
|
|
89
|
+
});
|
|
90
|
+
formLink.onSubmit(data => {
|
|
91
|
+
var _a, _b, _c, _d;
|
|
92
|
+
insertCode(call((_b = (_a = jodit.o.video) === null || _a === void 0 ? void 0 : _a.parseUrlToVideoEmbed) !== null && _b !== void 0 ? _b : convertMediaUrlToVideoEmbed, data.url, {
|
|
93
|
+
width: (_c = jodit.o.video) === null || _c === void 0 ? void 0 : _c.defaultWidth,
|
|
94
|
+
height: (_d = jodit.o.video) === null || _d === void 0 ? void 0 : _d.defaultHeight
|
|
95
|
+
}));
|
|
96
|
+
});
|
|
97
|
+
formCode.onSubmit(data => {
|
|
98
|
+
insertCode(data.code);
|
|
99
|
+
});
|
|
100
|
+
const box = TabsWidget(jodit, tabs);
|
|
101
|
+
// Its tabs are sized to their labels, as the file selector's are, since
|
|
102
|
+
// "Upload" doesn't fit a third of the popup
|
|
103
|
+
box.classList.add('jodit-file-selector');
|
|
104
|
+
return box;
|
|
105
|
+
}
|
|
106
|
+
Config.prototype.controls.video = {
|
|
107
|
+
popup: (jodit, current, close) => videoTabs(jodit, close),
|
|
112
108
|
tags: ['iframe'],
|
|
113
109
|
tooltip: 'Insert youtube/vimeo video'
|
|
114
110
|
};
|
|
@@ -0,0 +1,31 @@
|
|
|
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/video-properties
|
|
8
|
+
*/
|
|
9
|
+
export type EditedMedia = HTMLVideoElement | HTMLAudioElement | HTMLIFrameElement;
|
|
10
|
+
export interface VideoPropertiesValues {
|
|
11
|
+
width: number | string;
|
|
12
|
+
height: number | string;
|
|
13
|
+
poster: string;
|
|
14
|
+
autoplay: boolean;
|
|
15
|
+
loop: boolean;
|
|
16
|
+
muted: boolean;
|
|
17
|
+
controls: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface VideoPropertiesState {
|
|
20
|
+
/**
|
|
21
|
+
* What the dialog was opened for: the media, or a wrapper round it
|
|
22
|
+
*/
|
|
23
|
+
target: HTMLElement;
|
|
24
|
+
media: EditedMedia;
|
|
25
|
+
ratio: number;
|
|
26
|
+
sizeIsLocked: boolean;
|
|
27
|
+
values: VideoPropertiesValues;
|
|
28
|
+
}
|
|
29
|
+
export interface VideoPropertiesAPI {
|
|
30
|
+
openPosterPopup: (target: HTMLElement) => void;
|
|
31
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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/video-properties
|
|
8
|
+
*/
|
|
9
|
+
import type { Nullable } from "../../types/index";
|
|
10
|
+
import type { EditedMedia, VideoPropertiesState } from "./interface";
|
|
11
|
+
/**
|
|
12
|
+
* The media `target` is, or holds as its wrapper (`jodit-media`, the resizer's
|
|
13
|
+
* `jodit` for an embed, or one from `mediaWrappers`)
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export declare function editedMedia(target: HTMLElement): Nullable<EditedMedia>;
|
|
17
|
+
/**
|
|
18
|
+
* The size `media` is given, inline or by its attribute
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
export declare function ownSize(media: EditedMedia, key: 'width' | 'height'): string;
|
|
22
|
+
/**
|
|
23
|
+
* Read the media's values into the state
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
export declare function readValues(state: VideoPropertiesState): void;
|
|
@@ -0,0 +1,65 @@
|
|
|
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 { Dom } from "../../core/dom/dom.js";
|
|
7
|
+
import { isNumeric } from "../../core/helpers/checker/is-numeric.js";
|
|
8
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
9
|
+
import { cssInline } from "../../core/helpers/utils/css.js";
|
|
10
|
+
import { normalSizeFromString } from "../image-properties/utils/utils.js";
|
|
11
|
+
const mediaSelector = 'video, audio, iframe';
|
|
12
|
+
/**
|
|
13
|
+
* The media `target` is, or holds as its wrapper (`jodit-media`, the resizer's
|
|
14
|
+
* `jodit` for an embed, or one from `mediaWrappers`)
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
17
|
+
export function editedMedia(target) {
|
|
18
|
+
return (target.matches(mediaSelector)
|
|
19
|
+
? target
|
|
20
|
+
: target.querySelector(mediaSelector));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The size `media` is given, inline or by its attribute
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
26
|
+
export function ownSize(media, key) {
|
|
27
|
+
return cssInline(media, key) || attr(media, key) || '';
|
|
28
|
+
}
|
|
29
|
+
const toNumber = (value) => parseFloat(value.toString());
|
|
30
|
+
/**
|
|
31
|
+
* Read the media's values into the state
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
export function readValues(state) {
|
|
35
|
+
const { media, values } = state;
|
|
36
|
+
const width = ownSize(media, 'width');
|
|
37
|
+
const height = ownSize(media, 'height');
|
|
38
|
+
values.width = width ? normalSizeFromString(width) : media.offsetWidth;
|
|
39
|
+
values.height = height ? normalSizeFromString(height) : '';
|
|
40
|
+
if (Dom.isTag(media, 'video') && media.videoWidth) {
|
|
41
|
+
state.ratio = media.videoWidth / media.videoHeight;
|
|
42
|
+
}
|
|
43
|
+
else if (isNumeric(values.width) && isNumeric(values.height)) {
|
|
44
|
+
state.ratio = toNumber(values.width) / toNumber(values.height);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
state.ratio = media.offsetWidth / media.offsetHeight || 1;
|
|
48
|
+
}
|
|
49
|
+
// One with no height takes it from its width
|
|
50
|
+
if (!height && isNumeric(values.width)) {
|
|
51
|
+
values.height = Math.round(toNumber(values.width) / state.ratio);
|
|
52
|
+
}
|
|
53
|
+
state.sizeIsLocked =
|
|
54
|
+
isNumeric(values.width) &&
|
|
55
|
+
isNumeric(values.height) &&
|
|
56
|
+
(!height ||
|
|
57
|
+
Math.abs(toNumber(values.width) - toNumber(values.height) * state.ratio) < 1);
|
|
58
|
+
values.poster = attr(media, 'poster') || '';
|
|
59
|
+
values.autoplay = media.hasAttribute('autoplay');
|
|
60
|
+
values.loop = media.hasAttribute('loop');
|
|
61
|
+
// Autoplay's own: turning it off gives the sound back
|
|
62
|
+
values.muted = media.hasAttribute('muted') && !values.autoplay;
|
|
63
|
+
// Without Autoplay it keeps its controls, or it could never be played
|
|
64
|
+
values.controls = media.hasAttribute('controls') || !values.autoplay;
|
|
65
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
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/video-properties
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../types/index";
|
|
10
|
+
/**
|
|
11
|
+
* Run `insert`, which inserts media at the cursor, with the cursor after
|
|
12
|
+
* `replaced`, and put what it inserts in place of `replaced`
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
export declare function replaceMedia(j: IJodit, replaced: HTMLElement, insert: () => void): void;
|
|
@@ -0,0 +1,97 @@
|
|
|
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 { Dom } from "../../core/dom/dom.js";
|
|
7
|
+
import { attr } from "../../core/helpers/utils/attr.js";
|
|
8
|
+
import { css } from "../../core/helpers/utils/css.js";
|
|
9
|
+
import { editedMedia, ownSize, readValues } from "./readers.js";
|
|
10
|
+
import { applyValues } from "./writers.js";
|
|
11
|
+
/**
|
|
12
|
+
* Give `media`, in `outer`, the classes, inline styles, size and playback
|
|
13
|
+
* settings of `old`, in `oldOuter`. It keeps its own source and poster.
|
|
14
|
+
*/
|
|
15
|
+
function takeOver(j, oldOuter, old, outer, media) {
|
|
16
|
+
var _a;
|
|
17
|
+
const state = {
|
|
18
|
+
target: oldOuter,
|
|
19
|
+
media: old,
|
|
20
|
+
ratio: 1,
|
|
21
|
+
sizeIsLocked: true,
|
|
22
|
+
values: {
|
|
23
|
+
width: '',
|
|
24
|
+
height: '',
|
|
25
|
+
poster: '',
|
|
26
|
+
autoplay: false,
|
|
27
|
+
loop: false,
|
|
28
|
+
muted: false,
|
|
29
|
+
controls: true
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
readValues(state);
|
|
33
|
+
const pairs = [[old, media]];
|
|
34
|
+
// A wrapper kept in the content, which holds the alignment
|
|
35
|
+
if (oldOuter !== old &&
|
|
36
|
+
outer !== media &&
|
|
37
|
+
oldOuter.nodeName === outer.nodeName) {
|
|
38
|
+
pairs.push([oldOuter, outer]);
|
|
39
|
+
}
|
|
40
|
+
pairs.forEach(([from, to]) => {
|
|
41
|
+
['class', 'style'].forEach(name => attr(to, name, attr(from, name)));
|
|
42
|
+
});
|
|
43
|
+
// A video's size is CSS and an embed's its attributes, so the writer sizes
|
|
44
|
+
// one that's a different element
|
|
45
|
+
if (old.nodeName !== media.nodeName) {
|
|
46
|
+
css(media, { width: null, height: null });
|
|
47
|
+
if (!((_a = attr(media, 'style')) === null || _a === void 0 ? void 0 : _a.trim())) {
|
|
48
|
+
attr(media, 'style', null);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
state.media = media;
|
|
52
|
+
state.values.poster = attr(media, 'poster') || '';
|
|
53
|
+
applyValues(j, state, Boolean(ownSize(old, 'width') || ownSize(old, 'height')));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run `insert`, which inserts media at the cursor, with the cursor after
|
|
57
|
+
* `replaced`, and put what it inserts in place of `replaced`
|
|
58
|
+
* @private
|
|
59
|
+
*/
|
|
60
|
+
export function replaceMedia(j, replaced, insert) {
|
|
61
|
+
const inserted = [];
|
|
62
|
+
const collect = (node) => {
|
|
63
|
+
inserted.push(node);
|
|
64
|
+
};
|
|
65
|
+
j.history.snapshot.transaction(() => {
|
|
66
|
+
j.s.focus();
|
|
67
|
+
j.s.setCursorAfter(replaced);
|
|
68
|
+
j.e.on('afterInsertNode', collect);
|
|
69
|
+
try {
|
|
70
|
+
insert();
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
j.e.off('afterInsertNode', collect);
|
|
74
|
+
}
|
|
75
|
+
const [outer] = inserted;
|
|
76
|
+
if (!Dom.isHTMLElement(outer)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const old = editedMedia(replaced);
|
|
80
|
+
const media = editedMedia(outer);
|
|
81
|
+
if (old && media) {
|
|
82
|
+
takeOver(j, replaced, old, outer, media);
|
|
83
|
+
}
|
|
84
|
+
// The resizer can have put an embed in its own wrapper already
|
|
85
|
+
const placed = Dom.isHTMLElement(outer.parentElement) &&
|
|
86
|
+
attr(outer.parentElement, 'data-jodit-temp')
|
|
87
|
+
? outer.parentElement
|
|
88
|
+
: outer;
|
|
89
|
+
// Where the old one was, since media Jodit counts as blocks can be put
|
|
90
|
+
// after the paragraph
|
|
91
|
+
Dom.before(replaced, placed);
|
|
92
|
+
Dom.safeRemove(replaced);
|
|
93
|
+
j.s.setCursorAfter(placed);
|
|
94
|
+
});
|
|
95
|
+
j.synchronizeValues();
|
|
96
|
+
j.e.fire('closeAllPopups');
|
|
97
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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/video-properties
|
|
8
|
+
*/
|
|
9
|
+
import type { IJodit } from "../../../types/index";
|
|
10
|
+
import { UIElement } from "../../../core/ui/element";
|
|
11
|
+
import type { VideoPropertiesAPI, VideoPropertiesState } from "../interface";
|
|
12
|
+
/** @private */
|
|
13
|
+
export declare class UIVideoPropertiesForm extends UIElement<IJodit> {
|
|
14
|
+
private state;
|
|
15
|
+
private handlers;
|
|
16
|
+
className(): string;
|
|
17
|
+
constructor(jodit: IJodit, state: VideoPropertiesState, handlers: VideoPropertiesAPI);
|
|
18
|
+
protected render(): string;
|
|
19
|
+
private input;
|
|
20
|
+
private show;
|
|
21
|
+
/**
|
|
22
|
+
* A video has every field, an embed only its size, and audio only its
|
|
23
|
+
* playback settings
|
|
24
|
+
*/
|
|
25
|
+
protected onStateMediaChange(): void;
|
|
26
|
+
private showPreview;
|
|
27
|
+
protected hideChangePoster(): void;
|
|
28
|
+
protected onStatePosterChange(): void;
|
|
29
|
+
protected onPosterChange(): void;
|
|
30
|
+
protected onChangePosterClick(e: MouseEvent): void;
|
|
31
|
+
protected onRemovePosterClick(): void;
|
|
32
|
+
protected onStateSizeIsLockedChange(): void;
|
|
33
|
+
protected onLockSizeClick(): void;
|
|
34
|
+
protected onStateSizeChange(): void;
|
|
35
|
+
protected onSizeInput(e: Event): void;
|
|
36
|
+
/**
|
|
37
|
+
* Autoplay mutes it, and it keeps its controls unless it autoplays
|
|
38
|
+
*/
|
|
39
|
+
protected onStateFlagsChange(): void;
|
|
40
|
+
protected onFlagChange(e: Event): void;
|
|
41
|
+
}
|