浏览代码

Other: Implement basic configuration of alignment feature.

Maciej Gołaszewski 8 年之前
父节点
当前提交
954c8410fe

+ 4 - 3
packages/ckeditor5-alignment/src/alignmentcommand.js

@@ -70,10 +70,11 @@ export default class AlignmentCommand extends Command {
 			const batch = options.batch || document.batch();
 			const blocks = Array.from( document.selection.getSelectedBlocks() );
 
-			if ( this._isDefault() ) {
+			// Executing command on already aligned text should remove alignment attribute
+			if ( this.value || this._isDefault() ) {
 				removeAlignmentFromSelection( blocks, batch );
 			} else {
-				addAlignmentToSelection( blocks, batch, this.type );
+				setAlignmentOnSelection( blocks, batch, this.type );
 			}
 		} );
 	}
@@ -134,7 +135,7 @@ function removeAlignmentFromSelection( blocks, batch ) {
 
 // Sets alignment attribute on blocks.
 // @private
-function addAlignmentToSelection( blocks, batch, type ) {
+function setAlignmentOnSelection( blocks, batch, type ) {
 	for ( const block of blocks ) {
 		batch.setAttribute( block, 'alignment', type );
 	}

+ 73 - 7
packages/ckeditor5-alignment/src/alignmentediting.js

@@ -14,7 +14,7 @@ import AlignmentCommand from './alignmentcommand';
 import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
 import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
 
-const alignmentTypes = [ 'left', 'right', 'center', 'justify' ];
+import upperFirst from '@ckeditor/ckeditor5-utils/src/lib/lodash/upperFirst';
 
 /**
  * @extends module:core/plugin~Plugin
@@ -23,11 +23,42 @@ export default class AlignmentEditing extends Plugin {
 	/**
 	 * @inheritDoc
 	 */
+	constructor( editor ) {
+		super( editor );
+
+		editor.config.define( 'alignment', { styles: [ ...this.constructor.supportedStyles ] } );
+	}
+
+	/**
+	 * @inheritDoc
+	 */
 	static get requires() {
 		return [];
 	}
 
 	/**
+	 * Returns list of supported styles.
+	 *
+	 * @static
+	 * @readonly
+	 * @member {Array.<String>} module:alignment/alignmentediting~AlignmentEditing.supportedStyles
+	 */
+	static get supportedStyles() {
+		return [ 'left', 'right', 'center', 'justify' ];
+	}
+
+	/**
+	 * Helper function that returns command name for given style. May produce unknown commands if passed style is not
+	 * in {@link module:alignment/alignmentediting~AlignmentEditing.supportedStyles}.
+	 *
+	 * @param {String} style
+	 * @returns {String}
+	 */
+	static commandName( style ) {
+		return `align${ upperFirst( style ) }`;
+	}
+
+	/**
 	 * @inheritDoc
 	 */
 	init() {
@@ -37,6 +68,8 @@ export default class AlignmentEditing extends Plugin {
 		const data = editor.data;
 		const editing = editor.editing;
 
+		const enabledStyles = editor.config.get( 'alignment.styles' );
+
 		// Allow alignment attribute on all blocks.
 		schema.allow( { name: '$block', attributes: 'alignment' } );
 
@@ -52,18 +85,16 @@ export default class AlignmentEditing extends Plugin {
 				const textAlign = viewElement.getStyle( 'text-align' );
 
 				// Do not convert empty, default or unknown alignment values.
-				if ( !textAlign || isDefault( textAlign ) || !alignmentTypes.includes( textAlign ) ) {
+				if ( !textAlign || isDefault( textAlign ) || !enabledStyles.includes( textAlign ) ) {
 					return;
 				}
 
 				return { key: 'alignment', value: textAlign };
 			} );
 
-		// Register commands for text alignment.
-		editor.commands.add( 'alignLeft', new AlignmentCommand( editor, 'left' ) );
-		editor.commands.add( 'alignRight', new AlignmentCommand( editor, 'right' ) );
-		editor.commands.add( 'alignCenter', new AlignmentCommand( editor, 'center' ) );
-		editor.commands.add( 'alignJustify', new AlignmentCommand( editor, 'justify' ) );
+		enabledStyles
+			.filter( isSupported )
+			.forEach( style => editor.commands.add( AlignmentEditing.commandName( style ), new AlignmentCommand( editor, style ) ) );
 	}
 
 	/**
@@ -79,8 +110,43 @@ export default class AlignmentEditing extends Plugin {
 	}
 }
 
+export function isSupported( style ) {
+	return AlignmentEditing.supportedStyles.includes( style );
+}
+
 // Check whether alignment is default one.
 // @private
 function isDefault( textAlign ) {
 	return textAlign === 'left';
 }
+
+/**
+ * The configuration of the {@link module:alignment/alignmentediting~AlignmentEditing Alignment feature}.
+ *
+ * Read more in {@link module:alignment/alignmentediting~AlignmentEditingConfig}.
+ *
+ * @member {module:alignment/alignmentediting~AlignmentEditingConfig} module:core/editor/editorconfig~EditorConfig#alignment
+ */
+
+/**
+ * The configuration of the {@link module:alignment/alignmentediting~AlignmentEditing Alignment feature}.
+ *
+ *		ClassicEditor
+ *			.create( editorElement, {
+ * 				alignment: {
+ *					styles: [ 'left', 'right' ]
+ * 				}
+ *			} )
+ *			.then( ... )
+ *			.catch( ... );
+ *
+ * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
+ *
+ * @interface AlignmentEditingConfig
+ */
+
+/**
+ * Enabled alignment styles from supported styles: `left`, `right`, `center` and `justify`. Other values are ignored.
+ *
+ * @member {String} module:alignment/alignmentediting~AlignmentEditingConfig#styles
+ */

+ 23 - 12
packages/ckeditor5-alignment/src/alignmentui.js

@@ -15,6 +15,16 @@ import alignLeftIcon from '../theme/icons/align-left.svg';
 import alignRightIcon from '../theme/icons/align-right.svg';
 import alignCenterIcon from '../theme/icons/align-center.svg';
 import alignJustifyIcon from '../theme/icons/align-justify.svg';
+import AlignmentEditing, { isSupported } from './alignmentediting';
+
+import upperFirst from '@ckeditor/ckeditor5-utils/src/lib/lodash/upperFirst';
+
+const icons = new Map( [
+	[ 'left', alignLeftIcon ],
+	[ 'right', alignRightIcon ],
+	[ 'center', alignCenterIcon ],
+	[ 'justify', alignJustifyIcon ]
+] );
 
 /**
  * The default Alignment UI plugin.
@@ -28,7 +38,7 @@ export default class AlignmentUI extends Plugin {
 	 * @inheritDoc
 	 */
 	static get requires() {
-		return [];
+		return [ AlignmentEditing ];
 	}
 
 	/**
@@ -42,31 +52,32 @@ export default class AlignmentUI extends Plugin {
 	 * @inheritDoc
 	 */
 	init() {
-		const t = this.editor.t;
-		this._addButton( 'alignLeft', t( 'Left' ), alignLeftIcon );
-		this._addButton( 'alignRight', t( 'Right' ), alignRightIcon );
-		this._addButton( 'alignCenter', t( 'Center' ), alignCenterIcon );
-		this._addButton( 'alignJustify', t( 'Justify' ), alignJustifyIcon );
+		const styles = this.editor.config.get( 'alignment.styles' );
+
+		styles
+			.filter( isSupported )
+			.forEach( style => this._addButton( style ) );
 	}
 
 	/**
 	 * Helper method for initializing a button and linking it with an appropriate command.
 	 *
 	 * @private
-	 * @param {String} commandName The name of the command.
-	 * @param {Object} label The button label.
-	 * @param {String} icon The source of the icon.
+	 * @param {String} style The name of style for which add button.
 	 */
-	_addButton( commandName, label, icon ) {
+	_addButton( style ) {
 		const editor = this.editor;
+		const t = editor.t;
+
+		const commandName = AlignmentEditing.commandName( style );
 		const command = editor.commands.get( commandName );
 
 		editor.ui.componentFactory.add( commandName, locale => {
 			const buttonView = new ButtonView( locale );
 
 			buttonView.set( {
-				label,
-				icon,
+				label: t( upperFirst( style ) ),
+				icon: icons.get( style ),
 				tooltip: true
 			} );
 

+ 43 - 2
packages/ckeditor5-alignment/tests/alignmentcommand.js

@@ -83,6 +83,14 @@ describe( 'AlignmentCommand', () => {
 				expect( getModelData( doc ) ).to.equal( '<paragraph alignment="center">x[]x</paragraph>' );
 			} );
 
+			it( 'should remove alignment from single block element if already has one', () => {
+				setModelData( doc, '<paragraph alignment="center">x[]x</paragraph>' );
+
+				editor.execute( 'alignCenter' );
+
+				expect( getModelData( doc ) ).to.equal( '<paragraph>x[]x</paragraph>' );
+			} );
+
 			it( 'adds alignment to all selected blocks', () => {
 				setModelData( doc, '<paragraph>x[x</paragraph><paragraph>xx</paragraph><paragraph>x]x</paragraph>' );
 
@@ -94,6 +102,23 @@ describe( 'AlignmentCommand', () => {
 					'<paragraph alignment="center">x]x</paragraph>'
 				);
 			} );
+
+			it( 'sets alignment on all selected blocks as first block', () => {
+				setModelData(
+					doc,
+					'<paragraph>x[x</paragraph>' +
+					'<paragraph >xx</paragraph>' +
+					'<paragraph alignment="center">x]x</paragraph>'
+				);
+
+				editor.execute( 'alignCenter' );
+
+				expect( getModelData( doc ) ).to.equal(
+					'<paragraph alignment="center">x[x</paragraph>' +
+					'<paragraph alignment="center">xx</paragraph>' +
+					'<paragraph alignment="center">x]x</paragraph>'
+				);
+			} );
 		} );
 
 		describe( 'applying default alignment', () => {
@@ -106,9 +131,25 @@ describe( 'AlignmentCommand', () => {
 			} );
 
 			it( 'removes alignment from all selected blocks', () => {
-				setModelData( doc, '<paragraph alignment="center">x[x</paragraph>' +
+				setModelData( doc,
+					'<paragraph alignment="center">x[x</paragraph>' +
 					'<paragraph alignment="center">xx</paragraph>' +
-					'<paragraph alignment="center">x]x</paragraph>' );
+					'<paragraph alignment="center">x]x</paragraph>'
+				);
+
+				editor.execute( 'alignLeft' );
+
+				expect( getModelData( doc ) ).to.equal(
+					'<paragraph>x[x</paragraph><paragraph>xx</paragraph><paragraph>x]x</paragraph>'
+				);
+			} );
+
+			it( 'removes alignment from all selected blocks even if one has not alignment', () => {
+				setModelData( doc,
+					'<paragraph alignment="center">x[x</paragraph>' +
+					'<paragraph>xx</paragraph>' +
+					'<paragraph alignment="center">x]x</paragraph>'
+				);
 
 				editor.execute( 'alignLeft' );
 

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

@@ -154,4 +154,28 @@ describe( 'AlignmentEditing', () => {
 			expect( editor.getData() ).to.equal( '<p>x</p>' );
 		} );
 	} );
+
+	describe( 'config', () => {
+		describe( 'styles', () => {
+			describe( 'default value', () => {
+				it( 'should be set', () => {
+					expect( editor.config.get( 'alignment.styles' ) ).to.deep.equal( [ 'left', 'right', 'center', 'justify' ] );
+				} );
+			} );
+
+			it( 'should customize commands', () => {
+				return VirtualTestEditor
+					.create( {
+						alignment: { styles: [ 'left', 'right' ] },
+						plugins: [ AlignmentEditing, Paragraph ]
+					} )
+					.then( editor => {
+						expect( editor.commands.get( 'alignLeft' ), 'adds alignLeft' ).to.be.instanceof( AlignmentCommand );
+						expect( editor.commands.get( 'alignRight' ), 'adds alignLeft' ).to.be.instanceof( AlignmentCommand );
+						expect( editor.commands.get( 'alignCenter' ), 'does not add alignCenter' ).to.be.undefined;
+						expect( editor.commands.get( 'alignJustify' ), 'does not add alignJustify' ).to.be.undefined;
+					} );
+			} );
+		} );
+	} );
 } );