@ckeditor/ckeditor5-upload 41.3.0-alpha.0 → 41.3.0-alpha.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. package/dist/translations/ar.d.ts +8 -0
  2. package/dist/translations/ar.js +5 -0
  3. package/dist/translations/az.d.ts +8 -0
  4. package/dist/translations/az.js +5 -0
  5. package/dist/translations/bg.d.ts +8 -0
  6. package/dist/translations/bg.js +5 -0
  7. package/dist/translations/bn.d.ts +8 -0
  8. package/dist/translations/bn.js +5 -0
  9. package/dist/translations/ca.d.ts +8 -0
  10. package/dist/translations/ca.js +5 -0
  11. package/dist/translations/cs.d.ts +8 -0
  12. package/dist/translations/cs.js +5 -0
  13. package/dist/translations/da.d.ts +8 -0
  14. package/dist/translations/da.js +5 -0
  15. package/dist/translations/de-ch.d.ts +8 -0
  16. package/dist/translations/de-ch.js +5 -0
  17. package/dist/translations/de.d.ts +8 -0
  18. package/dist/translations/de.js +5 -0
  19. package/dist/translations/el.d.ts +8 -0
  20. package/dist/translations/el.js +5 -0
  21. package/dist/translations/en-au.d.ts +8 -0
  22. package/dist/translations/en-au.js +5 -0
  23. package/dist/translations/en-gb.d.ts +8 -0
  24. package/dist/translations/en-gb.js +5 -0
  25. package/dist/translations/en.d.ts +8 -0
  26. package/dist/translations/en.js +5 -0
  27. package/dist/translations/es-co.d.ts +8 -0
  28. package/dist/translations/es-co.js +5 -0
  29. package/dist/translations/es.d.ts +8 -0
  30. package/dist/translations/es.js +5 -0
  31. package/dist/translations/et.d.ts +8 -0
  32. package/dist/translations/et.js +5 -0
  33. package/dist/translations/fa.d.ts +8 -0
  34. package/dist/translations/fa.js +5 -0
  35. package/dist/translations/fi.d.ts +8 -0
  36. package/dist/translations/fi.js +5 -0
  37. package/dist/translations/fr.d.ts +8 -0
  38. package/dist/translations/fr.js +5 -0
  39. package/dist/translations/gl.d.ts +8 -0
  40. package/dist/translations/gl.js +5 -0
  41. package/dist/translations/he.d.ts +8 -0
  42. package/dist/translations/he.js +5 -0
  43. package/dist/translations/hi.d.ts +8 -0
  44. package/dist/translations/hi.js +5 -0
  45. package/dist/translations/hr.d.ts +8 -0
  46. package/dist/translations/hr.js +5 -0
  47. package/dist/translations/hu.d.ts +8 -0
  48. package/dist/translations/hu.js +5 -0
  49. package/dist/translations/id.d.ts +8 -0
  50. package/dist/translations/id.js +5 -0
  51. package/dist/translations/it.d.ts +8 -0
  52. package/dist/translations/it.js +5 -0
  53. package/dist/translations/ja.d.ts +8 -0
  54. package/dist/translations/ja.js +5 -0
  55. package/dist/translations/ko.d.ts +8 -0
  56. package/dist/translations/ko.js +5 -0
  57. package/dist/translations/ku.d.ts +8 -0
  58. package/dist/translations/ku.js +5 -0
  59. package/dist/translations/lt.d.ts +8 -0
  60. package/dist/translations/lt.js +5 -0
  61. package/dist/translations/lv.d.ts +8 -0
  62. package/dist/translations/lv.js +5 -0
  63. package/dist/translations/ms.d.ts +8 -0
  64. package/dist/translations/ms.js +5 -0
  65. package/dist/translations/nb.d.ts +8 -0
  66. package/dist/translations/nb.js +5 -0
  67. package/dist/translations/ne.d.ts +8 -0
  68. package/dist/translations/ne.js +5 -0
  69. package/dist/translations/nl.d.ts +8 -0
  70. package/dist/translations/nl.js +5 -0
  71. package/dist/translations/no.d.ts +8 -0
  72. package/dist/translations/no.js +5 -0
  73. package/dist/translations/pl.d.ts +8 -0
  74. package/dist/translations/pl.js +5 -0
  75. package/dist/translations/pt-br.d.ts +8 -0
  76. package/dist/translations/pt-br.js +5 -0
  77. package/dist/translations/pt.d.ts +8 -0
  78. package/dist/translations/pt.js +5 -0
  79. package/dist/translations/ro.d.ts +8 -0
  80. package/dist/translations/ro.js +5 -0
  81. package/dist/translations/ru.d.ts +8 -0
  82. package/dist/translations/ru.js +5 -0
  83. package/dist/translations/sk.d.ts +8 -0
  84. package/dist/translations/sk.js +5 -0
  85. package/dist/translations/sq.d.ts +8 -0
  86. package/dist/translations/sq.js +5 -0
  87. package/dist/translations/sr-latn.d.ts +8 -0
  88. package/dist/translations/sr-latn.js +5 -0
  89. package/dist/translations/sr.d.ts +8 -0
  90. package/dist/translations/sr.js +5 -0
  91. package/dist/translations/sv.d.ts +8 -0
  92. package/dist/translations/sv.js +5 -0
  93. package/dist/translations/th.d.ts +8 -0
  94. package/dist/translations/th.js +5 -0
  95. package/dist/translations/tk.d.ts +8 -0
  96. package/dist/translations/tk.js +5 -0
  97. package/dist/translations/tr.d.ts +8 -0
  98. package/dist/translations/tr.js +5 -0
  99. package/dist/translations/ug.d.ts +8 -0
  100. package/dist/translations/ug.js +5 -0
  101. package/dist/translations/uk.d.ts +8 -0
  102. package/dist/translations/uk.js +5 -0
  103. package/dist/translations/ur.d.ts +8 -0
  104. package/dist/translations/ur.js +5 -0
  105. package/dist/translations/uz.d.ts +8 -0
  106. package/dist/translations/uz.js +5 -0
  107. package/dist/translations/vi.d.ts +8 -0
  108. package/dist/translations/vi.js +5 -0
  109. package/dist/translations/zh-cn.d.ts +8 -0
  110. package/dist/translations/zh-cn.js +5 -0
  111. package/dist/translations/zh.d.ts +8 -0
  112. package/dist/translations/zh.js +5 -0
  113. package/dist/types/adapters/base64uploadadapter.d.ts +4 -0
  114. package/dist/types/adapters/simpleuploadadapter.d.ts +4 -0
  115. package/dist/types/augmentation.d.ts +4 -0
  116. package/dist/types/filereader.d.ts +4 -0
  117. package/dist/types/filerepository.d.ts +4 -0
  118. package/dist/types/index.d.ts +4 -0
  119. package/dist/types/ui/filedialogbuttonview.d.ts +4 -0
  120. package/dist/types/uploadconfig.d.ts +4 -0
  121. package/package.json +4 -4
  122. package/dist/index.js +0 -817
  123. package/dist/index.js.map +0 -1
