jodit 4.18.3 → 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.
Files changed (187) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/es2015/jodit.css +60 -1
  3. package/es2015/jodit.fat.min.css +1 -1
  4. package/es2015/jodit.fat.min.js +35 -10
  5. package/es2015/jodit.js +968 -152
  6. package/es2015/jodit.min.css +1 -1
  7. package/es2015/jodit.min.js +41 -16
  8. package/es2015/plugins/debug/debug.css +1 -1
  9. package/es2015/plugins/debug/debug.js +1 -1
  10. package/es2015/plugins/debug/debug.min.js +1 -1
  11. package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
  12. package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
  13. package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
  14. package/es2018/jodit.fat.min.css +1 -1
  15. package/es2018/jodit.fat.min.js +33 -8
  16. package/es2018/jodit.min.css +1 -1
  17. package/es2018/jodit.min.js +33 -8
  18. package/es2018/plugins/debug/debug.min.js +1 -1
  19. package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
  20. package/es2021/jodit.css +60 -1
  21. package/es2021/jodit.fat.min.css +1 -1
  22. package/es2021/jodit.fat.min.js +36 -11
  23. package/es2021/jodit.js +958 -150
  24. package/es2021/jodit.min.css +1 -1
  25. package/es2021/jodit.min.js +36 -11
  26. package/es2021/plugins/debug/debug.css +1 -1
  27. package/es2021/plugins/debug/debug.js +1 -1
  28. package/es2021/plugins/debug/debug.min.js +1 -1
  29. package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
  30. package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
  31. package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
  32. package/es2021.en/jodit.css +60 -1
  33. package/es2021.en/jodit.fat.min.css +1 -1
  34. package/es2021.en/jodit.fat.min.js +36 -11
  35. package/es2021.en/jodit.js +932 -124
  36. package/es2021.en/jodit.min.css +1 -1
  37. package/es2021.en/jodit.min.js +51 -26
  38. package/es2021.en/plugins/debug/debug.css +1 -1
  39. package/es2021.en/plugins/debug/debug.js +1 -1
  40. package/es2021.en/plugins/debug/debug.min.js +1 -1
  41. package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
  42. package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
  43. package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
  44. package/es5/jodit.css +76 -2
  45. package/es5/jodit.fat.min.css +1 -1
  46. package/es5/jodit.fat.min.js +2 -2
  47. package/es5/jodit.js +1103 -155
  48. package/es5/jodit.min.css +3 -3
  49. package/es5/jodit.min.js +2 -2
  50. package/es5/plugins/debug/debug.css +1 -1
  51. package/es5/plugins/debug/debug.js +1 -1
  52. package/es5/plugins/debug/debug.min.js +1 -1
  53. package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
  54. package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
  55. package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
  56. package/es5/polyfills.fat.min.js +1 -1
  57. package/es5/polyfills.js +1 -1
  58. package/es5/polyfills.min.js +1 -1
  59. package/esm/config.d.ts +25 -26
  60. package/esm/config.js +19 -21
  61. package/esm/core/constants.js +1 -1
  62. package/esm/core/helpers/utils/align.d.ts +1 -1
  63. package/esm/core/helpers/utils/align.js +2 -3
  64. package/esm/jodit.js +14 -4
  65. package/esm/langs/ar.d.ts +7 -0
  66. package/esm/langs/ar.js +8 -1
  67. package/esm/langs/az.d.ts +7 -0
  68. package/esm/langs/az.js +8 -1
  69. package/esm/langs/cs_cz.d.ts +7 -0
  70. package/esm/langs/cs_cz.js +9 -1
  71. package/esm/langs/de.d.ts +7 -0
  72. package/esm/langs/de.js +8 -1
  73. package/esm/langs/es.d.ts +7 -0
  74. package/esm/langs/es.js +8 -1
  75. package/esm/langs/fa.d.ts +7 -0
  76. package/esm/langs/fa.js +8 -1
  77. package/esm/langs/fi.d.ts +7 -0
  78. package/esm/langs/fi.js +8 -1
  79. package/esm/langs/fr.d.ts +7 -0
  80. package/esm/langs/fr.js +8 -1
  81. package/esm/langs/he.d.ts +7 -0
  82. package/esm/langs/he.js +8 -1
  83. package/esm/langs/hu.d.ts +7 -0
  84. package/esm/langs/hu.js +8 -1
  85. package/esm/langs/id.d.ts +7 -0
  86. package/esm/langs/id.js +8 -1
  87. package/esm/langs/it.d.ts +7 -0
  88. package/esm/langs/it.js +8 -1
  89. package/esm/langs/ja.d.ts +7 -0
  90. package/esm/langs/ja.js +8 -1
  91. package/esm/langs/ko.d.ts +7 -0
  92. package/esm/langs/ko.js +8 -1
  93. package/esm/langs/mn.d.ts +7 -0
  94. package/esm/langs/mn.js +8 -1
  95. package/esm/langs/nl.d.ts +7 -0
  96. package/esm/langs/nl.js +8 -1
  97. package/esm/langs/no.d.ts +7 -0
  98. package/esm/langs/no.js +8 -1
  99. package/esm/langs/pl.d.ts +7 -0
  100. package/esm/langs/pl.js +8 -1
  101. package/esm/langs/pt_br.d.ts +7 -0
  102. package/esm/langs/pt_br.js +8 -1
  103. package/esm/langs/ru.d.ts +7 -0
  104. package/esm/langs/ru.js +8 -1
  105. package/esm/langs/sk.d.ts +7 -0
  106. package/esm/langs/sk.js +8 -1
  107. package/esm/langs/sv.d.ts +7 -0
  108. package/esm/langs/sv.js +8 -1
  109. package/esm/langs/tr.d.ts +7 -0
  110. package/esm/langs/tr.js +8 -1
  111. package/esm/langs/ua.d.ts +7 -0
  112. package/esm/langs/ua.js +8 -1
  113. package/esm/langs/zh_cn.d.ts +7 -0
  114. package/esm/langs/zh_cn.js +8 -1
  115. package/esm/langs/zh_tw.d.ts +7 -0
  116. package/esm/langs/zh_tw.js +8 -1
  117. package/esm/plugins/all.d.ts +1 -0
  118. package/esm/plugins/all.js +1 -0
  119. package/esm/plugins/image-processor/image-processor.d.ts +4 -1
  120. package/esm/plugins/image-processor/image-processor.js +9 -3
  121. package/esm/plugins/image-properties/readers/align.d.ts +2 -2
  122. package/esm/plugins/index.d.ts +1 -0
  123. package/esm/plugins/inline-popup/config/items/iframe.d.ts +9 -1
  124. package/esm/plugins/inline-popup/config/items/iframe.js +15 -0
  125. package/esm/plugins/media/media.js +16 -7
  126. package/esm/plugins/resizer/config.d.ts +5 -3
  127. package/esm/plugins/resizer/config.js +8 -2
  128. package/esm/plugins/resizer/resizer.d.ts +10 -0
  129. package/esm/plugins/resizer/resizer.js +64 -15
  130. package/esm/plugins/video/config.d.ts +6 -0
  131. package/esm/plugins/video/config.js +77 -65
  132. package/esm/plugins/video-properties/interface.d.ts +31 -0
  133. package/esm/plugins/video-properties/interface.js +6 -0
  134. package/esm/plugins/video-properties/readers.d.ts +26 -0
  135. package/esm/plugins/video-properties/readers.js +65 -0
  136. package/esm/plugins/video-properties/replace.d.ts +15 -0
  137. package/esm/plugins/video-properties/replace.js +97 -0
  138. package/esm/plugins/video-properties/ui/ui-video-form.d.ts +41 -0
  139. package/esm/plugins/video-properties/ui/ui-video-form.js +228 -0
  140. package/esm/plugins/video-properties/video-properties.d.ts +37 -0
  141. package/esm/plugins/video-properties/video-properties.js +175 -0
  142. package/esm/plugins/video-properties/writers.d.ts +15 -0
  143. package/esm/plugins/video-properties/writers.js +73 -0
  144. package/esm/types/types.d.ts +1 -1
  145. package/package.json +1 -1
  146. package/types/config.d.ts +25 -26
  147. package/types/core/helpers/utils/align.d.ts +1 -1
  148. package/types/langs/ar.d.ts +7 -0
  149. package/types/langs/az.d.ts +7 -0
  150. package/types/langs/cs_cz.d.ts +7 -0
  151. package/types/langs/de.d.ts +7 -0
  152. package/types/langs/es.d.ts +7 -0
  153. package/types/langs/fa.d.ts +7 -0
  154. package/types/langs/fi.d.ts +7 -0
  155. package/types/langs/fr.d.ts +7 -0
  156. package/types/langs/he.d.ts +7 -0
  157. package/types/langs/hu.d.ts +7 -0
  158. package/types/langs/id.d.ts +7 -0
  159. package/types/langs/it.d.ts +7 -0
  160. package/types/langs/ja.d.ts +7 -0
  161. package/types/langs/ko.d.ts +7 -0
  162. package/types/langs/mn.d.ts +7 -0
  163. package/types/langs/nl.d.ts +7 -0
  164. package/types/langs/no.d.ts +7 -0
  165. package/types/langs/pl.d.ts +7 -0
  166. package/types/langs/pt_br.d.ts +7 -0
  167. package/types/langs/ru.d.ts +7 -0
  168. package/types/langs/sk.d.ts +7 -0
  169. package/types/langs/sv.d.ts +7 -0
  170. package/types/langs/tr.d.ts +7 -0
  171. package/types/langs/ua.d.ts +7 -0
  172. package/types/langs/zh_cn.d.ts +7 -0
  173. package/types/langs/zh_tw.d.ts +7 -0
  174. package/types/plugins/image-processor/image-processor.d.ts +4 -1
  175. package/types/plugins/image-properties/readers/align.d.ts +2 -2
  176. package/types/plugins/index.d.ts +1 -0
  177. package/types/plugins/inline-popup/config/items/iframe.d.ts +9 -1
  178. package/types/plugins/resizer/config.d.ts +5 -3
  179. package/types/plugins/resizer/resizer.d.ts +10 -0
  180. package/types/plugins/video/config.d.ts +6 -0
  181. package/types/plugins/video-properties/interface.d.ts +31 -0
  182. package/types/plugins/video-properties/readers.d.ts +26 -0
  183. package/types/plugins/video-properties/replace.d.ts +15 -0
  184. package/types/plugins/video-properties/ui/ui-video-form.d.ts +41 -0
  185. package/types/plugins/video-properties/video-properties.d.ts +37 -0
  186. package/types/plugins/video-properties/writers.d.ts +15 -0
  187. package/types/types/types.d.ts +1 -1
