Преглед изворни кода

Other: Use custom to style conversion.

Maciej Gołaszewski пре 8 година
родитељ
комит
dff6266b4a

+ 33 - 6
packages/ckeditor5-alignment/src/alignmentediting.js

@@ -11,8 +11,8 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 
 
 import AlignmentCommand from './alignmentcommand';
 import AlignmentCommand from './alignmentcommand';
 
 
-import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
 import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
 import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
+import { eventNameToConsumableType } from '@ckeditor/ckeditor5-engine/src/conversion/model-to-view-converters';
 
 
 import upperFirst from '@ckeditor/ckeditor5-utils/src/lib/lodash/upperFirst';
 import upperFirst from '@ckeditor/ckeditor5-utils/src/lib/lodash/upperFirst';
 
 
@@ -66,11 +66,8 @@ export default class AlignmentEditing extends Plugin {
 		// Allow alignment attribute on all blocks.
 		// Allow alignment attribute on all blocks.
 		schema.allow( { name: '$block', attributes: 'alignment' } );
 		schema.allow( { name: '$block', attributes: 'alignment' } );
 
 
-		// Convert model attribute alignment to `text-align` style property.
-		buildModelConverter()
-			.for( data.modelToView, editing.modelToView )
-			.fromAttribute( 'alignment' )
-			.toAttribute( value => ( { key: 'style', value: `text-align:${ value }` } ) );
+		attributeToStyleConverter( data.modelToView, 'alignment', attribute => ( { 'text-align': attribute } ), () => [ 'text-align' ] );
+		attributeToStyleConverter( editing.modelToView, 'alignment', attribute => ( { 'text-align': attribute } ), () => [ 'text-align' ] );
 
 
 		// Convert `text-align` style property from element to model attribute alignment.
 		// Convert `text-align` style property from element to model attribute alignment.
 		buildViewConverter()
 		buildViewConverter()
@@ -127,6 +124,36 @@ export function isSupported( style ) {
 	return AlignmentEditing.supportedStyles.includes( style );
 	return AlignmentEditing.supportedStyles.includes( style );
 }
 }
 
 
+function attributeToStyleConverter( dispatcher, modelAttributeName, setStyleFn, removeStyleFn ) {
+	dispatcher.on( `addAttribute:${ modelAttributeName }`, setStyle( setStyleFn ) );
+	dispatcher.on( `changeAttribute:${ modelAttributeName }`, setStyle( setStyleFn ) );
+	dispatcher.on( `removeAttribute:${ modelAttributeName }`, removeStyle( removeStyleFn ) );
+}
+
+function setStyle( setStyleFn ) {
+	return ( evt, data, consumable, conversionApi ) => {
+		if ( !consumable.consume( data.item, eventNameToConsumableType( evt.name ) ) ) {
+			return;
+		}
+
+		const styles = setStyleFn( data.attributeNewValue );
+
+		conversionApi.mapper.toViewElement( data.item ).setStyle( styles );
+	};
+}
+
+function removeStyle( removeStyleFn ) {
+	return ( evt, data, consumable, conversionApi ) => {
+		if ( !consumable.consume( data.item, eventNameToConsumableType( evt.name ) ) ) {
+			return;
+		}
+
+		const styles = removeStyleFn();
+		const viewElement = conversionApi.mapper.toViewElement( data.item );
+		viewElement.removeStyle( ...styles );
+	};
+}
+
 // Check whether alignment is default one.
 // Check whether alignment is default one.
 // @private
 // @private
 function isDefault( textAlign ) {
 function isDefault( textAlign ) {

+ 63 - 0
packages/ckeditor5-alignment/tests/alignmentediting.js

@@ -10,6 +10,7 @@ import ListEngine from '@ckeditor/ckeditor5-list/src/listengine';
 import HeadingEngine from '@ckeditor/ckeditor5-heading/src/headingengine';
 import HeadingEngine from '@ckeditor/ckeditor5-heading/src/headingengine';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { eventNameToConsumableType } from '@ckeditor/ckeditor5-engine/src/conversion/model-to-view-converters';
 
 
 import AlignmentCommand from '../src/alignmentcommand';
 import AlignmentCommand from '../src/alignmentcommand';
 
 
@@ -82,6 +83,18 @@ describe( 'AlignmentEditing', () => {
 			expect( getModelData( doc ) ).to.equal( '<paragraph>[]x</paragraph>' );
 			expect( getModelData( doc ) ).to.equal( '<paragraph>[]x</paragraph>' );
 			expect( editor.getData() ).to.equal( '<p>x</p>' );
 			expect( editor.getData() ).to.equal( '<p>x</p>' );
 		} );
 		} );
