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

Remove insertElement(), insertUIElement() from public API.

Maciej Gołaszewski преди 7 години
родител
ревизия
d7b4dd3556

+ 2 - 4
packages/ckeditor5-engine/src/conversion/downcasthelpers.js

@@ -421,8 +421,6 @@ export function createViewElementFromHighlightDescriptor( descriptor ) {
 	return viewElement;
 }
 
-// only: insertText, insertElement, wrap, insertUIElement
-
 /**
  * Function factory that creates a converter which converts set/change/remove attribute changes from the model to the view.
  * It can also be used to convert selection attributes. In that case, an empty attribute element will be created and the
@@ -517,7 +515,7 @@ export function wrap( elementCreator ) {
  * @param {Function} elementCreator Function returning a view element, which will be inserted.
  * @returns {Function} Insert element event converter.
  */
-export function insertElement( elementCreator ) {
+function insertElement( elementCreator ) {
 	return ( evt, data, conversionApi ) => {
 		const viewElement = elementCreator( data.item, conversionApi.writer );
 
@@ -550,7 +548,7 @@ export function insertElement( elementCreator ) {
  * that will be inserted.
  * @returns {Function} Insert element event converter.
  */
-export function insertUIElement( elementCreator ) {
+function insertUIElement( elementCreator ) {
 	return ( evt, data, conversionApi ) => {
 		// Create two view elements. One will be inserted at the beginning of marker, one at the end.
 		// If marker is collapsed, only "opening" element will be inserted.

+ 63 - 10
packages/ckeditor5-engine/src/dev-utils/model.js

@@ -32,7 +32,7 @@ import {
 	convertRangeSelection,
 	convertCollapsedSelection,
 } from '../conversion/downcast-selection-converters';
-import { insertText, insertElement, wrap, insertUIElement } from '../conversion/downcasthelpers';
+import { insertText, wrap } from '../conversion/downcasthelpers';
 
 import { isPlainObject } from 'lodash-es';
 import toMap from '@ckeditor/ckeditor5-utils/src/tomap';
@@ -225,19 +225,72 @@ export function stringify( node, selectionOrPositionOrRange = null, markers = nu
 			converter( evt, data, conversionApi );
 		}
 	} );
-	downcastDispatcher.on( 'insert', insertElement( modelItem => {
-		// Stringify object types values for properly display as an output string.
-		const attributes = convertAttributes( modelItem.getAttributes(), stringifyAttributeValue );
+	downcastDispatcher.on( 'insert', ( evt, data, conversionApi ) => {
+		const attributes = convertAttributes( data.item.getAttributes(), stringifyAttributeValue );
+		const viewElement = new ViewContainerElement( data.item.name, attributes );
+
+		if ( !conversionApi.consumable.consume( data.item, 'insert' ) ) {
+			return;
+		}
+
+		const viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
+
+		conversionApi.mapper.bindElements( data.item, viewElement );
+		conversionApi.writer.insert( viewPosition, viewElement );
+	} );
 
-		return new ViewContainerElement( modelItem.name, attributes );
-	} ) );
 	downcastDispatcher.on( 'selection', convertRangeSelection() );
 	downcastDispatcher.on( 'selection', convertCollapsedSelection() );
-	downcastDispatcher.on( 'addMarker', insertUIElement( ( data, writer ) => {
-		const name = data.markerName + ':' + ( data.isOpening ? 'start' : 'end' );
+	downcastDispatcher.on( 'addMarker', ( evt, data, conversionApi ) => {
+		const elementCreator = ( data, writer ) => {
+			const name = data.markerName + ':' + ( data.isOpening ? 'start' : 'end' );
+
+			return writer.createUIElement( name );
+		};
+
+		// Create two view elements. One will be inserted at the beginning of marker, one at the end.
+		// If marker is collapsed, only "opening" element will be inserted.
+		data.isOpening = true;
+		const viewStartElement = elementCreator( data, conversionApi.writer );
+
+		data.isOpening = false;
+		const viewEndElement = elementCreator( data, conversionApi.writer );
+
+		if ( !viewStartElement || !viewEndElement ) {
+			return;
+		}
+
+		const markerRange = data.markerRange;
 
-		return writer.createUIElement( name );
-	} ) );
+		// Marker that is collapsed has consumable build differently that non-collapsed one.
+		// For more information see `addMarker` event description.
+		// If marker's range is collapsed - check if it can be consumed.
+		if ( markerRange.isCollapsed && !conversionApi.consumable.consume( markerRange, evt.name ) ) {
+			return;
+		}
+
+		// If marker's range is not collapsed - consume all items inside.
+		for ( const value of markerRange ) {
+			if ( !conversionApi.consumable.consume( value.item, evt.name ) ) {
+				return;
+			}
+		}
+
+		const mapper = conversionApi.mapper;
+		const viewWriter = conversionApi.writer;
+
+		// Add "opening" element.
+		viewWriter.insert( mapper.toViewPosition( markerRange.start ), viewStartElement );
+		conversionApi.mapper.bindElementToMarker( viewStartElement, data.markerName );
+
+		// Add "closing" element only if range is not collapsed.
+		if ( !markerRange.isCollapsed ) {
+			viewWriter.insert( mapper.toViewPosition( markerRange.end ), viewEndElement );
+			conversionApi.mapper.bindElementToMarker( viewEndElement, data.markerName );
+		}
+
+		evt.stop();
+	} );
 
 	// Convert model to view.
 	const writer = view._writer;

+ 6 - 10
packages/ckeditor5-engine/tests/conversion/downcast-selection-converters.js

@@ -16,11 +16,7 @@ import {
 	clearAttributes,
 } from '../../src/conversion/downcast-selection-converters';
 
-import DowncastHelpers, {
-	insertElement,
-	insertText,
-	wrap
-} from '../../src/conversion/downcasthelpers';
+import DowncastHelpers, { insertText, wrap } from '../../src/conversion/downcasthelpers';
 
 import createViewRoot from '../view/_utils/createroot';
 import { stringify as stringifyView } from '../../src/dev-utils/view';
@@ -498,12 +494,12 @@ describe( 'downcast-selection-converters', () => {
 			model.schema.extend( 'td', { allowIn: 'tr' } );
 			model.schema.extend( '$text', { allowIn: 'td' } );
 
+			const downcastHelpers = new DowncastHelpers( dispatcher );
+
 			// "Universal" converter to convert table structure.
-			const containerCreator = ( modelElement, viewWriter ) => viewWriter.createContainerElement( modelElement.name );
-			const tableConverter = insertElement( containerCreator );
-			dispatcher.on( 'insert:table', tableConverter );
-			dispatcher.on( 'insert:tr', tableConverter );
-			dispatcher.on( 'insert:td', tableConverter );
+			downcastHelpers.elementToElement( { model: 'table', view: 'table' } );
+			downcastHelpers.elementToElement( { model: 'tr', view: 'tr' } );
+			downcastHelpers.elementToElement( { model: 'td', view: 'td' } );
 
 			// Special converter for table cells.
 			dispatcher.on( 'selection', ( evt, data, conversionApi ) => {

+ 17 - 37
packages/ckeditor5-engine/tests/conversion/downcasthelpers.js

@@ -20,7 +20,7 @@ import ViewText from '../../src/view/text';
 import log from '@ckeditor/ckeditor5-utils/src/log';
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 
-import DowncastHelpers, { createViewElementFromHighlightDescriptor, insertElement, wrap } from '../../src/conversion/downcasthelpers';
+import DowncastHelpers, { createViewElementFromHighlightDescriptor, wrap } from '../../src/conversion/downcasthelpers';
 
 import { stringify } from '../../src/dev-utils/view';
 
@@ -252,6 +252,18 @@ describe( 'DowncastHelpers', () => {
 
 			expectResult( '<span style="color:#FF0000">foo</span><img class="smiley" src="smile.jpg"></img>' );
 		} );
+
+		it( 'should not convert if creator returned null', () => {
+			downcastHelpers.elementToElement( { model: 'div', view: () => null } );
+
+			const modelElement = new ModelElement( 'div' );
+
+			model.change( writer => {
+				writer.insert( modelElement, modelRootStart );
+			} );
+
+			expect( viewToString( viewRoot ) ).to.equal( '<div></div>' );
+		} );
 	} );
 
 	describe( 'attributeToAttribute()', () => {
@@ -1343,15 +1355,8 @@ describe( 'downcast-converters', () => {
 		controller.view.document.getRoot()._name = 'div';
 
 		dispatcher = controller.downcastDispatcher;
-
-		dispatcher.on(
-			'insert:paragraph',
-			insertElement(
-				( modelItem, viewWriter ) => viewWriter.createContainerElement( 'p' )
-			)
-		);
-
-		// dispatcher.on( 'attribute:class', changeAttribute() );
+		const downcastHelpers = new DowncastHelpers( dispatcher );
+		downcastHelpers.elementToElement( { model: 'paragraph', view: 'p' } );
 
 		modelRootStart = model.createPositionAt( modelRoot, 0 );
 	} );
@@ -1419,30 +1424,6 @@ describe( 'downcast-converters', () => {
 		} );
 	} );
 
-	describe( 'insertElement', () => {
-		it( 'should convert element insertion in model', () => {
-			const modelElement = new ModelElement( 'paragraph', null, new ModelText( 'foobar' ) );
-
-			model.change( writer => {
-				writer.insert( modelElement, modelRootStart );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div><p>foobar</p></div>' );
-		} );
-
-		it( 'should not convert if creator returned null', () => {
-			dispatcher.on( 'insert:div', insertElement( () => null ) );
-
-			const modelElement = new ModelElement( 'div' );
-
-			model.change( writer => {
-				writer.insert( modelElement, modelRootStart );
-			} );
-
-			expect( viewToString( viewRoot ) ).to.equal( '<div></div>' );
-		} );
-	} );
-
 	describe( 'wrap', () => {
 		it( 'should convert insert/change/remove of attribute in model into wrapping element in a view', () => {
 			const modelElement = new ModelElement( 'paragraph', null, new ModelText( 'foobar', { bold: true } ) );
@@ -1693,9 +1674,8 @@ describe( 'downcast-converters', () => {
 			const modelP = new ModelElement( 'paragraph', null, new ModelText( 'foo' ) );
 			const modelWidget = new ModelElement( 'widget', null, modelP );
 
-			dispatcher.on( 'insert:widget', insertElement(
-				( modelElement, viewWriter ) => viewWriter.createContainerElement( 'widget' ) )
-			);
+			const downcastHelpers = new DowncastHelpers( dispatcher );
+			downcastHelpers.elementToElement( { model: 'widget', view: 'widget' } );
 
 			model.change( writer => {
 				writer.insert( modelWidget, modelRootStart );