@@ -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
+ }
@@ -0,0 +1,228 @@
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
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
9
+ r = Reflect.decorate(decorators, target, key, desc);
10
+ else
11
+ for (var i = decorators.length - 1; i >= 0; i--)
12
+ if (d = decorators[i])
13
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
14
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
15
+ };
16
+ import { component } from "../../../core/decorators/component/component.js";
17
+ import { hook } from "../../../core/decorators/hook/hook.js";
18
+ import { watch } from "../../../core/decorators/watch/watch.js";
19
+ import { Dom } from "../../../core/dom/dom.js";
20
+ import { isNumeric } from "../../../core/helpers/checker/is-numeric.js";
21
+ import { attr } from "../../../core/helpers/utils/attr.js";
22
+ import { css } from "../../../core/helpers/utils/css.js";
23
+ import { UIElement } from "../../../core/ui/element.js";
24
+ import { Icon } from "../../../core/ui/icon.js";
25
+ const flags = {
26
+ autoplay: 'Autoplay',
27
+ loop: 'Loop',
28
+ muted: 'Muted',
29
+ controls: 'Controls'
30
+ };
31
+ const checkbox = ([flag, label]) => `<label class="jodit_vertical_middle">
32
+ <input type="checkbox" class="jodit-checkbox &__${flag}"/>
33
+ <span>~${label}~</span>
34
+ </label>`;
35
+ /** @private */
36
+ let UIVideoPropertiesForm = class UIVideoPropertiesForm extends UIElement {
37
+ className() {
38
+ return 'UIVideoPropertiesForm';
39
+ }
40
+ constructor(jodit, state, handlers) {
41
+ super(jodit);
42
+ this.state = state;
43
+ this.handlers = handlers;
44
+ }
45
+ render() {
46
+ return `<form>
47
+ <div class="jodit-form__group &__previewBox">
48
+ <img class="&__preview" alt=""/>
49
+ </div>
50
+ <div class="jodit-form__group &__sizes">
51
+ <input type="text" class="jodit-input &__width" placeholder="~Width~" aria-label="~Width~"/>
52
+ <a class="&__lockSize">*lock*</a>
53
+ <input type="text" class="jodit-input &__height" placeholder="~Height~" aria-label="~Height~"/>
54
+ </div>
55
+ <div class="jodit-form__group &__editPoster">
56
+ <label>~Poster~</label>
57
+ <div class="jodit-input_group">
58
+ <input type="text" class="jodit-input &__poster" placeholder="https://"/>
59
+ <div class="jodit-input_group-buttons">
60
+ <a class="jodit-button &__changePoster" title="~Upload~">*image*</a>
61
+ <a class="jodit-button &__removePoster" title="~Remove~">*bin*</a>
62
+ </div>
63
+ </div>
64
+ </div>
65
+ <div class="jodit-form__group &__playback">
66
+ ${Object.entries(flags).map(checkbox).join('')}
67
+ </div>
68
+ </form>`;
69
+ }
70
+ input(name) {
71
+ return this.getElm(name);
72
+ }
73
+ show(name, shown) {
74
+ css(this.getElm(name), 'display', shown ? null : 'none');
75
+ }
76
+ /**
77
+ * A video has every field, an embed only its size, and audio only its
78
+ * playback settings
79
+ */
80
+ onStateMediaChange() {
81
+ const { media } = this.state;
82
+ this.show('editPoster', Dom.isTag(media, 'video'));
83
+ this.show('sizes', !Dom.isTag(media, 'audio'));
84
+ this.show('playback', !Dom.isTag(media, 'iframe'));
85
+ this.showPreview();
86
+ }
87
+ // A video's poster, when it has one
88
+ showPreview() {
89
+ const { media, values } = this.state;
90
+ const shown = Dom.isTag(media, 'video') && Boolean(values.poster);
91
+ this.show('previewBox', shown);
92
+ attr(this.getElm('preview'), 'src', shown ? values.poster : null);
93
+ }
94
+ hideChangePoster() {
95
+ const { uploader, filebrowser } = this.j.o;
96
+ // What FileSelectorWidget offers
97
+ const canUpload = uploader.showTabInFileSelector !== false &&
98
+ Boolean(uploader.url ||
99
+ uploader.insertImageAsBase64URI ||
100
+ uploader.customUploadFunction);
101
+ const canBrowse = Boolean(filebrowser.ajax.url || filebrowser.items.url);
102
+ this.show('changePoster', canUpload || canBrowse);
103
+ }
104
+ onStatePosterChange() {
105
+ const { poster } = this.state.values;
106
+ this.input('poster').value = poster;
107
+ this.show('removePoster', Boolean(poster));
108
+ this.showPreview();
109
+ }
110
+ onPosterChange() {
111
+ this.state.values.poster = this.input('poster').value;
112
+ }
113
+ onChangePosterClick(e) {
114
+ this.handlers.openPosterPopup(this.getElm('changePoster'));
115
+ e.stopPropagation();
116
+ }
117
+ onRemovePosterClick() {
118
+ this.state.values.poster = '';
119
+ }
120
+ onStateSizeIsLockedChange() {
121
+ this.getElm('lockSize').innerHTML = Icon.get(this.state.sizeIsLocked ? 'lock' : 'unlock');
122
+ }
123
+ onLockSizeClick() {
124
+ const { state } = this;
125
+ const { values } = state;
126
+ state.sizeIsLocked = !state.sizeIsLocked;
127
+ if (state.sizeIsLocked && isNumeric(values.width)) {
128
+ values.height = Math.round(parseFloat(values.width.toString()) / state.ratio);
129
+ }
130
+ }
131
+ onStateSizeChange() {
132
+ const { values } = this.state;
133
+ // Not the field being typed in
134
+ ['width', 'height'].forEach(key => {
135
+ const input = this.input(key);
136
+ if (input !== this.j.od.activeElement) {
137
+ input.value = values[key].toString();
138
+ }
139
+ });
140
+ }
141
+ onSizeInput(e) {
142
+ const { state } = this;
143
+ const { values } = state;
144
+ // Both read first, since setting one rewrites the other's field
145
+ const width = this.input('width').value;
146
+ const height = this.input('height').value;
147
+ if (!state.sizeIsLocked || !isNumeric(width) || !isNumeric(height)) {
148
+ values.width = width;
149
+ values.height = height;
150
+ return;
151
+ }
152
+ const w = parseFloat(width);
153
+ const h = parseFloat(height);
154
+ if (e.target === this.input('width')) {
155
+ values.width = w;
156
+ values.height = Math.round(w / state.ratio);
157
+ }
158
+ else {
159
+ values.width = Math.round(h * state.ratio);
160
+ values.height = h;
161
+ }
162
+ }
163
+ /**
164
+ * Autoplay mutes it, and it keeps its controls unless it autoplays
165
+ */
166
+ onStateFlagsChange() {
167
+ const { values } = this.state;
168
+ this.input('autoplay').checked = values.autoplay;
169
+ this.input('loop').checked = values.loop;
170
+ this.input('muted').checked = values.muted || values.autoplay;
171
+ this.input('muted').disabled = values.autoplay;
172
+ this.input('controls').checked = values.controls || !values.autoplay;
173
+ this.input('controls').disabled = !values.autoplay;
174
+ }
175
+ onFlagChange(e) {
176
+ Object.keys(flags).forEach(flag => {
177
+ const input = this.input(flag);
178
+ if (e.target === input) {
179
+ this.state.values[flag] = input.checked;
180
+ }
181
+ });
182
+ }
183
+ };
184
+ __decorate([
185
+ hook('ready'),
186
+ watch('state.media')
187
+ ], UIVideoPropertiesForm.prototype, "onStateMediaChange", null);
188
+ __decorate([
189
+ hook('ready')
190
+ ], UIVideoPropertiesForm.prototype, "hideChangePoster", null);
191
+ __decorate([
192
+ hook('ready'),
193
+ watch('state.values.poster')
194
+ ], UIVideoPropertiesForm.prototype, "onStatePosterChange", null);
195
+ __decorate([
196
+ watch('poster:change')
197
+ ], UIVideoPropertiesForm.prototype, "onPosterChange", null);
198
+ __decorate([
199
+ watch('changePoster:click')
200
+ ], UIVideoPropertiesForm.prototype, "onChangePosterClick", null);
201
+ __decorate([
202
+ watch('removePoster:click')
203
+ ], UIVideoPropertiesForm.prototype, "onRemovePosterClick", null);
204
+ __decorate([
205
+ hook('ready'),
206
+ watch('state.sizeIsLocked')
207
+ ], UIVideoPropertiesForm.prototype, "onStateSizeIsLockedChange", null);
208
+ __decorate([
209
+ watch('lockSize:click')
210
+ ], UIVideoPropertiesForm.prototype, "onLockSizeClick", null);
211
+ __decorate([
212
+ hook('ready'),
213
+ watch(['state.values.width', 'state.values.height'])
214
+ ], UIVideoPropertiesForm.prototype, "onStateSizeChange", null);
215
+ __decorate([
216
+ watch(['width:input', 'height:input', 'width:change', 'height:change'])
217
+ ], UIVideoPropertiesForm.prototype, "onSizeInput", null);
218
+ __decorate([
219
+ hook('ready'),
220
+ watch(Object.keys(flags).map(flag => `state.values.${flag}`))
221
+ ], UIVideoPropertiesForm.prototype, "onStateFlagsChange", null);
222
+ __decorate([
223
+ watch(Object.keys(flags).map(flag => `${flag}:change`))
224
+ ], UIVideoPropertiesForm.prototype, "onFlagChange", null);
225
+ UIVideoPropertiesForm = __decorate([
226
+ component
227
+ ], UIVideoPropertiesForm);
228
+ export { UIVideoPropertiesForm };
@@ -0,0 +1,37 @@
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 { Plugin } from "../../core/plugin/plugin";
7
+ import type { VideoPropertiesState } from "./interface";
8
+ /**
9
+ * Show a dialog with the size, poster and playback settings of a video, an
10
+ * embed or audio. The media popup's Edit button opens it:
11
+ *
12
+ * ```javascript
13
+ * editor.events.fire('openVideoProperties', video);
14
+ * ```
15
+ */
16
+ export declare class videoProperties extends Plugin {
17
+ protected state: VideoPropertiesState;
18
+ private __readSize;
19
+ private get __size();
20
+ private get form();
21
+ private get dialog();
22
+ private get __buttons();
23
+ /**
24
+ * Open the dialog for the media `target` is, or is the wrapper of
25
+ */
26
+ protected open(target: HTMLElement): void;
27
+ /**
28
+ * The video popup's tabs for the media popup's Replace: what they insert
29
+ * takes the place of the media `target` is, or is the wrapper of
30
+ */
31
+ protected onGenerateReplaceVideoTabs(target: HTMLElement, close: () => void): HTMLElement;
32
+ private __openPosterPopup;
33
+ /** @override */
34
+ protected afterInit(): void;
35
+ /** @override */
36
+ protected beforeDestruct(): void;
37
+ }
@@ -0,0 +1,175 @@
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
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
9
+ r = Reflect.decorate(decorators, target, key, desc);
10
+ else
11
+ for (var i = decorators.length - 1; i >= 0; i--)
12
+ if (d = decorators[i])
13
+ r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
14
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
15
+ };
16
+ import { cache, cached, watch } from "../../core/decorators/index.js";
17
+ import { Dom } from "../../core/dom/dom.js";
18
+ import { pluginSystem } from "../../core/global.js";
19
+ import { isArray } from "../../core/helpers/checker/is-array.js";
20
+ import { position } from "../../core/helpers/size/position.js";
21
+ import { markOwner } from "../../core/helpers/utils/utils.js";
22
+ import { Plugin } from "../../core/plugin/plugin.js";
23
+ import { Button } from "../../core/ui/button/index.js";
24
+ import { Popup } from "../../core/ui/popup/popup.js";
25
+ import { FileSelectorWidget } from "../../modules/widget/file-selector/file-selector.js";
26
+ import { UIVideoPropertiesForm } from "./ui/ui-video-form.js";
27
+ import { editedMedia, readValues } from "./readers.js";
28
+ import { replaceMedia } from "./replace.js";
29
+ import { applyValues } from "./writers.js";
30
+ import { videoTabs } from "../video/config.js";
31
+ /**
32
+ * Show a dialog with the size, poster and playback settings of a video, an
33
+ * embed or audio. The media popup's Edit button opens it:
34
+ *
35
+ * ```javascript
36
+ * editor.events.fire('openVideoProperties', video);
37
+ * ```
38
+ */
39
+ export class videoProperties extends Plugin {
40
+ constructor() {
41
+ super(...arguments);
42
+ this.state = {
43
+ target: this.j.c.element('video'),
44
+ media: this.j.c.element('video'),
45
+ ratio: 1,
46
+ sizeIsLocked: true,
47
+ values: {
48
+ width: '',
49
+ height: '',
50
+ poster: '',
51
+ autoplay: false,
52
+ loop: false,
53
+ muted: false,
54
+ controls: true
55
+ }
56
+ };
57
+ // The size as it was read, so an unchanged one isn't written
58
+ this.__readSize = '';
59
+ }
60
+ get __size() {
61
+ const { width, height } = this.state.values;
62
+ return `${width}x${height}`;
63
+ }
64
+ get form() {
65
+ return new UIVideoPropertiesForm(this.j, this.state, {
66
+ openPosterPopup: target => this.__openPosterPopup(target)
67
+ });
68
+ }
69
+ get dialog() {
70
+ const { j } = this;
71
+ const dialog = j.dlg({
72
+ minWidth: Math.min(400, screen.width),
73
+ buttons: ['dialog.close']
74
+ });
75
+ const buttons = this.__buttons;
76
+ buttons.check.onAction(() => {
77
+ applyValues(j, this.state, this.__size !== this.__readSize);
78
+ j.synchronizeValues();
79
+ dialog.close();
80
+ });
81
+ buttons.remove.onAction(() => {
82
+ j.s.removeNode(this.state.target);
83
+ dialog.close();
84
+ });
85
+ buttons.cancel.onAction(() => {
86
+ dialog.close();
87
+ });
88
+ dialog.setContent(this.form);
89
+ dialog.setFooter([[buttons.cancel, buttons.remove], buttons.check]);
90
+ markOwner(j, dialog.container);
91
+ return dialog;
92
+ }
93
+ get __buttons() {
94
+ const { j } = this;
95
+ return {
96
+ check: Button(j, 'ok', 'Apply', 'primary'),
97
+ remove: Button(j, 'bin', 'Delete'),
98
+ cancel: Button(j, 'cancel', 'Cancel')
99
+ };
100
+ }
101
+ /**
102
+ * Open the dialog for the media `target` is, or is the wrapper of
103
+ */
104
+ open(target) {
105
+ const media = editedMedia(target);
106
+ if (!media) {
107
+ return;
108
+ }
109
+ this.state.target = target;
110
+ this.state.media = media;
111
+ readValues(this.state);
112
+ this.__readSize = this.__size;
113
+ this.dialog.setHeader(this.j.i18n(Dom.isTag(media, 'audio')
114
+ ? 'Audio properties'
115
+ : 'Video properties'));
116
+ this.dialog.open().setModal(true).setPosition();
117
+ }
118
+ /**
119
+ * The video popup's tabs for the media popup's Replace: what they insert
120
+ * takes the place of the media `target` is, or is the wrapper of
121
+ */
122
+ onGenerateReplaceVideoTabs(target, close) {
123
+ return videoTabs(this.j, close, insert => replaceMedia(this.j, target, insert));
124
+ }
125
+ __openPosterPopup(button) {
126
+ const { j, state } = this;
127
+ const popup = new Popup(this.dialog);
128
+ const close = () => {
129
+ popup.close();
130
+ popup.destruct();
131
+ };
132
+ popup
133
+ .setContent(FileSelectorWidget(j, {
134
+ upload: (data) => {
135
+ if (data.files && data.files.length) {
136
+ state.values.poster =
137
+ data.baseurl + data.files[0];
138
+ }
139
+ close();
140
+ },
141
+ filebrowser: (data) => {
142
+ if (isArray(data.files) && data.files.length) {
143
+ state.values.poster = data.files[0];
144
+ close();
145
+ }
146
+ }
147
+ }, null, close))
148
+ .open(() => position(button));
149
+ }
150
+ /** @override */
151
+ afterInit() { }
152
+ /** @override */
153
+ beforeDestruct() {
154
+ var _a, _b, _c;
155
+ Object.values((_a = cached(this, '__buttons')) !== null && _a !== void 0 ? _a : {}).forEach(b => b.destruct());
156
+ (_b = cached(this, 'dialog')) === null || _b === void 0 ? void 0 : _b.destruct();
157
+ (_c = cached(this, 'form')) === null || _c === void 0 ? void 0 : _c.destruct();
158
+ }
159
+ }
160
+ __decorate([
161
+ cache
162
+ ], videoProperties.prototype, "form", null);
163
+ __decorate([
164
+ cache
165
+ ], videoProperties.prototype, "dialog", null);
166
+ __decorate([
167
+ cache
168
+ ], videoProperties.prototype, "__buttons", null);
169
+ __decorate([
170
+ watch(':openVideoProperties')
171
+ ], videoProperties.prototype, "open", null);
172
+ __decorate([
173
+ watch(':generateReplaceVideoTabs')
174
+ ], videoProperties.prototype, "onGenerateReplaceVideoTabs", null);
175
+ pluginSystem.add('videoProperties', videoProperties);
@@ -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
+ import type { VideoPropertiesState } from "./interface";
11
+ /**
12
+ * Apply the dialog's values to the media
13
+ * @private
14
+ */
15
+ export declare function applyValues(j: IJodit, state: VideoPropertiesState, sizeChanged: boolean): void;
@@ -0,0 +1,73 @@
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, cssInline } from "../../core/helpers/utils/css.js";
9
+ import { ownSize } from "./readers.js";
10
+ import { normalSizeToString } from "../image-properties/utils/utils.js";
11
+ const cssSize = (value) => value === '' ? null : normalSizeToString(value);
12
+ // Sizes go on as the resizer writes them: an embed takes them as attributes,
13
+ // and a video as CSS, without a height while its ratio is kept, if it had none
14
+ function applySize(j, state) {
15
+ var _a;
16
+ const { media, values } = state;
17
+ if (Dom.isTag(media, 'iframe')) {
18
+ ['width', 'height'].forEach(key => {
19
+ attr(media, key, values[key] === '' ? null : values[key]);
20
+ if (cssInline(media, key)) {
21
+ css(media, key, cssSize(values[key]));
22
+ }
23
+ });
24
+ // The resizer's frame for an embed
25
+ const wrapper = media.parentElement;
26
+ if (wrapper && attr(wrapper, 'data-jodit_iframe_wrapper')) {
27
+ css(wrapper, {
28
+ width: media.offsetWidth,
29
+ height: media.offsetHeight
30
+ });
31
+ }
32
+ return;
33
+ }
34
+ const heightFollowsWidth = state.sizeIsLocked && !ownSize(media, 'height');
35
+ css(media, {
36
+ width: cssSize(values.width),
37
+ height: heightFollowsWidth ? null : cssSize(values.height)
38
+ });
39
+ if (!((_a = attr(media, 'style')) === null || _a === void 0 ? void 0 : _a.trim())) {
40
+ attr(media, 'style', null);
41
+ }
42
+ j.e.fire(media, 'changesize');
43
+ }
44
+ function setFlag(media, name, on) {
45
+ if (media.hasAttribute(name) !== on) {
46
+ attr(media, name, on ? '' : null);
47
+ }
48
+ }
49
+ /**
50
+ * Apply the dialog's values to the media
51
+ * @private
52
+ */
53
+ export function applyValues(j, state, sizeChanged) {
54
+ const { media, values } = state;
55
+ if (sizeChanged && !Dom.isTag(media, 'audio')) {
56
+ applySize(j, state);
57
+ }
58
+ if (Dom.isTag(media, 'iframe')) {
59
+ return;
60
+ }
61
+ if (Dom.isTag(media, 'video')) {
62
+ attr(media, 'poster', values.poster || null);
63
+ }
64
+ // Browsers only autoplay muted media, and playsinline keeps an iPhone from
65
+ // playing it full screen
66
+ setFlag(media, 'autoplay', values.autoplay);
67
+ setFlag(media, 'muted', values.autoplay || values.muted);
68
+ setFlag(media, 'loop', values.loop);
69
+ setFlag(media, 'controls', values.controls || !values.autoplay);
70
+ if (values.autoplay && Dom.isTag(media, 'video')) {
71
+ setFlag(media, 'playsinline', true);
72
+ }
73
+ }
@@ -193,7 +193,7 @@ export type ImageHAlign = 'normal' | 'left' | 'right' | 'center' | '';
193
193
  */
194
194
  export type HAlignClasses = Partial<Record<Exclude<ImageHAlign, ''>, string | string[]>>;
195
195
  /**
196
- * Class names for each image alignment, see `imageAlignClasses`
196
+ * @deprecated Use `HAlignClasses`
197
197
  */
198
198
  export type ImageAlignClasses = HAlignClasses;
199
199
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jodit",
3
- "version": "4.18.3",
3
+ "version": "4.18.4",
4
4
  "description": "Jodit is an awesome and useful wysiwyg editor with filebrowser",
5
5
  "main": "esm/index.js",
6
6
  "types": "types/index.d.ts",