Explorar el Código

Merge branch 'master' into t/258

Krzysztof Krztoń hace 7 años
padre
commit
0f8827d6d8

+ 5 - 6
packages/ckeditor5-image/.travis.yml

@@ -11,17 +11,16 @@ language: node_js
 node_js:
 - '8'
 cache:
-- node_modules
+  yarn: true
 branches:
-   except:
-   - stable
+  except:
+  - stable
 before_install:
 - export DISPLAY=:99.0
 - sh -e /etc/init.d/xvfb start
-- npm config set package-lock false
-- npm i -g npm@^5.7.1
+- npm i -g yarn
 install:
-- npm install @ckeditor/ckeditor5-dev-tests
+- yarn add @ckeditor/ckeditor5-dev-tests
 - ckeditor5-dev-tests-install-dependencies
 script:
 - ckeditor5-dev-tests-travis

+ 1 - 1
packages/ckeditor5-image/package.json

@@ -31,7 +31,7 @@
     "@ckeditor/ckeditor5-typing": "^11.0.2",
     "@ckeditor/ckeditor5-undo": "^10.0.4",
     "eslint": "^5.5.0",
-    "eslint-config-ckeditor5": "^1.0.7",
+    "eslint-config-ckeditor5": "^1.0.9",
     "husky": "^0.14.3",
     "lint-staged": "^7.0.0"
   },

+ 10 - 12
packages/ckeditor5-image/src/image/imageediting.js

