diff --git a/src/converters.js b/src/converters.js index 495f228..19c826d 100644 --- a/src/converters.js +++ b/src/converters.js @@ -7,8 +7,6 @@ * @module list/converters */ -import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position'; -import ViewRange from '@ckeditor/ckeditor5-engine/src/view/range'; import ViewTreeWalker from '@ckeditor/ckeditor5-engine/src/view/treewalker'; import { createViewListItemElement } from './utils'; @@ -59,13 +57,13 @@ export function modelViewRemove( model ) { // 1. Break the container after and before the list item. // This will create a view list with one view list item - the one to remove. - viewWriter.breakContainer( ViewPosition.createBefore( viewItem ) ); - viewWriter.breakContainer( ViewPosition.createAfter( viewItem ) ); + viewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) ); + viewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) ); // 2. Remove the list with the item to remove. const viewList = viewItem.parent; const viewListPrev = viewList.previousSibling; - const removeRange = ViewRange.createOn( viewList ); + const removeRange = viewWriter.createRangeOn( viewList ); const removed = viewWriter.remove( removeRange ); // 3. Merge the whole created by breaking and removing the list. @@ -79,7 +77,7 @@ export function modelViewRemove( model ) { hoistNestedLists( modelItem.getAttribute( 'listIndent' ) + 1, data.position, removeRange.start, viewItem, conversionApi, model ); // 5. Unbind removed view item and all children. - for ( const child of ViewRange.createIn( removed ).getItems() ) { + for ( const child of viewWriter.createRangeIn( removed ).getItems() ) { conversionApi.mapper.unbindViewElement( child ); } @@ -108,8 +106,8 @@ export function modelViewChangeType( evt, data, conversionApi ) { // 1. Break the container after and before the list item. // This will create a view list with one view list item -- the one that changed type. - viewWriter.breakContainer( ViewPosition.createBefore( viewItem ) ); - viewWriter.breakContainer( ViewPosition.createAfter( viewItem ) ); + viewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) ); + viewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) ); // 2. Change name of the view list that holds the changed view item. // We cannot just change name property, because that would not render properly. @@ -145,13 +143,13 @@ export function modelViewChangeIndent( model ) { // 1. Break the container after and before the list item. // This will create a view list with one view list item -- the one that changed type. - viewWriter.breakContainer( ViewPosition.createBefore( viewItem ) ); - viewWriter.breakContainer( ViewPosition.createAfter( viewItem ) ); + viewWriter.breakContainer( viewWriter.createPositionBefore( viewItem ) ); + viewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) ); // 2. Extract view list with changed view list item and merge "hole" possibly created by breaking and removing elements. const viewList = viewItem.parent; const viewListPrev = viewList.previousSibling; - const removeRange = ViewRange.createOn( viewList ); + const removeRange = viewWriter.createRangeOn( viewList ); viewWriter.remove( removeRange ); if ( viewListPrev && viewListPrev.nextSibling ) { @@ -258,15 +256,15 @@ export function modelViewSplitOnInsert( evt, data, conversionApi ) { // Remove lists that are after inserted element. // They will be brought back later, below the inserted element. const removeStart = viewPosition; - const removeEnd = ViewPosition.createAt( viewPosition.parent, 'end' ); + const removeEnd = viewWriter.createPositionAt( viewPosition.parent, 'end' ); // Don't remove if there is nothing to remove. if ( !removeStart.isEqual( removeEnd ) ) { - const removed = viewWriter.remove( new ViewRange( removeStart, removeEnd ) ); + const removed = viewWriter.remove( viewWriter.createRange( removeStart, removeEnd ) ); lists.push( removed ); } - viewPosition = ViewPosition.createAfter( viewPosition.parent ); + viewPosition = viewWriter.createPositionAfter( viewPosition.parent ); } // Bring back removed lists. @@ -470,40 +468,42 @@ export function cleanListItem( evt, data, conversionApi ) { } /** - * The callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes + * Returns callback for model position to view position mapping for {@link module:engine/conversion/mapper~Mapper}. The callback fixes * positions between `listItem` elements that would be incorrectly mapped because of how list items are represented in model * and view. * * @see module:engine/conversion/mapper~Mapper#event:modelToViewPosition - * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event. - * @param {Object} data An object containing additional data and placeholder for mapping result. + * @param {module:engine/view/view~View} view A view instance. + * @returns {Function} */ -export function modelToViewPosition( evt, data ) { - if ( data.isPhantom ) { - return; - } +export function modelToViewPosition( view ) { + return ( evt, data ) => { + if ( data.isPhantom ) { + return; + } - const modelItem = data.modelPosition.nodeBefore; + const modelItem = data.modelPosition.nodeBefore; - if ( modelItem && modelItem.is( 'listItem' ) ) { - const viewItem = data.mapper.toViewElement( modelItem ); - const topmostViewList = viewItem.getAncestors().find( element => element.is( 'ul' ) || element.is( 'ol' ) ); - const walker = new ViewTreeWalker( { - startPosition: ViewPosition.createAt( viewItem, 0 ) - } ); + if ( modelItem && modelItem.is( 'listItem' ) ) { + const viewItem = data.mapper.toViewElement( modelItem ); + const topmostViewList = viewItem.getAncestors().find( element => element.is( 'ul' ) || element.is( 'ol' ) ); + const walker = new ViewTreeWalker( { + startPosition: view.createPositionAt( viewItem, 0 ) + } ); - for ( const value of walker ) { - if ( value.type == 'elementStart' && value.item.is( 'li' ) ) { - data.viewPosition = value.previousPosition; + for ( const value of walker ) { + if ( value.type == 'elementStart' && value.item.is( 'li' ) ) { + data.viewPosition = value.previousPosition; - break; - } else if ( value.type == 'elementEnd' && value.item == topmostViewList ) { - data.viewPosition = value.nextPosition; + break; + } else if ( value.type == 'elementEnd' && value.item == topmostViewList ) { + data.viewPosition = value.nextPosition; - break; + break; + } } } - } + }; } /** @@ -811,7 +811,7 @@ function generateLiInUl( modelItem, conversionApi ) { const viewItem = createViewListItemElement( viewWriter ); const viewList = viewWriter.createContainerElement( listType, null ); - viewWriter.insert( ViewPosition.createAt( viewList, 0 ), viewItem ); + viewWriter.insert( viewWriter.createPositionAt( viewList, 0 ), viewItem ); mapper.bindElements( modelItem, viewItem ); @@ -848,7 +848,7 @@ function getSiblingListItem( modelItem, options ) { // The merge happen only if both parameters are UL or OL elements. function mergeViewLists( viewWriter, firstList, secondList ) { if ( firstList && secondList && ( firstList.name == 'ul' || firstList.name == 'ol' ) && firstList.name == secondList.name ) { - return viewWriter.mergeContainers( ViewPosition.createAfter( firstList ) ); + return viewWriter.mergeContainers( viewWriter.createPositionAfter( firstList ) ); } return null; @@ -880,7 +880,7 @@ function injectViewList( modelItem, injectedItem, conversionApi, model ) { // There is a list item with same indent - we found same-level sibling. // Break the list after it. Inserted view item will be inserted in the broken space. const viewItem = mapper.toViewElement( refItem ); - insertPosition = viewWriter.breakContainer( ViewPosition.createAfter( viewItem ) ); + insertPosition = viewWriter.breakContainer( viewWriter.createPositionAfter( viewItem ) ); } else { // There is no list item with same indent. Check previous model item. if ( prevItem && prevItem.name == 'listItem' ) { @@ -904,8 +904,8 @@ function injectViewList( modelItem, injectedItem, conversionApi, model ) { const prevView = mapper.toViewElement( prevItem ); const walker = new ViewTreeWalker( { - boundaries: new ViewRange( - ViewPosition.createAt( prevView, 0 ), + boundaries: viewWriter.createRange( + viewWriter.createPositionAt( prevView, 0 ), insertPosition ), ignoreElementEnd: true @@ -913,12 +913,12 @@ function injectViewList( modelItem, injectedItem, conversionApi, model ) { for ( const value of walker ) { if ( value.item.is( 'li' ) ) { - const breakPosition = viewWriter.breakContainer( ViewPosition.createBefore( value.item ) ); + const breakPosition = viewWriter.breakContainer( viewWriter.createPositionBefore( value.item ) ); const viewList = value.item.parent; - const targetPosition = ViewPosition.createAt( injectedItem, 'end' ); + const targetPosition = viewWriter.createPositionAt( injectedItem, 'end' ); mergeViewLists( viewWriter, targetPosition.nodeBefore, targetPosition.nodeAfter ); - viewWriter.move( ViewRange.createOn( viewList ), targetPosition ); + viewWriter.move( viewWriter.createRangeOn( viewList ), targetPosition ); walker.position = breakPosition; } @@ -940,8 +940,8 @@ function injectViewList( modelItem, injectedItem, conversionApi, model ) { } if ( lastSubChild ) { - viewWriter.breakContainer( ViewPosition.createAfter( lastSubChild ) ); - viewWriter.move( ViewRange.createOn( lastSubChild.parent ), ViewPosition.createAt( injectedItem, 'end' ) ); + viewWriter.breakContainer( viewWriter.createPositionAfter( lastSubChild ) ); + viewWriter.move( viewWriter.createRangeOn( lastSubChild.parent ), viewWriter.createPositionAt( injectedItem, 'end' ) ); } } } @@ -1010,7 +1010,7 @@ function hoistNestedLists( nextIndent, modelRemoveStartPosition, viewRemoveStart // 2.1 -------- // 2.2 -------- const prevViewList = mapper.toViewElement( prevModelItem ).parent; - insertPosition = ViewPosition.createAfter( prevViewList ); + insertPosition = viewWriter.createPositionAfter( prevViewList ); } else { // If element has been found and has smaller indent as reference indent it means that nested items // should become nested items of found item: @@ -1040,7 +1040,7 @@ function hoistNestedLists( nextIndent, modelRemoveStartPosition, viewRemoveStart // are inserted after the first list (no need to recalculate insertion position for them). for ( const child of [ ...viewRemovedItem.getChildren() ] ) { if ( child.is( 'ul' ) || child.is( 'ol' ) ) { - insertPosition = viewWriter.move( ViewRange.createOn( child ), insertPosition ).end; + insertPosition = viewWriter.move( viewWriter.createRangeOn( child ), insertPosition ).end; mergeViewLists( viewWriter, child, child.nextSibling ); mergeViewLists( viewWriter, child.previousSibling, child ); diff --git a/src/listediting.js b/src/listediting.js index 0bc445b..5926ca7 100644 --- a/src/listediting.js +++ b/src/listediting.js @@ -68,9 +68,9 @@ export default class ListEditing extends Plugin { editing.mapper.registerViewToModelLength( 'li', getViewListItemLength ); data.mapper.registerViewToModelLength( 'li', getViewListItemLength ); - editing.mapper.on( 'modelToViewPosition', modelToViewPosition ); + editing.mapper.on( 'modelToViewPosition', modelToViewPosition( editing.view ) ); editing.mapper.on( 'viewToModelPosition', viewToModelPosition( editor.model ) ); - data.mapper.on( 'modelToViewPosition', modelToViewPosition ); + data.mapper.on( 'modelToViewPosition', modelToViewPosition( editing.view ) ); editing.downcastDispatcher.on( 'insert', modelViewSplitOnInsert, { priority: 'high' } ); editing.downcastDispatcher.on( 'insert:listItem', modelViewInsertion( editor.model ) ); diff --git a/tests/listediting.js b/tests/listediting.js index 82ed692..ad27c7e 100644 --- a/tests/listediting.js +++ b/tests/listediting.js @@ -7,8 +7,6 @@ import ListEditing from '../src/listediting'; import ListCommand from '../src/listcommand'; import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range'; -import ViewPosition from '@ckeditor/ckeditor5-engine/src/view/position'; -import ViewUIElement from '@ckeditor/ckeditor5-engine/src/view/uielement'; import BoldEditing from '@ckeditor/ckeditor5-basic-styles/src/bold/boldediting'; import UndoEditing from '@ckeditor/ckeditor5-undo/src/undoediting'; @@ -396,7 +394,7 @@ describe( 'ListEditing', () => { describe( 'view to model', () => { function test( testName, viewPath, modelPath ) { it( testName, () => { - const viewPos = getViewPosition( viewRoot, viewPath ); + const viewPos = getViewPosition( viewRoot, viewPath, view ); const modelPos = mapper.toModelPosition( viewPos ); expect( modelPos.root ).to.equal( modelRoot ); @@ -1374,7 +1372,7 @@ describe( 'ListEditing', () => { describe( 'view to model', () => { function test( testName, viewPath, modelPath ) { it( testName, () => { - const viewPos = getViewPosition( viewRoot, viewPath ); + const viewPos = getViewPosition( viewRoot, viewPath, view ); const modelPos = mapper.toModelPosition( viewPos ); expect( modelPos.root ).to.equal( modelRoot ); @@ -3675,13 +3673,12 @@ describe( 'ListEditing', () => { it( 'ul and ol should not be inserted before ui element - injectViewList()', () => { editor.setData( '' ); - const uiElement = new ViewUIElement( 'span' ); - // Append ui element at the end of first
  • . view.change( writer => { const firstChild = viewDoc.getRoot().getChild( 0 ).getChild( 0 ); - writer.insert( ViewPosition.createAt( firstChild, 'end' ), uiElement ); + const uiElement = writer.createUIElement( 'span' ); + writer.insert( writer.createPositionAt( firstChild, 'end' ), uiElement ); } ); expect( getViewData( editor.editing.view, { withoutSelection: true } ) ) @@ -3701,13 +3698,12 @@ describe( 'ListEditing', () => { it( 'ul and ol should not be inserted before ui element - hoistNestedLists()', () => { editor.setData( '' ); - const uiElement = new ViewUIElement( 'span' ); - // Append ui element at the end of first
  • . view.change( writer => { const firstChild = viewDoc.getRoot().getChild( 0 ).getChild( 0 ); - writer.insert( ViewPosition.createAt( firstChild, 'end' ), uiElement ); + const uiElement = writer.createUIElement( 'span' ); + writer.insert( writer.createPositionAt( firstChild, 'end' ), uiElement ); } ); expect( getViewData( editor.editing.view, { withoutSelection: true } ) ) @@ -3724,20 +3720,18 @@ describe( 'ListEditing', () => { } ); describe( 'remove converter should properly handle ui elements', () => { - let uiElement, liFoo, liBar; + let liFoo, liBar; beforeEach( () => { editor.setData( '' ); liFoo = modelRoot.getChild( 0 ); liBar = modelRoot.getChild( 1 ); - - uiElement = new ViewUIElement( 'span' ); } ); it( 'ui element before