Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1413 from ckeditor/t/1408
Browse files Browse the repository at this point in the history
Feature: Introduce `ElementDefinition#priority` property which allows specifying the priority of created element during the downcast conversion. Closes #1408.
  • Loading branch information
scofalik committed May 15, 2018
2 parents 86521df + cdd9c92 commit e20e133
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 64 deletions.
8 changes: 4 additions & 4 deletions src/conversion/conversion.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export default class Conversion {
* conversion.elementToElement( { model: 'paragraph', view: 'p' } );
*
* // Override other converters by specifying converter definition with higher priority.
* conversion.elementToElement( { model: 'paragraph', view: 'div', priority: 'high' } );
* conversion.elementToElement( { model: 'paragraph', view: 'div', converterPriority: 'high' } );
*
* // View specified as an object instead of a string.
* conversion.elementToElement( {
Expand Down Expand Up @@ -237,7 +237,7 @@ export default class Conversion {
upcastElementToElement( {
model,
view,
priority: definition.priority
converterPriority: definition.converterPriority
} )
);
}
Expand All @@ -251,7 +251,7 @@ export default class Conversion {
* conversion.attributeToElement( { model: 'bold', view: 'strong' } );
*
* // Override other converters by specifying converter definition with higher priority.
* conversion.attributeToElement( { model: 'bold', view: 'b', priority: 'high' } );
* conversion.attributeToElement( { model: 'bold', view: 'b', converterPriority: 'high' } );
*
* // View specified as an object instead of a string.
* conversion.attributeToElement( {
Expand Down Expand Up @@ -579,7 +579,7 @@ export default class Conversion {
* Any view element matching `upcastAlso` will also be converted to model. If `model` describes multiple values, `upcastAlso`
* is an object that assigns those values (`upcastAlso` object keys) to {@link module:engine/view/matcher~MatcherPattern}s
* (`upcastAlso` object values).
* @property {module:utils/priorities~PriorityString} [priority] Conversion priority.
* @property {module:utils/priorities~PriorityString} [converterPriority] Converter priority.
*/

// Helper function for `Conversion` `.add()` method.
Expand Down
45 changes: 25 additions & 20 deletions src/conversion/downcast-converters.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import cloneDeep from '@ckeditor/ckeditor5-utils/src/lib/lodash/cloneDeep';
*
* downcastElementToElement( { model: 'paragraph', view: 'p' } );
*
* downcastElementToElement( { model: 'paragraph', view: 'div', priority: 'high' } );
* downcastElementToElement( { model: 'paragraph', view: 'div', converterPriority: 'high' } );
*
* downcastElementToElement( {
* model: 'fancyParagraph',
Expand Down Expand Up @@ -55,7 +55,7 @@ export function downcastElementToElement( config ) {
config.view = _normalizeToElementConfig( config.view, 'container' );

return dispatcher => {
dispatcher.on( 'insert:' + config.model, insertElement( config.view ), { priority: config.priority || 'normal' } );
dispatcher.on( 'insert:' + config.model, insertElement( config.view ), { priority: config.converterPriority || 'normal' } );
};
}

Expand All @@ -67,7 +67,7 @@ export function downcastElementToElement( config ) {
*
* downcastAttributeToElement( { model: 'bold', view: 'strong' } );
*
* downcastAttributeToElement( { model: 'bold', view: 'b', priority: 'high' } );
* downcastAttributeToElement( { model: 'bold', view: 'b', converterPriority: 'high' } );
*
* downcastAttributeToElement( {
* model: 'invert',
Expand Down Expand Up @@ -123,7 +123,7 @@ export function downcastElementToElement( config ) {
* @param {module:engine/view/elementdefinition~ElementDefinition|Function|Object} config.view View element definition or a function
* that takes model attribute value and view writer as parameters and returns a view attribute element. If `config.model.values` is
* given, `config.view` should be an object assigning values from `config.model.values` to view element definitions or functions.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function downcastAttributeToElement( config ) {
Expand All @@ -147,7 +147,7 @@ export function downcastAttributeToElement( config ) {
const elementCreator = _getFromAttributeCreator( config );

return dispatcher => {
dispatcher.on( eventName, wrap( elementCreator ), { priority: config.priority || 'normal' } );
dispatcher.on( eventName, wrap( elementCreator ), { priority: config.converterPriority || 'normal' } );
};
}

Expand All @@ -159,7 +159,7 @@ export function downcastAttributeToElement( config ) {
*
* downcastAttributeToAttribute( { model: 'source', view: 'src' } );
*
* downcastAttributeToAttribute( { model: 'source', view: 'href', priority: 'high' } );
* downcastAttributeToAttribute( { model: 'source', view: 'href', converterPriority: 'high' } );
*
* downcastAttributeToAttribute( {
* model: {
Expand Down Expand Up @@ -201,7 +201,7 @@ export function downcastAttributeToElement( config ) {
* array of `String`s. If `key` is `'style'`, `value` is an object with key-value pairs. In other cases, `value` is a `String`.
* If `config.model.values` is set, `config.view` should be an object assigning values from `config.model.values` to
* `{ key, value }` objects or a functions.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function downcastAttributeToAttribute( config ) {
Expand All @@ -225,7 +225,7 @@ export function downcastAttributeToAttribute( config ) {
const elementCreator = _getFromAttributeCreator( config );

return dispatcher => {
dispatcher.on( eventName, changeAttribute( elementCreator ), { priority: config.priority || 'normal' } );
dispatcher.on( eventName, changeAttribute( elementCreator ), { priority: config.converterPriority || 'normal' } );
};
}

Expand All @@ -238,7 +238,7 @@ export function downcastAttributeToAttribute( config ) {
*
* downcastMarkerToElement( { model: 'search', view: 'marker-search' } );
*
* downcastMarkerToElement( { model: 'search', view: 'search-result', priority: 'high' } );
* downcastMarkerToElement( { model: 'search', view: 'search-result', converterPriority: 'high' } );
*
* downcastMarkerToElement( {
* model: 'search',
Expand Down Expand Up @@ -272,7 +272,7 @@ export function downcastAttributeToAttribute( config ) {
* @param {String} config.model Name of the model marker (or model marker group) to convert.
* @param {module:engine/view/elementdefinition~ElementDefinition|Function} config.view View element definition or a function
* that takes model marker data as a parameter and returns view ui element.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function downcastMarkerToElement( config ) {
Expand All @@ -281,8 +281,8 @@ export function downcastMarkerToElement( config ) {
config.view = _normalizeToElementConfig( config.view, 'ui' );

return dispatcher => {
dispatcher.on( 'addMarker:' + config.model, insertUIElement( config.view ), { priority: config.priority || 'normal' } );
dispatcher.on( 'removeMarker:' + config.model, removeUIElement( config.view ), { priority: config.priority || 'normal' } );
dispatcher.on( 'addMarker:' + config.model, insertUIElement( config.view ), { priority: config.converterPriority || 'normal' } );
dispatcher.on( 'removeMarker:' + config.model, removeUIElement( config.view ), { priority: config.converterPriority || 'normal' } );
};
}

Expand All @@ -307,7 +307,7 @@ export function downcastMarkerToElement( config ) {
*
* downcastMarkerToHighlight( { model: 'comment', view: { classes: 'comment' } } );
*
* downcastMarkerToHighlight( { model: 'comment', view: { classes: 'new-comment' }, priority: 'high' } );
* downcastMarkerToHighlight( { model: 'comment', view: { classes: 'new-comment' }, converterPriority: 'high' } );
*
* downcastMarkerToHighlight( {
* model: 'comment',
Expand All @@ -331,14 +331,14 @@ export function downcastMarkerToElement( config ) {
* @param {String} config.model Name of the model marker (or model marker group) to convert.
* @param {module:engine/conversion/downcast-converters~HighlightDescriptor|Function} config.view Highlight descriptor
* which will be used for highlighting or a function that takes model marker data as a parameter and returns a highlight descriptor.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function downcastMarkerToHighlight( config ) {
return dispatcher => {
dispatcher.on( 'addMarker:' + config.model, highlightText( config.view ), { priority: config.priority || 'normal' } );
dispatcher.on( 'addMarker:' + config.model, highlightElement( config.view ), { priority: config.priority || 'normal' } );
dispatcher.on( 'removeMarker:' + config.model, removeHighlight( config.view ), { priority: config.priority || 'normal' } );
dispatcher.on( 'addMarker:' + config.model, highlightText( config.view ), { priority: config.converterPriority || 'normal' } );
dispatcher.on( 'addMarker:' + config.model, highlightElement( config.view ), { priority: config.converterPriority || 'normal' } );
dispatcher.on( 'removeMarker:' + config.model, removeHighlight( config.view ), { priority: config.converterPriority || 'normal' } );
};
}

Expand Down Expand Up @@ -370,14 +370,19 @@ function _createViewElementFromDefinition( viewElementDefinition, viewWriter, vi
}

let element;
const attributes = Object.assign( {}, viewElementDefinition.attributes );

if ( viewElementType == 'container' ) {
element = viewWriter.createContainerElement( viewElementDefinition.name, Object.assign( {}, viewElementDefinition.attributes ) );
element = viewWriter.createContainerElement( viewElementDefinition.name, attributes );
} else if ( viewElementType == 'attribute' ) {
element = viewWriter.createAttributeElement( viewElementDefinition.name, Object.assign( {}, viewElementDefinition.attributes ) );
const options = {
priority: viewElementDefinition.priority || ViewAttributeElement.DEFAULT_PRIORITY
};

element = viewWriter.createAttributeElement( viewElementDefinition.name, attributes, options );
} else {
// 'ui'.
element = viewWriter.createUIElement( viewElementDefinition.name, Object.assign( {}, viewElementDefinition.attributes ) );
element = viewWriter.createUIElement( viewElementDefinition.name, attributes );
}

if ( viewElementDefinition.styles ) {
Expand Down
22 changes: 11 additions & 11 deletions src/conversion/upcast-converters.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import cloneDeep from '@ckeditor/ckeditor5-utils/src/lib/lodash/cloneDeep';
*
* upcastElementToElement( { view: 'p', model: 'paragraph' } );
*
* upcastElementToElement( { view: 'p', model: 'paragraph', priority: 'high' } );
* upcastElementToElement( { view: 'p', model: 'paragraph', converterPriority: 'high' } );
*
* upcastElementToElement( {
* view: {
Expand All @@ -52,7 +52,7 @@ import cloneDeep from '@ckeditor/ckeditor5-utils/src/lib/lodash/cloneDeep';
* @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.
* @param {String|module:engine/model/element~Element|Function} config.model Name of the model element, a model element
* instance or a function that takes a view element and returns a model element. The model element will be inserted in the model.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function upcastElementToElement( config ) {
Expand All @@ -64,7 +64,7 @@ export function upcastElementToElement( config ) {
const eventName = elementName ? 'element:' + elementName : 'element';

return dispatcher => {
dispatcher.on( eventName, converter, { priority: config.priority || 'normal' } );
dispatcher.on( eventName, converter, { priority: config.converterPriority || 'normal' } );
};
}

Expand All @@ -78,7 +78,7 @@ export function upcastElementToElement( config ) {
*
* upcastElementToAttribute( { view: 'strong', model: 'bold' } );
*
* upcastElementToAttribute( { view: 'strong', model: 'bold', priority: 'high' } );
* upcastElementToAttribute( { view: 'strong', model: 'bold', converterPriority: 'high' } );
*
* upcastElementToAttribute( {
* view: {
Expand Down Expand Up @@ -130,7 +130,7 @@ export function upcastElementToElement( config ) {
* @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing
* the model attribute. `value` property may be set as a function that takes a view element and returns the value.
* If `String` is given, the model attribute value will be set to `true`.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function upcastElementToAttribute( config ) {
Expand All @@ -144,7 +144,7 @@ export function upcastElementToAttribute( config ) {
const eventName = elementName ? 'element:' + elementName : 'element';

return dispatcher => {
dispatcher.on( eventName, converter, { priority: config.priority || 'normal' } );
dispatcher.on( eventName, converter, { priority: config.converterPriority || 'normal' } );
};
}

Expand All @@ -160,7 +160,7 @@ export function upcastElementToAttribute( config ) {
*
* upcastAttributeToAttribute( { view: { key: 'src' }, model: 'source' } );
*
* upcastAttributeToAttribute( { view: { key: 'src' }, model: 'source', priority: 'normal' } );
* upcastAttributeToAttribute( { view: { key: 'src' }, model: 'source', converterPriority: 'normal' } );
*
* upcastAttributeToAttribute( {
* view: {
Expand Down Expand Up @@ -209,7 +209,7 @@ export function upcastElementToAttribute( config ) {
* @param {String|Object} config.model Model attribute key or an object with `key` and `value` properties, describing
* the model attribute. `value` property may be set as a function that takes a view element and returns the value.
* If `String` is given, the model attribute value will be same as view attribute value.
* @param {module:utils/priorities~PriorityString} [config.priority='low'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='low'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function upcastAttributeToAttribute( config ) {
Expand All @@ -226,7 +226,7 @@ export function upcastAttributeToAttribute( config ) {
const converter = _prepareToAttributeConverter( config );

return dispatcher => {
dispatcher.on( 'element', converter, { priority: config.priority || 'low' } );
dispatcher.on( 'element', converter, { priority: config.converterPriority || 'low' } );
};
}

Expand All @@ -240,7 +240,7 @@ export function upcastAttributeToAttribute( config ) {
*
* upcastElementToMarker( { view: 'marker-search', model: 'search' } );
*
* upcastElementToMarker( { view: 'marker-search', model: 'search', priority: 'high' } );
* upcastElementToMarker( { view: 'marker-search', model: 'search', converterPriority: 'high' } );
*
* upcastElementToMarker( {
* view: 'marker-search',
Expand All @@ -263,7 +263,7 @@ export function upcastAttributeToAttribute( config ) {
* @param {module:engine/view/matcher~MatcherPattern} config.view Pattern matching all view elements which should be converted.
* @param {String|Function} config.model Name of the model marker, or a function that takes a view element and returns
* a model marker name.
* @param {module:utils/priorities~PriorityString} [config.priority='normal'] Converter priority.
* @param {module:utils/priorities~PriorityString} [config.converterPriority='normal'] Converter priority.
* @returns {Function} Conversion helper.
*/
export function upcastElementToMarker( config ) {
Expand Down
1 change: 1 addition & 0 deletions src/view/elementdefinition.jsdoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@
* Value under that key must be a string.
* @property {Object} [attributes] Object with key-value pairs representing attributes. Each object key represents
* attribute name. Value under that key must be a string.
* @property {Number} [priority] Element's {@link module:engine/view/attributeelement~AttributeElement#priority priority}.
*/
8 changes: 4 additions & 4 deletions tests/conversion/conversion.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ describe( 'Conversion', () => {
test( '<p>Foo</p>', '<paragraph>Foo</paragraph>' );
} );

it( 'config.priority is defined', () => {
it( 'config.converterPriority is defined', () => {
conversion.elementToElement( { model: 'paragraph', view: 'p' } );
conversion.elementToElement( { model: 'paragraph', view: 'div', priority: 'high' } );
conversion.elementToElement( { model: 'paragraph', view: 'div', converterPriority: 'high' } );

test( '<div>Foo</div>', '<paragraph>Foo</paragraph>' );
test( '<p>Foo</p>', '<paragraph>Foo</paragraph>', '<div>Foo</div>' );
Expand Down Expand Up @@ -224,9 +224,9 @@ describe( 'Conversion', () => {
test( '<p><strong>Foo</strong> bar</p>', '<paragraph><$text bold="true">Foo</$text> bar</paragraph>' );
} );

it( 'config.priority is defined', () => {
it( 'config.converterPriority is defined', () => {
conversion.attributeToElement( { model: 'bold', view: 'strong' } );
conversion.attributeToElement( { model: 'bold', view: 'b', priority: 'high' } );
conversion.attributeToElement( { model: 'bold', view: 'b', converterPriority: 'high' } );

test( '<p><b>Foo</b></p>', '<paragraph><$text bold="true">Foo</$text></paragraph>' );
test( '<p><strong>Foo</strong></p>', '<paragraph><$text bold="true">Foo</$text></paragraph>', '<p><b>Foo</b></p>' );
Expand Down
Loading

0 comments on commit e20e133

Please sign in to comment.