@ckeditor/ckeditor5-image 47.6.1 → 48.0.0-alpha.0

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 (289) hide show
  1. package/LICENSE.md +1 -1
  2. package/ckeditor5-metadata.json +25 -25
  3. package/{src → dist}/autoimage.d.ts +4 -4
  4. package/{src → dist}/image/converters.d.ts +1 -1
  5. package/{src → dist}/image/imageblockediting.d.ts +2 -2
  6. package/{src → dist}/image/imageediting.d.ts +1 -1
  7. package/{src → dist}/image/imageinlineediting.d.ts +2 -2
  8. package/{src → dist}/image/imageloadobserver.d.ts +1 -1
  9. package/{src → dist}/image/imageplaceholder.d.ts +1 -1
  10. package/{src → dist}/image/imagetypecommand.d.ts +2 -2
  11. package/{src → dist}/image/insertimagecommand.d.ts +2 -2
  12. package/{src → dist}/image/replaceimagesourcecommand.d.ts +2 -2
  13. package/{src → dist}/image/ui/utils.d.ts +2 -2
  14. package/{src → dist}/image/utils.d.ts +2 -2
  15. package/{src → dist}/image.d.ts +1 -1
  16. package/{src → dist}/imageblock.d.ts +2 -2
  17. package/{src → dist}/imagecaption/imagecaptionediting.d.ts +2 -2
  18. package/{src → dist}/imagecaption/imagecaptionui.d.ts +1 -1
  19. package/{src → dist}/imagecaption/imagecaptionutils.d.ts +2 -2
  20. package/{src → dist}/imagecaption/toggleimagecaptioncommand.d.ts +1 -1
  21. package/{src → dist}/imagecaption.d.ts +1 -1
  22. package/{src → dist}/imageconfig.d.ts +25 -16
  23. package/{src → dist}/imageinline.d.ts +2 -2
  24. package/{src → dist}/imageinsert/imageinsertui.d.ts +3 -3
  25. package/{src → dist}/imageinsert/imageinsertviaurlui.d.ts +2 -2
  26. package/{src → dist}/imageinsert/ui/imageinsertformview.d.ts +2 -2
  27. package/{src → dist}/imageinsert/ui/imageinserturlview.d.ts +2 -2
  28. package/{src → dist}/imageinsert.d.ts +1 -1
  29. package/{src → dist}/imageinsertviaurl.d.ts +1 -1
  30. package/{src → dist}/imageresize/imagecustomresizeui.d.ts +2 -2
  31. package/{src → dist}/imageresize/imageresizebuttons.d.ts +1 -1
  32. package/{src → dist}/imageresize/imageresizeediting.d.ts +1 -1
  33. package/{src → dist}/imageresize/imageresizehandles.d.ts +2 -2
  34. package/{src → dist}/imageresize/resizeimagecommand.d.ts +1 -1
  35. package/{src → dist}/imageresize/ui/imagecustomresizeformview.d.ts +2 -4
  36. package/{src → dist}/imageresize/utils/getselectedimageeditornodes.d.ts +2 -2
  37. package/{src → dist}/imageresize/utils/getselectedimagepossibleresizerange.d.ts +1 -1
  38. package/{src → dist}/imageresize/utils/getselectedimagewidthinunits.d.ts +1 -1
  39. package/{src → dist}/imageresize.d.ts +1 -1
  40. package/{src → dist}/imagesizeattributes.d.ts +1 -1
  41. package/{src → dist}/imagestyle/converters.d.ts +2 -2
  42. package/{src → dist}/imagestyle/imagestylecommand.d.ts +2 -2
  43. package/{src → dist}/imagestyle/imagestyleediting.d.ts +1 -1
  44. package/{src → dist}/imagestyle/imagestyleui.d.ts +1 -1
  45. package/{src → dist}/imagestyle/utils.d.ts +1 -1
  46. package/{src → dist}/imagestyle.d.ts +1 -1
  47. package/{src → dist}/imagetextalternative/imagetextalternativecommand.d.ts +1 -1
  48. package/{src → dist}/imagetextalternative/imagetextalternativeediting.d.ts +1 -1
  49. package/{src → dist}/imagetextalternative/imagetextalternativeui.d.ts +2 -2
  50. package/{src → dist}/imagetextalternative/ui/textalternativeformview.d.ts +2 -4
  51. package/{src → dist}/imagetextalternative.d.ts +1 -1
  52. package/{src → dist}/imagetoolbar.d.ts +2 -2
  53. package/{src → dist}/imageupload/imageuploadediting.d.ts +5 -5
  54. package/{src → dist}/imageupload/imageuploadprogress.d.ts +1 -1
  55. package/{src → dist}/imageupload/imageuploadui.d.ts +1 -1
  56. package/{src → dist}/imageupload/uploadimagecommand.d.ts +2 -2
  57. package/{src → dist}/imageupload/utils.d.ts +1 -1
  58. package/{src → dist}/imageupload.d.ts +1 -1
  59. package/{src → dist}/imageutils.d.ts +2 -2
  60. package/dist/index-content.css +97 -100
  61. package/dist/index-editor.css +313 -190
  62. package/dist/index.css +388 -458
  63. package/dist/index.css.map +1 -1
  64. package/dist/index.js +1 -2
  65. package/dist/index.js.map +1 -1
  66. package/{src → dist}/pictureediting.d.ts +1 -1
  67. package/package.json +29 -53
  68. package/build/image.js +0 -5
  69. package/build/translations/af.js +0 -1
  70. package/build/translations/ar.js +0 -1
  71. package/build/translations/ast.js +0 -1
  72. package/build/translations/az.js +0 -1
  73. package/build/translations/be.js +0 -1
  74. package/build/translations/bg.js +0 -1
  75. package/build/translations/bn.js +0 -1
  76. package/build/translations/bs.js +0 -1
  77. package/build/translations/ca.js +0 -1
  78. package/build/translations/cs.js +0 -1
  79. package/build/translations/da.js +0 -1
  80. package/build/translations/de-ch.js +0 -1
  81. package/build/translations/de.js +0 -1
  82. package/build/translations/el.js +0 -1
  83. package/build/translations/en-au.js +0 -1
  84. package/build/translations/en-gb.js +0 -1
  85. package/build/translations/eo.js +0 -1
  86. package/build/translations/es-co.js +0 -1
  87. package/build/translations/es.js +0 -1
  88. package/build/translations/et.js +0 -1
  89. package/build/translations/eu.js +0 -1
  90. package/build/translations/fa.js +0 -1
  91. package/build/translations/fi.js +0 -1
  92. package/build/translations/fr.js +0 -1
  93. package/build/translations/gl.js +0 -1
  94. package/build/translations/gu.js +0 -1
  95. package/build/translations/he.js +0 -1
  96. package/build/translations/hi.js +0 -1
  97. package/build/translations/hr.js +0 -1
  98. package/build/translations/hu.js +0 -1
  99. package/build/translations/hy.js +0 -1
  100. package/build/translations/id.js +0 -1
  101. package/build/translations/it.js +0 -1
  102. package/build/translations/ja.js +0 -1
  103. package/build/translations/jv.js +0 -1
  104. package/build/translations/kk.js +0 -1
  105. package/build/translations/km.js +0 -1
  106. package/build/translations/kn.js +0 -1
  107. package/build/translations/ko.js +0 -1
  108. package/build/translations/ku.js +0 -1
  109. package/build/translations/lt.js +0 -1
  110. package/build/translations/lv.js +0 -1
  111. package/build/translations/ms.js +0 -1
  112. package/build/translations/nb.js +0 -1
  113. package/build/translations/ne.js +0 -1
  114. package/build/translations/nl.js +0 -1
  115. package/build/translations/no.js +0 -1
  116. package/build/translations/oc.js +0 -1
  117. package/build/translations/pl.js +0 -1
  118. package/build/translations/pt-br.js +0 -1
  119. package/build/translations/pt.js +0 -1
  120. package/build/translations/ro.js +0 -1
  121. package/build/translations/ru.js +0 -1
  122. package/build/translations/si.js +0 -1
  123. package/build/translations/sk.js +0 -1
  124. package/build/translations/sl.js +0 -1
  125. package/build/translations/sq.js +0 -1
  126. package/build/translations/sr-latn.js +0 -1
  127. package/build/translations/sr.js +0 -1
  128. package/build/translations/sv.js +0 -1
  129. package/build/translations/th.js +0 -1
  130. package/build/translations/ti.js +0 -1
  131. package/build/translations/tk.js +0 -1
  132. package/build/translations/tr.js +0 -1
  133. package/build/translations/tt.js +0 -1
  134. package/build/translations/ug.js +0 -1
  135. package/build/translations/uk.js +0 -1
  136. package/build/translations/ur.js +0 -1
  137. package/build/translations/uz.js +0 -1
  138. package/build/translations/vi.js +0 -1
  139. package/build/translations/zh-cn.js +0 -1
  140. package/build/translations/zh.js +0 -1
  141. package/lang/contexts.json +0 -48
  142. package/lang/translations/af.po +0 -196
  143. package/lang/translations/ar.po +0 -196
  144. package/lang/translations/ast.po +0 -196
  145. package/lang/translations/az.po +0 -196
  146. package/lang/translations/be.po +0 -196
  147. package/lang/translations/bg.po +0 -196
  148. package/lang/translations/bn.po +0 -196
  149. package/lang/translations/bs.po +0 -196
  150. package/lang/translations/ca.po +0 -196
  151. package/lang/translations/cs.po +0 -196
  152. package/lang/translations/da.po +0 -196
  153. package/lang/translations/de-ch.po +0 -196
  154. package/lang/translations/de.po +0 -196
  155. package/lang/translations/el.po +0 -196
  156. package/lang/translations/en-au.po +0 -196
  157. package/lang/translations/en-gb.po +0 -196
  158. package/lang/translations/en.po +0 -196
  159. package/lang/translations/eo.po +0 -196
  160. package/lang/translations/es-co.po +0 -196
  161. package/lang/translations/es.po +0 -196
  162. package/lang/translations/et.po +0 -196
  163. package/lang/translations/eu.po +0 -196
  164. package/lang/translations/fa.po +0 -196
  165. package/lang/translations/fi.po +0 -196
  166. package/lang/translations/fr.po +0 -196
  167. package/lang/translations/gl.po +0 -196
  168. package/lang/translations/gu.po +0 -196
  169. package/lang/translations/he.po +0 -196
  170. package/lang/translations/hi.po +0 -196
  171. package/lang/translations/hr.po +0 -196
  172. package/lang/translations/hu.po +0 -196
  173. package/lang/translations/hy.po +0 -196
  174. package/lang/translations/id.po +0 -196
  175. package/lang/translations/it.po +0 -196
  176. package/lang/translations/ja.po +0 -196
  177. package/lang/translations/jv.po +0 -196
  178. package/lang/translations/kk.po +0 -196
  179. package/lang/translations/km.po +0 -196
  180. package/lang/translations/kn.po +0 -196
  181. package/lang/translations/ko.po +0 -196
  182. package/lang/translations/ku.po +0 -196
  183. package/lang/translations/lt.po +0 -196
  184. package/lang/translations/lv.po +0 -196
  185. package/lang/translations/ms.po +0 -196
  186. package/lang/translations/nb.po +0 -196
  187. package/lang/translations/ne.po +0 -196
  188. package/lang/translations/nl.po +0 -196
  189. package/lang/translations/no.po +0 -196
  190. package/lang/translations/oc.po +0 -196
  191. package/lang/translations/pl.po +0 -196
  192. package/lang/translations/pt-br.po +0 -196
  193. package/lang/translations/pt.po +0 -196
  194. package/lang/translations/ro.po +0 -196
  195. package/lang/translations/ru.po +0 -196
  196. package/lang/translations/si.po +0 -196
  197. package/lang/translations/sk.po +0 -196
  198. package/lang/translations/sl.po +0 -196
  199. package/lang/translations/sq.po +0 -196
  200. package/lang/translations/sr-latn.po +0 -196
  201. package/lang/translations/sr.po +0 -196
  202. package/lang/translations/sv.po +0 -196
  203. package/lang/translations/th.po +0 -196
  204. package/lang/translations/ti.po +0 -196
  205. package/lang/translations/tk.po +0 -196
  206. package/lang/translations/tr.po +0 -196
  207. package/lang/translations/tt.po +0 -196
  208. package/lang/translations/ug.po +0 -196
  209. package/lang/translations/uk.po +0 -196
  210. package/lang/translations/ur.po +0 -196
  211. package/lang/translations/uz.po +0 -196
  212. package/lang/translations/vi.po +0 -196
  213. package/lang/translations/zh-cn.po +0 -196
  214. package/lang/translations/zh.po +0 -196
  215. package/src/augmentation.js +0 -5
  216. package/src/autoimage.js +0 -148
  217. package/src/image/converters.js +0 -236
  218. package/src/image/imageblockediting.js +0 -159
  219. package/src/image/imageediting.js +0 -69
  220. package/src/image/imageinlineediting.js +0 -178
  221. package/src/image/imageloadobserver.js +0 -52
  222. package/src/image/imageplaceholder.js +0 -119
  223. package/src/image/imagetypecommand.js +0 -84
  224. package/src/image/insertimagecommand.js +0 -125
  225. package/src/image/replaceimagesourcecommand.js +0 -75
  226. package/src/image/ui/utils.js +0 -46
  227. package/src/image/utils.js +0 -125
  228. package/src/image.js +0 -44
  229. package/src/imageblock.js +0 -44
  230. package/src/imagecaption/imagecaptionediting.js +0 -238
  231. package/src/imagecaption/imagecaptionui.js +0 -68
  232. package/src/imagecaption/imagecaptionutils.js +0 -68
  233. package/src/imagecaption/toggleimagecaptioncommand.js +0 -138
  234. package/src/imagecaption.js +0 -36
  235. package/src/imageconfig.js +0 -5
  236. package/src/imageinline.js +0 -44
  237. package/src/imageinsert/imageinsertui.js +0 -216
  238. package/src/imageinsert/imageinsertviaurlui.js +0 -175
  239. package/src/imageinsert/ui/imageinsertformview.js +0 -117
  240. package/src/imageinsert/ui/imageinserturlview.js +0 -102
  241. package/src/imageinsert.js +0 -43
  242. package/src/imageinsertviaurl.js +0 -41
  243. package/src/imageresize/imagecustomresizeui.js +0 -177
  244. package/src/imageresize/imageresizebuttons.js +0 -303
  245. package/src/imageresize/imageresizeediting.js +0 -206
  246. package/src/imageresize/imageresizehandles.js +0 -118
  247. package/src/imageresize/resizeimagecommand.js +0 -63
  248. package/src/imageresize/ui/imagecustomresizeformview.js +0 -264
  249. package/src/imageresize/utils/getselectedimageeditornodes.js +0 -25
  250. package/src/imageresize/utils/getselectedimagepossibleresizerange.js +0 -33
  251. package/src/imageresize/utils/getselectedimagewidthinunits.js +0 -42
  252. package/src/imageresize/utils/tryparsedimensionwithunit.js +0 -58
  253. package/src/imageresize.js +0 -38
  254. package/src/imagesizeattributes.js +0 -163
  255. package/src/imagestyle/converters.js +0 -118
  256. package/src/imagestyle/imagestylecommand.js +0 -117
  257. package/src/imagestyle/imagestyleediting.js +0 -127
  258. package/src/imagestyle/imagestyleui.js +0 -198
  259. package/src/imagestyle/utils.js +0 -333
  260. package/src/imagestyle.js +0 -42
  261. package/src/imagetextalternative/imagetextalternativecommand.js +0 -44
  262. package/src/imagetextalternative/imagetextalternativeediting.js +0 -41
  263. package/src/imagetextalternative/imagetextalternativeui.js +0 -183
  264. package/src/imagetextalternative/ui/textalternativeformview.js +0 -193
  265. package/src/imagetextalternative.js +0 -39
  266. package/src/imagetoolbar.js +0 -63
  267. package/src/imageupload/imageuploadediting.js +0 -482
  268. package/src/imageupload/imageuploadprogress.js +0 -222
  269. package/src/imageupload/imageuploadui.js +0 -135
  270. package/src/imageupload/uploadimagecommand.js +0 -110
  271. package/src/imageupload/utils.js +0 -114
  272. package/src/imageupload.js +0 -42
  273. package/src/imageutils.js +0 -309
  274. package/src/index.js +0 -67
  275. package/src/pictureediting.js +0 -136
  276. package/theme/image.css +0 -143
  277. package/theme/imagecaption.css +0 -53
  278. package/theme/imagecustomresizeform.css +0 -4
  279. package/theme/imageinsert.css +0 -14
  280. package/theme/imageplaceholder.css +0 -10
  281. package/theme/imageresize.css +0 -53
  282. package/theme/imagestyle.css +0 -120
  283. package/theme/imageuploadicon.css +0 -23
  284. package/theme/imageuploadloader.css +0 -18
  285. package/theme/imageuploadprogress.css +0 -19
  286. package/theme/textalternativeform.css +0 -4
  287. /package/{src → dist}/augmentation.d.ts +0 -0
  288. /package/{src → dist}/imageresize/utils/tryparsedimensionwithunit.d.ts +0 -0
  289. /package/{src → dist}/index.d.ts +0 -0
