@ckeditor/ckeditor5-image 36.0.1 → 37.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 (106) hide show
  1. package/build/image.js +1 -1
  2. package/package.json +40 -35
  3. package/src/autoimage.d.ts +53 -0
  4. package/src/autoimage.js +111 -160
  5. package/src/image/converters.d.ts +66 -0
  6. package/src/image/converters.js +200 -261
  7. package/src/image/imageblockediting.d.ts +57 -0
  8. package/src/image/imageblockediting.js +111 -155
  9. package/src/image/imageediting.d.ts +34 -0
  10. package/src/image/imageediting.js +53 -67
  11. package/src/image/imageinlineediting.d.ts +53 -0
  12. package/src/image/imageinlineediting.js +135 -180
  13. package/src/image/imageloadobserver.d.ts +44 -0
  14. package/src/image/imageloadobserver.js +28 -47
  15. package/src/image/imagetypecommand.d.ts +46 -0
  16. package/src/image/imagetypecommand.js +67 -95
  17. package/src/image/insertimagecommand.d.ts +72 -0
  18. package/src/image/insertimagecommand.js +95 -101
  19. package/src/image/replaceimagesourcecommand.d.ts +39 -0
  20. package/src/image/replaceimagesourcecommand.js +28 -33
  21. package/src/image/ui/utils.d.ts +25 -0
  22. package/src/image/ui/utils.js +25 -35
  23. package/src/image/utils.d.ts +52 -0
  24. package/src/image/utils.js +63 -90
  25. package/src/image.d.ts +38 -0
  26. package/src/image.js +13 -43
  27. package/src/imageblock.d.ts +35 -0
  28. package/src/imageblock.js +12 -21
  29. package/src/imagecaption/imagecaptionediting.d.ts +92 -0
  30. package/src/imagecaption/imagecaptionediting.js +203 -262
  31. package/src/imagecaption/imagecaptionui.d.ts +30 -0
  32. package/src/imagecaption/imagecaptionui.js +46 -63
  33. package/src/imagecaption/imagecaptionutils.d.ts +42 -0
  34. package/src/imagecaption/imagecaptionutils.js +51 -78
  35. package/src/imagecaption/toggleimagecaptioncommand.d.ts +71 -0
  36. package/src/imagecaption/toggleimagecaptioncommand.js +112 -138
  37. package/src/imagecaption.d.ts +29 -0
  38. package/src/imagecaption.js +12 -19
  39. package/src/imageconfig.d.ts +723 -0
  40. package/src/imageconfig.js +5 -0
  41. package/src/imageinline.d.ts +35 -0
  42. package/src/imageinline.js +12 -21
  43. package/src/imageinsert/imageinsertui.d.ts +49 -0
  44. package/src/imageinsert/imageinsertui.js +120 -158
  45. package/src/imageinsert/ui/imageinsertformrowview.d.ts +61 -0
  46. package/src/imageinsert/ui/imageinsertformrowview.js +37 -86
  47. package/src/imageinsert/ui/imageinsertpanelview.d.ts +106 -0
  48. package/src/imageinsert/ui/imageinsertpanelview.js +148 -258
  49. package/src/imageinsert/utils.d.ts +26 -0
  50. package/src/imageinsert/utils.js +42 -58
  51. package/src/imageinsert.d.ts +35 -0
  52. package/src/imageinsert.js +13 -84
  53. package/src/imageinsertviaurl.d.ts +34 -0
  54. package/src/imageinsertviaurl.js +12 -18
  55. package/src/imageresize/imageresizebuttons.d.ts +66 -0
  56. package/src/imageresize/imageresizebuttons.js +190 -255
  57. package/src/imageresize/imageresizeediting.d.ts +42 -0
  58. package/src/imageresize/imageresizeediting.js +100 -125
  59. package/src/imageresize/imageresizehandles.d.ts +30 -0
  60. package/src/imageresize/imageresizehandles.js +91 -123
  61. package/src/imageresize/resizeimagecommand.d.ts +47 -0
  62. package/src/imageresize/resizeimagecommand.js +48 -55
  63. package/src/imageresize.d.ts +29 -0
  64. package/src/imageresize.js +12 -209
  65. package/src/imagestyle/converters.d.ts +24 -0
  66. package/src/imagestyle/converters.js +60 -78
  67. package/src/imagestyle/imagestylecommand.d.ts +70 -0
  68. package/src/imagestyle/imagestylecommand.js +88 -124
  69. package/src/imagestyle/imagestyleediting.d.ts +54 -0
  70. package/src/imagestyle/imagestyleediting.js +90 -137
  71. package/src/imagestyle/imagestyleui.d.ts +60 -0
  72. package/src/imagestyle/imagestyleui.js +169 -277
  73. package/src/imagestyle/utils.d.ts +61 -0
  74. package/src/imagestyle/utils.js +253 -306
  75. package/src/imagestyle.d.ts +35 -0
  76. package/src/imagestyle.js +13 -261
  77. package/src/imagetextalternative/imagetextalternativecommand.d.ts +39 -0
  78. package/src/imagetextalternative/imagetextalternativecommand.js +31 -47
  79. package/src/imagetextalternative/imagetextalternativeediting.d.ts +32 -0
  80. package/src/imagetextalternative/imagetextalternativeediting.js +18 -25
  81. package/src/imagetextalternative/imagetextalternativeui.d.ts +72 -0
  82. package/src/imagetextalternative/imagetextalternativeui.js +156 -219
  83. package/src/imagetextalternative/ui/textalternativeformview.d.ts +72 -0
  84. package/src/imagetextalternative/ui/textalternativeformview.js +103 -192
  85. package/src/imagetextalternative.d.ts +32 -0
  86. package/src/imagetextalternative.js +12 -18
  87. package/src/imagetoolbar.d.ts +38 -0
  88. package/src/imagetoolbar.js +31 -77
  89. package/src/imageupload/imageuploadediting.d.ts +114 -0
  90. package/src/imageupload/imageuploadediting.js +308 -427
  91. package/src/imageupload/imageuploadprogress.d.ts +47 -0
  92. package/src/imageupload/imageuploadprogress.js +180 -261
  93. package/src/imageupload/imageuploadui.d.ts +29 -0
  94. package/src/imageupload/imageuploadui.js +41 -57
  95. package/src/imageupload/uploadimagecommand.d.ts +65 -0
  96. package/src/imageupload/uploadimagecommand.js +73 -87
  97. package/src/imageupload/utils.d.ts +33 -0
  98. package/src/imageupload/utils.js +87 -112
  99. package/src/imageupload.d.ts +34 -0
  100. package/src/imageupload.js +12 -61
  101. package/src/imageutils.d.ts +108 -0
  102. package/src/imageutils.js +233 -329
  103. package/src/index.d.ts +31 -0
  104. package/src/index.js +0 -2
  105. package/src/pictureediting.d.ts +86 -0
  106. package/src/pictureediting.js +101 -120
