瀏覽代碼

Use map to store style converters.

Maciej Gołaszewski 6 年之前
父節點
當前提交
b5e5e7ca43

+ 5 - 0
packages/ckeditor5-engine/src/view/document.js

@@ -11,6 +11,7 @@ import DocumentSelection from './documentselection';
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
 import mix from '@ckeditor/ckeditor5-utils/src/mix';
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
+import Styles from './styles';
 
 // @if CK_DEBUG_ENGINE // const { logDocument } = require( '../dev-utils/utils' );
 
@@ -160,6 +161,10 @@ export default class Document {
 		this.stopListening();
 	}
 
+	addStyleProcessorRules( callback ) {
+		callback( Styles.processor );
+	}
+
 	/**
 	 * Performs post-fixer loops. Executes post-fixer callbacks as long as none of them has done any changes to the model.
 	 *

+ 40 - 20
packages/ckeditor5-engine/src/view/styles.js

@@ -8,8 +8,6 @@
  */
 
 import { get, isObject, merge, set, unset } from 'lodash-es';
-import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
-import mix from '@ckeditor/ckeditor5-utils/src/mix';
 
 /**
  * Styles class.
@@ -254,7 +252,9 @@ export default class Styles {
 
 export class StylesProcessor {
 	constructor() {
-		this._groups = new Set();
+		this._normalizers = new Map();
+		this._extractors = new Map();
+		this._reducers = new Map();
 	}
 
 	/**
@@ -270,9 +270,13 @@ export class StylesProcessor {
 			value: normalizedValue
 		};
 
-		this.fire( 'reduce:' + styleName, data );
+		if ( this._reducers.has( styleName ) ) {
+			const reducer = this._reducers.get( styleName );
 
-		return data.reduced || [ [ styleName, normalizedValue ] ];
+			return reducer( data );
+		}
+
+		return [ [ styleName, normalizedValue ] ];
 	}
 
 	getNormalized( name, styles ) {
@@ -289,14 +293,22 @@ export class StylesProcessor {
 			styles
 		};
 
-		this.fire( `extract:${ name }`, data );
+		if ( this._extractors.has( name ) ) {
+			const extractor = this._extractors.get( name );
 
-		if ( data.path ) {
-			return get( styles, data.path );
-		}
+			if ( typeof extractor === 'string' ) {
+				return get( styles, extractor );
+			}
+
+			const { path, value } = extractor( data );
 
-		if ( data.value ) {
-			return data.value;
+			if ( path ) {
+				return get( styles, path );
+			}
+
+			if ( value ) {
+				return value;
+			}
 		}
 
 		return get( styles, toPath( name ) );
@@ -322,21 +334,29 @@ export class StylesProcessor {
 			value
 		};
 
-		this.fire( 'normalize:' + propertyName, data );
+		if ( this._normalizers.has( propertyName ) ) {
+			const normalizer = this._normalizers.get( propertyName );
 
-		appendStyleValue( styles, data.path, data.value );
-	}
+			const { path, value } = normalizer( data );
 
-	registerListeners( groupName, callback ) {
-		if ( this._groups.has( groupName ) ) {
-			return;
+			appendStyleValue( styles, path, value );
+		} else {
+			appendStyleValue( styles, propertyName, value );
 		}
+	}
 
-		callback( this );
+	setNormalizer( propertyName, callback ) {
+		this._normalizers.set( propertyName, callback );
 	}
-}
 
-mix( StylesProcessor, EmitterMixin );
+	setExtractor( propertyName, callbackOrPath ) {
+		this._extractors.set( propertyName, callbackOrPath );
+	}
+
+	setReducer( propertyName, callback ) {
+		this._reducers.set( propertyName, callback );
+	}
+}
 
 // Parses inline styles and puts property - value pairs into styles map.
 //

+ 11 - 11
packages/ckeditor5-engine/src/view/styles/backgroundstyles.js

@@ -10,20 +10,18 @@ import { isAttachment, isColor, isPosition, isRepeat, isURL } from './utils';
  */
 
 export function addBackgroundStylesProcessor( stylesProcessor ) {
-	stylesProcessor.registerListeners( 'background', stylesProcessor => {
-		stylesProcessor.on( 'normalize:background', normalizeBackground );
-		stylesProcessor.on( 'normalize:background-color', ( evt, data ) => ( data.path = 'background.color' ) );
-		stylesProcessor.on( 'reduce:background', ( evt, data ) => {
-			const ret = [];
+	stylesProcessor.setNormalizer( 'background', normalizeBackground );
+	stylesProcessor.setNormalizer( 'background-color', data => ( { path: 'background.color', value: data.value } ) );
+	stylesProcessor.setReducer( 'background', data => {
+		const ret = [];
 
-			ret.push( [ 'background-color', data.value.color ] );
+		ret.push( [ 'background-color', data.value.color ] );
 
-			data.reduced = ret;
-		} );
+		return ret;
 	} );
 }
 
-function normalizeBackground( evt, data ) {
+function normalizeBackground( data ) {
 	const background = {};
 
 	const parts = data.value.split( ' ' );
@@ -44,6 +42,8 @@ function normalizeBackground( evt, data ) {
 		}
 	}
 
-	data.path = 'background';
-	data.value = background;
+	return {
+		path: 'background',
+		value: background
+	};
 }

+ 93 - 87
packages/ckeditor5-engine/src/view/styles/borderstyles.js

@@ -10,81 +10,81 @@ import { getShorthandValues, getTopRightBottomLeftValueReducer, getTopRightBotto
  */
 
 export function addBorderStylesProcessor( stylesProcessor ) {
-	stylesProcessor.registerListeners( 'border', stylesProcessor => {
-		stylesProcessor.on( 'normalize:border', borderNormalizer );
-
-		// Border-position shorthands.
-		stylesProcessor.on( 'normalize:border-top', getBorderPositionNormalizer( 'top' ) );
-		stylesProcessor.on( 'normalize:border-right', getBorderPositionNormalizer( 'right' ) );
-		stylesProcessor.on( 'normalize:border-bottom', getBorderPositionNormalizer( 'bottom' ) );
-		stylesProcessor.on( 'normalize:border-left', getBorderPositionNormalizer( 'left' ) );
-
-		// Border-property shorthands.
-		stylesProcessor.on( 'normalize:border-color', getBorderPropertyNormalizer( 'color' ) );
-		stylesProcessor.on( 'normalize:border-width', getBorderPropertyNormalizer( 'width' ) );
-		stylesProcessor.on( 'normalize:border-style', getBorderPropertyNormalizer( 'style' ) );
-
-		// Border longhands.
-		stylesProcessor.on( 'normalize:border-top-color', getBorderPropertyPositionNormalizer( 'color', 'top' ) );
-		stylesProcessor.on( 'normalize:border-top-style', getBorderPropertyPositionNormalizer( 'style', 'top' ) );
-		stylesProcessor.on( 'normalize:border-top-width', getBorderPropertyPositionNormalizer( 'width', 'top' ) );
-
-		stylesProcessor.on( 'normalize:border-right-color', getBorderPropertyPositionNormalizer( 'color', 'right' ) );
-		stylesProcessor.on( 'normalize:border-right-style', getBorderPropertyPositionNormalizer( 'style', 'right' ) );
-		stylesProcessor.on( 'normalize:border-right-width', getBorderPropertyPositionNormalizer( 'width', 'right' ) );
-
-		stylesProcessor.on( 'normalize:border-bottom-color', getBorderPropertyPositionNormalizer( 'color', 'bottom' ) );
-		stylesProcessor.on( 'normalize:border-bottom-style', getBorderPropertyPositionNormalizer( 'style', 'bottom' ) );
-		stylesProcessor.on( 'normalize:border-bottom-width', getBorderPropertyPositionNormalizer( 'width', 'bottom' ) );
-
-		stylesProcessor.on( 'normalize:border-left-color', getBorderPropertyPositionNormalizer( 'color', 'left' ) );
-		stylesProcessor.on( 'normalize:border-left-style', getBorderPropertyPositionNormalizer( 'style', 'left' ) );
-		stylesProcessor.on( 'normalize:border-left-width', getBorderPropertyPositionNormalizer( 'width', 'left' ) );
-
-		stylesProcessor.on( 'extract:border-top', getBorderPositionExtractor( 'top' ) );
-		stylesProcessor.on( 'extract:border-right', getBorderPositionExtractor( 'right' ) );
-		stylesProcessor.on( 'extract:border-bottom', getBorderPositionExtractor( 'bottom' ) );
-		stylesProcessor.on( 'extract:border-left', getBorderPositionExtractor( 'left' ) );
-
-		stylesProcessor.on( 'extract:border-top-color', ( evt, data ) => ( data.path = 'border.color.top' ) );
-		stylesProcessor.on( 'extract:border-right-color', ( evt, data ) => ( data.path = 'border.color.right' ) );
-		stylesProcessor.on( 'extract:border-bottom-color', ( evt, data ) => ( data.path = 'border.color.bottom' ) );
-		stylesProcessor.on( 'extract:border-left-color', ( evt, data ) => ( data.path = 'border.color.left' ) );
-
-		stylesProcessor.on( 'extract:border-top-width', ( evt, data ) => ( data.path = 'border.width.top' ) );
-		stylesProcessor.on( 'extract:border-right-width', ( evt, data ) => ( data.path = 'border.width.right' ) );
-		stylesProcessor.on( 'extract:border-bottom-width', ( evt, data ) => ( data.path = 'border.width.bottom' ) );
-		stylesProcessor.on( 'extract:border-left-width', ( evt, data ) => ( data.path = 'border.width.left' ) );
-
-		stylesProcessor.on( 'extract:border-top-style', ( evt, data ) => ( data.path = 'border.style.top' ) );
-		stylesProcessor.on( 'extract:border-right-style', ( evt, data ) => ( data.path = 'border.style.right' ) );
-		stylesProcessor.on( 'extract:border-bottom-style', ( evt, data ) => ( data.path = 'border.style.bottom' ) );
-		stylesProcessor.on( 'extract:border-left-style', ( evt, data ) => ( data.path = 'border.style.left' ) );
-
-		stylesProcessor.on( 'reduce:border-color', getTopRightBottomLeftValueReducer( 'border-color' ) );
-		stylesProcessor.on( 'reduce:border-style', getTopRightBottomLeftValueReducer( 'border-style' ) );
-		stylesProcessor.on( 'reduce:border-width', getTopRightBottomLeftValueReducer( 'border-width' ) );
-		stylesProcessor.on( 'reduce:border-top', getBorderPositionReducer( 'top' ) );
-		stylesProcessor.on( 'reduce:border-right', getBorderPositionReducer( 'right' ) );
-		stylesProcessor.on( 'reduce:border-bottom', getBorderPositionReducer( 'bottom' ) );
-		stylesProcessor.on( 'reduce:border-left', getBorderPositionReducer( 'left' ) );
-		stylesProcessor.on( 'reduce:border', borderReducer );
-	} );
+	stylesProcessor.setNormalizer( 'border', borderNormalizer );
+
+	// Border-position shorthands.
+	stylesProcessor.setNormalizer( 'border-top', getBorderPositionNormalizer( 'top' ) );
+	stylesProcessor.setNormalizer( 'border-right', getBorderPositionNormalizer( 'right' ) );
+	stylesProcessor.setNormalizer( 'border-bottom', getBorderPositionNormalizer( 'bottom' ) );
+	stylesProcessor.setNormalizer( 'border-left', getBorderPositionNormalizer( 'left' ) );
+
+	// Border-property shorthands.
+	stylesProcessor.setNormalizer( 'border-color', getBorderPropertyNormalizer( 'color' ) );
+	stylesProcessor.setNormalizer( 'border-width', getBorderPropertyNormalizer( 'width' ) );
+	stylesProcessor.setNormalizer( 'border-style', getBorderPropertyNormalizer( 'style' ) );
+
+	// Border longhands.
+	stylesProcessor.setNormalizer( 'border-top-color', getBorderPropertyPositionNormalizer( 'color', 'top' ) );
+	stylesProcessor.setNormalizer( 'border-top-style', getBorderPropertyPositionNormalizer( 'style', 'top' ) );
+	stylesProcessor.setNormalizer( 'border-top-width', getBorderPropertyPositionNormalizer( 'width', 'top' ) );
+
+	stylesProcessor.setNormalizer( 'border-right-color', getBorderPropertyPositionNormalizer( 'color', 'right' ) );
+	stylesProcessor.setNormalizer( 'border-right-style', getBorderPropertyPositionNormalizer( 'style', 'right' ) );
+	stylesProcessor.setNormalizer( 'border-right-width', getBorderPropertyPositionNormalizer( 'width', 'right' ) );
+
+	stylesProcessor.setNormalizer( 'border-bottom-color', getBorderPropertyPositionNormalizer( 'color', 'bottom' ) );
+	stylesProcessor.setNormalizer( 'border-bottom-style', getBorderPropertyPositionNormalizer( 'style', 'bottom' ) );
+	stylesProcessor.setNormalizer( 'border-bottom-width', getBorderPropertyPositionNormalizer( 'width', 'bottom' ) );
+
+	stylesProcessor.setNormalizer( 'border-left-color', getBorderPropertyPositionNormalizer( 'color', 'left' ) );
+	stylesProcessor.setNormalizer( 'border-left-style', getBorderPropertyPositionNormalizer( 'style', 'left' ) );
+	stylesProcessor.setNormalizer( 'border-left-width', getBorderPropertyPositionNormalizer( 'width', 'left' ) );
+
+	stylesProcessor.setExtractor( 'border-top', getBorderPositionExtractor( 'top' ) );
+	stylesProcessor.setExtractor( 'border-right', getBorderPositionExtractor( 'right' ) );
+	stylesProcessor.setExtractor( 'border-bottom', getBorderPositionExtractor( 'bottom' ) );
+	stylesProcessor.setExtractor( 'border-left', getBorderPositionExtractor( 'left' ) );
+
+	stylesProcessor.setExtractor( 'border-top-color', 'border.color.top' );
+	stylesProcessor.setExtractor( 'border-right-color', 'border.color.right' );
+	stylesProcessor.setExtractor( 'border-bottom-color', 'border.color.bottom' );
+	stylesProcessor.setExtractor( 'border-left-color', 'border.color.left' );
+
+	stylesProcessor.setExtractor( 'border-top-width', 'border.width.top' );
+	stylesProcessor.setExtractor( 'border-right-width', 'border.width.right' );
+	stylesProcessor.setExtractor( 'border-bottom-width', 'border.width.bottom' );
+	stylesProcessor.setExtractor( 'border-left-width', 'border.width.left' );
+
+	stylesProcessor.setExtractor( 'border-top-style', 'border.style.top' );
+	stylesProcessor.setExtractor( 'border-right-style', 'border.style.right' );
+	stylesProcessor.setExtractor( 'border-bottom-style', 'border.style.bottom' );
+	stylesProcessor.setExtractor( 'border-left-style', 'border.style.left' );
+
+	stylesProcessor.setReducer( 'border-color', getTopRightBottomLeftValueReducer( 'border-color' ) );
+	stylesProcessor.setReducer( 'border-style', getTopRightBottomLeftValueReducer( 'border-style' ) );
+	stylesProcessor.setReducer( 'border-width', getTopRightBottomLeftValueReducer( 'border-width' ) );
+	stylesProcessor.setReducer( 'border-top', getBorderPositionReducer( 'top' ) );
+	stylesProcessor.setReducer( 'border-right', getBorderPositionReducer( 'right' ) );
+	stylesProcessor.setReducer( 'border-bottom', getBorderPositionReducer( 'bottom' ) );
+	stylesProcessor.setReducer( 'border-left', getBorderPositionReducer( 'left' ) );
+	stylesProcessor.setReducer( 'border', borderReducer );
 }
 
-function borderNormalizer( evt, data ) {
+function borderNormalizer( data ) {
 	const { color, style, width } = normalizeBorderShorthand( data.value );
 
-	data.path = 'border';
-	data.value = {
-		color: getTopRightBottomLeftValues( color ),
-		style: getTopRightBottomLeftValues( style ),
-		width: getTopRightBottomLeftValues( width )
+	return {
+		path: 'border',
+		value: {
+			color: getTopRightBottomLeftValues( color ),
+			style: getTopRightBottomLeftValues( style ),
+			width: getTopRightBottomLeftValues( width )
+		}
 	};
 }
 
 function getBorderPositionNormalizer( side ) {
-	return ( evt, data ) => {
+	return data => {
 		const { color, style, width } = normalizeBorderShorthand( data.value );
 
 		const border = {};
@@ -101,15 +101,19 @@ function getBorderPositionNormalizer( side ) {
 			border.width = { [ side ]: width };
 		}
 
-		data.path = 'border';
-		data.value = border;
+		return {
+			path: 'border',
+			value: border
+		};
 	};
 }
 
 function getBorderPropertyNormalizer( propertyName ) {
-	return ( evt, data ) => {
-		data.path = 'border';
-		data.value = toBorderPropertyShorthand( data.value, propertyName );
+	return data => {
+		return {
+			path: 'border',
+			value: toBorderPropertyShorthand( data.value, propertyName )
+		};
 	};
 }
 
@@ -120,20 +124,22 @@ function toBorderPropertyShorthand( value, property ) {
 }
 
 function getBorderPropertyPositionNormalizer( property, side ) {
-	return ( evt, data ) => {
-		data.path = 'border';
-		data.value = {
-			[ property ]: {
-				[ side ]: data.value
+	return data => {
+		return {
+			path: 'border',
+			value: {
+				[ property ]: {
+					[ side ]: data.value
+				}
 			}
 		};
 	};
 }
 
 function getBorderPositionExtractor( which ) {
-	return ( evt, data ) => {
+	return data => {
 		if ( data.styles.border ) {
-			data.value = extractBorderPosition( data.styles.border, which, data );
+			return { value: extractBorderPosition( data.styles.border, which, data ) };
 		}
 	};
 }
@@ -174,19 +180,19 @@ function normalizeBorderShorthand( string ) {
 	return result;
 }
 
-function borderReducer( evt, data ) {
-	const ret = [];
+function borderReducer( data ) {
+	const reduced = [];
 
-	ret.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'top' ), 'top' ) );
-	ret.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'right' ), 'right' ) );
-	ret.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'bottom' ), 'bottom' ) );
-	ret.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'left' ), 'left' ) );
+	reduced.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'top' ), 'top' ) );
+	reduced.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'right' ), 'right' ) );
+	reduced.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'bottom' ), 'bottom' ) );
+	reduced.push( ...reduceBorderPosition( extractBorderPosition( data.value, 'left' ), 'left' ) );
 
