From 6b2541ae2a7d0e395c54e990eefce63d4a736a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Go=C5=82aszewski?= Date: Wed, 2 Jan 2019 12:39:35 +0100 Subject: [PATCH 1/3] Expose `insertElement()` conversion helper as a protected export. --- src/conversion/downcasthelpers.js | 51 ++++++++++++++++--------------- src/dev-utils/model.js | 19 ++++-------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/src/conversion/downcasthelpers.js b/src/conversion/downcasthelpers.js index 2f76e8069..a838f29e3 100644 --- a/src/conversion/downcasthelpers.js +++ b/src/conversion/downcasthelpers.js @@ -490,30 +490,33 @@ export function wrap( elementCreator ) { }; } -// Function factory that creates a converter which converts node insertion changes from the model to the view. -// The function passed will be provided with all the parameters of the dispatcher's -// {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert `insert` event}. -// It is expected that the function returns an {@link module:engine/view/element~Element}. -// The result of the function will be inserted into the view. -// -// The converter automatically consumes the corresponding value from the consumables list, stops the event (see -// {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}) and binds the model and view elements. -// -// downcastDispatcher.on( -// 'insert:myElem', -// insertElement( ( modelItem, viewWriter ) => { -// const text = viewWriter.createText( 'myText' ); -// const myElem = viewWriter.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text ); -// -// // Do something fancy with `myElem` using `modelItem` or other parameters. -// -// return myElem; -// } -// ) ); -// -// @param {Function} elementCreator Function returning a view element, which will be inserted. -// @returns {Function} Insert element event converter. -function insertElement( elementCreator ) { +/** + * Function factory that creates a converter which converts node insertion changes from the model to the view. + * The function passed will be provided with all the parameters of the dispatcher's + * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:insert `insert` event}. + * It is expected that the function returns an {@link module:engine/view/element~Element}. + * The result of the function will be inserted into the view. + * + * The converter automatically consumes the corresponding value from the consumables list, stops the event (see + * {@link module:engine/conversion/downcastdispatcher~DowncastDispatcher}) and binds the model and view elements. + * + * downcastDispatcher.on( + * 'insert:myElem', + * insertElement( ( modelItem, viewWriter ) => { + * const text = viewWriter.createText( 'myText' ); + * const myElem = viewWriter.createElement( 'myElem', { myAttr: 'my-' + modelItem.getAttribute( 'myAttr' ) }, text ); + * + * // Do something fancy with `myElem` using `modelItem` or other parameters. + * + * return myElem; + * } + * ) ); + * + * @protected + * @param {Function} elementCreator Function returning a view element, which will be inserted. + * @returns {Function} Insert element event converter. + */ +export function insertElement( elementCreator ) { return ( evt, data, conversionApi ) => { const viewElement = elementCreator( data.item, conversionApi.writer ); diff --git a/src/dev-utils/model.js b/src/dev-utils/model.js index 2289c34d8..4638f7c02 100644 --- a/src/dev-utils/model.js +++ b/src/dev-utils/model.js @@ -32,7 +32,7 @@ import { convertRangeSelection, convertCollapsedSelection, } from '../conversion/downcast-selection-converters'; -import { insertText, wrap } from '../conversion/downcasthelpers'; +import { insertElement, insertText, wrap } from '../conversion/downcasthelpers'; import { isPlainObject } from 'lodash-es'; import toMap from '@ckeditor/ckeditor5-utils/src/tomap'; @@ -225,19 +225,12 @@ export function stringify( node, selectionOrPositionOrRange = null, markers = nu converter( evt, data, conversionApi ); } } ); - downcastDispatcher.on( 'insert', ( evt, data, conversionApi ) => { - const attributes = convertAttributes( data.item.getAttributes(), stringifyAttributeValue ); - const viewElement = new ViewContainerElement( data.item.name, attributes ); + downcastDispatcher.on( 'insert', insertElement( modelItem => { + // Stringify object types values for properly display as an output string. + const attributes = convertAttributes( modelItem.getAttributes(), stringifyAttributeValue ); - if ( !conversionApi.consumable.consume( data.item, 'insert' ) ) { - return; - } - - const viewPosition = conversionApi.mapper.toViewPosition( data.range.start ); - - conversionApi.mapper.bindElements( data.item, viewElement ); - conversionApi.writer.insert( viewPosition, viewElement ); - } ); + return new ViewContainerElement( modelItem.name, attributes ); + } ) ); downcastDispatcher.on( 'selection', convertRangeSelection() ); downcastDispatcher.on( 'selection', convertCollapsedSelection() ); From ed98b60e0ec61ed53f76849a62724cbc214a7c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Go=C5=82aszewski?= Date: Wed, 2 Jan 2019 12:42:35 +0100 Subject: [PATCH 2/3] Expose `insertUIElement()` conversion helper as a protected export. --- src/conversion/downcasthelpers.js | 28 +++++++++++---------- src/dev-utils/model.js | 42 ++++--------------------------- 2 files changed, 20 insertions(+), 50 deletions(-) diff --git a/src/conversion/downcasthelpers.js b/src/conversion/downcasthelpers.js index a838f29e3..9b5248cf3 100644 --- a/src/conversion/downcasthelpers.js +++ b/src/conversion/downcasthelpers.js @@ -535,19 +535,21 @@ export function insertElement( elementCreator ) { }; } -// Function factory that creates a converter which converts marker adding change to the -// {@link module:engine/view/uielement~UIElement view UI element}. -// -// The view UI element that will be added to the view depends on the passed parameter. See {@link ~insertElement}. -// In case of a non-collapsed range, the UI element will not wrap nodes but separate elements will be placed at the beginning -// and at the end of the range. -// -// This converter binds created UI elements with the marker name using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}. -// -// @param {module:engine/view/uielement~UIElement|Function} elementCreator A view UI element or a function returning the view element -// that will be inserted. -// @returns {Function} Insert element event converter. -function insertUIElement( elementCreator ) { +/** + * Function factory that creates a converter which converts marker adding change to the + * {@link module:engine/view/uielement~UIElement view UI element}. + * + * The view UI element that will be added to the view depends on the passed parameter. See {@link ~insertElement}. + * In case of a non-collapsed range, the UI element will not wrap nodes but separate elements will be placed at the beginning + * and at the end of the range. + * + * This converter binds created UI elements with the marker name using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}. + * + * @param {module:engine/view/uielement~UIElement|Function} elementCreator A view UI element or a function returning the view element + * that will be inserted. + * @returns {Function} Insert element event converter. + */ +export function insertUIElement( elementCreator ) { return ( evt, data, conversionApi ) => { // Create two view elements. One will be inserted at the beginning of marker, one at the end. // If marker is collapsed, only "opening" element will be inserted. diff --git a/src/dev-utils/model.js b/src/dev-utils/model.js index 4638f7c02..4427c4097 100644 --- a/src/dev-utils/model.js +++ b/src/dev-utils/model.js @@ -32,7 +32,7 @@ import { convertRangeSelection, convertCollapsedSelection, } from '../conversion/downcast-selection-converters'; -import { insertElement, insertText, wrap } from '../conversion/downcasthelpers'; +import { insertElement, insertText, insertUIElement, wrap } from '../conversion/downcasthelpers'; import { isPlainObject } from 'lodash-es'; import toMap from '@ckeditor/ckeditor5-utils/src/tomap'; @@ -234,43 +234,11 @@ export function stringify( node, selectionOrPositionOrRange = null, markers = nu downcastDispatcher.on( 'selection', convertRangeSelection() ); downcastDispatcher.on( 'selection', convertCollapsedSelection() ); - downcastDispatcher.on( 'addMarker', ( evt, data, conversionApi ) => { - const elementCreator = ( data, writer ) => { - const name = data.markerName + ':' + ( data.isOpening ? 'start' : 'end' ); + downcastDispatcher.on( 'addMarker', insertUIElement( ( data, writer ) => { + const name = data.markerName + ':' + ( data.isOpening ? 'start' : 'end' ); - return writer.createUIElement( name ); - }; - - // Create two view elements. One will be inserted at the beginning of marker, one at the end. - // If marker is collapsed, only "opening" element will be inserted. - data.isOpening = true; - const viewStartElement = elementCreator( data, conversionApi.writer ); - - data.isOpening = false; - const viewEndElement = elementCreator( data, conversionApi.writer ); - - const markerRange = data.markerRange; - - // If marker's range is not collapsed - consume all items inside. - for ( const value of markerRange ) { - conversionApi.consumable.consume( value.item, evt.name ); - } - - const mapper = conversionApi.mapper; - const viewWriter = conversionApi.writer; - - // Add "opening" element. - viewWriter.insert( mapper.toViewPosition( markerRange.start ), viewStartElement ); - conversionApi.mapper.bindElementToMarker( viewStartElement, data.markerName ); - - // Add "closing" element only if range is not collapsed. - if ( !markerRange.isCollapsed ) { - viewWriter.insert( mapper.toViewPosition( markerRange.end ), viewEndElement ); - conversionApi.mapper.bindElementToMarker( viewEndElement, data.markerName ); - } - - evt.stop(); - } ); + return writer.createUIElement( name ); + } ) ); // Convert model to view. const writer = view._writer; From e4460dbd7853ef0c0f14d771805ca41b120caafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Go=C5=82aszewski?= Date: Wed, 2 Jan 2019 12:55:48 +0100 Subject: [PATCH 3/3] Add missing @protected annotation to insertUIElement function. --- src/conversion/downcasthelpers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/conversion/downcasthelpers.js b/src/conversion/downcasthelpers.js index 9b5248cf3..97dc6e241 100644 --- a/src/conversion/downcasthelpers.js +++ b/src/conversion/downcasthelpers.js @@ -545,6 +545,7 @@ export function insertElement( elementCreator ) { * * This converter binds created UI elements with the marker name using {@link module:engine/conversion/mapper~Mapper#bindElementToMarker}. * + * @protected * @param {module:engine/view/uielement~UIElement|Function} elementCreator A view UI element or a function returning the view element * that will be inserted. * @returns {Function} Insert element event converter.