@@ -2,15 +2,10 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
- /**
7
- * @module image/imageupload/imageuploadui
8
- */
9
-
10
5
  import { Plugin, icons } from 'ckeditor5/src/core';
11
6
  import { FileDialogButtonView } from 'ckeditor5/src/upload';
12
7
  import { createImageTypeRegExp } from './utils';
13
-
8
+ import '../imageconfig';
14
9
  /**
15
10
  * The image upload button plugin.
16
11
  *
@@ -18,57 +13,46 @@ import { createImageTypeRegExp } from './utils';
18
13
  *
19
14
  * Adds the `'uploadImage'` button to the {@link module:ui/componentfactory~ComponentFactory UI component factory}
20
15
  * and also the `imageUpload` button as an alias for backward compatibility.
21
- *
22
- * @extends module:core/plugin~Plugin
23
16
  */
24
17
  export default class ImageUploadUI extends Plugin {
25
- /**
26
- * @inheritDoc
27
- */
28
- static get pluginName() {
29
- return 'ImageUploadUI';
30
- }
31
-
32
- /**
33
- * @inheritDoc
34
- */
35
- init() {
36
- const editor = this.editor;
37
- const t = editor.t;
38
- const componentCreator = locale => {
39
- const view = new FileDialogButtonView( locale );
40
- const command = editor.commands.get( 'uploadImage' );
41
- const imageTypes = editor.config.get( 'image.upload.types' );
42
- const imageTypesRegExp = createImageTypeRegExp( imageTypes );
43
-
44
- view.set( {
45
- acceptedType: imageTypes.map( type => `image/${ type }` ).join( ',' ),
46
- allowMultipleFiles: true
47
- } );
48
-
49
- view.buttonView.set( {
50
- label: t( 'Insert image' ),
51
- icon: icons.image,
52
- tooltip: true
53
- } );
54
-
55
- view.buttonView.bind( 'isEnabled' ).to( command );
56
-
57
- view.on( 'done', ( evt, files ) => {
58
- const imagesToUpload = Array.from( files ).filter( file => imageTypesRegExp.test( file.type ) );
59
-
60
- if ( imagesToUpload.length ) {
61
- editor.execute( 'uploadImage', { file: imagesToUpload } );
62
-
63
- editor.editing.view.focus();
64
- }
65
- } );
66
-
67
- return view;
68
- };
69
-
70
- // Setup `uploadImage` button and add `imageUpload` button as an alias for backward compatibility.
71
- editor.ui.componentFactory.add( 'uploadImage', componentCreator );
72
- editor.ui.componentFactory.add( 'imageUpload', componentCreator );
73
- }
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ static get pluginName() {
22
+ return 'ImageUploadUI';
23
+ }
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ init() {
28
+ const editor = this.editor;
29
+ const t = editor.t;
30
+ const componentCreator = (locale) => {
31
+ const view = new FileDialogButtonView(locale);
32
+ const command = editor.commands.get('uploadImage');
33
+ const imageTypes = editor.config.get('image.upload.types');
34
+ const imageTypesRegExp = createImageTypeRegExp(imageTypes);
35
+ view.set({
36
+ acceptedType: imageTypes.map(type => `image/${type}`).join(','),
37
+ allowMultipleFiles: true
38
+ });
39
+ view.buttonView.set({
40
+ label: t('Insert image'),
41
+ icon: icons.image,
42
+ tooltip: true
43
+ });
44
+ view.buttonView.bind('isEnabled').to(command);
45
+ view.on('done', (evt, files) => {
46
+ const imagesToUpload = Array.from(files).filter(file => imageTypesRegExp.test(file.type));
47
+ if (imagesToUpload.length) {
48
+ editor.execute('uploadImage', { file: imagesToUpload });
49
+ editor.editing.view.focus();
50
+ }
51
+ });
52
+ return view;
53
+ };
54
+ // Setup `uploadImage` button and add `imageUpload` button as an alias for backward compatibility.
55
+ editor.ui.componentFactory.add('uploadImage', componentCreator);
56
+ editor.ui.componentFactory.add('imageUpload', componentCreator);
57
+ }
74
58
  }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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 { Command } from 'ckeditor5/src/core';