-	data.reduced = ret;
+	return reduced;
 }
 
 function getBorderPositionReducer( which ) {
-	return ( evt, data ) => ( data.reduced = reduceBorderPosition( data.value, which ) );
+	return data => ( data.reduced = reduceBorderPosition( data.value, which ) );
 }
 
 function reduceBorderPosition( value, which ) {

+ 6 - 8
packages/ckeditor5-engine/src/view/styles/marginstyles.js

@@ -10,14 +10,12 @@ import { getPositionShorthandNormalizer, getTopRightBottomLeftValueReducer } fro
  */
 
 export function addMarginStylesProcessor( stylesProcessor ) {
-	stylesProcessor.registerListeners( 'margin', stylesProcessor => {
-		stylesProcessor.on( 'normalize:margin', getPositionShorthandNormalizer( 'margin' ) );
+	stylesProcessor.setNormalizer( 'margin', getPositionShorthandNormalizer( 'margin' ) );
 
-		stylesProcessor.on( 'normalize:margin-top', ( evt, data ) => ( data.path = 'margin.top' ) );
-		stylesProcessor.on( 'normalize:margin-right', ( evt, data ) => ( data.path = 'margin.right' ) );
-		stylesProcessor.on( 'normalize:margin-bottom', ( evt, data ) => ( data.path = 'margin.bottom' ) );
-		stylesProcessor.on( 'normalize:margin-left', ( evt, data ) => ( data.path = 'margin.left' ) );
+	stylesProcessor.setNormalizer( 'margin-top', data => ( { path: 'margin.top', value: data.value } ) );
+	stylesProcessor.setNormalizer( 'margin-right', data => ( { path: 'margin.right', value: data.value } ) );
+	stylesProcessor.setNormalizer( 'margin-bottom', data => ( { path: 'margin.bottom', value: data.value } ) );
+	stylesProcessor.setNormalizer( 'margin-left', data => ( { path: 'margin.left', value: data.value } ) );
 
-		stylesProcessor.on( 'reduce:margin', getTopRightBottomLeftValueReducer( 'margin' ) );
-	} );
+	stylesProcessor.setReducer( 'margin', getTopRightBottomLeftValueReducer( 'margin' ) );
 }

+ 6 - 8
packages/ckeditor5-engine/src/view/styles/paddingstyles.js

@@ -10,13 +10,11 @@ import { getPositionShorthandNormalizer, getTopRightBottomLeftValueReducer } fro
  */
 
 export function addPaddingStylesProcessor( stylesProcessor ) {
-	stylesProcessor.registerListeners( 'padding', stylesProcessor => {
-		stylesProcessor.on( 'normalize:padding', getPositionShorthandNormalizer( 'padding' ) );
-		stylesProcessor.on( 'normalize:padding-top', ( evt, data ) => ( data.path = 'padding.top' ) );
-		stylesProcessor.on( 'normalize:padding-right', ( evt, data ) => ( data.path = 'padding.right' ) );
-		stylesProcessor.on( 'normalize:padding-bottom', ( evt, data ) => ( data.path = 'padding.bottom' ) );
-		stylesProcessor.on( 'normalize:padding-left', ( evt, data ) => ( data.path = 'padding.left' ) );
+	stylesProcessor.setNormalizer( 'padding', getPositionShorthandNormalizer( 'padding' ) );
+	stylesProcessor.setNormalizer( 'padding-top', data => ( { path: 'padding.top', value: data.value } ) );
+	stylesProcessor.setNormalizer( 'padding-right', data => ( { path: 'padding.right', value: data.value } ) );
+	stylesProcessor.setNormalizer( 'padding-bottom', data => ( { path: 'padding.bottom', value: data.value } ) );
+	stylesProcessor.setNormalizer( 'padding-left', data => ( { path: 'padding.left', value: data.value } ) );
 
-		stylesProcessor.on( 'reduce:padding', getTopRightBottomLeftValueReducer( 'padding' ) );
-	} );
+	stylesProcessor.setReducer( 'padding', getTopRightBottomLeftValueReducer( 'padding' ) );
 }

+ 7 - 5
packages/ckeditor5-engine/src/view/styles/utils.js

@@ -65,7 +65,7 @@ export function getTopRightBottomLeftValues( value = '' ) {
 }
 
 export function getTopRightBottomLeftValueReducer( styleShorthand ) {
-	return ( evt, data ) => {
+	return data => {
 		const { top, right, bottom, left } = ( data.value || {} );
 
 		const reduced = [];
@@ -90,7 +90,7 @@ export function getTopRightBottomLeftValueReducer( styleShorthand ) {
 			reduced.push( [ styleShorthand, getTopRightBottomLeftShorthandValue( data.value ) ] );
 		}
 
-		data.reduced = reduced;
+		return reduced;
 	};
 }
 
@@ -111,9 +111,11 @@ export function getTopRightBottomLeftShorthandValue( { left, right, top, bottom
 }
 
 export function getPositionShorthandNormalizer( longhand ) {
-	return ( evt, data ) => {
-		data.path = longhand;
-		data.value = getTopRightBottomLeftValues( data.value );
+	return data => {
+		return {
+			path: longhand,
+			value: getTopRightBottomLeftValues( data.value )
+		};
 	};
 }
 

+ 8 - 8
packages/ckeditor5-engine/tests/view/styles.js

@@ -14,14 +14,14 @@ describe( 'Styles', () => {
 		converter = new StylesProcessor();
 
 		// Define simple "foo" shorthand normalizers, similar to the "margin" shorthand normalizers, for testing purposes.
-		converter.on( 'normalize:foo', ( evt, data ) => {
-			data.path = 'foo';
-			data.value = { top: data.value, right: data.value, bottom: data.value, left: data.value };
-		} );
-		converter.on( 'normalize:foo-top', ( evt, data ) => {
-			data.path = 'foo';
-			data.value = { top: data.value };
-		} );
+		converter.setNormalizer( 'foo', data => ( {
+			path: 'foo',
+			value: { top: data.value, right: data.value, bottom: data.value, left: data.value }
+		} ) );
+		converter.setNormalizer( 'foo-top', data => ( {
+			path: 'foo',
+			value: { top: data.value }
+		} ) );
 
 		addPaddingStylesProcessor( converter );
 		styles = new Styles( converter );