Explorar el Código

Added ImageUploadCommand.

Szymon Kupś hace 8 años
padre
commit
a4f8681b3c

+ 3 - 0
packages/ckeditor5-upload/package.json

@@ -5,10 +5,13 @@
   "keywords": [],
   "dependencies": {
 	  "@ckeditor/ckeditor5-core": "^0.7.0",
+	  "@ckeditor/ckeditor5-engine": "^0.8.0",
 	  "@ckeditor/ckeditor5-utils": "^0.8.0"
   },
   "devDependencies": {
     "@ckeditor/ckeditor5-dev-lint": "^2.0.2",
+    "@ckeditor/ckeditor5-image": "v0.4.0",
+  	"@ckeditor/ckeditor5-paragraph": "v0.6.1",
     "gulp": "^3.9.1",
     "guppy-pre-commit": "^0.4.0"
   },

+ 54 - 0
packages/ckeditor5-upload/src/imageuploadcommand.js

@@ -0,0 +1,54 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import ModelDocumentFragment from '@ckeditor/ckeditor5-engine/src/model/documentfragment';
+import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
+import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range';
+import ModelSelection from '@ckeditor/ckeditor5-engine/src/model/selection';
+import FileRepository from './filerepository';
+import { isImageType } from './utils';
+import Command from '@ckeditor/ckeditor5-core/src/command/command';
+
+/**
+ * Image upload command.
+ *
+ * @extends module:core/command/command~Command
+ */
+export default class ImageUploadCommand extends Command {
+	/**
+	 * Executes command.
+	 *
+	 * @protected
+	 * @param {Object} options Options for executed command.
+	 * @param {File} options.file Image file to upload.
+	 * @param {module:engine/model/batch~Batch} [options.batch] Batch to collect all the change steps.
+	 * New batch will be created if this option is not set.
+	 */
+	_doExecute( options = {} ) {
+		const editor = this.editor;
+		const doc = editor.document;
+		const batch = options.batch || doc.batch();
+		const file = options.file;
+		const fileRepository = editor.plugins.get( FileRepository );
+
+		if ( !isImageType( file ) ) {
+			return;
+		}
+
+		doc.enqueueChanges( () => {
+			const imageElement = new ModelElement( 'image', {
+				uploadId: fileRepository.createLoader( file ).id
+			} );
+			const documentFragment = new ModelDocumentFragment( [ imageElement ] );
+
+			const firstBlock = doc.selection.getSelectedBlocks().next().value;
+			const range = ModelRange.createFromParentsAndOffsets( firstBlock, 0, firstBlock, 0 );
+			const insertSelection = new ModelSelection();
+			insertSelection.setRanges( [ range ] );
+
+			editor.data.insertContent( documentFragment, insertSelection, batch );
+		} );
+	}
+}

+ 17 - 0
packages/ckeditor5-upload/src/utils.js

@@ -0,0 +1,17 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * Checks if given file is an image.
+ *
+ * @param {File} file
+ * @returns {Boolean}
+ */
+export function isImageType( file ) {
+	const types = /^image\/(jpeg|png|gif|bmp)$/;
+
+	return types.test( file.type );
+}
+

+ 1 - 0
packages/ckeditor5-upload/tests/_utils/mocks.js

@@ -4,6 +4,7 @@
  */
 
 export const createNativeFileMock = () => ( {
+	type: 'image/jpeg',
 	size: 1024
 } );
 

+ 73 - 0
packages/ckeditor5-upload/tests/imageuploadcommand.js

@@ -0,0 +1,73 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
+import ImageUploadCommand from '../src/imageuploadcommand';
+import FileRepository from '../src/filerepository';
+import { createNativeFileMock, AdapterMock } from './_utils/mocks';
+import { setData as setModelData, getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import Image from '@ckeditor/ckeditor5-image/src/image/imageengine';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+
+describe( 'ImageUploadCommand', () => {
+	let editor, command, adapterMock, document, fileRepository;
+
+	beforeEach( () => {
+		return ClassicTestEditor.create( {
+			plugins: [ FileRepository, Image, Paragraph ]
+		} )
+		.then( newEditor => {
+			editor = newEditor;
+			command = new ImageUploadCommand( editor );
+			fileRepository = editor.plugins.get( FileRepository );
+			fileRepository.createAdapter = loader => {
+				adapterMock = new AdapterMock( loader );
+
+				return adapterMock;
+			};
+
+			document = editor.document;
+
+			const schema = document.schema;
+			schema.allow( { name: 'image', attributes: [ 'uploadId' ], inside: '$root' } );
+			schema.requireAttributes( 'image', [ 'uploadId' ] );
+		} );
+	} );
+
+	describe( '_doExecute', () => {
+		it( 'should insert image', () => {
+			const file = createNativeFileMock();
+			setModelData( document, '<paragraph>foo[]</paragraph>' );
+			command._doExecute( { file } );
+
+			const id = fileRepository.getLoader( file ).id;
+
+			expect( getModelData( document ) ).to.equal( `<image uploadId="${ id }"></image><paragraph>foo[]</paragraph>` );
+		} );
+
+		it( 'should not insert non-image', () => {
+			const file = createNativeFileMock();
+			file.type = 'audio/mpeg3';
+			setModelData( document, '<paragraph>foo[]</paragraph>' );
+			command._doExecute( { file } );
+
+			expect( getModelData( document ) ).to.equal( '<paragraph>foo[]</paragraph>' );
+		} );
+
+		it( 'should allow to provide batch instance', () => {
+			const batch = document.batch();
+			const file = createNativeFileMock();
+			const spy = sinon.spy( batch, 'insert' );
+
+			setModelData( document, '<paragraph>foo[]</paragraph>' );
+
+			command._doExecute( { batch, file } );
+			const id = fileRepository.getLoader( file ).id;
+
+			expect( getModelData( document ) ).to.equal( `<image uploadId="${ id }"></image><paragraph>foo[]</paragraph>` );
+			sinon.assert.calledOnce( spy );
+		} );
+	} );
+} );