6
+ import { type ArrayOrItem } from 'ckeditor5/src/utils';
7
+ /**
8
+ * @module image/imageupload/uploadimagecommand
9
+ */
10
+ /**
11
+ * The upload image command.
12
+ *
13
+ * The command is registered by the {@link module:image/imageupload/imageuploadediting~ImageUploadEditing} plugin as `uploadImage`
14
+ * and it is also available via aliased `imageUpload` name.
15
+ *
16
+ * In order to upload an image at the current selection position
17
+ * (according to the {@link module:widget/utils~findOptimalInsertionRange} algorithm),
18
+ * execute the command and pass the native image file instance:
19
+ *
20
+ * ```ts
21
+ * this.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
22
+ * // Assuming that only images were pasted:
23
+ * const images = Array.from( data.dataTransfer.files );
24
+ *
25
+ * // Upload the first image:
26
+ * editor.execute( 'uploadImage', { file: images[ 0 ] } );
27
+ * } );
28
+ * ```
29
+ *
30
+ * It is also possible to insert multiple images at once:
31
+ *
32
+ * ```ts
33
+ * editor.execute( 'uploadImage', {
34
+ * file: [
35
+ * file1,
36
+ * file2
37
+ * ]
38
+ * } );
39
+ * ```
40
+ */
41
+ export default class UploadImageCommand extends Command {
42
+ /**
43
+ * @inheritDoc
44
+ */
45
+ refresh(): void;
46
+ /**
47
+ * Executes the command.
48
+ *
49
+ * @fires execute
50
+ * @param options Options for the executed command.
51
+ * @param options.file The image file or an array of image files to upload.
52
+ */
53
+ execute(options: {
54
+ file: ArrayOrItem<File>;
55
+ }): void;
56
+ /**
57
+ * Handles uploading single file.
58
+ */
59
+ private _uploadImage;
60
+ }
61
+ declare module '@ckeditor/ckeditor5-core' {
62
+ interface CommandsMap {
63
+ uploadImage: UploadImageCommand;
64
+ }
65
+ }
@@ -2,15 +2,12 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  import { FileRepository } from 'ckeditor5/src/upload';
7
6
  import { Command } from 'ckeditor5/src/core';
