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

Other: Extract common UI and Editing parts as utils.

Maciej Gołaszewski 8 лет назад
Родитель
Сommit
616a5baede

+ 5 - 126
packages/ckeditor5-font/src/fontfamily/fontfamilyediting.js

@@ -14,6 +14,7 @@ import {
 } from '@ckeditor/ckeditor5-engine/src/conversion/definition-based-converters';
 
 import FontFamilyCommand from './fontfamilycommand';
+import { normalizeOptions } from './utils';
 
 /**
  * The Font Family Editing feature.
@@ -42,43 +43,6 @@ export default class FontFamilyEditing extends Plugin {
 		} );
 	}
 
-	/**
-	 * Returns {@link module:font/fontfamily/fontfamilyediting~FontFamilyConfig#options} array with options normalized in the
-	 * {@link module:font/fontfamily/fontfamilyediting~FontFamilyOption} format, translated
-	 * `title` for each style.
-	 *
-	 * @readonly
-	 * @type {Array.<module:font/fontfamily/fontfamilyediting/imagestyleengine~ImageStyleFormat>}
-	 */
-	get configuredOptions() {
-		// Cache value
-		if ( this._cachedOptions ) {
-			return this._cachedOptions;
-		}
-
-		const editor = this.editor;
-		const t = editor.t;
-
-		const options = [];
-		const configuredOptions = editor.config.get( 'fontFamily.options' );
-
-		for ( const item of configuredOptions ) {
-			const itemDefinition = getItemDefinition( item );
-
-			// Set only valid definitions.
-			if ( itemDefinition ) {
-				// Localize the "Default" title if set.
-				if ( itemDefinition.title === 'Default' ) {
-					itemDefinition.title = t( 'Default' );
-				}
-
-				options.push( itemDefinition );
-			}
-		}
-
-		return ( this._cachedOptions = options );
-	}
-
 	/**
 	 * @inheritDoc
 	 */
@@ -91,105 +55,20 @@ export default class FontFamilyEditing extends Plugin {
 		editor.model.schema.extend( '$text', { allowAttributes: 'fontFamily' } );
 
 		// Get configured font family options without "default" option.
-		const fontFamilyOptions = this.configuredOptions.filter( item => item.model );
+		const options = normalizeOptions( editor.config.get( 'fontFamily.options' ) ).filter( item => item.model );
 
 		// Define view to model conversion.
-		for ( const item of fontFamilyOptions ) {
-			viewToModelAttribute( 'fontFamily', item, [ data.viewToModel ] );
+		for ( const option of options ) {
+			viewToModelAttribute( 'fontFamily', option, [ data.viewToModel ] );
 		}
 
 		// Define model to view conversion.
-		modelAttributeToViewAttributeElement( 'fontFamily', fontFamilyOptions, [ data.modelToView, editing.modelToView ] );
+		modelAttributeToViewAttributeElement( 'fontFamily', options, [ data.modelToView, editing.modelToView ] );
 
 		editor.commands.add( 'fontFamily', new FontFamilyCommand( editor ) );
 	}
 }
 