+
+		it( 'adds a converter to the view pipeline for removing attribute', () => {
+			setModelData( doc, '<paragraph alignment="center">[]x</paragraph>' );
+
+			expect( editor.getData() ).to.equal( '<p style="text-align:center;">x</p>' );
+
+			const command = editor.commands.get( 'alignLeft' );
+
+			command.execute();
+
+			expect( editor.getData() ).to.equal( '<p>x</p>' );
+		} );
 	} );
 	} );
 
 
 	describe( 'alignCenter', () => {
 	describe( 'alignCenter', () => {
@@ -99,6 +112,18 @@ describe( 'AlignmentEditing', () => {
 
 
 			expect( editor.getData() ).to.equal( '<p style="text-align:center;">x</p>' );
 			expect( editor.getData() ).to.equal( '<p style="text-align:center;">x</p>' );
 		} );
 		} );
+
+		it( 'adds a converter to the view pipeline for changing attribute', () => {
+			setModelData( doc, '<paragraph alignment="right">[]x</paragraph>' );
+
+			expect( editor.getData() ).to.equal( '<p style="text-align:right;">x</p>' );
+
+			const command = editor.commands.get( 'alignCenter' );
+
+			command.execute();
+
+			expect( editor.getData() ).to.equal( '<p style="text-align:center;">x</p>' );
+		} );
 	} );
 	} );
 
 
 	describe( 'alignRight', () => {
 	describe( 'alignRight', () => {
@@ -135,6 +160,26 @@ describe( 'AlignmentEditing', () => {
 		} );
 		} );
 	} );
 	} );
 
 
+	describe( 'should be extensible', () => {
+		it( 'converters in the data pipeline', () => {
+			blockDefaultConversion( editor.data.modelToView );
+			blockDefaultConversion( editor.editing.modelToView );
+
+			const data = '<p style="text-align:justify;">x</p>';
+
+			editor.setData( data );
+
+			expect( getModelData( doc ) ).to.equal( '<paragraph alignment="justify">[]x</paragraph>' );
+
+			expect( editor.getData() ).to.equal( '<p>x</p>' );
+
+			const command = editor.commands.get( 'alignLeft' );
+			command.execute();
+
+			expect( editor.getData() ).to.equal( '<p>x</p>' );
+		} );
+	} );
+
 	describe( 'should work with broken styles', () => {
 	describe( 'should work with broken styles', () => {
 		it( 'should ignore empty style', () => {
 		it( 'should ignore empty style', () => {
 			const data = '<p style="text-align:">x</p>';
 			const data = '<p style="text-align:">x</p>';
@@ -179,3 +224,21 @@ describe( 'AlignmentEditing', () => {
 		} );
 		} );
 	} );
 	} );
 } );
 } );
+
+function blockDefaultConversion( dispatcher ) {
+	dispatcher.on(
+		'addAttribute:alignment',
+		( evt, data, consumable ) => consumable.consume( data.item, eventNameToConsumableType( evt.name ) ),
+		{ 'priority': 'high' }
+	);
+	dispatcher.on(
+		'changeAttribute:alignment',
+		( evt, data, consumable ) => consumable.consume( data.item, eventNameToConsumableType( evt.name ) ),
+		{ 'priority': 'high' }
+	);
+	dispatcher.on(
+		'removeAttribute:alignment',
+		( evt, data, consumable ) => consumable.consume( data.item, eventNameToConsumableType( evt.name ) ),
+		{ 'priority': 'high' }
+	);
+}