8
7
  import { toArray } from 'ckeditor5/src/utils';
9
-
10
8
  /**
11
9
  * @module image/imageupload/uploadimagecommand
12
10
  */
13
-
14
11
  /**
15
12
  * The upload image command.
16
13
  *
@@ -21,94 +18,83 @@ import { toArray } from 'ckeditor5/src/utils';
21
18
  * (according to the {@link module:widget/utils~findOptimalInsertionRange} algorithm),
22
19
  * execute the command and pass the native image file instance:
23
20
  *
24
- * this.listenTo( editor.editing.view.document, 'clipboardInput', ( evt, data ) => {
25
- * // Assuming that only images were pasted:
26
- * const images = Array.from( data.dataTransfer.files );
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 );
27
25
  *
28
- * // Upload the first image:
29
- * editor.execute( 'uploadImage', { file: images[ 0 ] } );
30
- * } );
26
+ * // Upload the first image:
27
+ * editor.execute( 'uploadImage', { file: images[ 0 ] } );
28
+ * } );
29
+ * ```
31
30
  *
32
31
  * It is also possible to insert multiple images at once:
33
32
  *
34
- * editor.execute( 'uploadImage', {
35
- * file: [
36
- * file1,
37
- * file2
38
- * ]
39
- * } );
40
- *
41
- * @extends module:core/command~Command
33
+ * ```ts
34
+ * editor.execute( 'uploadImage', {
35
+ * file: [
36
+ * file1,
37
+ * file2
38
+ * ]
39
+ * } );
40
+ * ```
42
41
  */
