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

Commit 131e9c8

Browse files
author
Piotr Jasiun
authored
Merge pull request #1241 from ckeditor/t/1214
Feature: Consumable type name is now normalized inside `conversion.ModelConsumable` methods. Closes #1214.
2 parents 3f059a7 + 6e98412 commit 131e9c8

File tree

4 files changed

+68
-24
lines changed

4 files changed

+68
-24
lines changed

src/conversion/model-selection-to-view-converters.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,19 +181,18 @@ export function convertSelectionMarker( highlightDescriptor ) {
181181
}
182182

183183
const viewElement = createViewElementFromHighlightDescriptor( descriptor );
184-
const consumableName = 'selectionMarker:' + data.markerName;
185184

186-
wrapCollapsedSelectionPosition( data.selection, conversionApi.viewSelection, viewElement, consumable, consumableName );
185+
wrapCollapsedSelectionPosition( data.selection, conversionApi.viewSelection, viewElement, consumable, evt.name );
187186
};
188187
}
189188

190189
// Helper function for `convertSelectionAttribute` and `convertSelectionMarker`, which perform similar task.
191-
function wrapCollapsedSelectionPosition( modelSelection, viewSelection, viewElement, consumable, consumableName ) {
190+
function wrapCollapsedSelectionPosition( modelSelection, viewSelection, viewElement, consumable, eventName ) {
192191
if ( !modelSelection.isCollapsed ) {
193192
return;
194193
}
195194

196-
if ( !consumable.consume( modelSelection, consumableName ) ) {
195+
if ( !consumable.consume( modelSelection, eventName ) ) {
197196
return;
198197
}
199198

src/conversion/model-to-view-converters.js

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,17 @@ export function insertUIElement( elementCreator ) {
153153
}
154154

155155
const markerRange = data.markerRange;
156-
const eventName = evt.name;
157156

158157
// Marker that is collapsed has consumable build differently that non-collapsed one.
159158
// For more information see `addMarker` event description.
160159
// If marker's range is collapsed - check if it can be consumed.
161-
if ( markerRange.isCollapsed && !consumable.consume( markerRange, eventName ) ) {
160+
if ( markerRange.isCollapsed && !consumable.consume( markerRange, evt.name ) ) {
162161
return;
163162
}
164163

165164
// If marker's range is not collapsed - consume all items inside.
166165
for ( const value of markerRange ) {
167-
if ( !consumable.consume( value.item, eventName ) ) {
166+
if ( !consumable.consume( value.item, evt.name ) ) {
168167
return;
169168
}
170169
}
@@ -263,7 +262,7 @@ export function changeAttribute( attributeCreator ) {
263262
attributeCreator = attributeCreator || ( ( value, key ) => ( { value, key } ) );
264263

265264
return ( evt, data, consumable, conversionApi ) => {
266-
if ( !consumable.consume( data.item, eventNameToConsumableType( evt.name ) ) ) {
265+
if ( !consumable.consume( data.item, evt.name ) ) {
267266
return;
268267
}
269268

@@ -322,7 +321,7 @@ export function wrap( elementCreator ) {
322321
return;
323322
}
324323

325-
if ( !consumable.consume( data.item, eventNameToConsumableType( evt.name ) ) ) {
324+
if ( !consumable.consume( data.item, evt.name ) ) {
326325
return;
327326
}
328327

@@ -524,18 +523,6 @@ function _prepareDescriptor( highlightDescriptor, data, conversionApi ) {
524523
return descriptor;
525524
}
526525

527-
/**
528-
* Returns the consumable type that is to be consumed in an event, basing on that event name.
529-
*
530-
* @param {String} evtName Event name.
531-
* @returns {String} Consumable type.
532-
*/
533-
export function eventNameToConsumableType( evtName ) {
534-
const parts = evtName.split( ':' );
535-
536-
return parts[ 0 ] + ':' + parts[ 1 ];
537-
}
538-
539526
/**
540527
* Creates `span` {@link module:engine/view/attributeelement~AttributeElement view attribute element} from information
541528
* provided by {@link module:engine/conversion/model-to-view-converters~HighlightDescriptor} object. If priority

src/conversion/modelconsumable.js

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,12 @@ export default class ModelConsumable {
125125
*
126126
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
127127
* Model item, range or selection that has the consumable.
128-
* @param {String} type Consumable type.
128+
* @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
129+
* Second colon and everything after will be cut. Passing event name is a safe and good practice.
129130
*/
130131
add( item, type ) {
132+
type = _normalizeConsumableType( type );
133+
131134
if ( item instanceof TextProxy ) {
132135
item = this._getSymbolForTextProxy( item );
133136
}
@@ -151,10 +154,13 @@ export default class ModelConsumable {
151154
*
152155
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
153156
* Model item, range or selection from which consumable will be consumed.
154-
* @param {String} type Consumable type.
157+
* @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
158+
* Second colon and everything after will be cut. Passing event name is a safe and good practice.
155159
* @returns {Boolean} `true` if consumable value was available and was consumed, `false` otherwise.
156160
*/
157161
consume( item, type ) {
162+
type = _normalizeConsumableType( type );
163+
158164
if ( item instanceof TextProxy ) {
159165
item = this._getSymbolForTextProxy( item );
160166
}
@@ -180,11 +186,14 @@ export default class ModelConsumable {
180186
*
181187
* @param {module:engine/model/item~Item|module:engine/model/selection~Selection|module:engine/model/range~Range} item
182188
* Model item, range or selection to be tested.
183-
* @param {String} type Consumable type.
189+
* @param {String} type Consumable type. Will be normalized to a proper form, that is either `<word>` or `<part>:<part>`.
190+
* Second colon and everything after will be cut. Passing event name is a safe and good practice.
184191
* @returns {null|Boolean} `null` if such consumable was never added, `false` if the consumable values was
185192
* already consumed or `true` if it was added and not consumed yet.
186193
*/
187194
test( item, type ) {
195+
type = _normalizeConsumableType( type );
196+
188197
if ( item instanceof TextProxy ) {
189198
item = this._getSymbolForTextProxy( item );
190199
}
@@ -221,6 +230,8 @@ export default class ModelConsumable {
221230
* never been added.
222231
*/
223232
revert( item, type ) {
233+
type = _normalizeConsumableType( type );
234+
224235
if ( item instanceof TextProxy ) {
225236
item = this._getSymbolForTextProxy( item );
226237
}
@@ -302,3 +313,15 @@ export default class ModelConsumable {
302313
return symbol;
303314
}
304315
}
316+
317+
// Returns a normalized consumable type name from given string. A normalized consumable type name is a string that has
318+
// at most one colon, for example: `insert` or `addMarker:highlight`. If string to normalize has more "parts" (more colons),
319+
// the other parts are dropped, for example: `addAttribute:bold:$text` -> `addAttribute:bold`.
320+
//
321+
// @param {String} type Consumable type.
322+
// @returns {String} Normalized consumable type.
323+
function _normalizeConsumableType( type ) {
324+
const parts = type.split( ':' );
325+
326+
return parts.length > 1 ? parts[ 0 ] + ':' + parts[ 1 ] : parts[ 0 ];
327+
}

tests/conversion/modelconsumable.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ describe( 'ModelConsumable', () => {
4040

4141
expect( modelConsumable.test( modelTextProxy, 'type' ) ).to.be.true;
4242
} );
43+
44+
it( 'should normalize type name', () => {
45+
modelConsumable.add( modelElement, 'foo:bar:baz:abc' );
46+
47+
expect( modelConsumable.test( modelElement, 'foo:bar:baz:abc' ) ).to.be.true;
48+
expect( modelConsumable.test( modelElement, 'foo:bar:baz' ) ).to.be.true;
49+
expect( modelConsumable.test( modelElement, 'foo:bar' ) ).to.be.true;
50+
expect( modelConsumable.test( modelElement, 'foo:bar:xxx' ) ).to.be.true;
51+
52+
expect( modelConsumable.test( modelElement, 'foo:xxx' ) ).to.be.null;
53+
} );
4354
} );
4455

4556
describe( 'consume', () => {
@@ -74,6 +85,17 @@ describe( 'ModelConsumable', () => {
7485
expect( result ).to.be.true;
7586
expect( modelConsumable.test( proxy1To4, 'type' ) ).to.be.false;
7687
} );
88+
89+
it( 'should normalize type name', () => {
90+
modelConsumable.add( modelElement, 'foo:bar:baz:abc' );
91+
const result = modelConsumable.consume( modelElement, 'foo:bar:baz' );
92+
93+
expect( result ).to.be.true;
94+
95+
expect( modelConsumable.test( modelElement, 'foo:bar:baz:abc' ) ).to.be.false;
96+
expect( modelConsumable.test( modelElement, 'foo:bar:baz' ) ).to.be.false;
97+
expect( modelConsumable.test( modelElement, 'foo:bar' ) ).to.be.false;
98+
} );
7799
} );
78100

79101
describe( 'revert', () => {
@@ -112,6 +134,19 @@ describe( 'ModelConsumable', () => {
112134
expect( result ).to.be.true;
113135
expect( modelConsumable.test( modelTextProxy, 'type' ) ).to.be.true;
114136
} );
137+
138+
it( 'should normalize type name', () => {
139+
modelConsumable.add( modelElement, 'foo:bar:baz:abc' );
140+
modelConsumable.consume( modelElement, 'foo:bar:baz' );
141+
142+
const result = modelConsumable.revert( modelElement, 'foo:bar:baz' );
143+
144+
expect( result ).to.be.true;
145+
146+
expect( modelConsumable.test( modelElement, 'foo:bar:baz:abc' ) ).to.be.true;
147+
expect( modelConsumable.test( modelElement, 'foo:bar:baz' ) ).to.be.true;
148+
expect( modelConsumable.test( modelElement, 'foo:bar' ) ).to.be.true;
149+
} );
115150
} );
116151

117152
describe( 'test', () => {

0 commit comments

Comments
 (0)