@@ -18,8 +18,6 @@ import {
 
 import { toImageWidget } from './utils';
 
-import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
-import { upcastElementToElement, upcastAttributeToAttribute } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 import ImageInsertCommand from './imageinsertcommand';
 
 /**
@@ -54,15 +52,15 @@ export default class ImageEditing extends Plugin {
 			allowAttributes: [ 'alt', 'src', 'srcset' ]
 		} );
 
-		conversion.for( 'dataDowncast' ).add( downcastElementToElement( {
+		conversion.for( 'dataDowncast' ).elementToElement( {
 			model: 'image',
 			view: ( modelElement, viewWriter ) => createImageViewElement( viewWriter )
-		} ) );
+		} );
 
-		conversion.for( 'editingDowncast' ).add( downcastElementToElement( {
+		conversion.for( 'editingDowncast' ).elementToElement( {
 			model: 'image',
 			view: ( modelElement, viewWriter ) => toImageWidget( createImageViewElement( viewWriter ), viewWriter, t( 'image widget' ) )
-		} ) );
+		} );
 
 		conversion.for( 'downcast' )
 			.add( modelToViewAttributeConverter( 'src' ) )
@@ -70,7 +68,7 @@ export default class ImageEditing extends Plugin {
 			.add( srcsetAttributeConverter() );
 
 		conversion.for( 'upcast' )
-			.add( upcastElementToElement( {
+			.elementToElement( {
 				view: {
 					name: 'img',
 					attributes: {
@@ -78,15 +76,15 @@ export default class ImageEditing extends Plugin {
 					}
 				},
 				model: ( viewImage, modelWriter ) => modelWriter.createElement( 'image', { src: viewImage.getAttribute( 'src' ) } )
-			} ) )
-			.add( upcastAttributeToAttribute( {
+			} )
+			.attributeToAttribute( {
 				view: {
 					name: 'img',
 					key: 'alt'
 				},
 				model: 'alt'
-			} ) )
-			.add( upcastAttributeToAttribute( {
+			} )
+			.attributeToAttribute( {
 				view: {
 					name: 'img',
 					key: 'srcset'
@@ -105,7 +103,7 @@ export default class ImageEditing extends Plugin {
 						return value;
 					}
 				}
-			} ) )
+			} )
 			.add( viewFigureToModel() );
 
 		// Register imageUpload command.

+ 13 - 12
packages/ckeditor5-image/src/image/utils.js

@@ -100,7 +100,9 @@ export function isImageAllowed( model ) {
 	const schema = model.schema;
 	const selection = model.document.selection;
 
-	return isImageAllowedInParent( selection, schema, model ) && checkSelectionWithObject( selection, schema );
+	return isImageAllowedInParent( selection, schema, model ) &&
+		!checkSelectionOnObject( selection, schema ) &&
+		isInOtherImage( selection );
 }
 
 // Checks if image is allowed by schema in optimal insertion parent.
@@ -112,29 +114,28 @@ function isImageAllowedInParent( selection, schema, model ) {
 	return schema.checkChild( parent, 'image' );
 }
 
-// Check used in image commands for additional cases when the command should be disabled:
-//
-// - selection is on object
-// - selection is inside object
+// Check if selection is on object.
 //
 // @returns {Boolean}
-function checkSelectionWithObject( selection, schema ) {
+function checkSelectionOnObject( selection, schema ) {
 	const selectedElement = selection.getSelectedElement();
 
-	const isSelectionOnObject = !!selectedElement && schema.isObject( selectedElement );
-	const isSelectionInObject = !![ ...selection.focus.getAncestors() ].find( ancestor => schema.isObject( ancestor ) );
+	return selectedElement && schema.isObject( selectedElement );
+}
 
-	return !isSelectionOnObject && !isSelectionInObject;
+// Checks if selection is placed in other image (ie. in caption).
+function isInOtherImage( selection ) {
+	return [ ...selection.focus.getAncestors() ].every( ancestor => !ancestor.is( 'image' ) );
 }
 
 // Returns a node that will be used to insert image with `model.insertContent` to check if image can be placed there.
 function getInsertImageParent( selection, model ) {
 	const insertAt = findOptimalInsertionPosition( selection, model );
 
-	let parent = insertAt.parent;
+	const parent = insertAt.parent;
 
-	if ( !parent.is( '$root' ) ) {
-		parent = parent.parent;
+	if ( parent.isEmpty && !parent.is( '$root' ) ) {
+		return parent.parent;
 	}
 
 	return parent;

+ 3 - 4
packages/ckeditor5-image/src/imagecaption/imagecaptionediting.js

@@ -8,7 +8,6 @@
  */
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
-import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 import { isImage } from '../image/utils';
 import {
 	captionElementCreator,
@@ -55,10 +54,10 @@ export default class ImageCaptionEditing extends Plugin {
 		editor.model.document.registerPostFixer( writer => this._insertMissingModelCaptionElement( writer ) );
 
 		// View to model converter for the data pipeline.
-		editor.conversion.for( 'upcast' ).add( upcastElementToElement( {
+		editor.conversion.for( 'upcast' ).elementToElement( {
 			view: matchImageCaption,
 			model: 'caption'
-		} ) );
+		} );
 
 		// Model to view converter for the data pipeline.
 		const createCaptionForData = writer => writer.createContainerElement( 'figcaption' );
@@ -237,7 +236,7 @@ function captionModelToView( elementCreator, hide = true ) {
 // @param {module:engine/view/containerelement~ContainerElement} viewCaption
 // @param {module:engine/model/element~Element} modelCaption
 // @param {module:engine/view/containerelement~ContainerElement} viewImage
-// @param {Object} conversionApi
+// @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
 function insertViewCaptionAndBind( viewCaption, modelCaption, viewImage, conversionApi ) {
 	const viewPosition = conversionApi.writer.createPositionAt( viewImage, 'end' );
 

+ 0 - 8
packages/ckeditor5-image/src/imagestyle/imagestyleediting.js

@@ -9,7 +9,6 @@
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import ImageStyleCommand from './imagestylecommand';
-import ImageEditing from '../image/imageediting';
 import { viewToModelStyleAttribute, modelToViewStyleAttribute } from './converters';
 import { normalizeImageStyles } from './utils';
 
@@ -23,13 +22,6 @@ export default class ImageStyleEditing extends Plugin {
 	/**
 	 * @inheritDoc
 	 */
-	static get requires() {
-		return [ ImageEditing ];
-	}
-
-	/**
-	 * @inheritDoc
-	 */
 	static get pluginName() {
 		return 'ImageStyleEditing';
 	}

+ 1 - 3
packages/ckeditor5-image/src/imagestyle/utils.js

@@ -95,9 +95,7 @@ const defaultIcons = {
  * @returns {Array.<module:image/imagestyle/imagestyleediting~ImageStyleFormat>}
  */
 export function normalizeImageStyles( configuredStyles = [] ) {
-	return configuredStyles
-		.map( _normalizeStyle )
-		.map( style => Object.assign( {}, style ) );
+	return configuredStyles.map( _normalizeStyle );
 }
 
 // Normalizes an image style provided in the {@link module:image/image~ImageConfig#styles}

+ 2 - 3
packages/ckeditor5-image/src/imageupload/imageuploadediting.js

@@ -11,7 +11,6 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
 import Notification from '@ckeditor/ckeditor5-ui/src/notification/notification';
 import UpcastWriter from '@ckeditor/ckeditor5-engine/src/view/upcastwriter';
-import { upcastAttributeToAttribute } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 
 import ImageUploadCommand from '../../src/imageupload/imageuploadcommand';
 import { isImageType, isLocalImage, fetchLocalImage } from '../../src/imageupload/utils';
@@ -49,13 +48,13 @@ export default class ImageUploadEditing extends Plugin {
 
 		// Register upcast converter for uploadId.
 		conversion.for( 'upcast' )
-			.add( upcastAttributeToAttribute( {
+			.attributeToAttribute( {
 				view: {
 					name: 'img',
 					key: 'uploadId'
 				},
 				model: 'uploadId'
-			} ) );
+			} );
 
 		// Handle pasted images.
 		// For every image file, a new file loader is created and a placeholder image is

+ 1 - 2
packages/ckeditor5-image/src/imageupload/imageuploadprogress.js

@@ -55,8 +55,7 @@ export default class ImageUploadProgress extends Plugin {
 	 *
 	 * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.
 	 * @param {Object} data Additional information about the change.
-	 * @param {module:engine/conversion/modelconsumable~ModelConsumable} consumable Values to consume.
-	 * @param {Object} conversionApi
+	 * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi
 	 */
 	uploadStatusChange( evt, data, conversionApi ) {
 		const editor = this.editor;

+ 7 - 10
packages/ckeditor5-image/tests/image/converters.js

@@ -11,9 +11,6 @@ import { toImageWidget } from '../../src/image/utils';
 import { createImageViewElement } from '../../src/image/imageediting';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 
-import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
-import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
-
 import { getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
 import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import env from '@ckeditor/ckeditor5-utils/src/env';
@@ -47,10 +44,10 @@ describe( 'Image converters', () => {
 				const editingElementCreator = ( modelElement, viewWriter ) =>
 					toImageWidget( createImageViewElement( viewWriter ), viewWriter, '' );
 
-				editor.conversion.for( 'editingDowncast' ).add( downcastElementToElement( {
+				editor.conversion.for( 'editingDowncast' ).elementToElement( {
 					model: 'image',
 					view: editingElementCreator
-				} ) );
+				} );
 
 				editor.conversion.for( 'downcast' )
 					.add( modelToViewAttributeConverter( 'src' ) )
@@ -75,7 +72,7 @@ describe( 'Image converters', () => {
 
 			editor.conversion.for( 'upcast' )
 				.add( viewFigureToModel() )
-				.add( upcastElementToElement( {
+				.elementToElement( {
 					view: {
 						name: 'img',
 						attributes: {
@@ -87,7 +84,7 @@ describe( 'Image converters', () => {
 
 						return writer.createElement( 'image', { src: viewImage.getAttribute( 'src' ) } );
 					}
-				} ) );
+				} );
 		} );
 
 		it( 'should find img element among children and convert it using already defined converters', () => {
@@ -98,8 +95,8 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should convert children allowed by schema and omit disallowed', () => {
-			editor.conversion.for( 'upcast' ).add( upcastElementToElement( { view: 'foo', model: 'foo' } ) );
-			editor.conversion.for( 'upcast' ).add( upcastElementToElement( { view: 'bar', model: 'bar' } ) );
+			editor.conversion.for( 'upcast' ).elementToElement( { view: 'foo', model: 'foo' } );
+			editor.conversion.for( 'upcast' ).elementToElement( { view: 'bar', model: 'bar' } );
 
 			schema.register( 'foo', { allowIn: 'image' } );
 			// Is allowed in root, but should not try to split image element.
@@ -112,7 +109,7 @@ describe( 'Image converters', () => {
 		} );
 
 		it( 'should split parent element when image is not allowed - in the middle', () => {
-			editor.conversion.for( 'upcast' ).add( upcastElementToElement( { view: 'div', model: 'div' } ) );
+			editor.conversion.for( 'upcast' ).elementToElement( { view: 'div', model: 'div' } );
 
 			schema.register( 'div', { inheritAllFrom: '$block' } );
 			schema.extend( 'image', { disallowIn: 'div' } );

+ 28 - 12
packages/ckeditor5-image/tests/image/imageinsertcommand.js

@@ -9,7 +9,6 @@ import ImageInsertCommand from '../../src/image/imageinsertcommand';
 import Image from '../../src/image/imageediting';
 
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
 import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
 describe( 'ImageInsertCommand', () => {
@@ -59,7 +58,7 @@ describe( 'ImageInsertCommand', () => {
 		it( 'should be true when the selection directly in a block', () => {
 			model.schema.register( 'block', { inheritAllFrom: '$block' } );
 			model.schema.extend( '$text', { allowIn: 'block' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'block', view: 'block' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'block', view: 'block' } );
 
 			setModelData( model, '<block>foo[]</block>' );
 			expect( command.isEnabled ).to.be.true;
@@ -76,26 +75,43 @@ describe( 'ImageInsertCommand', () => {
 				allowContentOf: '$block',
 				isLimit: true
 			} );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'caption', view: 'figcaption' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'caption', view: 'figcaption' } );
 			setModelData( model, '<image><caption>[]</caption></image>' );
 			expect( command.isEnabled ).to.be.false;
 		} );
 
 		it( 'should be false when the selection is on other object', () => {
 			model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'object', view: 'object' } );
 			setModelData( model, '[<object></object>]' );
 
 			expect( command.isEnabled ).to.be.false;
 		} );
 
-		it( 'should be false when the selection is inside other object', () => {
-			model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
-			model.schema.extend( '$text', { allowIn: 'object' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
-			setModelData( model, '<object>[]</object>' );
+		it( 'should be true when the selection is inside isLimit element which allows image', () => {
+			model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
+			model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
+			model.schema.extend( '$block', { allowIn: 'limit' } );
 
-			expect( command.isEnabled ).to.be.false;
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'outerObject', view: 'outerObject' } );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'limit', view: 'limit' } );
+
+			setModelData( model, '<outerObject><limit>[]</limit></outerObject>' );
+
+			expect( command.isEnabled ).to.be.true;
+		} );
+
+		it( 'should be true when the selection is inside isLimit element which allows image', () => {
+			model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
+			model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
+			model.schema.extend( '$block', { allowIn: 'limit' } );
+
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'outerObject', view: 'outerObject' } );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'limit', view: 'limit' } );
+
+			setModelData( model, '<outerObject><limit><paragraph>foo[]</paragraph></limit></outerObject>' );
+
+			expect( command.isEnabled ).to.be.true;
 		} );
 
 		it( 'should be false when schema disallows image', () => {
@@ -107,7 +123,7 @@ describe( 'ImageInsertCommand', () => {
 					return false;
 				}
 			} );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'block', view: 'block' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'block', view: 'block' } );
 
 			setModelData( model, '<block><paragraph>[]</paragraph></block>' );
 
@@ -147,7 +163,7 @@ describe( 'ImageInsertCommand', () => {
 			} );
 			model.schema.extend( '$text', { allowIn: 'other' } );
 
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'other', view: 'p' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'other', view: 'p' } );
 
 			setModelData( model, '<other>[]</other>' );
 

+ 28 - 12
packages/ckeditor5-image/tests/image/utils.js

@@ -12,7 +12,6 @@ import { isWidget, getLabel } from '@ckeditor/ckeditor5-widget/src/utils';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
-import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
 import Image from '../../src/image/imageediting';
 
 describe( 'image widget utils', () => {
@@ -150,7 +149,7 @@ describe( 'image widget utils', () => {
 		it( 'should return true when the selection directly in a block', () => {
 			model.schema.register( 'block', { inheritAllFrom: '$block' } );
 			model.schema.extend( '$text', { allowIn: 'block' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'block', view: 'block' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'block', view: 'block' } );
 
 			setModelData( model, '<block>foo[]</block>' );
 			expect( isImageAllowed( model ) ).to.be.true;
@@ -167,26 +166,43 @@ describe( 'image widget utils', () => {
 				allowContentOf: '$block',
 				isLimit: true
 			} );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'caption', view: 'figcaption' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'caption', view: 'figcaption' } );
 			setModelData( model, '<image><caption>[]</caption></image>' );
 			expect( isImageAllowed( model ) ).to.be.false;
 		} );
 
 		it( 'should return false when the selection is on other object', () => {
 			model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'object', view: 'object' } );
 			setModelData( model, '[<object></object>]' );
 
 			expect( isImageAllowed( model ) ).to.be.false;
 		} );
 
-		it( 'should return false when the selection is inside other object', () => {
-			model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
-			model.schema.extend( '$text', { allowIn: 'object' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
-			setModelData( model, '<object>[]</object>' );
+		it( 'should be true when the selection is inside isLimit element which allows image', () => {
+			model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
+			model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
+			model.schema.extend( '$block', { allowIn: 'limit' } );
 
-			expect( isImageAllowed( model ) ).to.be.false;
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'outerObject', view: 'outerObject' } );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'limit', view: 'limit' } );
+
+			setModelData( model, '<outerObject><limit>[]</limit></outerObject>' );
+
+			expect( isImageAllowed( model ) ).to.be.true;
+		} );
+
+		it( 'should be true when the selection is inside isLimit element which allows image', () => {
+			model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
+			model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
+			model.schema.extend( '$block', { allowIn: 'limit' } );
+
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'outerObject', view: 'outerObject' } );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'limit', view: 'limit' } );
+
+			setModelData( model, '<outerObject><limit><paragraph>foo[]</paragraph></limit></outerObject>' );
+
+			expect( isImageAllowed( model ) ).to.be.true;
 		} );
 
 		it( 'should return false when schema disallows image', () => {
@@ -198,7 +214,7 @@ describe( 'image widget utils', () => {
 					return false;
 				}
 			} );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'block', view: 'block' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'block', view: 'block' } );
 
 			setModelData( model, '<block><paragraph>[]</paragraph></block>' );
 
@@ -250,7 +266,7 @@ describe( 'image widget utils', () => {
 			} );
 			model.schema.extend( '$text', { allowIn: 'other' } );
 
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'other', view: 'p' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'other', view: 'p' } );
 
 			setModelData( model, '<other>[]</other>' );
 

+ 2 - 1
packages/ckeditor5-image/tests/imagestyle.js

@@ -4,6 +4,7 @@
  */
 
 import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
+import Image from '../src/image';
 import ImageStyle from '../src/imagestyle';
 import ImageStyleEditing from '../src/imagestyle/imagestyleediting';
 import ImageStyleUI from '../src/imagestyle/imagestyleui';
@@ -18,7 +19,7 @@ describe( 'ImageStyle', () => {
 
 		return ClassicTestEditor
 			.create( editorElement, {
-				plugins: [ ImageStyle ]
+				plugins: [ Image, ImageStyle ]
 			} )
 			.then( newEditor => {
 				editor = newEditor;

+ 6 - 10
packages/ckeditor5-image/tests/imagestyle/imagestyleediting.js

@@ -32,7 +32,7 @@ describe( 'ImageStyleEditing', () => {
 		beforeEach( () => {
 			return VirtualTestEditor
 				.create( {
-					plugins: [ ImageStyleEditing ],
+					plugins: [ ImageEditing, ImageStyleEditing ]
 				} )
 				.then( newEditor => {
 					editor = newEditor;
@@ -42,17 +42,13 @@ describe( 'ImageStyleEditing', () => {
 		it( 'should be loaded', () => {
 			expect( editor.plugins.get( ImageStyleEditing ) ).to.be.instanceOf( ImageStyleEditing );
 		} );
-
-		it( 'should load image editing', () => {
-			expect( editor.plugins.get( ImageEditing ) ).to.be.instanceOf( ImageEditing );
-		} );
 	} );
 
 	describe( 'init', () => {
 		beforeEach( () => {
 			return VirtualTestEditor
 				.create( {
-					plugins: [ ImageStyleEditing ],
+					plugins: [ ImageEditing, ImageStyleEditing ],
 					image: {
 						styles: [
 							{ name: 'fullStyle', title: 'foo', icon: 'object-center', isDefault: true },
@@ -72,7 +68,7 @@ describe( 'ImageStyleEditing', () => {
 		it( 'should define image.styles config', () => {
 			return VirtualTestEditor
 				.create( {
-					plugins: [ ImageStyleEditing ]
+					plugins: [ ImageEditing, ImageStyleEditing ]
 				} )
 				.then( newEditor => {
 					editor = newEditor;
@@ -265,7 +261,7 @@ describe( 'ImageStyleEditing', () => {
 		it( 'should fall back to defaults when no image.styles', () => {
 			return VirtualTestEditor
 				.create( {
-					plugins: [ ImageStyleEditing ]
+					plugins: [ ImageEditing, ImageStyleEditing ]
 				} )
 				.then( newEditor => {
 					editor = newEditor;
@@ -277,7 +273,7 @@ describe( 'ImageStyleEditing', () => {
 		it( 'should not alter the image.styles config', () => {
 			return VirtualTestEditor
 				.create( {
-					plugins: [ ImageStyleEditing ],
+					plugins: [ ImageEditing, ImageStyleEditing ],
 					image: {
 						styles: [
 							'side'
@@ -294,7 +290,7 @@ describe( 'ImageStyleEditing', () => {
 		it( 'should not alter object definitions in the image.styles config', () => {
 			return VirtualTestEditor
 				.create( {
-					plugins: [ ImageStyleEditing ],
+					plugins: [ ImageEditing, ImageStyleEditing ],
 					image: {
 						styles: [
 							{ name: 'side' }

+ 4 - 3
packages/ckeditor5-image/tests/imagestyle/imagestyleui.js

@@ -6,6 +6,7 @@
 import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
 import ImageStyleEditing from '../../src/imagestyle/imagestyleediting';
 import ImageStyleUI from '../../src/imagestyle/imagestyleui';
+import ImageEditing from '../../src/image/imageediting';
 import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
 import global from '@ckeditor/ckeditor5-utils/src/dom/global';
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
@@ -26,7 +27,7 @@ describe( 'ImageStyleUI', () => {
 
 		return ClassicTestEditor
 			.create( editorElement, {
-				plugins: [ ImageStyleEditing, ImageStyleUI ],
+				plugins: [ ImageEditing, ImageStyleEditing, ImageStyleUI ],
 				image: {
 					styles
 				}
@@ -77,7 +78,7 @@ describe( 'ImageStyleUI', () => {
 
 		return ClassicTestEditor
 			.create( editorElement, {
-				plugins: [ TranslationMock, ImageStyleEditing, ImageStyleUI ],
+				plugins: [ TranslationMock, ImageEditing, ImageStyleEditing, ImageStyleUI ],
 				image: {
 					styles: [
 						{ name: 'style 1', title: 'Side image', icon: 'style1-icon', isDefault: true }
@@ -99,7 +100,7 @@ describe( 'ImageStyleUI', () => {
 
 		return ClassicTestEditor
 			.create( editorElement, {
-				plugins: [ ImageStyleEditing, ImageStyleUI ],
+				plugins: [ ImageEditing, ImageStyleEditing, ImageStyleUI ],
 				image: {
 					styles,
 					toolbar: [ 'foo', 'bar' ]

+ 28 - 12
packages/ckeditor5-image/tests/imageupload/imageuploadcommand.js

@@ -14,7 +14,6 @@ import { createNativeFileMock, UploadAdapterMock } from '@ckeditor/ckeditor5-upl
 import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import Image from '../../src/image/imageediting';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import { downcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/downcast-converters';
 
 import log from '@ckeditor/ckeditor5-utils/src/log';
 
@@ -78,7 +77,7 @@ describe( 'ImageUploadCommand', () => {
 		it( 'should be true when the selection directly in a block', () => {
 			model.schema.register( 'block', { inheritAllFrom: '$block' } );
 			model.schema.extend( '$text', { allowIn: 'block' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'block', view: 'block' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'block', view: 'block' } );
 
 			setModelData( model, '<block>foo[]</block>' );
 			expect( command.isEnabled ).to.be.true;
@@ -95,26 +94,43 @@ describe( 'ImageUploadCommand', () => {
 				allowContentOf: '$block',
 				isLimit: true
 			} );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'caption', view: 'figcaption' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'caption', view: 'figcaption' } );
 			setModelData( model, '<image><caption>[]</caption></image>' );
 			expect( command.isEnabled ).to.be.false;
 		} );
 
 		it( 'should be false when the selection is on other object', () => {
 			model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'object', view: 'object' } );
 			setModelData( model, '[<object></object>]' );
 
 			expect( command.isEnabled ).to.be.false;
 		} );
 
-		it( 'should be false when the selection is inside other object', () => {
-			model.schema.register( 'object', { isObject: true, allowIn: '$root' } );
-			model.schema.extend( '$text', { allowIn: 'object' } );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'object', view: 'object' } ) );
-			setModelData( model, '<object>[]</object>' );
+		it( 'should be true when the selection is inside isLimit element which allows image', () => {
+			model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
+			model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
+			model.schema.extend( '$block', { allowIn: 'limit' } );
 
-			expect( command.isEnabled ).to.be.false;
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'outerObject', view: 'outerObject' } );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'limit', view: 'limit' } );
+
+			setModelData( model, '<outerObject><limit>[]</limit></outerObject>' );
+
+			expect( command.isEnabled ).to.be.true;
+		} );
+
+		it( 'should be true when the selection is inside isLimit element which allows image', () => {
+			model.schema.register( 'outerObject', { isObject: true, isBlock: true, allowIn: '$root' } );
+			model.schema.register( 'limit', { isLimit: true, allowIn: 'outerObject' } );
+			model.schema.extend( '$block', { allowIn: 'limit' } );
+
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'outerObject', view: 'outerObject' } );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'limit', view: 'limit' } );
+
+			setModelData( model, '<outerObject><limit><paragraph>foo[]</paragraph></limit></outerObject>' );
+
+			expect( command.isEnabled ).to.be.true;
 		} );
 
 		it( 'should be false when schema disallows image', () => {
@@ -126,7 +142,7 @@ describe( 'ImageUploadCommand', () => {
 					return false;
 				}
 			} );
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'block', view: 'block' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'block', view: 'block' } );
 
 			setModelData( model, '<block><paragraph>[]</paragraph></block>' );
 
@@ -169,7 +185,7 @@ describe( 'ImageUploadCommand', () => {
 			} );
 			model.schema.extend( '$text', { allowIn: 'other' } );
 
-			editor.conversion.for( 'downcast' ).add( downcastElementToElement( { model: 'other', view: 'p' } ) );
+			editor.conversion.for( 'downcast' ).elementToElement( { model: 'other', view: 'p' } );
 
 			setModelData( model, '<other>[]</other>' );
 

+ 8 - 15
packages/ckeditor5-image/tests/imageupload/imageuploadediting.js

@@ -492,7 +492,7 @@ describe( 'ImageUploadEditing', () => {
 
 		expect( loader.status ).to.equal( 'reading' );
 
-		loader.file.then( () => {
+		return loader.file.then( () => {
 			nativeReaderMock.mockSuccess( base64Sample );
 
 			const image = doc.getRoot().getChild( 0 );
@@ -500,10 +500,8 @@ describe( 'ImageUploadEditing', () => {
 				writer.remove( image );
 			} );
 
-			tryExpect( done, () => {
-				expect( loader.status ).to.equal( 'aborted' );
-				sinon.assert.calledOnce( abortSpy );
-			} );
+			expect( loader.status ).to.equal( 'aborted' );
+			sinon.assert.calledOnce( abortSpy );
 		} );
 	} );
 
@@ -781,10 +779,8 @@ describe( 'ImageUploadEditing', () => {
 	// Skip this test on Edge as we mock `File` object there so there is no sense in testing it.
 	( isEdgeEnv ? it.skip : it )( 'should get file extension from base64 string', done => {
 		editor.plugins.get( 'Clipboard' ).on( 'inputTransformation', () => {
-			loader.file.then( file => {
-				tryExpect( done, () => {
-					expect( file.name.split( '.' ).pop() ).to.equal( 'png' );
-				} );
+			tryExpect( done, () => {
+				loader.file.then( file => expect( file.name.split( '.' ).pop() ).to.equal( 'png' ) );
 			} );
 		}, { priority: 'low' } );
 
@@ -811,10 +807,8 @@ describe( 'ImageUploadEditing', () => {
 	// Skip this test on Edge as we mock `File` object there so there is no sense in testing it.
 	( isEdgeEnv ? it.skip : it )( 'should use fallback file extension', done => {
 		editor.plugins.get( 'Clipboard' ).on( 'inputTransformation', () => {
-			loader.file.then( file => {
-				tryExpect( done, () => {
-					expect( file.name.split( '.' ).pop() ).to.equal( 'jpeg' );
-				} );
+			tryExpect( done, () => {
+				loader.file.then( file => expect( file.name.split( '.' ).pop() ).to.equal( 'jpeg' ) );
 			} );
 		}, { priority: 'low' } );
 
@@ -915,8 +909,7 @@ function expectModel( done, actual, expected ) {
 }
 
 // Runs given expect function in a try-catch. It should be used only when `expect` is called as a result of a `Promise`
-// resolution. In such cases all errors may be caught by tested code and needs to be rethrow to be correctly processed
-// by a testing framework.
+// resolution as all errors may be caught by tested code and needs to be rethrow to be correctly processed by a testing framework.
 //
 // @param {Function} doneFn Function to run when assertion is done.
 // @param {Function} expectFn Function containing all assertions.