43
42
  export default class UploadImageCommand extends Command {
44
- /**
45
- * @inheritDoc
46
- */
47
- refresh() {
48
- const editor = this.editor;
49
- const imageUtils = editor.plugins.get( 'ImageUtils' );
50
- const selectedElement = editor.model.document.selection.getSelectedElement();
51
-
52
- // TODO: This needs refactoring.
53
- this.isEnabled = imageUtils.isImageAllowed() || imageUtils.isImage( selectedElement );
54
- }
55
-
56
- /**
57
- * Executes the command.
58
- *
59
- * @fires execute
60
- * @param {Object} options Options for the executed command.
61
- * @param {File|Array.<File>} options.file The image file or an array of image files to upload.
62
- */
63
- execute( options ) {
64
- const files = toArray( options.file );
65
- const selection = this.editor.model.document.selection;
66
- const imageUtils = this.editor.plugins.get( 'ImageUtils' );
67
-
68
- // In case of multiple files, each file (starting from the 2nd) will be inserted at a position that
69
- // follows the previous one. That will move the selection and, to stay on the safe side and make sure
70
- // all images inherit the same selection attributes, they are collected beforehand.
71
- //
72
- // Applying these attributes ensures, for instance, that inserting an (inline) image into a link does
73
- // not split that link but preserves its continuity.
74
- //
75
- // Note: Selection attributes that do not make sense for images will be filtered out by insertImage() anyway.
76
- const selectionAttributes = Object.fromEntries( selection.getAttributes() );
77
-
78
- files.forEach( ( file, index ) => {
79
- const selectedElement = selection.getSelectedElement();
80
-
81
- // Inserting of an inline image replace the selected element and make a selection on the inserted image.
82
- // Therefore inserting multiple inline images requires creating position after each element.
83
- if ( index && selectedElement && imageUtils.isImage( selectedElement ) ) {
84
- const position = this.editor.model.createPositionAfter( selectedElement );
85
-
86
- this._uploadImage( file, selectionAttributes, position );
87
- } else {
88
- this._uploadImage( file, selectionAttributes );
89
- }
90
- } );
91
- }
92
-
93
- /**
94
- * Handles uploading single file.
95
- *
96
- * @private
97
- * @param {File} file
98
- * @param {Object} attributes
99
- * @param {module:engine/model/position~Position} position
100
- */
101
- _uploadImage( file, attributes, position ) {
102
- const editor = this.editor;
103
- const fileRepository = editor.plugins.get( FileRepository );
104
- const loader = fileRepository.createLoader( file );
105
- const imageUtils = editor.plugins.get( 'ImageUtils' );
106
-
107
- // Do not throw when upload adapter is not set. FileRepository will log an error anyway.
108
- if ( !loader ) {
109
- return;
110
- }
111
-
112
- imageUtils.insertImage( { ...attributes, uploadId: loader.id }, position );
113
- }
43
+ /**
44
+ * @inheritDoc
45
+ */
46
+ refresh() {
47
+ const editor = this.editor;
48
+ const imageUtils = editor.plugins.get('ImageUtils');
49
+ const selectedElement = editor.model.document.selection.getSelectedElement();
50
+ // TODO: This needs refactoring.
51
+ this.isEnabled = imageUtils.isImageAllowed() || imageUtils.isImage(selectedElement);
52
+ }
53
+ /**
54
+ * Executes the command.
55
+ *
56
+ * @fires execute
57
+ * @param options Options for the executed command.
58
+ * @param options.file The image file or an array of image files to upload.
59
+ */
60
+ execute(options) {
61
+ const files = toArray(options.file);
62
+ const selection = this.editor.model.document.selection;
63
+ const imageUtils = this.editor.plugins.get('ImageUtils');
64
+ // In case of multiple files, each file (starting from the 2nd) will be inserted at a position that
65
+ // follows the previous one. That will move the selection and, to stay on the safe side and make sure
66
+ // all images inherit the same selection attributes, they are collected beforehand.
67
+ //
68
+ // Applying these attributes ensures, for instance, that inserting an (inline) image into a link does
69
+ // not split that link but preserves its continuity.
70
+ //
71
+ // Note: Selection attributes that do not make sense for images will be filtered out by insertImage() anyway.
72
+ const selectionAttributes = Object.fromEntries(selection.getAttributes());
73
+ files.forEach((file, index) => {
74
+ const selectedElement = selection.getSelectedElement();
75
+ // Inserting of an inline image replace the selected element and make a selection on the inserted image.
76
+ // Therefore inserting multiple inline images requires creating position after each element.
77
+ if (index && selectedElement && imageUtils.isImage(selectedElement)) {
78
+ const position = this.editor.model.createPositionAfter(selectedElement);
79
+ this._uploadImage(file, selectionAttributes, position);
80
+ }
81
+ else {
82
+ this._uploadImage(file, selectionAttributes);
83
+ }
84
+ });
85
+ }
86
+ /**
87
+ * Handles uploading single file.
88
+ */
89
+ _uploadImage(file, attributes, position) {
90
+ const editor = this.editor;
91
+ const fileRepository = editor.plugins.get(FileRepository);
92
+ const loader = fileRepository.createLoader(file);
93
+ const imageUtils = editor.plugins.get('ImageUtils');
94
+ // Do not throw when upload adapter is not set. FileRepository will log an error anyway.
95
+ if (!loader) {
96
+ return;
97
+ }
98
+ imageUtils.insertImage({ ...attributes, uploadId: loader.id }, position);
99
+ }
114
100
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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
+ /**
6
+ * @module image/imageupload/utils
7
+ */
8
+ import type { ViewElement } from 'ckeditor5/src/engine';
9
+ import type ImageUtils from '../imageutils';
10
+ /**
11
+ * Creates a regular expression used to test for image files.
12
+ *
13
+ * ```ts
14
+ * const imageType = createImageTypeRegExp( [ 'png', 'jpeg', 'svg+xml', 'vnd.microsoft.icon' ] );
15
+ *
16
+ * console.log( 'is supported image', imageType.test( file.type ) );
17
+ * ```
18
+ */
19
+ export declare function createImageTypeRegExp(types: Array<string>): RegExp;
20
+ /**
21
+ * Creates a promise that fetches the image local source (Base64 or blob) and resolves with a `File` object.
22
+ *
23
+ * @param image Image whose source to fetch.
24
+ * @returns A promise which resolves when an image source is fetched and converted to a `File` instance.
25
+ * It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.
26
+ */
27
+ export declare function fetchLocalImage(image: ViewElement): Promise<File>;
28
+ /**
29
+ * Checks whether a given node is an image element with a local source (Base64 or blob).
30
+ *
31
+ * @param node The node to check.
32
+ */
33
+ export declare function isLocalImage(imageUtils: ImageUtils, node: ViewElement): boolean;
@@ -2,136 +2,111 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
- /**
7
- * @module image/imageupload/utils
8
- */
9
-
10
- /* global fetch, File */
11
-
12
5
  import { global } from 'ckeditor5/src/utils';
13
-
14
6
  /**
15
7
  * Creates a regular expression used to test for image files.
16
8
  *
17
- * const imageType = createImageTypeRegExp( [ 'png', 'jpeg', 'svg+xml', 'vnd.microsoft.icon' ] );
18
- *
19
- * console.log( 'is supported image', imageType.test( file.type ) );
9
+ * ```ts
10
+ * const imageType = createImageTypeRegExp( [ 'png', 'jpeg', 'svg+xml', 'vnd.microsoft.icon' ] );
20
11
  *
21
- * @param {Array.<String>} types
22
- * @returns {RegExp}
12
+ * console.log( 'is supported image', imageType.test( file.type ) );
13
+ * ```
23
14
  */
24
- export function createImageTypeRegExp( types ) {
25
- // Sanitize the MIME type name which may include: "+", "-" or ".".
26
- const regExpSafeNames = types.map( type => type.replace( '+', '\\+' ) );
27
-
28
- return new RegExp( `^image\\/(${ regExpSafeNames.join( '|' ) })$` );
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('|')})$`);
29
19
  }
30
-
31
20
  /**
32
21
  * Creates a promise that fetches the image local source (Base64 or blob) and resolves with a `File` object.
33
22
  *
34
- * @param {module:engine/view/element~Element} image Image whose source to fetch.
35
- * @returns {Promise.<File>} A promise which resolves when an image source is fetched and converted to a `File` instance.
23
+ * @param image Image whose source to fetch.
24
+ * @returns A promise which resolves when an image source is fetched and converted to a `File` instance.
36
25
  * It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.
37
26
  */
38
- export function fetchLocalImage( image ) {
39
- return new Promise( ( resolve, reject ) => {
40
- const imageSrc = image.getAttribute( 'src' );
41
-
42
- // Fetch works asynchronously and so does not block browser UI when processing data.
43
- fetch( imageSrc )
44
- .then( resource => resource.blob() )
45
- .then( blob => {
46
- const mimeType = getImageMimeType( blob, imageSrc );
47
- const ext = mimeType.replace( 'image/', '' );
48
- const filename = `image.${ ext }`;
49
- const file = new File( [ blob ], filename, { type: mimeType } );
50
-
51
- resolve( file );
52
- } )
53
- .catch( err => {
54
- // Fetch fails only, if it can't make a request due to a network failure or if anything prevented the request
55
- // from completing, i.e. the Content Security Policy rules. It is not possible to detect the exact cause of failure,
56
- // so we are just trying the fallback solution, if general TypeError is thrown.
57
- return err && err.name === 'TypeError' ?
58
- convertLocalImageOnCanvas( imageSrc ).then( resolve ).catch( reject ) :
59
- reject( err );
60
- } );
61
- } );
27
+ export function fetchLocalImage(image) {
28
+ return new Promise((resolve, reject) => {
29
+ const imageSrc = image.getAttribute('src');
30
+ // Fetch works asynchronously and so does not block browser UI when processing data.
31
+ fetch(imageSrc)
32
+ .then(resource => resource.blob())
33
+ .then(blob => {
34
+ const mimeType = getImageMimeType(blob, imageSrc);
35
+ const ext = mimeType.replace('image/', '');
36
+ const filename = `image.${ext}`;
37
+ const file = new File([blob], filename, { type: mimeType });
38
+ resolve(file);
39
+ })
40
+ .catch(err => {
41
+ // Fetch fails only, if it can't make a request due to a network failure or if anything prevented the request
42
+ // from completing, i.e. the Content Security Policy rules. It is not possible to detect the exact cause of failure,
43
+ // so we are just trying the fallback solution, if general TypeError is thrown.
44
+ return err && err.name === 'TypeError' ?
45
+ convertLocalImageOnCanvas(imageSrc).then(resolve).catch(reject) :
46
+ reject(err);
47
+ });
48
+ });
62
49
  }
63
-
64
50
  /**
65
51
  * Checks whether a given node is an image element with a local source (Base64 or blob).
66
52
  *
67
- * @param {module:image/imageutils~ImageUtils} imageUtils
68
- * @param {module:engine/view/node~Node} node The node to check.
69
- * @returns {Boolean}
53
+ * @param node The node to check.
70
54
  */
71
- export function isLocalImage( imageUtils, node ) {
72
- if ( !imageUtils.isInlineImageView( node ) || !node.getAttribute( 'src' ) ) {
73
- return false;
74
- }
75
-
76
- return node.getAttribute( 'src' ).match( /^data:image\/\w+;base64,/g ) ||
77
- node.getAttribute( 'src' ).match( /^blob:/g );
55
+ export function isLocalImage(imageUtils, node) {
56
+ if (!imageUtils.isInlineImageView(node) || !node.getAttribute('src')) {
57
+ return false;
58
+ }
59
+ return !!node.getAttribute('src').match(/^data:image\/\w+;base64,/g) ||
60
+ !!node.getAttribute('src').match(/^blob:/g);
78
61
  }
79
-
80
- // Extracts an image type based on its blob representation or its source.
81
- //
82
- // @param {String} src Image `src` attribute value.
83
- // @param {Blob} blob Image blob representation.
84
- // @returns {String}
85
- function getImageMimeType( blob, src ) {
86
- if ( blob.type ) {
87
- return blob.type;
88
- } else if ( src.match( /data:(image\/\w+);base64/ ) ) {
89
- return src.match( /data:(image\/\w+);base64/ )[ 1 ].toLowerCase();
90
- } else {
91
- // Fallback to 'jpeg' as common extension.
92
- return 'image/jpeg';
93
- }
62
+ /**
63
+ * Extracts an image type based on its blob representation or its source.
64
+ * @param blob Image blob representation.
65
+ * @param src Image `src` attribute value.
66
+ */
67
+ function getImageMimeType(blob, src) {
68
+ if (blob.type) {
69
+ return blob.type;
70
+ }
71
+ else if (src.match(/data:(image\/\w+);base64/)) {
72
+ return src.match(/data:(image\/\w+);base64/)[1].toLowerCase();
73
+ }
74
+ else {
75
+ // Fallback to 'jpeg' as common extension.
76
+ return 'image/jpeg';
77
+ }
94
78
  }
95
-
96
- // Creates a promise that converts the image local source (Base64 or blob) to a blob using canvas and resolves
97
- // with a `File` object.
98
- //
99
- // @param {String} imageSrc Image `src` attribute value.
100
- // @returns {Promise.<File>} A promise which resolves when an image source is converted to a `File` instance.
101
- // It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.
102
- function convertLocalImageOnCanvas( imageSrc ) {
103
- return getBlobFromCanvas( imageSrc ).then( blob => {
104
- const mimeType = getImageMimeType( blob, imageSrc );
105
- const ext = mimeType.replace( 'image/', '' );
106
- const filename = `image.${ ext }`;
107
-
108
- return new File( [ blob ], filename, { type: mimeType } );
109
- } );
79
+ /**
80
+ * Creates a promise that converts the image local source (Base64 or blob) to a blob using canvas and resolves
81
+ * with a `File` object.
82
+ * @param imageSrc Image `src` attribute value.
83
+ * @returns A promise which resolves when an image source is converted to a `File` instance.
84
+ * It resolves with a `File` object. If there were any errors during file processing, the promise will be rejected.
85
+ */
86
+ function convertLocalImageOnCanvas(imageSrc) {
87
+ return getBlobFromCanvas(imageSrc).then(blob => {
88
+ const mimeType = getImageMimeType(blob, imageSrc);
89
+ const ext = mimeType.replace('image/', '');
90
+ const filename = `image.${ext}`;
91
+ return new File([blob], filename, { type: mimeType });
92
+ });
110
93
  }
111
-
112
- // Creates a promise that resolves with a `Blob` object converted from the image source (Base64 or blob).
113
- //
114
- // @param {String} imageSrc Image `src` attribute value.
115
- // @returns {Promise.<Blob>}
116
- function getBlobFromCanvas( imageSrc ) {
117
- return new Promise( ( resolve, reject ) => {
118
- const image = global.document.createElement( 'img' );
119
-
120
- image.addEventListener( 'load', () => {
121
- const canvas = global.document.createElement( 'canvas' );
122
-
123
- canvas.width = image.width;
124
- canvas.height = image.height;
125
-
126
- const ctx = canvas.getContext( '2d' );
127
-
128
- ctx.drawImage( image, 0, 0 );
129
-
130
- canvas.toBlob( blob => blob ? resolve( blob ) : reject() );
131
- } );
132
-
133
- image.addEventListener( 'error', () => reject() );
134
-
135
- image.src = imageSrc;
136
- } );
94
+ /**
95
+ * Creates a promise that resolves with a `Blob` object converted from the image source (Base64 or blob).
96
+ * @param imageSrc Image `src` attribute value.
97
+ */
98
+ function getBlobFromCanvas(imageSrc) {
99
+ return new Promise((resolve, reject) => {
100
+ const image = global.document.createElement('img');
101
+ image.addEventListener('load', () => {
102
+ const canvas = global.document.createElement('canvas');
103
+ canvas.width = image.width;
104
+ canvas.height = image.height;
105
+ const ctx = canvas.getContext('2d');
106
+ ctx.drawImage(image, 0, 0);
107
+ canvas.toBlob(blob => blob ? resolve(blob) : reject());
108
+ });
109
+ image.addEventListener('error', () => reject());
110
+ image.src = imageSrc;
111
+ });
137
112
  }