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

Merge pull request #63 from ckeditor/t/40

Feature: Add support for `copyOnEnter` attribute's parameter. Closes #40.
Maciej преди 6 години
родител
ревизия
89fd5f6e37

+ 3 - 0
packages/ckeditor5-enter/src/entercommand.js

@@ -8,6 +8,7 @@
  */
 
 import Command from '@ckeditor/ckeditor5-core/src/command';
+import { getCopyOnEnterAttributes } from './utils';
 
 /**
  * Enter command. It is used by the {@link module:enter/enter~Enter Enter feature} to handle the <kbd>Enter</kbd> key.
@@ -56,7 +57,9 @@ function enterBlock( model, writer, selection, schema ) {
 	}
 
 	if ( isSelectionEmpty ) {
+		const attributesToCopy = getCopyOnEnterAttributes( writer.model.schema, selection.getAttributes() );
 		splitBlock( writer, range.start );
+		writer.setSelectionAttribute( attributesToCopy );
 	} else {
 		const leaveUnmerged = !( range.start.isAtStart && range.end.isAtEnd );
 		const isContainedWithinOneElement = ( startElement == endElement );

+ 5 - 0
packages/ckeditor5-enter/src/shiftentercommand.js

@@ -8,6 +8,7 @@
  */
 
 import Command from '@ckeditor/ckeditor5-core/src/command';
+import { getCopyOnEnterAttributes } from './utils';
 
 /**
  * ShiftEnter command. It is used by the {@link module:enter/shiftenter~ShiftEnter ShiftEnter feature} to handle
@@ -81,7 +82,11 @@ function softBreakAction( model, writer, selection ) {
 	const isContainedWithinOneElement = ( startElement == endElement );
 
 	if ( isSelectionEmpty ) {
+		const attributesToCopy = getCopyOnEnterAttributes( model.schema, selection.getAttributes() );
 		insertBreak( writer, range.end );
+
+		writer.removeSelectionAttribute( selection.getAttributeKeys() );
+		writer.setSelectionAttribute( attributesToCopy );
 	} else {
 		const leaveUnmerged = !( range.start.isAtStart && range.end.isAtEnd );
 		model.deleteContent( selection, { leaveUnmerged } );

+ 26 - 0
packages/ckeditor5-enter/src/utils.js

@@ -0,0 +1,26 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module enter/utils
+ */
+
+/**
+ * Returns attributes that should be preserved on the enter key.
+ *
+ * Filtering is realized based on `copyOnEnter` attribute property. Read more about attribute properties
+ * {@link module:engine/model/schema~Schema#setAttributeProperties here}.
+ *
+ * @param {module:engine/model/schema~Schema} schema
+ * @param {Iterable.<*>} allAttributes attributes to filter.
+ * @returns {Iterable.<*>}
+ */
+export function* getCopyOnEnterAttributes( schema, allAttributes ) {
+	for ( const attribute of allAttributes ) {
+		if ( attribute && schema.getAttributeProperties( attribute[ 0 ] ).copyOnEnter ) {
+			yield attribute;
+		}
+	}
+}

+ 25 - 0
packages/ckeditor5-enter/tests/entercommand.js

@@ -87,6 +87,31 @@ describe( 'EnterCommand', () => {
 				'<p>x</p><p>[]</p><p>y</p>',
 				'<p>x</p><p></p><p>[]</p><p>y</p>'
 			);
+
+			describe( 'copyOnEnter', () => {
+				beforeEach( () => {
+					schema.extend( '$text', { allowAttributes: [ 'foo', 'bar' ] } );
+					schema.setAttributeProperties( 'foo', { copyOnEnter: true } );
+				} );
+
+				test(
+					'allowed attributes are copied',
+					'<p><$text foo="true">test[]</$text></p>',
+					'<p><$text foo="true">test</$text></p><p selection:foo="true"><$text foo="true">[]</$text></p>'
+				);
+
+				test(
+					'unknown attributes are not copied',
+					'<p><$text bar="true">test[]</$text></p>',
+					'<p><$text bar="true">test</$text></p><p>[]</p>'
+				);
+
+				test(
+					'only allowed attributes are copied from mix set',
+					'<p><$text bar="true" foo="true">test[]</$text></p>',
+					'<p><$text bar="true" foo="true">test</$text></p><p selection:foo="true"><$text foo="true">[]</$text></p>'
+				);
+			} );
 		} );
 
 		describe( 'non-collapsed selection', () => {

+ 25 - 0
packages/ckeditor5-enter/tests/shiftentercommand.js

@@ -101,6 +101,31 @@ describe( 'ShiftEnterCommand', () => {
 				'<p>x</p><p>[]foo</p><p>y</p>',
 				'<p>x</p><p><softBreak></softBreak>[]foo</p><p>y</p>'
 			);
+
+			describe( 'copyOnEnter', () => {
+				beforeEach( () => {
+					schema.extend( '$text', { allowAttributes: [ 'foo', 'bar' ] } );
+					schema.setAttributeProperties( 'foo', { copyOnEnter: true } );
+				} );
+
+				test(
+					'allowed attributes are copied',
+					'<p><$text foo="true">test[]</$text></p>',
+					'<p><$text foo="true">test</$text><softBreak></softBreak><$text foo="true">[]</$text></p>'
+				);
+
+				test(
+					'unknown attributes are not copied',
+					'<p><$text bar="true">test[]</$text></p>',
+					'<p><$text bar="true">test</$text><softBreak></softBreak>[]</p>'
+				);
+
+				test(
+					'only allowed attributes are copied from mix set',
+					'<p><$text bar="true" foo="true">test[]</$text></p>',
+					'<p><$text bar="true" foo="true">test</$text><softBreak></softBreak><$text foo="true">[]</$text></p>'
+				);
+			} );
 		} );
 
 		describe( 'non-collapsed selection', () => {

+ 38 - 0
packages/ckeditor5-enter/tests/utils.js

@@ -0,0 +1,38 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+import { getCopyOnEnterAttributes } from '../src/utils';
+import ModelTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/modeltesteditor';
+
+describe( 'utils', () => {
+	describe( 'getCopyOnEnterAttributes()', () => {
+		it( 'filters attributes with copyOnEnter property', () => {
+			return ModelTestEditor.create()
+				.then( editor => {
+					const schema = editor.model.schema;
+
+					schema.extend( '$text', {
+						allowAttributes: [ 'foo', 'bar', 'baz' ]
+					} );
+
+					schema.setAttributeProperties( 'foo', { copyOnEnter: true } );
+					schema.setAttributeProperties( 'baz', { copyOnEnter: true } );
+
+					const allAttributes = ( new Map( [
+						[ 'foo', true ],
+						[ 'bar', true ],
+						[ 'baz', true ]
+					] ) )[ Symbol.iterator ]();
+
+					expect( Array.from( getCopyOnEnterAttributes( schema, allAttributes ) ) ).to.deep.equal(
+						[
+							[ 'foo', true ],
+							[ 'baz', true ]
+						]
+					);
+				} );
+		} );
+	} );
+} );