-// Returns item definition from preset
-function getItemDefinition( item ) {
-	// Probably it is full item definition so return it.
-	if ( typeof item === 'object' ) {
-		return item;
-	}
-
-	// Handle 'default' string as a special case. It will be used to remove the fontFamily attribute.
-	if ( item === 'default' ) {
-		return {
-			title: 'Default',
-			model: undefined
-		};
-	}
-
-	// Ignore values that we cannot parse to a definition.
-	if ( typeof item !== 'string' ) {
-		return;
-	}
-
-	return generateFontPreset( item );
-}
-
-// Creates a predefined preset for pixel size. It deconstructs font-family like string into full configuration option.
-// A font definition is passed as coma delimited set of font family names. Font names might be quoted.
-//
-// @param {String} A font definition form configuration.
-function generateFontPreset( fontDefinition ) {
-	// Remove quotes from font names - will be normalized later.
-	const fontNames = fontDefinition.replace( /"|'/g, '' ).split( ',' );
-
-	// The first matched font name will be used as dropdown list item title and as model value
-	const firstFontName = fontNames[ 0 ];
-
-	const cssFontNames = fontNames.map( normalizeFontName );
-
-	// TODO: Maybe we can come with something better here?
-	// TODO: Also document this behavior in engine as it uses matcher~Pattern not ViewElementDefinition.
-	// TODO: Maybe a better solution will be a callback here? (also needs documentation)
-	// This will match any quote type with whitespace.
-	const quotesMatch = '("|\'|&qout;|\\W){0,2}';
-	// Full regex will catch any style of quotation used in view.
-	// Example:
-	// from string: "Font Foo Foo, Font Bar"
-	// it will create a regex that will match any quotation mix:
-	//     - "Font Foo Foo", Font Bar
-	//     - 'Font Foo Foo', "Font Bar"
-	//     - ... etc.
-	const regexString = `${ quotesMatch }${ fontNames.map( n => n.trim() ).join( `${ quotesMatch },${ quotesMatch }` ) }${ quotesMatch }`;
-
-	return {
-		title: firstFontName,
-		model: firstFontName,
-		view: {
-			name: 'span',
-			style: {
-				'font-family': cssFontNames.join( ', ' )
-			}
-		},
-		acceptsAlso: [
-			{
-				name: 'span',
-				style: {
-					'font-family': new RegExp( regexString )
-				}
-			}
-		]
-	};
-}
-
-// Normalizes font name for the view style attribute.
-//
-// @param {String} fontName
-// @returns {String}
-function normalizeFontName( fontName ) {
-	fontName = fontName.trim();
-
-	// Compound font names should be quoted.
-	if ( fontName.indexOf( ' ' ) > 0 ) {
-		fontName = `'${ fontName }'`;
-	}
-
-	return fontName;
-}
-
 /**
  * Font family option. Compatible with {@link module:engine/conversion/definition-based-converters~ConverterDefinition}.
  *

+ 11 - 13
packages/ckeditor5-font/src/fontfamily/fontfamilyui.js

@@ -12,9 +12,8 @@ import Model from '@ckeditor/ckeditor5-ui/src/model';
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
 import createListDropdown from '@ckeditor/ckeditor5-ui/src/dropdown/list/createlistdropdown';
 
-import FontFamilyEditing from './fontfamilyediting';
-
 import fontFamilyIcon from '../../theme/icons/font-family.svg';
+import { normalizeOptions } from './utils';
 
 /**
  * @extends module:core/plugin~Plugin
@@ -25,15 +24,15 @@ export default class FontFamilyUI extends Plugin {
 	 */
 	init() {
 		const editor = this.editor;
+		const t = editor.t;
+
 		const dropdownItems = new Collection();
 
 		const options = this._getLocalizedOptions();
-		const t = editor.t;
 
 		const command = editor.commands.get( 'fontFamily' );
 
-		const dropdownTooltip = t( 'Font Family' );
-
+		// Create dropdown items.
 		for ( const option of options ) {
 			const itemModel = new Model( {
 				commandName: 'fontFamily',
@@ -41,12 +40,11 @@ export default class FontFamilyUI extends Plugin {
 				label: option.title,
 			} );
 
-			// Try to set style
+			// Try to set a dropdown list item style.
 			if ( option.view && option.view.style ) {
 				itemModel.set( 'style', 'font-family:' + option.view.style[ 'font-family' ] );
 			}
 
-			// Add the option to the collection.
 			dropdownItems.add( itemModel );
 		}
 
@@ -55,7 +53,7 @@ export default class FontFamilyUI extends Plugin {
 			icon: fontFamilyIcon,
 			withText: false,
 			items: dropdownItems,
-			tooltip: dropdownTooltip
+			tooltip: t( 'Font Family' )
 		} );
 
 		dropdownModel.bind( 'isEnabled' ).to( command, 'isEnabled' );
@@ -64,7 +62,6 @@ export default class FontFamilyUI extends Plugin {
 		editor.ui.componentFactory.add( 'fontFamily', locale => {
 			const dropdown = createListDropdown( dropdownModel, locale );
 
-			// TODO check if needed
 			dropdown.extendTemplate( {
 				attributes: {
 					class: [
@@ -84,7 +81,7 @@ export default class FontFamilyUI extends Plugin {
 	}
 
 	/**
-	 * Returns heading options as defined in `config.heading.options` but processed to consider
+	 * Returns TODO options as defined in `config.heading.options` but processed to consider
 	 * editor localization, i.e. to display {@link module:heading/heading~HeadingOption}
 	 * in the correct language.
 	 *
@@ -97,21 +94,22 @@ export default class FontFamilyUI extends Plugin {
 	_getLocalizedOptions() {
 		const editor = this.editor;
 		const t = editor.t;
+
 		const localizedTitles = {
+			Default: t( 'Default' ),
 			Tiny: t( 'Tiny' ),
 			Small: t( 'Small' ),
 			Big: t( 'Big' ),
 			Huge: t( 'Huge' )
 		};
 
-		// TODO this is not nice :/ in terms of feature split.
-		const options = editor.plugins.get( FontFamilyEditing ).configuredOptions;
+		const options = normalizeOptions( editor.config.get( 'fontFamily.options' ) );
 
 		return options.map( option => {
 			const title = localizedTitles[ option.title ];
 
 			if ( title && title != option.title ) {
-				// Clone the option to avoid altering the original `config.heading.options`.
+				// Clone the option to avoid altering the original `config.fontFamily.options`.
 				option = Object.assign( {}, option, { title } );
 			}
 

+ 114 - 0
packages/ckeditor5-font/src/fontfamily/utils.js

@@ -0,0 +1,114 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module font/fontfamily/fontfamilyediting
+ */
+
+/**
+ * Returns {@link module:font/fontfamily/fontfamilyediting~FontFamilyConfig#options} array with options normalized in the
+ * {@link module:font/fontfamily/fontfamilyediting~FontFamilyOption} format, translated
+ * `title` for each style.
+ *
+ * @returns {Array.<module:font/fontfamily/fontfamilyediting~FontFamilyOption>}
+ */
+export function normalizeOptions( configuredOptions ) {
+	const options = [];
+	for ( const item of configuredOptions ) {
+		const itemDefinition = getItemDefinition( item );
+
+		// Set only valid definitions.
+		if ( itemDefinition ) {
+			options.push( itemDefinition );
+		}
+	}
+
+	return options;
+}
+
+// Returns item definition from preset
+function getItemDefinition( item ) {
+	// Probably it is full item definition so return it.
+	if ( typeof item === 'object' ) {
+		return item;
+	}
+
+	// Handle 'default' string as a special case. It will be used to remove the fontFamily attribute.
+	if ( item === 'default' ) {
+		return {
+			title: 'Default',
+			model: undefined
+		};
+	}
+
+	// Ignore values that we cannot parse to a definition.
+	if ( typeof item !== 'string' ) {
+		return;
+	}
+
+	return generateFontPreset( item );
+}
+
+// Creates a predefined preset for pixel size. It deconstructs font-family like string into full configuration option.
+// A font definition is passed as coma delimited set of font family names. Font names might be quoted.
+//
+// @param {String} A font definition form configuration.
+function generateFontPreset( fontDefinition ) {
+	// Remove quotes from font names - will be normalized later.
+	const fontNames = fontDefinition.replace( /"|'/g, '' ).split( ',' );
+
+	// The first matched font name will be used as dropdown list item title and as model value
+	const firstFontName = fontNames[ 0 ];
+
+	const cssFontNames = fontNames.map( normalizeFontName );
+
+	// TODO: Maybe we can come with something better here?
+	// TODO: Also document this behavior in engine as it uses matcher~Pattern not ViewElementDefinition.
+	// TODO: Maybe a better solution will be a callback here? (also needs documentation)
+	// This will match any quote type with whitespace.
+	const quotesMatch = '("|\'|&qout;|\\W){0,2}';
+	// Full regex will catch any style of quotation used in view.
+	// Example:
+	// from string: "Font Foo Foo, Font Bar"
+	// it will create a regex that will match any quotation mix:
+	//     - "Font Foo Foo", Font Bar
+	//     - 'Font Foo Foo', "Font Bar"
+	//     - ... etc.
+	const regexString = `${ quotesMatch }${ fontNames.map( n => n.trim() ).join( `${ quotesMatch },${ quotesMatch }` ) }${ quotesMatch }`;
+
+	return {
+		title: firstFontName,
+		model: firstFontName,
+		view: {
+			name: 'span',
+			style: {
+				'font-family': cssFontNames.join( ', ' )
+			}
+		},
+		acceptsAlso: [
+			{
+				name: 'span',
+				style: {
+					'font-family': new RegExp( regexString )
+				}
+			}
+		]
+	};
+}
+
+// Normalizes font name for the view style attribute.
+//
+// @param {String} fontName
+// @returns {String}
+function normalizeFontName( fontName ) {
+	fontName = fontName.trim();
+
+	// Compound font names should be quoted.
+	if ( fontName.indexOf( ' ' ) > 0 ) {
+		fontName = `'${ fontName }'`;
+	}
+
+	return fontName;
+}

+ 7 - 110
packages/ckeditor5-font/src/fontsize/fontsizeediting.js

@@ -14,6 +14,7 @@ import {
 } from '@ckeditor/ckeditor5-engine/src/conversion/definition-based-converters';
 
 import FontSizeCommand from './fontsizecommand';
+import { normalizeOptions } from './utils';
 
 /**
  * The Font Size Editing feature.
@@ -29,7 +30,7 @@ export default class FontSizeEditing extends Plugin {
 
 		// Define default configuration using named presets
 		editor.config.define( 'fontSize', {
-			items: [
+			options: [
 				'tiny',
 				'small',
 				'normal',
@@ -43,43 +44,20 @@ export default class FontSizeEditing extends Plugin {
 		const editing = editor.editing;
 
 		// Define view to model conversion.
-		const items = this.configuredItems.filter( item => item.model );
+		const options = normalizeOptions( this.editor.config.get( 'fontSize.options' ) ).filter( item => item.model );
 
-		for ( const item of items ) {
+		for ( const option of options ) {
 			// Covert view to model.
-			viewToModelAttribute( 'fontSize', item, [ data.viewToModel ] );
+			viewToModelAttribute( 'fontSize', option, [ data.viewToModel ] );
 		}
 
 		// Define model to view conversion.
-		modelAttributeToViewAttributeElement( 'fontSize', items, [ data.modelToView, editing.modelToView ] );
+		modelAttributeToViewAttributeElement( 'fontSize', options, [ data.modelToView, editing.modelToView ] );
 
 		// Add FontSize command.
 		editor.commands.add( 'fontSize', new FontSizeCommand( editor ) );
 	}
 
-	get configuredItems() {
-		// Cache value
-		if ( this._cachedItems ) {
-			return this._cachedItems;
-		}
-
-		const items = [];
-		const editor = this.editor;
-		const config = editor.config;
-
-		const configuredItems = config.get( 'fontSize.items' );
-
-		for ( const item of configuredItems ) {
-			const itemDefinition = getItemDefinition( item );
-
-			if ( itemDefinition ) {
-				items.push( itemDefinition );
-			}
-		}
-
-		return ( this._cachedItems = items );
-	}
-
 	/**
 	 * @inheritDoc
 	 */
@@ -91,87 +69,6 @@ export default class FontSizeEditing extends Plugin {
 	}
 }
 
-const namedPresets = {
-	tiny: {
-		title: 'Tiny',
-		model: 'text-tiny',
-		view: {
-			name: 'span',
-			class: 'text-tiny'
-		}
-	},
-	small: {
-		title: 'Small',
-		model: 'text-small',
-		view: {
-			name: 'span',
-			class: 'text-small'
-		}
-	},
-	big: {
-		title: 'Big',
-		model: 'text-big',
-		view: {
-			name: 'span',
-			class: 'text-big'
-		}
-	},
-	huge: {
-		title: 'Huge',
-		model: 'text-huge',
-		view: {
-			name: 'span',
-			class: 'text-huge'
-		}
-	}
-};
-
-// Returns item definition from preset
-function getItemDefinition( item ) {
-	// Named preset exist so return it
-	if ( namedPresets[ item ] ) {
-		return namedPresets[ item ];
-	}
-
-	// Probably it is full item definition so return it
-	if ( typeof item === 'object' ) {
-		return item;
-	}
-
-	if ( item === 'normal' ) {
-		return {
-			model: undefined,
-			title: 'Normal'
-		};
-	}
-
-	// At this stage we probably have numerical value to generate a preset so parse it's value.
-	const sizePreset = parseInt( item ); // TODO: Should we parse floats? 🤔
-
-	// Discard any faulty values.
-	if ( isNaN( sizePreset ) ) {
-		return;
-	}
-
-	return generatePixelPreset( sizePreset );
-}
-
-// Creates a predefined preset for pixel size.
-function generatePixelPreset( size ) {
-	const sizeName = String( size );
-
-	return {
-		title: sizeName,
-		model: sizeName,
-		view: {
-			name: 'span',
-			style: {
-				'font-size': `${ size }px`
-			}
-		}
-	};
-}
-
 /**
  * Font size option descriptor.
  *
@@ -214,5 +111,5 @@ function generatePixelPreset( size ) {
  * which configures
  *
  * @member {Array.<String|Number|module:font/fontsize/fontsizeediting~FontSizeOption>}
- *  module:font/fontsize/fontsizeediting~FontSizeConfig#items
+ *  module:font/fontsize/fontsizeediting~FontSizeConfig#options
  */

+ 4 - 5
packages/ckeditor5-font/src/fontsize/fontsizeui.js

@@ -12,8 +12,7 @@ import Model from '@ckeditor/ckeditor5-ui/src/model';
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
 import createListDropdown from '@ckeditor/ckeditor5-ui/src/dropdown/list/createlistdropdown';
 
-import FontSizeEditing from './fontsizeediting';
-
+import { normalizeOptions } from '../fontsize/utils';
 import fontSizeIcon from '../../theme/icons/font-size.svg';
 
 /**
@@ -91,6 +90,7 @@ export default class FontSizeUI extends Plugin {
 	_getLocalizedOptions() {
 		const editor = this.editor;
 		const t = editor.t;
+
 		const localizedTitles = {
 			Tiny: t( 'Tiny' ),
 			Small: t( 'Small' ),
@@ -98,10 +98,9 @@ export default class FontSizeUI extends Plugin {
 			Huge: t( 'Huge' )
 		};
 
-		// TODO this is not nice :/ in terms of feature split.
-		const items = editor.plugins.get( FontSizeEditing ).configuredItems;
+		const options = normalizeOptions( editor.config.get( 'fontSize.options' ) );
 
-		return items.map( option => {
+		return options.map( option => {
 			const title = localizedTitles[ option.title ];
 
 			if ( title && title != option.title ) {

+ 116 - 0
packages/ckeditor5-font/src/fontsize/utils.js

@@ -0,0 +1,116 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/**
+ * @module font/fontsize/utils
+ */
+
+/**
+ * Returns {@link module:font/fontsize/fontsizeediting~FontSizeConfig#options} array with options normalized in the
+ * {@link module:font/fontsize/fontsizeediting~FontSizeOption} format, translated
+ * `title` for each style.
+ *
+ * @returns {Array.<module:font/fontsize/fontsizeediting~FontSizeOption>}
+ */
+export function normalizeOptions( configuredOptions ) {
+	const options = [];
+
+	for ( const option of configuredOptions ) {
+		const definition = getOptionDefinition( option );
+
+		if ( definition ) {
+			options.push( definition );
+		}
+	}
+	return options;
+}
+
+const namedPresets = {
+	tiny: {
+		title: 'Tiny',
+		model: 'text-tiny',
+		view: {
+			name: 'span',
+			class: 'text-tiny'
+		}
+	},
+	small: {
+		title: 'Small',
+		model: 'text-small',
+		view: {
+			name: 'span',
+			class: 'text-small'
+		}
+	},
+	big: {
+		title: 'Big',
+		model: 'text-big',
+		view: {
+			name: 'span',
+			class: 'text-big'
+		}
+	},
+	huge: {
+		title: 'Huge',
+		model: 'text-huge',
+		view: {
+			name: 'span',
+			class: 'text-huge'
+		}
+	}
+};
+
+// Returns item definition from preset. Returns undefined for unparsable item. If object is passed then this method will return it without
+// alternating.
+//
+// @param {String|Number|Object} item
+// @returns {undefinde|module:font/fontsize/fontsizeediting~FontSizeOption}
+function getOptionDefinition( item ) {
+	// Named preset exist so return it
+	if ( namedPresets[ item ] ) {
+		return namedPresets[ item ];
+	}
+
+	// Probably it is full item definition so return it
+	if ( typeof item === 'object' ) {
+		return item;
+	}
+
+	if ( item === 'normal' ) {
+		return {
+			model: undefined,
+			title: 'Normal'
+		};
+	}
+
+	// At this stage we probably have numerical value to generate a preset so parse it's value.
+	const sizePreset = parseInt( item ); // TODO: Should we parse floats? 🤔
+
+	// Discard any faulty values.
+	if ( isNaN( sizePreset ) ) {
+		return;
+	}
+
+	return generatePixelPreset( sizePreset );
+}
+
+// Creates a predefined preset for pixel size.
+//
+// @param {Number} size Font size in pixels.
+// @returns {module:font/fontsize/fontsizeediting~FontSizeOption}
+function generatePixelPreset( size ) {
+	const sizeName = String( size );
+
+	return {
+		title: sizeName,
+		model: sizeName,
+		view: {
+			name: 'span',
+			style: {
+				'font-size': `${ size }px`
+			}
+		}
+	};
+}

+ 0 - 149
packages/ckeditor5-font/tests/fontfamily/fontfamilyediting.js

@@ -54,155 +54,6 @@ describe( 'FontFamilyEditing', () => {
 		} );
 	} );
 
-	describe( 'configuredOptions', () => {
-		it( 'should discard unparsable values', () => {
-			return VirtualTestEditor
-				.create( {
-					plugins: [ FontFamilyEditing ],
-					fontFamily: {
-						options: [ () => {}, 0, true ]
-					}
-				} )
-				.then( newEditor => {
-					editor = newEditor;
-
-					const plugin = editor.plugins.get( FontFamilyEditing );
-
-					expect( plugin.configuredOptions ).to.deep.equal( [] );
-				} );
-		} );
-
-		it( 'should pass through object definition', () => {
-			return VirtualTestEditor
-				.create( {
-					plugins: [ FontFamilyEditing ],
-					fontFamily: {
-						options: [
-							'default',
-							{
-								title: 'Comic Sans',
-								model: 'comic',
-								view: {
-									name: 'span',
-									style: {
-										'font-family': 'Comic Sans'
-									}
-								}
-							}
-						]
-					}
-				} )
-				.then( newEditor => {
-					editor = newEditor;
-
-					const plugin = editor.plugins.get( FontFamilyEditing );
-
-					expect( plugin.configuredOptions ).to.deep.equal( [
-						{
-							model: undefined,
-							title: 'Default'
-						},
-						{
-							title: 'Comic Sans',
-							model: 'comic',
-							view: {
-								name: 'span',
-								style: {
-									'font-family': 'Comic Sans'
-								}
-							}
-						}
-					] );
-				} );
-		} );
-
-		describe( 'shorthand presets', () => {
-			it( 'should return full preset from string presets', () => {
-				return VirtualTestEditor
-					.create( {
-						plugins: [ FontFamilyEditing ],
-						fontFamily: {
-							options: [
-								'Arial',
-								'"Comic Sans MS", sans-serif',
-								'Lucida Console, \'Courier New\', Courier, monospace'
-							]
-						}
-					} )
-					.then( newEditor => {
-						editor = newEditor;
-
-						const plugin = editor.plugins.get( FontFamilyEditing );
-
-						expect( plugin.configuredOptions ).to.deep.equal( [
-							{
-								title: 'Arial',
-								model: 'Arial',
-								view: {
-									name: 'span',
-									style: {
-										'font-family': 'Arial'
-									}
-								},
-								acceptsAlso: [
-									{
-										name: 'span',
-										style: {
-											'font-family': new RegExp( '("|\'|&qout;|\\W){0,2}Arial("|\'|&qout;|\\W){0,2}' )
-										}
-									}
-								]
-							},
-							{
-								title: 'Comic Sans MS',
-								model: 'Comic Sans MS',
-								view: {
-									name: 'span',
-									style: {
-										'font-family': '\'Comic Sans MS\', sans-serif'
-									}
-								},
-								acceptsAlso: [
-									{
-										name: 'span',
-										style: {
-											'font-family': new RegExp(
-												'("|\'|&qout;|\\W){0,2}Comic Sans MS("|\'|&qout;|\\W){0,2},' +
-												'("|\'|&qout;|\\W){0,2}sans-serif("|\'|&qout;|\\W){0,2}'
-											)
-										}
-									}
-								]
-							},
-							{
-								title: 'Lucida Console',
-								model: 'Lucida Console',
-								view: {
-									name: 'span',
-									style: {
-										'font-family': '\'Lucida Console\', \'Courier New\', Courier, monospace'
-									}
-								},
-								acceptsAlso: [
-									{
-										name: 'span',
-										style: {
-											'font-family': new RegExp(
-												'("|\'|&qout;|\\W){0,2}Lucida Console("|\'|&qout;|\\W){0,2},' +
-												'("|\'|&qout;|\\W){0,2}Courier New("|\'|&qout;|\\W){0,2},' +
-												'("|\'|&qout;|\\W){0,2}Courier("|\'|&qout;|\\W){0,2},' +
-												'("|\'|&qout;|\\W){0,2}monospace("|\'|&qout;|\\W){0,2}'
-											)
-										}
-									}
-								]
-							}
-						] );
-					} );
-			} );
-		} );
-	} );
-
 	describe( 'editing pipeline conversion', () => {
 		beforeEach( () => {
 			return VirtualTestEditor

+ 118 - 0
packages/ckeditor5-font/tests/fontfamily/utils.js

@@ -0,0 +1,118 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import { normalizeOptions } from '../../src/fontfamily/utils';
+
+describe( 'FontFamily utils', () => {
+	describe( 'normalizeOptions', () => {
+		it( 'should discard unparsable values', () => {
+			expect( normalizeOptions( [ () => {}, 0, true ] ) ).to.deep.equal( [] );
+		} );
+
+		it( 'should pass through object definition', () => {
+			expect( normalizeOptions( [
+				'default',
+				{
+					title: 'Comic Sans',
+					model: 'comic',
+					view: {
+						name: 'span',
+						style: {
+							'font-family': 'Comic Sans'
+						}
+					}
+				}
+			] ) ).to.deep.equal( [
+				{
+					model: undefined,
+					title: 'Default'
+				},
+				{
+					title: 'Comic Sans',
+					model: 'comic',
+					view: {
+						name: 'span',
+						style: {
+							'font-family': 'Comic Sans'
+						}
+					}
+				}
+			] );
+		} );
+
+		describe( 'shorthand presets', () => {
+			it( 'should return full preset from string presets', () => {
+				expect( normalizeOptions( ( [
+					'Arial',
+					'"Comic Sans MS", sans-serif',
+					'Lucida Console, \'Courier New\', Courier, monospace'
+				] ) ) ).to.deep.equal( [
+					{
+						title: 'Arial',
+						model: 'Arial',
+						view: {
+							name: 'span',
+							style: {
+								'font-family': 'Arial'
+							}
+						},
+						acceptsAlso: [
+							{
+								name: 'span',
+								style: {
+									'font-family': new RegExp( '("|\'|&qout;|\\W){0,2}Arial("|\'|&qout;|\\W){0,2}' )
+								}
+							}
+						]
+					},
+					{
+						title: 'Comic Sans MS',
+						model: 'Comic Sans MS',
+						view: {
+							name: 'span',
+							style: {
+								'font-family': '\'Comic Sans MS\', sans-serif'
+							}
+						},
+						acceptsAlso: [
+							{
+								name: 'span',
+								style: {
+									'font-family': new RegExp(
+										'("|\'|&qout;|\\W){0,2}Comic Sans MS("|\'|&qout;|\\W){0,2},' +
+										'("|\'|&qout;|\\W){0,2}sans-serif("|\'|&qout;|\\W){0,2}'
+									)
+								}
+							}
+						]
+					},
+					{
+						title: 'Lucida Console',
+						model: 'Lucida Console',
+						view: {
+							name: 'span',
+							style: {
+								'font-family': '\'Lucida Console\', \'Courier New\', Courier, monospace'
+							}
+						},
+						acceptsAlso: [
+							{
+								name: 'span',
+								style: {
+									'font-family': new RegExp(
+										'("|\'|&qout;|\\W){0,2}Lucida Console("|\'|&qout;|\\W){0,2},' +
+										'("|\'|&qout;|\\W){0,2}Courier New("|\'|&qout;|\\W){0,2},' +
+										'("|\'|&qout;|\\W){0,2}Courier("|\'|&qout;|\\W){0,2},' +
+										'("|\'|&qout;|\\W){0,2}monospace("|\'|&qout;|\\W){0,2}'
+									)
+								}
+							}
+						]
+					}
+				] );
+			} );
+		} );
+	} );
+} );

+ 3 - 95
packages/ckeditor5-font/tests/fontsize/fontsizeediting.js

@@ -39,99 +39,7 @@ describe( 'FontSizeEditing', () => {
 	describe( 'config', () => {
 		describe( 'default value', () => {
 			it( 'should be set', () => {
-				expect( editor.config.get( 'fontSize.items' ) ).to.deep.equal( [ 'tiny', 'small', 'normal', 'big', 'huge' ] );
-			} );
-		} );
-	} );
-
-	describe( 'configuredItems', () => {
-		it( 'should discard unsupported values', () => {
-			return VirtualTestEditor
-				.create( {
-					plugins: [ FontSizeEditing ],
-					fontSize: {
-						items: [ () => {}, 'normal', 'unknown' ]
-					}
-				} )
-				.then( newEditor => {
-					editor = newEditor;
-
-					const plugin = editor.plugins.get( FontSizeEditing );
-
-					expect( plugin.configuredItems ).to.deep.equal( [ { title: 'Normal', model: undefined } ] );
-				} );
-		} );
-
-		it( 'should pass through object definition', () => {
-			return VirtualTestEditor
-				.create( {
-					plugins: [ FontSizeEditing ],
-					fontSize: {
-						items: [ { title: 'My Size', model: 'my-size', view: { name: 'span', style: 'font-size: 12em;' } } ]
-					}
-				} )
-				.then( newEditor => {
-					editor = newEditor;
-
-					const plugin = editor.plugins.get( FontSizeEditing );
-
-					expect( plugin.configuredItems ).to.deep.equal( [
-						{
-							title: 'My Size',
-							model: 'my-size',
-							view: { name: 'span', style: 'font-size: 12em;' }
-						}
-					] );
-				} );
-		} );
-
-		describe( 'named presets', () => {
-			it( 'should return defined presets', () => {
-				return VirtualTestEditor
-					.create( {
-						plugins: [ FontSizeEditing ],
-						fontSize: {
-							items: [ 'tiny', 'small', 'normal', 'big', 'huge' ]
-						}
-					} )
-					.then( newEditor => {
-						editor = newEditor;
-
-						const plugin = editor.plugins.get( FontSizeEditing );
-
-						expect( plugin.configuredItems ).to.deep.equal( [
-							{ title: 'Tiny', model: 'text-tiny', view: { name: 'span', class: 'text-tiny' } },
-							{ title: 'Small', model: 'text-small', view: { name: 'span', class: 'text-small' } },
-							{ title: 'Normal', model: undefined },
-							{ title: 'Big', model: 'text-big', view: { name: 'span', class: 'text-big' } },
-							{ title: 'Huge', model: 'text-huge', view: { name: 'span', class: 'text-huge' } }
-						] );
-					} );
-			} );
-		} );
-
-		describe( 'numeric presets', () => {
-			it( 'should return generated presets', () => {
-				return VirtualTestEditor
-					.create( {
-						plugins: [ FontSizeEditing ],
-						fontSize: {
-							items: [ '10', 12, 'normal', '14.1', 18.3 ]
-						}
-					} )
-					.then( newEditor => {
-						editor = newEditor;
-
-						const plugin = editor.plugins.get( FontSizeEditing );
-
-						expect( plugin.configuredItems ).to.deep.equal( [
-							{ title: '10', model: '10', view: { name: 'span', style: { 'font-size': '10px' } } },
-							{ title: '12', model: '12', view: { name: 'span', style: { 'font-size': '12px' } } },
-							{ title: 'Normal', model: undefined },
-							{ title: '14', model: '14', view: { name: 'span', style: { 'font-size': '14px' } } },
-							{ title: '18', model: '18', view: { name: 'span', style: { 'font-size': '18px' } } }
-						] );
-					} );
+				expect( editor.config.get( 'fontSize.options' ) ).to.deep.equal( [ 'tiny', 'small', 'normal', 'big', 'huge' ] );
 			} );
 		} );
 	} );
@@ -142,7 +50,7 @@ describe( 'FontSizeEditing', () => {
 				.create( {
 					plugins: [ FontSizeEditing, Paragraph ],
 					fontSize: {
-						items: [
+						options: [
 							'tiny',
 							'normal',
 							18,
@@ -196,7 +104,7 @@ describe( 'FontSizeEditing', () => {
 				.create( {
 					plugins: [ FontSizeEditing, Paragraph ],
 					fontSize: {
-						items: [
+						options: [
 							'tiny',
 							'normal',
 							18,

+ 52 - 0
packages/ckeditor5-font/tests/fontsize/utils.js

@@ -0,0 +1,52 @@
+/**
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import { normalizeOptions } from '../../src/fontsize/utils';
+
+describe( 'FontSizeEditing', () => {
+	describe( 'configuredItems', () => {
+		it( 'should discard unsupported values', () => {
+			expect( normalizeOptions( [ () => {}, 'normal', 'unknown' ] ) ).to.deep.equal( [ { title: 'Normal', model: undefined } ] );
+		} );
+
+		it( 'should pass through object definition', () => {
+			expect( normalizeOptions( [ {
+				title: 'My Size',
+				model: 'my-size',
+				view: { name: 'span', style: 'font-size: 12em;' }
+			} ] ) ).to.deep.equal( [
+				{
+					title: 'My Size',
+					model: 'my-size',
+					view: { name: 'span', style: 'font-size: 12em;' }
+				}
+			] );
+		} );
+
+		describe( 'named presets', () => {
+			it( 'should return defined presets', () => {
+				expect( normalizeOptions( [ 'tiny', 'small', 'normal', 'big', 'huge' ] ) ).to.deep.equal( [
+					{ title: 'Tiny', model: 'text-tiny', view: { name: 'span', class: 'text-tiny' } },
+					{ title: 'Small', model: 'text-small', view: { name: 'span', class: 'text-small' } },
+					{ title: 'Normal', model: undefined },
+					{ title: 'Big', model: 'text-big', view: { name: 'span', class: 'text-big' } },
+					{ title: 'Huge', model: 'text-huge', view: { name: 'span', class: 'text-huge' } }
+				] );
+			} );
+		} );
+
+		describe( 'numeric presets', () => {
+			it( 'should return generated presets', () => {
+				expect( normalizeOptions( [ '10', 12, 'normal', '14.1', 18.3 ] ) ).to.deep.equal( [
+					{ title: '10', model: '10', view: { name: 'span', style: { 'font-size': '10px' } } },
+					{ title: '12', model: '12', view: { name: 'span', style: { 'font-size': '12px' } } },
+					{ title: 'Normal', model: undefined },
+					{ title: '14', model: '14', view: { name: 'span', style: { 'font-size': '14px' } } },
+					{ title: '18', model: '18', view: { name: 'span', style: { 'font-size': '18px' } } }
+				] );
+			} );
+		} );
+	} );
+} );