@ckeditor/ckeditor5-image 32.0.0 → 33.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.
@@ -1 +1 @@
1
- !function(e){const i=e.el=e.el||{};i.dictionary=Object.assign(i.dictionary||{},{"Break text":"","Centered image":"","Change image text alternative":"Αλλαγή εναλλακτικού κείμενου","Enter image caption":"Λεζάντα","Full size image":"Εικόνα πλήρης μεγέθους","Image resize list":"","Image toolbar":"","image widget":"","In line":"",Insert:"","Insert image":"Εισαγωγή εικόνας","Insert image via URL":"","Left aligned image":"",Original:"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Right aligned image":"","Side image":"","Text alternative":"Εναλλακτικό κείμενο",Update:"","Update image URL":"","Upload failed":"","Wrap text":""})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
1
+ !function(e){const i=e.el=e.el||{};i.dictionary=Object.assign(i.dictionary||{},{"Break text":"Κατάτμηση κειμένου","Centered image":"Εικόνα με στοίχιση στο κέντρο","Change image text alternative":"Αλλαγή εναλλακτικού κείμενου εικόνας","Enter image caption":"Εισαγωγή λεζάντας εικόνας","Full size image":"Εικόνα σε πλήρες μέγεθος","Image resize list":"Λίστα μεγεθών εικόνων","Image toolbar":"Γραμμή εργαλείων εικόνας","image widget":"Γραφικό στοιχείο εικόνας","In line":"Εντός γραμμής",Insert:"Εισαγωγή","Insert image":"Εισαγωγή εικόνας","Insert image via URL":"Εισαγωγή εικόνας μέσω διεύθυνσης","Left aligned image":"Εικόνα με αριστερή στοίχιση",Original:"Αρχικό","Resize image":"Αλλαγή μεγέθους εικόνας","Resize image to %0":"Αλλαγή μεγέθους σε %0","Resize image to the original size":"Αλλαγή μεγέθους εικόνας στο αρχικό μέγεθος","Right aligned image":"Εικόνα με δεξιά στοίχιση","Side image":"Πλευρική εικόνα","Text alternative":"Εναλλακτικό κείμενο",Update:"Ενημέρωση","Update image URL":"Ενημέρωση διεύθυνσης εικόνας","Upload failed":"Η αποστολή απέτυχε","Wrap text":"Αναδίπλωση κειμένου"})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
@@ -1 +1 @@
1
- !function(a){const e=a.es=a.es||{};e.dictionary=Object.assign(e.dictionary||{},{"Break text":"","Centered image":"Imagen centrada","Change image text alternative":"Cambiar el texto alternativo de la imagen","Enter image caption":"Introducir título de la imagen","Full size image":"Imagen a tamaño completo","Image resize list":"","Image toolbar":"Barra de herramientas de imagen","image widget":"Widget de imagen","In line":"",Insert:"Insertar","Insert image":"Insertar imagen","Insert image via URL":"Insertar imagen vía URL","Left aligned image":"Imagen alineada a la izquierda",Original:"Original","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Right aligned image":"Imagen alineada a la derecha","Side image":"Imagen lateral","Text alternative":"Texto alternativo",Update:"Actualizar","Update image URL":"Actualizar imagen vía URL","Upload failed":"Fallo en la subida","Wrap text":""})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
1
+ !function(a){const e=a.es=a.es||{};e.dictionary=Object.assign(e.dictionary||{},{"Break text":"Permitir quebrar texto","Centered image":"Imagen centrada","Change image text alternative":"Cambiar el texto alternativo de la imagen","Enter image caption":"Introducir título de la imagen","Full size image":"Imagen a tamaño completo","Image resize list":"Listado para redimensionar imagen","Image toolbar":"Barra de herramientas de imagen","image widget":"Widget de imagen","In line":"En línea",Insert:"Insertar","Insert image":"Insertar imagen","Insert image via URL":"Insertar imagen vía URL","Left aligned image":"Imagen alineada a la izquierda",Original:"Original","Resize image":"Redimensionar imagen","Resize image to %0":"Redimensionar imagen al %0","Resize image to the original size":"Redimensionar imagen al tamaño original","Right aligned image":"Imagen alineada a la derecha","Side image":"Imagen lateral","Text alternative":"Texto alternativo",Update:"Actualizar","Update image URL":"Actualizar imagen vía URL","Upload failed":"Fallo en la subida","Wrap text":"Mantener texto unido"})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
@@ -18,43 +18,43 @@ msgstr ""
18
18
 
19
19
  msgctxt "The label for the image widget."
20
20
  msgid "image widget"
21
- msgstr ""
21
+ msgstr "Γραφικό στοιχείο εικόνας"
22
22
 
23
23
  msgctxt "The label for the image style button that wraps text around the image."
24
24
  msgid "Wrap text"
25
- msgstr ""
25
+ msgstr "Αναδίπλωση κειμένου"
26
26
 
27
27
  msgctxt "The label for the image style button that breaks the text around the image."
28
28
  msgid "Break text"
29
- msgstr ""
29
+ msgstr "Κατάτμηση κειμένου"
30
30
 
31
31
  msgctxt "The label for the image style button that places the image inside the line of text."
32
32
  msgid "In line"
33
- msgstr ""
33
+ msgstr "Εντός γραμμής"
34
34
 
35
35
  msgctxt "The label for the Side image option."
36
36
  msgid "Side image"
37
- msgstr ""
37
+ msgstr "Πλευρική εικόνα"
38
38
 
39
39
  msgctxt "The label for the Full size image option."
40
40
  msgid "Full size image"
41
- msgstr "Εικόνα πλήρης μεγέθους"
41
+ msgstr "Εικόνα σε πλήρες μέγεθος"
42
42
 
43
43
  msgctxt "The label for the Left aligned image option."
44
44
  msgid "Left aligned image"
45
- msgstr ""
45
+ msgstr "Εικόνα με αριστερή στοίχιση"
46
46
 
47
47
  msgctxt "The label for the Centered image option."
48
48
  msgid "Centered image"
49
- msgstr ""
49
+ msgstr "Εικόνα με στοίχιση στο κέντρο"
50
50
 
51
51
  msgctxt "The label for the Right aligned image option."
52
52
  msgid "Right aligned image"
53
- msgstr ""
53
+ msgstr "Εικόνα με δεξιά στοίχιση"
54
54
 
55
55
  msgctxt "The label for the Change image text alternative button."
56
56
  msgid "Change image text alternative"
57
- msgstr "Αλλαγή εναλλακτικού κείμενου"
57
+ msgstr "Αλλαγή εναλλακτικού κείμενου εικόνας"
58
58
 
59
59
  msgctxt "The label for the image text alternative input."
60
60
  msgid "Text alternative"
@@ -62,7 +62,7 @@ msgstr "Εναλλακτικό κείμενο"
62
62
 
63
63
  msgctxt "The placeholder text for the image caption displayed when the caption is empty."
64
64
  msgid "Enter image caption"
65
- msgstr "Λεζάντα"
65
+ msgstr "Εισαγωγή λεζάντας εικόνας"
66
66
 
67
67
  msgctxt "The label for the insert image toolbar button."
68
68
  msgid "Insert image"
@@ -70,44 +70,44 @@ msgstr "Εισαγωγή εικόνας"
70
70
 
71
71
  msgctxt "The title of the notification displayed when upload fails."
72
72
  msgid "Upload failed"
73
- msgstr ""
73
+ msgstr "Η αποστολή απέτυχε"
74
74
 
75
75
  msgctxt "The label used by assistive technologies describing an image toolbar attached to an image widget."
76
76
  msgid "Image toolbar"
77
- msgstr ""
77
+ msgstr "Γραμμή εργαλείων εικόνας"
78
78
 
79
79
  msgctxt "The label used for the dropdown in the image toolbar containing defined resize options."
80
80
  msgid "Resize image"
81
- msgstr ""
81
+ msgstr "Αλλαγή μεγέθους εικόνας"
82
82
 
83
83
  msgctxt "The label used for the standalone resize options buttons in the image toolbar."
84
84
  msgid "Resize image to %0"
85
- msgstr ""
85
+ msgstr "Αλλαγή μεγέθους σε %0"
86
86
 
87
87
  msgctxt "The accessibility label of the standalone image resize reset option button in the image toolbar for screen readers."
88
88
  msgid "Resize image to the original size"
89
- msgstr ""
89
+ msgstr "Αλλαγή μεγέθους εικόνας στο αρχικό μέγεθος"
90
90
 
91
91
  msgctxt "The default label for the resize option that resets the size of the image."
92
92
  msgid "Original"
93
- msgstr ""
93
+ msgstr "Αρχικό"
94
94
 
95
95
  msgctxt "The accessibility label of the image resize dropdown for screen readers."
96
96
  msgid "Image resize list"
97
- msgstr ""
97
+ msgstr "Λίστα μεγεθών εικόνων"
98
98
 
99
99
  msgctxt "The label of the form submit button if the image source URL input has no value."
100
100
  msgid "Insert"
101
- msgstr ""
101
+ msgstr "Εισαγωγή"
102
102
 
103
103
  msgctxt "The label of the form submit button if the image source URL input has a value."
104
104
  msgid "Update"
105
- msgstr ""
105
+ msgstr "Ενημέρωση"
106
106
 
107
107
  msgctxt "The input label for the Insert image via URL form."
108
108
  msgid "Insert image via URL"
109
- msgstr ""
109
+ msgstr "Εισαγωγή εικόνας μέσω διεύθυνσης"
110
110
 
111
111
  msgctxt "The input label for the Insert image via URL form for a pre-existing image."
112
112
  msgid "Update image URL"
113
- msgstr ""
113
+ msgstr "Ενημέρωση διεύθυνσης εικόνας"
@@ -22,15 +22,15 @@ msgstr "Widget de imagen"
22
22
 
23
23
  msgctxt "The label for the image style button that wraps text around the image."
24
24
  msgid "Wrap text"
25
- msgstr ""
25
+ msgstr "Mantener texto unido"
26
26
 
27
27
  msgctxt "The label for the image style button that breaks the text around the image."
28
28
  msgid "Break text"
29
- msgstr ""
29
+ msgstr "Permitir quebrar texto"
30
30
 
31
31
  msgctxt "The label for the image style button that places the image inside the line of text."
32
32
  msgid "In line"
33
- msgstr ""
33
+ msgstr "En línea"
34
34
 
35
35
  msgctxt "The label for the Side image option."
36
36
  msgid "Side image"
@@ -78,15 +78,15 @@ msgstr "Barra de herramientas de imagen"
78
78
 
79
79
  msgctxt "The label used for the dropdown in the image toolbar containing defined resize options."
80
80
  msgid "Resize image"
81
- msgstr ""
81
+ msgstr "Redimensionar imagen"
82
82
 
83
83
  msgctxt "The label used for the standalone resize options buttons in the image toolbar."
84
84
  msgid "Resize image to %0"
85
- msgstr ""
85
+ msgstr "Redimensionar imagen al %0"
86
86
 
87
87
  msgctxt "The accessibility label of the standalone image resize reset option button in the image toolbar for screen readers."
88
88
  msgid "Resize image to the original size"
89
- msgstr ""
89
+ msgstr "Redimensionar imagen al tamaño original"
90
90
 
91
91
  msgctxt "The default label for the resize option that resets the size of the image."
92
92
  msgid "Original"
@@ -94,7 +94,7 @@ msgstr "Original"
94
94
 
95
95
  msgctxt "The accessibility label of the image resize dropdown for screen readers."
96
96
  msgid "Image resize list"
97
- msgstr ""
97
+ msgstr "Listado para redimensionar imagen"
98
98
 
99
99
  msgctxt "The label of the form submit button if the image source URL input has no value."
100
100
  msgid "Insert"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-image",
3
- "version": "32.0.0",
3
+ "version": "33.0.0",
4
4
  "description": "Image feature for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,39 +12,40 @@
12
12
  ],
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "@ckeditor/ckeditor5-ui": "^32.0.0",
16
- "ckeditor5": "^32.0.0",
15
+ "@ckeditor/ckeditor5-ui": "^33.0.0",
16
+ "ckeditor5": "^33.0.0",
17
17
  "lodash-es": "^4.17.15"
18
18
  },
19
19
  "devDependencies": {
20
- "@ckeditor/ckeditor5-adapter-ckfinder": "^32.0.0",
21
- "@ckeditor/ckeditor5-autoformat": "^32.0.0",
22
- "@ckeditor/ckeditor5-basic-styles": "^32.0.0",
23
- "@ckeditor/ckeditor5-block-quote": "^32.0.0",
24
- "@ckeditor/ckeditor5-ckfinder": "^32.0.0",
25
- "@ckeditor/ckeditor5-clipboard": "^32.0.0",
26
- "@ckeditor/ckeditor5-cloud-services": "^32.0.0",
27
- "@ckeditor/ckeditor5-core": "^32.0.0",
28
- "@ckeditor/ckeditor5-dev-utils": "^27.1.0",
29
- "@ckeditor/ckeditor5-easy-image": "^32.0.0",
30
- "@ckeditor/ckeditor5-editor-classic": "^32.0.0",
31
- "@ckeditor/ckeditor5-engine": "^32.0.0",
32
- "@ckeditor/ckeditor5-enter": "^32.0.0",
33
- "@ckeditor/ckeditor5-essentials": "^32.0.0",
34
- "@ckeditor/ckeditor5-heading": "^32.0.0",
35
- "@ckeditor/ckeditor5-html-embed": "^32.0.0",
36
- "@ckeditor/ckeditor5-indent": "^32.0.0",
37
- "@ckeditor/ckeditor5-link": "^32.0.0",
38
- "@ckeditor/ckeditor5-list": "^32.0.0",
39
- "@ckeditor/ckeditor5-media-embed": "^32.0.0",
40
- "@ckeditor/ckeditor5-paragraph": "^32.0.0",
41
- "@ckeditor/ckeditor5-table": "^32.0.0",
42
- "@ckeditor/ckeditor5-theme-lark": "^32.0.0",
43
- "@ckeditor/ckeditor5-typing": "^32.0.0",
44
- "@ckeditor/ckeditor5-undo": "^32.0.0",
45
- "@ckeditor/ckeditor5-upload": "^32.0.0",
46
- "@ckeditor/ckeditor5-utils": "^32.0.0",
47
- "@ckeditor/ckeditor5-widget": "^32.0.0",
20
+ "@ckeditor/ckeditor5-adapter-ckfinder": "^33.0.0",
21
+ "@ckeditor/ckeditor5-autoformat": "^33.0.0",
22
+ "@ckeditor/ckeditor5-basic-styles": "^33.0.0",
23
+ "@ckeditor/ckeditor5-block-quote": "^33.0.0",
24
+ "@ckeditor/ckeditor5-ckfinder": "^33.0.0",
25
+ "@ckeditor/ckeditor5-clipboard": "^33.0.0",
26
+ "@ckeditor/ckeditor5-cloud-services": "^33.0.0",
27
+ "@ckeditor/ckeditor5-core": "^33.0.0",
28
+ "@ckeditor/ckeditor5-dev-utils": "^28.0.1",
29
+ "@ckeditor/ckeditor5-easy-image": "^33.0.0",
30
+ "@ckeditor/ckeditor5-editor-classic": "^33.0.0",
31
+ "@ckeditor/ckeditor5-engine": "^33.0.0",
32
+ "@ckeditor/ckeditor5-enter": "^33.0.0",
33
+ "@ckeditor/ckeditor5-essentials": "^33.0.0",
34
+ "@ckeditor/ckeditor5-heading": "^33.0.0",
35
+ "@ckeditor/ckeditor5-html-embed": "^33.0.0",
36
+ "@ckeditor/ckeditor5-indent": "^33.0.0",
37
+ "@ckeditor/ckeditor5-link": "^33.0.0",
38
+ "@ckeditor/ckeditor5-list": "^33.0.0",
39
+ "@ckeditor/ckeditor5-media-embed": "^33.0.0",
40
+ "@ckeditor/ckeditor5-paragraph": "^33.0.0",
41
+ "@ckeditor/ckeditor5-table": "^33.0.0",
42
+ "@ckeditor/ckeditor5-theme-lark": "^33.0.0",
43
+ "@ckeditor/ckeditor5-typing": "^33.0.0",
44
+ "@ckeditor/ckeditor5-undo": "^33.0.0",
45
+ "@ckeditor/ckeditor5-upload": "^33.0.0",
46
+ "@ckeditor/ckeditor5-utils": "^33.0.0",
47
+ "@ckeditor/ckeditor5-watchdog": "^33.0.0",
48
+ "@ckeditor/ckeditor5-widget": "^33.0.0",
48
49
  "webpack": "^5.58.1",
49
50
  "webpack-cli": "^4.9.0"
50
51
  },
@@ -235,13 +235,12 @@ export function downcastSourcesAttribute( imageUtils ) {
235
235
 
236
236
  if ( data.attributeNewValue && data.attributeNewValue.length ) {
237
237
  // Make sure <picture> does not break attribute elements, for instance <a> in linked images.
238
- const pictureElement = viewWriter.createContainerElement( 'picture', {}, { isAllowedInsideAttributeElement: true } );
239
-
240
- for ( const sourceAttributes of data.attributeNewValue ) {
241
- const sourceElement = viewWriter.createEmptyElement( 'source', sourceAttributes );
242
-
243
- viewWriter.insert( viewWriter.createPositionAt( pictureElement, 'end' ), sourceElement );
244
- }
238
+ const pictureElement = viewWriter.createContainerElement( 'picture', null,
239
+ data.attributeNewValue.map( sourceAttributes => {
240
+ return viewWriter.createEmptyElement( 'source', sourceAttributes );
241
+ } ),
242
+ { isAllowedInsideAttributeElement: true }
243
+ );
245
244
 
246
245
  // Collect all wrapping attribute elements.
247
246
  const attributeElements = [];
@@ -22,7 +22,7 @@ import ImageTypeCommand from './imagetypecommand';
22
22
  import ImageUtils from '../imageutils';
23
23
  import {
24
24
  getImgViewElementMatcher,
25
- createImageViewElement,
25
+ createBlockImageViewElement,
26
26
  determineImageTypeForInsertionAtSelection
27
27
  } from '../image/utils';
28
28
 
@@ -90,16 +90,16 @@ export default class ImageBlockEditing extends Plugin {
90
90
  const imageUtils = editor.plugins.get( 'ImageUtils' );
91
91
 
92
92
  conversion.for( 'dataDowncast' )
93
- .elementToElement( {
93
+ .elementToStructure( {
94
94
  model: 'imageBlock',
95
- view: ( modelElement, { writer } ) => createImageViewElement( writer, 'imageBlock' )
95
+ view: ( modelElement, { writer } ) => createBlockImageViewElement( writer )
96
96
  } );
97
97
 
98
98
  conversion.for( 'editingDowncast' )
99
- .elementToElement( {
99
+ .elementToStructure( {
100
100
  model: 'imageBlock',
101
101
  view: ( modelElement, { writer } ) => imageUtils.toImageWidget(
102
- createImageViewElement( writer, 'imageBlock' ), writer, t( 'image widget' )
102
+ createBlockImageViewElement( writer ), writer, t( 'image widget' )
103
103
  )
104
104
  } );
105
105
 
@@ -21,7 +21,7 @@ import ImageTypeCommand from './imagetypecommand';
21
21
  import ImageUtils from '../imageutils';
22
22
  import {
23
23
  getImgViewElementMatcher,
24
- createImageViewElement,
24
+ createInlineImageViewElement,
25
25
  determineImageTypeForInsertionAtSelection
26
26
  } from '../image/utils';
27
27
 
@@ -105,10 +105,10 @@ export default class ImageInlineEditing extends Plugin {
105
105
  } );
106
106
 
107
107
  conversion.for( 'editingDowncast' )
108
- .elementToElement( {
108
+ .elementToStructure( {
109
109
  model: 'imageInline',
110
110
  view: ( modelElement, { writer } ) => imageUtils.toImageWidget(
111
- createImageViewElement( writer, 'imageInline' ), writer, t( 'image widget' )
111
+ createInlineImageViewElement( writer ), writer, t( 'image widget' )
112
112
  )
113
113
  } );
114
114
 
@@ -10,33 +10,39 @@
10
10
  import { first } from 'ckeditor5/src/utils';
11
11
 
12
12
  /**
13
- * Creates a view element representing the image of provided image type.
13
+ * Creates a view element representing the inline image.
14
14
  *
15
- * An 'imageBlock' type (block image):
15
+ * <span class="image-inline"><img></img></span>
16
16
  *
17
- * <figure class="image"><img></img></figure>
17
+ * Note that `alt` and `src` attributes are converted separately, so they are not included.
18
18
  *
19
- * An 'imageInline' type (inline image):
19
+ * @protected
20
+ * @param {module:engine/view/downcastwriter~DowncastWriter} writer
21
+ * @returns {module:engine/view/containerelement~ContainerElement}
22
+ */
23
+ export function createInlineImageViewElement( writer ) {
24
+ return writer.createContainerElement( 'span', { class: 'image-inline' },
25
+ writer.createEmptyElement( 'img' ),
26
+ { isAllowedInsideAttributeElement: true }
27
+ );
28
+ }
29
+
30
+ /**
31
+ * Creates a view element representing the block image.
20
32
  *
21
- * <span class="image-inline"><img></img></span>
33
+ * <figure class="image"><img></img></figure>
22
34
  *
23
35
  * Note that `alt` and `src` attributes are converted separately, so they are not included.
24
36
  *
25
37
  * @protected
26
38
  * @param {module:engine/view/downcastwriter~DowncastWriter} writer
27
- * @param {'imageBlock'|'imageInline'} imageType The type of created image.
28
39
  * @returns {module:engine/view/containerelement~ContainerElement}
29
40
  */
30
- export function createImageViewElement( writer, imageType ) {
31
- const emptyElement = writer.createEmptyElement( 'img' );
32
-
33
- const container = imageType === 'imageBlock' ?
34
- writer.createContainerElement( 'figure', { class: 'image' } ) :
35
- writer.createContainerElement( 'span', { class: 'image-inline' }, { isAllowedInsideAttributeElement: true } );
36
-
37
- writer.insert( writer.createPositionAt( container, 0 ), emptyElement );
38
-
39
- return container;
41
+ export function createBlockImageViewElement( writer ) {
42
+ return writer.createContainerElement( 'figure', { class: 'image' }, [
43
+ writer.createEmptyElement( 'img' ),
44
+ writer.createSlot()
45
+ ] );
40
46
  }
41
47
 
42
48
  /**
@@ -14,7 +14,7 @@ import { toWidgetEditable } from 'ckeditor5/src/widget';
14
14
  import ToggleImageCaptionCommand from './toggleimagecaptioncommand';
15
15
 
16
16
  import ImageUtils from '../imageutils';
17
- import { getCaptionFromImageModelElement, matchImageCaptionViewElement } from './utils';
17
+ import ImageCaptionUtils from './imagecaptionutils';
18
18
 
19
19
  /**
20
20
  * The image caption engine plugin. It is responsible for:
@@ -30,7 +30,7 @@ export default class ImageCaptionEditing extends Plugin {
30
30
  * @inheritDoc
31
31
  */
32
32
  static get requires() {
33
- return [ ImageUtils ];
33
+ return [ ImageUtils, ImageCaptionUtils ];
34
34
  }
35
35
 
36
36
  /**
@@ -93,11 +93,12 @@ export default class ImageCaptionEditing extends Plugin {
93
93
  const editor = this.editor;
94
94
  const view = editor.editing.view;
95
95
  const imageUtils = editor.plugins.get( 'ImageUtils' );
96
+ const imageCaptionUtils = editor.plugins.get( 'ImageCaptionUtils' );
96
97
  const t = editor.t;
97
98
 
98
99
  // View -> model converter for the data pipeline.
99
100
  editor.conversion.for( 'upcast' ).elementToElement( {
100
- view: element => matchImageCaptionViewElement( imageUtils, element ),
101
+ view: element => imageCaptionUtils.matchImageCaptionViewElement( element ),
101
102
  model: 'caption'
102
103
  } );
103
104
 
@@ -134,9 +135,6 @@ export default class ImageCaptionEditing extends Plugin {
134
135
  return toWidgetEditable( figcaptionElement, writer );
135
136
  }
136
137
  } );
137
-
138
- editor.editing.mapper.on( 'modelToViewPosition', mapModelPositionToView( view ) );
139
- editor.data.mapper.on( 'modelToViewPosition', mapModelPositionToView( view ) );
140
138
  }
141
139
 
142
140
  /**
@@ -149,6 +147,7 @@ export default class ImageCaptionEditing extends Plugin {
149
147
  _setupImageTypeCommandsIntegration() {
150
148
  const editor = this.editor;
151
149
  const imageUtils = editor.plugins.get( 'ImageUtils' );
150
+ const imageCaptionUtils = editor.plugins.get( 'ImageCaptionUtils' );
152
151
  const imageTypeInlineCommand = editor.commands.get( 'imageTypeInline' );
153
152
  const imageTypeBlockCommand = editor.commands.get( 'imageTypeBlock' );
154
153
 
@@ -166,7 +165,7 @@ export default class ImageCaptionEditing extends Plugin {
166
165
  }
167
166
 
168
167
  if ( imageUtils.isBlockImage( oldElement ) ) {
169
- const oldCaptionElement = getCaptionFromImageModelElement( oldElement );
168
+ const oldCaptionElement = imageCaptionUtils.getCaptionFromImageModelElement( oldElement );
170
169
 
171
170
  // If the old element was a captioned block image (the caption was visible),
172
171
  // simply save it so it can be restored.
@@ -244,28 +243,3 @@ export default class ImageCaptionEditing extends Plugin {
244
243
  this._savedCaptionsMap.set( imageModelElement, caption.toJSON() );
245
244
  }
246
245
  }
247
-
248
- // Creates a mapper callback that reverses the order of `<img>` and `<figcaption>` in the image.
249
- // Without it, `<figcaption>` would precede the `<img>` in the conversion.
250
- //
251
- // <imageBlock>^</imageBlock> -> <figure><img>^<caption></caption></figure>
252
- //
253
- // @private
254
- // @param {module:engine/view/view~View} editingView
255
- // @returns {Function}
256
- function mapModelPositionToView( editingView ) {
257
- return ( evt, data ) => {
258
- const modelPosition = data.modelPosition;
259
- const parent = modelPosition.parent;
260
-
261
- if ( !parent.is( 'element', 'imageBlock' ) ) {
262
- return;
263
- }
264
-
265
- const viewElement = data.mapper.toViewElement( parent );
266
-
267
- // The "img" element is inserted by ImageBlockEditing during the downcast conversion via
268
- // an explicit view position so the "0" position does not need any mapping.
269
- data.viewPosition = editingView.createPositionAt( viewElement, modelPosition.offset + 1 );
270
- };
271
- }
@@ -9,9 +9,7 @@
9
9
 
10
10
  import { Plugin, icons } from 'ckeditor5/src/core';
11
11
  import { ButtonView } from 'ckeditor5/src/ui';
12
- import ImageUtils from '../imageutils';
13
-
14
- import { getCaptionFromModelSelection } from './utils';
12
+ import ImageCaptionUtils from './imagecaptionutils';
15
13
 
16
14
  /**
17
15
  * The image caption UI plugin. It introduces the `'toggleImageCaption'` UI button.
@@ -23,7 +21,7 @@ export default class ImageCaptionUI extends Plugin {
23
21
  * @inheritDoc
24
22
  */
25
23
  static get requires() {
26
- return [ ImageUtils ];
24
+ return [ ImageCaptionUtils ];
27
25
  }
28
26
 
29
27
  /**
@@ -39,7 +37,7 @@ export default class ImageCaptionUI extends Plugin {
39
37
  init() {
40
38
  const editor = this.editor;
41
39
  const editingView = editor.editing.view;
42
- const imageUtils = editor.plugins.get( 'ImageUtils' );
40
+ const imageCaptionUtils = editor.plugins.get( 'ImageCaptionUtils' );
43
41
  const t = editor.t;
44
42
 
45
43
  editor.ui.componentFactory.add( 'toggleImageCaption', locale => {
@@ -59,7 +57,7 @@ export default class ImageCaptionUI extends Plugin {
59
57
  editor.execute( 'toggleImageCaption', { focusCaptionOnShow: true } );
60
58
 
61
59
  // Scroll to the selection and highlight the caption if the caption showed up.
62
- const modelCaptionElement = getCaptionFromModelSelection( imageUtils, editor.model.document.selection );
60
+ const modelCaptionElement = imageCaptionUtils.getCaptionFromModelSelection( editor.model.document.selection );
63
61
 
64
62
  if ( modelCaptionElement ) {
65
63
  const figcaptionElement = editor.editing.mapper.toViewElement( modelCaptionElement );
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, 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
+ /**
7
+ * @module image/imagecaptionutils/utils
8
+ */
9
+
10
+ import { Plugin } from 'ckeditor5/src/core';
11
+
12
+ import ImageUtils from '../imageutils';
13
+
14
+ /**
15
+ * The image caption utilities plugin.
16
+ *
17
+ * @extends module:core/plugin~Plugin
18
+ */
19
+ export default class ImageCaptionUtils extends Plugin {
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ static get pluginName() {
24
+ return 'ImageCaptionUtils';
25
+ }
26
+
27
+ /**
28
+ * @inheritDoc
29
+ */
30
+ static get requires() {
31
+ return [ ImageUtils ];
32
+ }
33
+
34
+ /**
35
+ * Returns the caption model element from a given image element. Returns `null` if no caption is found.
36
+ *
37
+ * @param {module:engine/model/element~Element} imageModelElement
38
+ * @returns {module:engine/model/element~Element|null}
39
+ */
40
+ getCaptionFromImageModelElement( imageModelElement ) {
41
+ for ( const node of imageModelElement.getChildren() ) {
42
+ if ( !!node && node.is( 'element', 'caption' ) ) {
43
+ return node;
44
+ }
45
+ }
46
+
47
+ return null;
48
+ }
49
+
50
+ /**
51
+ * Returns the caption model element for a model selection. Returns `null` if the selection has no caption element ancestor.
52
+ *
53
+ * @param {module:engine/model/selection~Selection} selection
54
+ * @returns {module:engine/model/element~Element|null}
55
+ */
56
+ getCaptionFromModelSelection( selection ) {
57
+ const imageUtils = this.editor.plugins.get( 'ImageUtils' );
58
+ const captionElement = selection.getFirstPosition().findAncestor( 'caption' );
59
+
60
+ if ( !captionElement ) {
61
+ return null;
62
+ }
63
+
64
+ if ( imageUtils.isBlockImage( captionElement.parent ) ) {
65
+ return captionElement;
66
+ }
67
+
68
+ return null;
69
+ }
70
+
71
+ /**
72
+ * {@link module:engine/view/matcher~Matcher} pattern. Checks if a given element is a `<figcaption>` element that is placed
73
+ * inside the image `<figure>` element.
74
+ *
75
+ * @param {module:engine/view/element~Element} element
76
+ * @returns {Object|null} Returns the object accepted by {@link module:engine/view/matcher~Matcher} or `null` if the element
77
+ * cannot be matched.
78
+ */
79
+ matchImageCaptionViewElement( element ) {
80
+ const imageUtils = this.editor.plugins.get( 'ImageUtils' );
81
+
82
+ // Convert only captions for images.
83
+ if ( element.name == 'figcaption' && imageUtils.isBlockImageView( element.parent ) ) {
84
+ return { name: true };
85
+ }
86
+
87
+ return null;
88
+ }
89
+ }