8
0
Просмотр исходного кода

Introduced the InsertParagraphCommand.

Aleksander Nowodzinski 5 лет назад
Родитель
Сommit
6684ecd49d

+ 61 - 0
packages/ckeditor5-paragraph/src/insertparagraphcommand.js

@@ -0,0 +1,61 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module paragraph/insertparagraphcommand
+ */
+
+import Command from '@ckeditor/ckeditor5-core/src/command';
+
+/**
+ * The insert paragraph command. It insert a new paragraph next to the provided model element.
+ *
+ *		// Insert a new paragraph before the first element in the document root.
+ *		editor.execute( 'insertParagraph', {
+ *			element: editor.model.document.getRoot().getChild( 0 ),
+ *			position: 'before'
+ *		} );
+ *
+ * **Note**: This command moves the selection to the inserted paragraph.
+ *
+ * @extends module:core/command~Command
+ */
+export default class InsertParagraphCommand extends Command {
+	/**
+	 * Executes the command.
+	 *
+	 * @protected
+	 * @param {Object} options Options for the executed command.
+	 * @param {module:engine/model/element~Element} options.element The model element next to which
+	 * the new paragraph will be inserted.
+	 * @param {'before'|'after'} options.position The position relative to the passed `element` where
+	 * the new paragraph will be inserted.
+	 * @fires execute
+	 */
+	execute( options = {} ) {
+		const editor = this.editor;
+		const model = this.editor.model;
+		let modelPosition;
+
+		if ( options.position === 'before' ) {
+			modelPosition = model.createPositionBefore( options.element );
+		} else {
+			modelPosition = model.createPositionAfter( options.element );
+		}
+
+		if ( !model.schema.checkChild( modelPosition, 'paragraph' ) ) {
+			return;
+		}
+
+		editor.model.change( writer => {
+			const paragraph = writer.createElement( 'paragraph' );
+			const selection = writer.createSelection( paragraph, 'in' );
+
+			editor.model.insertContent( paragraph, modelPosition );
+
+			writer.setSelection( selection );
+		} );
+	}
+}

+ 9 - 0
packages/ckeditor5-paragraph/src/paragraph.js

@@ -8,6 +8,7 @@
  */
 
 import ParagraphCommand from './paragraphcommand';
+import InsertParagraphCommand from './insertparagraphcommand';
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 
@@ -16,6 +17,13 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  *
  * It introduces the `<paragraph>` element in the model which renders as a `<p>` element in the DOM and data.
  *
