Преглед на файлове

Added ImageResizeCommand.

Piotrek Koszuliński преди 6 години
родител
ревизия
a52c67e8b1

+ 8 - 9
packages/ckeditor5-image/src/imageresize.js

@@ -9,6 +9,7 @@
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import WidgetResize from '@ckeditor/ckeditor5-widget/src/widgetresize';
+import ImageResizeCommand from './imageresize/imageresizecommand';
 
 /**
  *	Image resize plugin.
@@ -36,6 +37,11 @@ export default class ImageResize extends Plugin {
 	init() {
 		const editor = this.editor;
 
+		this._registerSchema();
+		this._registerConverters();
+
+		editor.commands.add( 'imageResize', new ImageResizeCommand( editor ) );
+
 		editor.editing.downcastDispatcher.on( 'insert:image', ( evt, data, conversionApi ) => {
 			const widget = conversionApi.mapper.toViewElement( data.item );
 
@@ -58,9 +64,7 @@ export default class ImageResize extends Plugin {
 						return !imageStyle || imageStyle == 'full';
 					},
 					onCommit( resizerState ) {
-						editor.model.change( writer => {
-							writer.setAttribute( 'width', resizerState.proposedWidth + 'px', data.item );
-						} );
+						editor.execute( 'imageResize', { width: resizerState.proposedWidth + 'px' } );
 					}
 				} );
 
@@ -71,12 +75,7 @@ export default class ImageResize extends Plugin {
 					} );
 				}
 			} );
-		}, {
-			priority: 'low'
-		} );
-
-		this._registerSchema();
-		this._registerConverters();
+		}, { priority: 'low' } );
 	}
 
 	/**

+ 58 - 0
packages/ckeditor5-image/src/imageresize/imageresizecommand.js

@@ -0,0 +1,58 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module image/imagestyle/imageresize
+ */
+
+import Command from '@ckeditor/ckeditor5-core/src/command';
+import { isImage } from '../image/utils';
+
+/**
+ * The image resize command. Currently, it supports only the width attribute.
+ *
+ * @extends module:core/command~Command
+ */
+export default class ImageResize extends Command {
+	/**
+	 * @inheritDoc
+	 */
+	refresh() {
+		const element = this.editor.model.document.selection.getSelectedElement();
+
+		this.isEnabled = isImage( element );
+
+		if ( !element || !element.hasAttribute( 'width' ) ) {
+			this.value = null;
+		} else {
+			this.value = {
+				width: element.getAttribute( 'width' ),
+				height: null
+			};
+		}
+	}
+
+	/**
+	 * Executes the command.
+	 *
+	 *		// Sets the width to 50%:
+	 *		editor.execute( 'imageResize', { width: '50%' } );
+	 *
+	 *		// Removes the width attribute:
+	 *		editor.execute( 'imageResize', { width: null } );
+	 *
+	 * @param {Object} options
+	 * @param {String|null} options.width The new width of the image.
+	 * @fires execute
+	 */
+	execute( options ) {
+		const model = this.editor.model;
+		const imageElement = model.document.selection.getSelectedElement();
+
+		model.change( writer => {
+			writer.setAttribute( 'width', options.width, imageElement );
+		} );
+	}
+}

+ 34 - 42
packages/ckeditor5-image/tests/imageresize.js

@@ -11,6 +11,7 @@ import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 import Image from '../src/image';
 import ImageResize from '../src/imageresize';
+import ImageResizeCommand from '../src/imageresize/imageresizecommand';
 import ImageStyle from '../src/imagestyle';
 import Undo from '@ckeditor/ckeditor5-undo/src/undo';
 import Table from '@ckeditor/ckeditor5-table/src/table';
@@ -105,6 +106,12 @@ describe( 'ImageResize', () => {
 		} );
 	} );
 
