ModelConsumable
Manages a list of consumable values for the model items.
Consumables are various aspects of the model. A model item can be broken down into separate, single properties that might be taken into consideration when converting that item.
ModelConsumable is used by DowncastDispatcher while analyzing the changed parts of the document. The added / changed / removed model items are broken down into singular properties (the item itself and its attributes). All those parts are saved in ModelConsumable. Then, during conversion, when the given part of a model item is converted (i.e. the view element has been inserted into the view, but without attributes), the consumable value is removed from ModelConsumable.
For model items, ModelConsumable stores consumable values of one of following types: insert, addattribute:<attributeKey>, changeattributes:<attributeKey>, removeattributes:<attributeKey>.
In most cases, it is enough to let th DowncastDispatcher gather consumable values, so there is no need to use the add method directly. However, it is important to understand how consumable values can be consumed. See default downcast converters for more information.
Keep in mind that one conversion event may have multiple callbacks (converters) attached to it. Each of those is able to convert one or more parts of the model. However, when one of those callbacks actually converts something, the others should not, because they would duplicate the results. Using ModelConsumable helps to avoid this situation, because callbacks should only convert these values that were not yet consumed from ModelConsumable.
Consuming multiple values in a single callback:
// Converter for custom `imageBlock` element that might have a `caption` element inside which changes
// how the image is displayed in the view:
//
// Model:
//
// [imageBlock]
// └─ [caption]
// └─ foo
//
// View:
//
// <figure>
// ├─ <img />
// └─ <caption>
// └─ foo
modelConversionDispatcher.on( 'insert:imageBlock', ( evt, data, conversionApi ) => {
// First, consume the `imageBlock` element.
conversionApi.consumable.consume( data.item, 'insert' );
// Just create normal image element for the view.
// Maybe it will be "decorated" later.
const viewImage = new ViewElement( 'img' );
const insertPosition = conversionApi.mapper.toViewPosition( data.range.start );
const viewWriter = conversionApi.writer;
// Check if the `imageBlock` element has children.
if ( data.item.childCount > 0 ) {
const modelCaption = data.item.getChild( 0 );
// `modelCaption` insertion change is consumed from consumable values.
// It will not be converted by other converters, but it's children (probably some text) will be.
// Through mapping, converters for text will know where to insert contents of `modelCaption`.
if ( conversionApi.consumable.consume( modelCaption, 'insert' ) ) {
const viewCaption = new ViewElement( 'figcaption' );
const viewImageHolder = new ViewElement( 'figure', null, [ viewImage, viewCaption ] );
conversionApi.mapper.bindElements( modelCaption, viewCaption );
conversionApi.mapper.bindElements( data.item, viewImageHolder );
viewWriter.insert( insertPosition, viewImageHolder );
}
} else {
conversionApi.mapper.bindElements( data.item, viewImage );
viewWriter.insert( insertPosition, viewImage );
}
evt.stop();
} );
Properties
_consumable : Map<any, Map<string, boolean>>privatemodule:engine/conversion/modelconsumable~ModelConsumable#_consumableContains list of consumable values.
_textProxyRegistry : Map<null | number, Map<null | number, Map<unknown, symbol>>>privatemodule:engine/conversion/modelconsumable~ModelConsumable#_textProxyRegistryFor each
ModelTextProxyadded toModelConsumable, this registry holds a parent of thatModelTextProxyand the start and end indices of thatModelTextProxy. This allows identification of theModelTextProxyinstances that point to the same part of the model but are different instances. Each distinctModelTextProxyis given a uniqueSymbolwhich is then registered as consumable. This process is transparent for theModelConsumableAPI user because wheneverModelTextProxyis added, tested, consumed or reverted, the internal mechanisms ofModelConsumabletranslateModelTextProxyto that uniqueSymbol.
Methods
add( item, type ) → voidmodule:engine/conversion/modelconsumable~ModelConsumable#addAdds a consumable value to the consumables list and links it with a given model item.
modelConsumable.add( modelElement, 'insert' ); // Add `modelElement` insertion change to consumable values. modelConsumable.add( modelElement, 'addAttribute:bold' ); // Add `bold` attribute insertion on `modelElement` change. modelConsumable.add( modelElement, 'removeAttribute:bold' ); // Add `bold` attribute removal on `modelElement` change. modelConsumable.add( modelSelection, 'selection' ); // Add `modelSelection` to consumable values. modelConsumable.add( modelRange, 'range' ); // Add `modelRange` to consumable values.Copy codeParameters
item : ModelRange | ModelSelection | ModelDocumentSelection | ModelItemModel item, range or selection that has the consumable.
type : stringConsumable type. Will be normalized to a proper form, that is either
<word>or<part>:<part>. Second colon and everything after will be cut. Passing event name is a safe and good practice.
Returns
void
consume( item, type ) → booleanmodule:engine/conversion/modelconsumable~ModelConsumable#consumeRemoves a given consumable value from a given model item.
modelConsumable.consume( modelElement, 'insert' ); // Remove `modelElement` insertion change from consumable values. modelConsumable.consume( modelElement, 'addAttribute:bold' ); // Remove `bold` attribute insertion on `modelElement` change. modelConsumable.consume( modelElement, 'removeAttribute:bold' ); // Remove `bold` attribute removal on `modelElement` change. modelConsumable.consume( modelSelection, 'selection' ); // Remove `modelSelection` from consumable values. modelConsumable.consume( modelRange, 'range' ); // Remove 'modelRange' from consumable values.Copy codeParameters
item : ModelRange | ModelSelection | ModelDocumentSelection | ModelItemModel item, range or selection from which consumable will be consumed.
type : stringConsumable type. Will be normalized to a proper form, that is either
<word>or<part>:<part>. Second colon and everything after will be cut. Passing event name is a safe and good practice.
Returns
booleantrueif consumable value was available and was consumed,falseotherwise.
revert( item, type ) → null | booleanmodule:engine/conversion/modelconsumable~ModelConsumable#revertReverts consuming of a consumable value.
modelConsumable.revert( modelElement, 'insert' ); // Revert consuming `modelElement` insertion change. modelConsumable.revert( modelElement, 'addAttribute:bold' ); // Revert consuming `bold` attribute insert from `modelElement`. modelConsumable.revert( modelElement, 'removeAttribute:bold' ); // Revert consuming `bold` attribute remove from `modelElement`. modelConsumable.revert( modelSelection, 'selection' ); // Revert consuming `modelSelection`. modelConsumable.revert( modelRange, 'range' ); // Revert consuming `modelRange`.Copy codeParameters
item : ModelRange | ModelSelection | ModelDocumentSelection | ModelItemModel item, range or selection to be reverted.
type : stringConsumable type.
Returns
null | booleantrueif consumable has been reversed,falseotherwise.nullif the consumable has never been added.
test( item, type ) → null | booleanmodule:engine/conversion/modelconsumable~ModelConsumable#testTests whether there is a consumable value of a given type connected with a given model item.
modelConsumable.test( modelElement, 'insert' ); // Check for `modelElement` insertion change. modelConsumable.test( modelElement, 'addAttribute:bold' ); // Check for `bold` attribute insertion on `modelElement` change. modelConsumable.test( modelElement, 'removeAttribute:bold' ); // Check for `bold` attribute removal on `modelElement` change. modelConsumable.test( modelSelection, 'selection' ); // Check if `modelSelection` is consumable. modelConsumable.test( modelRange, 'range' ); // Check if `modelRange` is consumable.Copy codeParameters
item : ModelRange | ModelSelection | ModelDocumentSelection | ModelItemModel item, range or selection to be tested.
type : stringConsumable type. Will be normalized to a proper form, that is either
<word>or<part>:<part>. Second colon and everything after will be cut. Passing event name is a safe and good practice.
Returns
null | booleannullif such consumable was never added,falseif the consumable values was already consumed ortrueif it was added and not consumed yet.
verifyAllConsumed( eventGroup ) → voidmodule:engine/conversion/modelconsumable~ModelConsumable#verifyAllConsumedVerifies if all events from the specified group were consumed.
Parameters
eventGroup : stringThe events group to verify.
Returns
void
_getSymbolForTextProxy( textProxy ) → symbolinternalmodule:engine/conversion/modelconsumable~ModelConsumable#_getSymbolForTextProxyGets a unique symbol for the passed
ModelTextProxyinstance. AllModelTextProxyinstances that have same parent, same start index and same end index will get the same symbol.Used internally to correctly consume
ModelTextProxyinstances.Parameters
textProxy : ModelTextProxyModelTextProxyinstance to get a symbol for.
Returns
symbolSymbol representing all equal instances of
ModelTextProxy.
_addSymbolForTextProxy( textProxy ) → symbolprivatemodule:engine/conversion/modelconsumable~ModelConsumable#_addSymbolForTextProxyAdds a symbol for the given
ModelTextProxyinstance.Used internally to correctly consume
ModelTextProxyinstances.Parameters
textProxy : ModelTextProxyText proxy instance.
Returns
symbolSymbol generated for given
ModelTextProxy.