@ckeditor/ckeditor5-image 28.0.0 → 30.0.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 (167) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +3 -3
  3. package/build/image.js +1 -1
  4. package/build/translations/ar.js +1 -0
  5. package/build/translations/ast.js +1 -0
  6. package/build/translations/az.js +1 -0
  7. package/build/translations/bg.js +1 -0
  8. package/build/translations/cs.js +1 -0
  9. package/build/translations/da.js +1 -0
  10. package/build/translations/de-ch.js +1 -0
  11. package/build/translations/de.js +1 -0
  12. package/build/translations/el.js +1 -0
  13. package/build/translations/en-au.js +1 -0
  14. package/build/translations/en-gb.js +1 -0
  15. package/build/translations/eo.js +1 -0
  16. package/build/translations/es.js +1 -0
  17. package/build/translations/et.js +1 -0
  18. package/build/translations/eu.js +1 -0
  19. package/build/translations/fa.js +1 -0
  20. package/build/translations/fi.js +1 -0
  21. package/build/translations/fr.js +1 -0
  22. package/build/translations/gl.js +1 -0
  23. package/build/translations/he.js +1 -0
  24. package/build/translations/hi.js +1 -0
  25. package/build/translations/hr.js +1 -0
  26. package/build/translations/hu.js +1 -0
  27. package/build/translations/id.js +1 -0
  28. package/build/translations/it.js +1 -0
  29. package/build/translations/ja.js +1 -0
  30. package/build/translations/km.js +1 -0
  31. package/build/translations/kn.js +1 -0
  32. package/build/translations/ko.js +1 -0
  33. package/build/translations/ku.js +1 -0
  34. package/build/translations/lt.js +1 -0
  35. package/build/translations/lv.js +1 -0
  36. package/build/translations/nb.js +1 -0
  37. package/build/translations/ne.js +1 -0
  38. package/build/translations/nl.js +1 -0
  39. package/build/translations/no.js +1 -0
  40. package/build/translations/pl.js +1 -0
  41. package/build/translations/pt-br.js +1 -0
  42. package/build/translations/pt.js +1 -0
  43. package/build/translations/ro.js +1 -0
  44. package/build/translations/ru.js +1 -0
  45. package/build/translations/si.js +1 -0
  46. package/build/translations/sk.js +1 -0
  47. package/build/translations/sq.js +1 -0
  48. package/build/translations/sr-latn.js +1 -0
  49. package/build/translations/sr.js +1 -0
  50. package/build/translations/sv.js +1 -0
  51. package/build/translations/th.js +1 -0
  52. package/build/translations/tk.js +1 -0
  53. package/build/translations/tr.js +1 -0
  54. package/build/translations/ug.js +1 -0
  55. package/build/translations/uk.js +1 -0
  56. package/build/translations/vi.js +1 -0
  57. package/build/translations/zh-cn.js +1 -0
  58. package/build/translations/zh.js +1 -0
  59. package/ckeditor5-metadata.json +233 -0
  60. package/lang/contexts.json +3 -0
  61. package/lang/translations/ar.po +12 -0
  62. package/lang/translations/ast.po +12 -0
  63. package/lang/translations/az.po +12 -0
  64. package/lang/translations/bg.po +12 -0
  65. package/lang/translations/cs.po +12 -0
  66. package/lang/translations/da.po +12 -0
  67. package/lang/translations/de-ch.po +12 -0
  68. package/lang/translations/de.po +15 -3
  69. package/lang/translations/el.po +12 -0
  70. package/lang/translations/en-au.po +12 -0
  71. package/lang/translations/en-gb.po +12 -0
  72. package/lang/translations/en.po +12 -0
  73. package/lang/translations/eo.po +12 -0
  74. package/lang/translations/es.po +12 -0
  75. package/lang/translations/et.po +12 -0
  76. package/lang/translations/eu.po +12 -0
  77. package/lang/translations/fa.po +12 -0
  78. package/lang/translations/fi.po +12 -0
  79. package/lang/translations/fr.po +12 -0
  80. package/lang/translations/gl.po +12 -0
  81. package/lang/translations/he.po +12 -0
  82. package/lang/translations/hi.po +12 -0
  83. package/lang/translations/hr.po +12 -0
  84. package/lang/translations/hu.po +13 -1
  85. package/lang/translations/id.po +21 -9
  86. package/lang/translations/it.po +12 -0
  87. package/lang/translations/ja.po +12 -0
  88. package/lang/translations/km.po +12 -0
  89. package/lang/translations/kn.po +12 -0
  90. package/lang/translations/ko.po +12 -0
  91. package/lang/translations/ku.po +12 -0
  92. package/lang/translations/lt.po +12 -0
  93. package/lang/translations/lv.po +12 -0
  94. package/lang/translations/nb.po +12 -0
  95. package/lang/translations/ne.po +12 -0
  96. package/lang/translations/nl.po +14 -2
  97. package/lang/translations/no.po +12 -0
  98. package/lang/translations/pl.po +20 -8
  99. package/lang/translations/pt-br.po +12 -0
  100. package/lang/translations/pt.po +12 -0
  101. package/lang/translations/ro.po +21 -9
  102. package/lang/translations/ru.po +12 -0
  103. package/lang/translations/si.po +12 -0
  104. package/lang/translations/sk.po +12 -0
  105. package/lang/translations/sq.po +12 -0
  106. package/lang/translations/sr-latn.po +12 -0
  107. package/lang/translations/sr.po +12 -0
  108. package/lang/translations/sv.po +12 -0
  109. package/lang/translations/th.po +12 -0
  110. package/lang/translations/tk.po +12 -0
  111. package/lang/translations/tr.po +12 -0
  112. package/lang/translations/ug.po +12 -0
  113. package/lang/translations/uk.po +12 -0
  114. package/lang/translations/vi.po +12 -0
  115. package/lang/translations/zh-cn.po +12 -0
  116. package/lang/translations/zh.po +12 -0
  117. package/package.json +36 -29
  118. package/src/autoimage.js +9 -4
  119. package/src/image/converters.js +191 -15
  120. package/src/image/imageblockediting.js +182 -0
  121. package/src/image/imageediting.js +13 -70
  122. package/src/image/imageinlineediting.js +207 -0
  123. package/src/image/imagetypecommand.js +105 -0
  124. package/src/image/insertimagecommand.js +77 -10
  125. package/src/image/ui/utils.js +5 -4
  126. package/src/image/utils.js +65 -121
  127. package/src/image.js +7 -19
  128. package/src/imageblock.js +46 -0
  129. package/src/imagecaption/imagecaptionediting.js +183 -227
  130. package/src/imagecaption/imagecaptionui.js +78 -0
  131. package/src/imagecaption/toggleimagecaptioncommand.js +165 -0
  132. package/src/imagecaption/utils.js +25 -40
  133. package/src/imagecaption.js +3 -2
  134. package/src/imageinline.js +46 -0
  135. package/src/imageinsert/imageinsertui.js +5 -6
  136. package/src/imageinsert.js +16 -4
  137. package/src/imageresize/imageresizebuttons.js +1 -1
  138. package/src/imageresize/imageresizeediting.js +21 -8
  139. package/src/imageresize/imageresizehandles.js +30 -8
  140. package/src/imageresize/resizeimagecommand.js +8 -5
  141. package/src/imagestyle/converters.js +26 -17
  142. package/src/imagestyle/imagestylecommand.js +73 -33
  143. package/src/imagestyle/imagestyleediting.js +113 -52
  144. package/src/imagestyle/imagestyleui.js +197 -31
  145. package/src/imagestyle/utils.js +300 -85
  146. package/src/imagestyle.js +218 -47
  147. package/src/imagetextalternative/imagetextalternativecommand.js +10 -7
  148. package/src/imagetextalternative/imagetextalternativeediting.js +9 -1
  149. package/src/imagetextalternative/imagetextalternativeui.js +2 -2
  150. package/src/imagetextalternative.js +1 -1
  151. package/src/imagetoolbar.js +33 -11
  152. package/src/imageupload/imageuploadediting.js +90 -30
  153. package/src/imageupload/imageuploadprogress.js +17 -9
  154. package/src/imageupload/imageuploadui.js +1 -1
  155. package/src/imageupload/uploadimagecommand.js +50 -24
  156. package/src/imageupload/utils.js +3 -2
  157. package/src/imageupload.js +1 -1
  158. package/src/imageutils.js +342 -0
  159. package/src/pictureediting.js +149 -0
  160. package/theme/image.css +101 -21
  161. package/theme/imagecaption.css +24 -2
  162. package/theme/imageresize.css +11 -0
  163. package/theme/imagestyle.css +76 -0
  164. package/theme/imageuploadicon.css +8 -2
  165. package/theme/imageuploadprogress.css +12 -8
  166. package/CHANGELOG.md +0 -423
  167. package/build/image.js.map +0 -1