+	describe( 'command', () => {
+		it( 'defines the imageResize command', () => {
+			expect( editor.commands.get( 'imageResize' ) ).to.be.instanceOf( ImageResizeCommand );
+		} );
+	} );
+
 	describe( 'visual resizers', () => {
 		it( 'correct amount is added by default', () => {
 			const resizers = document.querySelectorAll( '.ck-widget__resizer__handle' );
@@ -140,18 +147,31 @@ describe( 'ImageResize', () => {
 		} );
 	} );
 
+	it( 'uses the command on commit', async () => {
+		setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
+
+		widget = viewDocument.getRoot().getChild( 1 );
+
+		const spy = sinon.spy( editor.commands.get( 'imageResize' ), 'execute' );
+
+		await generateResizeTest( {
+			expectedWidth: 80,
+			pointerOffset: {
+				x: 10,
+				y: -10
+			},
+			resizerPosition: 'bottom-left'
+		} )();
+
+		expect( spy.calledOnce ).to.be.true;
+		expect( spy.args[ 0 ][ 0 ] ).to.deep.equal( { width: '80px' } );
+	} );
+
 	describe( 'standard image resizing', () => {
 		beforeEach( () => {
-			editor.setData( `<p>foo</p><figure><img src="${ IMAGE_SRC_FIXTURE }"></figure>` );
+			setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
 
 			widget = viewDocument.getRoot().getChild( 1 );
-
-			const domEventDataMock = {
-				target: widget,
-				preventDefault: sinon.spy()
-			};
-
-			viewDocument.fire( 'mousedown', domEventDataMock );
 		} );
 
 		it( 'shrinks correctly with left-bottom handler', generateResizeTest( {
@@ -249,15 +269,9 @@ describe( 'ImageResize', () => {
 
 	describe( 'side image resizing', () => {
 		beforeEach( () => {
-			editor.setData( `<p>foo</p><figure class="image image-style-side"><img src="${ IMAGE_SRC_FIXTURE }"></figure>` );
+			setData( editor.model, `<paragraph>foo</paragraph>[<image imageStyle="side" src="${ IMAGE_SRC_FIXTURE }"></image>]` );
 
 			widget = viewDocument.getRoot().getChild( 1 );
-			const domEventDataMock = {
-				target: widget,
-				preventDefault: sinon.spy()
-			};
-
-			viewDocument.fire( 'mousedown', domEventDataMock );
 		} );
 
 		it( 'shrinks correctly with left-bottom handler', generateSideResizeTest( {
@@ -370,16 +384,9 @@ describe( 'ImageResize', () => {
 
 	describe( 'undo integration', () => {
 		beforeEach( () => {
-			editor.setData( `<p>foo</p><figure><img src="${ IMAGE_SRC_FIXTURE }"></figure>` );
+			setData( editor.model, `<paragraph>foo</paragraph>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]` );
 
 			widget = viewDocument.getRoot().getChild( 1 );
-
-			const domEventDataMock = {
-				target: widget,
-				preventDefault: sinon.spy()
-			};
-
-			viewDocument.fire( 'mousedown', domEventDataMock );
 		} );
 
 		it( 'has correct border size after undo', async () => {
@@ -406,28 +413,13 @@ describe( 'ImageResize', () => {
 
 	describe( 'table integration', () => {
 		beforeEach( () => {
-			editor.setData(
-				`<figure class="table">
-					<table>
-						<tbody>
-							<tr>
-								<td>
-									<figure class="image"><img src="${ IMAGE_SRC_FIXTURE }" alt="Sample image"></figure>
-								</td>
-							</tr>
-						</tbody>
-					</table>
-				</figure>`
+			setData( editor.model,
+				'<table>' +
+					`<tableRow><tableCell>[<image src="${ IMAGE_SRC_FIXTURE }"></image>]</tableCell></tableRow>` +
+				'</table>'
 			);
 
 			widget = viewDocument.getRoot().getChild( 0 ).getChild( 1 ).getChild( 0 ).getChild( 0 ).getChild( 0 ).getChild( 0 );
-
-			const domEventDataMock = {
-				target: widget,
-				preventDefault: sinon.spy()
-			};
-
-			viewDocument.fire( 'mousedown', domEventDataMock );
 		} );
 
 		it( 'works when resizing in a table', generateResizeTest( {

+ 88 - 0
packages/ckeditor5-image/tests/imageresize/imageresizecommand.js

@@ -0,0 +1,88 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
+import ImageResizeCommand from '../../src/imageresize/imageresizecommand';
+import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+
+describe( 'ImageStyleCommand', () => {
+	let model, command;
+
+	beforeEach( () => {
+		return ModelTestEditor.create()
+			.then( newEditor => {
+				model = newEditor.model;
+				command = new ImageResizeCommand( newEditor );
+
+				model.schema.register( 'p', { inheritAllFrom: '$block' } );
+
+				model.schema.register( 'image', {
+					isObject: true,
+					isBlock: true,
+					allowWhere: '$block',
+					allowAttributes: 'width'
+				} );
+			} );
+	} );
+
+	describe( '#isEnabled', () => {
+		it( 'is true when image is selected', () => {
+			setData( model, '<p>x</p>[<image width="50px"></image>]<p>x</p>' );
+
+			expect( command ).to.have.property( 'isEnabled', true );
+		} );
+
+		it( 'is false when image is not selected', () => {
+			setData( model, '<p>x[]</p><image width="50px"></image>' );
+
+			expect( command ).to.have.property( 'isEnabled', false );
+		} );
+
+		it( 'is false when more than one image is selected', () => {
+			setData( model, '<p>x</p>[<image width="50px"></image><image width="50px"></image>]' );
+
+			expect( command ).to.have.property( 'isEnabled', false );
+		} );
+	} );
+
+	describe( '#value', () => {
+		it( 'is null when image is not selected', () => {
+			setData( model, '<p>x[]</p><image width="50px"></image>' );
+
+			expect( command ).to.have.property( 'value', null );
+		} );
+
+		it( 'is set to an object with a width property (and height set to null)', () => {
+			setData( model, '<p>x</p>[<image width="50px"></image>]<p>x</p>' );
+
+			expect( command ).to.have.deep.property( 'value', { width: '50px', height: null } );
+		} );
+
+		it( 'is set to null if image does not have the width set', () => {
+			setData( model, '<p>x</p>[<image></image>]<p>x</p>' );
+
+			expect( command ).to.have.property( 'value', null );
+		} );
+	} );
+
+	describe( 'execute()', () => {
+		it( 'sets image width', () => {
+			setData( model, '[<image width="50px"></image>]' );
+
+			command.execute( { width: '100%' } );
+
+			expect( getData( model ) ).to.equal( '[<image width="100%"></image>]' );
+		} );
+
+		it( 'removes image width when null passed', () => {
+			setData( model, '[<image width="50px"></image>]' );
+
+			command.execute( { width: null } );
+
+			expect( getData( model ) ).to.equal( '[<image></image>]' );
+			expect( model.document.getRoot().getChild( 0 ).hasAttribute( 'width' ) ).to.be.false;
+		} );
+	} );
+} );