8
0
Эх сурвалжийг харах

Moved ImageCaptionEngine methods to utils file. Added tests.

Szymon Kupś 9 жил өмнө
parent
commit
a39c64a774

+ 15 - 33
packages/ckeditor5-image/src/imagecaption/imagecaptionengine.js

@@ -12,13 +12,19 @@ import ModelTreeWalker from '@ckeditor/ckeditor5-engine/src/model/treewalker';
 import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
 import ViewContainerElement from '@ckeditor/ckeditor5-engine/src/view/containerelement';
 import ViewElement from '@ckeditor/ckeditor5-engine/src/view/element';
-import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';
 import ViewRange from '@ckeditor/ckeditor5-engine/src/view/range';
 import viewWriter from '@ckeditor/ckeditor5-engine/src/view/writer';
 import ModelPosition from '@ckeditor/ckeditor5-engine/src/model/position';
 import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
 import { isImage, isImageWidget } from '../image/utils';
-import { captionElementCreator, isCaption, getCaptionFromImage, isInsideCaption } from './utils';
+import {
+	captionElementCreator,
+	isCaption,
+	getCaptionFromImage,
+	isInsideCaption,
+	matchImageCaption,
+	insertViewCaptionAndBind
+} from './utils';
 
 /**
  * The image caption engine plugin.
@@ -189,6 +195,13 @@ function insertMissingModelCaptionElement( evt, changeType, data, batch ) {
 	}
 }
 
+// Returns function that should be executed before model to view conversion is made. It checks if insertion is placed
+// inside model caption and makes sure that corresponding view element exists.
+//
+// @private
+// @param {function} creator Function that returns view caption element.
+// @param {module:engine/conversion/mapper~Mapper} mapper
+// @return {function}
 function insertMissingViewCaptionElement( creator, mapper ) {
 	return ( evt, data ) => {
 		if ( isInsideCaption( data.item ) ) {
@@ -230,34 +243,3 @@ function captionModelToView( elementCreator ) {
 		}
 	};
 }
-
-// Checks if given element is `figcaption` element and is placed inside image `figure` element.
-//
-// @private
-// @param {module:engine/view/element~Element} element
-// @returns {Object|null} Returns object accepted by {@link module:engine/view/matcher~Matcher} or `null` if element
-// cannot be matched.
-function matchImageCaption( element ) {
-	const parent = element.parent;
-
-	// Convert only captions for images.
-	if ( element.name == 'figcaption' && parent && parent.name == 'figure' && parent.hasClass( 'image' ) ) {
-		return { name: true };
-	}
-
-	return null;
-}
-
-// Inserts `viewCaption` at the end of `viewImage` and binds it to `modelCaption`.
-//
-// @private
-// @param {module:engine/view/element~Element} viewCaption
-// @param {module:engine/model/element~Element} modelCaption
-// @param {module:engine/view/element~Element} viewImage
-// @param {module:engine/conversion/mapper~Mapper} mapper
-function insertViewCaptionAndBind( viewCaption, modelCaption, viewImage, mapper ) {
-	const viewPosition = ViewPosition.createAt( viewImage, 'end' );
-
-	viewWriter.insert( viewPosition, viewCaption );
-	mapper.bindElements( modelCaption, viewCaption );
-}

+ 36 - 0
packages/ckeditor5-image/src/imagecaption/utils.js

@@ -9,6 +9,8 @@
 
 import ViewEditableElement from '@ckeditor/ckeditor5-engine/src/view/editableelement';
 import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
+import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position';
+import viewWriter from '@ckeditor/ckeditor5-engine/src/view/writer';
 
 const captionSymbol = Symbol( 'imageCaption' );
 
@@ -71,3 +73,37 @@ export function getCaptionFromImage( imageModelElement ) {
 export function isInsideCaption( node ) {
 	return !!( node.parent && node.parent.name == 'caption' && node.parent.parent && node.parent.parent.name == 'image' );
 }
+
+/**
+ * {@link module:engine/view/matcher~Matcher} pattern. Checks if given element is `figcaption` element and is placed
+ * inside image `figure` element.
+ *
+ * @param {module:engine/view/element~Element} element
+ * @returns {Object|null} Returns object accepted by {@link module:engine/view/matcher~Matcher} or `null` if element
+ * cannot be matched.
+ */
+export function matchImageCaption( element ) {
+	const parent = element.parent;
+
+	// Convert only captions for images.
+	if ( element.name == 'figcaption' && parent && parent.name == 'figure' && parent.hasClass( 'image' ) ) {
+		return { name: true };
+	}
+
+	return null;
+}
+
+/**
+ * Inserts `viewCaption` at the end of `viewImage` and binds it to `modelCaption`.
+ *
+ * @param {module:engine/view/containerelement~ContainerElement} viewCaption
+ * @param {module:engine/model/element~Element} modelCaption
+ * @param {module:engine/view/containerelement~ContainerElement} viewImage
+ * @param {module:engine/conversion/mapper~Mapper} mapper
+ */
+export function insertViewCaptionAndBind( viewCaption, modelCaption, viewImage, mapper ) {
+	const viewPosition = ViewPosition.createAt( viewImage, 'end' );
+
+	viewWriter.insert( viewPosition, viewCaption );
+	mapper.bindElements( modelCaption, viewCaption );
+}