package/dist/index.js DELETED
@@ -1,817 +0,0 @@
1
- /**
2
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
- */
5
- import { Plugin, PendingActions } from '@ckeditor/ckeditor5-core/dist/index.js';
6
- import { ObservableMixin, uid, CKEditorError, Collection, logWarning } from '@ckeditor/ckeditor5-utils/dist/index.js';
7
- import { ButtonView, View } from '@ckeditor/ckeditor5-ui/dist/index.js';
8
-
9
- /**
10
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
11
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
12
- */
13
- /**
14
- * @module upload/filereader
15
- */
16
- /* globals window */
17
- /**
18
- * Wrapper over the native `FileReader`.
19
- */
20
- class FileReader extends ObservableMixin() {
21
- /**
22
- * Creates an instance of the FileReader.
23
- */
24
- constructor() {
25
- super();
26
- const reader = new window.FileReader();
27
- this._reader = reader;
28
- this._data = undefined;
29
- this.set('loaded', 0);
30
- reader.onprogress = evt => {
31
- this.loaded = evt.loaded;
32
- };
33
- }
34
- /**
35
- * Returns error that occurred during file reading.
36
- */
37
- get error() {
38
- return this._reader.error;
39
- }
40
- /**
41
- * Holds the data of an already loaded file. The file must be first loaded
42
- * by using {@link module:upload/filereader~FileReader#read `read()`}.
43
- */
44
- get data() {
45
- return this._data;
46
- }
47
- /**
48
- * Reads the provided file.
49
- *
50
- * @param file Native File object.
51
- * @returns Returns a promise that will be resolved with file's content.
52
- * The promise will be rejected in case of an error or when the reading process is aborted.
53
- */
54
- read(file) {
55
- const reader = this._reader;
56
- this.total = file.size;
57
- return new Promise((resolve, reject) => {
58
- reader.onload = () => {
59
- const result = reader.result;
60
- this._data = result;
61
- resolve(result);
62
- };
63
- reader.onerror = () => {
64
- reject('error');
65
- };
66
- reader.onabort = () => {
67
- reject('aborted');
68
- };
69
- this._reader.readAsDataURL(file);
70
- });
71
- }
72
- /**
73
- * Aborts file reader.
74
- */
75
- abort() {
76
- this._reader.abort();
77
- }
78
- }
79
-
80
- /**
81
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
82
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
83
- */
84
- /**
85
- * @module upload/filerepository
86
- */
87
- /**
88
- * File repository plugin. A central point for managing file upload.
89
- *
90
- * To use it, first you need an upload adapter. Upload adapter's job is to handle communication with the server
91
- * (sending the file and handling server's response). You can use one of the existing plugins introducing upload adapters
92
- * (e.g. {@link module:easy-image/cloudservicesuploadadapter~CloudServicesUploadAdapter} or
93
- * {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}) or write your own one – see
94
- * the {@glink framework/deep-dive/upload-adapter Custom image upload adapter deep-dive} guide.
95
- *
96
- * Then, you can use {@link module:upload/filerepository~FileRepository#createLoader `createLoader()`} and the returned
97
- * {@link module:upload/filerepository~FileLoader} instance to load and upload files.
98
- */
99
- class FileRepository extends Plugin {
100
- constructor() {
101
- super(...arguments);
102
- /**
103
- * Collection of loaders associated with this repository.
104
- */
105
- this.loaders = new Collection();
106
- /**
107
- * Loaders mappings used to retrieve loaders references.
108
- */
109
- this._loadersMap = new Map();
110
- /**
111
- * Reference to a pending action registered in a {@link module:core/pendingactions~PendingActions} plugin
112
- * while upload is in progress. When there is no upload then value is `null`.
113
- */
114
- this._pendingAction = null;
115
- }
116
- /**
117
- * @inheritDoc
118
- */
119
- static get pluginName() {
120
- return 'FileRepository';
121
- }
122
- /**
123
- * @inheritDoc
124
- */
125
- static get requires() {
126
- return [PendingActions];
127
- }
128
- /**
129
- * @inheritDoc
130
- */
131
- init() {
132
- // Keeps upload in a sync with pending actions.
133
- this.loaders.on('change', () => this._updatePendingAction());
134
- this.set('uploaded', 0);
135
- this.set('uploadTotal', null);
136
- this.bind('uploadedPercent').to(this, 'uploaded', this, 'uploadTotal', (uploaded, total) => {
137
- return total ? (uploaded / total * 100) : 0;
138
- });
139
- }
140
- /**
141
- * Returns the loader associated with specified file or promise.
142
- *
143
- * To get loader by id use `fileRepository.loaders.get( id )`.
144
- *
145
- * @param fileOrPromise Native file or promise handle.
146
- */
147
- getLoader(fileOrPromise) {
148
- return this._loadersMap.get(fileOrPromise) || null;
149
- }
150
- /**
151
- * Creates a loader instance for the given file.
152
- *
153
- * Requires {@link #createUploadAdapter} factory to be defined.
154
- *
155
- * @param fileOrPromise Native File object or native Promise object which resolves to a File.
156
- */
157
- createLoader(fileOrPromise) {
158
- if (!this.createUploadAdapter) {
159
- /**
160
- * You need to enable an upload adapter in order to be able to upload files.
161
- *
162
- * This warning shows up when {@link module:upload/filerepository~FileRepository} is being used
163
- * without {@link module:upload/filerepository~FileRepository#createUploadAdapter defining an upload adapter}.
164
- *
165
- * **If you see this warning when using one of the {@glink installation/getting-started/predefined-builds
166
- * CKEditor 5 Builds}**
167
- * it means that you did not configure any of the upload adapters available by default in those builds.
168
- *
169
- * See the {@glink features/images/image-upload/image-upload comprehensive "Image upload overview"} to learn which upload
170
- * adapters are available in the builds and how to configure them.
171
- *
172
- * **If you see this warning when using a custom build** there is a chance that you enabled
173
- * a feature like {@link module:image/imageupload~ImageUpload},
174
- * or {@link module:image/imageupload/imageuploadui~ImageUploadUI} but you did not enable any upload adapter.
175
- * You can choose one of the existing upload adapters listed in the
176
- * {@glink features/images/image-upload/image-upload "Image upload overview"}.
177
- *
178
- * You can also implement your {@glink framework/deep-dive/upload-adapter own image upload adapter}.
179
- *
180
- * @error filerepository-no-upload-adapter
181
- */
182
- logWarning('filerepository-no-upload-adapter');
183
- return null;
184
- }
185
- const loader = new FileLoader(Promise.resolve(fileOrPromise), this.createUploadAdapter);
186
- this.loaders.add(loader);
187
- this._loadersMap.set(fileOrPromise, loader);
188
- // Store also file => loader mapping so loader can be retrieved by file instance returned upon Promise resolution.
189
- if (fileOrPromise instanceof Promise) {
190
- loader.file
191
- .then(file => {
192
- this._loadersMap.set(file, loader);
193
- })
194
- // Every then() must have a catch().
195
- // File loader state (and rejections) are handled in read() and upload().
196
- // Also, see the "does not swallow the file promise rejection" test.
197
- .catch(() => { });
198
- }
199
- loader.on('change:uploaded', () => {
200
- let aggregatedUploaded = 0;
201
- for (const loader of this.loaders) {
202
- aggregatedUploaded += loader.uploaded;
203
- }
204
- this.uploaded = aggregatedUploaded;
205
- });
206
- loader.on('change:uploadTotal', () => {
207
- let aggregatedTotal = 0;
208
- for (const loader of this.loaders) {
209
- if (loader.uploadTotal) {
210
- aggregatedTotal += loader.uploadTotal;
211
- }
212
- }
213
- this.uploadTotal = aggregatedTotal;
214
- });
215
- return loader;
216
- }
217
- /**
218
- * Destroys the given loader.
219
- *
220
- * @param fileOrPromiseOrLoader File or Promise associated with that loader or loader itself.
221
- */
222
- destroyLoader(fileOrPromiseOrLoader) {
223
- const loader = fileOrPromiseOrLoader instanceof FileLoader ? fileOrPromiseOrLoader : this.getLoader(fileOrPromiseOrLoader);
224
- loader._destroy();
225
- this.loaders.remove(loader);
226
- this._loadersMap.forEach((value, key) => {
227
- if (value === loader) {
228
- this._loadersMap.delete(key);
229
- }
230
- });
231
- }
232
- /**
233
- * Registers or deregisters pending action bound with upload progress.
234
- */
235
- _updatePendingAction() {
236
- const pendingActions = this.editor.plugins.get(PendingActions);
237
- if (this.loaders.length) {
238
- if (!this._pendingAction) {
239
- const t = this.editor.t;
240
- const getMessage = (value) => `${t('Upload in progress')} ${parseInt(value)}%.`;
241
- this._pendingAction = pendingActions.add(getMessage(this.uploadedPercent));
242
- this._pendingAction.bind('message').to(this, 'uploadedPercent', getMessage);
243
- }
244
- }
245
- else {
246
- pendingActions.remove(this._pendingAction);
247
- this._pendingAction = null;
248
- }
249
- }
250
- }
251
- /**
252
- * File loader class.
253
- *
254
- * It is used to control the process of reading the file and uploading it using the specified upload adapter.
255
- */
256
- class FileLoader extends ObservableMixin() {
257
- /**
258
- * Creates a new instance of `FileLoader`.
259
- *
260
- * @param filePromise A promise which resolves to a file instance.
261
- * @param uploadAdapterCreator The function which returns {@link module:upload/filerepository~UploadAdapter} instance.
262
- */
263
- constructor(filePromise, uploadAdapterCreator) {
264
- super();
265
- this.id = uid();
266
- this._filePromiseWrapper = this._createFilePromiseWrapper(filePromise);
267
- this._adapter = uploadAdapterCreator(this);
268
- this._reader = new FileReader();
269
- this.set('status', 'idle');
270
- this.set('uploaded', 0);
271
- this.set('uploadTotal', null);
272
- this.bind('uploadedPercent').to(this, 'uploaded', this, 'uploadTotal', (uploaded, total) => {
273
- return total ? (uploaded / total * 100) : 0;
274
- });
275
- this.set('uploadResponse', null);
276
- }
277
- /**
278
- * A `Promise` which resolves to a `File` instance associated with this file loader.
279
- */
280
- get file() {
281
- if (!this._filePromiseWrapper) {
282
- // Loader was destroyed, return promise which resolves to null.
283
- return Promise.resolve(null);
284
- }
285
- else {
286
- // The `this._filePromiseWrapper.promise` is chained and not simply returned to handle a case when:
287
- //
288
- // * The `loader.file.then( ... )` is called by external code (returned promise is pending).
289
- // * Then `loader._destroy()` is called (call is synchronous) which destroys the `loader`.
290
- // * Promise returned by the first `loader.file.then( ... )` call is resolved.
291
- //
292
- // Returning `this._filePromiseWrapper.promise` will still resolve to a `File` instance so there
293
- // is an additional check needed in the chain to see if `loader` was destroyed in the meantime.
294
- return this._filePromiseWrapper.promise.then(file => this._filePromiseWrapper ? file : null);
295
- }
296
- }
297
- /**
298
- * Returns the file data. To read its data, you need for first load the file
299
- * by using the {@link module:upload/filerepository~FileLoader#read `read()`} method.
300
- */
301
- get data() {
302
- return this._reader.data;
303
- }
304
- /**
305
- * Reads file using {@link module:upload/filereader~FileReader}.
306
- *
307
- * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-read-wrong-status` when status
308
- * is different than `idle`.
309
- *
310
- * Example usage:
311
- *
312
- * ```ts
313
- * fileLoader.read()
314
- * .then( data => { ... } )
315
- * .catch( err => {
316
- * if ( err === 'aborted' ) {
317
- * console.log( 'Reading aborted.' );
318
- * } else {
319
- * console.log( 'Reading error.', err );
320
- * }
321
- * } );
322
- * ```
323
- *
324
- * @returns Returns promise that will be resolved with read data. Promise will be rejected if error
325
- * occurs or if read process is aborted.
326
- */
327
- read() {
328
- if (this.status != 'idle') {
329
- /**
330
- * You cannot call read if the status is different than idle.
331
- *
332
- * @error filerepository-read-wrong-status
333
- */
334
- throw new CKEditorError('filerepository-read-wrong-status', this);
335
- }
336
- this.status = 'reading';
337
- return this.file
338
- .then(file => this._reader.read(file))
339
- .then(data => {
340
- // Edge case: reader was aborted after file was read - double check for proper status.
341
- // It can happen when image was deleted during its upload.
342
- if (this.status !== 'reading') {
343
- throw this.status;
344
- }
345
- this.status = 'idle';
346
- return data;
347
- })
348
- .catch(err => {
349
- if (err === 'aborted') {
350
- this.status = 'aborted';
351
- throw 'aborted';
352
- }
353
- this.status = 'error';
354
- throw this._reader.error ? this._reader.error : err;
355
- });
356
- }
357
- /**
358
- * Reads file using the provided {@link module:upload/filerepository~UploadAdapter}.
359
- *
360
- * Throws {@link module:utils/ckeditorerror~CKEditorError CKEditorError} `filerepository-upload-wrong-status` when status
361
- * is different than `idle`.
362
- * Example usage:
363
- *
364
- * ```ts
365
- * fileLoader.upload()
366
- * .then( data => { ... } )
367
- * .catch( e => {
368
- * if ( e === 'aborted' ) {
369
- * console.log( 'Uploading aborted.' );
370
- * } else {
371
- * console.log( 'Uploading error.', e );
372
- * }
373
- * } );
374
- * ```
375
- *
376
- * @returns Returns promise that will be resolved with response data. Promise will be rejected if error
377
- * occurs or if read process is aborted.
378
- */
379
- upload() {
380
- if (this.status != 'idle') {
381
- /**
382
- * You cannot call upload if the status is different than idle.
383
- *
384
- * @error filerepository-upload-wrong-status
385
- */
386
- throw new CKEditorError('filerepository-upload-wrong-status', this);
387
- }
388
- this.status = 'uploading';
389
- return this.file
390
- .then(() => this._adapter.upload())
391
- .then(data => {
392
- this.uploadResponse = data;
393
- this.status = 'idle';
394
- return data;
395
- })
396
- .catch(err => {
397
- if (this.status === 'aborted') {
398
- throw 'aborted';
399
- }
400
- this.status = 'error';
401
- throw err;
402
- });
403
- }
404
- /**
405
- * Aborts loading process.
406
- */
407
- abort() {
408
- const status = this.status;
409
- this.status = 'aborted';
410
- if (!this._filePromiseWrapper.isFulfilled) {
411
- // Edge case: file loader is aborted before read() is called
412
- // so it might happen that no one handled the rejection of this promise.
413
- // See https://github.com/ckeditor/ckeditor5-upload/pull/100
414
- this._filePromiseWrapper.promise.catch(() => { });
415
- this._filePromiseWrapper.rejecter('aborted');
416
- }
417
- else if (status == 'reading') {
418
- this._reader.abort();
419
- }
420
- else if (status == 'uploading' && this._adapter.abort) {
421
- this._adapter.abort();
422
- }
423
- this._destroy();
424
- }
425
- /**
426
- * Performs cleanup.
427
- *
428
- * @internal
429
- */
430
- _destroy() {
431
- this._filePromiseWrapper = undefined;
432
- this._reader = undefined;
433
- this._adapter = undefined;
434
- this.uploadResponse = undefined;
435
- }
436
- /**
437
- * Wraps a given file promise into another promise giving additional
438
- * control (resolving, rejecting, checking if fulfilled) over it.
439
- *
440
- * @param filePromise The initial file promise to be wrapped.
441
- */
442
- _createFilePromiseWrapper(filePromise) {
443
- const wrapper = {};
444
- wrapper.promise = new Promise((resolve, reject) => {
445
- wrapper.rejecter = reject;
446
- wrapper.isFulfilled = false;
447
- filePromise
448
- .then(file => {
449
- wrapper.isFulfilled = true;
450
- resolve(file);
451
- })
452
- .catch(err => {
453
- wrapper.isFulfilled = true;
454
- reject(err);
455
- });
456
- });
457
- return wrapper;
458
- }
459
- }
460
-
461
- /**
462
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
463
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
464
- */
465
- /**
466
- * @module upload/ui/filedialogbuttonview
467
- */
468
- /**
469
- * The file dialog button view.
470
- *
471
- * This component provides a button that opens the native file selection dialog.
472
- * It can be used to implement the UI of a file upload feature.
473
- *
474
- * ```ts
475
- * const view = new FileDialogButtonView( locale );
476
- *
477
- * view.set( {
478
- * acceptedType: 'image/*',
479
- * allowMultipleFiles: true
480
- * label: t( 'Insert image' ),
481
- * icon: imageIcon,
482
- * tooltip: true
483
- * } );
484
- *
485
- * view.on( 'done', ( evt, files ) => {
486
- * for ( const file of Array.from( files ) ) {
487
- * console.log( 'Selected file', file );
488
- * }
489
- * } );
490
- * ```
491
- */
492
- class FileDialogButtonView extends ButtonView {
493
- /**
494
- * @inheritDoc
495
- */
496
- constructor(locale) {
497
- super(locale);
498
- // For backward compatibility.
499
- this.buttonView = this;
500
- this._fileInputView = new FileInputView(locale);
501
- this._fileInputView.bind('acceptedType').to(this);
502
- this._fileInputView.bind('allowMultipleFiles').to(this);
503
- this._fileInputView.delegate('done').to(this);
504
- this.on('execute', () => {
505
- this._fileInputView.open();
506
- });
507
- this.extendTemplate({
508
- attributes: {
509
- class: 'ck-file-dialog-button'
510
- }
511
- });
512
- }
513
- /**
514
- * @inheritDoc
515
- */
516
- render() {
517
- super.render();
518
- this.children.add(this._fileInputView);
519
- }
520
- }
521
- /**
522
- * The hidden file input view class.
523
- */
524
- class FileInputView extends View {
525
- /**
526
- * @inheritDoc
527
- */
528
- constructor(locale) {
529
- super(locale);
530
- this.set('acceptedType', undefined);
531
- this.set('allowMultipleFiles', false);
532
- const bind = this.bindTemplate;
533
- this.setTemplate({
534
- tag: 'input',
535
- attributes: {
536
- class: [
537
- 'ck-hidden'
538
- ],
539
- type: 'file',
540
- tabindex: '-1',
541
- accept: bind.to('acceptedType'),
542
- multiple: bind.to('allowMultipleFiles')
543
- },
544
- on: {
545
- // Removing from code coverage since we cannot programmatically set input element files.
546
- change: bind.to(/* istanbul ignore next -- @preserve */ () => {
547
- if (this.element && this.element.files && this.element.files.length) {
548
- this.fire('done', this.element.files);
549
- }
550
- this.element.value = '';
551
- })
552
- }
553
- });
554
- }
555
- /**
556
- * Opens file dialog.
557
- */
558
- open() {
559
- this.element.click();
560
- }
561
- }
562
-
563
- /**
564
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
565
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
566
- */
567
- /**
568
- * @module upload/adapters/base64uploadadapter
569
- */
570
- /* globals window */
571
- /**
572
- * A plugin that converts images inserted into the editor into [Base64 strings](https://en.wikipedia.org/wiki/Base64)
573
- * in the {@glink installation/getting-started/getting-and-setting-data editor output}.
574
- *
575
- * This kind of image upload does not require server processing – images are stored with the rest of the text and
576
- * displayed by the web browser without additional requests.
577
- *
578
- * Check out the {@glink features/images/image-upload/image-upload comprehensive "Image upload overview"} to learn about
579
- * other ways to upload images into CKEditor 5.
580
- */
581
- class Base64UploadAdapter extends Plugin {
582
- /**
583
- * @inheritDoc
584
- */
585
- static get requires() {
586
- return [FileRepository];
587
- }
588
- /**
589
- * @inheritDoc
590
- */
591
- static get pluginName() {
592
- return 'Base64UploadAdapter';
593
- }
594
- /**
595
- * @inheritDoc
596
- */
597
- init() {
598
- this.editor.plugins.get(FileRepository).createUploadAdapter = loader => new Adapter$1(loader);
599
- }
600
- }
601
- /**
602
- * The upload adapter that converts images inserted into the editor into Base64 strings.
603
- */
604
- let Adapter$1 = class Adapter {
605
- /**
606
- * Creates a new adapter instance.
607
- */
608
- constructor(loader) {
609
- this.loader = loader;
610
- }
611
- /**
612
- * Starts the upload process.
613
- *
614
- * @see module:upload/filerepository~UploadAdapter#upload
615
- */
616
- upload() {
617
- return new Promise((resolve, reject) => {
618
- const reader = this.reader = new window.FileReader();
619
- reader.addEventListener('load', () => {
620
- resolve({ default: reader.result });
621
- });
622
- reader.addEventListener('error', err => {
623
- reject(err);
624
- });
625
- reader.addEventListener('abort', () => {
626
- reject();
627
- });
628
- this.loader.file.then(file => {
629
- reader.readAsDataURL(file);
630
- });
631
- });
632
- }
633
- /**
634
- * Aborts the upload process.
635
- *
636
- * @see module:upload/filerepository~UploadAdapter#abort
637
- */
638
- abort() {
639
- this.reader.abort();
640
- }
641
- };
642
-
643
- /**
644
- * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
645
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
646
- */
647
- /**
648
- * @module upload/adapters/simpleuploadadapter
649
- */
650
- /* globals XMLHttpRequest, FormData */
651
- /**
652
- * The Simple upload adapter allows uploading images to an application running on your server using
653
- * the [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) API with a
654
- * minimal {@link module:upload/uploadconfig~SimpleUploadConfig editor configuration}.
655
- *
656
- * ```ts
657
- * ClassicEditor
658
- * .create( document.querySelector( '#editor' ), {
659
- * simpleUpload: {
660
- * uploadUrl: 'http://example.com',
661
- * headers: {
662
- * ...
663
- * }
664
- * }
665
- * } )
666
- * .then( ... )
667
- * .catch( ... );
668
- * ```
669
- *
670
- * See the {@glink features/images/image-upload/simple-upload-adapter "Simple upload adapter"} guide to learn how to
671
- * learn more about the feature (configuration, server–side requirements, etc.).
672
- *
673
- * Check out the {@glink features/images/image-upload/image-upload comprehensive "Image upload overview"} to learn about
674
- * other ways to upload images into CKEditor 5.
675
- */
676
- class SimpleUploadAdapter extends Plugin {
677
- /**
678
- * @inheritDoc
679
- */
680
- static get requires() {
681
- return [FileRepository];
682
- }
683
- /**
684
- * @inheritDoc
685
- */
686
- static get pluginName() {
687
- return 'SimpleUploadAdapter';
688
- }
689
- /**
690
- * @inheritDoc
691
- */
692
- init() {
693
- const options = this.editor.config.get('simpleUpload');
694
- if (!options) {
695
- return;
696
- }
697
- if (!options.uploadUrl) {
698
- /**
699
- * The {@link module:upload/uploadconfig~SimpleUploadConfig#uploadUrl `config.simpleUpload.uploadUrl`}
700
- * configuration required by the {@link module:upload/adapters/simpleuploadadapter~SimpleUploadAdapter `SimpleUploadAdapter`}
701
- * is missing. Make sure the correct URL is specified for the image upload to work properly.
702
- *
703
- * @error simple-upload-adapter-missing-uploadurl
704
- */
705
- logWarning('simple-upload-adapter-missing-uploadurl');
706
- return;
707
- }
708
- this.editor.plugins.get(FileRepository).createUploadAdapter = loader => {
709
- return new Adapter(loader, options);
710
- };
711
- }
712
- }
713
- /**
714
- * Upload adapter.
715
- */
716
- class Adapter {
717
- /**
718
- * Creates a new adapter instance.
719
- */
720
- constructor(loader, options) {
721
- this.loader = loader;
722
- this.options = options;
723
- }
724
- /**
725
- * Starts the upload process.
726
- *
727
- * @see module:upload/filerepository~UploadAdapter#upload
728
- */
729
- upload() {
730
- return this.loader.file
731
- .then(file => new Promise((resolve, reject) => {
732
- this._initRequest();
733
- this._initListeners(resolve, reject, file);
734
- this._sendRequest(file);
735
- }));
736
- }
737
- /**
738
- * Aborts the upload process.
739
- *
740
- * @see module:upload/filerepository~UploadAdapter#abort
741
- */
742
- abort() {
743
- if (this.xhr) {
744
- this.xhr.abort();
745
- }
746
- }
747
- /**
748
- * Initializes the `XMLHttpRequest` object using the URL specified as
749
- * {@link module:upload/uploadconfig~SimpleUploadConfig#uploadUrl `simpleUpload.uploadUrl`} in the editor's
750
- * configuration.
751
- */
752
- _initRequest() {
753
- const xhr = this.xhr = new XMLHttpRequest();
754
- xhr.open('POST', this.options.uploadUrl, true);
755
- xhr.responseType = 'json';
756
- }
757
- /**
758
- * Initializes XMLHttpRequest listeners
759
- *
760
- * @param resolve Callback function to be called when the request is successful.
761
- * @param reject Callback function to be called when the request cannot be completed.
762
- * @param file Native File object.
763
- */
764
- _initListeners(resolve, reject, file) {
765
- const xhr = this.xhr;
766
- const loader = this.loader;
767
- const genericErrorText = `Couldn't upload file: ${file.name}.`;
768
- xhr.addEventListener('error', () => reject(genericErrorText));
769
- xhr.addEventListener('abort', () => reject());
770
- xhr.addEventListener('load', () => {
771
- const response = xhr.response;
772
- if (!response || response.error) {
773
- return reject(response && response.error && response.error.message ? response.error.message : genericErrorText);
774
- }
775
- const urls = response.url ? { default: response.url } : response.urls;
776
- // Resolve with the normalized `urls` property and pass the rest of the response
777
- // to allow customizing the behavior of features relying on the upload adapters.
778
- resolve({
779
- ...response,
780
- urls
781
- });
782
- });
783
- // Upload progress when it is supported.
784
- /* istanbul ignore else -- @preserve */
785
- if (xhr.upload) {
786
- xhr.upload.addEventListener('progress', evt => {
787
- if (evt.lengthComputable) {
788
- loader.uploadTotal = evt.total;
789
- loader.uploaded = evt.loaded;
790
- }
791
- });
792
- }
793
- }
794
- /**
795
- * Prepares the data and sends the request.
796
- *
797
- * @param file File instance to be uploaded.
798
- */
799
- _sendRequest(file) {
800
- // Set headers if specified.
801
- const headers = this.options.headers || {};
802
- // Use the withCredentials flag if specified.
803
- const withCredentials = this.options.withCredentials || false;
804
- for (const headerName of Object.keys(headers)) {
805
- this.xhr.setRequestHeader(headerName, headers[headerName]);
806
- }
807
- this.xhr.withCredentials = withCredentials;
808
- // Prepare the form data.
809
- const data = new FormData();
810
- data.append('upload', file);
811
- // Send the request.
812
- this.xhr.send(data);
813
- }
814
- }
815
-
816
- export { Base64UploadAdapter, FileDialogButtonView, FileRepository, SimpleUploadAdapter };
817
- //# sourceMappingURL=index.js.map