瀏覽代碼

Changed: Use EnterCommand's afterExecute event to alter it's behavior.

Szymon Cofalik 9 年之前
父節點
當前提交
0bd74a0801

+ 5 - 1
packages/ckeditor5-heading/src/headings.js

@@ -3,11 +3,14 @@
  * For licensing, see LICENSE.md.
  */
 
-import Feature from '../core/feature.js';
 import HeadingsEngine from './headingsengine.js';
+
+import Feature from '../core/feature.js';
+
 import Model from '../ui/model.js';
 import ListDropdownController from '../ui/dropdown/list/listdropdown.js';
 import ListDropdownView from '../ui/dropdown/list/listdropdownview.js';
+
 import Collection from '../utils/collection.js';
 
 /**
@@ -65,6 +68,7 @@ export default class Headings extends Feature {
 			editor.editing.view.focus();
 		} );
 
+		// Register UI component.
 		editor.ui.featureComponents.add( 'headings', ListDropdownController, ListDropdownView, dropdownModel );
 	}
 }

+ 5 - 2
packages/ckeditor5-heading/src/headingscommand.js

@@ -64,11 +64,14 @@ export default class HeadingsCommand extends Command {
 	}
 
 	/**
-	 * Executes the command if it is enabled.
+	 * Executes command.
 	 *
+	 * @protected
 	 * @param {String} [formatId] The identifier of the heading format that should be applied. It should be one of the
 	 * {@link headings.HeadingsFormat heading formats} provided to the command constructor. If this parameter is not provided,
 	 * the value from {@link headings.HeadingsCommand#defaultFormat defaultFormat} will be used.
+	 * @returns {Object} data Data object, available in {@link core.Command#event:afterExecute}
+	 * @returns {engine.model.Batch} data.batch Batch created and used by the command.
 	 */
 	_doExecute( formatId = this.defaultFormat.id ) {
 		// TODO: What should happen if format is not found?
@@ -134,7 +137,7 @@ export default class HeadingsCommand extends Command {
 	 * @returns {headings.HeadingsFormat}
 	 */
 	_getFormatById( id ) {
-		return this.formats.find( item => item.id === id );
+		return this.formats.find( item => item.id === id ) || this.defaultFormat;
 	}
 }
 

+ 15 - 0
packages/ckeditor5-heading/src/headingsengine.js

@@ -60,5 +60,20 @@ export default class HeadingsEngine extends Feature {
 		// Register command.
 		const command = new HeadingsCommand( editor, formats );
 		editor.commands.set( 'headings', command );
+
+		// If Enter Command is added to the editor, alter it's behavior.
+		const enterCommand = editor.commands.get( 'enter' );
+
+		if ( enterCommand ) {
+			this.listenTo( enterCommand, 'afterExecute', ( evt, data ) => {
+				const positionParent = editor.document.selection.getFirstPosition().parent;
+				const batch = data.batch;
+				const isHeading = formats.some( ( format ) => format.id == positionParent.name );
+
+				if ( isHeading && positionParent.name != command.defaultFormat.id && positionParent.childCount === 0 ) {
+					batch.rename( command.defaultFormat.id, positionParent );
+				}
+			} );
+		}
 	}
 }

+ 11 - 2
packages/ckeditor5-heading/tests/headingscommand.js

@@ -16,7 +16,7 @@ const formats = [
 ];
 
 describe( 'HeadingsCommand', () => {
-	let editor, document, command, root;
+	let editor, document, command, root, schema;
 
 	beforeEach( () => {
 		return ModelTestEditor.create()
@@ -24,7 +24,7 @@ describe( 'HeadingsCommand', () => {
 				editor = newEditor;
 				document = editor.document;
 				command = new HeadingsCommand( editor, formats );
-				const schema = document.schema;
+				schema = document.schema;
 
 				for ( let format of formats ) {
 					schema.registerItem( format.id, '$block' );
@@ -53,6 +53,15 @@ describe( 'HeadingsCommand', () => {
 				expect( command.value ).to.equal( format );
 			} );
 		}
+
+		it( 'should be equal to defaultFormat if format has not been found', () => {
+			schema.registerItem( 'div', '$block' );
+			setData( document, '<div>xyz</div>' );
+			const element = root.getChild( 0 );
+			document.selection.addRange( Range.createFromParentsAndOffsets( element, 1, element, 1 ) );
+
+			expect( command.value ).to.equal( command.defaultFormat );
+		} );
 	} );
 
 	describe( '_doExecute', () => {

+ 21 - 1
packages/ckeditor5-heading/tests/headingsengine.js

@@ -7,6 +7,7 @@ import HeadingsEngine from '/ckeditor5/headings/headingsengine.js';
 import Paragraph from '/ckeditor5/paragraph/paragraph.js';
 import VirtualTestEditor from '/tests/core/_utils/virtualtesteditor.js';
 import HeadingsCommand from '/ckeditor5/headings/headingscommand.js';
+import Enter from '/ckeditor5/enter/enter.js';
 import { getData } from '/tests/engine/_utils/model.js';
 
 describe( 'HeadingsEngine', () => {
@@ -14,7 +15,7 @@ describe( 'HeadingsEngine', () => {
 
 	beforeEach( () => {
 		return VirtualTestEditor.create( {
-			features: [ HeadingsEngine ]
+			features: [ Enter, HeadingsEngine ]
 		} )
 		.then( newEditor => {
 			editor = newEditor;
@@ -72,4 +73,23 @@ describe( 'HeadingsEngine', () => {
 		expect( getData( document, { withoutSelection: true } ) ).to.equal( '<heading3>foobar</heading3>' );
 		expect( editor.getData() ).to.equal( '<h4>foobar</h4>' );
 	} );
+
+	it( 'should make enter command insert a defaultFormat block if selection ended at the end of heading block', () => {
+		editor.setData( '<h2>foobar</h2>' );
+		document.selection.collapse( document.getRoot().getChild( 0 ), 'end' );
+
+		editor.execute( 'enter' );
+
+		expect( getData( document ) ).to.equal( '<heading1>foobar</heading1><paragraph>[]</paragraph>' );
+	} );
+
+	it( 'should not alter enter command if selection not ended at the end of heading block', () => {
+		// This test is to fill code coverage.
+		editor.setData( '<h2>foobar</h2>' );
+		document.selection.collapse( document.getRoot().getChild( 0 ), 3 );
+
+		editor.execute( 'enter' );
+
+		expect( getData( document ) ).to.equal( '<heading1>foo</heading1><heading1>[]bar</heading1>' );
+	} );
 } );