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

Commit

Permalink
Merge branch 'master' into t/ckeditor5/645
Browse files Browse the repository at this point in the history
  • Loading branch information
oleq committed Feb 1, 2018
2 parents d41f9c3 + bc35f32 commit 378ecd4
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 161 deletions.
4 changes: 2 additions & 2 deletions src/controller/datacontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export default class DataController {
}

/**
* Returns data parsed by the {@link #processor data processor} and then
* Returns the data parsed by the {@link #processor data processor} and then
* converted by the {@link #viewToModel view-to-model converters}.
*
* @see #set
Expand All @@ -226,7 +226,7 @@ export default class DataController {
* {@link module:engine/view/documentfragment~DocumentFragment view document fragment} converted by the
* {@link #viewToModel view-to-model converters}, wrapped by {module:engine/model/documentfragment~DocumentFragment}.
*
* When marker elements were converted during the conversion process, it will be set as a DocumentFragment's
* When marker elements were converted during the conversion process, it will be set as a document fragment's
* {@link module:engine/model/documentfragment~DocumentFragment#markers static markers map}.
*
* @param {module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment} viewElementOrFragment
Expand Down
16 changes: 8 additions & 8 deletions src/conversion/buildviewconverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ class ViewConverterBuilder {
// Find allowed parent for element that we are going to insert.
// If current parent does not allow to insert element but one of the ancestors does
// then split nodes to allowed parent.
const splitResult = conversionApi.splitToAllowedParent( modelElement, data.cursorPosition );
const splitResult = conversionApi.splitToAllowedParent( modelElement, data.modelCursor );

// When there is no split result it means that we can't insert element to model tree, so let's skip it.
if ( !splitResult ) {
Expand All @@ -324,20 +324,20 @@ class ViewConverterBuilder {
// element, so we need to move range after parent of the last converted child.
// before: <allowed>[]</allowed>
// after: <allowed>[<converted><child></child></converted><child></child><converted>]</converted></allowed>
Position.createAfter( childrenResult.cursorPosition.parent )
Position.createAfter( childrenResult.modelCursor.parent )
);

// Now we need to check where the cursorPosition should be.
// Now we need to check where the modelCursor should be.
// If we had to split parent to insert our element then we want to continue conversion inside split parent.
//
// before: <allowed><notAllowed>[]</notAllowed></allowed>
// after: <allowed><notAllowed></notAllowed><converted></converted><notAllowed>[]</notAllowed></allowed>
if ( splitResult.cursorParent ) {
data.cursorPosition = Position.createAt( splitResult.cursorParent );
data.modelCursor = Position.createAt( splitResult.cursorParent );

// Otherwise just continue after inserted element.
} else {
data.cursorPosition = data.modelRange.end;
data.modelCursor = data.modelRange.end;
}

// Prevent multiple conversion if there are other correct matches.
Expand Down Expand Up @@ -389,7 +389,7 @@ class ViewConverterBuilder {
// If the range is not created yet, we will create it.
if ( !data.modelRange ) {
// Convert children and set conversion result as a current data.
data = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.cursorPosition ) );
data = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.modelCursor ) );
}

// Use attribute creator function, if provided.
Expand Down Expand Up @@ -501,9 +501,9 @@ class ViewConverterBuilder {
continue;
}

writer.insert( modelElement, data.cursorPosition );
writer.insert( modelElement, data.modelCursor );
data.modelRange = Range.createOn( modelElement );
data.cursorPosition = data.modelRange.end;
data.modelCursor = data.modelRange.end;

// Prevent multiple conversion if there are other correct matches.
break;
Expand Down
12 changes: 6 additions & 6 deletions src/conversion/view-to-model-converters.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export function convertToModelFragment() {
return ( evt, data, conversionApi ) => {
// Second argument in `consumable.consume` is discarded for ViewDocumentFragment but is needed for ViewElement.
if ( !data.modelRange && conversionApi.consumable.consume( data.viewItem, { name: true } ) ) {
data = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.cursorPosition ) );
data.cursorPosition = data.modelRange.end;
data = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.modelCursor ) );
data.modelCursor = data.modelRange.end;
}
};
}
Expand All @@ -44,14 +44,14 @@ export function convertToModelFragment() {
*/
export function convertText() {
return ( evt, data, conversionApi ) => {
if ( conversionApi.schema.checkChild( data.cursorPosition, '$text' ) ) {
if ( conversionApi.schema.checkChild( data.modelCursor, '$text' ) ) {
if ( conversionApi.consumable.consume( data.viewItem ) ) {
const text = conversionApi.writer.createText( data.viewItem.data );

conversionApi.writer.insert( text, data.cursorPosition );
conversionApi.writer.insert( text, data.modelCursor );

data.modelRange = Range.createFromPositionAndShift( data.cursorPosition, text.offsetSize );
data.cursorPosition = data.modelRange.end;
data.modelRange = Range.createFromPositionAndShift( data.modelCursor, text.offsetSize );
data.modelCursor = data.modelRange.end;
}
}
};
Expand Down
52 changes: 26 additions & 26 deletions src/conversion/viewconversiondispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
* `ViewConversionDispatcher` fires corresponding events. Special callbacks called "converters" should listen to
* `ViewConversionDispatcher` for those events.
*
* Each callback, as a first argument, is passed a special object `data` that has `viewItem`, `cursorPosition` and
* Each callback, as a first argument, is passed a special object `data` that has `viewItem`, `modelCursor` and
* `modelRange` properties. `viewItem` property contains {@link module:engine/view/node~Node view node} or
* {@link module:engine/view/documentfragment~DocumentFragment view document fragment}
* that is converted at the moment and might be handled by the callback. `modelRange` property should be used to save the result
* of conversion and is always a {@link module:engine/model/range~Range} when conversion result is correct.
* `cursorPosition` property is a {@link module:engine/model/position~Position position} on which conversion result will be inserted
* `modelCursor` property is a {@link module:engine/model/position~Position position} on which conversion result will be inserted
* and is a context according to {@link module:engine/model/schema~Schema schema} will be checked before the conversion.
* See also {@link ~ViewConversionDispatcher#convert}. It is also shared by reference by all callbacks listening to given event.
*
Expand All @@ -46,11 +46,11 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
* const paragraph = conversionApi.createElement( 'paragraph' );
*
* // Check if paragraph is allowed on current cursor position.
* if ( conversionApi.schema.checkChild( data.cursorPosition, paragraph ) ) {
* if ( conversionApi.schema.checkChild( data.modelCursor, paragraph ) ) {
* // Try to consume value from consumable list.
* if ( !conversionApi.consumable.consume( data.viewItem, { name: true } ) ) {
* // Insert paragraph on cursor position.
* conversionApi.writer.insert( paragraph, data.cursorPosition );
* conversionApi.writer.insert( paragraph, data.modelCursor );
*
* // Convert paragraph children to paragraph element.
* conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( paragraph ) );
Expand All @@ -59,7 +59,7 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
* data.modelRange = ModelRange.createOn( paragraph );
*
* // Continue conversion just after paragraph.
* data.cursorPosition = data.modelRange.end;
* data.modelCursor = data.modelRange.end;
* }
* }
* } );
Expand All @@ -69,7 +69,7 @@ import mix from '@ckeditor/ckeditor5-utils/src/mix';
* if ( conversionApi.consumable.consume( data.viewItem, { name: true, attributes: [ 'href' ] } ) ) {
* // <a> element is inline and is represented by an attribute in the model.
* // This is why we need to convert only children.
* const { modelRange } = conversionApi.convertChildren( data.viewItem, data.cursorPosition );
* const { modelRange } = conversionApi.convertChildren( data.viewItem, data.modelCursor );
*
* for ( let item of modelRange.getItems() ) {
* if ( conversionApi.schema.checkAttribute( item, 'linkHref' ) ) {
Expand Down Expand Up @@ -221,8 +221,8 @@ export default class ViewConversionDispatcher {
* @private
* @see module:engine/conversion/viewconversiondispatcher~ViewConversionApi#convertItem
*/
_convertItem( viewItem, cursorPosition ) {
const data = Object.assign( { viewItem, cursorPosition, modelRange: null } );
_convertItem( viewItem, modelCursor ) {
const data = Object.assign( { viewItem, modelCursor, modelRange: null } );

if ( viewItem.is( 'element' ) ) {
this.fire( 'element:' + viewItem.name, data, this.conversionApi );
Expand All @@ -244,45 +244,45 @@ export default class ViewConversionDispatcher {
throw new CKEditorError( 'view-conversion-dispatcher-incorrect-result: Incorrect conversion result was dropped.' );
}

return { modelRange: data.modelRange, cursorPosition: data.cursorPosition };
return { modelRange: data.modelRange, modelCursor: data.modelCursor };
}

/**
* @private
* @see module:engine/conversion/viewconversiondispatcher~ViewConversionApi#convertChildren
*/
_convertChildren( viewItem, cursorPosition ) {
const modelRange = new ModelRange( cursorPosition );
let nextCursorPosition = cursorPosition;
_convertChildren( viewItem, modelCursor ) {
const modelRange = new ModelRange( modelCursor );
let nextModelCursor = modelCursor;

for ( const viewChild of Array.from( viewItem.getChildren() ) ) {
const result = this._convertItem( viewChild, nextCursorPosition );
const result = this._convertItem( viewChild, nextModelCursor );

if ( result.modelRange instanceof ModelRange ) {
modelRange.end = result.modelRange.end;
nextCursorPosition = result.cursorPosition;
nextModelCursor = result.modelCursor;
}
}

return { modelRange, cursorPosition: nextCursorPosition };
return { modelRange, modelCursor: nextModelCursor };
}

/**
* @private
* @see module:engine/conversion/viewconversiondispatcher~ViewConversionApi#splitToAllowedParent
*/
_splitToAllowedParent( node, cursorPosition ) {
_splitToAllowedParent( node, modelCursor ) {
// Try to find allowed parent.
const allowedParent = this.conversionApi.schema.findAllowedParent( node, cursorPosition );
const allowedParent = this.conversionApi.schema.findAllowedParent( node, modelCursor );

// When there is no parent that allows to insert node then return `null`.
if ( !allowedParent ) {
return null;
}

// When current position parent allows to insert node then return this position.
if ( allowedParent === cursorPosition.parent ) {
return { position: cursorPosition };
if ( allowedParent === modelCursor.parent ) {
return { position: modelCursor };
}

// When allowed parent is in context tree.
Expand All @@ -291,7 +291,7 @@ export default class ViewConversionDispatcher {
}

// Split element to allowed parent.
const splitResult = this.conversionApi.writer.split( cursorPosition, allowedParent );
const splitResult = this.conversionApi.writer.split( modelCursor, allowedParent );

// Remember all elements that are created as a result of split.
// This is important because at the end of conversion we want to remove all empty split elements.
Expand Down Expand Up @@ -350,12 +350,12 @@ export default class ViewConversionDispatcher {
* all elements conversion or to conversion of specific elements.
*
* @event element
* @param {Object} data Object containing viewItem to convert, cursorPosition as a conversion position and placeholder
* @param {Object} data Object containing viewItem to convert, modelCursor as a conversion position and placeholder
* for modelRange that is a conversion result. Keep in mind that this object is shared by reference between all
* callbacks that will be called. This means that callbacks can override values if needed, and those values will
* be available in other callbacks.
* @param {module:engine/view/item~Item} data.viewItem Converted item.
* @param {module:engine/model/position~Position} data.cursorPosition Target position for current item.
* @param {module:engine/model/position~Position} data.modelCursor Target position for current item.
* @param {module:engine/model/range~Range} data.modelRange The current state of conversion result. Every change to
* converted element should be reflected by setting or modifying this property.
* @param {ViewConversionApi} conversionApi Conversion interface to be used by callback, passed in
Expand Down Expand Up @@ -462,11 +462,11 @@ function createContextTree( contextDefinition, writer ) {
* @fires module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:text
* @fires module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:documentFragment
* @param {module:engine/view/item~Item} viewItem Item to convert.
* @param {module:engine/model/position~Position} cursorPosition Position of conversion.
* @param {module:engine/model/position~Position} modelCursor Position of conversion.
* @returns {Object} result Conversion result.
* @returns {module:engine/model/range~Range|null} result.modelRange Model range containing result of item conversion,
* created and modified by callbacks attached to fired event, or `null` if the conversion result was incorrect.
* @returns {module:engine/model/position~Position} result.cursorPosition Position where conversion should be continued.
* @returns {module:engine/model/position~Position} result.modelCursor Position where conversion should be continued.
*/

/**
Expand All @@ -477,11 +477,11 @@ function createContextTree( contextDefinition, writer ) {
* @fires module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:text
* @fires module:engine/conversion/viewconversiondispatcher~ViewConversionDispatcher#event:documentFragment
* @param {module:engine/view/item~Item} viewItem Item to convert.
* @param {module:engine/model/position~Position} cursorPosition Position of conversion.
* @param {module:engine/model/position~Position} modelCursor Position of conversion.
* @returns {Object} result Conversion result.
* @returns {module:engine/model/range~Range} result.modelRange Model range containing results of conversion of all children of given item.
* When no children was converted then range is collapsed.
* @returns {module:engine/model/position~Position} result.cursorPosition Position where conversion should be continued.
* @returns {module:engine/model/position~Position} result.modelCursor Position where conversion should be continued.
*/

/**
Expand Down
22 changes: 11 additions & 11 deletions src/dev-utils/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ export function parse( data, schema, options = {} ) {

function convertToModelFragment() {
return ( evt, data, conversionApi ) => {
const childrenResult = conversionApi.convertChildren( data.viewItem, data.cursorPosition );
const childrenResult = conversionApi.convertChildren( data.viewItem, data.modelCursor );

conversionApi.mapper.bindElements( data.cursorPosition.parent, data.viewItem );
conversionApi.mapper.bindElements( data.modelCursor.parent, data.viewItem );

data = Object.assign( data, childrenResult );

Expand All @@ -335,32 +335,32 @@ function convertToModelElement() {
return ( evt, data, conversionApi ) => {
const elementName = data.viewItem.name;

if ( !conversionApi.schema.checkChild( data.cursorPosition, elementName ) ) {
throw new Error( `Element '${ elementName }' was not allowed in given position.`, { position: data.cursorPosition } );
if ( !conversionApi.schema.checkChild( data.modelCursor, elementName ) ) {
throw new Error( `Element '${ elementName }' was not allowed in given position.` );
}

// View attribute value is a string so we want to typecast it to the original type.
// E.g. `bold="true"` - value will be parsed from string `"true"` to boolean `true`.
const attributes = convertAttributes( data.viewItem.getAttributes(), parseAttributeValue );
const element = conversionApi.writer.createElement( data.viewItem.name, attributes );

conversionApi.writer.insert( element, data.cursorPosition );
conversionApi.writer.insert( element, data.modelCursor );

conversionApi.mapper.bindElements( element, data.viewItem );

conversionApi.convertChildren( data.viewItem, ModelPosition.createAt( element ) );

data.modelRange = ModelRange.createOn( element );
data.cursorPosition = data.modelRange.end;
data.modelCursor = data.modelRange.end;

evt.stop();
};
}

function convertToModelText( withAttributes = false ) {
return ( evt, data, conversionApi ) => {
if ( !conversionApi.schema.checkChild( data.cursorPosition, '$text' ) ) {
throw new Error( 'Text was not allowed in given position.', { position: data.cursorPosition } );
if ( !conversionApi.schema.checkChild( data.modelCursor, '$text' ) ) {
throw new Error( 'Text was not allowed in given position.' );
}

let node;
Expand All @@ -375,10 +375,10 @@ function convertToModelText( withAttributes = false ) {
node = conversionApi.writer.createText( data.viewItem.data );
}

conversionApi.writer.insert( node, data.cursorPosition );
conversionApi.writer.insert( node, data.modelCursor );

data.modelRange = ModelRange.createFromPositionAndShift( data.cursorPosition, node.offsetSize );
data.cursorPosition = data.modelRange.end;
data.modelRange = ModelRange.createFromPositionAndShift( data.modelCursor, node.offsetSize );
data.modelCursor = data.modelRange.end;

evt.stop();
};
Expand Down
Loading

0 comments on commit 378ecd4

Please sign in to comment.