Jelajahi Sumber

Added: Enabled markers conversion in `engine.DataController`.

Szymon Cofalik 8 tahun lalu
induk
melakukan
5fec3553e7

+ 39 - 2
packages/ckeditor5-engine/src/controller/datacontroller.js

@@ -135,10 +135,10 @@ export default class DataController {
 	 * @returns {String} Output data.
 	 * @returns {String} Output data.
 	 */
 	 */
 	stringify( modelElementOrFragment ) {
 	stringify( modelElementOrFragment ) {
-		// model -> view
+		// Model -> view.
 		const viewDocumentFragment = this.toView( modelElementOrFragment );
 		const viewDocumentFragment = this.toView( modelElementOrFragment );
 
 
-		// view -> data
+		// View -> data.
 		return this.processor.toData( viewDocumentFragment );
 		return this.processor.toData( viewDocumentFragment );
 	}
 	}
 
 
@@ -153,6 +153,7 @@ export default class DataController {
 	 * @returns {module:engine/view/documentfragment~DocumentFragment} Output view DocumentFragment.
 	 * @returns {module:engine/view/documentfragment~DocumentFragment} Output view DocumentFragment.
 	 */
 	 */
 	toView( modelElementOrFragment ) {
 	toView( modelElementOrFragment ) {
+		// First, convert elements.
 		const modelRange = ModelRange.createIn( modelElementOrFragment );
 		const modelRange = ModelRange.createIn( modelElementOrFragment );
 
 
 		const viewDocumentFragment = new ViewDocumentFragment();
 		const viewDocumentFragment = new ViewDocumentFragment();
@@ -160,6 +161,17 @@ export default class DataController {
 
 
 		this.modelToView.convertInsert( modelRange );
 		this.modelToView.convertInsert( modelRange );
 
 
+		if ( !modelElementOrFragment.is( 'documentFragment' ) ) {
+			// Then, if document element is converted, convert markers.
+			// Get only those markers that contain or are contained by the element.
+			const markers = _getMarkersRelativeToElement( modelElementOrFragment );
+
+			for ( const [ name, range ] of markers ) {
+				this.modelToView.convertMarkerAdd( name, range );
+			}
+		}
+
+		// Clear bindings so the next call to this method gives correct results.
 		this.mapper.clearBindings();
 		this.mapper.clearBindings();
 
 
 		return viewDocumentFragment;
 		return viewDocumentFragment;
@@ -234,3 +246,28 @@ export default class DataController {
 }
 }
 
 
 mix( DataController, ObservableMixin );
 mix( DataController, ObservableMixin );
+
+// Helper function for converting part of a model to view.
+//
+// Takes a document element (element that is added to a model document) and checks which markers are inside it
+// and which markers are containing it. If the marker is intersecting with element, the intersection is returned.
+function _getMarkersRelativeToElement( element ) {
+	const result = [];
+	const doc = element.root.document;
+
+	if ( !doc ) {
+		return [];
+	}
+
+	const elementRange = ModelRange.createIn( element );
+
+	for ( const marker of doc.model.markers ) {
+		const intersection = elementRange.getIntersection( marker.getRange() );
+
+		if ( intersection ) {
+			result.push( [ marker.name, intersection ] );
+		}
+	}
+
+	return result;
+}

+ 41 - 1
packages/ckeditor5-engine/tests/controller/datacontroller.js

@@ -4,6 +4,7 @@
  */
  */
 
 
 import Model from '../../src/model/model';
 import Model from '../../src/model/model';
+import Range from '../../src/model/range';
 import DataController from '../../src/controller/datacontroller';
 import DataController from '../../src/controller/datacontroller';
 import HtmlDataProcessor from '../../src/dataprocessor/htmldataprocessor';
 import HtmlDataProcessor from '../../src/dataprocessor/htmldataprocessor';
 
 
@@ -15,7 +16,7 @@ import ModelDocumentFragment from '../../src/model/documentfragment';
 import ViewDocumentFragment from '../../src/view/documentfragment';
 import ViewDocumentFragment from '../../src/view/documentfragment';
 
 
 import { getData, setData, stringify, parse as parseModel } from '../../src/dev-utils/model';
 import { getData, setData, stringify, parse as parseModel } from '../../src/dev-utils/model';
-import { parse as parseView } from '../../src/dev-utils/view';
+import { parse as parseView, stringify as stringifyView } from '../../src/dev-utils/view';
 
 
 import count from '@ckeditor/ckeditor5-utils/src/count';
 import count from '@ckeditor/ckeditor5-utils/src/count';
 
 
@@ -312,6 +313,45 @@ describe( 'DataController', () => {
 			expect( viewElement.getChild( 0 ).data ).to.equal( 'foo' );
 			expect( viewElement.getChild( 0 ).data ).to.equal( 'foo' );
 		} );
 		} );
 
 
+		it( 'should correctly convert document markers #1', () => {
+			const modelElement = parseModel( '<div><paragraph>foobar</paragraph></div>', schema );
+			const modelRoot = model.document.getRoot();
+
+			buildModelConverter().for( data.modelToView ).fromMarker( 'marker:a' ).toHighlight( { class: 'a' } );
+
+			model.change( writer => {
+				writer.insert( modelElement, modelRoot, 0 );
+				writer.setMarker( 'marker:a', Range.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 ) );
+			} );
+
+			const viewDocumentFragment = data.toView( modelElement );
+			const viewElement = viewDocumentFragment.getChild( 0 );
+
+			expect( stringifyView( viewElement ) ).to.equal( '<p><span class="a">foobar</span></p>' );
+		} );
+
+		it( 'should correctly convert document markers #2', () => {
+			const modelElement = parseModel( '<div><paragraph>foo</paragraph><paragraph>bar</paragraph></div>', schema );
+			const modelRoot = model.document.getRoot();
+
+			buildModelConverter().for( data.modelToView ).fromMarker( 'marker:a' ).toHighlight( { class: 'a' } );
+			buildModelConverter().for( data.modelToView ).fromMarker( 'marker:b' ).toHighlight( { class: 'b' } );
+
+			const modelP1 = modelElement.getChild( 0 );
+			const modelP2 = modelElement.getChild( 1 );
+
+			model.change( writer => {
+				writer.insert( modelElement, modelRoot, 0 );
+
+				writer.setMarker( 'marker:a', Range.createFromParentsAndOffsets( modelP1, 1, modelP1, 3 ) );
+				writer.setMarker( 'marker:b', Range.createFromParentsAndOffsets( modelP2, 0, modelP2, 2 ) );
+			} );
+
+			const viewDocumentFragment = data.toView( modelP1 );
+
+			expect( stringifyView( viewDocumentFragment ) ).to.equal( 'f<span class="a">oo</span>' );
+		} );
+
 		it( 'should convert a document fragment', () => {
 		it( 'should convert a document fragment', () => {
 			const modelDocumentFragment = parseModel( '<paragraph>foo</paragraph><paragraph>bar</paragraph>', schema );
 			const modelDocumentFragment = parseModel( '<paragraph>foo</paragraph><paragraph>bar</paragraph>', schema );
 			const viewDocumentFragment = data.toView( modelDocumentFragment );
 			const viewDocumentFragment = data.toView( modelDocumentFragment );