8
0
Quellcode durchsuchen

Trim markers to the body range when using Title#getBody().

Oskar Wróbel vor 6 Jahren
Ursprung
Commit
735d0bdd23
2 geänderte Dateien mit 116 neuen und 6 gelöschten Zeilen
  1. 29 6
      packages/ckeditor5-heading/src/title.js
  2. 87 0
      packages/ckeditor5-heading/tests/title.js

+ 29 - 6
packages/ckeditor5-heading/src/title.js

@@ -10,14 +10,16 @@
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 
-import ViewWriter from '@ckeditor/ckeditor5-engine/src/view/downcastwriter';
+import ViewDocumentFragment from '@ckeditor/ckeditor5-engine/src/view/documentfragment';
+import ViewDowncastWriter from '@ckeditor/ckeditor5-engine/src/view/downcastwriter';
+import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document';
+import first from '@ckeditor/ckeditor5-utils/src/first';
 import {
 	needsPlaceholder,
 	showPlaceholder,
 	hidePlaceholder,
 	enablePlaceholder
 } from '@ckeditor/ckeditor5-engine/src/view/placeholder';
-import first from '@ckeditor/ckeditor5-utils/src/first';
 
 // A list of element names which should be treated by the Title plugin as title-like.
 // This means that element of a type from this list will be changed to a title element
@@ -158,13 +160,34 @@ export default class Title extends Plugin {
 	 * @returns {String} Body of the document.
 	 */
 	getBody() {
+		const data = this.editor.data;
+		const model = this.editor.model;
 		const root = this.editor.model.document.getRoot();
-		const viewWriter = new ViewWriter();
+		const viewWriter = new ViewDowncastWriter( new ViewDocument() );
+
+		const rootRange = model.createRangeIn( root );
+		const viewDocumentFragment = new ViewDocumentFragment();
+
+		// Convert the entire root to view.
+		data.mapper.clearBindings();
+		data.mapper.bindElements( root, viewDocumentFragment );
+		data.downcastDispatcher.convertInsert( rootRange, viewWriter );
 
-		// model -> view
-		const viewDocumentFragment = this.editor.data.toView( root );
+		// Convert all markers that intersects with body.
+		// Avoid markers that starts before body, move it to the first selection position.
+		const bodyStartPosition = model.createPositionAfter( root.getChild( 0 ) );
+		const bodySelectionPosition = model.schema.getNearestSelectionRange( bodyStartPosition, 'forward' ).start;
+		const bodyRange = model.createRange( bodySelectionPosition, model.createPositionAt( root, 'end' ) );
+
+		for ( const marker of model.markers ) {
+			const intersection = bodyRange.getIntersection( marker.getRange() );
+
+			if ( intersection ) {
+				data.downcastDispatcher.convertMarkerAdd( marker.name, intersection, viewWriter );
+			}
+		}
 
-		// Remove title.
+		// Remove title element from view.
 		viewWriter.remove( viewWriter.createRangeOn( viewDocumentFragment.getChild( 0 ) ) );
 
 		// view -> data

+ 87 - 0
packages/ckeditor5-heading/tests/title.js

@@ -419,6 +419,48 @@ describe( 'Title', () => {
 
 			expect( editor.plugins.get( 'Title' ).getTitle() ).to.equal( '' );
 		} );
+
+		it( 'should return marker - starts and ends inside a title', () => {
+			editor.conversion.for( 'downcast' ).markerToElement( { model: 'comment', view: 'comment' } );
+
+			setData( model, '<title><title-content>Foo Bar</title-content></title>' );
+
+			const title = model.document.getRoot().getChild( 0 ).getChild( 0 );
+
+			model.change( writer => {
+				writer.addMarker( 'comment', {
+					range: model.createRange( model.createPositionAt( title, 1 ), model.createPositionAt( title, 5 ) ),
+					usingOperation: true
+				} );
+			} );
+
+			expect( editor.plugins.get( 'Title' ).getTitle() ).to.equal(
+				'F<comment></comment>oo B<comment></comment>ar'
+			);
+		} );
+
+		it( 'should return marker - starts inside a title ends inside a body', () => {
+			editor.conversion.for( 'downcast' ).markerToElement( { model: 'comment', view: 'comment' } );
+
+			setData( model,
+				'<title><title-content>Foo Bar</title-content></title>' +
+				'<paragraph>Biz</paragraph>'
+			);
+
+			const title = model.document.getRoot().getChild( 0 ).getChild( 0 );
+			const body = model.document.getRoot().getChild( 1 );
+
+			model.change( writer => {
+				writer.addMarker( 'comment', {
+					range: model.createRange( model.createPositionAt( title, 1 ), model.createPositionAt( body, 3 ) ),
+					usingOperation: true
+				} );
+			} );
+
+			expect( editor.plugins.get( 'Title' ).getTitle() ).to.equal(
+				'F<comment></comment>oo Bar<comment></comment>'
+			);
+		} );
 	} );
 
 	describe( 'setBody()', () => {
@@ -482,6 +524,51 @@ describe( 'Title', () => {
 
 			expect( editor.plugins.get( 'Title' ).getBody() ).to.equal( '<p>&nbsp;</p>' );
 		} );
+
+		it( 'should return marker - starts and ends inside a body', () => {
+			editor.conversion.for( 'downcast' ).markerToElement( { model: 'comment', view: 'comment' } );
+
+			setData( model,
+				'<title><title-content></title-content></title>' +
+				'<paragraph>Foo Bar</paragraph>'
+			);
+
+			const body = model.document.getRoot().getChild( 1 );
+
+			model.change( writer => {
+				writer.addMarker( 'comment', {
+					range: model.createRange( model.createPositionAt( body, 1 ), model.createPositionAt( body, 5 ) ),
+					usingOperation: true
+				} );
+			} );
+
+			expect( editor.plugins.get( 'Title' ).getBody() ).to.equal(
+				'<p>F<comment></comment>oo B<comment></comment>ar</p>'
+			);
+		} );
+
+		it( 'should return marker - starts inside a title ends inside a body', () => {
+			editor.conversion.for( 'downcast' ).markerToElement( { model: 'comment', view: 'comment' } );
+
+			setData( model,
+				'<title><title-content>Foo</title-content></title>' +
+				'<paragraph>Bar</paragraph>'
+			);
+
+			const title = model.document.getRoot().getChild( 0 ).getChild( 0 );
+			const body = model.document.getRoot().getChild( 1 );
+
+			model.change( writer => {
+				writer.addMarker( 'comment', {
+					range: model.createRange( model.createPositionAt( title, 1 ), model.createPositionAt( body, 2 ) ),
+					usingOperation: true
+				} );
+			} );
+
+			expect( editor.plugins.get( 'Title' ).getBody() ).to.equal(
+				'<p><comment></comment>Ba<comment></comment>r</p>'
+			);
+		} );
 	} );
 
 	describe( 'placeholders', () => {