+ 78 - 1
packages/ckeditor5-image/tests/imagecaption/utils.js

@@ -5,8 +5,18 @@
 
 import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document';
 import ViewEditableElement from '@ckeditor/ckeditor5-engine/src/view/editableelement';
-import { captionElementCreator, isCaption, getCaptionFromImage, isInsideCaption } from '../../src/imagecaption/utils';
+import ViewElement from '@ckeditor/ckeditor5-engine/src/view/element';
+import ViewContainerElement from '@ckeditor/ckeditor5-engine/src/view/containerelement';
+import {
+	captionElementCreator,
+	isCaption,
+	getCaptionFromImage,
+	isInsideCaption,
+	matchImageCaption,
+	insertViewCaptionAndBind
+} from '../../src/imagecaption/utils';
 import ModelElement from '@ckeditor/ckeditor5-engine/src/model/element';
+import Mapper from '@ckeditor/ckeditor5-engine/src/conversion/mapper';
 
 describe( 'image captioning utils', () => {
 	let element, document;
@@ -103,4 +113,71 @@ describe( 'image captioning utils', () => {
 			expect( isInsideCaption( el ) ).to.be.true;
 		} );
 	} );
+
+	describe( 'matchImageCaption', () => {
+		it( 'should return null for element that is not a figcaption', () => {
+			const element = new ViewElement( 'div' );
+
+			expect( matchImageCaption( element ) ).to.be.null;
+		} );
+
+		it( 'should return null if figcaption has no parent', () => {
+			const element = new ViewElement( 'figcaption' );
+
+			expect( matchImageCaption( element ) ).to.be.null;
+		} );
+
+		it( 'should return null if figcaption\'s parent is not a figure', () => {
+			const element = new ViewElement( 'figcaption' );
+			new ViewElement( 'div', null, element );
+
+			expect( matchImageCaption( element ) ).to.be.null;
+		} );
+
+		it( 'should return null if parent has no image class', () => {
+			const element = new ViewElement( 'figcaption' );
+			new ViewElement( 'figure', null, element );
+
+			expect( matchImageCaption( element ) ).to.be.null;
+		} );
+
+		it( 'should return object if element is a valid caption', () => {
+			const element = new ViewElement( 'figcaption' );
+			new ViewElement( 'figure', { class: 'image' }, element );
+
+			expect( matchImageCaption( element ) ).to.deep.equal( { name: true } );
+		} );
+	} );
+
+	describe( 'insertViewCaptionAndBind', () => {
+		let viewCaption, modelCaption, viewImage, mapper;
+
+		beforeEach( () => {
+			viewCaption = new ViewContainerElement( 'figcaption' );
+			modelCaption = new ModelElement( 'caption' );
+			viewImage = new ViewContainerElement( 'figure', { class: 'image' } );
+			mapper = new Mapper();
+		} );
+
+		it( 'should insert provided caption to provided image', () => {
+			insertViewCaptionAndBind( viewCaption, modelCaption, viewImage, mapper );
+
+			expect( viewImage.getChild( 0 ) ).to.equal( viewCaption );
+		} );
+
+		it( 'should insert provided caption at the end of provided image', () => {
+			const dummyElement = new ViewElement( 'dummy' );
+			viewImage.appendChildren( dummyElement );
+
+			insertViewCaptionAndBind( viewCaption, modelCaption, viewImage, mapper );
+
+			expect( viewImage.getChild( 1 ) ).to.equal( viewCaption );
+		} );
+
+		it( 'should bind view caption to model caption using provided mapper', () => {
+			insertViewCaptionAndBind( viewCaption, modelCaption, viewImage, mapper );
+
+			expect( mapper.toModelElement( viewCaption ) ).to.equal( modelCaption );
+		} );
+	} );
 } );