@ckeditor/ckeditor5-image 32.0.0 → 34.1.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.
- package/LICENSE.md +2 -2
- package/README.md +2 -1
- package/build/image.js +2 -2
- package/build/translations/el.js +1 -1
- package/build/translations/en-au.js +1 -1
- package/build/translations/es.js +1 -1
- package/build/translations/hr.js +1 -1
- package/build/translations/jv.js +1 -0
- package/build/translations/lv.js +1 -1
- package/build/translations/sk.js +1 -1
- package/build/translations/ur.js +1 -0
- package/lang/translations/el.po +22 -22
- package/lang/translations/en-au.po +3 -3
- package/lang/translations/es.po +7 -7
- package/lang/translations/hr.po +12 -12
- package/lang/translations/jv.po +113 -0
- package/lang/translations/lv.po +12 -12
- package/lang/translations/sk.po +3 -3
- package/lang/translations/ur.po +113 -0
- package/package.json +32 -31
- package/src/image/converters.js +6 -8
- package/src/image/imageblockediting.js +6 -8
- package/src/image/imageinlineediting.js +4 -7
- package/src/image/utils.js +42 -22
- package/src/imagecaption/imagecaptionediting.js +6 -32
- package/src/imagecaption/imagecaptionui.js +4 -6
- package/src/imagecaption/imagecaptionutils.js +89 -0
- package/src/imagecaption/toggleimagecaptioncommand.js +6 -7
- package/src/imagestyle/utils.js +64 -48
- package/src/imageutils.js +6 -9
- package/src/index.js +2 -0
- package/src/imagecaption/utils.js +0 -63
package/src/image/converters.js
CHANGED
|
@@ -82,7 +82,7 @@ export function upcastImageFigure( imageUtils ) {
|
|
|
82
82
|
* @returns {Function}
|
|
83
83
|
*/
|
|
84
84
|
export function upcastPicture( imageUtils ) {
|
|
85
|
-
const sourceAttributeNames = [ 'srcset', 'media', 'type' ];
|
|
85
|
+
const sourceAttributeNames = [ 'srcset', 'media', 'type', 'sizes' ];
|
|
86
86
|
|
|
87
87
|
return dispatcher => {
|
|
88
88
|
dispatcher.on( 'element:picture', converter );
|
|
@@ -235,13 +235,11 @@ 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',
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
+
);
|
|
245
243
|
|
|
246
244
|
// Collect all wrapping attribute elements.
|
|
247
245
|
const attributeElements = [];
|
|
@@ -22,7 +22,7 @@ import ImageTypeCommand from './imagetypecommand';
|
|
|
22
22
|
import ImageUtils from '../imageutils';
|
|
23
23
|
import {
|
|
24
24
|
getImgViewElementMatcher,
|
|
25
|
-
|
|
25
|
+
createBlockImageViewElement,
|
|
26
26
|
determineImageTypeForInsertionAtSelection
|
|
27
27
|
} from '../image/utils';
|
|
28
28
|
|
|
@@ -62,9 +62,7 @@ export default class ImageBlockEditing extends Plugin {
|
|
|
62
62
|
|
|
63
63
|
// Converters 'alt' and 'srcset' are added in 'ImageEditing' plugin.
|
|
64
64
|
schema.register( 'imageBlock', {
|
|
65
|
-
|
|
66
|
-
isBlock: true,
|
|
67
|
-
allowWhere: '$block',
|
|
65
|
+
inheritAllFrom: '$blockObject',
|
|
68
66
|
allowAttributes: [ 'alt', 'src', 'srcset' ]
|
|
69
67
|
} );
|
|
70
68
|
|
|
@@ -90,16 +88,16 @@ export default class ImageBlockEditing extends Plugin {
|
|
|
90
88
|
const imageUtils = editor.plugins.get( 'ImageUtils' );
|
|
91
89
|
|
|
92
90
|
conversion.for( 'dataDowncast' )
|
|
93
|
-
.
|
|
91
|
+
.elementToStructure( {
|
|
94
92
|
model: 'imageBlock',
|
|
95
|
-
view: ( modelElement, { writer } ) =>
|
|
93
|
+
view: ( modelElement, { writer } ) => createBlockImageViewElement( writer )
|
|
96
94
|
} );
|
|
97
95
|
|
|
98
96
|
conversion.for( 'editingDowncast' )
|
|
99
|
-
.
|
|
97
|
+
.elementToStructure( {
|
|
100
98
|
model: 'imageBlock',
|
|
101
99
|
view: ( modelElement, { writer } ) => imageUtils.toImageWidget(
|
|
102
|
-
|
|
100
|
+
createBlockImageViewElement( writer ), writer, t( 'image widget' )
|
|
103
101
|
)
|
|
104
102
|
} );
|
|
105
103
|
|
|
@@ -21,7 +21,7 @@ import ImageTypeCommand from './imagetypecommand';
|
|
|
21
21
|
import ImageUtils from '../imageutils';
|
|
22
22
|
import {
|
|
23
23
|
getImgViewElementMatcher,
|
|
24
|
-
|
|
24
|
+
createInlineImageViewElement,
|
|
25
25
|
determineImageTypeForInsertionAtSelection
|
|
26
26
|
} from '../image/utils';
|
|
27
27
|
|
|
@@ -61,10 +61,7 @@ export default class ImageInlineEditing extends Plugin {
|
|
|
61
61
|
|
|
62
62
|
// Converters 'alt' and 'srcset' are added in 'ImageEditing' plugin.
|
|
63
63
|
schema.register( 'imageInline', {
|
|
64
|
-
|
|
65
|
-
isInline: true,
|
|
66
|
-
allowWhere: '$text',
|
|
67
|
-
allowAttributesOf: '$text',
|
|
64
|
+
inheritAllFrom: '$inlineObject',
|
|
68
65
|
allowAttributes: [ 'alt', 'src', 'srcset' ]
|
|
69
66
|
} );
|
|
70
67
|
|
|
@@ -105,10 +102,10 @@ export default class ImageInlineEditing extends Plugin {
|
|
|
105
102
|
} );
|
|
106
103
|
|
|
107
104
|
conversion.for( 'editingDowncast' )
|
|
108
|
-
.
|
|
105
|
+
.elementToStructure( {
|
|
109
106
|
model: 'imageInline',
|
|
110
107
|
view: ( modelElement, { writer } ) => imageUtils.toImageWidget(
|
|
111
|
-
|
|
108
|
+
createInlineImageViewElement( writer ), writer, t( 'image widget' )
|
|
112
109
|
)
|
|
113
110
|
} );
|
|
114
111
|
|
package/src/image/utils.js
CHANGED
|
@@ -10,33 +10,38 @@
|
|
|
10
10
|
import { first } from 'ckeditor5/src/utils';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Creates a view element representing the
|
|
13
|
+
* Creates a view element representing the inline image.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
15
|
+
* <span class="image-inline"><img></img></span>
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* Note that `alt` and `src` attributes are converted separately, so they are not included.
|
|
18
18
|
*
|
|
19
|
-
*
|
|
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
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a view element representing the block image.
|
|
20
31
|
*
|
|
21
|
-
* <
|
|
32
|
+
* <figure class="image"><img></img></figure>
|
|
22
33
|
*
|
|
23
34
|
* Note that `alt` and `src` attributes are converted separately, so they are not included.
|
|
24
35
|
*
|
|
25
36
|
* @protected
|
|
26
37
|
* @param {module:engine/view/downcastwriter~DowncastWriter} writer
|
|
27
|
-
* @param {'imageBlock'|'imageInline'} imageType The type of created image.
|
|
28
38
|
* @returns {module:engine/view/containerelement~ContainerElement}
|
|
29
39
|
*/
|
|
30
|
-
export function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
writer.createContainerElement( 'span', { class: 'image-inline' }, { isAllowedInsideAttributeElement: true } );
|
|
36
|
-
|
|
37
|
-
writer.insert( writer.createPositionAt( container, 0 ), emptyElement );
|
|
38
|
-
|
|
39
|
-
return container;
|
|
40
|
+
export function createBlockImageViewElement( writer ) {
|
|
41
|
+
return writer.createContainerElement( 'figure', { class: 'image' }, [
|
|
42
|
+
writer.createEmptyElement( 'img' ),
|
|
43
|
+
writer.createSlot()
|
|
44
|
+
] );
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
/**
|
|
@@ -48,18 +53,20 @@ export function createImageViewElement( writer, imageType ) {
|
|
|
48
53
|
* @returns {module:engine/view/matcher~MatcherPattern}
|
|
49
54
|
*/
|
|
50
55
|
export function getImgViewElementMatcher( editor, matchImageType ) {
|
|
51
|
-
if ( editor.plugins.has( 'ImageInlineEditing' ) !== editor.plugins.has( 'ImageBlockEditing' ) ) {
|
|
52
|
-
return { name: 'img' };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
56
|
const imageUtils = editor.plugins.get( 'ImageUtils' );
|
|
57
|
+
const areBothImagePluginsLoaded = editor.plugins.has( 'ImageInlineEditing' ) && editor.plugins.has( 'ImageBlockEditing' );
|
|
56
58
|
|
|
57
59
|
return element => {
|
|
58
|
-
// Check if view element is an
|
|
60
|
+
// Check if the matched view element is an <img>.
|
|
59
61
|
if ( !imageUtils.isInlineImageView( element ) ) {
|
|
60
62
|
return null;
|
|
61
63
|
}
|
|
62
64
|
|
|
65
|
+
// If just one of the plugins is loaded (block or inline), it will match all kinds of images.
|
|
66
|
+
if ( !areBothImagePluginsLoaded ) {
|
|
67
|
+
return getPositiveMatchPattern( element );
|
|
68
|
+
}
|
|
69
|
+
|
|
63
70
|
// The <img> can be standalone, wrapped in <figure>...</figure> (ImageBlock plugin) or
|
|
64
71
|
// wrapped in <figure><a>...</a></figure> (LinkImage plugin).
|
|
65
72
|
const imageType = element.findAncestor( imageUtils.isBlockImageView ) ? 'imageBlock' : 'imageInline';
|
|
@@ -68,8 +75,21 @@ export function getImgViewElementMatcher( editor, matchImageType ) {
|
|
|
68
75
|
return null;
|
|
69
76
|
}
|
|
70
77
|
|
|
71
|
-
return
|
|
78
|
+
return getPositiveMatchPattern( element );
|
|
72
79
|
};
|
|
80
|
+
|
|
81
|
+
function getPositiveMatchPattern( element ) {
|
|
82
|
+
const pattern = {
|
|
83
|
+
name: true
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// This will trigger src consumption (See https://github.com/ckeditor/ckeditor5/issues/11530).
|
|
87
|
+
if ( element.hasAttribute( 'src' ) ) {
|
|
88
|
+
pattern.attributes = [ 'src' ];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return pattern;
|
|
92
|
+
}
|
|
73
93
|
}
|
|
74
94
|
|
|
75
95
|
/**
|
|
@@ -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
|
|
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(
|
|
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
|
|
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 [
|
|
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
|
|
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(
|
|
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
|
+
}
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
import { Command } from 'ckeditor5/src/core';
|
|
11
11
|
|
|
12
12
|
import ImageBlockEditing from '../image/imageblockediting';
|
|
13
|
-
import { getCaptionFromImageModelElement, getCaptionFromModelSelection } from './utils';
|
|
14
13
|
|
|
15
14
|
/**
|
|
16
15
|
* The toggle image caption command.
|
|
@@ -41,7 +40,7 @@ export default class ToggleImageCaptionCommand extends Command {
|
|
|
41
40
|
*/
|
|
42
41
|
refresh() {
|
|
43
42
|
const editor = this.editor;
|
|
44
|
-
const
|
|
43
|
+
const imageCaptionUtils = editor.plugins.get( 'ImageCaptionUtils' );
|
|
45
44
|
|
|
46
45
|
// Only block images can get captions.
|
|
47
46
|
if ( !editor.plugins.has( ImageBlockEditing ) ) {
|
|
@@ -55,7 +54,7 @@ export default class ToggleImageCaptionCommand extends Command {
|
|
|
55
54
|
const selectedElement = selection.getSelectedElement();
|
|
56
55
|
|
|
57
56
|
if ( !selectedElement ) {
|
|
58
|
-
const ancestorCaptionElement = getCaptionFromModelSelection(
|
|
57
|
+
const ancestorCaptionElement = imageCaptionUtils.getCaptionFromModelSelection( selection );
|
|
59
58
|
|
|
60
59
|
this.isEnabled = !!ancestorCaptionElement;
|
|
61
60
|
this.value = !!ancestorCaptionElement;
|
|
@@ -70,7 +69,7 @@ export default class ToggleImageCaptionCommand extends Command {
|
|
|
70
69
|
if ( !this.isEnabled ) {
|
|
71
70
|
this.value = false;
|
|
72
71
|
} else {
|
|
73
|
-
this.value = !!getCaptionFromImageModelElement( selectedElement );
|
|
72
|
+
this.value = !!imageCaptionUtils.getCaptionFromImageModelElement( selectedElement );
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -145,14 +144,14 @@ export default class ToggleImageCaptionCommand extends Command {
|
|
|
145
144
|
const editor = this.editor;
|
|
146
145
|
const selection = editor.model.document.selection;
|
|
147
146
|
const imageCaptionEditing = editor.plugins.get( 'ImageCaptionEditing' );
|
|
148
|
-
const
|
|
147
|
+
const imageCaptionUtils = editor.plugins.get( 'ImageCaptionUtils' );
|
|
149
148
|
let selectedImage = selection.getSelectedElement();
|
|
150
149
|
let captionElement;
|
|
151
150
|
|
|
152
151
|
if ( selectedImage ) {
|
|
153
|
-
captionElement = getCaptionFromImageModelElement( selectedImage );
|
|
152
|
+
captionElement = imageCaptionUtils.getCaptionFromImageModelElement( selectedImage );
|
|
154
153
|
} else {
|
|
155
|
-
captionElement = getCaptionFromModelSelection(
|
|
154
|
+
captionElement = imageCaptionUtils.getCaptionFromModelSelection( selection );
|
|
156
155
|
selectedImage = captionElement.parent;
|
|
157
156
|
}
|
|
158
157
|
|
package/src/imagestyle/utils.js
CHANGED
|
@@ -40,75 +40,91 @@ const {
|
|
|
40
40
|
*/
|
|
41
41
|
const DEFAULT_OPTIONS = {
|
|
42
42
|
// This style represents an image placed in the line of text.
|
|
43
|
-
inline
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
get inline() {
|
|
44
|
+
return {
|
|
45
|
+
name: 'inline',
|
|
46
|
+
title: 'In line',
|
|
47
|
+
icon: objectInline,
|
|
48
|
+
modelElements: [ 'imageInline' ],
|
|
49
|
+
isDefault: true
|
|
50
|
+
};
|
|
49
51
|
},
|
|
50
52
|
|
|
51
53
|
// This style represents an image aligned to the left and wrapped with text.
|
|
52
|
-
alignLeft
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
get alignLeft() {
|
|
55
|
+
return {
|
|
56
|
+
name: 'alignLeft',
|
|
57
|
+
title: 'Left aligned image',
|
|
58
|
+
icon: objectLeft,
|
|
59
|
+
modelElements: [ 'imageBlock', 'imageInline' ],
|
|
60
|
+
className: 'image-style-align-left'
|
|
61
|
+
};
|
|
58
62
|
},
|
|
59
63
|
|
|
60
64
|
// This style represents an image aligned to the left.
|
|
61
|
-
alignBlockLeft
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
get alignBlockLeft() {
|
|
66
|
+
return {
|
|
67
|
+
name: 'alignBlockLeft',
|
|
68
|
+
title: 'Left aligned image',
|
|
69
|
+
icon: objectBlockLeft,
|
|
70
|
+
modelElements: [ 'imageBlock' ],
|
|
71
|
+
className: 'image-style-block-align-left'
|
|
72
|
+
};
|
|
67
73
|
},
|
|
68
74
|
|
|
69
75
|
// This style represents a centered image.
|
|
70
|
-
alignCenter
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
get alignCenter() {
|
|
77
|
+
return {
|
|
78
|
+
name: 'alignCenter',
|
|
79
|
+
title: 'Centered image',
|
|
80
|
+
icon: objectCenter,
|
|
81
|
+
modelElements: [ 'imageBlock' ],
|
|
82
|
+
className: 'image-style-align-center'
|
|
83
|
+
};
|
|
76
84
|
},
|
|
77
85
|
|
|
78
86
|
// This style represents an image aligned to the right and wrapped with text.
|
|
79
|
-
alignRight
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
get alignRight() {
|
|
88
|
+
return {
|
|
89
|
+
name: 'alignRight',
|
|
90
|
+
title: 'Right aligned image',
|
|
91
|
+
icon: objectRight,
|
|
92
|
+
modelElements: [ 'imageBlock', 'imageInline' ],
|
|
93
|
+
className: 'image-style-align-right'
|
|
94
|
+
};
|
|
85
95
|
},
|
|
86
96
|
|
|
87
97
|
// This style represents an image aligned to the right.
|
|
88
|
-
alignBlockRight
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
get alignBlockRight() {
|
|
99
|
+
return {
|
|
100
|
+
name: 'alignBlockRight',
|
|
101
|
+
title: 'Right aligned image',
|
|
102
|
+
icon: objectBlockRight,
|
|
103
|
+
modelElements: [ 'imageBlock' ],
|
|
104
|
+
className: 'image-style-block-align-right'
|
|
105
|
+
};
|
|
94
106
|
},
|
|
95
107
|
|
|
96
108
|
// This option is equal to the situation when no style is applied.
|
|
97
|
-
block
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
get block() {
|
|
110
|
+
return {
|
|
111
|
+
name: 'block',
|
|
112
|
+
title: 'Centered image',
|
|
113
|
+
icon: objectCenter,
|
|
114
|
+
modelElements: [ 'imageBlock' ],
|
|
115
|
+
isDefault: true
|
|
116
|
+
};
|
|
103
117
|
},
|
|
104
118
|
|
|
105
119
|
// This represents a side image.
|
|
106
|
-
side
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
get side() {
|
|
121
|
+
return {
|
|
122
|
+
name: 'side',
|
|
123
|
+
title: 'Side image',
|
|
124
|
+
icon: objectRight,
|
|
125
|
+
modelElements: [ 'imageBlock' ],
|
|
126
|
+
className: 'image-style-side'
|
|
127
|
+
};
|
|
112
128
|
}
|
|
113
129
|
};
|
|
114
130
|
|
package/src/imageutils.js
CHANGED
|
@@ -103,18 +103,15 @@ export default class ImageUtils extends Plugin {
|
|
|
103
103
|
return model.change( writer => {
|
|
104
104
|
const imageElement = writer.createElement( imageType, attributes );
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
selectable
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
model.insertContent( imageElement, selectable );
|
|
106
|
+
model.insertObject( imageElement, selectable, null, {
|
|
107
|
+
setSelection: 'on',
|
|
108
|
+
// If we want to insert a block image (for whatever reason) then we don't want to split text blocks.
|
|
109
|
+
// This applies only when we don't have the selectable specified (i.e., we insert multiple block images at once).
|
|
110
|
+
findOptimalPosition: !selectable && imageType != 'imageInline'
|
|
111
|
+
} );
|
|
113
112
|
|
|
114
113
|
// Inserting an image might've failed due to schema regulations.
|
|
115
114
|
if ( imageElement.parent ) {
|
|
116
|
-
writer.setSelection( imageElement, 'on' );
|
|
117
|
-
|
|
118
115
|
return imageElement;
|
|
119
116
|
}
|
|
120
117
|
|
package/src/index.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
export { default as AutoImage } from './autoimage';
|
|
11
11
|
export { default as Image } from './image';
|
|
12
12
|
export { default as ImageEditing } from './image/imageediting';
|
|
13
|
+
export { default as ImageCaptionUtils } from './imagecaption/imagecaptionutils';
|
|
13
14
|
export { default as ImageCaption } from './imagecaption';
|
|
14
15
|
export { default as ImageCaptionEditing } from './imagecaption/imagecaptionediting';
|
|
15
16
|
export { default as ImageInsert } from './imageinsert';
|
|
@@ -29,3 +30,4 @@ export { default as ImageUpload } from './imageupload';
|
|
|
29
30
|
export { default as ImageUploadEditing } from './imageupload/imageuploadediting';
|
|
30
31
|
export { default as ImageUploadProgress } from './imageupload/imageuploadprogress';
|
|
31
32
|
export { default as ImageUploadUI } from './imageupload/imageuploadui';
|
|
33
|
+
export { default as PictureEditing } from './pictureediting';
|