@@ -7,155 +7,99 @@
7
7
  * @module image/image/utils
8
8
  */
9
9
 
10
- import { findOptimalInsertionPosition, checkSelectionOnObject, isWidget, toWidget } from 'ckeditor5/src/widget';
10
+ import { first } from 'ckeditor5/src/utils';
11
11
 
12
12
  /**
13
- * Converts a given {@link module:engine/view/element~Element} to an image widget:
14
- * * Adds a {@link module:engine/view/element~Element#_setCustomProperty custom property} allowing to recognize the image widget element.
15
- * * Calls the {@link module:widget/utils~toWidget} function with the proper element's label creator.
13
+ * Creates a view element representing the image of provided image type.
16
14
  *
17
- * @param {module:engine/view/element~Element} viewElement
18
- * @param {module:engine/view/downcastwriter~DowncastWriter} writer An instance of the view writer.
19
- * @param {String} label The element's label. It will be concatenated with the image `alt` attribute if one is present.
20
- * @returns {module:engine/view/element~Element}
21
- */
22
- export function toImageWidget( viewElement, writer, label ) {
23
- writer.setCustomProperty( 'image', true, viewElement );
24
-
25
- return toWidget( viewElement, writer, { label: labelCreator } );
26
-
27
- function labelCreator() {
28
- const imgElement = getViewImgFromWidget( viewElement );
29
- const altText = imgElement.getAttribute( 'alt' );
30
-
31
- return altText ? `${ altText } ${ label }` : label;
32
- }
33
- }
34
-
35
- /**
36
- * Checks if a given view element is an image widget.
15
+ * An 'imageBlock' type (block image):
37
16
  *
38
- * @param {module:engine/view/element~Element} viewElement
39
- * @returns {Boolean}
40
- */
41
- export function isImageWidget( viewElement ) {
42
- return !!viewElement.getCustomProperty( 'image' ) && isWidget( viewElement );
43
- }
44
-
45
- /**
46
- * Returns an image widget editing view element if one is selected.
17
+ * <figure class="image"><img></img></figure>
18
+ *
19
+ * An 'imageInline' type (inline image):
20
+ *
21
+ * <span class="image-inline"><img></img></span>
47
22
  *
48
- * @param {module:engine/view/selection~Selection|module:engine/view/documentselection~DocumentSelection} selection
49
- * @returns {module:engine/view/element~Element|null}
23
+ * Note that `alt` and `src` attributes are converted separately, so they are not included.
24
+ *
25
+ * @protected
26
+ * @param {module:engine/view/downcastwriter~DowncastWriter} writer
27
+ * @param {'imageBlock'|'imageInline'} imageType The type of created image.
28
+ * @returns {module:engine/view/containerelement~ContainerElement}
50
29
  */