@@ -1,222 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module image/imageupload/imageuploadprogress
7
- */
8
- import { Plugin } from 'ckeditor5/src/core.js';
9
- import { FileRepository } from 'ckeditor5/src/upload.js';
10
- import '../../theme/imageuploadprogress.css';
11
- import '../../theme/imageuploadicon.css';
12
- import '../../theme/imageuploadloader.css';
13
- /**
14
- * The image upload progress plugin.
15
- * It shows a placeholder when the image is read from the disk and a progress bar while the image is uploading.
16
- */
17
- export class ImageUploadProgress extends Plugin {
18
- /**
19
- * @inheritDoc
20
- */
21
- static get pluginName() {
22
- return 'ImageUploadProgress';
23
- }
24
- /**
25
- * @inheritDoc
26
- */
27
- static get isOfficialPlugin() {
28
- return true;
29
- }
30
- /**
31
- * The image placeholder that is displayed before real image data can be accessed.
32
- *
33
- * For the record, this image is a 1x1 px GIF with an aspect ratio set by CSS.
34
- */
35
- placeholder;
36
- /**
37
- * @inheritDoc
38
- */
39
- constructor(editor) {
40
- super(editor);
41
- this.placeholder = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
42
- }
43
- /**
44
- * @inheritDoc
45
- */
46
- init() {
47
- const editor = this.editor;
48
- // Upload status change - update image's view according to that status.
49
- if (editor.plugins.has('ImageBlockEditing')) {
50
- editor.editing.downcastDispatcher.on('attribute:uploadStatus:imageBlock', this.uploadStatusChange);
51
- }
52
- if (editor.plugins.has('ImageInlineEditing')) {
53
- editor.editing.downcastDispatcher.on('attribute:uploadStatus:imageInline', this.uploadStatusChange);
54
- }
55
- }
56
- /**
57
- * This method is called each time the image `uploadStatus` attribute is changed.
58
- *
59
- * @param evt An object containing information about the fired event.
60
- * @param data Additional information about the change.
61
- */
62
- uploadStatusChange = (evt, data, conversionApi) => {
63
- const editor = this.editor;
64
- const modelImage = data.item;
65
- const uploadId = modelImage.getAttribute('uploadId');
66
- if (!conversionApi.consumable.consume(data.item, evt.name)) {
67
- return;
68
- }
69
- const imageUtils = editor.plugins.get('ImageUtils');
70
- const fileRepository = editor.plugins.get(FileRepository);
71
- const status = uploadId ? data.attributeNewValue : null;
72
- const placeholder = this.placeholder;
73
- const viewFigure = editor.editing.mapper.toViewElement(modelImage);
74
- const viewWriter = conversionApi.writer;
75
- if (status == 'reading') {
76
- // Start "appearing" effect and show placeholder with infinite progress bar on the top
77
- // while image is read from disk.
78
- _startAppearEffect(viewFigure, viewWriter);
79
- _showPlaceholder(imageUtils, placeholder, viewFigure, viewWriter);
80
- return;
81
- }
82
- // Show progress bar on the top of the image when image is uploading.
83
- if (status == 'uploading') {
84
- const loader = fileRepository.loaders.get(uploadId);
85
- // Start appear effect if needed - see https://github.com/ckeditor/ckeditor5-image/issues/191.
86
- _startAppearEffect(viewFigure, viewWriter);
87
- if (!loader) {
88
- // There is no loader associated with uploadId - this means that image came from external changes.
89
- // In such cases we still want to show the placeholder until image is fully uploaded.
90
- // Show placeholder if needed - see https://github.com/ckeditor/ckeditor5-image/issues/191.
91
- _showPlaceholder(imageUtils, placeholder, viewFigure, viewWriter);
92
- }
93
- else {
94
- // Hide placeholder and initialize progress bar showing upload progress.
95
- _hidePlaceholder(viewFigure, viewWriter);
96
- _showProgressBar(viewFigure, viewWriter, loader, editor.editing.view);
97
- _displayLocalImage(imageUtils, viewFigure, viewWriter, loader);
98
- }
99
- return;
100
- }
101
- if (status == 'complete' && fileRepository.loaders.get(uploadId)) {
102
- _showCompleteIcon(viewFigure, viewWriter, editor.editing.view);
103
- }
104
- // Clean up.
105
- _hideProgressBar(viewFigure, viewWriter);
106
- _hidePlaceholder(viewFigure, viewWriter);
107
- _stopAppearEffect(viewFigure, viewWriter);
108
- };
109
- }
110
- /**
111
- * Adds ck-appear class to the image figure if one is not already applied.
112
- */
113
- function _startAppearEffect(viewFigure, writer) {
114
- if (!viewFigure.hasClass('ck-appear')) {
115
- writer.addClass('ck-appear', viewFigure);
116
- }
117
- }
118
- /**
119
- * Removes ck-appear class to the image figure if one is not already removed.
120
- */
121
- function _stopAppearEffect(viewFigure, writer) {
122
- writer.removeClass('ck-appear', viewFigure);
123
- }
124
- /**
125
- * Shows placeholder together with infinite progress bar on given image figure.
126
- */
127
- function _showPlaceholder(imageUtils, placeholder, viewFigure, writer) {
128
- if (!viewFigure.hasClass('ck-image-upload-placeholder')) {
129
- writer.addClass('ck-image-upload-placeholder', viewFigure);
130
- }
131
- const viewImg = imageUtils.findViewImgElement(viewFigure);
132
- if (viewImg.getAttribute('src') !== placeholder) {
133
- writer.setAttribute('src', placeholder, viewImg);
134
- }
135
- if (!_getUIElement(viewFigure, 'placeholder')) {
136
- writer.insert(writer.createPositionAfter(viewImg), _createPlaceholder(writer));
137
- }
138
- }
139
- /**
140
- * Removes placeholder together with infinite progress bar on given image figure.
141
- */
142
- function _hidePlaceholder(viewFigure, writer) {
143
- if (viewFigure.hasClass('ck-image-upload-placeholder')) {
144
- writer.removeClass('ck-image-upload-placeholder', viewFigure);
145
- }
146
- _removeUIElement(viewFigure, writer, 'placeholder');
147
- }
148
- /**
149
- * Shows progress bar displaying upload progress.
150
- * Attaches it to the file loader to update when upload percentace is changed.
151
- */
152
- function _showProgressBar(viewFigure, writer, loader, view) {
153
- const progressBar = _createProgressBar(writer);
154
- writer.insert(writer.createPositionAt(viewFigure, 'end'), progressBar);
155
- // Update progress bar width when uploadedPercent is changed.
156
- loader.on('change:uploadedPercent', (evt, name, value) => {
157
- view.change(writer => {
158
- writer.setStyle('width', value + '%', progressBar);
159
- });
160
- });
161
- }
162
- /**
163
- * Hides upload progress bar.
164
- */
165
- function _hideProgressBar(viewFigure, writer) {
166
- _removeUIElement(viewFigure, writer, 'progressBar');
167
- }
168
- /**
169
- * Shows complete icon and hides after a certain amount of time.
170
- */
171
- function _showCompleteIcon(viewFigure, writer, view) {
172
- const completeIcon = writer.createUIElement('div', { class: 'ck-image-upload-complete-icon' });
173
- writer.insert(writer.createPositionAt(viewFigure, 'end'), completeIcon);
174
- setTimeout(() => {
175
- view.change(writer => writer.remove(writer.createRangeOn(completeIcon)));
176
- }, 3000);
177
- }
178
- /**
179
- * Create progress bar element using {@link module:engine/view/uielement~ViewUIElement}.
180
- */
181
- function _createProgressBar(writer) {
182
- const progressBar = writer.createUIElement('div', { class: 'ck-progress-bar' });
183
- writer.setCustomProperty('progressBar', true, progressBar);
184
- return progressBar;
185
- }
186
- /**
187
- * Create placeholder element using {@link module:engine/view/uielement~ViewUIElement}.
188
- */
189
- function _createPlaceholder(writer) {
190
- const placeholder = writer.createUIElement('div', { class: 'ck-upload-placeholder-loader' });
191
- writer.setCustomProperty('placeholder', true, placeholder);
192
- return placeholder;
193
- }
194
- /**
195
- * Returns {@link module:engine/view/uielement~ViewUIElement} of given unique property from image figure element.
196
- * Returns `undefined` if element is not found.
197
- */
198
- function _getUIElement(imageFigure, uniqueProperty) {
199
- for (const child of imageFigure.getChildren()) {
200
- if (child.getCustomProperty(uniqueProperty)) {
201
- return child;
202
- }
203
- }
204
- }
205
- /**
206
- * Removes {@link module:engine/view/uielement~ViewUIElement} of given unique property from image figure element.
207
- */
208
- function _removeUIElement(viewFigure, writer, uniqueProperty) {
209
- const element = _getUIElement(viewFigure, uniqueProperty);
210
- if (element) {
211
- writer.remove(writer.createRangeOn(element));
212
- }
213
- }
214
- /**
215
- * Displays local data from file loader.
216
- */
217
- function _displayLocalImage(imageUtils, viewFigure, writer, loader) {
218
- if (loader.data) {
219
- const viewImg = imageUtils.findViewImgElement(viewFigure);
220
- writer.setAttribute('src', loader.data, viewImg);
221
- }
222
- }
@@ -1,135 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module image/imageupload/imageuploadui
7
- */
8
- import { Plugin } from 'ckeditor5/src/core.js';
9
- import { FileDialogButtonView, MenuBarMenuListItemFileDialogButtonView } from 'ckeditor5/src/ui.js';
10
- import { IconImageUpload } from 'ckeditor5/src/icons.js';
11
- import { createImageTypeRegExp } from './utils.js';
12
- /**
13
- * The image upload button plugin.
14
- *
15
- * For a detailed overview, check the {@glink features/images/image-upload/image-upload Image upload feature} documentation.
16
- *
17
- * Adds the `'uploadImage'` button to the {@link module:ui/componentfactory~ComponentFactory UI component factory}
18
- * and also the `imageUpload` button as an alias for backward compatibility.
19
- *
20
- * Adds the `'menuBar:uploadImage'` menu button to the {@link module:ui/componentfactory~ComponentFactory UI component factory}.
21
- *
22
- * It also integrates with the `insertImage` toolbar component and `menuBar:insertImage` menu component, which are the default components
23
- * through which image upload is available.
24
- */
25
- export class ImageUploadUI extends Plugin {
26
- /**
27
- * @inheritDoc
28
- */
29
- static get pluginName() {
30
- return 'ImageUploadUI';
31
- }
32
- /**
33
- * @inheritDoc
34
- */
35
- static get isOfficialPlugin() {
36
- return true;
37
- }
38
- /**
39
- * @inheritDoc
40
- */
41
- init() {
42
- const editor = this.editor;
43
- // Setup `uploadImage` button and add `imageUpload` button as an alias for backward compatibility.
44
- editor.ui.componentFactory.add('uploadImage', () => this._createToolbarButton());
45
- editor.ui.componentFactory.add('imageUpload', () => this._createToolbarButton());
46
- editor.ui.componentFactory.add('menuBar:uploadImage', () => this._createMenuBarButton('standalone'));
47
- if (editor.plugins.has('ImageInsertUI')) {
48
- editor.plugins.get('ImageInsertUI').registerIntegration({
49
- name: 'upload',
50
- observable: () => editor.commands.get('uploadImage'),
51
- buttonViewCreator: () => this._createToolbarButton(),
52
- formViewCreator: () => this._createDropdownButton(),
53
- menuBarButtonViewCreator: isOnly => this._createMenuBarButton(isOnly ? 'insertOnly' : 'insertNested')
54
- });
55
- }
56
- }
57
- /**
58
- * Creates the base for various kinds of the button component provided by this feature.
59
- */
60
- _createButton(ButtonClass) {
61
- const editor = this.editor;
62
- const locale = editor.locale;
63
- const command = editor.commands.get('uploadImage');
64
- const imageTypes = editor.config.get('image.upload.types');
65
- const imageTypesRegExp = createImageTypeRegExp(imageTypes);
66
- const view = new ButtonClass(editor.locale);
67
- const t = locale.t;
68
- view.set({
69
- acceptedType: imageTypes.map(type => `image/${type}`).join(','),
70
- allowMultipleFiles: true,
71
- label: t('Upload from computer'),
72
- icon: IconImageUpload
73
- });
74
- view.bind('isEnabled').to(command);
75
- view.on('done', (evt, files) => {
76
- const imagesToUpload = Array.from(files).filter(file => imageTypesRegExp.test(file.type));
77
- if (imagesToUpload.length) {
78
- editor.execute('uploadImage', { file: imagesToUpload });
79
- editor.editing.view.focus();
80
- }
81
- });
82
- return view;
83
- }
84
- /**
85
- * Creates a simple toolbar button, with an icon and a tooltip.
86
- */
87
- _createToolbarButton() {
88
- const t = this.editor.locale.t;
89
- const imageInsertUI = this.editor.plugins.get('ImageInsertUI');
90
- const uploadImageCommand = this.editor.commands.get('uploadImage');
91
- const button = this._createButton(FileDialogButtonView);
92
- button.tooltip = true;
93
- button.bind('label').to(imageInsertUI, 'isImageSelected', uploadImageCommand, 'isAccessAllowed', (isImageSelected, isAccessAllowed) => {
94
- if (!isAccessAllowed) {
95
- return t('You have no image upload permissions.');
96
- }
97
- return isImageSelected ? t('Replace image from computer') : t('Upload image from computer');
98
- });
99
- return button;
100
- }
101
- /**
102
- * Creates a button for the dropdown view, with an icon, text and no tooltip.
103
- */
104
- _createDropdownButton() {
105
- const t = this.editor.locale.t;
106
- const imageInsertUI = this.editor.plugins.get('ImageInsertUI');
107
- const button = this._createButton(FileDialogButtonView);
108
- button.withText = true;
109
- button.bind('label').to(imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ? t('Replace from computer') : t('Upload from computer'));
110
- button.on('execute', () => {
111
- imageInsertUI.dropdownView.isOpen = false;
112
- });
113
- return button;
114
- }
115
- /**
116
- * Creates a button for the menu bar.
117
- */
118
- _createMenuBarButton(type) {
119
- const t = this.editor.locale.t;
120
- const button = this._createButton(MenuBarMenuListItemFileDialogButtonView);
121
- button.withText = true;
122
- switch (type) {
123
- case 'standalone':
124
- button.label = t('Image from computer');
125
- break;
126
- case 'insertOnly':
127
- button.label = t('Image');
128
- break;
129
- case 'insertNested':
130
- button.label = t('From computer');
131
- break;
132
- }
133
- return button;
134
- }
135
- }
@@ -1,110 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- import { FileRepository } from 'ckeditor5/src/upload.js';
6
- import { Command } from 'ckeditor5/src/core.js';
7
- import { toArray } from 'ckeditor5/src/utils.js';
8
- /**
9
- * @module image/imageupload/uploadimagecommand
10
- */
11
- /**
12
- * The upload image command.
13
- *
14
- * The command is registered by the {@link module:image/imageupload/imageuploadediting~ImageUploadEditing} plugin as `uploadImage`
15
- * and it is also available via aliased `imageUpload` name.
16
- *
17
- * In order to upload an image at the current selection position
18
- * (according to the {@link module:widget/utils~findOptimalInsertionRange} algorithm),
19
- * execute the command and pass the native image file instance:
20
- *
21
- * ```ts
22
- * this.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
23
- * // Assuming that only images were pasted:
24
- * const images = Array.from( data.dataTransfer.files );
25
- *
26
- * // Upload the first image:
27
- * editor.execute( 'uploadImage', { file: images[ 0 ] } );
28
- * } );
29
- * ```
30
- *
31
- * It is also possible to insert multiple images at once:
32
- *
33
- * ```ts
34
- * editor.execute( 'uploadImage', {
35
- * file: [
36
- * file1,
37
- * file2
38
- * ]
39
- * } );
40
- * ```
41
- */
42
- export class UploadImageCommand extends Command {
43
- /**
44
- * Creates an instance of the `imageUlpoad` command. When executed, the command upload one of
45
- * the currently selected image from computer.
46
- *
47
- * @param editor The editor instance.
48
- */
49
- constructor(editor) {
50
- super(editor);
51
- this.set('isAccessAllowed', true);
52
- }
53
- /**
54
- * @inheritDoc
55
- */
56
- refresh() {
57
- const editor = this.editor;
58
- const imageUtils = editor.plugins.get('ImageUtils');
59
- const selectedElement = editor.model.document.selection.getSelectedElement();
60
- // TODO: This needs refactoring.
61
- this.isEnabled = imageUtils.isImageAllowed() || imageUtils.isImage(selectedElement);
62
- }
63
- /**
64
- * Executes the command.
65
- *
66
- * @fires execute
67
- * @param options Options for the executed command.
68
- * @param options.file The image file or an array of image files to upload.
69
- */
70
- execute(options) {
71
- const files = toArray(options.file);
72
- const selection = this.editor.model.document.selection;
73
- const imageUtils = this.editor.plugins.get('ImageUtils');
74
- // In case of multiple files, each file (starting from the 2nd) will be inserted at a position that
75
- // follows the previous one. That will move the selection and, to stay on the safe side and make sure
76
- // all images inherit the same selection attributes, they are collected beforehand.
77
- //
78
- // Applying these attributes ensures, for instance, that inserting an (inline) image into a link does
79
- // not split that link but preserves its continuity.
80
- //
81
- // Note: Selection attributes that do not make sense for images will be filtered out by insertImage() anyway.
82
- const selectionAttributes = Object.fromEntries(selection.getAttributes());
83
- files.forEach((file, index) => {
84
- const selectedElement = selection.getSelectedElement();
85
- // Inserting of an inline image replace the selected element and make a selection on the inserted image.
86
- // Therefore inserting multiple inline images requires creating position after each element.
87
- if (index && selectedElement && imageUtils.isImage(selectedElement)) {
88
- const position = this.editor.model.createPositionAfter(selectedElement);
89
- this._uploadImage(file, selectionAttributes, position);
90
- }
91
- else {
92
- this._uploadImage(file, selectionAttributes);
93
- }
94
- });
95
- }
96
- /**
97
- * Handles uploading single file.
98
- */
99
- _uploadImage(file, attributes, position) {
100
- const editor = this.editor;
101
- const fileRepository = editor.plugins.get(FileRepository);
102
- const loader = fileRepository.createLoader(file);
103
- const imageUtils = editor.plugins.get('ImageUtils');
104
- // Do not throw when upload adapter is not set. FileRepository will log an error anyway.
105
- if (!loader) {
106
- return;
107
- }
108
- imageUtils.insertImage({ ...attributes, uploadId: loader.id }, position);
109
- }
110
- }
@@ -1,114 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- import { global } from 'ckeditor5/src/utils.js';
6
- /**
7
- * Creates a regular expression used to test for image files.
8
- *
9
- * ```ts
10
- * const imageType = createImageTypeRegExp( [ 'png', 'jpeg', 'svg+xml', 'vnd.microsoft.icon' ] );
11
- *
12
- * console.log( 'is supported image', imageType.test( file.type ) );
13
- * ```
14
- */
15
- export function createImageTypeRegExp(types) {
16
- // Sanitize the MIME type name which may include: "+", "-" or ".".
17
- const regExpSafeNames = types.map(type => type.replace('+', '\\+'));
18
- return new RegExp(`^image\\/(${regExpSafeNames.join('|')})$`);
19
- }
20
- /**
21
- * Creates a promise that fetches the image local source (Base64 or blob) and resolves with a `File` object.
22
- *
23
- * @internal
24
- * @param image Image whose source to fetch.
25
- * @returns A promise which resolves when an image source is fetched and converted to a `File` instance.
26
- * It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.
27
- */
28
- export function fetchLocalImage(image) {
29
- return new Promise((resolve, reject) => {
30
- const imageSrc = image.getAttribute('src');
31
- // Fetch works asynchronously and so does not block browser UI when processing data.
32
- fetch(imageSrc)
33
- .then(resource => resource.blob())
34
- .then(blob => {
35
- const mimeType = getImageMimeType(blob, imageSrc);
36
- const ext = mimeType.replace('image/', '');
37
- const filename = `image.${ext}`;
38
- const file = new File([blob], filename, { type: mimeType });
39
- resolve(file);
40
- })
41
- .catch(err => {
42
- // Fetch fails only, if it can't make a request due to a network failure or if anything prevented the request
43
- // from completing, i.e. the Content Security Policy rules. It is not possible to detect the exact cause of failure,
44
- // so we are just trying the fallback solution, if general TypeError is thrown.
45
- return err && err.name === 'TypeError' ?
46
- convertLocalImageOnCanvas(imageSrc).then(resolve).catch(reject) :
47
- reject(err);
48
- });
49
- });
50
- }
51
- /**
52
- * Checks whether a given node is an image element with a local source (Base64 or blob).
53
- *
54
- * @param node The node to check.
55
- * @internal
56
- */
57
- export function isLocalImage(imageUtils, node) {
58
- if (!imageUtils.isInlineImageView(node) || !node.getAttribute('src')) {
59
- return false;
60
- }
61
- return !!node.getAttribute('src').match(/^data:image\/\w+;base64,/g) ||
62
- !!node.getAttribute('src').match(/^blob:/g);
63
- }
64
- /**
65
- * Extracts an image type based on its blob representation or its source.
66
- * @param blob Image blob representation.
67
- * @param src Image `src` attribute value.
68
- */
69
- function getImageMimeType(blob, src) {
70
- if (blob.type) {
71
- return blob.type;
72
- }
73
- else if (src.match(/data:(image\/\w+);base64/)) {
74
- return src.match(/data:(image\/\w+);base64/)[1].toLowerCase();
75
- }
76
- else {
77
- // Fallback to 'jpeg' as common extension.
78
- return 'image/jpeg';
79
- }
80
- }
81
- /**
82
- * Creates a promise that converts the image local source (Base64 or blob) to a blob using canvas and resolves
83
- * with a `File` object.
84
- * @param imageSrc Image `src` attribute value.
85
- * @returns A promise which resolves when an image source is converted to a `File` instance.
86
- * It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.
87
- */
88
- function convertLocalImageOnCanvas(imageSrc) {
89
- return getBlobFromCanvas(imageSrc).then(blob => {
90
- const mimeType = getImageMimeType(blob, imageSrc);
91
- const ext = mimeType.replace('image/', '');
92
- const filename = `image.${ext}`;
93
- return new File([blob], filename, { type: mimeType });
94
- });
95
- }
96
- /**
97
- * Creates a promise that resolves with a `Blob` object converted from the image source (Base64 or blob).
98
- * @param imageSrc Image `src` attribute value.
99
- */
100
- function getBlobFromCanvas(imageSrc) {
101
- return new Promise((resolve, reject) => {
102
- const image = global.document.createElement('img');
103
- image.addEventListener('load', () => {
104
- const canvas = global.document.createElement('canvas');
105
- canvas.width = image.width;
106
- canvas.height = image.height;
107
- const ctx = canvas.getContext('2d');
108
- ctx.drawImage(image, 0, 0);
109
- canvas.toBlob(blob => blob ? resolve(blob) : reject());
110
- });
111
- image.addEventListener('error', () => reject());
112
- image.src = imageSrc;
113
- });
114
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
- */
5
- /**
6
- * @module image/imageupload
7
- */
8
- import { Plugin } from 'ckeditor5/src/core.js';
9
- import { ImageUploadUI } from './imageupload/imageuploadui.js';
10
- import { ImageUploadProgress } from './imageupload/imageuploadprogress.js';
11
- import { ImageUploadEditing } from './imageupload/imageuploadediting.js';
12
- /**
13
- * The image upload plugin.
14
- *
15
- * For a detailed overview, check the {@glink features/images/image-upload/image-upload image upload feature} documentation.
16
- *
17
- * This plugin does not do anything directly, but it loads a set of specific plugins to enable image uploading:
18
- *
19
- * * {@link module:image/imageupload/imageuploadediting~ImageUploadEditing},
20
- * * {@link module:image/imageupload/imageuploadui~ImageUploadUI},
21
- * * {@link module:image/imageupload/imageuploadprogress~ImageUploadProgress}.
22
- */
23
- export class ImageUpload extends Plugin {
24
- /**
25
- * @inheritDoc
26
- */
27
- static get pluginName() {
28
- return 'ImageUpload';
29
- }
30
- /**
31
- * @inheritDoc
32
- */
33
- static get isOfficialPlugin() {
34
- return true;
35
- }
36
- /**
37
- * @inheritDoc
38
- */
39
- static get requires() {
40
- return [ImageUploadEditing, ImageUploadUI, ImageUploadProgress];
41
- }
42
- }