+ * It also brings two editors commands:
+ *
+ * * The {@link module:paragraph/paragraphcommand~ParagraphCommand `'paragraph'`} command that converts all
+ * blocks in the model selection into paragraphs.
+ * * The {@link module:paragraph/insertparagraphcommand~InsertParagraphCommand `'insertParagraph'`} command
+ * that inserts a new paragraph at a specified location in the model.
+ *
  * @extends module:core/plugin~Plugin
  */
 export default class Paragraph extends Plugin {
@@ -35,6 +43,7 @@ export default class Paragraph extends Plugin {
 		const data = editor.data;
 
 		editor.commands.add( 'paragraph', new ParagraphCommand( editor ) );
+		editor.commands.add( 'insertParagraph', new InsertParagraphCommand( editor ) );
 
 		// Schema.
 		model.schema.register( 'paragraph', { inheritAllFrom: '$block' } );

+ 119 - 0
packages/ckeditor5-paragraph/tests/insertparagraphcommand.js

@@ -0,0 +1,119 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
+import InsertParagraphCommand from '../src/insertparagraphcommand';
+
+import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+
+describe( 'InsertParagraphCommand', () => {
+	let editor, model, document, command, root, schema;
+
+	beforeEach( () => {
+		return ModelTestEditor.create().then( newEditor => {
+			editor = newEditor;
+			model = editor.model;
+			document = model.document;
+			schema = model.schema;
+			command = new InsertParagraphCommand( editor );
+			root = document.getRoot();
+
+			editor.commands.add( 'insertParagraph', command );
+			schema.register( 'paragraph', { inheritAllFrom: '$block' } );
+			schema.register( 'heading1', { inheritAllFrom: '$block', allowIn: 'headersOnly' } );
+			schema.register( 'headersOnly', { inheritAllFrom: '$block' } );
+		} );
+	} );
+
+	afterEach( () => {
+		command.destroy();
+	} );
+
+	describe( 'execute()', () => {
+		it( 'should insert a paragraph before the provided model element and anchor the selection inside of it', () => {
+			setData( model, '<heading1>foo[]</heading1>' );
+
+			command.execute( {
+				element: root.getChild( 0 ),
+				position: 'before'
+			} );
+
+			expect( getData( model ) ).to.equal( '<paragraph>[]</paragraph><heading1>foo</heading1>' );
+		} );
+
+		it( 'should insert a paragraph after the provided model element and anchor the selection inside of it', () => {
+			setData( model, '<heading1>foo[]</heading1>' );
+
+			command.execute( {
+				element: root.getChild( 0 ),
+				position: 'after'
+			} );
+
+			expect( getData( model ) ).to.equal( '<heading1>foo</heading1><paragraph>[]</paragraph>' );
+		} );
+
+		it( 'should do nothing if the paragraph is not allowed in the provided context', () => {
+			setData( model, '<headersOnly><heading1>foo[]</heading1></headersOnly>' );
+
+			command.execute( {
+				element: root.getChild( 0 ).getChild( 0 ),
+				position: 'before'
+			} );
+
+			command.execute( {
+				element: root.getChild( 0 ).getChild( 0 ),
+				position: 'after'
+			} );
+
+			expect( getData( model ) ).to.equal( '<headersOnly><heading1>foo[]</heading1></headersOnly>' );
+		} );
+
+		describe( 'interation with existing paragraphs in the content', () => {
+			it( 'should insert a paragraph before another paragraph', () => {
+				setData( model, '<paragraph>foo[]</paragraph>' );
+
+				command.execute( {
+					element: root.getChild( 0 ),
+					position: 'before'
+				} );
+
+				expect( getData( model ) ).to.equal( '<paragraph>[]</paragraph><paragraph>foo</paragraph>' );
+			} );
+
+			it( 'should insert a paragraph after another paragraph', () => {
+				setData( model, '<paragraph>foo[]</paragraph>' );
+
+				command.execute( {
+					element: root.getChild( 0 ),
+					position: 'after'
+				} );
+
+				expect( getData( model ) ).to.equal( '<paragraph>foo</paragraph><paragraph>[]</paragraph>' );
+			} );
+
+			it( 'should not merge with a paragraph that precedes the model element before which a new paragraph is inserted', () => {
+				setData( model, '<paragraph>bar</paragraph><heading1>foo[]</heading1>' );
+
+				command.execute( {
+					element: root.getChild( 1 ),
+					position: 'before'
+				} );
+
+				expect( getData( model ) ).to.equal( '<paragraph>bar</paragraph><paragraph>[]</paragraph><heading1>foo</heading1>' );
+			} );
+
+			it( 'should not merge with a paragraph that follows the model element before which a new paragraph is inserted', () => {
+				setData( model, '<heading1>foo[]</heading1><paragraph>bar</paragraph>' );
+
+				command.execute( {
+					element: root.getChild( 0 ),
+					position: 'after'
+				} );
+
+				expect( getData( model ) ).to.equal( '<heading1>foo</heading1><paragraph>[]</paragraph><paragraph>bar</paragraph>' );
+			} );
+		} );
+	} );
+} );

+ 7 - 2
packages/ckeditor5-paragraph/tests/paragraph.js

@@ -5,6 +5,7 @@
 
 import Paragraph from '../src/paragraph';
 import ParagraphCommand from '../src/paragraphcommand';
+import InsertParagraphCommand from '../src/insertparagraphcommand';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import {
 	getData as getModelData,
@@ -437,9 +438,13 @@ describe( 'Paragraph feature', () => {
 		} );
 	} );
 
-	describe( 'command', () => {
-		it( 'should be set in the editor', () => {
+	describe( 'commands', () => {
+		it( '"paragraph" command should be registered in the editor', () => {
 			expect( editor.commands.get( 'paragraph' ) ).to.be.instanceof( ParagraphCommand );
 		} );
+
+		it( '"insertParagraph" command should be registered in the editor', () => {
+			expect( editor.commands.get( 'insertParagraph' ) ).to.be.instanceof( InsertParagraphCommand );
+		} );
 	} );
 } );