51
- export function getSelectedImageWidget( selection ) {
52
- const viewElement = selection.getSelectedElement();
30
+ export function createImageViewElement( writer, imageType ) {
31
+ const emptyElement = writer.createEmptyElement( 'img' );
53
32
 
54
- if ( viewElement && isImageWidget( viewElement ) ) {
55
- return viewElement;
56
- }
33
+ const container = imageType === 'imageBlock' ?
34
+ writer.createContainerElement( 'figure', { class: 'image' } ) :
35
+ writer.createContainerElement( 'span', { class: 'image-inline' }, { isAllowedInsideAttributeElement: true } );
57
36
 
58
- return null;
59
- }
37
+ writer.insert( writer.createPositionAt( container, 0 ), emptyElement );
60
38
 
61
- /**
62
- * Checks if the provided model element is an `image`.
63
- *
64
- * @param {module:engine/model/element~Element} modelElement
65
- * @returns {Boolean}
66
- */
67
- export function isImage( modelElement ) {
68
- return !!modelElement && modelElement.is( 'element', 'image' );
39
+ return container;
69
40
  }
70
41
 
71
42
  /**
72
- * Handles inserting single file. This method unifies image insertion using {@link module:widget/utils~findOptimalInsertionPosition} method.
73
- *
74
- * insertImage( model, { src: 'path/to/image.jpg' } );
43
+ * A function returning a `MatcherPattern` for a particular type of View images.
75
44
  *
76
- * @param {module:engine/model/model~Model} model
77
- * @param {Object} [attributes={}] Attributes of inserted image
78
- * @param {module:engine/model/position~Position} [insertPosition] Position to insert the image. If not specified,
79
- * the {@link module:widget/utils~findOptimalInsertionPosition} logic will be applied.
45
+ * @protected
46
+ * @param {module:core/editor/editor~Editor} editor
47
+ * @param {'imageBlock'|'imageInline'} matchImageType The type of created image.
48
+ * @returns {module:engine/view/matcher~MatcherPattern}
80
49
  */
81
- export function insertImage( model, attributes = {}, insertPosition = null ) {
82
- model.change( writer => {
83
- const imageElement = writer.createElement( 'image', attributes );
84
-
85
- const insertAtSelection = insertPosition || findOptimalInsertionPosition( model.document.selection, model );
50
+ export function getImgViewElementMatcher( editor, matchImageType ) {
51
+ if ( editor.plugins.has( 'ImageInlineEditing' ) !== editor.plugins.has( 'ImageBlockEditing' ) ) {
52
+ return { name: 'img' };
53
+ }
86
54
 
87
- model.insertContent( imageElement, insertAtSelection );
55
+ const imageUtils = editor.plugins.get( 'ImageUtils' );
88
56
 
89
- // Inserting an image might've failed due to schema regulations.
90
- if ( imageElement.parent ) {
91
- writer.setSelection( imageElement, 'on' );
57
+ return element => {
58
+ // Check if view element is an `img`.
59
+ if ( !imageUtils.isInlineImageView( element ) ) {
60
+ return null;
92
61
  }
93
- } );
94
- }
95
62
 
96
- /**
97
- * Checks if image can be inserted at current model selection.
98
- *
99
- * @param {module:engine/model/model~Model} model
100
- * @returns {Boolean}
101
- */
102
- export function isImageAllowed( model ) {
103
- const schema = model.schema;
104
- const selection = model.document.selection;
63
+ // The <img> can be standalone, wrapped in <figure>...</figure> (ImageBlock plugin) or
64
+ // wrapped in <figure><a>...</a></figure> (LinkImage plugin).
65
+ const imageType = element.findAncestor( imageUtils.isBlockImageView ) ? 'imageBlock' : 'imageInline';
66
+
67
+ if ( imageType !== matchImageType ) {
68
+ return null;
69
+ }
105
70
 
106
- return isImageAllowedInParent( selection, schema, model ) &&
107
- !checkSelectionOnObject( selection, schema ) &&
108
- isInOtherImage( selection );
71
+ return { name: true };
72
+ };
109
73
  }
110
74
 
111
75
  /**
112
- * Get view `<img>` element from the view widget (`<figure>`).
76
+ * Considering the current model selection, it returns the name of the model image element
77
+ * (`'imageBlock'` or `'imageInline'`) that will make most sense from the UX perspective if a new
78
+ * image was inserted (also: uploaded, dropped, pasted) at that selection.
113
79
  *
114
- * Assuming that image is always a first child of a widget (ie. `figureView.getChild( 0 )`) is unsafe as other features might
115
- * inject their own elements to the widget.
80
+ * The assumption is that inserting images into empty blocks or on other block widgets should
81
+ * produce block images. Inline images should be inserted in other cases, e.g. in paragraphs
82
+ * that already contain some text.
116
83
  *
117
- * The `<img>` can be wrapped to other elements, e.g. `<a>`. Nested check required.
118
- *
119
- * @param {module:engine/view/element~Element} figureView
120
- * @returns {module:engine/view/element~Element}
84
+ * @protected
85
+ * @param {module:engine/model/schema~Schema} schema
86
+ * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection
87
+ * @returns {'imageBlock'|'imageInline'}
121
88
  */
122
- export function getViewImgFromWidget( figureView ) {
123
- const figureChildren = [];
124
-
125
- for ( const figureChild of figureView.getChildren() ) {
126
- figureChildren.push( figureChild );
89
+ export function determineImageTypeForInsertionAtSelection( schema, selection ) {
90
+ const firstBlock = first( selection.getSelectedBlocks() );
127
91
 
128
- if ( figureChild.is( 'element' ) ) {
129
- figureChildren.push( ...figureChild.getChildren() );
130
- }
92
+ // Insert a block image if the selection is not in/on block elements or it's on a block widget.
93
+ if ( !firstBlock || schema.isObject( firstBlock ) ) {
94
+ return 'imageBlock';
131
95
  }
132
96
 
133
- return figureChildren.find( viewChild => viewChild.is( 'element', 'img' ) );
134
- }
135
-
136
- // Checks if image is allowed by schema in optimal insertion parent.
137
- //
138
- // @returns {Boolean}
139
- function isImageAllowedInParent( selection, schema, model ) {
140
- const parent = getInsertImageParent( selection, model );
141
-
142
- return schema.checkChild( parent, 'image' );
143
- }
144
-
145
- // Checks if selection is placed in other image (ie. in caption).
146
- function isInOtherImage( selection ) {
147
- return [ ...selection.focus.getAncestors() ].every( ancestor => !ancestor.is( 'element', 'image' ) );
148
- }
149
-
150
- // Returns a node that will be used to insert image with `model.insertContent` to check if image can be placed there.
151
- function getInsertImageParent( selection, model ) {
152
- const insertAt = findOptimalInsertionPosition( selection, model );
153
-
154
- const parent = insertAt.parent;
155
-
156
- if ( parent.isEmpty && !parent.is( 'element', '$root' ) ) {
157
- return parent.parent;
97
+ // A block image should also be inserted into an empty block element
98
+ // (that is not an empty list item so the list won't get split).
99
+ if ( firstBlock.isEmpty && firstBlock.name != 'listItem' ) {
100
+ return 'imageBlock';
158
101
  }
159
102
 
160
- return parent;
103
+ // Otherwise insert an inline image.
104
+ return 'imageInline';
161
105
  }
package/src/image.js CHANGED
@@ -8,25 +8,23 @@
8
8
  */
9
9
 
10
10
  import { Plugin } from 'ckeditor5/src/core';
11
- import { Widget } from 'ckeditor5/src/widget';
12
11
 
13
- import ImageEditing from './image/imageediting';
14
- import ImageTextAlternative from './imagetextalternative';
15
- import { isImageWidget } from './image/utils';
12
+ import ImageBlock from './imageblock';
13
+ import ImageInline from './imageinline';
16
14
 
17
15
  import '../theme/image.css';
18
16
 
19
17
  /**
20
18
  * The image plugin.
21
19
  *
22
- * For a detailed overview, check the {@glink features/image image feature} documentation.
20
+ * For a detailed overview, check the {@glink features/images/images-overview image feature} documentation.
23
21
  *
24
22
  * This is a "glue" plugin which loads the following plugins:
25
23
  *
26
- * * {@link module:image/image/imageediting~ImageEditing},
27
- * * {@link module:image/imagetextalternative~ImageTextAlternative}.
24
+ * * {@link module:image/imageblock~ImageBlock},
25
+ * * {@link module:image/imageinline~ImageInline},
28
26
  *
29
- * Usually, it is used in conjuction with other plugins from this package. See the {@glink api/image package page}
27
+ * Usually, it is used in conjunction with other plugins from this package. See the {@glink api/image package page}
30
28
  * for more information.
31
29
  *
32
30
  * @extends module:core/plugin~Plugin
@@ -36,7 +34,7 @@ export default class Image extends Plugin {
36
34
  * @inheritDoc
37
35
  */
38
36
  static get requires() {
39
- return [ ImageEditing, Widget, ImageTextAlternative ];
37
+ return [ ImageBlock, ImageInline ];
40
38
  }
41
39
 
42
40
  /**
@@ -45,16 +43,6 @@ export default class Image extends Plugin {
45
43
  static get pluginName() {
46
44
  return 'Image';
47
45
  }
48
-
49
- /**
50
- * Checks if a given view element is an image widget.
51
- *
52
- * @param {module:engine/view/element~Element} viewElement
53
- * @returns {Boolean}
54
- */
55
- isImageWidget( viewElement ) {
56
- return isImageWidget( viewElement );
57
- }
58
46
  }
59
47
 
60
48
  /**
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module image/imageblock
8
+ */
9
+
10
+ import { Plugin } from 'ckeditor5/src/core';
11
+ import { Widget } from 'ckeditor5/src/widget';
12
+
13
+ import ImageTextAlternative from './imagetextalternative';
14
+ import ImageBlockEditing from './image/imageblockediting';
15
+
16
+ import '../theme/image.css';
17
+
18
+ /**
19
+ * The image inline plugin.
20
+ *
21
+ * This is a "glue" plugin which loads the following plugins:
22
+ *
23
+ * * {@link module:image/image/imageblockediting~ImageBlockEditing},
24
+ * * {@link module:image/imagetextalternative~ImageTextAlternative}.
25
+ *
26
+ * Usually, it is used in conjunction with other plugins from this package. See the {@glink api/image package page}
27
+ * for more information.
28
+ *
29
+ * @extends module:core/plugin~Plugin
30
+ */
31
+ export default class ImageBlock extends Plugin {
32
+ /**
33
+ * @inheritDoc
34
+ */
35
+ static get requires() {
36
+ return [ ImageBlockEditing, Widget, ImageTextAlternative ];
37
+ }
38
+
39
+ /**
40
+ * @inheritDoc
41
+ */
42
+ static get pluginName() {
43
+ return 'ImageBlock';
44
+ }
45
+ }
46
+